BrowserGlue.jsm 175 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
var EXPORTED_SYMBOLS = [
6
  "AboutHomeStartupCache",
7
8
9
10
  "BrowserGlue",
  "ContentPermissionPrompt",
  "DefaultBrowserCheck",
];
11

12
13
14
15
16
17
18
const { XPCOMUtils } = ChromeUtils.import(
  "resource://gre/modules/XPCOMUtils.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { AppConstants } = ChromeUtils.import(
  "resource://gre/modules/AppConstants.jsm"
);
19

20
21
22
23
24
ChromeUtils.defineModuleGetter(
  this,
  "ActorManagerParent",
  "resource://gre/modules/ActorManagerParent.jsm"
);
25

26
27
28
29
30
31
ChromeUtils.defineModuleGetter(
  this,
  "CustomizableUI",
  "resource:///modules/CustomizableUI.jsm"
);

32
33
34
35
36
37
38
39
40
41
42
43
44
45
ChromeUtils.defineModuleGetter(
  this,
  "E10SUtils",
  "resource://gre/modules/E10SUtils.jsm"
);

ChromeUtils.defineModuleGetter(this, "Log", "resource://gre/modules/Log.jsm");

ChromeUtils.defineModuleGetter(
  this,
  "NetUtil",
  "resource://gre/modules/NetUtil.jsm"
);

46
47
48
49
50
51
ChromeUtils.defineModuleGetter(
  this,
  "DeferredTask",
  "resource://gre/modules/DeferredTask.jsm"
);

52
53
54
55
56
57
58
XPCOMUtils.defineLazyServiceGetter(
  this,
  "PushService",
  "@mozilla.org/push/Service;1",
  "nsIPushService"
);

59
60
61
62
63
64
65
XPCOMUtils.defineLazyServiceGetters(this, {
  resProto: [
    "@mozilla.org/network/protocol;1?name=resource",
    "nsISubstitutingProtocolHandler",
  ],
});

66
const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
67

68
69
70
71
72
73
74
75
/**
 * Fission-compatible JSProcess implementations.
 * Each actor options object takes the form of a ProcessActorOptions dictionary.
 * Detailed documentation of these options is in dom/docs/Fission.rst,
 * available at https://firefox-source-docs.mozilla.org/dom/Fission.html#jsprocessactor
 */
let JSPROCESSACTORS = {};

76
77
78
79
80
/**
 * Fission-compatible JSWindowActor implementations.
 * Detailed documentation of these is in dom/docs/Fission.rst,
 * available at https://firefox-source-docs.mozilla.org/dom/Fission.html#jswindowactor
 */
