GeckoViewStartup.jsm 9.03 KB
Newer Older
1
2
3
/* 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/. */
4
5
6
"use strict";

var EXPORTED_SYMBOLS = ["GeckoViewStartup"];
7

8
9
10
11
12
13
const { XPCOMUtils } = ChromeUtils.import(
  "resource://gre/modules/XPCOMUtils.jsm"
);
const { GeckoViewUtils } = ChromeUtils.import(
  "resource://gre/modules/GeckoViewUtils.jsm"
);
14

15
XPCOMUtils.defineLazyModuleGetters(this, {
16
  ActorManagerParent: "resource://gre/modules/ActorManagerParent.jsm",
17
  EventDispatcher: "resource://gre/modules/Messaging.jsm",
18
  Preferences: "resource://gre/modules/Preferences.jsm",
19
  SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
20
  Services: "resource://gre/modules/Services.jsm",
21
  RFPHelper: "resource://gre/modules/RFPHelper.jsm",
22
});
23

24
const { debug, warn } = GeckoViewUtils.initLogging("Startup");
25

26
const JSWINDOWACTORS = {
27
28
29
30
31
  LoadURIDelegate: {
    child: {
      moduleURI: "resource:///actors/LoadURIDelegateChild.jsm",
    },
  },
32
33
34
35
36
37
38
39
40
41
42
  GeckoViewPrompt: {
    child: {
      moduleURI: "resource:///actors/GeckoViewPromptChild.jsm",
      events: {
        click: { capture: false, mozSystemGroup: true },
        contextmenu: { capture: false, mozSystemGroup: true },
        DOMPopupBlocked: { capture: false, mozSystemGroup: true },
      },
    },
    allFrames: true,
  },
43
44
45
46
  WebBrowserChrome: {
    child: {
      moduleURI: "resource:///actors/WebBrowserChromeChild.jsm",
    },
47
    includeChrome: true,
48
  },
49
50
};

