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");