81
let JSWINDOWACTORS = {
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  AboutLogins: {
    parent: {
      moduleURI: "resource:///actors/AboutLoginsParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutLoginsChild.jsm",
      events: {
        AboutLoginsCopyLoginDetail: { wantUntrusted: true },
        AboutLoginsCreateLogin: { wantUntrusted: true },
        AboutLoginsDeleteLogin: { wantUntrusted: true },
        AboutLoginsDismissBreachAlert: { wantUntrusted: true },
        AboutLoginsHideFooter: { wantUntrusted: true },
        AboutLoginsImport: { wantUntrusted: true },
        AboutLoginsInit: { wantUntrusted: true },
        AboutLoginsGetHelp: { wantUntrusted: true },
        AboutLoginsOpenMobileAndroid: { wantUntrusted: true },
        AboutLoginsOpenMobileIos: { wantUntrusted: true },
        AboutLoginsOpenPreferences: { wantUntrusted: true },
        AboutLoginsOpenSite: { wantUntrusted: true },
        AboutLoginsRecordTelemetryEvent: { wantUntrusted: true },
        AboutLoginsSortChanged: { wantUntrusted: true },
        AboutLoginsSyncEnable: { wantUntrusted: true },
        AboutLoginsSyncOptions: { wantUntrusted: true },
        AboutLoginsUpdateLogin: { wantUntrusted: true },
106
        AboutLoginsExportPasswords: { wantUntrusted: true },
107
108
109
110
111
      },
    },
    matches: ["about:logins", "about:logins?*"],
  },

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  AboutNewInstall: {
    parent: {
      moduleURI: "resource:///actors/AboutNewInstallParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutNewInstallChild.jsm",

      events: {
        DOMWindowCreated: { capture: true },
      },
    },

    matches: ["about:newinstall"],
  },

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  AboutPlugins: {
    parent: {
      moduleURI: "resource:///actors/AboutPluginsParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutPluginsChild.jsm",

      events: {
        DOMWindowCreated: { capture: true },
      },
    },

    matches: ["about:plugins"],
  },

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  AboutPrivateBrowsing: {
    parent: {
      moduleURI: "resource:///actors/AboutPrivateBrowsingParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutPrivateBrowsingChild.jsm",

      events: {
        DOMWindowCreated: { capture: true },
      },
    },

    matches: ["about:privatebrowsing"],
  },

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  AboutProtections: {
    parent: {
      moduleURI: "resource:///actors/AboutProtectionsParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutProtectionsChild.jsm",

      events: {
        DOMWindowCreated: { capture: true },
      },
    },

    matches: ["about:protections"],
  },

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  AboutTabCrashed: {
    parent: {
      moduleURI: "resource:///actors/AboutTabCrashedParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutTabCrashedChild.jsm",

      events: {
        DOMWindowCreated: { capture: true },
      },
    },

    matches: ["about:tabcrashed*"],
  },

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  AboutWelcome: {
    parent: {
      moduleURI: "resource:///actors/AboutWelcomeParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/AboutWelcomeChild.jsm",
      events: {
        // This is added so the actor instantiates immediately and makes
        // methods available to the page js on load.
        DOMWindowCreated: {},
      },
    },
    matches: ["about:welcome"],

    // See Bug 1618306
    // Remove this preference check when we turn on separate about:welcome for all users.
    enablePreference: "browser.aboutwelcome.enabled",
  },

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  BlockedSite: {
    parent: {
      moduleURI: "resource:///actors/BlockedSiteParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/BlockedSiteChild.jsm",
      events: {
        AboutBlockedLoaded: { wantUntrusted: true },
        click: {},
      },
    },
    matches: ["about:blocked?*"],
    allFrames: true,
  },

221
222
223
224
225
226
227
228
  BrowserTab: {
    parent: {
      moduleURI: "resource:///actors/BrowserTabParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/BrowserTabChild.jsm",

      events: {
229
230
        DOMWindowCreated: {},
        MozAfterPaint: {},
231
232
233
234
235
236
        "MozDOMPointerLock:Entered": {},
        "MozDOMPointerLock:Exited": {},
      },
    },
  },

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  ClickHandler: {
    parent: {
      moduleURI: "resource:///actors/ClickHandlerParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/ClickHandlerChild.jsm",
      events: {
        click: { capture: true, mozSystemGroup: true },
        auxclick: { capture: true, mozSystemGroup: true },
      },
    },

    allFrames: true,
  },

252
253
254
255
256
257
258
259
260
261
262
263
264
265
  // Collects description and icon information from meta tags.
  ContentMeta: {
    parent: {
      moduleURI: "resource:///actors/ContentMetaParent.jsm",
    },

    child: {
      moduleURI: "resource:///actors/ContentMetaChild.jsm",
      events: {
        DOMMetaAdded: {},
      },
    },
  },

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  ContentSearch: {
    parent: {
      moduleURI: "resource:///actors/ContentSearchParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/ContentSearchChild.jsm",
      matches: [
        "about:home",
        "about:newtab",
        "about:welcome",
        "about:privatebrowsing",
        "chrome://mochitests/content/*",
      ],
      events: {
        ContentSearchClient: { capture: true, wantUntrusted: true },
      },
    },
  },

285
286
287
288
289
290
291
292
  ContextMenu: {
    parent: {
      moduleURI: "resource:///actors/ContextMenuParent.jsm",
    },

    child: {
      moduleURI: "resource:///actors/ContextMenuChild.jsm",
      events: {
293
        contextmenu: { mozSystemGroup: true },
294
295
296
297
298
299
      },
    },

    allFrames: true,
  },

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  DOMFullscreen: {
    parent: {
      moduleURI: "resource:///actors/DOMFullscreenParent.jsm",
    },

    child: {
      moduleURI: "resource:///actors/DOMFullscreenChild.jsm",
      group: "browsers",
      events: {
        "MozDOMFullscreen:Request": {},
        "MozDOMFullscreen:Entered": {},
        "MozDOMFullscreen:NewOrigin": {},
        "MozDOMFullscreen:Exit": {},
        "MozDOMFullscreen:Exited": {},
      },
    },

    allFrames: true,
  },

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  FormValidation: {
    parent: {
      moduleURI: "resource:///actors/FormValidationParent.jsm",
    },

    child: {
      moduleURI: "resource:///actors/FormValidationChild.jsm",
      events: {
        MozInvalidForm: {},
      },
    },

    allFrames: true,
  },

335
336
337
338
339
340
341
342
343
344
345
346
347
348
  LightweightTheme: {
    child: {
      moduleURI: "resource:///actors/LightweightThemeChild.jsm",
      events: {
        pageshow: { mozSystemGroup: true },
      },
    },
    includeChrome: true,
    allFrames: true,
    matches: [
      "about:home",
      "about:newtab",
      "about:welcome",
      "chrome://browser/content/syncedtabs/sidebar.xhtml",
349
350
      "chrome://browser/content/places/historySidebar.xhtml",
      "chrome://browser/content/places/bookmarksSidebar.xhtml",
351
352
353
    ],
  },

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  LinkHandler: {
    parent: {
      moduleURI: "resource:///actors/LinkHandlerParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/LinkHandlerChild.jsm",
      events: {
        DOMHeadElementParsed: {},
        DOMLinkAdded: {},
        DOMLinkChanged: {},
        pageshow: {},
        pagehide: {},
      },
    },
  },

370
371
372
373
374
375
376
  NetError: {
    parent: {
      moduleURI: "resource:///actors/NetErrorParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/NetErrorChild.jsm",
      events: {
377
        DOMWindowCreated: {},
378
379
380
381
382
383
384
385
        click: {},
      },
    },

    matches: ["about:certerror?*", "about:neterror?*"],
    allFrames: true,
  },

386
387
388
389
390
391
392
393
  PageInfo: {
    child: {
      moduleURI: "resource:///actors/PageInfoChild.jsm",
    },

    allFrames: true,
  },

394
395
396
397
398
399
400
401
402
403
404
405
406
407
  PageStyle: {
    parent: {
      moduleURI: "resource:///actors/PageStyleParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/PageStyleChild.jsm",
      events: {
        pageshow: {},
      },
    },

    // Only matching web pages, as opposed to internal about:, chrome: or
    // resource: pages. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
    matches: ["*://*/*"],
408
    messageManagerGroups: ["browsers"],
409
410
411
    allFrames: true,
  },

412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  Plugin: {
    parent: {
      moduleURI: "resource:///actors/PluginParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/PluginChild.jsm",
      events: {
        PluginBindingAttached: { capture: true, wantUntrusted: true },
        PluginCrashed: { capture: true },
        PluginOutdated: { capture: true },
        PluginInstantiated: { capture: true },
        PluginRemoved: { capture: true },
        HiddenPlugin: { capture: true },
      },

      observers: ["decoder-doctor-notification"],
    },

    allFrames: true,
  },

433
434
435
436
  Prompt: {
    parent: {
      moduleURI: "resource:///actors/PromptParent.jsm",
    },
437
    includeChrome: true,
438
439
440
    allFrames: true,
  },

441
442
443
444
445
446
447
448
449
450
451
452
453
454
  SearchTelemetry: {
    parent: {
      moduleURI: "resource:///actors/SearchTelemetryParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/SearchTelemetryChild.jsm",
      events: {
        DOMContentLoaded: {},
        pageshow: { mozSystemGroup: true },
        unload: {},
      },
    },
  },

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  ShieldFrame: {
    parent: {
      moduleURI: "resource://normandy-content/ShieldFrameParent.jsm",
    },
    child: {
      moduleURI: "resource://normandy-content/ShieldFrameChild.jsm",
      events: {
        pageshow: {},
        pagehide: {},
        ShieldPageEvent: { wantUntrusted: true },
      },
    },
    matches: ["about:studies"],
  },

470
471
472
473
474
475
476
  SwitchDocumentDirection: {
    child: {
      moduleURI: "resource:///actors/SwitchDocumentDirectionChild.jsm",
    },

    allFrames: true,
  },
477

478
479
480
481
482
483
484
485
486
487
488
  SiteSpecificBrowser: {
    parent: {
      moduleURI: "resource:///actors/SiteSpecificBrowserParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/SiteSpecificBrowserChild.jsm",
    },

    allFrames: true,
  },

489
490
491
492
493
494
495
496
  Translation: {
    parent: {
      moduleURI: "resource:///modules/translation/TranslationParent.jsm",
    },
    child: {
      moduleURI: "resource:///modules/translation/TranslationChild.jsm",
      events: {
        pageshow: {},
497
        load: { mozSystemGroup: true, capture: true },
498
499
500
501
502
      },
    },
    enablePreference: "browser.translation.detectLanguage",
  },

503
504
505
506
507
508
509
510
511
512
513
  UITour: {
    parent: {
      moduleURI: "resource:///modules/UITourParent.jsm",
    },
    child: {
      moduleURI: "resource:///modules/UITourChild.jsm",
      events: {
        mozUITour: { wantUntrusted: true },
      },
    },
  },
514
515
516
517
518
519
520
521
522
523
524

  WebRTC: {
    parent: {
      moduleURI: "resource:///actors/WebRTCParent.jsm",
    },
    child: {
      moduleURI: "resource:///actors/WebRTCChild.jsm",
    },

    allFrames: true,
  },
525
526
527
};

