diff options
Diffstat (limited to 'mobile/android/components/geckoview/GeckoViewStartup.jsm')
-rw-r--r-- | mobile/android/components/geckoview/GeckoViewStartup.jsm | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/mobile/android/components/geckoview/GeckoViewStartup.jsm b/mobile/android/components/geckoview/GeckoViewStartup.jsm new file mode 100644 index 0000000000..9f0d3934bd --- /dev/null +++ b/mobile/android/components/geckoview/GeckoViewStartup.jsm @@ -0,0 +1,333 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var EXPORTED_SYMBOLS = ["GeckoViewStartup"]; + +const { GeckoViewUtils } = ChromeUtils.importESModule( + "resource://gre/modules/GeckoViewUtils.sys.mjs" +); + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + ActorManagerParent: "resource://gre/modules/ActorManagerParent.sys.mjs", + EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", + Preferences: "resource://gre/modules/Preferences.sys.mjs", +}); + +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +XPCOMUtils.defineLazyModuleGetters(lazy, { + PdfJs: "resource://pdf.js/PdfJs.jsm", +}); + +const { debug, warn } = GeckoViewUtils.initLogging("Startup"); + +var { DelayedInit } = ChromeUtils.import( + "resource://gre/modules/DelayedInit.jsm" +); + +function InitLater(fn, object, name) { + return DelayedInit.schedule(fn, object, name, 15000 /* 15s max wait */); +} + +const JSPROCESSACTORS = { + GeckoViewPermissionProcess: { + parent: { + moduleURI: "resource:///actors/GeckoViewPermissionProcessParent.jsm", + }, + child: { + moduleURI: "resource:///actors/GeckoViewPermissionProcessChild.jsm", + observers: [ + "getUserMedia:ask-device-permission", + "getUserMedia:request", + "recording-device-events", + "PeerConnection:request", + ], + }, + }, +}; + +const JSWINDOWACTORS = { + LoadURIDelegate: { + parent: { + moduleURI: "resource:///actors/LoadURIDelegateParent.jsm", + }, + child: { + moduleURI: "resource:///actors/LoadURIDelegateChild.jsm", + }, + messageManagerGroups: ["browsers"], + }, + GeckoViewPermission: { + parent: { + moduleURI: "resource:///actors/GeckoViewPermissionParent.jsm", + }, + child: { + moduleURI: "resource:///actors/GeckoViewPermissionChild.jsm", + }, + allFrames: true, + includeChrome: true, + }, + GeckoViewPrompt: { + child: { + moduleURI: "resource:///actors/GeckoViewPromptChild.jsm", + events: { + click: { capture: false, mozSystemGroup: true }, + contextmenu: { capture: false, mozSystemGroup: true }, + mozshowdropdown: {}, + "mozshowdropdown-sourcetouch": {}, + MozOpenDateTimePicker: {}, + DOMPopupBlocked: { capture: false, mozSystemGroup: true }, + }, + }, + allFrames: true, + messageManagerGroups: ["browsers"], + }, + GeckoViewFormValidation: { + child: { + moduleURI: "resource:///actors/GeckoViewFormValidationChild.jsm", + events: { + MozInvalidForm: {}, + }, + }, + allFrames: true, + messageManagerGroups: ["browsers"], + }, + GeckoViewClipboardPermission: { + parent: { + moduleURI: "resource:///actors/GeckoViewClipboardPermissionParent.jsm", + }, + child: { + moduleURI: "resource:///actors/GeckoViewClipboardPermissionChild.jsm", + events: { + MozClipboardReadPaste: {}, + deactivate: { mozSystemGroup: true }, + mousedown: { capture: true, mozSystemGroup: true }, + mozvisualscroll: { mozSystemGroup: true }, + pagehide: { capture: true, mozSystemGroup: true }, + }, + }, + allFrames: true, + }, +}; + +class GeckoViewStartup { + /* ---------- nsIObserver ---------- */ + observe(aSubject, aTopic, aData) { + debug`observe: ${aTopic}`; + switch (aTopic) { + case "content-process-ready-for-script": + case "app-startup": { + GeckoViewUtils.addLazyGetter(this, "GeckoViewConsole", { + module: "resource://gre/modules/GeckoViewConsole.jsm", + }); + + GeckoViewUtils.addLazyGetter(this, "GeckoViewStorageController", { + module: "resource://gre/modules/GeckoViewStorageController.jsm", + ged: [ + "GeckoView:ClearData", + "GeckoView:ClearSessionContextData", + "GeckoView:ClearHostData", + "GeckoView:ClearBaseDomainData", + "GeckoView:GetAllPermissions", + "GeckoView:GetPermissionsByURI", + "GeckoView:SetPermission", + "GeckoView:SetPermissionByURI", + "GeckoView:GetCookieBannerModeForDomain", + "GeckoView:SetCookieBannerModeForDomain", + "GeckoView:RemoveCookieBannerModeForDomain", + ], + }); + + GeckoViewUtils.addLazyGetter(this, "GeckoViewPushController", { + module: "resource://gre/modules/GeckoViewPushController.jsm", + ged: ["GeckoView:PushEvent", "GeckoView:PushSubscriptionChanged"], + }); + + GeckoViewUtils.addLazyPrefObserver( + { + name: "geckoview.console.enabled", + default: false, + }, + { + handler: _ => this.GeckoViewConsole, + } + ); + + // Parent process only + if ( + Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT + ) { + lazy.ActorManagerParent.addJSWindowActors(JSWINDOWACTORS); + lazy.ActorManagerParent.addJSProcessActors(JSPROCESSACTORS); + + if (Services.appinfo.sessionHistoryInParent) { + GeckoViewUtils.addLazyGetter(this, "GeckoViewSessionStore", { + module: "resource://gre/modules/GeckoViewSessionStore.jsm", + observers: [ + "browsing-context-did-set-embedder", + "browsing-context-discarded", + ], + }); + } + + GeckoViewUtils.addLazyGetter(this, "GeckoViewWebExtension", { + module: "resource://gre/modules/GeckoViewWebExtension.jsm", + ged: [ + "GeckoView:ActionDelegate:Attached", + "GeckoView:BrowserAction:Click", + "GeckoView:PageAction:Click", + "GeckoView:RegisterWebExtension", + "GeckoView:UnregisterWebExtension", + "GeckoView:WebExtension:CancelInstall", + "GeckoView:WebExtension:Disable", + "GeckoView:WebExtension:Enable", + "GeckoView:WebExtension:EnsureBuiltIn", + "GeckoView:WebExtension:Get", + "GeckoView:WebExtension:Install", + "GeckoView:WebExtension:InstallBuiltIn", + "GeckoView:WebExtension:List", + "GeckoView:WebExtension:PortDisconnect", + "GeckoView:WebExtension:PortMessageFromApp", + "GeckoView:WebExtension:SetPBAllowed", + "GeckoView:WebExtension:Uninstall", + "GeckoView:WebExtension:Update", + ], + observers: [ + "devtools-installed-addon", + "testing-installed-addon", + "testing-uninstalled-addon", + ], + }); + + GeckoViewUtils.addLazyGetter(this, "ChildCrashHandler", { + module: "resource://gre/modules/ChildCrashHandler.jsm", + observers: ["ipc:content-shutdown", "compositor:process-aborted"], + }); + + lazy.EventDispatcher.instance.registerListener(this, [ + "GeckoView:StorageDelegate:Attached", + ]); + } + break; + } + + case "profile-after-change": { + GeckoViewUtils.addLazyGetter(this, "GeckoViewRemoteDebugger", { + module: "resource://gre/modules/GeckoViewRemoteDebugger.jsm", + init: gvrd => gvrd.onInit(), + }); + + GeckoViewUtils.addLazyPrefObserver( + { + name: "devtools.debugger.remote-enabled", + default: false, + }, + { + handler: _ => this.GeckoViewRemoteDebugger, + } + ); + + GeckoViewUtils.addLazyGetter(this, "DownloadTracker", { + module: "resource://gre/modules/GeckoViewWebExtension.jsm", + ged: ["GeckoView:WebExtension:DownloadChanged"], + }); + + ChromeUtils.import("resource://gre/modules/NotificationDB.jsm"); + + // Listen for global EventDispatcher messages + lazy.EventDispatcher.instance.registerListener(this, [ + "GeckoView:ResetUserPrefs", + "GeckoView:SetDefaultPrefs", + "GeckoView:SetLocale", + ]); + + Services.obs.addObserver(this, "browser-idle-startup-tasks-finished"); + Services.obs.addObserver(this, "handlersvc-store-initialized"); + + Services.obs.notifyObservers(null, "geckoview-startup-complete"); + break; + } + case "browser-idle-startup-tasks-finished": { + // TODO bug 1730026: when an alternative is introduced that runs once, + // replace this observer topic with that alternative. + // This only needs to happen once during startup. + Services.obs.removeObserver(this, aTopic); + // Notify the start up crash tracker that the browser has successfully + // started up so the startup cache isn't rebuilt on next startup. + Services.startup.trackStartupCrashEnd(); + break; + } + case "handlersvc-store-initialized": { + // Initialize PdfJs when running in-process and remote. This only + // happens once since PdfJs registers global hooks. If the PdfJs + // extension is installed the init method below will be overridden + // leaving initialization to the extension. + // parent only: configure default prefs, set up pref observers, register + // pdf content handler, and initializes parent side message manager + // shim for privileged api access. + try { + lazy.PdfJs.init(this._isNewProfile); + } catch {} + break; + } + } + } + + onEvent(aEvent, aData, aCallback) { + debug`onEvent ${aEvent}`; + + switch (aEvent) { + case "GeckoView:ResetUserPrefs": { + const prefs = new lazy.Preferences(); + prefs.reset(aData.names); + break; + } + case "GeckoView:SetDefaultPrefs": { + const prefs = new lazy.Preferences({ defaultBranch: true }); + for (const name of Object.keys(aData)) { + try { + prefs.set(name, aData[name]); + } catch (e) { + warn`Failed to set preference ${name}: ${e}`; + } + } + break; + } + case "GeckoView:SetLocale": + if (aData.requestedLocales) { + Services.locale.requestedLocales = aData.requestedLocales; + } + const pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance( + Ci.nsIPrefLocalizedString + ); + pls.data = aData.acceptLanguages; + Services.prefs.setComplexValue( + "intl.accept_languages", + Ci.nsIPrefLocalizedString, + pls + ); + break; + + case "GeckoView:StorageDelegate:Attached": + InitLater(() => { + const loginDetection = Cc[ + "@mozilla.org/login-detection-service;1" + ].createInstance(Ci.nsILoginDetectionService); + loginDetection.init(); + }); + break; + } + } +} + +GeckoViewStartup.prototype.classID = Components.ID( + "{8e993c34-fdd6-432c-967e-f995d888777f}" +); +GeckoViewStartup.prototype.QueryInterface = ChromeUtils.generateQI([ + "nsIObserver", +]); |