51
class GeckoViewStartup {
52
  /* ----------  nsIObserver  ---------- */
53
  observe(aSubject, aTopic, aData) {
54
    debug`observe: ${aTopic}`;
55
56
57
    switch (aTopic) {
      case "app-startup": {
        // Parent and content process.
58
        GeckoViewUtils.addLazyGetter(this, "GeckoViewPermission", {
59
60
61
62
63
64
          service: "@mozilla.org/content-permission/prompt;1",
          observers: [
            "getUserMedia:ask-device-permission",
            "getUserMedia:request",
            "PeerConnection:request",
          ],
65
          ppmm: ["GeckoView:AddCameraPermission"],
66
67
        });

68
69
        GeckoViewUtils.addLazyGetter(this, "GeckoViewRecordingMedia", {
          module: "resource://gre/modules/GeckoViewMedia.jsm",
70
          observers: ["recording-device-events"],
71
72
        });

73
74
75
76
        GeckoViewUtils.addLazyGetter(this, "GeckoViewConsole", {
          module: "resource://gre/modules/GeckoViewConsole.jsm",
        });

77
78
79
        GeckoViewUtils.addLazyGetter(this, "GeckoViewWebExtension", {
          module: "resource://gre/modules/GeckoViewWebExtension.jsm",
          ged: [
80
            "GeckoView:ActionDelegate:Attached",
81
82
            "GeckoView:BrowserAction:Click",
            "GeckoView:PageAction:Click",
83
            "GeckoView:RegisterWebExtension",
84
            "GeckoView:UnregisterWebExtension",
85
            "GeckoView:WebExtension:CancelInstall",
86
87
            "GeckoView:WebExtension:Disable",
            "GeckoView:WebExtension:Enable",
88
89
            "GeckoView:WebExtension:EnsureBuiltIn",
            "GeckoView:WebExtension:Get",
90
91
92
            "GeckoView:WebExtension:Install",
            "GeckoView:WebExtension:InstallBuiltIn",
            "GeckoView:WebExtension:List",
93
94
            "GeckoView:WebExtension:PortDisconnect",
            "GeckoView:WebExtension:PortMessageFromApp",
95
            "GeckoView:WebExtension:SetPBAllowed",
96
97
            "GeckoView:WebExtension:Uninstall",
            "GeckoView:WebExtension:Update",
98
99
100
          ],
        });

101
102
        GeckoViewUtils.addLazyGetter(this, "GeckoViewStorageController", {
          module: "resource://gre/modules/GeckoViewStorageController.jsm",
103
104
105
106
107
          ged: [
            "GeckoView:ClearData",
            "GeckoView:ClearSessionContextData",
            "GeckoView:ClearHostData",
          ],
108
109
        });

110
111
112
113
114
        GeckoViewUtils.addLazyGetter(this, "GeckoViewPushController", {
          module: "resource://gre/modules/GeckoViewPushController.jsm",
          ged: ["GeckoView:PushEvent", "GeckoView:PushSubscriptionChanged"],
        });

115
116
117
118
119
120
121
122
123
        GeckoViewUtils.addLazyGetter(
          this,
          "GeckoViewContentBlockingController",
          {
            module:
              "resource://gre/modules/GeckoViewContentBlockingController.jsm",
            ged: [
              "ContentBlocking:AddException",
              "ContentBlocking:RemoveException",
124
              "ContentBlocking:RemoveExceptionByPrincipal",
125
126
127
128
129
130
131
132
              "ContentBlocking:CheckException",
              "ContentBlocking:SaveList",
              "ContentBlocking:RestoreList",
              "ContentBlocking:ClearList",
            ],
          }
        );

133
134
135
136
137
138
139
140
141
        GeckoViewUtils.addLazyPrefObserver(
          {
            name: "geckoview.console.enabled",
            default: false,
          },
          {
            handler: _ => this.GeckoViewConsole,
          }
        );
142

143
144
        // Handle invalid form submission. If we don't hook up to this,
        // invalid forms are allowed to be submitted!
145
146
147
        Services.obs.addObserver(
          {
            QueryInterface: ChromeUtils.generateQI([
148
149
              "nsIObserver",
              "nsIFormSubmitObserver",
150
151
152
153
            ]),
            notifyInvalidSubmit: (form, element) => {
              // We should show the validation message here, bug 1510450.
            },
154
          },
155
156
          "invalidformsubmit"
        );
157

158
159
160
        if (
          Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT
        ) {
161
          ActorManagerParent.addJSWindowActors(JSWINDOWACTORS);
162

163
          Services.mm.loadFrameScript(
164
165
166
            "chrome://geckoview/content/GeckoViewPromptChild.js",
            true
          );
167
168
169

          GeckoViewUtils.addLazyGetter(this, "ContentCrashHandler", {
            module: "resource://gre/modules/ContentCrashHandler.jsm",
170
            observers: ["ipc:content-shutdown"],
171
          });
172
173
174
175
176
177
178
        }
        break;
      }

      case "profile-after-change": {
        // Parent process only.
        // ContentPrefServiceParent is needed for e10s file picker.
179
        GeckoViewUtils.addLazyGetter(this, "ContentPrefServiceParent", {
180
181
182
183
184
185
186
187
          module: "resource://gre/modules/ContentPrefServiceParent.jsm",
          init: cpsp => cpsp.alwaysInit(),
          ppmm: [
            "ContentPrefs:FunctionCall",
            "ContentPrefs:AddObserverForName",
            "ContentPrefs:RemoveObserverForName",
          ],
        });
188

189
190
191
192
193
        GeckoViewUtils.addLazyGetter(this, "GeckoViewRemoteDebugger", {
          module: "resource://gre/modules/GeckoViewRemoteDebugger.jsm",
          init: gvrd => gvrd.onInit(),
        });

194
195
196
197
198
199
200
201
202
        GeckoViewUtils.addLazyPrefObserver(
          {
            name: "devtools.debugger.remote-enabled",
            default: false,
          },
          {
            handler: _ => this.GeckoViewRemoteDebugger,
          }
        );
203

204
205
        ChromeUtils.import("resource://gre/modules/NotificationDB.jsm");

206
207
208
209
        // Initialize safe browsing module. This is required for content
        // blocking features and manages blocklist downloads and updates.
        SafeBrowsing.init();

210
        // Listen for global EventDispatcher messages
211
212
213
214
215
        EventDispatcher.instance.registerListener(this, [
          "GeckoView:ResetUserPrefs",
          "GeckoView:SetDefaultPrefs",
          "GeckoView:SetLocale",
        ]);
216
217

        Services.obs.notifyObservers(null, "geckoview-startup-complete");
218
219
        break;
      }
220
221
222
223
224
225
226
227
      case "browser-idle-startup-tasks-finished": {
        // 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;
      }
228
    }
229
  }
230
231

  onEvent(aEvent, aData, aCallback) {
232
    debug`onEvent ${aEvent}`;
233
234
235
236
237
238
239
240
241
242
243
244
245

    switch (aEvent) {
      case "GeckoView:ResetUserPrefs": {
        const prefs = new Preferences();
        prefs.reset(aData.names);
        break;
      }
      case "GeckoView:SetDefaultPrefs": {
        const prefs = new Preferences({ defaultBranch: true });
        for (const name of Object.keys(aData)) {
          try {
            prefs.set(name, aData[name]);
          } catch (e) {
246
            warn`Failed to set preference ${name}: ${e}`;
247
248
249
250
251
          }
        }
        break;
      }
      case "GeckoView:SetLocale":
252
253
254
        if (aData.requestedLocales) {
          Services.locale.requestedLocales = aData.requestedLocales;
        }
255
256
257
258
        RFPHelper._handleSpoofEnglishChanged();
        if (Services.prefs.getIntPref("privacy.spoof_english", 0) === 2) {
          break;
        }
259
        const pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(
260
261
          Ci.nsIPrefLocalizedString
        );
262
        pls.data = aData.acceptLanguages;
263
264
265
266
267
        Services.prefs.setComplexValue(
          "intl.accept_languages",
          Ci.nsIPrefLocalizedString,
          pls
        );
268
269
        break;
    }
270
271
  }
}
272

273
274
275
276
GeckoViewStartup.prototype.classID = Components.ID(
  "{8e993c34-fdd6-432c-967e-f995d888777f}"
);
GeckoViewStartup.prototype.QueryInterface = ChromeUtils.generateQI([
277
  "nsIObserver",
278
]);