let LEGACY_ACTORS = {
528
529
530
531
532
533
534
535
536
537
538
539
540
541
  AboutReader: {
    child: {
      module: "resource:///actors/AboutReaderChild.jsm",
      group: "browsers",
      events: {
        AboutReaderContentLoaded: { wantUntrusted: true },
        DOMContentLoaded: {},
        pageshow: { mozSystemGroup: true },
        pagehide: { mozSystemGroup: true },
      },
      messages: ["Reader:ToggleReaderMode", "Reader:PushState"],
    },
  },

542
543
544
545
546
547
548
  URIFixup: {
    child: {
      module: "resource:///actors/URIFixupChild.jsm",
      group: "browsers",
      observers: ["keyword-uri-fixup"],
    },
  },
549
550
551
552
553
554
555
  OnionLocation: {
    child: {
      module: "resource:///modules/OnionLocationChild.jsm",
      events: { pageshow: {} },
      messages: ["OnionLocation:Refresh"],
    },
  },
556
557
};

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
if (AppConstants.TOR_BROWSER_UPDATE) {
  LEGACY_ACTORS["AboutTBUpdate"] = {
    child: {
      module: "resource:///actors/AboutTBUpdateChild.jsm",
      events: {
        "AboutTBUpdateLoad": {wantUntrusted: true},
        "pagehide": {capture: true},
      },
      matches: ["about:tbupdate"],
      messages: [
        "AboutTBUpdate:Update",
      ],
    }
  };
}

