tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser.sys.mjs (9434B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { RootBiDiModule } from "chrome://remote/content/webdriver-bidi/modules/RootBiDiModule.sys.mjs";
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  assert: "chrome://remote/content/shared/webdriver/Assert.sys.mjs",
     11  Certificates: "chrome://remote/content/shared/webdriver/Certificates.sys.mjs",
     12  error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
     13  getWebDriverSessionById:
     14    "chrome://remote/content/shared/webdriver/Session.sys.mjs",
     15  pprint: "chrome://remote/content/shared/Format.sys.mjs",
     16  ProxyConfiguration:
     17    "chrome://remote/content/shared/webdriver/Capabilities.sys.mjs",
     18  ProxyPerUserContextManager:
     19    "chrome://remote/content/webdriver-bidi/ProxyPerUserContextManager.sys.mjs",
     20  ProxyTypes: "chrome://remote/content/shared/webdriver/Capabilities.sys.mjs",
     21  TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
     22  UserContextManager:
     23    "chrome://remote/content/shared/UserContextManager.sys.mjs",
     24  windowManager: "chrome://remote/content/shared/WindowManager.sys.mjs",
     25  WindowState: "chrome://remote/content/shared/WindowManager.sys.mjs",
     26 });
     27 
     28 /**
     29 * An object that holds information about the client window
     30 *
     31 * @typedef ClientWindowInfo
     32 *
     33 * @property {boolean} active
     34 *    True if client window is keyboard-interactable. False, if
     35 *    otherwise.
     36 * @property {string} clientWindow
     37 *    The id of the client window.
     38 * @property {number} height
     39 *    The height of the client window.
     40 *  @property {WindowState} state
     41 *    The client window state.
     42 * @property {number} width
     43 *    The width of the client window.
     44 * @property {number} x
     45 *    The x-coordinate of the client window.
     46 * @property {number} y
     47 *    The y-coordinate of the client window.
     48 */
     49 
     50 /**
     51 * Return value of the getClientWindows command.
     52 *
     53 * @typedef GetClientWindowsResult
     54 *
     55 * @property {Array<ClientWindowInfo>} clientWindows
     56 */
     57 
     58 /**
     59 * An object that holds information about a user context.
     60 *
     61 * @typedef UserContextInfo
     62 *
     63 * @property {string} userContext
     64 *     The id of the user context.
     65 */
     66 
     67 /**
     68 * Return value for the getUserContexts command.
     69 *
     70 * @typedef GetUserContextsResult
     71 *
     72 * @property {Array<UserContextInfo>} userContexts
     73 *     Array of UserContextInfo for the current user contexts.
     74 */
     75 
     76 class BrowserModule extends RootBiDiModule {
     77  #proxyManager;
     78  #userContextsWithInsecureCertificatesOverrides;
     79 
     80  constructor(messageHandler) {
     81    super(messageHandler);
     82 
     83    this.#proxyManager = new lazy.ProxyPerUserContextManager();
     84 
     85    // A set of internal user context ids to keep track of user contexts
     86    // which had insecure certificates overrides set for them.
     87    this.#userContextsWithInsecureCertificatesOverrides = new Set();
     88  }
     89 
     90  destroy() {
     91    // Reset "allowInsecureCerts" for the userContexts,
     92    // which were created in the scope of this session.
     93    for (const userContext of this
     94      .#userContextsWithInsecureCertificatesOverrides) {
     95      lazy.Certificates.resetSecurityChecksForUserContext(userContext);
     96    }
     97 
     98    this.#userContextsWithInsecureCertificatesOverrides = null;
     99 
    100    this.#proxyManager.destroy();
    101  }
    102 
    103  /**
    104   * Commands
    105   */
    106 
    107  /**
    108   * Terminate all WebDriver sessions and clean up automation state in the
    109   * remote browser instance.
    110   *
    111   * The actual session clean-up and closing the browser will happen later
    112   * in WebDriverBiDiConnection class.
    113   */
    114  async close() {
    115    const session = lazy.getWebDriverSessionById(this.messageHandler.sessionId);
    116 
    117    // TODO Bug 1838269. Enable browser.close command for the case of classic + bidi session, when
    118    // session ending for this type of session is supported.
    119    if (session.http) {
    120      throw new lazy.error.UnsupportedOperationError(
    121        "Closing the browser in a session started with WebDriver classic" +
    122          ' is not supported. Use the WebDriver classic "Delete Session"' +
    123          " command instead which will also close the browser."
    124      );
    125    }
    126 
    127    // Close all open top-level browsing contexts by not prompting for beforeunload.
    128    for (const tab of lazy.TabManager.allTabs) {
    129      lazy.TabManager.removeTab(tab, { skipPermitUnload: true });
    130    }
    131  }
    132 
    133  /**
    134   * Returns a list of client windows info
    135   *
    136   * @returns {GetClientWindowsResult}
    137   *     The list of client windows info
    138   */
    139  async getClientWindows() {
    140    const clientWindowsIds = new Set();
    141    const clientWindows = [];
    142 
    143    for (const win of lazy.windowManager.windows) {
    144      let clientWindowId = lazy.windowManager.getIdForWindow(win);
    145      if (clientWindowsIds.has(clientWindowId)) {
    146        continue;
    147      }
    148      clientWindowsIds.add(clientWindowId);
    149      let clientWindowInfo = this.#getClientWindowInfo(win);
    150      clientWindows.push(clientWindowInfo);
    151    }
    152 
    153    return { clientWindows };
    154  }
    155 
    156  /**
    157   * Creates a user context.
    158   *
    159   * @param {object=} options
    160   * @param {boolean=} options.acceptInsecureCerts
    161   *     Indicates whether untrusted and self-signed TLS certificates
    162   *     should be implicitly trusted on navigation for this user context.
    163   * @param {object=} options.proxy
    164   *     An object which holds the proxy settings.
    165   *
    166   * @returns {UserContextInfo}
    167   *     UserContextInfo object for the created user context.
    168   *
    169   * @throws {InvalidArgumentError}
    170   *     Raised if an argument is of an invalid type or value.
    171   * @throws {UnsupportedOperationError}
    172   *     Raised when the command is called with unsupported proxy types.
    173   */
    174  async createUserContext(options = {}) {
    175    const { acceptInsecureCerts = null, proxy = null } = options;
    176 
    177    if (acceptInsecureCerts !== null) {
    178      lazy.assert.boolean(
    179        acceptInsecureCerts,
    180        lazy.pprint`Expected "acceptInsecureCerts" to be a boolean, got ${acceptInsecureCerts}`
    181      );
    182    }
    183 
    184    let proxyObject;
    185    if (proxy !== null) {
    186      proxyObject = lazy.ProxyConfiguration.fromJSON(proxy);
    187 
    188      if (
    189        proxyObject.proxyType === lazy.ProxyTypes.System ||
    190        proxyObject.proxyType === lazy.ProxyTypes.Autodetect ||
    191        proxyObject.proxyType === lazy.ProxyTypes.Pac
    192      ) {
    193        // Bug 1968887: Add support for "system", "autodetect" and "pac" proxy types.
    194        throw new lazy.error.UnsupportedOperationError(
    195          `Proxy type "${proxyObject.proxyType}" is not supported`
    196        );
    197      }
    198    }
    199 
    200    const userContextId = lazy.UserContextManager.createContext("webdriver");
    201    const internalId = lazy.UserContextManager.getInternalIdById(userContextId);
    202 
    203    if (acceptInsecureCerts !== null) {
    204      this.#userContextsWithInsecureCertificatesOverrides.add(internalId);
    205      if (acceptInsecureCerts) {
    206        lazy.Certificates.disableSecurityChecks(internalId);
    207      } else {
    208        lazy.Certificates.enableSecurityChecks(internalId);
    209      }
    210    }
    211 
    212    if (proxy !== null) {
    213      this.#proxyManager.addConfiguration(internalId, proxyObject);
    214    }
    215 
    216    return { userContext: userContextId };
    217  }
    218 
    219  /**
    220   * Returns the list of available user contexts.
    221   *
    222   * @returns {GetUserContextsResult}
    223   *     Object containing an array of UserContextInfo.
    224   */
    225  async getUserContexts() {
    226    const userContexts = lazy.UserContextManager.getUserContextIds().map(
    227      userContextId => ({
    228        userContext: userContextId,
    229      })
    230    );
    231 
    232    return { userContexts };
    233  }
    234 
    235  /**
    236   * Closes a user context and all browsing contexts in it without running
    237   * beforeunload handlers.
    238   *
    239   * @param {object=} options
    240   * @param {string} options.userContext
    241   *     Id of the user context to close.
    242   *
    243   * @throws {InvalidArgumentError}
    244   *     Raised if an argument is of an invalid type or value.
    245   * @throws {NoSuchUserContextError}
    246   *     Raised if the user context id could not be found.
    247   */
    248  async removeUserContext(options = {}) {
    249    const { userContext: userContextId } = options;
    250 
    251    lazy.assert.string(
    252      userContextId,
    253      lazy.pprint`Expected "userContext" to be a string, got ${userContextId}`
    254    );
    255 
    256    if (userContextId === lazy.UserContextManager.defaultUserContextId) {
    257      throw new lazy.error.InvalidArgumentError(
    258        `Default user context cannot be removed`
    259      );
    260    }
    261 
    262    if (!lazy.UserContextManager.hasUserContextId(userContextId)) {
    263      throw new lazy.error.NoSuchUserContextError(
    264        `User Context with id ${userContextId} was not found`
    265      );
    266    }
    267 
    268    const internalId = lazy.UserContextManager.getInternalIdById(userContextId);
    269 
    270    lazy.UserContextManager.removeUserContext(userContextId, {
    271      closeContextTabs: true,
    272    });
    273 
    274    // Reset the state to clean up the platform state.
    275    lazy.Certificates.resetSecurityChecksForUserContext(internalId);
    276    this.#userContextsWithInsecureCertificatesOverrides.delete(internalId);
    277 
    278    this.#proxyManager.deleteConfiguration(internalId);
    279  }
    280 
    281  #getClientWindowInfo(window) {
    282    return {
    283      active: Services.focus.activeWindow === window,
    284      clientWindow: lazy.windowManager.getIdForWindow(window),
    285      height: window.outerHeight,
    286      state: lazy.WindowState.from(window.windowState),
    287      width: window.outerWidth,
    288      x: window.screenX,
    289      y: window.screenY,
    290    };
    291  }
    292 }
    293 
    294 // To export the class as lower-case
    295 export const browser = BrowserModule;