tor-browser

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

GeckoViewSettings.sys.mjs (5934B)


      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 file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { GeckoViewModule } from "resource://gre/modules/GeckoViewModule.sys.mjs";
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
     11 });
     12 
     13 // This needs to match GeckoSessionSettings.java
     14 const USER_AGENT_MODE_MOBILE = 0;
     15 const USER_AGENT_MODE_DESKTOP = 1;
     16 const USER_AGENT_MODE_VR = 2;
     17 
     18 // This needs to match GeckoSessionSettings.java
     19 const DISPLAY_MODE_BROWSER = 0;
     20 const DISPLAY_MODE_MINIMAL_UI = 1;
     21 const DISPLAY_MODE_STANDALONE = 2;
     22 const DISPLAY_MODE_FULLSCREEN = 3;
     23 
     24 // This needs to match GeckoSessionSettings.java
     25 // eslint-disable-next-line no-unused-vars
     26 const VIEWPORT_MODE_MOBILE = 0;
     27 const VIEWPORT_MODE_DESKTOP = 1;
     28 
     29 // Handles GeckoSession settings.
     30 export class GeckoViewSettings extends GeckoViewModule {
     31  onInit() {
     32    debug`onInit`;
     33    this._userAgentMode = USER_AGENT_MODE_MOBILE;
     34    this._userAgentOverride = null;
     35    this._sessionContextId = null;
     36 
     37    this.registerListener(["GeckoView:GetUserAgent"]);
     38  }
     39 
     40  onEvent(aEvent, aData, aCallback) {
     41    debug`onEvent ${aEvent} ${aData}`;
     42 
     43    switch (aEvent) {
     44      case "GeckoView:GetUserAgent": {
     45        aCallback.onSuccess(this.customUserAgent ?? this.getMobileUserAgent());
     46      }
     47    }
     48  }
     49 
     50  getMobileUserAgent() {
     51    if (ChromeUtils.shouldResistFingerprinting("HttpUserAgent", null)) {
     52      return Services.rfp.getSpoofedUserAgent(false);
     53    }
     54 
     55    return Cc["@mozilla.org/network/protocol;1?name=http"].getService(
     56      Ci.nsIHttpProtocolHandler
     57    ).userAgent;
     58  }
     59 
     60  getDesktopUserAgent() {
     61    if (ChromeUtils.shouldResistFingerprinting("HttpUserAgent", null)) {
     62      return Services.rfp.getSpoofedUserAgent(true);
     63    }
     64 
     65    return this.getMobileUserAgent()
     66      .replace(/Android \d.+?; [a-zA-Z]+/, "X11; Linux x86_64")
     67      .replace(/Gecko\/[0-9\.]+/, "Gecko/20100101");
     68  }
     69 
     70  getVrUserAgent() {
     71    return this.getMobileUserAgent().replace(/Mobile/, "Mobile VR");
     72  }
     73 
     74  onSettingsUpdate() {
     75    const { settings } = this;
     76    debug`onSettingsUpdate: ${settings}`;
     77 
     78    this.displayMode = settings.displayMode;
     79    this.unsafeSessionContextId = settings.unsafeSessionContextId;
     80    this.userAgentMode = settings.userAgentMode;
     81    this.userAgentOverride = settings.userAgentOverride;
     82    this.sessionContextId = settings.sessionContextId;
     83    this.suspendMediaWhenInactive = settings.suspendMediaWhenInactive;
     84    this.allowJavascript = settings.allowJavascript;
     85    this.viewportMode = settings.viewportMode;
     86    this.useTrackingProtection = !!settings.useTrackingProtection;
     87 
     88    if (settings.isExtensionPopup) {
     89      // NOTE: Only add the webextension-view-type and emit extension-browser-inserted
     90      // once, an extension popup should never change webextension-view-type once set.
     91      if (!this.browser.hasAttribute("webextension-view-type")) {
     92        this.browser.setAttribute("webextension-view-type", "popup");
     93        lazy.ExtensionParent.apiManager.emit(
     94          "extension-browser-inserted",
     95          this.browser
     96        );
     97      }
     98    }
     99 
    100    // When the page is loading from the main process (e.g. from an extension
    101    // page) we won't be able to query the actor here.
    102    this.getActor("GeckoViewSettings")?.sendAsyncMessage(
    103      "SettingsUpdate",
    104      settings
    105    );
    106  }
    107 
    108  get allowJavascript() {
    109    return this.browsingContext.allowJavascript;
    110  }
    111 
    112  set allowJavascript(aAllowJavascript) {
    113    this.browsingContext.allowJavascript = aAllowJavascript;
    114  }
    115 
    116  get customUserAgent() {
    117    if (this.userAgentOverride !== null) {
    118      return this.userAgentOverride;
    119    }
    120    if (this.userAgentMode === USER_AGENT_MODE_DESKTOP) {
    121      return this.getDesktopUserAgent();
    122    }
    123    if (this.userAgentMode === USER_AGENT_MODE_VR) {
    124      return this.getVrUserAgent();
    125    }
    126    return null;
    127  }
    128 
    129  set useTrackingProtection(aUse) {
    130    this.browsingContext.useTrackingProtection = aUse;
    131  }
    132 
    133  set viewportMode(aViewportMode) {
    134    this.browsingContext.forceDesktopViewport =
    135      aViewportMode == VIEWPORT_MODE_DESKTOP;
    136  }
    137 
    138  get userAgentMode() {
    139    return this._userAgentMode;
    140  }
    141 
    142  set userAgentMode(aMode) {
    143    if (this.userAgentMode === aMode) {
    144      return;
    145    }
    146    this._userAgentMode = aMode;
    147    this.browsingContext.customUserAgent = this.customUserAgent;
    148  }
    149 
    150  get browsingContext() {
    151    return this.browser.browsingContext.top;
    152  }
    153 
    154  get userAgentOverride() {
    155    return this._userAgentOverride;
    156  }
    157 
    158  set userAgentOverride(aUserAgent) {
    159    if (aUserAgent === this.userAgentOverride) {
    160      return;
    161    }
    162    this._userAgentOverride = aUserAgent;
    163    this.browsingContext.customUserAgent = this.customUserAgent;
    164  }
    165 
    166  get suspendMediaWhenInactive() {
    167    return this.browser.suspendMediaWhenInactive;
    168  }
    169 
    170  set suspendMediaWhenInactive(aSuspendMediaWhenInactive) {
    171    if (aSuspendMediaWhenInactive != this.browser.suspendMediaWhenInactive) {
    172      this.browser.suspendMediaWhenInactive = aSuspendMediaWhenInactive;
    173    }
    174  }
    175 
    176  displayModeSettingToValue(aSetting) {
    177    switch (aSetting) {
    178      case DISPLAY_MODE_BROWSER:
    179        return "browser";
    180      case DISPLAY_MODE_MINIMAL_UI:
    181        return "minimal-ui";
    182      case DISPLAY_MODE_STANDALONE:
    183        return "standalone";
    184      case DISPLAY_MODE_FULLSCREEN:
    185        return "fullscreen";
    186      default:
    187        warn`Invalid displayMode value ${aSetting}.`;
    188        return "browser";
    189    }
    190  }
    191 
    192  set displayMode(aMode) {
    193    this.browsingContext.displayMode = this.displayModeSettingToValue(aMode);
    194  }
    195 
    196  set sessionContextId(aAttribute) {
    197    this._sessionContextId = aAttribute;
    198  }
    199 
    200  get sessionContextId() {
    201    return this._sessionContextId;
    202  }
    203 }
    204 
    205 const { debug, warn } = GeckoViewSettings.initLogging("GeckoViewSettings");