574
(function earlyBlankFirstPaint() {
575
576
577
578
  if (
    AppConstants.platform == "macosx" ||
    !Services.prefs.getBoolPref("browser.startup.blankWindow", false)
  ) {
579
    return;
580
  }
581

582
583
  // Until bug 1450626 and bug 1488384 are fixed, skip the blank window when
  // using a non-default theme.
584
585
586
587
588
589
  if (
    Services.prefs.getCharPref(
      "extensions.activeThemeID",
      "default-theme@mozilla.org"
    ) != "default-theme@mozilla.org"
  ) {
590
    return;
591
  }
592

593
  let store = Services.xulStore;
594
  let getValue = attr =>
595
    store.getValue(AppConstants.BROWSER_CHROME_URL, "main-window", attr);
596
597
598
599
  let width = getValue("width");
  let height = getValue("height");

  // The clean profile case isn't handled yet. Return early for now.
600
  if (!width || !height) {
601
    return;
602
  }
603
604
605

  let browserWindowFeatures =
    "chrome,all,dialog=no,extrachrome,menubar,resizable,scrollbars,status," +
606
    "location,toolbar,personalbar";
607
608
609
610
611
612
613
  let win = Services.ww.openWindow(
    null,
    "about:blank",
    null,
    browserWindowFeatures,
    null
  );
614
615

  // Hide the titlebar if the actual browser window will draw in it.
616
617
618
619
  let hiddenTitlebar = Services.prefs.getBoolPref(
    "browser.tabs.drawInTitlebar",
    win.matchMedia("(-moz-gtk-csd-hide-titlebar-by-default)").matches
  );
620
  if (hiddenTitlebar) {
621
    win.windowUtils.setChromeMargin(0, 2, 2, 2);
622
623
  }

624
625
626
  let docElt = win.document.documentElement;
  docElt.setAttribute("screenX", getValue("screenX"));
  docElt.setAttribute("screenY", getValue("screenY"));
627
628
629
630
631
632

  // The sizemode="maximized" attribute needs to be set before first paint.
  let sizemode = getValue("sizemode");
  if (sizemode == "maximized") {
    docElt.setAttribute("sizemode", sizemode);

633
634
635
    // Set the size to use when the user leaves the maximized mode.
    // The persisted size is the outer size, but the height/width
    // attributes set the inner size.
636
    let appWin = win.docShell.treeOwner
637
      .QueryInterface(Ci.nsIInterfaceRequestor)
638
639
640
      .getInterface(Ci.nsIAppWindow);
    height -= appWin.outerToInnerHeightDifferenceInCSSPixels;
    width -= appWin.outerToInnerWidthDifferenceInCSSPixels;
641
642
643
644
645
646
647
648
    docElt.setAttribute("height", height);
    docElt.setAttribute("width", width);
  } else {
    // Setting the size of the window in the features string instead of here
    // causes the window to grow by the size of the titlebar.
    win.resizeTo(width, height);
  }

649
650
651
652
  // Set this before showing the window so that graphics code can use it to
  // decide to skip some expensive code paths (eg. starting the GPU process).
  docElt.setAttribute("windowtype", "navigator:blank");

653
654
655
  // The window becomes visible after OnStopRequest, so make this happen now.
  win.stop();

656
657
658
  let { TelemetryTimestamps } = ChromeUtils.import(
    "resource://gre/modules/TelemetryTimestamps.jsm"
  );
659
  TelemetryTimestamps.add("blankWindowShown");
660
661
})();

662
663
664
665
XPCOMUtils.defineLazyGetter(
  this,
  "WeaveService",
  () => Cc["@mozilla.org/weave/service;1"].getService().wrappedJSObject
666
);
667

668
// lazy module getters
669

670
XPCOMUtils.defineLazyModuleGetters(this, {
671
  AboutCertViewerHandler: "resource://gre/modules/AboutCertViewerHandler.jsm",
672
673
674
  AddonManager: "resource://gre/modules/AddonManager.jsm",
  AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.jsm",
  AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
675
  Blocklist: "resource://gre/modules/Blocklist.jsm",
676
677
678
  BookmarkHTMLUtils: "resource://gre/modules/BookmarkHTMLUtils.jsm",
  BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.jsm",
  BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
679
  BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
680
  BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
681
682
  ContextualIdentityService:
    "resource://gre/modules/ContextualIdentityService.jsm",
683
  Corroborate: "resource://gre/modules/Corroborate.jsm",
684
  Discovery: "resource:///modules/Discovery.jsm",
685
  ExtensionData: "resource://gre/modules/Extension.jsm",
686
  ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
687
  FirefoxMonitor: "resource:///modules/FirefoxMonitor.jsm",
688
  FxAccounts: "resource://gre/modules/FxAccounts.jsm",
689
  HomePage: "resource:///modules/HomePage.jsm",
690
  Integration: "resource://gre/modules/Integration.jsm",
691
  LoginBreaches: "resource:///modules/LoginBreaches.jsm",
692
  LiveBookmarkMigrator: "resource:///modules/LiveBookmarkMigrator.jsm",
693
  NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
694
  Normandy: "resource://normandy/Normandy.jsm",
695
  ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
696
697
698
699
700
701
702
703
704
705
  OS: "resource://gre/modules/osfile.jsm",
  PageActions: "resource:///modules/PageActions.jsm",
  PageThumbs: "resource://gre/modules/PageThumbs.jsm",
  PdfJs: "resource://pdf.js/PdfJs.jsm",
  PermissionUI: "resource:///modules/PermissionUI.jsm",
  PlacesBackups: "resource://gre/modules/PlacesBackups.jsm",
  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
  PluralForm: "resource://gre/modules/PluralForm.jsm",
  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
  ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
706
  RemoteSettings: "resource://services-settings/remote-settings.js",
707
708
  RemoteSecuritySettings:
    "resource://gre/modules/psm/RemoteSecuritySettings.jsm",
709
  RFPHelper: "resource://gre/modules/RFPHelper.jsm",
710
  SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
711
  Sanitizer: "resource:///modules/Sanitizer.jsm",
712
  SaveToPocket: "chrome://pocket/content/SaveToPocket.jsm",
713
  SearchTelemetry: "resource:///modules/SearchTelemetry.jsm",
714
  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
715
716
717
  SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
  ShellService: "resource:///modules/ShellService.jsm",
  TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
718
  TabUnloader: "resource:///modules/TabUnloader.jsm",
719
  TRRRacer: "resource:///modules/TRRPerformance.jsm",
720
  OnionAliasStore: "resource:///modules/OnionAliasStore.jsm",
721
722
723
724
  UIState: "resource://services-sync/UIState.jsm",
  WebChannel: "resource://gre/modules/WebChannel.jsm",
  WindowsRegistry: "resource://gre/modules/WindowsRegistry.jsm",
});
725

726
727
// eslint-disable-next-line no-unused-vars
XPCOMUtils.defineLazyModuleGetters(this, {
728
  AboutLoginsParent: "resource:///modules/AboutLoginsParent.jsm",
729
  AsyncPrefs: "resource://gre/modules/AsyncPrefs.jsm",
730
  OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
731
  PluginManager: "resource:///actors/PluginParent.jsm",
732
  ReaderParent: "resource:///modules/ReaderParent.jsm",
733
734
});

735
736
737
738
739
/**
 * IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL.
 * XXX Bug 1325373 is for making eslint detect these automatically.
 */

740
741
let initializedModules = {};

742
[
743
744
745
746
747
  [
    "ContentPrefServiceParent",
    "resource://gre/modules/ContentPrefServiceParent.jsm",
    "alwaysInit",
  ],
748
  ["UpdateListener", "resource://gre/modules/UpdateListener.jsm", "init"],
749
].forEach(([name, resource, init]) => {
750
  XPCOMUtils.defineLazyGetter(this, name, () => {
751
    ChromeUtils.import(resource, initializedModules);
752
753
754
    initializedModules[name][init]();
    return initializedModules[name];
  });
755
});
756

757
if (AppConstants.MOZ_CRASHREPORTER) {
758
759
760
  XPCOMUtils.defineLazyModuleGetters(this, {
    UnsubmittedCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
  });
761
}
762

763
764
765
766
767
if (AppConstants.TOR_BROWSER_UPDATE) {
  XPCOMUtils.defineLazyModuleGetter(this, "AboutTBUpdate",
                                    "resource:///modules/AboutTBUpdate.jsm");
}

768
XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
769
770
771
  return Services.strings.createBundle(
    "chrome://branding/locale/brand.properties"
  );
772
773
774
});

XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
775
776
777
  return Services.strings.createBundle(
    "chrome://browser/locale/browser.properties"
  );
778
779
});

780
XPCOMUtils.defineLazyGetter(this, "gTabbrowserBundle", function() {
781
782
783
  return Services.strings.createBundle(
    "chrome://browser/locale/tabbrowser.properties"
  );
784
785
});

786
787
788
const global = this;

const listeners = {
789
  observers: {
790
    "update-downloading": ["UpdateListener"],
791
792
793
794
    "update-staged": ["UpdateListener"],
    "update-downloaded": ["UpdateListener"],
    "update-available": ["UpdateListener"],
    "update-error": ["UpdateListener"],
795
796
    "gmp-plugin-crash": ["PluginManager"],
    "plugin-crashed": ["PluginManager"],
797
798
  },

799
  ppmm: {
800
801
802
803
804
    // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN ContentPrefServiceParent.init
    "ContentPrefs:FunctionCall": ["ContentPrefServiceParent"],
    "ContentPrefs:AddObserverForName": ["ContentPrefServiceParent"],
    "ContentPrefs:RemoveObserverForName": ["ContentPrefServiceParent"],
    // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN ContentPrefServiceParent.init
805
806
807
808
809

    // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN AsyncPrefs.init
    "AsyncPrefs:SetPref": ["AsyncPrefs"],
    "AsyncPrefs:ResetPref": ["AsyncPrefs"],
    // PLEASE KEEP THIS LIST IN SYNC WITH THE LISTENERS ADDED IN AsyncPrefs.init
810
811
812
  },

  mm: {
813
    "AboutLogins:CreateLogin": ["AboutLoginsParent"],
814
    "AboutLogins:DeleteLogin": ["AboutLoginsParent"],
815
    "AboutLogins:DismissBreachAlert": ["AboutLoginsParent"],
816
    "AboutLogins:HideFooter": ["AboutLoginsParent"],
817
    "AboutLogins:Import": ["AboutLoginsParent"],
818
    "AboutLogins:MasterPasswordRequest": ["AboutLoginsParent"],
819
    "AboutLogins:OpenFAQ": ["AboutLoginsParent"],
820
    "AboutLogins:GetHelp": ["AboutLoginsParent"],
821
    "AboutLogins:OpenPreferences": ["AboutLoginsParent"],
822
823
    "AboutLogins:OpenMobileAndroid": ["AboutLoginsParent"],
    "AboutLogins:OpenMobileIos": ["AboutLoginsParent"],
824
    "AboutLogins:OpenSite": ["AboutLoginsParent"],
825
    "AboutLogins:SortChanged": ["AboutLoginsParent"],
826
    "AboutLogins:Subscribe": ["AboutLoginsParent"],
827
828
    "AboutLogins:SyncEnable": ["AboutLoginsParent"],
    "AboutLogins:SyncOptions": ["AboutLoginsParent"],
829
    "AboutLogins:TestOnlyResetOSAuth": ["AboutLoginsParent"],
830
    "AboutLogins:UpdateLogin": ["AboutLoginsParent"],
831
    "AboutLogins:VulnerableLogins": ["AboutLoginsParent"],
832
833
    "Reader:FaviconRequest": ["ReaderParent"],
    "Reader:UpdateReaderButton": ["ReaderParent"],
834
    "OnionLocation:Set": ["OnionLocationParent"],
835
836
  },

837
838
839
840
841
842
843
844
845
846
  observe(subject, topic, data) {
    for (let module of this.observers[topic]) {
      try {
        global[module].observe(subject, topic, data);
      } catch (e) {
        Cu.reportError(e);
      }
    }
  },

847
  receiveMessage(modules, data) {
848
    let val;
849
850
    for (let module of modules[data.name]) {
      try {
851
        val = global[module].receiveMessage(data) || val;
852
853
854
855
      } catch (e) {
        Cu.reportError(e);
      }
    }
856
    return val;
857
858
859
  },

  init() {
860
861
862
863
    for (let observer of Object.keys(this.observers)) {
      Services.obs.addObserver(this, observer);
    }

864
865
866
867
868
869
870
871
872
    let receiveMessageMM = this.receiveMessage.bind(this, this.mm);
    for (let message of Object.keys(this.mm)) {
      Services.mm.addMessageListener(message, receiveMessageMM);
    }

    let receiveMessagePPMM = this.receiveMessage.bind(this, this.ppmm);
    for (let message of Object.keys(this.ppmm)) {
      Services.ppmm.addMessageListener(message, receiveMessagePPMM);
    }
873
  },
874
875
};

876
// Seconds of idle before trying to create a bookmarks backup.
877
const BOOKMARKS_BACKUP_IDLE_TIME_SEC = 8 * 60;
878
879
880
881
882
// Minimum interval between backups.  We try to not create more than one backup
// per interval.
const BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS = 1;
// Maximum interval between backups.  If the last backup is older than these
// days we will try to create a new one more aggressively.
883
const BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS = 3;
884
885
// Seconds of idle time before the late idle tasks will be scheduled.
const LATE_TASKS_IDLE_TIME_SEC = 20;
886
887
// Time after we stop tracking startup crashes.
const STARTUP_CRASHES_END_DELAY_MS = 30 * 1000;
888

889
890
891
892
893
/*
 * OS X has the concept of zero-window sessions and therefore ignores the
 * browser-lastwindow-close-* topics.
 */
const OBSERVE_LASTWINDOW_CLOSE_TOPICS = AppConstants.platform != "macosx";
894
895

function BrowserGlue() {
896
897
898
899
900
901
  XPCOMUtils.defineLazyServiceGetter(
    this,
    "_idleService",
    "@mozilla.org/widget/idleservice;1",
    "nsIIdleService"
  );
902

903
  XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() {
904
905
906
907
908
    const { DistributionCustomizer } = ChromeUtils.import(
      "resource:///modules/distribution.js"
    );
    return new DistributionCustomizer();
  });
909

910
911
912
913
914
915
  XPCOMUtils.defineLazyServiceGetter(
    this,
    "AlertsService",
    "@mozilla.org/alerts-service;1",
    "nsIAlertsService"
  );
916

917
918
919
920
  this._init();
}

BrowserGlue.prototype = {
921
  _saveSession: false,
922
  _migrationImportsDefaultBookmarks: false,
923
  _placesBrowserInitComplete: false,
924
  _isNewProfile: undefined,
925

926
  _setPrefToSaveSession: function BG__setPrefToSaveSession(aForce) {
927
    if (!this._saveSession && !aForce) {
928
      return;
929
    }
930

931
    if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
932
933
934
935
      Services.prefs.setBoolPref(
        "browser.sessionstore.resume_session_once",
        true
      );
936
    }
937
938
939
940

    // This method can be called via [NSApplication terminate:] on Mac, which
    // ends up causing prefs not to be flushed to disk, so we need to do that
    // explicitly here. See bug 497652.
941
    Services.prefs.savePrefFile(null);
942
943
  },

944
945
946
  _setSyncAutoconnectDelay: function BG__setSyncAutoconnectDelay() {
    // Assume that a non-zero value for services.sync.autoconnectDelay should override
    if (Services.prefs.prefHasUserValue("services.sync.autoconnectDelay")) {
947
948
949
      let prefDelay = Services.prefs.getIntPref(
        "services.sync.autoconnectDelay"
      );
950

951
      if (prefDelay > 0) {
952
        return;
953
      }
954
955
956
957
958
    }

    // delays are in seconds
    const MAX_DELAY = 300;
    let delay = 3;
959
    for (let win of Services.wm.getEnumerator("navigator:browser")) {
960
961
962
963
964
      // browser windows without a gBrowser almost certainly means we are
      // shutting down, so instead of just ignoring that window we abort.
      if (win.closed || !win.gBrowser) {
        return;
      }
965
      delay += win.gBrowser.tabs.length;
966
967
968
    }
    delay = delay <= MAX_DELAY ? delay : MAX_DELAY;

969
    const { Weave } = ChromeUtils.import("resource://services-sync/main.js");
970
    Weave.Service.scheduler.delayedAutoConnect(delay);
971
972
  },

973
  // nsIObserver implementation
974
  observe: async function BG_observe(subject, topic, data) {
975
    switch (topic) {
976
      case "notifications-open-settings":
977
        this._openPreferences("privacy-permissions");
978
        break;
979
      case "final-ui-startup":
980
        this._beforeUIStartup();
981
        break;
982
      case "browser-delayed-startup-finished":
983
        this._onFirstWindowLoaded(subject);
984
985
        Services.obs.removeObserver(this, "browser-delayed-startup-finished");
        break;
986
      case "sessionstore-windows-restored":
987
        this._onWindowsRestored();
988
        break;
989
990
      case "browser:purge-session-history":
        // reset the console service's error buffer
991
992
        Services.console.logStringMessage(null); // clear the console (in case it's open)
        Services.console.reset();
993
        break;
994
995
996
      case "restart-in-safe-mode":
        this._onSafeModeRestart();
        break;
997
      case "quit-application-requested":
998
        this._onQuitRequest(subject, data);
999
1000
        break;
      case "quit-application-granted":
For faster browsing, not all history is shown. View entire blame