merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 15 Apr 2017 19:59:24 +0200
changeset 563334 d65b53cf8fd9f7747c7ee4e3ea96f12434917daa
parent 563333 ed88aa504601fc1a97ad83f8b4f3c17182a09425 (current diff)
parent 563292 cd981920d0ef8adf66e504b718a4208dc03c7a4c (diff)
child 563335 ce69b6e1773e9e0d0a190ce899f34b1658e66ca4
push id54258
push usercpeterson@mozilla.com
push dateSun, 16 Apr 2017 05:52:14 +0000
reviewersmerge, merge
milestone55.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: JpAhOPjgvkF
browser/base/content/browser-data-submission-info-bar.js
browser/base/content/nsContextMenu.js
browser/base/content/tabbrowser.xml
browser/base/content/urlbarBindings.xml
browser/components/preferences/in-content/advanced.js
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/privacy.js
browser/components/search/content/search.xml
browser/modules/BrowserUsageTelemetry.jsm
gfx/layers/Compositor.h
gfx/layers/d3d11/CompositorD3D11.cpp
tools/lint/eslint/eslint-plugin-mozilla/package.json
tools/profiler/core/platform.cpp
tools/profiler/gecko/nsIProfileSaveEvent.idl
--- a/.eslintignore
+++ b/.eslintignore
@@ -59,16 +59,18 @@ browser/base/content/test/general/file_c
 browser/base/content/test/urlbar/file_blank_but_not_blank.html
 browser/base/content/newtab/**
 # Test files that are really json not js, and don't need to be linted.
 browser/components/sessionstore/test/unit/data/sessionstore_valid.js
 browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
 browser/components/tabview/**
 # generated & special files in cld2
 browser/components/translation/cld2/**
+# Screenshots is imported as a system add-on and has its own lint rules currently.
+browser/extensions/screenshots/**
 browser/extensions/pdfjs/content/build**
 browser/extensions/pdfjs/content/web**
 # generated or library files in pocket
 browser/extensions/pocket/content/panels/js/tmpl.js
 browser/extensions/pocket/content/panels/js/vendor/**
 browser/locales/**
 # vendor library files in activity-stream
 browser/extensions/activity-stream/vendor/**
--- a/.gitignore
+++ b/.gitignore
@@ -2,16 +2,17 @@
 
 # Filenames that should be ignored wherever they appear
 *~
 *.pyc
 *.pyo
 TAGS
 tags
 ID
+!/browser/extensions/screenshots/webextension/_locales/id/
 .DS_Store*
 *.pdb
 *.egg-info
 
 # Vim swap files.
 .*.sw[a-z]
 
 # Emacs directory variable files.
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -130,18 +130,18 @@ this.AccessFu = { // jshint ignore:line
         'Accessibility:MoveByGranularity',
         'Accessibility:NextObject',
         'Accessibility:PreviousObject',
         'Accessibility:ScrollBackward',
         'Accessibility:ScrollForward',
       ]);
     }
 
-    Services.obs.addObserver(this, 'remote-browser-shown', false);
-    Services.obs.addObserver(this, 'inprocess-browser-shown', false);
+    Services.obs.addObserver(this, 'remote-browser-shown');
+    Services.obs.addObserver(this, 'inprocess-browser-shown');
     Utils.win.addEventListener('TabOpen', this);
     Utils.win.addEventListener('TabClose', this);
     Utils.win.addEventListener('TabSelect', this);
 
     if (this.readyCallback) {
       this.readyCallback();
       delete this.readyCallback;
     }
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -594,17 +594,17 @@ const AccessibilityEventObserver = {
 
   /**
    * Start an AccessibilityEventObserver.
    */
   start: function start() {
     if (this.started || this.listenerCount === 0) {
       return;
     }
-    Services.obs.addObserver(this, 'accessible-event', false);
+    Services.obs.addObserver(this, 'accessible-event');
     this.started = true;
   },
 
   /**
    * Stop an AccessibilityEventObserver.
    */
   stop: function stop() {
     if (!this.started) {
--- a/accessible/tests/browser/e10s/events.js
+++ b/accessible/tests/browser/e10s/events.js
@@ -95,17 +95,17 @@ function waitForEvent(eventType, expecte
           ok(event.accessibleDocument instanceof nsIAccessibleDocument,
             'Accessible document present.');
 
           Services.obs.removeObserver(this, 'accessible-event');
           resolve(event);
         }
       }
     };
-    Services.obs.addObserver(eventObserver, 'accessible-event', false);
+    Services.obs.addObserver(eventObserver, 'accessible-event');
   });
 }
 
 /**
  * A helper function that waits for a sequence of accessible events in
  * specified order.
  * @param {Array} events        a list of events to wait (same format as
  *                              waitForEvent arguments)
--- a/accessible/tests/browser/head.js
+++ b/accessible/tests/browser/head.js
@@ -42,17 +42,17 @@ Services.scriptloader.loadSubScript(
  * @return {Promise} event promise evaluating to event's data
  */
 function a11yInitOrShutdownPromise() {
   return new Promise(resolve => {
     let observe = (subject, topic, data) => {
       Services.obs.removeObserver(observe, 'a11y-init-or-shutdown');
       resolve(data);
     };
-    Services.obs.addObserver(observe, 'a11y-init-or-shutdown', false);
+    Services.obs.addObserver(observe, 'a11y-init-or-shutdown');
   });
 }
 
 /**
  * Returns a promise that resolves when 'a11y-init-or-shutdown' event is fired
  * in content.
  * @param  {Object}   browser  current "tabbrowser" element
  * @return {Promise}  event    promise evaluating to event's data
@@ -118,17 +118,17 @@ function waitForEvent(eventType, expecte
         let event = subject.QueryInterface(Ci.nsIAccessibleEvent);
         if (event.eventType === eventType &&
             event.accessible.id === expectedId) {
           Services.obs.removeObserver(this, 'accessible-event');
           resolve(event);
         }
       }
     };
-    Services.obs.addObserver(eventObserver, 'accessible-event', false);
+    Services.obs.addObserver(eventObserver, 'accessible-event');
   });
 }
 
 /**
  * Force garbage collection.
  */
 function forceGC() {
   SpecialPowers.gc();
--- a/accessible/tests/mochitest/browser.js
+++ b/accessible/tests/mochitest/browser.js
@@ -144,10 +144,10 @@ function startBrowserTests()
 }
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       setTimeout(aCallback, 0);
     }
-  }, "browser-delayed-startup-finished", false);
+  }, "browser-delayed-startup-finished");
 }
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -2115,17 +2115,17 @@ var gA11yEventObserver =
   }
 };
 
 function listenA11yEvents(aStartToListen)
 {
   if (aStartToListen) {
     // Add observer when adding the first applicant only.
     if (!(gA11yEventApplicantsCount++))
-      Services.obs.addObserver(gA11yEventObserver, "accessible-event", false);
+      Services.obs.addObserver(gA11yEventObserver, "accessible-event");
   } else {
     // Remove observer when there are no more applicants only.
     // '< 0' case should not happen, but just in case: removeObserver() will throw.
     if (--gA11yEventApplicantsCount <= 0)
       Services.obs.removeObserver(gA11yEventObserver, "accessible-event");
   }
 }
 
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -65,17 +65,17 @@ var AccessFuTest = {
       var data = JSON.parse(aData)[1];
       // Ignore non-relevant outputs.
       if (!data) {
         return;
       }
       isDeeply(data.details, aWaitForData, "Data is correct");
       aListener.apply(listener);
     };
-    Services.obs.addObserver(listener, 'accessibility-output', false);
+    Services.obs.addObserver(listener, 'accessibility-output');
     return listener;
   },
 
   on: function AccessFuTest_on(aWaitForData, aListener) {
     return this._addObserver(aWaitForData, aListener);
   },
 
   off: function AccessFuTest_off(aListener) {
--- a/addon-sdk/source/lib/dev/frame-script.js
+++ b/addon-sdk/source/lib/dev/frame-script.js
@@ -106,15 +106,15 @@ const observer = {
           readyState: "uninitialized",
           uri: document.documentURI
         });
       }
     }
   }
 };
 
-observerService.addObserver(observer, "content-document-interactive", false);
-observerService.addObserver(observer, "content-document-loaded", false);
-observerService.addObserver(observer, "chrome-document-interactive", false);
-observerService.addObserver(observer, "chrome-document-loaded", false);
+observerService.addObserver(observer, "content-document-interactive");
+observerService.addObserver(observer, "content-document-loaded");
+observerService.addObserver(observer, "chrome-document-interactive");
+observerService.addObserver(observer, "chrome-document-loaded");
 addEventListener("unload", observer, false);
 
 })(this);
--- a/addon-sdk/source/lib/sdk/addon/bootstrap.js
+++ b/addon-sdk/source/lib/sdk/addon/bootstrap.js
@@ -130,17 +130,18 @@ Bootstrap.prototype = {
       self.loader = loader;
 
       const module = Module("package.json", `${baseURI}package.json`);
       const require = Require(loader, module);
       const main = command === "test" ? "sdk/test/runner" : null;
       const prefsURI = `${baseURI}defaults/preferences/prefs.js`;
 
       // Init the 'sdk/webextension' module from the bootstrap addon parameter.
-      require("sdk/webextension").initFromBootstrapAddonParam(addon);
+      if (addon.webExtension)
+        require("sdk/webextension").initFromBootstrapAddonParam(addon);
 
       const { startup } = require("sdk/addon/runner");
       startup(reason, {loader, main, prefsURI});
     }.bind(this)).catch(error => {
       console.error(`Failed to start ${id} addon`, error);
       throw error;
     });
   },
--- a/addon-sdk/source/lib/sdk/addon/runner.js
+++ b/addon-sdk/source/lib/sdk/addon/runner.js
@@ -5,24 +5,20 @@
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Cc, Ci, Cu } = require('chrome');
 const { rootURI, metadata, isNative } = require('@loader/options');
 const { id, loadReason } = require('../self');
 const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
-const { once } = require('../system/events');
 const { exit, env, staticArgs } = require('../system');
 const { when: unload } = require('../system/unload');
 const globals = require('../system/globals');
-const xulApp = require('../system/xul-app');
 const { get } = require('../preferences/service');
-const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
-                        getService(Ci.nsIAppShellService);
 const { preferences } = metadata;
 
 const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function () {
   return Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", {}).
          BrowserToolboxProcess;
--- a/addon-sdk/source/lib/sdk/console/traceback.js
+++ b/addon-sdk/source/lib/sdk/console/traceback.js
@@ -4,17 +4,17 @@
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Ci, components } = require("chrome");
 const { parseStack, sourceURI } = require("toolkit/loader");
-const { readURISync } = require("../net/url");
+lazyRequire(this, "../net/url", "readURISync");
 
 function safeGetFileLine(path, line) {
   try {
     var scheme = require("../url").URL(path).scheme;
     // TODO: There should be an easier, more accurate way to figure out
     // what's the case here.
     if (!(scheme == "http" || scheme == "https"))
       return readURISync(path).split("\n")[line - 1];
--- a/addon-sdk/source/lib/sdk/content/events.js
+++ b/addon-sdk/source/lib/sdk/content/events.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Ci } = require("chrome");
-const { open } = require("../event/dom");
+lazyRequire(this, "../event/dom", "open");
 const { observe } = require("../event/chrome");
 const { filter, merge, map, expand } = require("../event/utils");
 const { windows } = require("../window/utils");
 const { events: windowEvents } = require("sdk/window/events");
 
 // Note: Please note that even though pagehide event is included
 // it's not observable reliably since it's not always triggered
 // when closing tabs. Implementation can be imrpoved once that
--- a/addon-sdk/source/lib/sdk/content/l10n-html.js
+++ b/addon-sdk/source/lib/sdk/content/l10n-html.js
@@ -3,19 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Ci, Cc, Cu } = require("chrome");
-const core = require("../l10n/core");
-const { loadSheet, removeSheet } = require("../stylesheet/utils");
+lazyRequireModule(this, "../l10n/core", "core");
+lazyRequire(this, "../stylesheet/utils", "loadSheet", "removeSheet");
 const { process, frames } = require("../remote/child");
+
 var observerService = Cc["@mozilla.org/observer-service;1"]
                       .getService(Ci.nsIObserverService);
 const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
 const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
 const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
 
 const assetsURI = require('../self').data.url();
 
--- a/addon-sdk/source/lib/sdk/content/page-mod.js
+++ b/addon-sdk/source/lib/sdk/content/page-mod.js
@@ -2,36 +2,30 @@
  * 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";
 
 module.metadata = {
   "stability": "stable"
 };
 
-const { getAttachEventType } = require('../content/utils');
+lazyRequire(this, '../content/utils', 'getAttachEventType');
 const { Class } = require('../core/heritage');
 const { Disposable } = require('../core/disposable');
-const { WeakReference } = require('../core/reference');
-const { WorkerChild } = require('./worker-child');
+lazyRequire(this, './worker-child', 'WorkerChild');
 const { EventTarget } = require('../event/target');
 const { on, emit, once, setListeners } = require('../event/core');
-const { on: domOn, removeListener: domOff } = require('../dom/events');
-const { isRegExp, isUndefined } = require('../lang/type');
-const { merge } = require('../util/object');
-const { isBrowser, getFrames } = require('../window/utils');
-const { getTabs, getURI: getTabURI } = require('../tabs/utils');
-const { ignoreWindow } = require('../private-browsing/utils');
-const { Style } = require("../stylesheet/style");
-const { attach, detach } = require("../content/mod");
-const { has, hasAny } = require("../util/array");
-const { Rules } = require("../util/rules");
-const { List, addListItem, removeListItem } = require('../util/list');
-const { when } = require("../system/unload");
-const { uuid } = require('../util/uuid');
+lazyRequire(this, '../dom/events',{'on': 'domOn', 'removeListener': 'domOff'});
+lazyRequire(this, '../util/object', "merge");
+lazyRequire(this, '../window/utils', "getFrames");
+lazyRequire(this, '../private-browsing/utils', "ignoreWindow");
+lazyRequire(this, '../stylesheet/style', 'Style');
+lazyRequire(this, '../content/mod', 'attach', 'detach');
+lazyRequire(this, '../util/rules', 'Rules');
+lazyRequire(this, '../util/uuid', 'uuid');
 const { frames, process } = require('../remote/child');
 
 const pagemods = new Map();
 const styles = new WeakMap();
 var styleFor = (mod) => styles.get(mod);
 
 // Helper functions
 var modMatchesURI = (mod, uri) => mod.include.matchesAny(uri) && !mod.exclude.matchesAny(uri);
@@ -74,17 +68,17 @@ const ChildPageMod = Class({
       }));
     }
 
     pagemods.set(this.id, this);
     this.seenDocuments = new WeakMap();
 
     // `applyOnExistingDocuments` has to be called after `pagemods.add()`
     // otherwise its calls to `onContent` method won't do anything.
-    if (has(this.attachTo, 'existing'))
+    if (this.attachTo.includes('existing'))
       applyOnExistingDocuments(this);
   },
 
   dispose: function() {
     let style = styleFor(this);
     if (style)
       detach(style);
 
@@ -127,19 +121,19 @@ function applyOnExistingDocuments (mod) 
   for (let frame of frames) {
     // Fake a newly created document
     let window = frame.content;
     // on startup with e10s, contentWindow might not exist yet,
     // in which case we will get notified by "document-element-inserted".
     if (!window || !window.frames)
       return;
     let uri = window.location.href;
-    if (has(mod.attachTo, "top") && modMatchesURI(mod, uri))
+    if (mod.attachTo.includes("top") && modMatchesURI(mod, uri))
       onContent(mod, window);
-    if (has(mod.attachTo, "frame"))
+    if (mod.attachTo.includes("frame"))
       getFrames(window).
         filter(iframe => modMatchesURI(mod, iframe.location.href)).
         forEach(frame => onContent(mod, frame));
   }
 }
 
 function createWorker(mod, window) {
   let workerId = String(uuid());
@@ -162,20 +156,20 @@ function createWorker(mod, window) {
   });
 
   once(worker, 'detach', () => worker.destroy());
 }
 
 function onContent (mod, window) {
   let isTopDocument = window.top === window;
   // Is a top level document and `top` is not set, ignore
-  if (isTopDocument && !has(mod.attachTo, "top"))
+  if (isTopDocument && !mod.attachTo.includes("top"))
     return;
   // Is a frame document and `frame` is not set, ignore
-  if (!isTopDocument && !has(mod.attachTo, "frame"))
+  if (!isTopDocument && !mod.attachTo.includes("frame"))
     return;
 
   // ensure we attach only once per document
   let seen = mod.seenDocuments;
   if (seen.has(window.document))
     return;
   seen.set(window.document, true);
 
--- a/addon-sdk/source/lib/sdk/content/page-worker.js
+++ b/addon-sdk/source/lib/sdk/content/page-worker.js
@@ -1,28 +1,30 @@
 /* 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";
 
 const { frames } = require("../remote/child");
 const { Class } = require("../core/heritage");
 const { Disposable } = require('../core/disposable');
-const { data } = require("../self");
-const { once } = require("../dom/events");
-const { getAttachEventType } = require("./utils");
-const { Rules } = require('../util/rules');
-const { uuid } = require('../util/uuid');
-const { WorkerChild } = require("./worker-child");
+lazyRequire(this, "../self", "data");
+lazyRequire(this, "../dom/events", "once");
+lazyRequire(this, "./utils", "getAttachEventType");
+lazyRequire(this, '../util/rules', "Rules");
+lazyRequire(this, '../util/uuid', "uuid");
+lazyRequire(this, "./worker-child", "WorkerChild");
 const { Cc, Ci, Cu } = require("chrome");
 const { on: onSystemEvent } = require("../system/events");
 
-const appShell = Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci.nsIAppShellService);
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 
-const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, 'appShell',
+                                   "@mozilla.org/appshell/appShellService;1",
+                                   "nsIAppShellService");
 
 const pages = new Map();
 
 const DOC_INSERTED = "document-element-inserted";
 
 function isValidURL(page, url) {
   return !page.rules || page.rules.matchesAny(url);
 }
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ b/addon-sdk/source/lib/sdk/content/sandbox.js
@@ -4,29 +4,32 @@
 'use strict';
 
 module.metadata = {
   'stability': 'unstable'
 };
 
 const { Class } = require('../core/heritage');
 const { EventTarget } = require('../event/target');
-const { on, off, emit } = require('../event/core');
-const { events } = require('./sandbox/events');
-const { requiresAddonGlobal } = require('./utils');
-const { delay: async } = require('../lang/functional');
+lazyRequire(this, '../event/core', "on", "off", "emit");
+lazyRequire(this, './sandbox/events', "events");
+lazyRequire(this, './utils', "requiresAddonGlobal");
+lazyRequire(this, '../lang/functional', {"delay": "async"});
 const { Ci, Cu, Cc } = require('chrome');
-const timer = require('../timers');
-const { URL } = require('../url');
-const { sandbox, evaluate, load } = require('../loader/sandbox');
-const { merge } = require('../util/object');
-const { getTabForContentWindowNoShim } = require('../tabs/utils');
-const { getInnerId } = require('../window/utils');
-const { PlainTextConsole } = require('../console/plain-text');
-const { data } = require('../self');const { isChildLoader } = require('../remote/core');
+lazyRequireModule(this, "../timers", "timer");
+lazyRequire(this, '../url', "URL");
+lazyRequire(this, '../loader/sandbox', "sandbox", "evaluate", "load");
+lazyRequire(this, '../util/object', "merge");
+lazyRequire(this, '../tabs/utils', "getTabForContentWindowNoShim");
+lazyRequire(this, '../window/utils', "getInnerId");
+lazyRequire(this, '../console/plain-text', "PlainTextConsole");
+
+lazyRequire(this, '../self', "data");
+lazyRequire(this, '../remote/core', "isChildLoader");
+
 // WeakMap of sandboxes so we can access private values
 const sandboxes = new WeakMap();
 
 /* Trick the linker in order to ensure shipping these files in the XPI.
   require('./content-worker.js');
   Then, retrieve URL of these files in the XPI:
 */
 var prefix = module.uri.split('sandbox.js')[0];
--- a/addon-sdk/source/lib/sdk/content/utils.js
+++ b/addon-sdk/source/lib/sdk/content/utils.js
@@ -2,22 +2,22 @@
  * 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';
 
 module.metadata = {
   'stability': 'unstable'
 };
 
-var { merge } = require('../util/object');
-var { data } = require('../self');
+lazyRequire(this, '../util/object', "merge");
+lazyRequire(this, '../self', "data");
 var assetsURI = data.url();
 var isArray = Array.isArray;
 var method = require('../../method/core');
-var { uuid } = require('../util/uuid');
+lazyRequire(this, '../util/uuid', "uuid");
 
 const isAddonContent = ({ contentURL }) =>
   contentURL && data.url(contentURL).startsWith(assetsURI);
 
 exports.isAddonContent = isAddonContent;
 
 function hasContentScript({ contentScript, contentScriptFile }) {
   return (isArray(contentScript) ? contentScript.length > 0 :
--- a/addon-sdk/source/lib/sdk/content/worker-child.js
+++ b/addon-sdk/source/lib/sdk/content/worker-child.js
@@ -1,22 +1,22 @@
 /* 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';
 
-const { merge } = require('../util/object');
+lazyRequire(this, '../util/object', 'merge');
 const { Class } = require('../core/heritage');
-const { emit } = require('../event/core');
+lazyRequire(this, '../event/core', 'emit');
 const { EventTarget } = require('../event/target');
-const { getInnerId, getByInnerId } = require('../window/utils');
-const { instanceOf, isObject } = require('../lang/type');
-const system = require('../system/events');
+lazyRequire(this, '../window/utils', 'getInnerId');
+lazyRequire(this, '../lang/type', 'instanceOf', 'isObject');
+lazyRequireModule(this, '../system/events', 'system');
 const { when } = require('../system/unload');
-const { WorkerSandbox } = require('./sandbox');
+lazyRequire(this, './sandbox', 'WorkerSandbox');
 const { Ci } = require('chrome');
 const { process, frames } = require('../remote/child');
 
 const EVENTS = {
   'chrome-page-shown': 'pageshow',
   'content-page-shown': 'pageshow',
   'chrome-page-hidden': 'pagehide',
   'content-page-hidden': 'pagehide',
--- a/addon-sdk/source/lib/sdk/content/worker.js
+++ b/addon-sdk/source/lib/sdk/content/worker.js
@@ -2,29 +2,29 @@
  * 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";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-const { emit } = require('../event/core');
+lazyRequire(this, '../event/core', "emit");
 const { omit, merge } = require('../util/object');
 const { Class } = require('../core/heritage');
 const { method } = require('../lang/functional');
-const { getInnerId } = require('../window/utils');
+lazyRequire(this, '../window/utils', "getInnerId");
 const { EventTarget } = require('../event/target');
-const { isPrivate } = require('../private-browsing/utils');
-const { getTabForBrowser, getTabForContentWindowNoShim, getBrowserForTab } = require('../tabs/utils');
-const { attach, connect, detach, destroy, makeChildOptions } = require('./utils');
+lazyRequire(this, '../private-browsing/utils', "isPrivate");
+lazyRequire(this, '../tabs/utils', "getTabForBrowser", "getTabForContentWindowNoShim", "getBrowserForTab");
+lazyRequire(this, './utils', "attach", "connect", "detach", "destroy", "makeChildOptions");
 const { ensure } = require('../system/unload');
-const { on: observe } = require('../system/events');
+lazyRequire(this, '../system/events', {"on": "observe"});
 const { Ci, Cu } = require('chrome');
-const { modelFor: tabFor } = require('sdk/model/core');
+lazyRequire(this, 'sdk/model/core', {"modelFor": "tabFor"});
 const { remoteRequire, processes, frames } = require('../remote/parent');
 remoteRequire('sdk/content/worker-child');
 
 const workers = new WeakMap();
 var modelFor = (worker) => workers.get(worker);
 
 const ERR_DESTROYED = "Couldn't find the worker to receive this message. " +
   "The script may not be initialized yet, or may already have been unloaded.";
--- a/addon-sdk/source/lib/sdk/context-menu.js
+++ b/addon-sdk/source/lib/sdk/context-menu.js
@@ -8,29 +8,28 @@ module.metadata = {
   "engines": {
     // TODO Fennec support Bug 788334
     "Firefox": "*",
     "SeaMonkey": "*"
   }
 };
 
 const { Class, mix } = require("./core/heritage");
-const { addCollectionProperty } = require("./util/collection");
 const { ns } = require("./core/namespace");
-const { validateOptions, getTypeOf } = require("./deprecated/api-utils");
-const { URL, isValidURI } = require("./url");
-const { WindowTracker, browserWindowIterator } = require("./deprecated/window-utils");
-const { isBrowser, getInnerId } = require("./window/utils");
-const { MatchPattern } = require("./util/match-pattern");
+lazyRequire(this, "./deprecated/api-utils", "validateOptions", "getTypeOf");
+lazyRequire(this, "./url", "URL", "isValidURI");
+lazyRequire(this, "./deprecated/window-utils", "WindowTracker", "browserWindowIterator");
+lazyRequire(this, "./window/utils", "isBrowser", "getInnerId");
+lazyRequire(this, "./util/match-pattern", "MatchPattern");
 const { EventTarget } = require("./event/target");
-const { emit } = require('./event/core');
+lazyRequire(this, './event/core', "emit");
 const { when } = require('./system/unload');
 const { contract: loaderContract } = require('./content/loader');
 const { omit } = require('./util/object');
-const self = require('./self')
+lazyRequireModule(this, './self', "self");
 const { remoteRequire, processes } = require('./remote/parent');
 remoteRequire('sdk/content/context-menu');
 
 // All user items we add have this class.
 const ITEM_CLASS = "addon-context-menu-item";
 
 // Items in the top-level context menu also have this class.
 const TOPLEVEL_ITEM_CLASS = "addon-context-menu-item-toplevel";
--- a/addon-sdk/source/lib/sdk/context-menu/context.js
+++ b/addon-sdk/source/lib/sdk/context-menu/context.js
@@ -1,15 +1,14 @@
 /* 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/. */
 
 const { Class } = require("../core/heritage");
-const { extend } = require("../util/object");
-const { MatchPattern } = require("../util/match-pattern");
+lazyRequire(this, "../util/match-pattern", "MatchPattern");
 const readers = require("./readers");
 
 // Context class is required to implement a single `isCurrent(target)` method
 // that must return boolean value indicating weather given target matches a
 // context or not. Most context implementations below will have an associated
 // reader that way context implementation can setup a reader to extract necessary
 // information to make decision if target is matching a context.
 const Context = Class({
--- a/addon-sdk/source/lib/sdk/context-menu/core.js
+++ b/addon-sdk/source/lib/sdk/context-menu/core.js
@@ -61,17 +61,17 @@ const ContextMenuExtension = Class({
   extends: Component,
   initialize: Component,
   setup() {
     const messageListener = new WeakMessageListener(this, onMessage);
     loadModule(globalMessageManager, "framescript/context-menu", true, "onContentFrame");
     globalMessageManager.addMessageListener("sdk/context-menu/read", messageListener);
     globalMessageManager.addMessageListener("sdk/context-menu/readers?", messageListener);
 
-    preferencesService.addObserver(OVERFLOW_THRESH, this, false);
+    preferencesService.addObserver(OVERFLOW_THRESH, this);
   },
   observe(_, __, name) {
     if (name === OVERFLOW_THRESH) {
       const overflowThreshold = prefs.get(OVERFLOW_THRESH, 10);
       this[Component.patch]({overflowThreshold});
     }
   },
   [onMessage]({name, data, target}) {
--- a/addon-sdk/source/lib/sdk/core/disposable.js
+++ b/addon-sdk/source/lib/sdk/core/disposable.js
@@ -5,18 +5,19 @@
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Class } = require("./heritage");
 const { Observer, subscribe, unsubscribe, observe } = require("./observer");
-const { isWeak } = require("./reference");
-const SDKWeakSet = require("../lang/weak-set");
+
+lazyRequire(this, "./reference", "isWeak");
+lazyRequireModule(this, "../lang/weak-set", "SDKWeakSet");
 
 const method = require("../../method/core");
 
 const unloadSubject = require('@loader/unload');
 const addonUnloadTopic = "sdk:loader:destroy";
 
 const uninstall = method("disposable/uninstall");
 exports.uninstall = uninstall;
--- a/addon-sdk/source/lib/sdk/core/observer.js
+++ b/addon-sdk/source/lib/sdk/core/observer.js
@@ -6,17 +6,17 @@
 
 module.metadata = {
   "stability": "experimental"
 };
 
 
 const { Cc, Ci, Cr, Cu } = require("chrome");
 const { Class } = require("./heritage");
-const { isWeak } = require("./reference");
+lazyRequire(this, "./reference", "isWeak");
 const method = require("../../method/core");
 
 const observerService = Cc['@mozilla.org/observer-service;1'].
                           getService(Ci.nsIObserverService);
 
 const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
 const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
 const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test.js
@@ -2,22 +2,22 @@
  * 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";
 
 module.metadata = {
   "stability": "deprecated"
 };
 
-const timer = require("../timers");
+lazyRequireModule(this, "../timers", "timer");
 const cfxArgs = require("../test/options");
-const { getTabs, closeTab, getURI, getTabId, getSelectedTab } = require("../tabs/utils");
-const { windows, isBrowser, getMostRecentBrowserWindow } = require("../window/utils");
+lazyRequire(this, "../tabs/utils", "getTabs", "closeTab", "getURI", "getTabId", "getSelectedTab");
+lazyRequire(this, "../window/utils", "windows", "isBrowser", "getMostRecentBrowserWindow");
 const { defer, all, Debugging: PromiseDebugging, resolve } = require("../core/promise");
-const { getInnerId } = require("../window/utils");
+lazyRequire(this, "../window/utils", "getInnerId");
 const { cleanUI } = require("../test/utils");
 
 const findAndRunTests = function findAndRunTests(options) {
   var TestFinder = require("./unit-test-finder").TestFinder;
   var finder = new TestFinder({
     filter: options.filter,
     testInProcess: options.testInProcess,
     testOutOfProcess: options.testOutOfProcess
--- a/addon-sdk/source/lib/sdk/event/dom.js
+++ b/addon-sdk/source/lib/sdk/event/dom.js
@@ -5,17 +5,17 @@
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Ci } = require("chrome");
 
-var { emit } = require("./core");
+lazyRequire(this, "./core", "emit");
 var { when: unload } = require("../system/unload");
 var listeners = new WeakMap();
 
 const { Cu } = require("chrome");
 const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
 const { ThreadSafeChromeUtils } = Cu.import("resource://gre/modules/Services.jsm", {});
 
 var getWindowFrom = x =>
--- a/addon-sdk/source/lib/sdk/event/utils.js
+++ b/addon-sdk/source/lib/sdk/event/utils.js
@@ -2,17 +2,17 @@
  * 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";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-var { emit, on, once, off, EVENT_TYPE_PATTERN } = require("./core");
+lazyRequire(this, "./core", "emit", "on", "once", "off", "EVENT_TYPE_PATTERN");
 const { Cu } = require("chrome");
 
 // This module provides set of high order function for working with event
 // streams (streams in a NodeJS style that dispatch data, end and error
 // events).
 
 // Function takes a `target` object and returns set of implicit references
 // (non property references) it keeps. This basically allows defining
--- a/addon-sdk/source/lib/sdk/frame/hidden-frame.js
+++ b/addon-sdk/source/lib/sdk/frame/hidden-frame.js
@@ -7,23 +7,23 @@
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Cc, Ci } = require("chrome");
 const { Class } = require("../core/heritage");
 const { List, addListItem, removeListItem } = require("../util/list");
 const { EventTarget } = require("../event/target");
-const { emit } = require("../event/core");
-const { create: makeFrame } = require("./utils");
-const { defer } = require("../core/promise");
+lazyRequire(this, "../event/core", "emit");
+lazyRequire(this, "./utils", { "create": "makeFrame" });
+lazyRequire(this, "../core/promise", "defer");
 const { when: unload } = require("../system/unload");
-const { validateOptions, getTypeOf } = require("../deprecated/api-utils");
-const { window } = require("../addon/window");
-const { fromIterator } = require("../util/array");
+lazyRequire(this, "../deprecated/api-utils", "validateOptions", "getTypeOf");
+lazyRequire(this, "../addon/window", "window");
+lazyRequire(this, "../util/array", "fromIterator");
 
 // This cache is used to access friend properties between functions
 // without exposing them on the public API.
 var cache = new Set();
 var elements = new WeakMap();
 
 function contentLoaded(target) {
   var deferred = defer();
--- a/addon-sdk/source/lib/sdk/io/buffer.js
+++ b/addon-sdk/source/lib/sdk/io/buffer.js
@@ -13,18 +13,18 @@ module.metadata = {
  * utf-8, utf-16le, utf-16be
  * http://encoding.spec.whatwg.org/#interface-textencoder
  *
  * Node however supports the following encodings:
  * ascii, utf-8, utf-16le, usc2, base64, hex
  */
 
 const { Cu } = require('chrome');
-const { isNumber } = require('sdk/lang/type');
-const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
+lazyRequire(this, 'sdk/lang/type', "isNumber");
+Cu.importGlobalProperties(["TextEncoder", "TextDecoder"]);
 
 exports.TextEncoder = TextEncoder;
 exports.TextDecoder = TextDecoder;
 
 /**
  * Use WeakMaps to work around Bug 929146, which prevents us from adding
  * getters or values to typed arrays
  * https://bugzilla.mozilla.org/show_bug.cgi?id=929146
--- a/addon-sdk/source/lib/sdk/io/file.js
+++ b/addon-sdk/source/lib/sdk/io/file.js
@@ -4,18 +4,19 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "deprecated"
 };
 
 const {Cc,Ci,Cr} = require("chrome");
-const byteStreams = require("./byte-streams");
-const textStreams = require("./text-streams");
+
+lazyRequireModule(this, "./byte-streams", "byteStreams");
+lazyRequireModule(this, "./text-streams", "textStreams");
 
 // Flags passed when opening a file.  See nsprpub/pr/include/prio.h.
 const OPEN_FLAGS = {
   RDONLY: parseInt("0x01"),
   WRONLY: parseInt("0x02"),
   CREATE_FILE: parseInt("0x08"),
   APPEND: parseInt("0x10"),
   TRUNCATE: parseInt("0x20"),
--- a/addon-sdk/source/lib/sdk/io/fs.js
+++ b/addon-sdk/source/lib/sdk/io/fs.js
@@ -4,20 +4,21 @@
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Cc, Ci, CC } = require("chrome");
 
-const { setTimeout } = require("../timers");
-const { Stream, InputStream, OutputStream } = require("./stream");
-const { emit, on } = require("../event/core");
-const { Buffer } = require("./buffer");
+lazyRequire(this, "../timers", "setTimeout");
+lazyRequire(this, "./stream", "Stream", "InputStream", "OutputStream");
+lazyRequire(this, "../event/core", "emit", "on");
+lazyRequire(this, "./buffer", "Buffer");
+
 const { ns } = require("../core/namespace");
 const { Class } = require("../core/heritage");
 
 
 const nsILocalFile = CC("@mozilla.org/file/local;1", "nsILocalFile",
                         "initWithPath");
 const FileOutputStream = CC("@mozilla.org/network/file-output-stream;1",
                             "nsIFileOutputStream", "init");
--- a/addon-sdk/source/lib/sdk/io/stream.js
+++ b/addon-sdk/source/lib/sdk/io/stream.js
@@ -4,20 +4,21 @@
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { CC, Cc, Ci, Cu, Cr, components } = require("chrome");
 const { EventTarget } = require("../event/target");
-const { emit } = require("../event/core");
-const { Buffer } = require("./buffer");
 const { Class } = require("../core/heritage");
-const { setTimeout } = require("../timers");
+
+lazyRequire(this, "../event/core", "emit");
+lazyRequire(this, "./buffer", "Buffer");
+lazyRequire(this, "../timers", "setTimeout");
 
 
 const MultiplexInputStream = CC("@mozilla.org/io/multiplex-input-stream;1",
                                 "nsIMultiplexInputStream");
 const AsyncStreamCopier = CC("@mozilla.org/network/async-stream-copier;1",
                              "nsIAsyncStreamCopier", "init");
 const StringInputStream = CC("@mozilla.org/io/string-input-stream;1",
                              "nsIStringInputStream");
--- a/addon-sdk/source/lib/sdk/l10n.js
+++ b/addon-sdk/source/lib/sdk/l10n.js
@@ -2,24 +2,27 @@
  * 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";
 
 module.metadata = {
   "stability": "stable"
 };
 
-const json = require("./l10n/json/core");
-const { get: getKey } = require("./l10n/core");
-const properties = require("./l10n/properties/core");
-const { getRulesForLocale } = require("./l10n/plural-rules");
+lazyRequireModule(this, "./l10n/json/core", "json");
+lazyRequire(this, "./l10n/core", {"get": "getKey"});
+lazyRequireModule(this, "./l10n/properties/core", "properties");
+lazyRequire(this, "./l10n/plural-rules", "getRulesForLocale");
+
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 
 // Retrieve the plural mapping function
-var pluralMappingFunction = getRulesForLocale(json.language()) ||
-                            getRulesForLocale("en");
+XPCOMUtils.defineLazyGetter(this, "pluralMappingFunction",
+                            () => getRulesForLocale(json.language()) ||
+                                  getRulesForLocale("en"));
 
 exports.get = function get(k) {
   // For now, we only accept a "string" as first argument
   // TODO: handle plural forms in gettext pattern
   if (typeof k !== "string")
     throw new Error("First argument of localization method should be a string");
   let n = arguments[1];
 
--- a/addon-sdk/source/lib/sdk/l10n/core.js
+++ b/addon-sdk/source/lib/sdk/l10n/core.js
@@ -1,9 +1,15 @@
 /* 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";
 
-const json = require("./json/core");
-const properties = require("./properties/core");
+lazyRequireModule(this, "./json/core", "json");
+lazyRequireModule(this, "./properties/core", "properties");
 
-exports.get = json.usingJSON ? json.get : properties.get;
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyGetter(this, "get",
+                            () => json.usingJSON ? json.get : properties.get);
+
+module.exports = Object.freeze({
+  get get() { return get; }, // ... yeah.
+});
--- a/addon-sdk/source/lib/sdk/l10n/loader.js
+++ b/addon-sdk/source/lib/sdk/l10n/loader.js
@@ -3,19 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci } = require("chrome");
-const { getPreferedLocales, findClosestLocale } = require("./locale");
-const { readURI } = require("../net/url");
-const { resolve } = require("../core/promise");
+lazyRequire(this, "./locale", "getPreferedLocales", "findClosestLocale");
+lazyRequire(this, "../net/url", "readURI");
+lazyRequire(this, "../core/promise", "resolve");
 
 function parseJsonURI(uri) {
   return readURI(uri).
     then(JSON.parse).
     then(null, function (error) {
       throw Error("Failed to parse locale file:\n" + uri + "\n" + error);
     });
 }
--- a/addon-sdk/source/lib/sdk/l10n/prefs.js
+++ b/addon-sdk/source/lib/sdk/l10n/prefs.js
@@ -1,15 +1,15 @@
 /* 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";
 
-const { on } = require("../system/events");
-const core = require("./core");
+lazyRequire(this, "../system/events", "on");
+lazyRequireModule(this, "./core", "core");
 const { id: jetpackId } = require('../self');
 
 const OPTIONS_DISPLAYED = "addon-options-displayed";
 
 function enable() {
   on(OPTIONS_DISPLAYED, onOptionsDisplayed);  
 }
 exports.enable = enable;
--- a/addon-sdk/source/lib/sdk/l10n/properties/core.js
+++ b/addon-sdk/source/lib/sdk/l10n/properties/core.js
@@ -1,22 +1,24 @@
 /* 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";
 
 const { Cu } = require("chrome");
-const { newURI } = require('../../url/utils')
-const { getRulesForLocale } = require("../plural-rules");
-const { getPreferedLocales } = require('../locale');
+lazyRequire(this, '../../url/utils', 'newURI');
+lazyRequire(this, "../plural-rules", 'getRulesForLocale');
+lazyRequire(this, '../locale', 'getPreferedLocales');
 const { rootURI } = require("@loader/options");
-const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+const { Services } = require("resource://gre/modules/Services.jsm");
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 
 const baseURI = rootURI + "locale/";
-const preferedLocales = getPreferedLocales(true);
+
+XPCOMUtils.defineLazyGetter(this, "preferedLocales", () => getPreferedLocales(true));
 
 // Make sure we don't get stale data after an update
 // (See Bug 1300735 for rationale).
 Services.strings.flushBundles();
 
 function getLocaleURL(locale) {
   // if the locale is a valid chrome URI, return it
   try {
--- a/addon-sdk/source/lib/sdk/lang/functional/concurrent.js
+++ b/addon-sdk/source/lib/sdk/lang/functional/concurrent.js
@@ -8,17 +8,18 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { arity, name, derive, invoke } = require("./helpers");
-const { setTimeout, clearTimeout, setImmediate } = require("../../timers");
+
+lazyRequire(this, "sdk/timers", "setTimeout", "clearTimeout", "setImmediate");
 
 /**
  * Takes a function and returns a wrapped one instead, calling which will call
  * original function in the next turn of event loop. This is basically utility
  * to do `setImmediate(function() { ... })`, with a difference that returned
  * function is reused, instead of creating a new one each time. This also allows
  * to use this functions as event listeners.
  */
--- a/addon-sdk/source/lib/sdk/net/url.js
+++ b/addon-sdk/source/lib/sdk/net/url.js
@@ -5,18 +5,17 @@
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Ci, Cu, components } = require("chrome");
 
-const { defer } = require("../core/promise");
-const { merge } = require("../util/object");
+lazyRequire(this, "../core/promise", "defer");
 
 const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
 
 /**
  * Reads a URI and returns a promise.
  *
  * @param uri {string} The URI to read
--- a/addon-sdk/source/lib/sdk/page-mod.js
+++ b/addon-sdk/source/lib/sdk/page-mod.js
@@ -7,23 +7,23 @@ module.metadata = {
   "stability": "stable"
 };
 
 const { contract: loaderContract } = require('./content/loader');
 const { contract } = require('./util/contract');
 const { WorkerHost, connect } = require('./content/utils');
 const { Class } = require('./core/heritage');
 const { Disposable } = require('./core/disposable');
-const { Worker } = require('./content/worker');
+lazyRequire(this, './content/worker', "Worker");
 const { EventTarget } = require('./event/target');
-const { on, emit, once, setListeners } = require('./event/core');
-const { isRegExp, isUndefined } = require('./lang/type');
+lazyRequire(this, './event/core', "on", "emit", "once", "setListeners");
+lazyRequire(this, './lang/type', "isRegExp", "isUndefined");
 const { merge, omit } = require('./util/object');
-const { remove, has, hasAny } = require("./util/array");
-const { Rules } = require("./util/rules");
+lazyRequire(this, "./util/array", "remove", "has", "hasAny");
+lazyRequire(this, "./util/rules", "Rules");
 const { processes, frames, remoteRequire } = require('./remote/parent');
 remoteRequire('sdk/content/page-mod');
 
 const pagemods = new Map();
 const workers = new Map();
 const models = new WeakMap();
 var modelFor = (mod) => models.get(mod);
 var workerFor = (mod) => workers.get(mod)[0];
--- a/addon-sdk/source/lib/sdk/page-worker.js
+++ b/addon-sdk/source/lib/sdk/page-worker.js
@@ -4,29 +4,29 @@
 "use strict";
 
 module.metadata = {
   "stability": "stable"
 };
 
 const { Class } = require('./core/heritage');
 const { ns } = require('./core/namespace');
-const { pipe, stripListeners } = require('./event/utils');
+lazyRequire(this, './event/utils', "pipe", "stripListeners");
 const { connect, destroy, WorkerHost } = require('./content/utils');
-const { Worker } = require('./content/worker');
+lazyRequire(this, './content/worker', "Worker");
 const { Disposable } = require('./core/disposable');
 const { EventTarget } = require('./event/target');
-const { setListeners } = require('./event/core');
-const { window } = require('./addon/window');
-const { create: makeFrame, getDocShell } = require('./frame/utils');
+lazyRequire(this, './event/core', "setListeners");
+lazyRequire(this, './addon/window', "window");
+lazyRequire(this, './frame/utils', { "create": "makeFrame" }, "getDocShell");
 const { contract } = require('./util/contract');
 const { contract: loaderContract } = require('./content/loader');
-const { Rules } = require('./util/rules');
+lazyRequire(this, './util/rules', "Rules");
 const { merge } = require('./util/object');
-const { uuid } = require('./util/uuid');
+lazyRequire(this, './util/uuid', "uuid");
 const { useRemoteProcesses, remoteRequire, frames } = require("./remote/parent");
 remoteRequire("sdk/content/page-worker");
 
 const workers = new WeakMap();
 const pages = new Map();
 
 const internal = ns();
 
--- a/addon-sdk/source/lib/sdk/panel.js
+++ b/addon-sdk/source/lib/sdk/panel.js
@@ -9,38 +9,37 @@ module.metadata = {
   "stability": "stable",
   "engines": {
     "Firefox": "*",
     "SeaMonkey": "*"
   }
 };
 
 const { Cu, Ci } = require("chrome");
-const { setTimeout } = require('./timers');
+lazyRequire(this, './timers', "setTimeout");
 const { Class } = require("./core/heritage");
-const { merge } = require("./util/object");
+const { DefaultWeakMap, merge } = require("./util/object");
 const { WorkerHost } = require("./content/utils");
-const { Worker } = require("./deprecated/sync-worker");
+lazyRequire(this, "./deprecated/sync-worker", "Worker");
 const { Disposable } = require("./core/disposable");
 const { WeakReference } = require('./core/reference');
 const { contract: loaderContract } = require("./content/loader");
 const { contract } = require("./util/contract");
-const { on, off, emit, setListeners } = require("./event/core");
+lazyRequire(this, "./event/core", "on", "off", "emit", "setListeners");
 const { EventTarget } = require("./event/target");
-const domPanel = require("./panel/utils");
-const { getDocShell } = require('./frame/utils');
+lazyRequireModule(this, "./panel/utils", "domPanel");
+lazyRequire(this, './frame/utils', "getDocShell");
 const { events } = require("./panel/events");
-const systemEvents = require("./system/events");
 const { filter, pipe, stripListeners } = require("./event/utils");
-const { getNodeView, getActiveView } = require("./view/core");
-const { isNil, isObject, isNumber } = require("./lang/type");
-const { getAttachEventType } = require("./content/utils");
+lazyRequire(this, "./view/core", "getNodeView", "getActiveView");
+lazyRequire(this, "./lang/type", "isNil", "isObject", "isNumber");
+lazyRequire(this, "./content/utils", "getAttachEventType");
 const { number, boolean, object } = require('./deprecated/api-utils');
-const { Style } = require("./stylesheet/style");
-const { attach, detach } = require("./content/mod");
+lazyRequire(this, "./stylesheet/style", "Style");
+lazyRequire(this, "./content/mod", "attach", "detach");
 
 var isRect = ({top, right, bottom, left}) => [top, right, bottom, left].
   some(value => isNumber(value) && !isNaN(value));
 
 var isSDKObj = obj => obj instanceof Class;
 
 var rectContract = contract({
   top: number,
@@ -94,20 +93,46 @@ function setScriptState(panel, value) {
   getDocShell(view.viewFrame).allowJavascript = value;
   view.setAttribute("sdkscriptenabled", "" + value);
 }
 
 function isDisposed(panel) {
   return !views.has(panel);
 }
 
+var optionsMap = new WeakMap();
 var panels = new WeakMap();
 var models = new WeakMap();
-var views = new WeakMap();
-var workers = new WeakMap();
+var views = new DefaultWeakMap(panel => {
+  let model = models.get(panel);
+
+  // Setup view
+  let viewOptions = {allowJavascript: !model.allow || (model.allow.script !== false)};
+  let view = domPanel.make(null, viewOptions);
+  panels.set(view, panel);
+
+  // Load panel content.
+  domPanel.setURL(view, model.contentURL);
+
+  // Allow context menu
+  domPanel.allowContextMenu(view, model.contextMenu);
+
+  return view;
+});
+var workers = new DefaultWeakMap(panel => {
+  let options = optionsMap.get(panel);
+
+  let worker = new Worker(stripListeners(options));
+  workers.set(panel, worker);
+
+  // pipe events from worker to a panel.
+  pipe(worker, panel);
+
+  return worker;
+});
 var styles = new WeakMap();
 
 const viewFor = (panel) => views.get(panel);
 const modelFor = (panel) => models.get(panel);
 const panelFor = (view) => panels.get(view);
 const workerFor = (panel) => workers.get(panel);
 const styleFor = (panel) => styles.get(panel);
 
@@ -202,48 +227,32 @@ const Panel = Class({
 
     if (model.contentStyle || model.contentStyleFile) {
       styles.set(this, Style({
         uri: model.contentStyleFile,
         source: model.contentStyle
       }));
     }
 
-    // Setup view
-    let viewOptions = {allowJavascript: !model.allow || (model.allow.script !== false)};
-    let view = domPanel.make(null, viewOptions);
-    panels.set(view, this);
-    views.set(this, view);
-
-    // Load panel content.
-    domPanel.setURL(view, model.contentURL);
-
-    // Allow context menu
-    domPanel.allowContextMenu(view, model.contextMenu);
+    optionsMap.set(this, options);
 
     // Setup listeners.
     setListeners(this, options);
-    let worker = new Worker(stripListeners(options));
-    workers.set(this, worker);
-
-    // pipe events from worker to a panel.
-    pipe(worker, this);
   },
   dispose: function dispose() {
-    this.hide();
+    if (views.has(this))
+      this.hide();
     off(this);
 
     workerFor(this).destroy();
     detach(styleFor(this));
 
-    domPanel.dispose(viewFor(this));
+    if (views.has(this))
+      domPanel.dispose(viewFor(this));
 
-    // Release circular reference between view and panel instance. This
-    // way view will be GC-ed. And panel as well once all the other refs
-    // will be removed from it.
     views.delete(this);
   },
   /* Public API: Panel.width */
   get width() {
     return modelFor(this).width;
   },
   set width(value) {
     this.resize(value, this.height);
@@ -296,31 +305,31 @@ const Panel = Class({
 
   /* Public API: Panel.isShowing */
   get isShowing() {
     return !isDisposed(this) && domPanel.isOpen(viewFor(this));
   },
 
   /* Public API: Panel.show */
   show: function show(options={}, anchor) {
+    let view = viewFor(this);
     SinglePanelManager.requestOpen(this, () => {
       if (options instanceof Ci.nsIDOMElement) {
         [anchor, options] = [options, null];
       }
 
       if (anchor instanceof Ci.nsIDOMElement) {
         console.warn(
           "Passing a DOM node to Panel.show() method is an unsupported " +
           "feature that will be soon replaced. " +
           "See: https://bugzilla.mozilla.org/show_bug.cgi?id=878877"
         );
       }
 
       let model = modelFor(this);
-      let view = viewFor(this);
       let anchorView = getNodeView(anchor || options.position || model.position);
 
       options = merge({
         position: model.position,
         width: model.width,
         height: model.height,
         defaultWidth: model.defaultWidth,
         defaultHeight: model.defaultHeight,
--- a/addon-sdk/source/lib/sdk/panel/events.js
+++ b/addon-sdk/source/lib/sdk/panel/events.js
@@ -7,17 +7,17 @@
 // This module basically translates system/events to a SDK standard events
 // so that `map`, `filter` and other utilities could be used with them.
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const events = require("../system/events");
-const { emit } = require("../event/core");
+lazyRequire(this, "../event/core", "emit");
 
 var channel = {};
 
 function forward({ subject, type, data }) {
   return emit(channel, "data", { target: subject, type: type, data: data });
 }
 
 ["popupshowing", "popuphiding", "popupshown", "popuphidden",
--- a/addon-sdk/source/lib/sdk/panel/utils.js
+++ b/addon-sdk/source/lib/sdk/panel/utils.js
@@ -5,27 +5,27 @@
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci } = require("chrome");
 const { Services } = require("resource://gre/modules/Services.jsm");
-const { setTimeout } = require("../timers");
-const { platform } = require("../system");
-const { getMostRecentBrowserWindow, getOwnerBrowserWindow,
-        getScreenPixelsPerCSSPixel } = require("../window/utils");
+lazyRequire(this, "../timers", "setTimeout");
+lazyRequire(this, "../system", "platform");
+lazyRequire(this, "../window/utils", "getMostRecentBrowserWindow", "getOwnerBrowserWindow",
+            "getScreenPixelsPerCSSPixel");
 
-const { create: createFrame, swapFrameLoaders, getDocShell } = require("../frame/utils");
-const { window: addonWindow } = require("../addon/window");
-const { isNil } = require("../lang/type");
-const { data } = require('../self');
+lazyRequire(this, "../frame/utils", { "create": "createFrame" }, "swapFrameLoaders", "getDocShell");
+lazyRequire(this, "../addon/window", { "window": "addonWindow" });
+lazyRequire(this, "../lang/type", "isNil");
+lazyRequire(this, '../self', "data");
 
-const events = require("../system/events");
+lazyRequireModule(this, "../system/events", "events");
 
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 function calculateRegion({ position, width, height, defaultWidth, defaultHeight }, rect) {
   position = position || {};
 
   let x, y;
--- a/addon-sdk/source/lib/sdk/places/events.js
+++ b/addon-sdk/source/lib/sdk/places/events.js
@@ -124,19 +124,19 @@ historyObserver.onVisit = function(url, 
                                    visitCount, typed, lastKnownTitle) {
   // If this is the first visit we're adding, fire title-changed
   // in case anyone cares.
   if (visitCount == 1) {
     historyObserver.onTitleChanged(url, lastKnownTitle);
   }
   this.realOnVisit(url, visitId, time, sessionId, referringId, transitionType);
 };
-historyService.addObserver(historyObserver, false);
+historyService.addObserver(historyObserver);
 
 var bookmarkObserver = createObserverInstance(BOOKMARK_EVENTS, BOOKMARK_ARGS);
-bookmarkService.addObserver(bookmarkObserver, false);
+bookmarkService.addObserver(bookmarkObserver);
 
 when(() => {
   historyService.removeObserver(historyObserver);
   bookmarkService.removeObserver(bookmarkObserver);
 });
 
 exports.events = emitter;
--- a/addon-sdk/source/lib/sdk/platform/xpcom.js
+++ b/addon-sdk/source/lib/sdk/platform/xpcom.js
@@ -7,19 +7,19 @@
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, Cr, Cm, components: { classesByID } } = require('chrome');
 const { registerFactory, unregisterFactory, isCIDRegistered } =
       Cm.QueryInterface(Ci.nsIComponentRegistrar);
 
-const { merge } = require('../util/object');
 const { Class, extend, mix } = require('../core/heritage');
-const { uuid } = require('../util/uuid');
+lazyRequire(this, '../util/object', 'merge');
+lazyRequire(this, '../util/uuid', 'uuid');
 
 // This is a base prototype, that provides bare bones of XPCOM. JS based
 // components can be easily implement by extending it.
 const Unknown = new function() {
   function hasInterface(component, iid) {
     return component && component.interfaces &&
       ( component.interfaces.some(id => iid.equals(Ci[id])) ||
         component.implements.some($ => hasInterface($, iid)) ||
--- a/addon-sdk/source/lib/sdk/preferences/event-target.js
+++ b/addon-sdk/source/lib/sdk/preferences/event-target.js
@@ -29,17 +29,17 @@ const PrefsTarget = Class({
         QueryInterface(Ci.nsIPrefBranch2);
     prefTargetNS(this).branch = branch;
 
     // provides easy access to preference values
     this.prefs = Branch(branchName);
 
     // start listening to preference changes
     let observer = prefTargetNS(this).observer = onChange.bind(this);
-    branch.addObserver('', observer, false);
+    branch.addObserver('', observer);
 
     // Make sure to destroy this on unload
     unload(destroy.bind(this));
   }
 });
 exports.PrefsTarget = PrefsTarget;
 
 /* HELPERS */
--- a/addon-sdk/source/lib/sdk/preferences/native-options.js
+++ b/addon-sdk/source/lib/sdk/preferences/native-options.js
@@ -3,74 +3,73 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, Cu } = require('chrome');
-const { on } = require('../system/events');
-const { id, preferencesBranch } = require('../self');
-const { localizeInlineOptions } = require('../l10n/prefs');
-const { Services } = require("resource://gre/modules/Services.jsm");
-const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
-const { defer } = require("sdk/core/promise");
+lazyRequire(this, '../system/events', "on");
+lazyRequire(this, '../self', "preferencesBranch");
+lazyRequire(this, '../l10n/prefs', "localizeInlineOptions");
+
+lazyRequire(this, "resource://gre/modules/Services.jsm", "Services");
+lazyRequire(this, "resource://gre/modules/AddonManager.jsm", "AddonManager");
+lazyRequire(this, "resource://gre/modules/Preferences.jsm", "Preferences");
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";;
 const DEFAULT_OPTIONS_URL = 'data:text/xml,<placeholder/>';
 
 const VALID_PREF_TYPES = ['bool', 'boolint', 'integer', 'string', 'color',
                           'file', 'directory', 'control', 'menulist', 'radio'];
 
 const isFennec = require("sdk/system/xul-app").is("Fennec");
 
 function enable({ preferences, id }) {
-  let enabled = defer();
+  return new Promise(resolve => {
+    validate(preferences);
 
-  validate(preferences);
-
-  setDefaults(preferences, preferencesBranch);
+    setDefaults(preferences, preferencesBranch);
 
-  // allow the use of custom options.xul
-  AddonManager.getAddonByID(id, (addon) => {
-    on('addon-options-displayed', onAddonOptionsDisplayed, true);
-    enabled.resolve({ id: id });
-  });
+    // allow the use of custom options.xul
+    AddonManager.getAddonByID(id, (addon) => {
+      on('addon-options-displayed', onAddonOptionsDisplayed, true);
+      resolve({ id });
+    });
 
-  function onAddonOptionsDisplayed({ subject: doc, data }) {
-    if (data === id) {
-      let parent;
+    function onAddonOptionsDisplayed({ subject: doc, data }) {
+      if (data === id) {
+        let parent;
 
-      if (isFennec) {
-        parent = doc.querySelector('.options-box');
+        if (isFennec) {
+          parent = doc.querySelector('.options-box');
 
-        // NOTE: This disable the CSS rule that makes the options invisible
-        let item = doc.querySelector('#addons-details .addon-item');
-        item.removeAttribute("optionsURL");
-      } else {
-        parent = doc.getElementById('detail-downloads').parentNode;
-      }
+          // NOTE: This disable the CSS rule that makes the options invisible
+          let item = doc.querySelector('#addons-details .addon-item');
+          item.removeAttribute("optionsURL");
+        } else {
+          parent = doc.getElementById('detail-downloads').parentNode;
+        }
 
-      if (parent) {
-        injectOptions({
-          preferences: preferences,
-          preferencesBranch: preferencesBranch,
-          document: doc,
-          parent: parent,
-          id: id
-        });
-        localizeInlineOptions(doc);
-      } else {
-        throw Error("Preferences parent node not found in Addon Details. The configured custom preferences will not be visible.");
+        if (parent) {
+          injectOptions({
+            preferences: preferences,
+            preferencesBranch: preferencesBranch,
+            document: doc,
+            parent: parent,
+            id: id
+          });
+          localizeInlineOptions(doc);
+        } else {
+          throw Error("Preferences parent node not found in Addon Details. The configured custom preferences will not be visible.");
+        }
       }
     }
-  }
-
-  return enabled.promise;
+  });
 }
 exports.enable = enable;
 
 // centralized sanity checks
 function validate(preferences) {
   for (let { name, title, type, label, options } of preferences) {
     // make sure the title is set and non-empty
     if (!title)
@@ -98,38 +97,24 @@ function validate(preferences) {
 
     // TODO: check that pref type matches default value type
   }
 }
 exports.validate = validate;
 
 // initializes default preferences, emulates defaults/prefs.js
 function setDefaults(preferences, preferencesBranch) {
-  const branch = Cc['@mozilla.org/preferences-service;1'].
-                 getService(Ci.nsIPrefService).
-                 getDefaultBranch('extensions.' + preferencesBranch + '.');
-  for (let { name, value } of preferences) {
-    switch (typeof value) {
-      case 'boolean':
-        branch.setBoolPref(name, value);
-        break;
-      case 'number':
-        // must be integer, ignore otherwise
-        if (value % 1 === 0) {
-          branch.setIntPref(name, value);
-        }
-        break;
-      case 'string':
-        let str = Cc["@mozilla.org/supports-string;1"].
-                  createInstance(Ci.nsISupportsString);
-        str.data = value;
-        branch.setComplexValue(name, Ci.nsISupportsString, str);
-        break;
-    }
-  }
+  let prefs = new Preferences({
+    branch: `extensions.${preferencesBranch}.`,
+    defaultBranch: true,
+  });
+
+  for (let { name, value } of preferences)
+    if (value !== undefined)
+      prefs.set(name, value);
 }
 exports.setDefaults = setDefaults;
 
 // dynamically injects inline options into about:addons page at runtime
 // NOTE: on Firefox Desktop the about:addons page is a xul page document,
 // on Firefox for Android the about:addons page is an xhtml page, to support both
 // the XUL xml namespace have to be enforced.
 function injectOptions({ preferences, preferencesBranch, document, parent, id }) {
--- a/addon-sdk/source/lib/sdk/private-browsing/utils.js
+++ b/addon-sdk/source/lib/sdk/private-browsing/utils.js
@@ -4,20 +4,21 @@
 'use strict';
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, Cu } = require('chrome');
 const { is } = require('../system/xul-app');
-const { isWindowPrivate } = require('../window/utils');
-const { isPrivateBrowsingSupported } = require('../self');
 const { dispatcher } = require("../util/dispatcher");
 
+lazyRequire(this, '../window/utils', "isWindowPrivate");
+lazyRequire(this, '../self', "isPrivateBrowsingSupported");
+
 var PrivateBrowsingUtils;
 
 // Private browsing is only supported in Fx
 try {
   PrivateBrowsingUtils = Cu.import('resource://gre/modules/PrivateBrowsingUtils.jsm', {}).PrivateBrowsingUtils;
 }
 catch (e) {}
 
--- a/addon-sdk/source/lib/sdk/remote/parent.js
+++ b/addon-sdk/source/lib/sdk/remote/parent.js
@@ -22,35 +22,32 @@ const { Disposable } = require('../core/
 const { omit } = require('../util/object');
 const { when } = require('../system/unload');
 const { EventTarget } = require('../event/target');
 const { emit } = require('../event/core');
 const system = require('../system/events');
 const { EventParent } = require('./utils');
 const options = require('@loader/options');
 const loaderModule = require('toolkit/loader');
-const { getTabForBrowser } = require('../tabs/utils');
+
+lazyRequire(this, '../tabs/utils', "getTabForBrowser");
 
 const appInfo = Cc["@mozilla.org/xre/app-info;1"].
                 getService(Ci.nsIXULRuntime);
 
 exports.useRemoteProcesses = appInfo.browserTabsRemoteAutostart;
 
 // Chose the right function for resolving relative a module id
 var moduleResolve;
 if (options.isNative) {
   moduleResolve = (id, requirer) => loaderModule.nodeResolve(id, requirer, { rootURI: options.rootURI });
 }
 else {
   moduleResolve = loaderModule.resolve;
 }
-// Build the sorted path mapping structure that resolveURI requires
-var pathMapping = Object.keys(options.paths)
-                        .sort((a, b) => b.length - a.length)
-                        .map(p => [p, options.paths[p]]);
 
 // Load the scripts in the child processes
 var { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm');
 var PATH = options.paths[''];
 
 const childOptions = omit(options, ['modules', 'globals', 'resolve', 'load']);
 childOptions.modules = {};
 // @l10n/data is just JSON data and can be safely sent across to the child loader
@@ -321,18 +318,17 @@ var remoteModules = new Set();
 
 // Ensures a module is loaded in every child process. It is safe to send 
 // messages to this module immediately after calling this.
 // Pass a module to resolve the id relatively.
 function remoteRequire(id, module = null) {
   // Resolve relative to calling module if passed
   if (module)
     id = moduleResolve(id, module.id);
-  let uri = loaderModule.resolveURI(id, pathMapping);
 
   // Don't reload the same module
-  if (remoteModules.has(uri))
+  if (remoteModules.has(id))
     return;
 
-  remoteModules.add(uri);
-  processes.port.emit('sdk/remote/require', uri);
+  remoteModules.add(id);
+  processes.port.emit('sdk/remote/require', id);
 }
 exports.remoteRequire = remoteRequire;
--- a/addon-sdk/source/lib/sdk/remote/utils.js
+++ b/addon-sdk/source/lib/sdk/remote/utils.js
@@ -1,17 +1,17 @@
 /* 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";
 
 const { Class } = require('../core/heritage');
 const { List, addListItem, removeListItem } = require('../util/list');
-const { emit } = require('../event/core');
-const { pipe } = require('../event/utils');
+lazyRequire(this, '../event/core', 'emit');
+lazyRequire(this, '../event/utils', 'pipe');
 
 // A helper class that maintains a list of EventTargets. Any events emitted
 // to an EventTarget are also emitted by the EventParent. Likewise for an
 // EventTarget's port property.
 const EventParent = Class({
   implements: [ List ],
 
   attachItem: function(item) {
--- a/addon-sdk/source/lib/sdk/selection.js
+++ b/addon-sdk/source/lib/sdk/selection.js
@@ -7,28 +7,27 @@
 module.metadata = {
   "stability": "stable",
   "engines": {
     "Firefox": "*",
     "SeaMonkey": "*"
   }
 };
 
-const { Ci, Cc } = require("chrome"),
-    { setTimeout } = require("./timers"),
-    { emit, off } = require("./event/core"),
-    { Class, obscure } = require("./core/heritage"),
-    { EventTarget } = require("./event/target"),
-    { ns } = require("./core/namespace"),
-    { when: unload } = require("./system/unload"),
-    { ignoreWindow } = require('./private-browsing/utils'),
-    { getTabs, getTabForContentWindow,
-      getAllTabContentWindows } = require('./tabs/utils'),
-    winUtils = require("./window/utils"),
-    events = require("./system/events");
+const { Ci, Cc } = require("chrome");
+lazyRequire(this, "./timers", "setTimeout");
+lazyRequire(this, "./event/core", "emit", "off");
+const { Class, obscure } = require("./core/heritage");
+const { EventTarget } = require("./event/target");
+const { ns } = require("./core/namespace");
+const { when: unload } = require("./system/unload");
+lazyRequire(this, './private-browsing/utils', "ignoreWindow");
+lazyRequire(this, './tabs/utils', "getTabs", "getTabForContentWindow", "getAllTabContentWindows");
+lazyRequireModule(this, "./window/utils", "winUtils");
+const events = require("./system/events");
 
 // The selection types
 const HTML = 0x01,
       TEXT = 0x02,
       DOM  = 0x03; // internal use only
 
 // A more developer-friendly message than the caught exception when is not
 // possible change a selection.
--- a/addon-sdk/source/lib/sdk/self.js
+++ b/addon-sdk/source/lib/sdk/self.js
@@ -6,17 +6,17 @@
 module.metadata = {
   "stability": "stable"
 };
 
 const { CC } = require('chrome');
 const options = require('@loader/options');
 
 const { get } = require("./preferences/service");
-const { readURISync } = require('./net/url');
+lazyRequire(this, './net/url', "readURISync");
 
 const id = options.id;
 
 const readPref = key => get("extensions." + id + ".sdk." + key);
 
 const name = readPref("name") || options.name;
 const version = readPref("version") || options.version;
 const loadReason = readPref("load.reason") || options.loadReason;
--- a/addon-sdk/source/lib/sdk/simple-storage.js
+++ b/addon-sdk/source/lib/sdk/simple-storage.js
@@ -4,22 +4,22 @@
 
 "use strict";
 
 module.metadata = {
   "stability": "stable"
 };
 
 const { Cc, Ci } = require("chrome");
-const file = require("./io/file");
-const prefs = require("./preferences/service");
 const jpSelf = require("./self");
-const timer = require("./timers");
+lazyRequireModule(this, "./timers", "timer");
+lazyRequireModule(this, "./io/file", "file");
+lazyRequireModule(this, "./preferences/service", "prefs");
 const unload = require("./system/unload");
-const { emit, on, off } = require("./event/core");
+lazyRequire(this, "./event/core", "emit", "on", "off");
 
 const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
 const WRITE_PERIOD_DEFAULT = 300000; // 5 minutes
 
 const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
 const QUOTA_DEFAULT = 5242880; // 5 MiB
 
 const JETPACK_DIR_BASENAME = "jetpack";
--- a/addon-sdk/source/lib/sdk/stylesheet/style.js
+++ b/addon-sdk/source/lib/sdk/stylesheet/style.js
@@ -2,24 +2,22 @@
  * 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";
 
 module.metadata = {
   "stability": "experimental"
 };
 
-const { Cc, Ci } = require("chrome");
 const { Class } = require("../core/heritage");
-const { URL, isLocalURL } = require('../url');
-const events = require("../system/events");
-const { loadSheet, removeSheet, isTypeValid } = require("./utils");
-const { isString } = require("../lang/type");
+lazyRequire(this, "../url", "isLocalURL");
+lazyRequire(this, "./utils", "loadSheet", "removeSheet", "isTypeValid");
+lazyRequire(this, "../lang/type", "isString");
 const { attachTo, detachFrom } = require("../content/mod");
-const { data } = require('../self');
+lazyRequire(this, '../self', "data");
 
 const { freeze, create } = Object;
 
 function Style({ source, uri, type }) {
   source = source == null ? null : freeze([].concat(source));
   uri = uri == null ? null : freeze([].concat(uri));
   type = type == null ? "author" : type;
 
--- a/addon-sdk/source/lib/sdk/system.js
+++ b/addon-sdk/source/lib/sdk/system.js
@@ -7,40 +7,43 @@ module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, CC } = require('chrome');
 const options = require('@loader/options');
 const runtime = require("./system/runtime");
 const { when: unload } = require("./system/unload");
 
-const appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
-                   getService(Ci.nsIAppStartup);
+const { XPCOMUtils } = require('resource://gre/modules/XPCOMUtils.jsm');
+
+XPCOMUtils.defineLazyServiceGetter(this, 'appStartup',
+                                   '@mozilla.org/toolkit/app-startup;1',
+                                   'nsIAppStartup');
+XPCOMUtils.defineLazyServiceGetter(this, 'directoryService',
+                                   '@mozilla.org/file/directory_service;1',
+                                   'nsIProperties');
+
 const appInfo = Cc["@mozilla.org/xre/app-info;1"].
                 getService(Ci.nsIXULAppInfo);
-const directoryService = Cc['@mozilla.org/file/directory_service;1'].
-                         getService(Ci.nsIProperties);
 
 const PR_WRONLY = parseInt("0x02");
 const PR_CREATE_FILE = parseInt("0x08");
 const PR_APPEND = parseInt("0x10");
 const PR_TRUNCATE = parseInt("0x20");
 
 function openFile(path, mode) {
   let file = Cc["@mozilla.org/file/local;1"].
              createInstance(Ci.nsILocalFile);
   file.initWithPath(path);
   let stream = Cc["@mozilla.org/network/file-output-stream;1"].
                createInstance(Ci.nsIFileOutputStream);
   stream.init(file, mode, -1, 0);
   return stream
 }
 
-const { eAttemptQuit: E_ATTEMPT, eForceQuit: E_FORCE } = appStartup;
-
 /**
  * Parsed JSON object that was passed via `cfx --static-args "{ foo: 'bar' }"`
  */
 exports.staticArgs = options.staticArgs;
 
 /**
  * Environment variables. Environment variables are non-enumerable properties
  * of this object (key is name and value is value).
@@ -81,17 +84,17 @@ exports.exit = function exit(code) {
   }
 
   // Bug 856999: Prevent automatic kill of Firefox when running tests
   if (options.noQuit) {
     return unload(unloader);
   }
 
   unloader();
-  appStartup.quit(code ? E_ATTEMPT : E_FORCE);
+  appStartup.quit(code ? appStartup.eAttemptQuit : appStartup.eForceQuit);
 };
 
 // Adapter for nodejs's stdout & stderr:
 // http://nodejs.org/api/process.html#process_process_stdout
 var stdout = Object.freeze({ write: dump, end: dump });
 exports.stdout = stdout;
 exports.stderr = stdout;
 
--- a/addon-sdk/source/lib/sdk/system/events.js
+++ b/addon-sdk/source/lib/sdk/system/events.js
@@ -158,24 +158,26 @@ var stillAlive = new Map();
 var wasShimmed = new Map();
 
 on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
   // using logic from ./unload, to avoid a circular module reference
   if (subject.wrappedJSObject === unloadSubject) {
     off('sdk:loader:destroy', onunload, false);
 
     // don't bother
-    if (reason === 'shutdown') 
+    if (reason === 'shutdown')
       return;
 
-    stillAlive.forEach( (type, ref) => {
-      let observer = ref.get();
-      if (observer) {
-        if (wasShimmed.get(ref)) {
-          removeObserver(observer, type);
-        } else {
-          removeObserverNoShim(observer, type);
+    // Wait until the next tick to let other shutdown handlers finish first.
+    Promise.resolve().then(() => {
+      stillAlive.forEach((type, ref) => {
+        let observer = ref.get();
+        if (observer) {
+          if (wasShimmed.get(ref)) {
+            removeObserver(observer, type);
+          } else {
+            removeObserverNoShim(observer, type);
+          }
         }
-      }
-    })
+      });
+    });
   }
-  // a strong reference
 }, true, false);
--- a/addon-sdk/source/lib/sdk/system/globals.js
+++ b/addon-sdk/source/lib/sdk/system/globals.js
@@ -3,44 +3,47 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-var { Cc, Ci, CC } = require('chrome');
-var { PlainTextConsole } = require('../console/plain-text');
-var { stdout } = require('../system');
-var ScriptError = CC('@mozilla.org/scripterror;1', 'nsIScriptError');
-var consoleService = Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService);
+defineLazyGetter(this, "console", () => new (require('../console/plain-text').PlainTextConsole)());
 
-// On windows dump does not writes into stdout so cfx can't read thous dumps.
-// To workaround this issue we write to a special file from which cfx will
-// read and print to the console.
-// For more details see: bug-673383
-exports.dump = stdout.write;
+exports = module.exports = {};
 
-exports.console = new PlainTextConsole();
+defineLazyGetter(exports, "console", () => console);
 
 // Provide CommonJS `define` to allow authoring modules in a format that can be
 // loaded both into jetpack and into browser via AMD loaders.
-Object.defineProperty(exports, 'define', {
-  // `define` is provided as a lazy getter that binds below defined `define`
-  // function to the module scope, so that require, exports and module
-  // variables remain accessible.
-  configurable: true,
-  get: function() {
-    let sandbox = this;
-    return function define(factory) {
-      factory = Array.slice(arguments).pop();
-      factory.call(sandbox, sandbox.require, sandbox.exports, sandbox.module);
-    }
-  },
-  set: function(value) {
-    Object.defineProperty(this, 'define', {
+
+// `define` is provided as a lazy getter that binds below defined `define`
+// function to the module scope, so that require, exports and module
+// variables remain accessible.
+defineLazyGetter(exports, 'define', function() {
+  return (...args) => {
+    let factory = args.pop();
+    factory.call(this, this.require, this.exports, this.module);
+  };
+});
+
+function defineLazyGetter(object, prop, getter) {
+  let redefine = (obj, value) => {
+    Object.defineProperty(obj, prop, {
       configurable: true,
-      enumerable: true,
+      writable: true,
       value,
     });
-  },
-});
+    return value;
+  };
+
+  Object.defineProperty(object, prop, {
+    configurable: true,
+    get() {
+      return redefine(this, getter.call(this));
+    },
+    set(value) {
+      redefine(this, value);
+    }
+  });
+}
--- a/addon-sdk/source/lib/sdk/tabs/helpers.js
+++ b/addon-sdk/source/lib/sdk/tabs/helpers.js
@@ -6,17 +6,17 @@
 module.metadata = {
   'stability': 'unstable'
 };
 
 
 // NOTE: This file should only export Tab instances
 
 
-const { getTabForBrowser: getRawTabForBrowser } = require('./utils');
+lazyRequire(this, './utils', { "getTabForBrowser": "getRawTabForBrowser" });
 const { modelFor } = require('../model/core');
 
 exports.getTabForRawTab = modelFor;
 
 function getTabForBrowser(browser) {
   return modelFor(getRawTabForBrowser(browser)) || null;
 }
 exports.getTabForBrowser = getTabForBrowser;
--- a/addon-sdk/source/lib/sdk/tabs/tab.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   'stability': 'unstable'
 };
 
 const { getTargetWindow } = require("../content/mod");
-const { getTabContentWindow, isTab } = require("./utils");
-const { viewFor } = require("../view/core");
+lazyRequire(this, "./utils", "getTabContentWindow", "isTab");
+lazyRequire(this, "../view/core", "viewFor");
 
 if (require('../system/xul-app').name == 'Fennec') {
   module.exports = require('./tab-fennec');
 }
 else {
   module.exports = require('./tab-firefox');
 }
 
--- a/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tabs-firefox.js
@@ -1,27 +1,27 @@
 /* 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";
 
 const { Class } = require('../core/heritage');
 const { Tab, tabEvents } = require('./tab');
 const { EventTarget } = require('../event/target');
-const { emit, setListeners } = require('../event/core');
+lazyRequire(this, '../event/core', "emit", "setListeners");
 const { pipe } = require('../event/utils');
 const { observer: windowObserver } = require('../windows/observer');
 const { List, addListItem, removeListItem } = require('../util/list');
-const { modelFor } = require('../model/core');
-const { viewFor } = require('../view/core');
-const { getTabs, getSelectedTab } = require('./utils');
-const { getMostRecentBrowserWindow, isBrowser } = require('../window/utils');
-const { Options } = require('./common');
-const { isPrivate } = require('../private-browsing');
-const { ignoreWindow, isWindowPBSupported } = require('../private-browsing/utils')
+lazyRequire(this, '../model/core', "modelFor");
+lazyRequire(this, '../view/core', "viewFor");
+lazyRequire(this, './utils', "getTabs", "getSelectedTab");
+lazyRequire(this, '../window/utils', "getMostRecentBrowserWindow", "isBrowser");
+lazyRequire(this, './common', "Options");
+lazyRequire(this, '../private-browsing', "isPrivate");
+lazyRequire(this, '../private-browsing/utils', "ignoreWindow", "isWindowPBSupported")
 const { isPrivateBrowsingSupported } = require('sdk/self');
 
 const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
 
 const Tabs = Class({
   implements: [EventTarget],
   extends: List,
   initialize: function() {
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ b/addon-sdk/source/lib/sdk/tabs/utils.js
@@ -7,19 +7,19 @@ module.metadata = {
   'stability': 'unstable'
 };
 
 
 // NOTE: This file should only deal with xul/native tabs
 
 
 const { Ci, Cu } = require('chrome');
-const { defer } = require("../lang/functional");
-const { windows, isBrowser } = require('../window/utils');
-const { isPrivateBrowsingSupported } = require('../self');
+lazyRequire(this, "../lang/functional", "defer");
+lazyRequire(this, '../window/utils', "windows", "isBrowser");
+lazyRequire(this, '../self', "isPrivateBrowsingSupported");
 const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
 
 // Bug 834961: ignore private windows when they are not supported
 function getWindows() {
   return windows(null, { includePrivate: isPrivateBrowsingSupported });
 }
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
--- a/addon-sdk/source/lib/sdk/test/harness.js
+++ b/addon-sdk/source/lib/sdk/test/harness.js
@@ -8,17 +8,17 @@ module.metadata = {
 };
 
 const { Cc, Ci, Cu } = require("chrome");
 const { Loader } = require('./loader');
 const { serializeStack, parseStack  } = require("toolkit/loader");
 const { setTimeout } = require('../timers');
 const { PlainTextConsole } = require("../console/plain-text");
 const { when: unload } = require("../system/unload");
-const { format, fromException }  = require("../console/traceback");
+lazyRequire(this, "../console/traceback", "format", "fromException");
 const system = require("../system");
 const { gc: gcPromise } = require('./memory');
 const { defer } = require('../core/promise');
 const { extend } = require('../core/heritage');
 
 // Trick manifest builder to make it think we need these modules ?
 const unit = require("../deprecated/unit-test");
 const test = require("../../test");
--- a/addon-sdk/source/lib/sdk/test/utils.js
+++ b/addon-sdk/source/lib/sdk/test/utils.js
@@ -2,23 +2,23 @@
  * 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';
 
 module.metadata = {
   'stability': 'unstable'
 };
 
-const { defer } = require('../core/promise');
-const { setInterval, clearInterval } = require('../timers');
-const { getTabs, closeTab } = require("../tabs/utils");
-const { windows: getWindows } = require("../window/utils");
-const { close: closeWindow } = require("../window/helpers");
-const { isGenerator } = require("../lang/type");
-const { env } = require("../system/environment");
+lazyRequire(this, '../core/promise', "defer");
+lazyRequire(this, '../timers', "setInterval", "clearInterval");
+lazyRequire(this, "../tabs/utils", "getTabs", "closeTab");
+lazyRequire(this, "../window/utils", {"windows": "getWindows"});
+lazyRequire(this, "../window/helpers", {"close": "closeWindow"});
+lazyRequire(this, "../lang/type", "isGenerator");
+lazyRequire(this, "../system/environment", "env");
 const { Task } = require("resource://gre/modules/Task.jsm");
 
 const getTestNames = (exports) =>
   Object.keys(exports).filter(name => /^test/.test(name));
 
 const isTestAsync = ({length}) => length > 1;
 const isHelperAsync = ({length}) => length > 2;
 
--- a/addon-sdk/source/lib/sdk/timers.js
+++ b/addon-sdk/source/lib/sdk/timers.js
@@ -75,18 +75,17 @@ var dispatcher = _ => {
 
 function setImmediate(callback, ...params) {
   let id = ++ lastID;
   // register new immediate timer with curried params.
   immediates.set(id, _ => callback.apply(callback, params));
   // if dispatch loop is not scheduled schedule one. Own scheduler
   if (!dispatcher.scheduled) {
     dispatcher.scheduled = true;
-    threadManager.currentThread.dispatch(dispatcher,
-                                         Ci.nsIThread.DISPATCH_NORMAL);
+    threadManager.dispatchToMainThread(dispatcher);
   }
   return id;
 }
 
 function clearImmediate(id) {
   immediates.delete(id);
 }
 
--- a/addon-sdk/source/lib/sdk/ui.js
+++ b/addon-sdk/source/lib/sdk/ui.js
@@ -5,13 +5,21 @@
 
 module.metadata = {
   'stability': 'experimental',
   'engines': {
     'Firefox': '> 28'
   }
 };
 
-exports.ActionButton = require('./ui/button/action').ActionButton;
-exports.ToggleButton = require('./ui/button/toggle').ToggleButton;
-exports.Sidebar = require('./ui/sidebar').Sidebar;
-exports.Frame = require('./ui/frame').Frame;
-exports.Toolbar = require('./ui/toolbar').Toolbar;
+lazyRequire(this, './ui/button/action', 'ActionButton');
+lazyRequire(this, './ui/button/toggle', 'ToggleButton');
+lazyRequire(this, './ui/sidebar', 'Sidebar');
+lazyRequire(this, './ui/frame', 'Frame');
+lazyRequire(this, './ui/toolbar', 'Toolbar');
+
+module.exports = Object.freeze({
+  get ActionButton() { return ActionButton; },
+  get ToggleButton() { return ToggleButton; },
+  get Sidebar() { return Sidebar; },
+  get Frame() { return Frame; },
+  get Toolbar() { return Toolbar; },
+});
--- a/addon-sdk/source/lib/sdk/ui/button/action.js
+++ b/addon-sdk/source/lib/sdk/ui/button/action.js
@@ -8,32 +8,32 @@ module.metadata = {
   'engines': {
     'Firefox': '> 28'
   }
 };
 
 const { Class } = require('../../core/heritage');
 const { merge } = require('../../util/object');
 const { Disposable } = require('../../core/disposable');
-const { on, off, emit, setListeners } = require('../../event/core');
+lazyRequire(this, '../../event/core', "on", "off", "emit", "setListeners");
 const { EventTarget } = require('../../event/target');
-const { getNodeView } = require('../../view/core');
+lazyRequire(this, '../../view/core', "getNodeView");
 
-const view = require('./view');
+lazyRequireModule(this, './view', "view");
 const { buttonContract, stateContract } = require('./contract');
-const { properties, render, state, register, unregister,
-        getDerivedStateFor } = require('../state');
-const { events: stateEvents } = require('../state/events');
-const { events: viewEvents } = require('./view/events');
-const events = require('../../event/utils');
+lazyRequire(this, '../state', "properties", "render", "state", "register",
+            "unregister", "getDerivedStateFor");
+lazyRequire(this, '../state/events', { "events": "stateEvents" });
+lazyRequire(this, './view/events', { "events": "viewEvents" });
+lazyRequireModule(this, '../../event/utils', "events");
 
-const { getActiveTab } = require('../../tabs/utils');
+lazyRequire(this, '../../tabs/utils', "getActiveTab");
 
-const { id: addonID } = require('../../self');
-const { identify } = require('../id');
+lazyRequire(this, '../../self', { "id": "addonID" });
+lazyRequire(this, '../id', "identify");
 
 const buttons = new Map();
 
 const toWidgetId = id =>
   ('action-button--' + addonID.toLowerCase()+ '-' + id).
     replace(/[^a-z0-9_-]/g, '');
 
 const ActionButton = Class({
--- a/addon-sdk/source/lib/sdk/ui/button/contract.js
+++ b/addon-sdk/source/lib/sdk/ui/button/contract.js
@@ -1,16 +1,16 @@
 /* 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';
 
 const { contract } = require('../../util/contract');
-const { isLocalURL } = require('../../url');
-const { isNil, isObject, isString } = require('../../lang/type');
+lazyRequire(this, '../../url', "isLocalURL");
+lazyRequire(this, '../../lang/type', "isNil", "isObject", "isString");
 const { required, either, string, boolean, object, number } = require('../../deprecated/api-utils');
 const { merge } = require('../../util/object');
 const { freeze } = Object;
 
 const isIconSet = (icons) =>
   Object.keys(icons).
     every(size => String(size >>> 0) === size && isLocalURL(icons[size]));
 
--- a/addon-sdk/source/lib/sdk/ui/button/toggle.js
+++ b/addon-sdk/source/lib/sdk/ui/button/toggle.js
@@ -6,34 +6,34 @@
 module.metadata = {
   'stability': 'experimental',
   'engines': {
     'Firefox': '> 28'
   }
 };
 
 const { Class } = require('../../core/heritage');
-const { merge } = require('../../util/object');
+lazyRequire(this, '../../util/object', "merge");
 const { Disposable } = require('../../core/disposable');
-const { on, off, emit, setListeners } = require('../../event/core');
+lazyRequire(this, '../../event/core', "on", "off", "emit", "setListeners");
 const { EventTarget } = require('../../event/target');
-const { getNodeView } = require('../../view/core');
+lazyRequire(this, '../../view/core', "getNodeView");
 
-const view = require('./view');
+lazyRequireModule(this, "./view", "view");
 const { toggleButtonContract, toggleStateContract } = require('./contract');
-const { properties, render, state, register, unregister,
-  setStateFor, getStateFor, getDerivedStateFor } = require('../state');
-const { events: stateEvents } = require('../state/events');
-const { events: viewEvents } = require('./view/events');
-const events = require('../../event/utils');
+lazyRequire(this, '../state', "properties", "render", "state", "register", "unregister",
+            "setStateFor", "getStateFor", "getDerivedStateFor");
+lazyRequire(this, '../state/events', { "events": "stateEvents" });
+lazyRequire(this, './view/events', { "events": "viewEvents" });
+lazyRequireModule(this, '../../event/utils', "events");
 
-const { getActiveTab } = require('../../tabs/utils');
+lazyRequire(this, '../../tabs/utils', "getActiveTab");
 
-const { id: addonID } = require('../../self');
-const { identify } = require('../id');
+lazyRequire(this, '../../self', { "id": "addonID" });
+lazyRequire(this, '../id', "identify");
 
 const buttons = new Map();
 
 const toWidgetId = id =>
   ('toggle-button--' + addonID.toLowerCase()+ '-' + id).
     replace(/[^a-z0-9_-]/g, '');
 
 const ToggleButton = Class({
--- a/addon-sdk/source/lib/sdk/ui/button/view.js
+++ b/addon-sdk/source/lib/sdk/ui/button/view.js
@@ -6,28 +6,28 @@
 module.metadata = {
   'stability': 'experimental',
   'engines': {
     'Firefox': '> 28'
   }
 };
 
 const { Cu } = require('chrome');
-const { on, off, emit } = require('../../event/core');
+lazyRequire(this, '../../event/core', "on", "off", "emit");
 
-const { data } = require('sdk/self');
+lazyRequire(this, 'sdk/self', "data");
 
-const { isObject, isNil } = require('../../lang/type');
+lazyRequire(this, '../../lang/type', "isObject", "isNil");
 
-const { getMostRecentBrowserWindow } = require('../../window/utils');
-const { ignoreWindow } = require('../../private-browsing/utils');
+lazyRequire(this, '../../window/utils', "getMostRecentBrowserWindow");
+lazyRequire(this, '../../private-browsing/utils', "ignoreWindow");
 const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
 const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
 
-const { events: viewEvents } = require('./view/events');
+lazyRequire(this, './view/events', { "events": "viewEvents" });
 
 const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
 
 const views = new Map();
 const customizedWindows = new WeakMap();
 
 const buttonListener = {
   onCustomizeStart: window => {
--- a/addon-sdk/source/lib/sdk/ui/frame.js
+++ b/addon-sdk/source/lib/sdk/ui/frame.js
@@ -5,12 +5,11 @@
 
 module.metadata = {
   "stability": "experimental",
   "engines": {
     "Firefox": "> 28"
   }
 };
 
-require("./frame/view");
 const { Frame } = require("./frame/model");
 
 exports.Frame = Frame;
--- a/addon-sdk/source/lib/sdk/ui/frame/model.js
+++ b/addon-sdk/source/lib/sdk/ui/frame/model.js
@@ -7,29 +7,29 @@ module.metadata = {
   "stability": "experimental",
   "engines": {
     "Firefox": "> 28"
   }
 };
 
 const { Class } = require("../../core/heritage");
 const { EventTarget } = require("../../event/target");
-const { emit, off, setListeners } = require("../../event/core");
+lazyRequire(this, "../../event/core", "emit", "off", "setListeners");
 const { Reactor, foldp, send, merges } = require("../../event/utils");
 const { Disposable } = require("../../core/disposable");
 const { OutputPort } = require("../../output/system");
-const { InputPort } = require("../../input/system");
-const { identify } = require("../id");
-const { pairs, object, map, each } = require("../../util/sequence");
-const { patch, diff } = require("diffpatcher/index");
-const { isLocalURL } = require("../../url");
+lazyRequire(this, "../id", "identify");
+const { pairs, object, each } = require("../../util/sequence");
+lazyRequire(this, "diffpatcher/index", "patch", "diff");
+lazyRequire(this, "../../url", "isLocalURL");
 const { compose } = require("../../lang/functional");
 const { contract } = require("../../util/contract");
 const { id: addonID, data: { url: resolve }} = require("../../self");
 const { Frames } = require("../../input/frame");
+require("./view");
 
 
 const output = new OutputPort({ id: "frame-change" });
 const mailbox = new OutputPort({ id: "frame-mailbox" });
 const input = Frames;
 
 
 const makeID = url =>
--- a/addon-sdk/source/lib/sdk/ui/frame/view.js
+++ b/addon-sdk/source/lib/sdk/ui/frame/view.js
@@ -7,26 +7,23 @@ module.metadata = {
   "stability": "experimental",
   "engines": {
     "Firefox": "> 28"
   }
 };
 
 const { Cu, Ci } = require("chrome");
 const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { subscribe, send, Reactor, foldp, lift, merges, keepIf } = require("../../event/utils");
-const { InputPort } = require("../../input/system");
+const { send, Reactor } = require("../../event/utils");
 const { OutputPort } = require("../../output/system");
-const { LastClosed } = require("../../input/browser");
-const { pairs, keys, object, each } = require("../../util/sequence");
+lazyRequire(this, "../../util/sequence", "pairs", "keys", "object", "each");
 const { curry, compose } = require("../../lang/functional");
-const { getFrameElement, getOuterId,
-        getByOuterId, getOwnerBrowserWindow } = require("../../window/utils");
-const { patch, diff } = require("diffpatcher/index");
-const { encode } = require("../../base64");
+lazyRequire(this, "../../window/utils", "getFrameElement", "getOuterId", "getByOuterId", "getOwnerBrowserWindow");
+lazyRequire(this, "diffpatcher/index", "patch", "diff");
+lazyRequire(this, "../../base64", "encode");
 const { Frames } = require("../../input/frame");
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html");
 
 const mailbox = new OutputPort({ id: "frame-mailbox" });
 
--- a/addon-sdk/source/lib/sdk/ui/id.js
+++ b/addon-sdk/source/lib/sdk/ui/id.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   'stability': 'experimental'
 };
 
 const method = require('../../method/core');
-const { uuid } = require('../util/uuid');
+lazyRequire(this, '../util/uuid', "uuid");
 
 // NOTE: use lang/functional memoize when it is updated to use WeakMap
 function memoize(f) {
   const memo = new WeakMap();
 
   return function memoizer(o) {
     let key = o;
     if (!memo.has(key))
--- a/addon-sdk/source/lib/sdk/ui/sidebar.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar.js
@@ -8,46 +8,43 @@ module.metadata = {
   'engines': {
     'Firefox': '*'
   }
 };
 
 const { Class } = require('../core/heritage');
 const { merge } = require('../util/object');
 const { Disposable } = require('../core/disposable');
-const { off, emit, setListeners } = require('../event/core');
+lazyRequire(this, '../event/core', "off", "emit", "setListeners");
 const { EventTarget } = require('../event/target');
-const { URL } = require('../url');
-const { add, remove, has, clear, iterator } = require('../lang/weak-set');
-const { id: addonID, data } = require('../self');
-const { WindowTracker } = require('../deprecated/window-utils');
-const { isShowing } = require('./sidebar/utils');
-const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../window/utils');
+lazyRequire(this, '../url', "URL");
+lazyRequire(this, '../self', { "id": "addonID" }, "data");
+lazyRequire(this, '../deprecated/window-utils', 'WindowTracker');
+lazyRequire(this, './sidebar/utils', "isShowing");
+lazyRequire(this, '../window/utils', "isBrowser", "getMostRecentBrowserWindow", "windows", "isWindowPrivate");
 const { ns } = require('../core/namespace');
-const { remove: removeFromArray } = require('../util/array');
-const { show, hide, toggle } = require('./sidebar/actions');
-const { Worker } = require('../deprecated/sync-worker');
+lazyRequire(this, '../util/array', { "remove": "removeFromArray" });
+lazyRequire(this, './sidebar/actions', "show", "hide", "toggle");
+lazyRequire(this, '../deprecated/sync-worker', "Worker");
 const { contract: sidebarContract } = require('./sidebar/contract');
-const { create, dispose, updateTitle, updateURL, isSidebarShowing, showSidebar, hideSidebar } = require('./sidebar/view');
-const { defer } = require('../core/promise');
-const { models, views, viewsFor, modelFor } = require('./sidebar/namespace');
-const { isLocalURL } = require('../url');
+lazyRequire(this, './sidebar/view', "create", "dispose", "updateTitle", "updateURL", "isSidebarShowing", "showSidebar", "hideSidebar");
+lazyRequire(this, '../core/promise', "defer");
+lazyRequire(this, './sidebar/namespace', "models", "views", "viewsFor", "modelFor");
+lazyRequire(this, '../url', "isLocalURL");
 const { ensure } = require('../system/unload');
-const { identify } = require('./id');
-const { uuid } = require('../util/uuid');
-const { viewFor } = require('../view/core');
+lazyRequire(this, './id', "identify");
+lazyRequire(this, '../util/uuid', "uuid");
+lazyRequire(this, '../view/core', "viewFor");
 
 const resolveURL = (url) => url ? data.url(url) : url;
 
 const sidebarNS = ns();
 
 const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
 
-var sidebars = {};
-
 const Sidebar = Class({
   implements: [ Disposable ],
   extends: EventTarget,
   setup: function(options) {
     // inital validation for the model information
     let model = sidebarContract(options);
 
     // save the model information
@@ -204,18 +201,16 @@ const Sidebar = Class({
         if (windowNS(window).onWebPanelSidebarUnload) {
           panelBrowser && panelBrowser.contentWindow.removeEventListener('unload', windowNS(window).onWebPanelSidebarUnload, true);
           windowNS(window).onWebPanelSidebarUnload();
         }
       }
     });
 
     views.set(this, bars);
-
-    add(sidebars, this);
   },
   get id() {
     return (modelFor(this) || {}).id;
   },
   get title() {
     return (modelFor(this) || {}).title;
   },
   set title(v) {
@@ -254,18 +249,16 @@ const Sidebar = Class({
   hide: function(window) {
     return hideSidebar(viewFor(window), this);
   },
   dispose: function() {
     const internals = sidebarNS(this);
 
     off(this);
 
-    remove(sidebars, this);
-
     // stop tracking windows
     if (internals.tracker) {
       internals.tracker.unload();
     }
 
     internals.tracker = null;
     internals.windowNS = null;
 
--- a/addon-sdk/source/lib/sdk/ui/sidebar/view.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/view.js
@@ -5,21 +5,21 @@
 
 module.metadata = {
   'stability': 'unstable',
   'engines': {
     'Firefox': '*'
   }
 };
 
-const { models, buttons, views, viewsFor, modelFor } = require('./namespace');
-const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../../window/utils');
-const { setStateFor } = require('../state');
-const { defer } = require('../../core/promise');
-const { isPrivateBrowsingSupported, data } = require('../../self');
+lazyRequire(this, './namespace', "models", "buttons", "views", "viewsFor", "modelFor");
+lazyRequire(this, '../../window/utils', "isBrowser", "getMostRecentBrowserWindow", "windows", "isWindowPrivate");
+lazyRequire(this, '../state', "setStateFor");
+lazyRequire(this, '../../core/promise', "defer");
+lazyRequire(this, '../../self', "isPrivateBrowsingSupported", "data");
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
 
 const resolveURL = (url) => url ? data.url(url) : url;
 
 function create(window, details) {
   let id = makeID(details.id);
--- a/addon-sdk/source/lib/sdk/ui/state.js
+++ b/addon-sdk/source/lib/sdk/ui/state.js
@@ -16,29 +16,29 @@ module.metadata = {
 
 const { Ci } = require('chrome');
 
 const events = require('../event/utils');
 const { events: browserEvents } = require('../browser/events');
 const { events: tabEvents } = require('../tab/events');
 const { events: stateEvents } = require('./state/events');
 
-const { windows, isInteractive, getFocusedBrowser } = require('../window/utils');
-const { getActiveTab, getOwnerWindow } = require('../tabs/utils');
+lazyRequire(this, '../window/utils', "windows", "isInteractive", "getFocusedBrowser");
+lazyRequire(this, '../tabs/utils', "getActiveTab", "getOwnerWindow");
 
-const { ignoreWindow } = require('../private-browsing/utils');
+lazyRequire(this, '../private-browsing/utils', "ignoreWindow");
 
 const { freeze } = Object;
 const { merge } = require('../util/object');
-const { on, off, emit } = require('../event/core');
+lazyRequire(this, '../event/core', "on", "off", "emit");
 
-const { add, remove, has, clear, iterator } = require('../lang/weak-set');
-const { isNil } = require('../lang/type');
+lazyRequire(this, '../lang/weak-set', "add", "remove", "has", "clear", "iterator");
+lazyRequire(this, '../lang/type', "isNil");
 
-const { viewFor } = require('../view/core');
+lazyRequire(this, '../view/core', "viewFor");
 
 const components = new WeakMap();
 
 const ERR_UNREGISTERED = 'The state cannot be set or get. ' +
   'The object may be not be registered, or may already have been unloaded.';
 
 const ERR_INVALID_TARGET = 'The state cannot be set or get for this target.' +
   'Only window, tab and registered component are valid targets.';
--- a/addon-sdk/source/lib/sdk/ui/toolbar/view.js
+++ b/addon-sdk/source/lib/sdk/ui/toolbar/view.js
@@ -15,20 +15,20 @@ const { CustomizableUI } = Cu.import('re
 const { subscribe, send, Reactor, foldp, lift, merges } = require("../../event/utils");
 const { InputPort } = require("../../input/system");
 const { OutputPort } = require("../../output/system");
 const { Interactive } = require("../../input/browser");
 const { CustomizationInput } = require("../../input/customizable-ui");
 const { pairs, map, isEmpty, object,
         each, keys, values } = require("../../util/sequence");
 const { curry, flip } = require("../../lang/functional");
-const { patch, diff } = require("diffpatcher/index");
+lazyRequire(this, "diffpatcher/index", "patch", "diff");
 const prefs = require("../../preferences/service");
-const { getByOuterId } = require("../../window/utils");
-const { ignoreWindow } = require('../../private-browsing/utils');
+lazyRequire(this, "../../window/utils", "getByOuterId");
+lazyRequire(this, '../../private-browsing/utils', "ignoreWindow");
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const PREF_ROOT = "extensions.sdk-toolbar-collapsed.";
 
 
 // There are two output ports one for publishing changes that occured
 // and the other for change requests. Later is synchronous and is only
 // consumed here. Note: it needs to be synchronous to avoid race conditions
--- a/addon-sdk/source/lib/sdk/util/deprecate.js
+++ b/addon-sdk/source/lib/sdk/util/deprecate.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
-const { get, format } = require("../console/traceback");
-const { get: getPref } = require("../preferences/service");
+lazyRequire(this, "../console/traceback", "get", "format");
+lazyRequire(this, "../preferences/service", {"get": "getPref"});
 const PREFERENCE = "devtools.errorconsole.deprecation_warnings";
 
 function deprecateUsage(msg) {
   // Print caller stacktrace in order to help figuring out which code
   // does use deprecated thing
   let stack = get().slice(2);
 
   if (getPref(PREFERENCE)) 
--- a/addon-sdk/source/lib/sdk/util/match-pattern.js
+++ b/addon-sdk/source/lib/sdk/util/match-pattern.js
@@ -2,17 +2,17 @@
  * 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";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-const { URL } = require('../url');
+lazyRequire(this, '../url', "URL");
 const cache = {};
 
 function MatchPattern(pattern) {
   if (cache[pattern]) return cache[pattern];
 
   if (typeof pattern.test == "function") {
     // For compatibility with -moz-document rules, we require the RegExp's
     // global, ignoreCase, and multiline flags to be set to false.
--- a/addon-sdk/source/lib/sdk/util/object.js
+++ b/addon-sdk/source/lib/sdk/util/object.js
@@ -2,17 +2,17 @@
  * 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";
 
 module.metadata = {
   "stability": "unstable"
 };
 
-const { flatten } = require('./array');
+lazyRequire(this, './array', "flatten");
 
 // Create a shortcut for Array.prototype.slice.call().
 const unbind = Function.call.bind(Function.bind, Function.call);
 const slice = unbind(Array.prototype.slice);
 
 class DefaultWeakMap extends WeakMap {
   constructor(createItem, items = undefined) {
     super(items);
--- a/addon-sdk/source/lib/sdk/util/rules.js
+++ b/addon-sdk/source/lib/sdk/util/rules.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Class } = require('../core/heritage');
-const { MatchPattern } = require('./match-pattern');
-const { emit } = require('../event/core');
+lazyRequire(this, './match-pattern', "MatchPattern");
+lazyRequire(this, '../event/core', "emit");
 const { EventTarget } = require('../event/target');
 const { List, addListItem, removeListItem } = require('./list');
 
 // Should deprecate usage of EventEmitter/compose
 const Rules = Class({
   implements: [
     EventTarget,
     List
--- a/addon-sdk/source/lib/sdk/util/sequence.js
+++ b/addon-sdk/source/lib/sdk/util/sequence.js
@@ -16,18 +16,18 @@ module.metadata = {
 // - `p` stands for "predicate" that is function which returns logical
 //   true or false and is intended to be side effect free.
 // - `x` / `y` single item of the sequence.
 // - `xs` / `ys` sequence of `x` / `y` items where `x` / `y` signifies
 //    type of the items in sequence, so sequence is not of the same item.
 // - `_` used for argument(s) or variable(s) who's values are ignored.
 
 const { complement, flip, identity } = require("../lang/functional");
-const { isArray, isArguments, isMap, isSet, isGenerator,
-        isString, isBoolean, isNumber } = require("../lang/type");
+lazyRequire(this, "../lang/type", "isArray", "isArguments", "isMap", "isSet",
+            "isGenerator", "isString", "isBoolean", "isNumber");
 
 const Sequence = function Sequence(iterator) {
   if (!isGenerator(iterator)) {
     throw TypeError("Expected generator argument");
   }
 
   this[Symbol.iterator] = iterator;
 };
--- a/addon-sdk/source/lib/sdk/window/utils.js
+++ b/addon-sdk/source/lib/sdk/window/utils.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 module.metadata = {
   'stability': 'unstable'
 };
 
 const { Cc, Ci } = require('chrome');
-const array = require('../util/array');
+lazyRequireModule(this, "../util/array", "array");
 const { defer } = require('sdk/core/promise');
 const { dispatcher } = require("../util/dispatcher");
 
 const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
                        getService(Ci.nsIWindowWatcher);
 const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
                         getService(Ci.nsIAppShellService);
 const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -27,37 +27,41 @@ const { classes: Cc, Constructor: CC, in
         results: Cr, manager: Cm } = Components;
 const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
 const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
                      getService(Ci.mozIJSSubScriptLoader);
 const { addObserver, notifyObservers } = Cc['@mozilla.org/observer-service;1'].
                         getService(Ci.nsIObserverService);
 const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-const { join: pathJoin, normalize, dirname } = Cu.import("resource://gre/modules/osfile/ospath_unix.jsm");
+const { normalize, dirname } = Cu.import("resource://gre/modules/osfile/ospath_unix.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "resProto",
                                    "@mozilla.org/network/protocol;1?name=resource",
                                    "nsIResProtocolHandler");
 XPCOMUtils.defineLazyServiceGetter(this, "zipCache",
                                    "@mozilla.org/libjar/zip-reader-cache;1",
                                    "nsIZipReaderCache");
 
-XPCOMUtils.defineLazyGetter(this, "XulApp", () => {
+const { defineLazyGetter } = XPCOMUtils;
+
+defineLazyGetter(this, "XulApp", () => {
   let xulappURI = module.uri.replace("toolkit/loader.js",
                                      "sdk/system/xul-app.jsm");
   return Cu.import(xulappURI, {});
 });
 
 // Define some shortcuts.
 const bind = Function.call.bind(Function.bind);
 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
 const prototypeOf = Object.getPrototypeOf;
-const getOwnIdentifiers = x => [...Object.getOwnPropertyNames(x),
-                                ...Object.getOwnPropertySymbols(x)];
+function* getOwnIdentifiers(x) {
+  yield* Object.getOwnPropertyNames(x);
+  yield* Object.getOwnPropertySymbols(x);
+}
 
 const NODE_MODULES = new Set([
   "assert",
   "buffer_ieee754",
   "buffer",
   "child_process",
   "cluster",
   "console",
@@ -118,19 +122,18 @@ function freeze(object) {
       freeze(object);
   }
   return object;
 }
 
 // Returns map of given `object`-s own property descriptors.
 const descriptor = iced(function descriptor(object) {
   let value = {};
-  getOwnIdentifiers(object).forEach(function(name) {
+  for (let name of getOwnIdentifiers(object))
     value[name] = getOwnPropertyDescriptor(object, name)
-  });
   return value;
 });
 Loader.descriptor = descriptor;
 
 // Freeze important built-ins so they can't be used by untrusted code as a
 // message passing channel.
 freeze(Object);
 freeze(Object.prototype);
@@ -153,21 +156,21 @@ function iced(f) {
 }
 
 // Defines own properties of given `properties` object on the given
 // target object overriding any existing property with a conflicting name.
 // Returns `target` object. Note we only export this function because it's
 // useful during loader bootstrap when other util modules can't be used &
 // thats only case where this export should be used.
 const override = iced(function override(target, source) {
-  let properties = descriptor(target)
-  let extension = descriptor(source || {})
-  getOwnIdentifiers(extension).forEach(function(name) {
-    properties[name] = extension[name];
-  });
+  let properties = descriptor(target);
+
+  for (let name of getOwnIdentifiers(source || {}))
+    properties[name] = getOwnPropertyDescriptor(source, name);
+
   return Object.defineProperties({}, properties);
 });
 Loader.override = override;
 
 function sourceURI(uri) { return String(uri).split(" -> ").pop(); }
 Loader.sourceURI = iced(sourceURI);
 
 function isntLoaderFrame(frame) { return frame.fileName !== module.uri }
@@ -276,23 +279,43 @@ const urlCache = {
       let uri = NetUtil.newURI(url).QueryInterface(Ci.nsIFileURL);
 
       return uri.file.exists();
     } catch (e) {
       return false;
     }
   }),
 
+  resolutionCache: new DefaultMap(fullId => {
+    return (resolveAsFile(fullId) ||
+            resolveAsDirectory(fullId));
+  }),
+
+  nodeModulesCache: new Map(),
+
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
 
   observe() {
     // Clear any module resolution caches when the startup cache is flushed,
     // since it probably means we're loading new copies of extensions.
     this.zipContentsCache.clear();
     this.filesCache.clear();
+    this.resolutionCache.clear();
+    this.nodeModulesCache.clear();
+  },
+
+  getNodeModulePaths(rootURI, start) {
+    let url = join(rootURI, start);
+
+    if (this.nodeModulesCache.has(url))
+      return this.nodeModulesCache.get(url);
+
+    let result = Array.from(getNodeModulePaths(rootURI, start));
+    this.nodeModulesCache.set(url, result);
+    return result;
   },
 
   /**
    * Returns the base URL for the given URL, if one can be determined. For
    * a resource: URL, this is the root of the resource package. For a jar:
    * URL, it is the root of the JAR file. Otherwise, null is returned.
    *
    * @param {string} url
@@ -360,20 +383,20 @@ function readURI(uri) {
 }
 
 // Combines all arguments into a resolved, normalized path
 function join(base, ...paths) {
   // If this is an absolute URL, we need to normalize only the path portion,
   // or we wind up stripping too many slashes and producing invalid URLs.
   let match = /^((?:resource|file|chrome)\:\/\/[^\/]*|jar:[^!]+!)(.*)/.exec(base);
   if (match) {
-    return match[1] + normalize(pathJoin(match[2], ...paths));
+    return match[1] + normalize([match[2], ...paths].join("/"));
   }
 
-  return normalize(pathJoin(base, ...paths));
+  return normalize([base, ...paths].join("/"));
 }
 Loader.join = join;
 
 // Function takes set of options and returns a JS sandbox. Function may be
 // passed set of options:
 //  - `name`: A string value which identifies the sandbox in about:memory. Will
 //    throw exception if omitted.
 // - `principal`: String URI or `nsIPrincipal` for the sandbox. Defaults to
@@ -466,21 +489,38 @@ const load = iced(function load(loader, 
   });
 
   let sandbox;
   if ((loader.useSharedGlobalSandbox || isSystemURI(module.uri)) &&
       loader.sharedGlobalBlocklist.indexOf(module.id) == -1) {
     // Create a new object in this sandbox, that will be used as
     // the scope object for this particular module
     sandbox = new loader.sharedGlobalSandbox.Object();
-    // Inject all expected globals in the scope object
-    getOwnIdentifiers(globals).forEach(function(name) {
-      descriptors[name] = getOwnPropertyDescriptor(globals, name)
-      descriptors[name].configurable = true;
-    });
+    descriptors.lazyRequire = {
+      configurable: true,
+      value: lazyRequire.bind(sandbox),
+    };
+    descriptors.lazyRequireModule = {
+      configurable: true,
+      value: lazyRequireModule.bind(sandbox),
+    };
+
+    if ("console" in globals) {
+      descriptors.console = {
+        configurable: true,
+        get() {
+          return globals.console;
+        },
+      };
+    }
+    let define = Object.getOwnPropertyDescriptor(globals, "define");
+    if (define && define.value)
+      descriptors.define = define;
+    if ("DOMParser" in globals)
+      descriptors.DOMParser = Object.getOwnPropertyDescriptor(globals, "DOMParser");
     Object.defineProperties(sandbox, descriptors);
   }
   else {
     sandbox = Sandbox({
       name: module.uri,
       prototype: Object.create(globals, descriptors),
       wantXrays: false,
       wantGlobalProperties: module.id == "sdk/indexed-db" ? ["indexedDB"] : [],
@@ -545,52 +585,48 @@ const load = iced(function load(loader, 
       throw err;
     }
   }
 
   // Only freeze the exports object if we created it ourselves. Modules
   // which completely replace the exports object and still want it
   // frozen need to freeze it themselves.
   if (module.exports === originalExports)
-    freeze(module.exports);
+    Object.freeze(module.exports);
 
   return module;
 });
 Loader.load = load;
 
 // Utility function to normalize module `uri`s so they have `.js` extension.
 function normalizeExt(uri) {
   return isJSURI(uri) ? uri :
          isJSONURI(uri) ? uri :
          isJSMURI(uri) ? uri :
          uri + '.js';
 }
 
-// Strips `rootURI` from `string` -- used to remove absolute resourceURI
-// from a relative path
-function stripBase(rootURI, string) {
-  return string.replace(rootURI, './');
-}
-
 // Utility function to join paths. In common case `base` is a
 // `requirer.uri` but in some cases it may be `baseURI`. In order to
 // avoid complexity we require `baseURI` with a trailing `/`.
 const resolve = iced(function resolve(id, base) {
   if (!isRelative(id))
     return id;
 
   let baseDir = dirname(base);
-  if (!baseDir)
-    return normalize(id);
 
-  let resolved = join(baseDir, id);
+  let resolved;
+  if (baseDir.includes(":"))
+    resolved = join(baseDir, id);
+  else
+    resolved = normalize(`${baseDir}/${id}`);
 
   // Joining and normalizing removes the './' from relative files.
   // We need to ensure the resolution still has the root
-  if (isRelative(base))
+  if (base.startsWith('./'))
     resolved = './' + resolved;
 
   return resolved;
 });
 Loader.resolve = resolve;
 
 // Attempts to load `path` and then `path.js`
 // Returns `path` with valid file, or `undefined` otherwise
@@ -623,34 +659,33 @@ function resolveAsDirectory(path) {
   } catch (e) {}
 
   return resolveAsFile(addTrailingSlash(path) + 'index.js');
 }
 
 function resolveRelative(rootURI, modulesDir, id) {
   let fullId = join(rootURI, modulesDir, id);
 
-  let resolvedPath = (resolveAsFile(fullId) ||
-                      resolveAsDirectory(fullId));
+  let resolvedPath = urlCache.resolutionCache.get(fullId);
   if (resolvedPath) {
-    return stripBase(rootURI, resolvedPath);
+    return './' + resolvedPath.slice(rootURI.length);
   }
 
   return null;
 }
 
 // From `resolve` module
 // https://github.com/substack/node-resolve/blob/master/lib/node-modules-paths.js
 function* getNodeModulePaths(rootURI, start) {
   let moduleDir = 'node_modules';
 
   let parts = start.split('/');
   while (parts.length) {
     let leaf = parts.pop();
-    let path = join(...parts, leaf, moduleDir);
+    let path = [...parts, leaf, moduleDir].join("/");
     if (leaf !== moduleDir && urlCache.exists(join(rootURI, path))) {
       yield path;
     }
   }
 
   if (urlCache.exists(join(rootURI, moduleDir))) {
     yield moduleDir;
   }
@@ -681,17 +716,17 @@ const nodeResolve = iced(function nodeRe
   // If the requirer is an absolute URI then the node module resolution below
   // won't work correctly as we prefix everything with rootURI
   if (isAbsoluteURI(requirer)) {
     return null;
   }
 
   // If manifest has dependencies, attempt to look up node modules
   // in the `dependencies` list
-  for (let modulesDir of getNodeModulePaths(rootURI, dirname(requirer))) {
+  for (let modulesDir of urlCache.getNodeModulePaths(rootURI, dirname(requirer))) {
     if ((resolvedPath = resolveRelative(rootURI, modulesDir, id))) {
       return resolvedPath;
     }
   }
 
   // We would not find lookup for things like `sdk/tabs`, as that's part of
   // the alias mapping. If during `generateMap`, the runtime lookup resolves
   // with `resolveURI` -- if during runtime, then `resolve` will throw.
@@ -699,51 +734,128 @@ const nodeResolve = iced(function nodeRe
 });
 
 Loader.nodeResolve = nodeResolve;
 
 function addTrailingSlash(path) {
   return path.replace(/\/*$/, "/");
 }
 
-const resolveURI = iced(function resolveURI(id, mapping) {
-  // Do not resolve if already a resource URI
-  if (isAbsoluteURI(id))
-    return normalizeExt(id);
+function compileMapping(paths) {
+  // Make mapping array that is sorted from longest path to shortest path.
+  let mapping = Object.keys(paths)
+                      .sort((a, b) => b.length - a.length)
+                      .map(path => [path, paths[path]]);
+
+  const PATTERN = /([.\\?+*(){}[\]^$])/g;
+  const escapeMeta = str => str.replace(PATTERN, '\\$1')
+
+  let patterns = [];
+  paths = {};
 
   for (let [path, uri] of mapping) {
     // Strip off any trailing slashes to make comparisons simpler
-    let stripped = path.replace(/\/+$/, "");
+    if (path.endsWith("/")) {
+      path = path.slice(0, -1);
+      uri = uri.replace(/\/+$/, "");
+    }
+
+    paths[path] = uri;
 
     // We only want to match path segments explicitly. Examples:
     // * "foo/bar" matches for "foo/bar"
     // * "foo/bar" matches for "foo/bar/baz"
     // * "foo/bar" does not match for "foo/bar-1"
     // * "foo/bar/" does not match for "foo/bar"
     // * "foo/bar/" matches for "foo/bar/baz"
     //
     // Check for an empty path, an exact match, or a substring match
     // with the next character being a forward slash.
-    if(stripped === "" || id === stripped || id.startsWith(stripped + "/")) {
-      return normalizeExt(id.replace(path, uri));
-    }
+    if (path == "")
+      patterns.push("");
+    else
+      patterns.push(`${escapeMeta(path)}(?=$|/)`);
   }
-  return null;
+
+  let pattern = new RegExp(`^(${patterns.join('|')})`);
+
+  // This will replace the longest matching path mapping at the start of
+  // the ID string with its mapped value.
+  return id => {
+    return id.replace(pattern, (m0, m1) => paths[m1]);
+  };
+}
+
+const resolveURI = iced(function resolveURI(id, mapping) {
+  // Do not resolve if already a resource URI
+  if (isAbsoluteURI(id))
+    return normalizeExt(id);
+
+  return normalizeExt(mapping(id))
 });
 Loader.resolveURI = resolveURI;
 
+/**
+ * Defines lazy getters on the given object, which lazily require the
+ * given module the first time they are accessed, and then resolve that
+ * module's exported properties.
+ *
+ * @param {object} obj
+ *        The target object on which to define the lazy getters.
+ * @param {string} moduleId
+ *        The ID of the module to require, as passed to require().
+ * @param {Array<string | object>} args
+ *        Any number of properties to import from the module. A string
+ *        will cause the property to be defined which resolves to the
+ *        same property in the module's exports. An object will define a
+ *        lazy getter for every value in the object which corresponds to
+ *        the given key in the module's exports, as in an ordinary
+ *        destructuring assignment.
+ */
+function lazyRequire(obj, moduleId, ...args) {
+  let module;
+  let getModule = () => {
+    if (!module)
+      module = this.require(moduleId);
+    return module;
+  };
+
+  for (let props of args) {
+    if (typeof props !== "object")
+      props = {[props]: props};
+
+    for (let [fromName, toName] of Object.entries(props))
+      defineLazyGetter(obj, toName, () => getModule()[fromName]);
+  }
+}
+
+/**
+ * Defines a lazy getter on the given object which causes a module to be
+ * lazily imported the first time it is accessed.
+ *
+ * @param {object} obj
+ *        The target object on which to define the lazy getter.
+ * @param {string} moduleId
+ *        The ID of the module to require, as passed to require().
+ * @param {string} [prop = moduleId]
+ *        The name of the lazy getter property to define.
+ */
+function lazyRequireModule(obj, moduleId, prop = moduleId) {
+  defineLazyGetter(obj, prop, () => this.require(moduleId));
+}
+
+
 // Creates version of `require` that will be exposed to the given `module`
 // in the context of the given `loader`. Each module gets own limited copy
 // of `require` that is allowed to load only a modules that are associated
 // with it during link time.
 const Require = iced(function Require(loader, requirer) {
   let {
-    modules, mapping, resolve: loaderResolve, load,
-    manifest, rootURI, isNative, requireMap,
-    requireHook
+    modules, mapping, mappingCache, resolve: loaderResolve, load,
+    manifest, rootURI, isNative, requireHook
   } = loader;
 
   if (isSystemURI(requirer.uri)) {
     // Built-in modules don't require the expensive module resolution
     // algorithm used by SDK add-ons, so give them the more efficient standard
     // resolve instead.
     isNative = false;
     loaderResolve = Loader.resolve;
@@ -758,16 +870,17 @@ const Require = iced(function Require(lo
       return requireHook(id, _require);
     }
 
     return _require(id);
   }
 
   function _require(id) {
     let { uri, requirement } = getRequirements(id);
+
     let module = null;
     // If module is already cached by loader then just use it.
     if (uri in modules) {
       module = modules[uri];
     }
     else if (isJSMURI(uri)) {
       module = modules[uri] = Module(requirement, uri);
       module.exports = Cu.import(uri, {});
@@ -799,17 +912,17 @@ const Require = iced(function Require(lo
     // We also freeze module to prevent it from further changes
     // at runtime.
     if (!(uri in modules)) {
       // Many of the loader's functionalities are dependent
       // on modules[uri] being set before loading, so we set it and
       // remove it if we have any errors.
       module = modules[uri] = Module(requirement, uri);
       try {
-        freeze(load(loader, module));
+        Object.freeze(load(loader, module));
       }
       catch (e) {
         // Clear out modules cache so we can throw on a second invalid require
         delete modules[uri];
         // Also clear out the Sandbox that was created
         delete loader.sandboxes[uri];
         throw e;
       }
@@ -826,22 +939,16 @@ const Require = iced(function Require(lo
       throw Error('you must provide a module name when calling require() from '
                   + requirer.id, requirer.uri);
 
     let requirement, uri;
 
     // TODO should get native Firefox modules before doing node-style lookups
     // to save on loading time
     if (isNative) {
-      // If a requireMap is available from `generateMap`, use that to
-      // immediately resolve the node-style mapping.
-      // TODO: write more tests for this use case
-      if (requireMap && requireMap[requirer.id])
-        requirement = requireMap[requirer.id][id];
-
       let { overrides } = manifest.jetpack;
       for (let key in overrides) {
         // ignore any overrides using relative keys
         if (/^[.\/]/.test(key)) {
           continue;
         }
 
         // If the override is for x -> y,
@@ -854,18 +961,16 @@ const Require = iced(function Require(lo
       }
 
       // For native modules, we want to check if it's a module specified
       // in 'modules', like `chrome`, or `@loader` -- if it exists,
       // just set the uri to skip resolution
       if (!requirement && modules[id])
         uri = requirement = id;
 
-      // If no requireMap was provided, or resolution not found in
-      // the requireMap, and not a npm dependency, attempt a runtime lookup
       if (!requirement && !NODE_MODULES.has(id)) {
         // If `isNative` defined, this is using the new, native-style
         // loader, not cuddlefish, so lets resolve using node's algorithm
         // and get back a path that needs to be resolved via paths mapping
         // in `resolveURI`
         requirement = loaderResolve(id, requirer.id, {
           manifest: manifest,
           rootURI: rootURI
@@ -887,17 +992,24 @@ const Require = iced(function Require(lo
       // Resolve `id` to its requirer if it's relative.
       requirement = loaderResolve(id, requirer.id);
     }
     else {
       requirement = id;
     }
 
     // Resolves `uri` of module using loaders resolve function.
-    uri = uri || resolveURI(requirement, mapping);
+    if (!uri) {
+      if (mappingCache.has(requirement)) {
+        uri = mappingCache.get(requirement);
+      } else {
+        uri = resolveURI(requirement, mapping);
+        mappingCache.set(requirement, uri);
+      }
+    }
 
     // Throw if `uri` can not be resolved.
     if (!uri) {
       throw Error('Module: Can not resolve "' + id + '" module required by ' +
                   requirer.id + ' located at ' + requirer.uri, requirer.uri);
     }
 
     return { uri: uri, requirement: requirement };
@@ -970,21 +1082,25 @@ Loader.unload = unload;
 //   These modules will incorporated into module cache. Each module will be
 //   frozen.
 // - `resolve` Optional module `id` resolution function. If given it will be
 //   used to resolve module URIs, by calling it with require term, requirer
 //   module object (that has `uri` property) and `baseURI` of the loader.
 //   If `resolve` does not returns `uri` string exception will be thrown by
 //   an associated `require` call.
 function Loader(options) {
+  function normalizeRootURI(uri) {
+    return addTrailingSlash(join(uri));
+  }
+
   if (options.sharedGlobalBlacklist && !options.sharedGlobalBlocklist) {
     options.sharedGlobalBlocklist = options.sharedGlobalBlacklist;
   }
   let {
-    modules, globals, resolve, paths, rootURI, manifest, requireMap, isNative,
+    modules, globals, resolve, paths, rootURI, manifest, isNative,
     metadata, sharedGlobal, sharedGlobalBlocklist, checkCompatibility, waiveIntereposition
   } = override({
     paths: {},
     modules: {},
     globals: {
       get console() {
         // Import Console.jsm from here to prevent loading it until someone uses it
         let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm");
@@ -993,17 +1109,17 @@ function Loader(options) {
         });
         Object.defineProperty(this, "console", { value: console });
         return this.console;
       }
     },
     checkCompatibility: false,
     resolve: options.isNative ?
       // Make the returned resolve function have the same signature
-      (id, requirer) => Loader.nodeResolve(id, requirer, { rootURI: rootURI }) :
+      (id, requirer) => Loader.nodeResolve(id, requirer, { rootURI: normalizeRootURI(rootURI) }) :
       Loader.resolve,
     sharedGlobalBlocklist: ["sdk/indexed-db"],
     waiveIntereposition: false
   }, options);
 
   // Create overrides defaults, none at the moment
   if (typeof manifest != "object" || !manifest) {
     manifest = {};
@@ -1019,20 +1135,17 @@ function Loader(options) {
 
   // We create an identity object that will be dispatched on an unload
   // event as subject. This way unload listeners will be able to assert
   // which loader is unloaded. Please note that we intentionally don't
   // use `loader` as subject to prevent a loader access leakage through
   // observer notifications.
   let destructor = freeze(Object.create(null));
 
-  // Make mapping array that is sorted from longest path to shortest path.
-  let mapping = Object.keys(paths)
-                      .sort((a, b) => b.length - a.length)
-                      .map(path => [path, paths[path]]);
+  let mapping = compileMapping(paths);
 
   // Define pseudo modules.
   modules = override({
     '@loader/unload': destructor,
     '@loader/options': options,
     'chrome': { Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm,
                 CC: bind(CC, Components), components: Components,
                 // `ChromeWorker` has to be inject in loader global scope.
@@ -1072,26 +1185,36 @@ function Loader(options) {
     name: "Addon-SDK",
     wantXrays: false,
     wantGlobalProperties: [],
     invisibleToDebugger: options.invisibleToDebugger || false,
     metadata: {
       addonID: options.id,
       URI: "Addon-SDK"
     },
-    prototype: options.sandboxPrototype || {}
+    prototype: options.sandboxPrototype || globals,
   });
 
+  if (options.sandboxPrototype) {
+    // If we were given a sandboxPrototype, we have to define the globals on
+    // the sandbox directly. Note that this will not work for callers who
+    // depend on being able to add globals after the loader was created.
+    for (let name of getOwnIdentifiers(globals))
+      Object.defineProperty(sharedGlobalSandbox, name,
+                            getOwnPropertyDescriptor(globals, name));
+  }
+
   // Loader object is just a representation of a environment
   // state. We freeze it and mark make it's properties non-enumerable
   // as they are pure implementation detail that no one should rely upon.
   let returnObj = {
     destructor: { enumerable: false, value: destructor },
     globals: { enumerable: false, value: globals },
     mapping: { enumerable: false, value: mapping },
+    mappingCache: { enumerable: false, value: new Map() },
     // Map of module objects indexed by module URIs.
     modules: { enumerable: false, value: modules },
     metadata: { enumerable: false, value: metadata },
     useSharedGlobalSandbox: { enumerable: false, value: !!sharedGlobal },
     sharedGlobalSandbox: { enumerable: false, value: sharedGlobalSandbox },
     sharedGlobalBlocklist: { enumerable: false, value: sharedGlobalBlocklist },
     sharedGlobalBlacklist: { enumerable: false, value: sharedGlobalBlocklist },
     // Map of module sandboxes indexed by module URIs.
@@ -1117,32 +1240,29 @@ function Loader(options) {
         set: function(module) { main = main || module; }
       }
     }
   };
 
   if (isNative) {
     returnObj.isNative = { enumerable: false, value: true };
     returnObj.manifest = { enumerable: false, value: manifest };
-    returnObj.requireMap = { enumerable: false, value: requireMap };
-    returnObj.rootURI = { enumerable: false, value: addTrailingSlash(rootURI) };
+    returnObj.rootURI = { enumerable: false, value: normalizeRootURI(rootURI) };
   }
 
   return freeze(Object.create(null, returnObj));
 };
 Loader.Loader = Loader;
 
 var isSystemURI = uri => /^resource:\/\/(gre|devtools|testing-common)\//.test(uri);
 
 var isJSONURI = uri => uri.endsWith('.json');
 var isJSMURI = uri => uri.endsWith('.jsm');
 var isJSURI = uri => uri.endsWith('.js');
-var isAbsoluteURI = uri => uri.startsWith("resource://") ||
-                           uri.startsWith("chrome://") ||
-                           uri.startsWith("file://");
+var isAbsoluteURI = uri => /^(resource|chrome|file|jar):/.test(uri);
 var isRelative = id => id.startsWith(".");
 
 // Default `main` entry to './index.js' and ensure is relative,
 // since node allows 'lib/index.js' without relative `./`
 function getManifestMain(manifest) {
   let main = manifest.main || './index.js';
   return isRelative(main) ? main : './' + main;
 }
--- a/addon-sdk/source/lib/toolkit/require.js
+++ b/addon-sdk/source/lib/toolkit/require.js
@@ -42,17 +42,17 @@ const make = (exports, rootURI, componen
       // more than once. Unless we invalidate statup cache changes to a module
       // won't be reflected even after reload. Therefor we must dispatch an
       // nsIObserverService notification that causes cache invalidation.
       // Note: This is not ideal since it destroys whole cache, but since there
       // is no way to invalidate individual entries, we assume performance hit
       // during development is acceptable.
       components.classes["@mozilla.org/observer-service;1"].
         getService(components.interfaces.nsIObserverService).
-        notifyObservers({}, "startupcache-invalidate", null);
+        notifyObservers({}, "startupcache-invalidate");
 
       if (all) {
         for (let uri of Object.keys(loader.sandboxes)) {
           unload(uri);
         }
       }
       else {
         unload(require.resolve(id));
--- a/addon-sdk/source/modules/system/Startup.js
+++ b/addon-sdk/source/modules/system/Startup.js
@@ -44,14 +44,13 @@ else {
       appStartup = NAME2TOPIC[name];
       break;
     }
   }
 
   let listener = function (subject, topic) {
     Services.obs.removeObserver(this, topic);
     Startup.initialized = true;
-    Services.tm.currentThread.dispatch(() => gOnceInitializedDeferred.resolve(),
-                                       Ci.nsIThread.DISPATCH_NORMAL);
+    Services.tm.dispatchToMainThread(() => gOnceInitializedDeferred.resolve());
   }
 
-  Services.obs.addObserver(listener, appStartup, false);
+  Services.obs.addObserver(listener, appStartup);
 }
--- a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js
+++ b/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js
@@ -32,17 +32,17 @@ function startup(data, reason) {
 
   try {
     let QuitObserver = {
       observe: function (aSubject, aTopic, aData) {
         Services.obs.removeObserver(QuitObserver, "quit-application");
         dump("MU: APPLICATION-QUIT\n");
       }
     };
-    Services.obs.addObserver(QuitObserver, "quit-application", false);
+    Services.obs.addObserver(QuitObserver, "quit-application");
     log("MU: ready to watch firefox exit.");
   } catch(e) {
     log("MU: unable to register quit-application observer: " + e);
   }
 }
 
 function install() {}
 function shutdown() {}
--- a/addon-sdk/source/test/addons/chrome/main.js
+++ b/addon-sdk/source/test/addons/chrome/main.js
@@ -4,16 +4,17 @@
 'use strict'
 
 const { Cu, Cc, Ci } = require('chrome');
 const Request = require('sdk/request').Request;
 const { WindowTracker } = require('sdk/deprecated/window-utils');
 const { close, open } = require('sdk/window/helpers');
 const { data } = require('sdk/self');
 const { Panel } = require('sdk/panel');
+const { getActiveView } = require("sdk/view/core");
 
 const XUL_URL = 'chrome://test/content/new-window.xul'
 
 const { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
 const { NetUtil } = Cu.import('resource://gre/modules/NetUtil.jsm', {});
 
 exports.testChromeSkin = function(assert, done) {
   let skinURL = 'chrome://test/skin/style.css';
@@ -69,16 +70,18 @@ exports.testChromeLocale = function(asse
 
 exports.testChromeInPanel = function*(assert) {
   let panel = Panel({
     contentURL: 'chrome://test/content/panel.html',
     contentScriptWhen: 'end',
     contentScriptFile: data.url('panel.js')
   });
 
+  getActiveView(panel);
+
   yield new Promise(resolve => panel.port.once('start', resolve));
   assert.pass('start was emitted');
 
   yield new Promise(resolve => {
     panel.once('show', resolve);
     panel.show();
   });
   assert.pass('panel shown');
--- a/addon-sdk/source/test/addons/content-permissions/httpd.js
+++ b/addon-sdk/source/test/addons/content-permissions/httpd.js
@@ -451,18 +451,17 @@ nsHttpServer.prototype =
       var stopEvent =
         {
           run: function()
           {
             dumpn("*** _notifyStopped async callback");
             self._notifyStopped();
           }
         };
-      gThreadManager.currentThread
-                    .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL);
+      gThreadManager.dispatchToMainThread(stopEvent);
     }
   },
 
   // NSIHTTPSERVER
 
   //
   // see nsIHttpServer.start
   //
@@ -2690,18 +2689,17 @@ ServerHandler.prototype =
       catch (e)
       {
         fis.close();
         throw e;
       }
 
       let writeMore = function writeMore()
       {
-        gThreadManager.currentThread
-                      .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL);
+        gThreadManager.dispatchToMainThread(writeData);
       }
 
       var input = new BinaryInputStream(fis);
       var output = new BinaryOutputStream(response.bodyOutputStream);
       var writeData =
         {
           run: function()
           {
@@ -3762,23 +3760,23 @@ Response.prototype =
       // happening asynchronously with respect to the actual writing of data to
       // bodyOutputStream, as they currently do; if they happened synchronously,
       // an event which ran before this one could write more data to the
       // response body before we get around to canceling the copier. We have
       // tests for this in test_seizepower.js, however, and I can't think of a
       // way to handle both cases without removing bodyOutputStream access and
       // moving its effective write(data, length) method onto Response, which
       // would be slower and require more code than this anyway.
-      gThreadManager.currentThread.dispatch({
+      gThreadManager.dispatchToMainThread({
         run: function()
         {
           dumpn("*** canceling copy asynchronously...");
           copier.cancel(Cr.NS_ERROR_UNEXPECTED);
         }
-      }, Ci.nsIThread.DISPATCH_NORMAL);
+      });
     }
     else
     {
       this.end();
     }
   },
 
   /**
@@ -4517,17 +4515,17 @@ WriteThroughCopier.prototype =
           {
             NS_ASSERT(false,
                       "how are we throwing an exception here? we control " +
                       "all the callers! " + e);
           }
         }
       };
 
-    gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
+    gThreadManager.dispatchToMainThread(event);
   },
 
   /**
 * Kicks off another wait for more data to be available from the input stream.
 */
   _waitToReadData: function()
   {
     dumpn("*** _waitToReadData");
--- a/addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
+++ b/addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
@@ -451,18 +451,17 @@ nsHttpServer.prototype =
       var stopEvent =
         {
           run: function()
           {
             dumpn("*** _notifyStopped async callback");
             self._notifyStopped();
           }
         };
-      gThreadManager.currentThread
-                    .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL);
+      gThreadManager.dispatchToMainThread(stopEvent);
     }
   },
 
   // NSIHTTPSERVER
 
   //
   // see nsIHttpServer.start
   //
@@ -2690,18 +2689,17 @@ ServerHandler.prototype =
       catch (e)
       {
         fis.close();
         throw e;
       }
 
       let writeMore = function writeMore()
       {
-        gThreadManager.currentThread
-                      .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL);
+        gThreadManager.dispatchToMainThread(writeData);
       }
 
       var input = new BinaryInputStream(fis);
       var output = new BinaryOutputStream(response.bodyOutputStream);
       var writeData =
         {
           run: function()
           {
@@ -3762,23 +3760,23 @@ Response.prototype =
       // happening asynchronously with respect to the actual writing of data to
       // bodyOutputStream, as they currently do; if they happened synchronously,
       // an event which ran before this one could write more data to the
       // response body before we get around to canceling the copier. We have
       // tests for this in test_seizepower.js, however, and I can't think of a
       // way to handle both cases without removing bodyOutputStream access and
       // moving its effective write(data, length) method onto Response, which
       // would be slower and require more code than this anyway.
-      gThreadManager.currentThread.dispatch({
+      gThreadManager.dispatchToMainThread({
         run: function()
         {
           dumpn("*** canceling copy asynchronously...");
           copier.cancel(Cr.NS_ERROR_UNEXPECTED);
         }
-      }, Ci.nsIThread.DISPATCH_NORMAL);
+      });
     }
     else
     {
       this.end();
     }
   },
 
   /**
@@ -4517,17 +4515,17 @@ WriteThroughCopier.prototype =
           {
             NS_ASSERT(false,
                       "how are we throwing an exception here? we control " +
                       "all the callers! " + e);
           }
         }
       };
 
-    gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
+    gThreadManager.dispatchToMainThread(event);
   },
 
   /**
 * Kicks off another wait for more data to be available from the input stream.
 */
   _waitToReadData: function()
   {
     dumpn("*** _waitToReadData");
--- a/addon-sdk/source/test/addons/e10s-content/lib/httpd.js
+++ b/addon-sdk/source/test/addons/e10s-content/lib/httpd.js
@@ -452,18 +452,17 @@ nsHttpServer.prototype =
       var stopEvent =
         {
           run: function()
           {
             dumpn("*** _notifyStopped async callback");
             self._notifyStopped();
           }
         };
-      gThreadManager.currentThread
-                    .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL);
+      gThreadManager.dispatchToMainThread(stopEvent);
     }
   },
 
   // NSIHTTPSERVER
 
   //
   // see nsIHttpServer.start
   //
@@ -2691,18 +2690,17 @@ ServerHandler.prototype =
       catch (e)
       {
         fis.close();
         throw e;
       }
 
       let writeMore = function writeMore()
       {
-        gThreadManager.currentThread
-                      .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL);
+        gThreadManager.dispatchToMainThread(writeData);
       }
 
       var input = new BinaryInputStream(fis);
       var output = new BinaryOutputStream(response.bodyOutputStream);
       var writeData =
         {
           run: function()
           {
@@ -3763,23 +3761,23 @@ Response.prototype =
       // happening asynchronously with respect to the actual writing of data to
       // bodyOutputStream, as they currently do; if they happened synchronously,
       // an event which ran before this one could write more data to the
       // response body before we get around to canceling the copier. We have
       // tests for this in test_seizepower.js, however, and I can't think of a
       // way to handle both cases without removing bodyOutputStream access and
       // moving its effective write(data, length) method onto Response, which
       // would be slower and require more code than this anyway.
-      gThreadManager.currentThread.dispatch({
+      gThreadManager.dispatchToMainThread({
         run: function()
         {
           dumpn("*** canceling copy asynchronously...");
           copier.cancel(Cr.NS_ERROR_UNEXPECTED);
         }
-      }, Ci.nsIThread.DISPATCH_NORMAL);
+      });
     }
     else
     {
       this.end();
     }
   },
 
   /**
@@ -4518,17 +4516,17 @@ WriteThroughCopier.prototype =
           {
             NS_ASSERT(false,
                       "how are we throwing an exception here? we control " +
                       "all the callers! " + e);
           }
         }
       };
 
-    gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
+    gThreadManager.dispatchToMainThread(event);
   },
 
   /**
 * Kicks off another wait for more data to be available from the input stream.
 */
   _waitToReadData: function()
   {
     dumpn("*** _waitToReadData");
--- a/addon-sdk/source/test/addons/e10s-remote/remote-module.js
+++ b/addon-sdk/source/test/addons/e10s-remote/remote-module.js
@@ -100,17 +100,17 @@ process.port.on('sdk/test/parentload', (
     message
   )
 });
 
 function listener(event) {
   // Use the raw observer service here since it will be usable even if the
   // loader has unloaded
   let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-  Services.obs.notifyObservers(null, "Test:Reply", "");
+  Services.obs.notifyObservers(null, "Test:Reply");
 }
 
 frames.port.on('sdk/test/registerframesevent', (frame) => {
   frames.addEventListener("Test:Event", listener, true);
 });
 
 frames.port.on('sdk/test/unregisterframesevent', (frame) => {
   frames.removeEventListener("Test:Event", listener, true);
--- a/addon-sdk/source/test/addons/places/lib/httpd.js
+++ b/addon-sdk/source/test/addons/places/lib/httpd.js
@@ -451,18 +451,17 @@ nsHttpServer.prototype =
       var stopEvent =
         {
           run: function()
           {
             dumpn("*** _notifyStopped async callback");
             self._notifyStopped();
           }
         };
-      gThreadManager.currentThread
-                    .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL);
+      gThreadManager.dispatchToMainThread(stopEvent);
     }
   },
 
   // NSIHTTPSERVER
 
   //
   // see nsIHttpServer.start
   //
@@ -2690,18 +2689,17 @@ ServerHandler.prototype =
       catch (e)
       {
         fis.close();
         throw e;
       }
 
       let writeMore = function writeMore()
       {
-        gThreadManager.currentThread
-                      .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL);
+        gThreadManager.dispatchToMainThread(writeData);
       }
 
       var input = new BinaryInputStream(fis);
       var output = new BinaryOutputStream(response.bodyOutputStream);
       var writeData =
         {
           run: function()
           {
@@ -3762,23 +3760,23 @@ Response.prototype =
       // happening asynchronously with respect to the actual writing of data to
       // bodyOutputStream, as they currently do; if they happened synchronously,
       // an event which ran before this one could write more data to the
       // response body before we get around to canceling the copier. We have
       // tests for this in test_seizepower.js, however, and I can't think of a
       // way to handle both cases without removing bodyOutputStream access and
       // moving its effective write(data, length) method onto Response, which
       // would be slower and require more code than this anyway.
-      gThreadManager.currentThread.dispatch({
+      gThreadManager.dispatchToMainThread({
         run: function()
         {
           dumpn("*** canceling copy asynchronously...");
           copier.cancel(Cr.NS_ERROR_UNEXPECTED);
         }
-      }, Ci.nsIThread.DISPATCH_NORMAL);
+      });
     }
     else
     {
       this.end();
     }
   },
 
   /**
@@ -4517,17 +4515,17 @@ WriteThroughCopier.prototype =
           {
             NS_ASSERT(false,
                       "how are we throwing an exception here? we control " +
                       "all the callers! " + e);
           }
         }
       };
 
-    gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
+    gThreadManager.dispatchToMainThread(event);
   },
 
   /**
 * Kicks off another wait for more data to be available from the input stream.
 */
   _waitToReadData: function()
   {
     dumpn("*** _waitToReadData");
--- a/addon-sdk/source/test/addons/remote/remote-module.js
+++ b/addon-sdk/source/test/addons/remote/remote-module.js
@@ -100,17 +100,17 @@ process.port.on('sdk/test/parentload', (
     message
   )
 });
 
 function listener(event) {
   // Use the raw observer service here since it will be usable even if the
   // loader has unloaded
   let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-  Services.obs.notifyObservers(null, "Test:Reply", "");
+  Services.obs.notifyObservers(null, "Test:Reply");
 }
 
 frames.port.on('sdk/test/registerframesevent', (frame) => {
   frames.addEventListener("Test:Event", listener, true);
 });
 
 frames.port.on('sdk/test/unregisterframesevent', (frame) => {
   frames.removeEventListener("Test:Event", listener, true);
--- a/addon-sdk/source/test/leak/leak-utils.js
+++ b/addon-sdk/source/test/leak/leak-utils.js
@@ -35,30 +35,31 @@ function gc() {
 // Execute the given test function and verify that we did not leak windows
 // in the process.  The test function must return a promise or be a generator.
 // If the promise is resolved, or generator completes, with an sdk loader
 // object then it will be unloaded after the memory measurements.
 exports.asyncWindowLeakTest = function*(assert, asyncTestFunc) {
 
   // SelfSupportBackend periodically tries to open windows.  This can
   // mess up our window leak detection below, so turn it off.
-  SelfSupportBackend.uninit();
+  if (SelfSupportBackend._log)
+    SelfSupportBackend.uninit();
 
   // Wait for the browser to finish loading.
   yield Startup.onceInitialized;
 
   // Track windows that are opened in an array of weak references.
   let weakWindows = [];
   function windowObserver(subject, topic) {
     let supportsWeak = subject.QueryInterface(Ci.nsISupportsWeakReference);
     if (supportsWeak) {
       weakWindows.push(Cu.getWeakReference(supportsWeak));
     }
   }
-  Services.obs.addObserver(windowObserver, "domwindowopened", false);
+  Services.obs.addObserver(windowObserver, "domwindowopened");
 
   // Execute the body of the test.
   let testLoader = yield asyncTestFunc(assert);
 
   // Stop tracking new windows and attempt to GC any resources allocated
   // by the test body.
   Services.obs.removeObserver(windowObserver, "domwindowopened");
   yield gc();
--- a/addon-sdk/source/test/lib/httpd.js
+++ b/addon-sdk/source/test/lib/httpd.js
@@ -452,18 +452,17 @@ nsHttpServer.prototype =
       var stopEvent =
         {
           run: function()
           {
             dumpn("*** _notifyStopped async callback");
             self._notifyStopped();
           }
         };
-      gThreadManager.currentThread
-                    .dispatch(stopEvent, Ci.nsIThread.DISPATCH_NORMAL);
+      gThreadManager.dispatchToMainThread(stopEvent);
     }
   },
 
   // NSIHTTPSERVER
 
   //
   // see nsIHttpServer.start
   //
@@ -2691,18 +2690,17 @@ ServerHandler.prototype =
       catch (e)
       {
         fis.close();
         throw e;
       }
 
       let writeMore = function writeMore()
       {
-        gThreadManager.currentThread
-                      .dispatch(writeData, Ci.nsIThread.DISPATCH_NORMAL);
+        gThreadManager.dispatchToMainThread(writeData);
       }
 
       var input = new BinaryInputStream(fis);
       var output = new BinaryOutputStream(response.bodyOutputStream);
       var writeData =
         {
           run: function()
           {
@@ -3763,23 +3761,23 @@ Response.prototype =
       // happening asynchronously with respect to the actual writing of data to
       // bodyOutputStream, as they currently do; if they happened synchronously,
       // an event which ran before this one could write more data to the
       // response body before we get around to canceling the copier. We have
       // tests for this in test_seizepower.js, however, and I can't think of a
       // way to handle both cases without removing bodyOutputStream access and
       // moving its effective write(data, length) method onto Response, which
       // would be slower and require more code than this anyway.
-      gThreadManager.currentThread.dispatch({
+      gThreadManager.dispatchToMainThread({
         run: function()
         {
           dumpn("*** canceling copy asynchronously...");
           copier.cancel(Cr.NS_ERROR_UNEXPECTED);
         }
-      }, Ci.nsIThread.DISPATCH_NORMAL);
+      });
     }
     else
     {
       this.end();
     }
   },
 
   /**
@@ -4518,17 +4516,17 @@ WriteThroughCopier.prototype =
           {
             NS_ASSERT(false,
                       "how are we throwing an exception here? we control " +
                       "all the callers! " + e);
           }
         }
       };
 
-    gThreadManager.currentThread.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
+    gThreadManager.dispatchToMainThread(event);
   },
 
   /**
 * Kicks off another wait for more data to be available from the input stream.
 */
   _waitToReadData: function()
   {
     dumpn("*** _waitToReadData");
--- a/addon-sdk/source/test/test-addon-extras.js
+++ b/addon-sdk/source/test/test-addon-extras.js
@@ -15,16 +15,17 @@ exports["test changing result from addon
     modules: {
       "sdk/self": merge({}, self, {
         data: merge({}, self.data, {url: fixtures.url})
       })
     }
   });
 
   const { Panel } = loader.require("sdk/panel");
+  const { getActiveView } = loader.require("sdk/view/core");
   const { events } = loader.require("sdk/content/sandbox/events");
   const { on } = loader.require("sdk/event/core");
   const { isAddonContent } = loader.require("sdk/content/utils");
 
   var result = 1;
   var extrasVal = {
     test: function() {
       return result;
@@ -43,16 +44,19 @@ exports["test changing result from addon
       assert.pass("content-script-before-inserted done!");
     }
   });
 
   let panel = Panel({
     contentURL: "./test-addon-extras.html"
   });
 
+  // Force the panel view to actually load.
+  getActiveView(panel);
+
   panel.port.once("result1", (result) => {
     assert.equal(result, 1, "result is a number");
     result = true;
     panel.port.emit("get-result");
   });
 
   panel.port.once("result2", (result) => {
     assert.equal(result, true, "result is a boolean");
--- a/addon-sdk/source/test/test-loader.js
+++ b/addon-sdk/source/test/test-loader.js
@@ -414,26 +414,24 @@ exports["test require#resolve"] = functi
   let foundRoot = require.resolve("sdk/tabs").replace(/sdk\/tabs.js$/, "");
   assert.ok(root, foundRoot, "correct resolution root");
 
   assert.equal(foundRoot + "sdk/tabs.js", require.resolve("sdk/tabs"), "correct resolution of sdk module");
   assert.equal(foundRoot + "toolkit/loader.js", require.resolve("toolkit/loader"), "correct resolution of sdk module");
 
   const localLoader = Loader({
     paths: { "foo/bar": "bizzle",
-             "foo/bar2/": "bizzle2",
              // Just to make sure this doesn't match the first entry,
              // let use resolve this module
              "foo/bar-bar": "foo/bar-bar" }
   });
   const localRequire = Require(localLoader, module);
   assert.equal(localRequire.resolve("foo/bar"), "bizzle.js");
   assert.equal(localRequire.resolve("foo/bar/baz"), "bizzle/baz.js");
   assert.equal(localRequire.resolve("foo/bar-bar"), "foo/bar-bar.js");
-  assert.equal(localRequire.resolve("foo/bar2/"), "bizzle2.js");
 };
 
 const modulesURI = require.resolve("toolkit/loader").replace("toolkit/loader.js", "");
 exports["test loading a loader"] = function(assert) {
   const loader = Loader({ paths: { "": modulesURI } });
 
   const require = Require(loader, module);
 
--- a/addon-sdk/source/test/test-native-loader.js
+++ b/addon-sdk/source/test/test-native-loader.js
@@ -105,45 +105,16 @@ for (let variant of variants) {
 
   /*
   // TODO not working in current env
   exports[`test bundle (${variant.description`] = function (assert, done) {
     loadAddon('/native-addons/native-addon-test/')
   };
   */
 
-  exports[`test native Loader with mappings (${variant.description})`] = function (assert, done) {
-    all([
-      getJSON('/fixtures/native-addon-test/expectedmap.json'),
-      getJSON('/fixtures/native-addon-test/package.json')
-    ]).then(([expectedMap, manifest]) => {
-
-      // Override dummy module and point it to `test-math` to see if the
-      // require is pulling from the mapping
-      expectedMap['./index.js']['./dir/dummy'] = './dir/a.js';
-
-      let rootURI = variant.getRootURI('native-addon-test');
-      let loader = Loader({
-        paths: makePaths(rootURI),
-        rootURI: rootURI,
-        manifest: manifest,
-        requireMap: expectedMap,
-        isNative: true
-      });
-
-      let program = main(loader);
-      assert.equal(program.dummyModule, 'dir/a',
-        'The lookup uses the information given in the mapping');
-
-      testLoader(program, assert);
-      unload(loader);
-      done();
-    }).then(null, (reason) => console.error(reason));
-  };
-
   exports[`test native Loader overrides (${variant.description})`] = function*(assert) {
     const expectedKeys = Object.keys(require("sdk/io/fs")).join(", ");
     const manifest = yield getJSON('/fixtures/native-overrides-test/package.json');
     const rootURI = variant.getRootURI('native-overrides-test');
 
     let loader = Loader({
       paths: makePaths(rootURI),
       rootURI: rootURI,
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -44,16 +44,17 @@ function makeEmptyPrivateBrowserWindow(o
       toolbar: true,
       private: true
     }
   });
 }
 
 exports["test Panel"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  const { getActiveView } = require("sdk/view/core");
 
   let panel = Panel({
     contentURL: "about:buildconfig",
     contentScript: "self.postMessage(1); self.on('message', () => self.postMessage(2));",
     onMessage: function (message) {
       assert.equal(this, panel, "The 'this' object is the panel.");
       switch(message) {
         case 1:
@@ -63,56 +64,62 @@ exports["test Panel"] = function(assert,
         case 2:
           assert.pass("The panel posted a message and received a response.");
           panel.destroy();
           done();
           break;
       }
     }
   });
+  getActiveView(panel);
 };
 
 exports["test Panel Emit"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  const { getActiveView } = require("sdk/view/core");
 
   let panel = Panel({
     contentURL: "about:buildconfig",
     contentScript: "self.port.emit('loaded');" +
                    "self.port.on('addon-to-content', " +
                    "             () => self.port.emit('received'));",
   });
   panel.port.on("loaded", function () {
     assert.pass("The panel was loaded and sent a first event.");
     panel.port.emit("addon-to-content");
   });
   panel.port.on("received", function () {
     assert.pass("The panel posted a message and received a response.");
     panel.destroy();
     done();
   });
+  getActiveView(panel);
 };
 
 exports["test Panel Emit Early"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  const { getActiveView } = require("sdk/view/core");
 
   let panel = Panel({
     contentURL: "about:buildconfig",
     contentScript: "self.port.on('addon-to-content', " +
                    "             () => self.port.emit('received'));",
   });
   panel.port.on("received", function () {
     assert.pass("The panel posted a message early and received a response.");
     panel.destroy();
     done();
   });
   panel.port.emit("addon-to-content");
+  getActiveView(panel);
 };
 
 exports["test Show Hide Panel"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  let { getActiveView } = require('sdk/view/core');
 
   let panel = Panel({
     contentScript: "self.postMessage('')",
     contentScriptWhen: "end",
     contentURL: "data:text/html;charset=utf-8,",
     onMessage: function (message) {
       panel.show();
     },
@@ -125,20 +132,22 @@ exports["test Show Hide Panel"] = functi
     onHide: function () {
       assert.pass("The panel was hidden.");
       assert.equal(this, panel, "The 'this' object is the panel.");
       assert.equal(this.isShowing, false, "panel.isShowing == false.");
       panel.destroy();
       done();
     }
   });
+  getActiveView(panel);
 };
 
 exports["test Document Reload"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  const { getActiveView } = require("sdk/view/core");
 
   let url2 = "data:text/html;charset=utf-8,page2";
   let content =
     "<script>" +
     "window.addEventListener('message', function({ data }) {"+
     "  if (data == 'move') window.location = '" + url2 + "';" +
     '}, false);' +
     "</script>";
@@ -161,16 +170,17 @@ exports["test Document Reload"] = functi
       }
       else if (messageCount == 2) {
         assert.equal(message, url2, "Second document too; " + message);
         panel.destroy();
         done();
       }
     }
   });
+  getActiveView(panel);
   assert.pass('Panel was created');
 };
 
 // Test disabled because of bug 910230
 /*
 exports["test Parent Resize Hack"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
 
@@ -222,16 +232,17 @@ exports["test Parent Resize Hack"] = fun
   });
 
   panel.show();
 }
 */
 
 exports["test Resize Panel"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  let { getActiveView } = require('sdk/view/core');
 
   // These tests fail on Linux if the browser window in which the panel
   // is displayed is not active.  And depending on what other tests have run
   // before this one, it might not be (the untitled window in which the test
   // runner executes is often active).  So we make sure the browser window
   // is focused by focusing it before running the tests.  Then, to be the best
   // possible test citizen, we refocus whatever window was focused before we
   // started running these tests.
@@ -267,16 +278,17 @@ exports["test Resize Panel"] = function(
       onHide: function () {
         assert.ok((panel.width == 100) && (panel.height == 100),
           "The panel was resized.");
         if (activeWindow)
           activeWindow.focus();
         done();
       }
     });
+    getActiveView(panel);
   }
 
   if (browserWindow === activeWindow) {
     onFocus();
   }
   else {
     browserWindow.addEventListener("focus", onFocus, true);
     browserWindow.focus();
@@ -447,60 +459,67 @@ exports["test Panel Focus Not Set"] = fu
       done();
     }
   });
   panel.show();
 };
 
 exports["test Panel Text Color"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  let { getActiveView } = require('sdk/view/core');
 
   let html = "<html><head><style>body {color: yellow}</style></head>" +
              "<body><p>Foo</p></body></html>";
   let panel = Panel({
     contentURL: "data:text/html;charset=utf-8," + encodeURI(html),
     contentScript: "self.port.emit('color', " +
                    "window.getComputedStyle(document.body.firstChild, null). " +
                    "       getPropertyValue('color'));"
   });
   panel.port.on("color", function (color) {
     assert.equal(color, "rgb(255, 255, 0)",
       "The panel text color style is preserved when a style exists.");
     panel.destroy();
     done();
   });
+  getActiveView(panel);
 };
 
 // Bug 866333
 exports["test watch event name"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  let { getActiveView } = require('sdk/view/core');
 
   let html = "<html><head><style>body {color: yellow}</style></head>" +
              "<body><p>Foo</p></body></html>";
 
   let panel = Panel({
     contentURL: "data:text/html;charset=utf-8," + encodeURI(html),
     contentScript: "self.port.emit('watch', 'test');"
   });
   panel.port.on("watch", function (msg) {
     assert.equal(msg, "test", 'watch event name works');
     panel.destroy();
     done();
   });
+  getActiveView(panel);
 }
 
 // Bug 696552: Ensure panel.contentURL modification support
 exports["test Change Content URL"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
+  const { getActiveView } = require("sdk/view/core");
 
   let panel = Panel({
     contentURL: "about:blank",
     contentScript: "self.port.emit('ready', document.location.href);"
   });
 
+  getActiveView(panel);
+
   let count = 0;
   panel.port.on("ready", function (location) {
     count++;
     if (count == 1) {
       assert.equal(location, "about:blank");
       assert.equal(panel.contentURL, "about:blank");
       panel.contentURL = "about:buildconfig";
     }
@@ -620,16 +639,18 @@ exports["test ContentScriptOptions Optio
         assert.equal( msg[0], 'undefined', 'functions are stripped from contentScriptOptions' );
         assert.equal( typeof msg[1], 'object', 'object as contentScriptOptions' );
         assert.equal( msg[1].a, true, 'boolean in contentScriptOptions' );
         assert.equal( msg[1].b.join(), '1,2,3', 'array and numbers in contentScriptOptions' );
         assert.equal( msg[1].c, 'string', 'string in contentScriptOptions' );
         done();
       }
     });
+  const { getActiveView } = loader.require("sdk/view/core");
+  getActiveView(panel);
 };
 
 exports["test console.log in Panel"] = function(assert, done) {
   let text = 'console.log() in Panel works!';
   let html = '<script>onload = function log(){\
                 console.log("' + text + '");\
               }</script>';
 
--- a/addon-sdk/source/test/test-system-events.js
+++ b/addon-sdk/source/test/test-system-events.js
@@ -114,17 +114,17 @@ exports["test listeners are GC-ed"] = fu
     assert.equal(receivedFromWeak.length, 1, "weak listener was GC-ed");
     assert.equal(receivedFromStrong.length, 2, "strong listener was invoked");
 
     loader.unload();
     done();
   });
 };
 
-exports["test alive listeners are removed on unload"] = function(assert) {
+exports["test alive listeners are removed on unload"] = function*(assert) {
   let receivedFromWeak = [];
   let receivedFromStrong = [];
   let loader = Loader(module);
   let events = loader.require('sdk/system/events');
 
   let type = 'test-alive-listeners-are-removed';
   const handler = (event) => receivedFromStrong.push(event);
   const weakHandler = (event) => receivedFromWeak.push(event);
@@ -132,16 +132,18 @@ exports["test alive listeners are remove
   events.on(type, handler, true);
   events.on(type, weakHandler);
 
   events.emit(type, { data: 1 });
   assert.equal(receivedFromStrong.length, 1, "strong listener invoked");
   assert.equal(receivedFromWeak.length, 1, "weak listener invoked");
 
   loader.unload();
+  // Give the cleanup code a chance to run.
+  yield Promise.resolve();
   events.emit(type, { data: 2 });
 
   assert.equal(receivedFromWeak.length, 1, "weak listener was removed");
   assert.equal(receivedFromStrong.length, 1, "strong listener was removed");
 };
 
 exports["test handle nsIObserverService notifications"] = function(assert) {
   let ios = Cc['@mozilla.org/network/io-service;1']
@@ -228,17 +230,17 @@ exports["test emit to nsIObserverService
         return;
       timesCalled = timesCalled + 1;
       lastSubject = subject;
       lastData = data;
       lastTopic = topic;
     }
   };
 
-  nsIObserverService.addObserver(nsIObserver, topic, false);
+  nsIObserverService.addObserver(nsIObserver, topic);
 
   events.emit(topic, { subject: uri, data: "some data" });
 
   assert.equal(timesCalled, 1, "emit notifies observers");
   assert.equal(lastTopic, topic, "event type is notification topic");
   assert.equal(lastSubject.wrappedJSObject.object, uri,
                "event.subject is notification subject");
   assert.equal(lastData, "some data", "event.data is notification data");
@@ -253,17 +255,17 @@ exports["test emit to nsIObserverService
   assert.equal(lastData, customData, "event.data is notification data");
 
   nsIObserverService.removeObserver(nsIObserver, topic);
 
   events.emit(topic, { data: "more data" });
 
   assert.equal(timesCalled, 2, "removed observers no longer invoked");
 
-  nsIObserverService.addObserver(nsIObserver, "*", false);
+  nsIObserverService.addObserver(nsIObserver, "*");
 
   events.emit(topic, { data: "data again" });
 
   assert.equal(timesCalled, 3, "emit notifies * observers");
 
   assert.equal(lastTopic, topic, "event.type is notification");
   assert.equal(lastSubject, null,
                "event.subject is notification subject");
--- a/addon-sdk/source/test/test-system-input-output.js
+++ b/addon-sdk/source/test/test-system-input-output.js
@@ -101,17 +101,17 @@ exports["test send messages to nsIObserv
 
   addObserver(observer, topic, false);
 
   send(output, null);
   assert.deepEqual(messages.shift(), { topic: topic, subject: null },
                    "null message received");
 
 
-  const uri = newURI("http://www.foo.com", null, null);
+  const uri = newURI("http://www.foo.com");
   send(output, uri);
 
   assert.deepEqual(messages.shift(), { topic: topic, subject: uri },
                    "message received");
 
 
   function customSubject() {}
   send(output, customSubject);
--- a/b2g/chrome/content/devtools/debugger.js
+++ b/b2g/chrome/content/devtools/debugger.js
@@ -260,17 +260,17 @@ var USBRemoteDebugger = {
       let authenticator = new AuthenticatorType.Server();
       authenticator.allowConnection = RemoteDebugger.allowConnection;
       this._listener = DebuggerServer.createListener();
       this._listener.portOrPath = portOrPath;
       this._listener.authenticator = authenticator;
       this._listener.open();
       // Temporary event, until bug 942756 lands and offers a way to know
       // when the server is up and running.
-      Services.obs.notifyObservers(null, "debugger-server-started", null);
+      Services.obs.notifyObservers(null, "debugger-server-started");
     } catch (e) {
       debug("Unable to start USB debugger server: " + e);
     }
   },
 
   stop: function() {
     if (!this._listener) {
       return;
--- a/b2g/chrome/content/screen.js
+++ b/b2g/chrome/content/screen.js
@@ -219,17 +219,17 @@ function onStart() {
     if (screenOrientation != defaultOrientation) {
       let w = width;
       width = height;
       height = w;
     }
     defaultOrientation = screenOrientation;
 
     queueResize();
-  }, 'simulator-adjust-window-size', false);
+  }, 'simulator-adjust-window-size');
 
   // Queue resize request in order to prevent race and slowdowns
   // by requesting resize multiple times per loop
   let resizeTimeout;
   function queueResize() {
     if (resizeTimeout) {
       clearTimeout(resizeTimeout);
     }
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -217,17 +217,17 @@ var shell = {
     Services.obs.addObserver(function observer(subject, topic, state) {
       let network = subject.QueryInterface(Ci.nsINetworkInfo);
       if (network.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED
           && network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
         shell.submitQueuedCrashes();
 
         Services.obs.removeObserver(observer, topic);
       }
-    }, "network-connection-state-changed", false);
+    }, "network-connection-state-changed");
   },
 
   get homeURL() {
     try {
       let homeSrc = Services.env.get('B2G_HOMESCREEN');
       if (homeSrc)
         return homeSrc;
     } catch (e) {}
@@ -690,17 +690,17 @@ var shell = {
     content.addEventListener('load', this, true);
 
     this.reportCrash(true);
 
     SystemAppProxy.registerFrame(shell.contentBrowser);
 
     this.sendEvent(window, 'ContentStart');
 
-    Services.obs.notifyObservers(null, 'content-start', null);
+    Services.obs.notifyObservers(null, 'content-start');
 
     if (AppConstants.MOZ_GRAPHENE &&
         Services.prefs.getBoolPref("b2g.nativeWindowGeometry.fullscreen")) {
       window.fullScreen = true;
     }
 
     shell.handleCmdLine();
   },
@@ -727,17 +727,17 @@ var shell = {
   // This gets called when window.onload fires on the System app content window,
   // which means things in <html> are parsed and statically referenced <script>s
   // and <script defer>s are loaded and run.
   notifyContentWindowLoaded: function shell_notifyContentWindowLoaded() {
     isGonk && libcutils.property_set('sys.boot_completed', '1');
 
     // This will cause Gonk Widget to remove boot animation from the screen
     // and reveals the page.
-    Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
+    Services.obs.notifyObservers(null, "browser-ui-startup-complete");
 
     SystemAppProxy.setIsLoaded();
   },
 
   // This gets called when the content sends us system-message-listener-ready
   // mozContentEvent, OR when an observer message tell us we should consider
   // the content as ready.
   notifyEventListenerReady: function shell_notifyEventListenerReady() {
@@ -753,32 +753,32 @@ var shell = {
 
     SystemAppProxy.setIsReady();
   }
 };
 
 Services.obs.addObserver(function onFullscreenOriginChange(subject, topic, data) {
   shell.sendChromeEvent({ type: "fullscreenoriginchange",
                           fullscreenorigin: data });
-}, "fullscreen-origin-change", false);
+}, "fullscreen-origin-change");
 
 Services.obs.addObserver(function onBluetoothVolumeChange(subject, topic, data) {
   shell.sendChromeEvent({
     type: "bluetooth-volumeset",
     value: data
   });
-}, 'bluetooth-volume-change', false);
+}, 'bluetooth-volume-change');
 
 Services.obs.addObserver(function(subject, topic, data) {
   shell.sendCustomEvent('mozmemorypressure');
-}, 'memory-pressure', false);
+}, 'memory-pressure');
 
 Services.obs.addObserver(function(subject, topic, data) {
   shell.notifyEventListenerReady();
-}, 'system-message-listener-ready', false);
+}, 'system-message-listener-ready');
 
 var permissionMap = new Map([
   ['unknown', Services.perms.UNKNOWN_ACTION],
   ['allow', Services.perms.ALLOW_ACTION],
   ['deny', Services.perms.DENY_ACTION],
   ['prompt', Services.perms.PROMPT_ACTION],
 ]);
 var permissionMapRev = new Map(Array.from(permissionMap.entries()).reverse());
@@ -792,17 +792,17 @@ var CustomEventManager = {
   },
 
   handleEvent: function custevt_handleEvent(evt) {
     let detail = evt.detail;
     dump('XXX FIXME : Got a mozContentEvent: ' + detail.type + "\n");
 
     switch(detail.type) {
       case 'system-message-listener-ready':
-        Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
+        Services.obs.notifyObservers(null, 'system-message-listener-ready');
         break;
       case 'captive-portal-login-cancel':
         CaptivePortalLoginHelper.handleEvent(detail);
         break;
       case 'inputmethod-update-layouts':
       case 'inputregistry-add':
       case 'inputregistry-remove':
         KeyboardHelper.handleEvent(detail);
@@ -898,24 +898,24 @@ window.addEventListener('ContentStart', 
 
 (function contentCrashTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
       let props = aSubject.QueryInterface(Ci.nsIPropertyBag2);
       if (props.hasKey("abnormal") && props.hasKey("dumpID")) {
         shell.reportCrash(false, props.getProperty("dumpID"));
       }
     },
-    "ipc:content-shutdown", false);
+    "ipc:content-shutdown");
 })();
 
 var CaptivePortalLoginHelper = {
   init: function init() {
-    Services.obs.addObserver(this, 'captive-portal-login', false);
-    Services.obs.addObserver(this, 'captive-portal-login-abort', false);
-    Services.obs.addObserver(this, 'captive-portal-login-success', false);
+    Services.obs.addObserver(this, 'captive-portal-login');
+    Services.obs.addObserver(this, 'captive-portal-login-abort');
+    Services.obs.addObserver(this, 'captive-portal-login-success');
   },
   handleEvent: function handleEvent(detail) {
     Services.captivePortalDetector.cancelLogin(detail.id);
   },
   observe: function observe(subject, topic, data) {
     shell.sendChromeEvent(JSON.parse(data));
   }
 }
@@ -992,54 +992,54 @@ window.addEventListener('ContentStart', 
 
     if (gGeolocationActive != oldState) {
       shell.sendChromeEvent({
         type: 'geolocation-status',
         active: gGeolocationActive,
         prompt: promptWarning
       });
     }
-}, "geolocation-device-events", false);
+}, "geolocation-device-events");
 })();
 
 (function headphonesStatusTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'headphones-status-changed',
       state: aData
     });
-}, "headphones-status-changed", false);
+}, "headphones-status-changed");
 })();
 
 (function audioChannelChangedTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'audio-channel-changed',
       channel: aData
     });
-}, "audio-channel-changed", false);
+}, "audio-channel-changed");
 })();
 
 (function defaultVolumeChannelChangedTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'default-volume-channel-changed',
       channel: aData
     });
-}, "default-volume-channel-changed", false);
+}, "default-volume-channel-changed");
 })();
 
 (function visibleAudioChannelChangedTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'visible-audio-channel-changed',
       channel: aData
     });
     shell.visibleNormalAudioActive = (aData == 'normal');
-}, "visible-audio-channel-changed", false);
+}, "visible-audio-channel-changed");
 })();
 
 (function recordingStatusTracker() {
   // Recording status is tracked per process with following data structure:
   // {<processId>: {<requestURL>: {isApp: <isApp>,
   //                               count: <N>,
   //                               audioCount: <N>,
   //                               videoCount: <N>}}
@@ -1128,35 +1128,35 @@ window.addEventListener('ContentStart', 
         break;
     }
 
     // clean up process record if no page record in it.
     if (Object.keys(gRecordingActiveProcesses[processId]).length == 0) {
       delete gRecordingActiveProcesses[processId];
     }
   };
-  Services.obs.addObserver(recordingHandler, 'recording-device-events', false);
-  Services.obs.addObserver(recordingHandler, 'recording-device-ipc-events', false);
+  Services.obs.addObserver(recordingHandler, 'recording-device-events');
+  Services.obs.addObserver(recordingHandler, 'recording-device-ipc-events');
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     // send additional recording events if content process is being killed
     let processId = aSubject.QueryInterface(Ci.nsIPropertyBag2).get('childID');
     if (gRecordingActiveProcesses.hasOwnProperty(processId)) {
       Services.obs.notifyObservers(aSubject, 'recording-device-ipc-events', 'content-shutdown');
     }
-  }, 'ipc:content-shutdown', false);
+  }, 'ipc:content-shutdown');
 })();
 
 (function volumeStateTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'volume-state-changed',
       active: (aData == 'Shared')
     });
-}, 'volume-state-changed', false);
+}, 'volume-state-changed');
 })();
 
 if (isGonk) {
   // Devices don't have all the same partition size for /cache where we
   // store the http cache.
   (function setHTTPCacheSize() {
     let path = Services.prefs.getCharPref("browser.cache.disk.parent_directory");
     let volumeService = Cc["@mozilla.org/telephony/volume-service;1"]
@@ -1224,22 +1224,22 @@ Services.obs.addObserver(function resetP
       while (enumerator.hasMoreElements()) {
         let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
         if (whitelist.indexOf(file.leafName) == -1) {
           file.remove(true);
         }
       }
     }
   },
-  'profile-before-change-telemetry', false);
+  'profile-before-change-telemetry');
 
   let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
                      .getService(Ci.nsIAppStartup);
   appStartup.quit(Ci.nsIAppStartup.eForceQuit);
-}, 'b2g-reset-profile', false);
+}, 'b2g-reset-profile');
 
 var showInstallScreen;
 
 if (AppConstants.MOZ_GRAPHENE) {
   const restoreWindowGeometry = () => {
     let screenX = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenX");
     let screenY = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenY");
     let width = Services.prefs.getIntPref("b2g.nativeWindowGeometry.width");
--- a/b2g/chrome/content/test/mochitest/RecordingStatusChromeScript.js
+++ b/b2g/chrome/content/test/mochitest/RecordingStatusChromeScript.js
@@ -21,18 +21,18 @@ addMessageListener('init-chrome-event', 
   let type = message.type;
   SystemAppProxy.addEventListener('mozChromeEvent', function(event) {
     let details = event.detail;
     if (details.type === type) {
       sendAsyncMessage('chrome-event', details);
     }
   }, true);
 
-  Services.obs.addObserver(peekChildId, 'recording-device-events', false);
-  Services.obs.addObserver(peekChildId, 'recording-device-ipc-events', false);
+  Services.obs.addObserver(peekChildId, 'recording-device-events');
+  Services.obs.addObserver(peekChildId, 'recording-device-ipc-events');
 });
 
 addMessageListener('fake-content-shutdown', function(message) {
     let props = Cc["@mozilla.org/hash-property-bag;1"]
                   .createInstance(Ci.nsIWritablePropertyBag2);
     if (processId) {
       props.setPropertyAsUint64('childID', processId);
     }
--- a/b2g/components/AlertsHelper.jsm
+++ b/b2g/components/AlertsHelper.jsm
@@ -57,17 +57,17 @@ const kMessages = [
   kMessageAlertNotificationClose
 ];
 
 var AlertsHelper = {
 
   _listeners: {},
 
   init: function() {
-    Services.obs.addObserver(this, "xpcom-shutdown", false);
+    Services.obs.addObserver(this, "xpcom-shutdown");
     for (let message of kMessages) {
       ppmm.addMessageListener(message, this);
     }
     SystemAppProxy.addEventListener(kMozContentNotificationEvent, this);
   },
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
--- a/b2g/components/AlertsService.js
+++ b/b2g/components/AlertsService.js
@@ -39,17 +39,17 @@ const kNotificationSystemMessageName = "
 const kMessageAlertNotificationSend  = "alert-notification-send";
 const kMessageAlertNotificationClose = "alert-notification-close";
 
 const kTopicAlertShow          = "alertshow";
 const kTopicAlertFinished      = "alertfinished";
 const kTopicAlertClickCallback = "alertclickcallback";
 
 function AlertsService() {
-  Services.obs.addObserver(this, "xpcom-shutdown", false);
+  Services.obs.addObserver(this, "xpcom-shutdown");
 }
 
 AlertsService.prototype = {
   classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService,
                                          Ci.nsIObserver]),
 
   observe: function(aSubject, aTopic, aData) {
--- a/b2g/components/ErrorPage.jsm
+++ b/b2g/components/ErrorPage.jsm
@@ -45,19 +45,19 @@ SSLExceptions.prototype = {
   /**
    * To collect the SSL status we intercept the certificate error here
    * and store the status for later use.
    */
   notifyCertProblem: function SSLE_notifyCertProblem(aSocketInfo,
                                                      aSslStatus,
                                                      aTargetHost) {
     this._sslStatus = aSslStatus.QueryInterface(Ci.nsISSLStatus);
-    Services.tm.currentThread.dispatch({
+    Services.tm.dispatchToMainThread({
       run: this._addOverride.bind(this)
-    }, Ci.nsIThread.DISPATCH_NORMAL);
+    });
     return true; // suppress error UI
   },
 
   /**
    * Attempt to download the certificate for the location specified to get
    * the SSLState for the certificate and the errors.
    */
   _checkCert: function SSLE_checkCert() {
@@ -165,18 +165,18 @@ var ErrorPage = {
 
     frameElement.addEventListener('mozbrowsererror',
                                   injectErrorPageScript,
                                   true // use capture
                                  );
   },
 
   init: function errorPageInit() {
-    Services.obs.addObserver(this, 'inprocess-browser-shown', false);
-    Services.obs.addObserver(this, 'remote-browser-shown', false);
+    Services.obs.addObserver(this, 'inprocess-browser-shown');
+    Services.obs.addObserver(this, 'remote-browser-shown');
   },
 
   observe: function errorPageObserve(aSubject, aTopic, aData) {
     let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
     // Ignore notifications that aren't from a Browser
     if (!frameLoader.ownerIsMozBrowserFrame) {
       return;
     }
--- a/b2g/components/Frames.jsm
+++ b/b2g/components/Frames.jsm
@@ -15,19 +15,19 @@ Cu.import('resource://gre/modules/System
 const listeners = [];
 
 const Observer = {
   // Save a map of (MessageManager => Frame) to be able to dispatch
   // the FrameDestroyed event with a frame reference.
   _frames: new Map(),
 
   start: function () {
-    Services.obs.addObserver(this, 'remote-browser-shown', false);
-    Services.obs.addObserver(this, 'inprocess-browser-shown', false);
-    Services.obs.addObserver(this, 'message-manager-close', false);
+    Services.obs.addObserver(this, 'remote-browser-shown');
+    Services.obs.addObserver(this, 'inprocess-browser-shown');
+    Services.obs.addObserver(this, 'message-manager-close');
 
     SystemAppProxy.getFrames().forEach(frame => {
       let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
       this._frames.set(mm, frame);
     });
   },
 
   stop: function () {
--- a/b2g/components/FxAccountsMgmtService.jsm
+++ b/b2g/components/FxAccountsMgmtService.jsm
@@ -43,19 +43,19 @@ this.FxAccountsMgmtService = {
   _onReject: function(aMsgId, aReason) {
     SystemAppProxy._sendCustomEvent("mozFxAccountsChromeEvent", {
       id: aMsgId,
       error: aReason ? aReason : null
     });
   },
 
   init: function() {
-    Services.obs.addObserver(this, ONLOGIN_NOTIFICATION, false);
-    Services.obs.addObserver(this, ONVERIFIED_NOTIFICATION, false);
-    Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION, false);
+    Services.obs.addObserver(this, ONLOGIN_NOTIFICATION);
+    Services.obs.addObserver(this, ONVERIFIED_NOTIFICATION);
+    Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION);
     SystemAppProxy.addEventListener("mozFxAccountsContentEvent",
                                     FxAccountsMgmtService);
   },
 
   observe: function(aSubject, aTopic, aData) {
     log.debug("Observed " + aTopic);
     switch (aTopic) {
       case ONLOGIN_NOTIFICATION:
--- a/b2g/components/GlobalSimulatorScreen.jsm
+++ b/b2g/components/GlobalSimulatorScreen.jsm
@@ -66,22 +66,22 @@ this.GlobalSimulatorScreen = {
     }
 
     // If the actual orientation changed,
     // we have to fire mozorientation DOM events
     if (this.mozOrientation != orientation) {
       this.mozOrientation = orientation;
 
       // Notify each app screen object to fire the event
-      Services.obs.notifyObservers(null, 'simulator-orientation-change', null);
+      Services.obs.notifyObservers(null, 'simulator-orientation-change');
     }
 
     // Finally, in any case, we update the window size and orientation
     // (Use wrappedJSObject trick to be able to pass a raw JS object)
-    Services.obs.notifyObservers({wrappedJSObject:this}, 'simulator-adjust-window-size', null);
+    Services.obs.notifyObservers({wrappedJSObject:this}, 'simulator-adjust-window-size');
   },
 
   flipScreen: function() {
     if (this.screenOrientation == 'portrait') {
       this.screenOrientation = 'landscape';
     } else if (this.screenOrientation == 'landscape') {
       this.screenOrientation = 'portrait';
     }
--- a/b2g/components/LogShake.jsm
+++ b/b2g/components/LogShake.jsm
@@ -150,17 +150,17 @@ var LogShake = {
     }});
 
     // Reset excitement to clear residual motion
     this.excitement = 0;
 
     SystemAppProxy.addEventListener(CAPTURE_LOGS_CONTENT_EVENT, this);
     SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this);
 
-    Services.obs.addObserver(this, "xpcom-shutdown", false);
+    Services.obs.addObserver(this, "xpcom-shutdown");
   },
 
   /**
    * Handle an arbitrary event, passing it along to the proper function
    */
   handleEvent: function(event) {
     switch (event.type) {
     case DEVICE_MOTION_EVENT:
--- a/b2g/components/ProcessGlobal.js
+++ b/b2g/components/ProcessGlobal.js
@@ -155,17 +155,17 @@ ProcessGlobal.prototype = {
     );
 
     log("cleanupAfterWipe end.");
   },
 
   observe: function pg_observe(subject, topic, data) {
     switch (topic) {
     case 'app-startup': {
-      Services.obs.addObserver(this, 'console-api-log-event', false);
+      Services.obs.addObserver(this, 'console-api-log-event');
       let inParent = Cc["@mozilla.org/xre/app-info;1"]
                        .getService(Ci.nsIXULRuntime)
                        .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
       if (inParent) {
         Services.ppmm.addMessageListener("getProfD", function(message) {
           return Services.dirsvc.get("ProfD", Ci.nsIFile).path;
         });
 
--- a/b2g/components/SafeMode.jsm
+++ b/b2g/components/SafeMode.jsm
@@ -45,17 +45,17 @@ this.SafeMode = {
     return new Promise((aResolve, aReject) => {
       let observer = function(aSubject, aTopic, aData) {
         if (Services.prefs.getCharPref(kSafeModePref)) {
           Services.prefs.removeObserver(kSafeModePref, observer);
           aResolve();
         }
       }
 
-      Services.prefs.addObserver(kSafeModePref, observer, false);
+      Services.prefs.addObserver(kSafeModePref, observer);
     });
   },
 
   // Resolves once the user has decided how to start.
   // Note that all the actions happen here, so there is no other action from
   // consumers than to go on.
   _waitForUser: function() {
     debug("waitForUser");
@@ -119,17 +119,17 @@ this.SafeMode = {
 
       function notifyContentStart() {
         let window = SafeMode.window;
         window.shell.sendEvent(window, "SafeModeStart");
         contentBrowser.setVisible(true);
 
         // browser-ui-startup-complete is used by the AppShell to stop the
         // boot animation and start gecko rendering.
-        Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
+        Services.obs.notifyObservers(null, "browser-ui-startup-complete");
         content.addEventListener("mozContentEvent", handleEvent, true);
       }
 
       contentBrowser.addEventListener("mozbrowserloadstart", handleEvent, true);
       contentBrowser.src = url;
     });
   },
 
--- a/b2g/components/SignInToWebsite.jsm
+++ b/b2g/components/SignInToWebsite.jsm
@@ -127,18 +127,18 @@ function sendChromeEvent(details) {
 }
 
 function Pipe() {
   this._watchers = [];
 }
 
 Pipe.prototype = {
   init: function pipe_init() {
-    Services.obs.addObserver(this, "identity-child-process-shutdown", false);
-    Services.obs.addObserver(this, "identity-controller-unwatch", false);
+    Services.obs.addObserver(this, "identity-child-process-shutdown");
+    Services.obs.addObserver(this, "identity-controller-unwatch");
   },
 
   uninit: function pipe_uninit() {
     Services.obs.removeObserver(this, "identity-child-process-shutdown");
     Services.obs.removeObserver(this, "identity-controller-unwatch");
   },
 
   observe: function Pipe_observe(aSubject, aTopic, aData) {
@@ -324,19 +324,19 @@ this.SignInToWebsiteController = {
 
   /*
    * Initialize the controller.  To use a different content communication pipe,
    * such as when mocking it in tests, pass aOptions.pipe.
    */
   init: function SignInToWebsiteController_init(aOptions) {
     aOptions = aOptions || {};
     this.pipe = aOptions.pipe || new Pipe();
-    Services.obs.addObserver(this, "identity-controller-watch", false);
-    Services.obs.addObserver(this, "identity-controller-request", false);
-    Services.obs.addObserver(this, "identity-controller-logout", false);
+    Services.obs.addObserver(this, "identity-controller-watch");
+    Services.obs.addObserver(this, "identity-controller-request");
+    Services.obs.addObserver(this, "identity-controller-logout");
   },
 
   uninit: function SignInToWebsiteController_uninit() {
     Services.obs.removeObserver(this, "identity-controller-watch");
     Services.obs.removeObserver(this, "identity-controller-request");
     Services.obs.removeObserver(this, "identity-controller-logout");
   },
 
--- a/b2g/components/SimulatorScreen.js
+++ b/b2g/components/SimulatorScreen.js
@@ -74,19 +74,19 @@ SimulatorScreen.prototype = {
   QueryInterface:  XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference]),
   _windows: new Map(),
 
   observe: function (subject, topic, data) {
     let windows = this._windows;
     switch (topic) {
       case 'profile-after-change':
-        Services.obs.addObserver(this, 'document-element-inserted', false);
-        Services.obs.addObserver(this, 'simulator-orientation-change', false);
-        Services.obs.addObserver(this, 'inner-window-destroyed', false);
+        Services.obs.addObserver(this, 'document-element-inserted');
+        Services.obs.addObserver(this, 'simulator-orientation-change');
+        Services.obs.addObserver(this, 'inner-window-destroyed');
         break;
 
       case 'document-element-inserted':
         let window = subject.defaultView;
         if (!window) {
           return;
         }
 
--- a/b2g/components/test/unit/head_identity.js
+++ b/b2g/components/test/unit/head_identity.js
@@ -126,17 +126,17 @@ function makeObserver(aObserveTopic, aOb
     observe: function (aSubject, aTopic, aData) {
       if (aTopic == aObserveTopic) {
         Services.obs.removeObserver(observer, aObserveTopic);
         aObserveFunc(aSubject, aTopic, aData);
       }
     }
   };
 
-  Services.obs.addObserver(observer, aObserveTopic, false);
+  Services.obs.addObserver(observer, aObserveTopic);
 }
 
 // a hook to set up the ID service with an identity with keypair and all
 // when ready, invoke callback with the identity.  It's there if we need it.
 function setup_test_identity(identity, cert, cb) {
   cb();
 }
 
--- a/b2g/components/test/unit/test_aboutserviceworkers.js
+++ b/b2g/components/test/unit/test_aboutserviceworkers.js
@@ -22,25 +22,25 @@ const ORIGINAL_SENDERROR = AboutServiceW
 
 do_get_profile();
 
 var mockSendResult = (aId, aResult) => {
   let msg = {
     id: aId,
     result: aResult
   };
-  Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG, null);
+  Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG);
 };
 
 var mockSendError = (aId, aError) => {
   let msg = {
     id: aId,
     result: aError
   };
-  Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG, null);
+  Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG);
 };
 
 function attachMocks() {
   AboutServiceWorkers.sendResult = mockSendResult;
   AboutServiceWorkers.sendError = mockSendError;
 }
 
 function restoreMocks() {
@@ -99,17 +99,17 @@ function run_test() {
                   expected.result.registrations.length,
                   "Registrations length should be the expected one");
 
       Services.obs.removeObserver(onMessage, CHROME_MSG);
 
       run_next_test();
     }
 
-    Services.obs.addObserver(onMessage, CHROME_MSG, false);
+    Services.obs.addObserver(onMessage, CHROME_MSG);
 
     attachMocks();
 
     AboutServiceWorkers.handleEvent({ detail: {
       id: id,
       name: "init"
     }});
   });
--- a/b2g/components/test/unit/test_fxaccounts.js
+++ b/b2g/components/test/unit/test_fxaccounts.js
@@ -27,17 +27,17 @@ do_register_cleanup(function() {
   Services.prefs.clearUserPref("identity.fxaccounts.skipDeviceRegistration");
 });
 
 // Make profile available so that fxaccounts can store user data
 do_get_profile();
 
 // Mock the system app proxy; make message passing possible
 var mockSendCustomEvent = function(aEventName, aMsg) {
-  Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName, null);
+  Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName);
 };
 
 function run_test() {
   run_next_test();
 }
 
 add_task(function test_overall() {
   // FxA device registration throws from this context
@@ -146,17 +146,17 @@ add_test(function test_invalidEmailCase_
 
       // We should not receive any other mozFxAccountsChromeEvent messages
       default:
         do_throw("wat!");
         break;
     }
   }
 
-  Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent", false);
+  Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent");
 
   SystemAppProxy._sendCustomEvent = mockSendCustomEvent;
 
   // Trigger signIn using an email with incorrect capitalization
   FxAccountsMgmtService.handleEvent({
     detail: {
       id: "signIn",
       data: {
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -58,16 +58,19 @@ pref("extensions.update.autoUpdateDefaul
 pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
 pref("extensions.hotfix.cert.checkAttributes", true);
 pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
 pref("extensions.hotfix.certs.2.sha1Fingerprint", "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60");
 
 // Check AUS for system add-on updates.
 pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
 
+// Disable screenshots for now, Shield will enable this.
+pref("extensions.screenshots.system-disabled", true);
+
 // Disable add-ons that are not installed by the user in all scopes by default.
 // See the SCOPE constants in AddonManager.jsm for values to use here.
 pref("extensions.autoDisableScopes", 15);
 
 // Add-on content security policies.
 pref("extensions.webextensions.base-content-security-policy", "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; object-src 'self' https://* moz-extension: blob: filesystem:;");
 pref("extensions.webextensions.default-content-security-policy", "script-src 'self'; object-src 'self';");
 
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -383,17 +383,17 @@ appUpdater.prototype =
           } else if (status == "downloading") {
             // We've fallen back to downloading the full update because the
             // partial update failed to get staged in the background.
             // Therefore we need to keep our observer.
             self.setupDownloadingUI();
             return;
           }
           Services.obs.removeObserver(arguments.callee, "update-staged");
-        }, "update-staged", false);
+        }, "update-staged");
       } else {
         this.selectPanel("apply");
       }
       break;
     default:
       this.removeDownloadListener();
       this.selectPanel("downloadFailed");
       break;
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -494,17 +494,17 @@ function initObservers() {
       return;
     }
 
     // must be onverified - we want to open preferences.
     openPrefs();
   }
 
   for (let topic of OBSERVER_TOPICS) {
-    Services.obs.addObserver(observe, topic, false);
+    Services.obs.addObserver(observe, topic);
   }
   window.addEventListener("unload", function(event) {
     log("about:accounts unloading")
     for (let topic of OBSERVER_TOPICS) {
       Services.obs.removeObserver(observe, topic);
     }
   });
 }
--- a/browser/base/content/browser-captivePortal.js
+++ b/browser/base/content/browser-captivePortal.js
@@ -44,19 +44,19 @@ var CaptivePortalWatcher = {
 
   get _browserBundle() {
     delete this._browserBundle;
     return this._browserBundle =
       Services.strings.createBundle("chrome://browser/locale/browser.properties");
   },
 
   init() {
-    Services.obs.addObserver(this, "captive-portal-login", false);
-    Services.obs.addObserver(this, "captive-portal-login-abort", false);
-    Services.obs.addObserver(this, "captive-portal-login-success", false);
+    Services.obs.addObserver(this, "captive-portal-login");
+    Services.obs.addObserver(this, "captive-portal-login-abort");
+    Services.obs.addObserver(this, "captive-portal-login-success");
 
     if (cps.state == cps.LOCKED_PORTAL) {
       // A captive portal has already been detected.
       this._captivePortalDetected();
 
       // Automatically open a captive portal tab if there's no other browser window.
       let windows = Services.wm.getEnumerator("navigator:browser");
       if (windows.getNext() == window && !windows.hasMoreElements()) {
@@ -100,17 +100,17 @@ var CaptivePortalWatcher = {
 
     let win = RecentWindow.getMostRecentBrowserWindow();
     // If no browser window has focus, open and show the tab when we regain focus.
     // This is so that if a different application was focused, when the user
     // (re-)focuses a browser window, we open the tab immediately in that window
     // so they can log in before continuing to browse.
     if (win != Services.ww.activeWindow) {
       this._delayedCaptivePortalDetectedInProgress = true;
-      Services.obs.addObserver(this, "xul-window-visible", false);
+      Services.obs.addObserver(this, "xul-window-visible");
     }
 
     this._showNotification();
   },
 
   /**
    * Called after we regain focus if we detect a portal while a browser window
    * doesn't have focus. Triggers a portal recheck to reaffirm state, and adds
@@ -150,17 +150,17 @@ var CaptivePortalWatcher = {
       }
 
       if (time <= self.PORTAL_RECHECK_DELAY_MS) {
         // The amount of time elapsed since we requested a recheck (i.e. since
         // the browser window was focused) was small enough that we can add and
         // focus a tab with the login page with no noticeable delay.
         self.ensureCaptivePortalTab();
       }
-    }, "captive-portal-check-complete", false);
+    }, "captive-portal-check-complete");
   },
 
   _captivePortalGone() {
     if (this._delayedCaptivePortalDetectedInProgress) {
       Services.obs.removeObserver(this, "xul-window-visible");
       this._delayedCaptivePortalDetectedInProgress = false;
     }
 
@@ -246,12 +246,12 @@ var CaptivePortalWatcher = {
       Services.obs.removeObserver(tabCloser, "captive-portal-login-abort");
       Services.obs.removeObserver(tabCloser, "captive-portal-login-success");
       if (!tab || tab.closing || !tab.parentNode || !tab.linkedBrowser ||
           !tab.linkedBrowser.currentURI.equalsExceptRef(canonicalURI)) {
         return;
       }
       gBrowser.removeTab(tab);
     }
-    Services.obs.addObserver(tabCloser, "captive-portal-login-abort", false);
-    Services.obs.addObserver(tabCloser, "captive-portal-login-success", false);
+    Services.obs.addObserver(tabCloser, "captive-portal-login-abort");
+    Services.obs.addObserver(tabCloser, "captive-portal-login-success");
   },
 };
--- a/browser/base/content/browser-compacttheme.js
+++ b/browser/base/content/browser-compacttheme.js
@@ -19,17 +19,17 @@ var CompactTheme = {
     let theme = LightweightThemeManager.currentTheme;
     return theme && (
            theme.id == "firefox-compact-dark@mozilla.org" ||
            theme.id == "firefox-compact-light@mozilla.org");
   },
 
   init() {
     this.initialized = true;
-    Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
+    Services.obs.addObserver(this, "lightweight-theme-styling-update");
 
     if (this.isThemeCurrentlyApplied) {
       this._toggleStyleSheet(true);
     }
   },
 
   createStyleSheet() {
     let styleSheetAttr = `href="${this.styleSheetLocation}" type="text/css"`;
--- a/browser/base/content/browser-data-submission-info-bar.js
+++ b/browser/base/content/browser-data-submission-info-bar.js
@@ -80,17 +80,17 @@ var gDataNotificationInfoBar = {
     this._notificationBox.appendNotification(
       message,
       this._DATA_REPORTING_NOTIFICATION,
       null,
       this._notificationBox.PRIORITY_INFO_HIGH,
       buttons,
       event => {
         if (event == "removed") {
-          Services.obs.notifyObservers(null, "datareporting:notify-data-policy:close", null);
+          Services.obs.notifyObservers(null, "datareporting:notify-data-policy:close");
         }
       }
     );
     // It is important to defer calling onUserNotifyComplete() until we're
     // actually sure the notification was displayed. If we ever called
     // onUserNotifyComplete() without showing anything to the user, that
     // would be very good for user choice. It may also have legal impact.
     request.onUserNotifyComplete();
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -388,17 +388,17 @@ var FullScreen = {
         }
         break;
       }
       case "DOMFullscreen:Exit": {
         this._windowUtils.remoteFrameFullscreenReverted();
         break;
       }
       case "DOMFullscreen:Painted": {
-        Services.obs.notifyObservers(window, "fullscreen-painted", "");
+        Services.obs.notifyObservers(window, "fullscreen-painted");
         TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
         break;
       }
     }
   },
 
   enterDomFullscreen(aBrowser) {
 
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -282,17 +282,17 @@ var FullZoom = {
    * @return A promise which resolves when the zoom reset has been applied.
    */
   reset: function FullZoom_reset(browser = gBrowser.selectedBrowser) {
     let token = this._getBrowserToken(browser);
     let result = this._getGlobalValue(browser).then(value => {
       if (token.isCurrent) {
         ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value);
         this._ignorePendingZoomAccesses(browser);
-        Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", "");
+        Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset");
       }
     });
     this._removePref(browser);
     return result;
   },
 
   /**
    * Set the zoom level for a given browser.
@@ -350,17 +350,17 @@ var FullZoom = {
 
   /**
    * Saves the zoom level of the page in the given browser to the content
    * prefs store.
    *
    * @param browser  The zoom of this browser will be saved.  Required.
    */
   _applyZoomToPref: function FullZoom__applyZoomToPref(browser) {
-    Services.obs.notifyObservers(browser, "browser-fullZoom:zoomChange", "");
+    Services.obs.notifyObservers(browser, "browser-fullZoom:zoomChange");
     if (!this.siteSpecific ||
         gInPrintPreviewMode ||
         browser.isSyntheticDocument)
       return;
 
     this._cps2.set(browser.currentURI.spec, this.name,
                    ZoomManager.getZoomForBrowser(browser),
                    this._loadContextFromBrowser(browser), {
@@ -371,17 +371,17 @@ var FullZoom = {
   },
 
   /**
    * Removes from the content prefs store the zoom level of the given browser.
    *
    * @param browser  The zoom of this browser will be removed.  Required.
    */
   _removePref: function FullZoom__removePref(browser) {
-    Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", "");
+    Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset");
     if (browser.isSyntheticDocument)
       return;
     let ctxt = this._loadContextFromBrowser(browser);
     this._cps2.removeByDomainAndName(browser.currentURI.spec, this.name, ctxt, {
       handleCompletion: function() {
         this._isNextContentPrefChangeInternal = true;
       }.bind(this),
     });
@@ -509,18 +509,18 @@ var FullZoom = {
   /**
    * Asynchronously broadcasts "browser-fullZoom:location-change" so that
    * listeners can be notified when the zoom levels on those pages change.
    * The notification is always asynchronous so that observers are guaranteed a
    * consistent behavior.
    */
   _notifyOnLocationChange: function FullZoom__notifyOnLocationChange(browser) {
     this._executeSoon(function() {
-      Services.obs.notifyObservers(browser, "browser-fullZoom:location-change", "");
+      Services.obs.notifyObservers(browser, "browser-fullZoom:location-change");
     });
   },
 
   _executeSoon: function FullZoom__executeSoon(callback) {
     if (!callback)
       return;
-    Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
+    Services.tm.dispatchToMainThread(callback);
   },
 };
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -110,17 +110,17 @@ var gFxAccounts = {
 
   init() {
     // Bail out if we're already initialized and for pop-up windows.
     if (this._initialized || !window.toolbar.visible) {
       return;
     }
 
     for (let topic of this.topics) {
-      Services.obs.addObserver(this, topic, false);
+      Services.obs.addObserver(this, topic);
     }
 
     gNavToolbox.addEventListener("customizationstarting", this);
     gNavToolbox.addEventListener("customizationending", this);
 
     EnsureFxAccountsWebChannel();
     this._initialized = true;
 
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1480,17 +1480,17 @@ var BookmarkingUI = {
         this._recentlyBookmarkedObserver = null;
         if (placesContextMenu) {
           placesContextMenu.removeEventListener("popupshowing", onPlacesContextMenuShowing);
         }
         bookmarksMenu.removeEventListener("popuphidden", onBookmarksMenuHidden);
       }
     };
 
-    Services.prefs.addObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
+    Services.prefs.addObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver);
     PlacesUtils.bookmarks.addObserver(this._recentlyBookmarkedObserver, true);
 
     // The context menu doesn't exist in non-browser windows on Mac
     if (placesContextMenu) {
       placesContextMenu.addEventListener("popupshowing", onPlacesContextMenuShowing);
     }
 
     bookmarksMenu.addEventListener("popuphidden", onBookmarksMenuHidden);
@@ -2009,17 +2009,17 @@ var BookmarkingUI = {
 
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsINavBookmarkObserver
   ])
 };
 
 var AutoShowBookmarksToolbar = {
   init() {
-    Services.obs.addObserver(this, "autoshow-bookmarks-toolbar", false);
+    Services.obs.addObserver(this, "autoshow-bookmarks-toolbar");
   },
 
   uninit() {
     Services.obs.removeObserver(this, "autoshow-bookmarks-toolbar");
   },
 
   observe(subject, topic, data) {
     let toolbar = document.getElementById("PersonalToolbar");
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -35,17 +35,17 @@ SocialUI = {
   init: function SocialUI_init() {
     if (this._initialized) {
       return;
     }
     let mm = window.getGroupMessageManager("social");
     mm.loadFrameScript("chrome://browser/content/content.js", true);
     mm.loadFrameScript("chrome://browser/content/social-content.js", true);
 
-    Services.obs.addObserver(this, "social:providers-changed", false);
+    Services.obs.addObserver(this, "social:providers-changed");
 
     CustomizableUI.addListener(this);
     SocialActivationListener.init();
 
     Social.init().then((update) => {
       if (update)
         this._providersChanged();
     });
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -231,17 +231,17 @@ var gSyncUI = {
   // Commands
   // doSync forces a sync - it *does not* return a promise as it is called
   // via the various UI components.
   doSync() {
     this._needsSetup().then(needsSetup => {
       if (!needsSetup) {
         setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0);
       }
-      Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
+      Services.obs.notifyObservers(null, "cloudsync:user-sync");
     }).catch(err => {
       this.log.error("Failed to force a sync", err);
     });
   },
 
   // Handle clicking the toolbar button - which either opens the Sync setup
   // pages or forces a sync now. Does *not* return a promise as it is called
   // via the UI.
--- a/browser/base/content/browser-tabsintitlebar.js
+++ b/browser/base/content/browser-tabsintitlebar.js
@@ -7,17 +7,17 @@
 // this one on platforms which don't have CAN_DRAW_IN_TITLEBAR defined.
 
 var TabsInTitlebar = {
   init() {
     if (this._initialized) {
       return;
     }
     this._readPref();
-    Services.prefs.addObserver(this._prefName, this, false);
+    Services.prefs.addObserver(this._prefName, this);
 
     // We need to update the appearance of the titlebar when the menu changes
     // from the active to the inactive state. We can't, however, rely on
     // DOMMenuBarInactive, because the menu fires this event and then removes
     // the inactive attribute after an event-loop spin.
     //
     // Because updating the appearance involves sampling the heights and margins
     // of various elements, it's important that the layout be more or less
--- a/browser/base/content/browser-thumbnails.js
+++ b/browser/base/content/browser-thumbnails.js
@@ -31,17 +31,17 @@ var gBrowserThumbnails = {
   /**
    * List of tab events we want to listen for.
    */
   _tabEvents: ["TabClose", "TabSelect"],
 
   init: function Thumbnails_init() {
     PageThumbs.addExpirationFilter(this);
     gBrowser.addTabsProgressListener(this);
-    Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
+    Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this);
 
     this._sslDiskCacheEnabled =
       Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
 
     this._tabEvents.forEach(function(aEvent) {
       gBrowser.tabContainer.addEventListener(aEvent, this);
     }, this);
 
--- a/browser/base/content/browser-trackingprotection.js
+++ b/browser/base/content/browser-trackingprotection.js
@@ -17,18 +17,18 @@ var TrackingProtection = {
 
   init() {
     let $ = selector => document.querySelector(selector);
     this.container = $("#tracking-protection-container");
     this.content = $("#tracking-protection-content");
     this.icon = $("#tracking-protection-icon");
 
     this.updateEnabled();
-    Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this, false);
-    Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this, false);
+    Services.prefs.addObserver(this.PREF_ENABLED_GLOBALLY, this);
+    Services.prefs.addObserver(this.PREF_ENABLED_IN_PRIVATE_WINDOWS, this);
 
     this.activeTooltipText =
       gNavigatorBundle.getString("trackingProtection.icon.activeTooltip");
     this.disabledTooltipText =
       gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip");
 
     this.enabledHistogramAdd(this.enabledGlobally);
     this.disabledPBMHistogramAdd(!this.enabledInPrivateWindows);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1083,18 +1083,17 @@ function RedirectLoad({ target: browser,
     let delayedStartupFinished = (subject, topic) => {
       if (topic == "browser-delayed-startup-finished" &&
           subject == window) {
         Services.obs.removeObserver(delayedStartupFinished, topic);
         LoadInOtherProcess(browser, data.loadOptions, data.historyIndex);
       }
     };
     Services.obs.addObserver(delayedStartupFinished,
-                             "browser-delayed-startup-finished",
-                             false);
+                             "browser-delayed-startup-finished");
   }
 }
 
 addEventListener("DOMContentLoaded", function onDCL() {
   removeEventListener("DOMContentLoaded", onDCL);
 
   // There are some windows, like macBrowserOverlay.xul, that
   // load browser.js, but never load tabbrowser.xml. We can ignore
@@ -1129,17 +1128,17 @@ addEventListener("DOMContentLoaded", fun
 });
 
 var gBrowserInit = {
   delayedStartupFinished: false,
 
   onLoad() {
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver);
 
-    Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed", false);
+    Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
 
     // These routines add message listeners. They must run before
     // loading the frame script to ensure that we don't miss any
     // message sent between when the frame script is loaded and when
     // the listener is registered.
     DOMLinkHandler.init();
@@ -1184,17 +1183,17 @@ var gBrowserInit = {
     gHistorySwipeAnimation.init();
 
     SidebarUI.init();
 
     // Certain kinds of automigration rely on this notification to complete
     // their tasks BEFORE the browser window is shown. SessionStore uses it to
     // restore tabs into windows AFTER important parts like gMultiProcessBrowser
     // have been initialized.
-    Services.obs.notifyObservers(window, "browser-window-before-show", "");
+    Services.obs.notifyObservers(window, "browser-window-before-show");
 
     let isResistFingerprintingEnabled = gPrefService.getBoolPref("privacy.resistFingerprinting");
 
     // Set a sane starting width/height for all resolutions on new profiles.
     if (isResistFingerprintingEnabled) {
       // When the fingerprinting resistance is enabled, making sure that we don't
       // have a maximum window to interfere with generating rounded window dimensions.
       document.documentElement.setAttribute("sizemode", "normal");
@@ -1367,26 +1366,26 @@ var gBrowserInit = {
         // Such callers expect that window.arguments[0] is handled as a single URI.
         loadOneOrMoreURIs(uriToLoad);
       }
     }
 
     // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
     setTimeout(function() { SafeBrowsing.init(); }, 2000);
 
-    Services.obs.addObserver(gIdentityHandler, "perm-changed", false);
-    Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
-    Services.obs.addObserver(gStoragePressureObserver, "QuotaManager::StoragePressure", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-origin-blocked", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-confirmation", false);
-    Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
+    Services.obs.addObserver(gIdentityHandler, "perm-changed");
+    Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history");
+    Services.obs.addObserver(gStoragePressureObserver, "QuotaManager::StoragePressure");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-started");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-origin-blocked");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-failed");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-confirmation");
+    Services.obs.addObserver(gXPInstallObserver, "addon-install-complete");
     window.messageManager.addMessageListener("Browser:URIFixup", gKeywordURIFixup);
 
     BrowserOffline.init();
     IndexedDBPromptHelper.init();
 
     if (AppConstants.E10S_TESTING_ONLY)
       gRemoteTabsUI.init();
 
@@ -1420,17 +1419,17 @@ var gBrowserInit = {
     }
 
     // Enable/Disable auto-hide tabbar
     gBrowser.tabContainer.updateVisibility();
 
     BookmarkingUI.init();
     AutoShowBookmarksToolbar.init();
 
-    gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false);
+    gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton);
 
     var homeButton = document.getElementById("home-button");
     gHomeButton.updateTooltip(homeButton);
 
     let safeMode = document.getElementById("helpSafeMode");
     if (Services.appinfo.inSafeMode) {
       safeMode.label = safeMode.getAttribute("stoplabel");
       safeMode.accesskey = safeMode.getAttribute("stopaccesskey");
@@ -1452,17 +1451,17 @@ var gBrowserInit = {
 
     let NP = {};
     Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
     NP.trackBrowserWindow(window);
 
     PlacesToolbarHelper.init();
 
     ctrlTab.readPref();
-    gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false);
+    gPrefService.addObserver(ctrlTab.prefName, ctrlTab);
 
     // Initialize the download manager some time after the app starts so that
     // auto-resume downloads begin (such as after crashing or quitting with
     // active downloads) and speeds up the first-load of the download manager UI.
     // If the user manually opens the download manager before the timeout, the
     // downloads will start right away, and initializing again won't hurt.
     setTimeout(function() {
       try {
@@ -1602,17 +1601,17 @@ var gBrowserInit = {
         if (panel.state == "open") {
           panel.hidePopup();
         }
       }
     });
 
     this.delayedStartupFinished = true;
 
-    Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "");
+    Services.obs.notifyObservers(window, "browser-delayed-startup-finished");
     TelemetryTimestamps.add("delayedStartupFinished");
   },
 
   // Returns the URI(s) to load at startup.
   _getUriToLoad() {
     // window.arguments[0]: URI to load (string), or an nsIArray of
     //                      nsISupportsStrings to load, or a xul:tab of
     //                      a tabbrowser, which will be replaced by this
@@ -2763,17 +2762,17 @@ var gMenuButtonUpdateBadge = {
 
   get badgeWaitTime() {
     return Services.prefs.getIntPref("app.update.badgeWaitTime", 4 * 24 * 3600); // 4 days
   },
 
   init() {
     if (this.enabled) {
       this.kTopics.forEach(t => {
-        Services.obs.addObserver(this, t, false);
+        Services.obs.addObserver(this, t);
       });
     }
   },
 
   uninit() {
     if (this.enabled) {
       this.kTopics.forEach(t => {
         Services.obs.removeObserver(this, t);
@@ -2985,18 +2984,18 @@ var BrowserOnClick = {
     mm.addMessageListener("Browser:SiteBlockedError", this);
     mm.addMessageListener("Browser:EnableOnlineMode", this);
     mm.addMessageListener("Browser:SendSSLErrorReport", this);
     mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
     mm.addMessageListener("Browser:ResetSSLPreferences", this);
     mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
     mm.addMessageListener("Browser:SSLErrorGoBack", this);
 
-    Services.obs.addObserver(this, "captive-portal-login-abort", false);
-    Services.obs.addObserver(this, "captive-portal-login-success", false);
+    Services.obs.addObserver(this, "captive-portal-login-abort");
+    Services.obs.addObserver(this, "captive-portal-login-success");
   },
 
   uninit() {
     let mm = window.messageManager;
     mm.removeMessageListener("Browser:CertExceptionError", this);
     mm.removeMessageListener("Browser:SiteBlockedError", this);
     mm.removeMessageListener("Browser:EnableOnlineMode", this);
     mm.removeMessageListener("Browser:SendSSLErrorReport", this);
@@ -3814,17 +3813,17 @@ const BrowserSearch = {
         var observer = function(subject, topic, data) {
           if (subject == win) {
             BrowserSearch.webSearch();
             Services.obs.removeObserver(observer, "browser-delayed-startup-finished");
           }
         }
         win = window.openDialog(getBrowserURL(), "_blank",
                                 "chrome,all,dialog=no", "about:blank");
-        Services.obs.addObserver(observer, "browser-delayed-startup-finished", false);
+        Services.obs.addObserver(observer, "browser-delayed-startup-finished");
       }
       return;
     }
 
     let focusUrlBarIfSearchFieldIsNotActive = function(aSearchBar) {
       if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) {
         focusAndSelectUrlBar();
       }
@@ -4192,18 +4191,18 @@ function OpenBrowserWindow(options) {
     if (subject == win) {
       Services.obs.removeObserver(newDocumentShown, "document-shown");
       Services.obs.removeObserver(windowClosed, "domwindowclosed");
     }
   }
 
   // Make sure to remove the 'document-shown' observer in case the window
   // is being closed right after it was opened to avoid leaking.
-  Services.obs.addObserver(newDocumentShown, "document-shown", false);
-  Services.obs.addObserver(windowClosed, "domwindowclosed", false);
+  Services.obs.addObserver(newDocumentShown, "document-shown");
+  Services.obs.addObserver(windowClosed, "domwindowclosed");
 
   var charsetArg = new String();
   var handler = Components.classes["@mozilla.org/browser/clh;1"]
                           .getService(Components.interfaces.nsIBrowserHandler);
   var defaultArgs = handler.defaultArgs;
   var wintype = document.documentElement.getAttribute("windowtype");
 
   var extraFeatures = "";
@@ -5412,17 +5411,17 @@ function setToolbarVisibility(toolbar, i
   if (isVisible)
     ToolbarIconColor.inferFromText();
 }
 
 var TabletModeUpdater = {
   init() {
     if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
       this.update(WindowsUIUtils.inTabletMode);
-      Services.obs.addObserver(this, "tablet-mode-change", false);
+      Services.obs.addObserver(this, "tablet-mode-change");
     }
   },
 
   uninit() {
     if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
       Services.obs.removeObserver(this, "tablet-mode-change");
     }
   },
@@ -6118,17 +6117,17 @@ var LanguageDetectionListener = {
 var BrowserOffline = {
   _inited: false,
 
   // BrowserOffline Public Methods
   init() {
     if (!this._uiElement)
       this._uiElement = document.getElementById("workOfflineMenuitemState");
 
-    Services.obs.addObserver(this, "network:offline-status-changed", false);
+    Services.obs.addObserver(this, "network:offline-status-changed");
 
     this._updateOfflineUI(Services.io.offline);
 
     this._inited = true;
   },
 
   uninit() {
     if (this._inited) {
@@ -6156,17 +6155,17 @@ var BrowserOffline = {
     // which we ignore by updating the UI to the current value of io.offline
     this._updateOfflineUI(Services.io.offline);
   },
 
   // BrowserOffline Implementation Methods
   _canGoOffline() {
     try {
       var cancelGoOffline = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
-      Services.obs.notifyObservers(cancelGoOffline, "offline-requested", null);
+      Services.obs.notifyObservers(cancelGoOffline, "offline-requested");
 
       // Something aborted the quit process.
       if (cancelGoOffline.data)
         return false;
     } catch (ex) {
     }
 
     return true;
@@ -6347,17 +6346,17 @@ var OfflineApps = {
 var IndexedDBPromptHelper = {
   _permissionsPrompt: "indexedDB-permissions-prompt",
   _permissionsResponse: "indexedDB-permissions-response",
 
   _notificationIcon: "indexedDB-notification-icon",
 
   init:
   function IndexedDBPromptHelper_init() {
-    Services.obs.addObserver(this, this._permissionsPrompt, false);
+    Services.obs.addObserver(this, this._permissionsPrompt);
   },
 
   uninit:
   function IndexedDBPromptHelper_uninit() {
     Services.obs.removeObserver(this, this._permissionsPrompt);
   },
 
   observe:
@@ -6485,36 +6484,35 @@ function warnAboutClosingWindow() {
     }
   }
 
   if (isPBWindow && !otherPBWindowExists) {
     let exitingCanceled = Cc["@mozilla.org/supports-PRBool;1"].
                           createInstance(Ci.nsISupportsPRBool);
     exitingCanceled.data = false;
     Services.obs.notifyObservers(exitingCanceled,
-                                 "last-pb-context-exiting",
-                                 null);
+                                 "last-pb-context-exiting");
     if (exitingCanceled.data)
       return false;
   }
 
   if (nonPopupPresent) {
     return isPBWindow || gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL);
   }
 
   let os = Services.obs;
 
   let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].
                         createInstance(Ci.nsISupportsPRBool);
   os.notifyObservers(closingCanceled,
-                     "browser-lastwindow-close-requested", null);
+                     "browser-lastwindow-close-requested");
   if (closingCanceled.data)
     return false;
 
-  os.notifyObservers(null, "browser-lastwindow-close-granted", null);
+  os.notifyObservers(null, "browser-lastwindow-close-granted");
 
   // OS X doesn't quit the application when the last window is closed, but keeps
   // the session alive. Hence don't prompt users to save tabs, but warn about
   // closing multiple tabs.
   return AppConstants.platform != "macosx"
          || (isPBWindow || gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL));
 }
 
@@ -6561,18 +6559,18 @@ function BrowserOpenAddonsMgr(aView) {
                                .rootTreeItem
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIDOMWindow);
       if (!emWindow || browserWin == window /* favor the current window */) {
         emWindow = aSubject;
         browserWindow = browserWin;
       }
     }
-    Services.obs.addObserver(receivePong, "EM-pong", false);
-    Services.obs.notifyObservers(null, "EM-ping", "");
+    Services.obs.addObserver(receivePong, "EM-pong");
+    Services.obs.notifyObservers(null, "EM-ping");
     Services.obs.removeObserver(receivePong, "EM-pong");
 
     if (emWindow) {
       if (aView) {
         emWindow.loadView(aView);
       }
       browserWindow.gBrowser.selectedTab =
         browserWindow.gBrowser._getTabForContentWindow(emWindow);
@@ -6591,17 +6589,17 @@ function BrowserOpenAddonsMgr(aView) {
     Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
       Services.obs.removeObserver(observer, aTopic);
       if (aView) {
         aSubject.loadView(aView);
       }
       aSubject.QueryInterface(Ci.nsIDOMWindow);
       aSubject.focus();
       resolve(aSubject);
-    }, "EM-loaded", false);
+    }, "EM-loaded");
   });
 }
 
 function AddKeywordForSearchField() {
   let mm = gBrowser.selectedBrowser.messageManager;
 
   let onMessage = (message) => {
     mm.removeMessageListener("ContextMenu:SearchFieldBookmarkData:Result", onMessage);
@@ -8125,17 +8123,17 @@ function safeModeRestart() {
 
     if (cancelQuit.data)
       return;
 
     Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
     return;
   }
 
-  Services.obs.notifyObservers(null, "restart-in-safe-mode", "");
+  Services.obs.notifyObservers(null, "restart-in-safe-mode");
 }
 
 /* duplicateTabIn duplicates tab in a place specified by the parameter |where|.
  *
  * |where| can be:
  *  "tab"         new tab
  *  "tabshifted"  same as "tab" but in background if default is to select new
  *                tabs, and vice versa
@@ -8154,18 +8152,17 @@ function duplicateTabIn(aTab, where, del
           let otherGBrowser = otherWin.gBrowser;
           let otherTab = otherGBrowser.selectedTab;
           SessionStore.duplicateTab(otherWin, aTab, delta);
           otherGBrowser.removeTab(otherTab, { animate: false });
         }
       };
 
       Services.obs.addObserver(delayedStartupFinished,
-                               "browser-delayed-startup-finished",
-                               false);
+                               "browser-delayed-startup-finished");
       break;
     case "tabshifted":
       SessionStore.duplicateTab(window, aTab, delta);
       // A background tab has been opened, nothing else to do here.
       break;
     case "tab":
       let newTab = SessionStore.duplicateTab(window, aTab, delta);
       gBrowser.selectedTab = newTab;
@@ -8256,17 +8253,17 @@ var MousePosTracker = {
 };
 
 var ToolbarIconColor = {
   init() {
     this._initialized = true;
 
     window.addEventListener("activate", this);
     window.addEventListener("deactivate", this);
-    Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
+    Services.obs.addObserver(this, "lightweight-theme-styling-update");
 
     // If the window isn't active now, we assume that it has never been active
     // before and will soon become active such that inferFromText will be
     // called from the initial activate event.
     if (Services.focus.activeWindow == window)
       this.inferFromText();
   },
 
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -108,17 +108,17 @@ var handleContentContextMenu = function(
     return;
 
   let addonInfo = {};
   let subject = {
     event,
     addonInfo,
   };
   subject.wrappedJSObject = subject;
-  Services.obs.notifyObservers(subject, "content-contextmenu", null);
+  Services.obs.notifyObservers(subject, "content-contextmenu");
 
   let doc = event.target.ownerDocument;
   let docLocation = doc.mozDocumentURIIfNotForErrorPages;
   docLocation = docLocation && docLocation.spec;
   let charSet = doc.characterSet;
   let baseURI = doc.baseURI;
   let referrer = doc.referrer;
   let referrerPolicy = doc.referrerPolicy;
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -62,17 +62,17 @@ nsContextMenu.prototype = {
         srcUrl: this.mediaURL,
         frameUrl: gContextMenuContentData ? gContextMenuContentData.docLocation : undefined,
         pageUrl: this.browser ? this.browser.currentURI.spec : undefined,
         linkUrl: this.linkURL,
         selectionText: this.isTextSelected ? this.selectionInfo.text : undefined,
         frameId: this.frameOuterWindowID,
       };
       subject.wrappedJSObject = subject;
-      Services.obs.notifyObservers(subject, "on-build-contextmenu", null);
+      Services.obs.notifyObservers(subject, "on-build-contextmenu");
     }
 
     this.isFrameImage = document.getElementById("isFrameImage");
     this.ellipsis = "\u2026";
     try {
       this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -331,17 +331,17 @@ function onLoadPageInfo() {
   // init media view
   var imageTree = document.getElementById("imagetree");
   imageTree.view = gImageView;
 
   /* Select the requested tab, if the name is specified */
   loadTab(args);
   Components.classes["@mozilla.org/observer-service;1"]
             .getService(Components.interfaces.nsIObserverService)
-            .notifyObservers(window, "page-info-dialog-loaded", null);
+            .notifyObservers(window, "page-info-dialog-loaded");
 }
 
 function loadPageInfo(frameOuterWindowID, imageElement, browser) {
   browser = browser || window.opener.gBrowser.selectedBrowser;
   let mm = browser.messageManager;
 
   gStrings["application/rss+xml"]  = gBundle.getString("feedRss");
   gStrings["application/atom+xml"] = gBundle.getString("feedAtom");
@@ -594,17 +594,17 @@ function addImage(imageViewRow) {
       }
     });
 
     // Add the observer, only once.
     if (gImageView.data.length == 1) {
       document.getElementById("mediaTab").hidden = false;
       Components.classes["@mozilla.org/observer-service;1"]
                 .getService(Components.interfaces.nsIObserverService)
-                .addObserver(imagePermissionObserver, "perm-changed", false);
+                .addObserver(imagePermissionObserver, "perm-changed");
     }
   } else {
     var i = gImageHash[url][type][alt];
     gImageView.data[i][COL_IMAGE_COUNT]++;
     // The same image can occur several times on the page at different sizes.
     // If the "View Image Info" context menu item was used, ensure we select
     // the correct element.
     if (!gImageView.data[i][COL_IMAGE_BG] &&
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -42,17 +42,17 @@ function onLoadPermission(uri, principal
     gPermPrincipal = principal;
     var hostText = document.getElementById("hostText");
     hostText.value = gPermURI.prePath;
 
     for (var i of gPermissions)
       initRow(i);
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
-    os.addObserver(permissionObserver, "perm-changed", false);
+    os.addObserver(permissionObserver, "perm-changed");
     onUnloadRegistry.push(onUnloadPermission);
     permTab.hidden = false;
   } else
     permTab.hidden = true;
 }
 
 function onUnloadPermission() {
   var os = Components.classes["@mozilla.org/observer-service;1"]
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -83,17 +83,17 @@ Sanitizer.prototype = {
           fetchState: () => ({ progress })
         }
       );
     }
 
     try {
       yield promise;
     } finally {
-      Services.obs.notifyObservers(null, "sanitizer-sanitization-complete", "");
+      Services.obs.notifyObservers(null, "sanitizer-sanitization-complete");
     }
   }),
 
   _sanitize: Task.async(function*(aItemsToClear, progress = {}) {
     let seenError = false;
     let itemsToClear;
     if (Array.isArray(aItemsToClear)) {
       // Shallow copy the array, as we are going to modify
@@ -432,17 +432,17 @@ Sanitizer.prototype = {
 
         try {
           // clear all auth tokens
           let sdr = Components.classes["@mozilla.org/security/sdr;1"]
                               .getService(Components.interfaces.nsISecretDecoderRing);
           sdr.logoutAndTeardown();
 
           // clear FTP and plain HTTP auth sessions
-          Services.obs.notifyObservers(null, "net:clear-active-logins", null);
+          Services.obs.notifyObservers(null, "net:clear-active-logins");
         } finally {
           TelemetryStopwatch.finish("FX_SANITIZE_SESSIONS", refObj);
         }
       })
     },
 
     siteSettings: {
       clear: Task.async(function* (range) {
@@ -622,18 +622,18 @@ Sanitizer.prototype = {
               Services.obs.removeObserver(onWindowClosed, "xul-window-destroyed");
               // If we're the last thing to happen, invoke callback.
               if (newWindowOpened) {
                 TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS", refObj);
                 resolve();
               }
             }
           }
-          Services.obs.addObserver(onWindowOpened, "browser-delayed-startup-finished", false);
-          Services.obs.addObserver(onWindowClosed, "xul-window-destroyed", false);
+          Services.obs.addObserver(onWindowOpened, "browser-delayed-startup-finished");
+          Services.obs.addObserver(onWindowClosed, "xul-window-destroyed");
         });
 
         // Start the process of closing windows
         while (windowList.length) {
           windowList.pop().close();
         }
         newWindow.focus();
         yield promiseReady;
--- a/browser/base/content/sync/aboutSyncTabs.js
+++ b/browser/base/content/sync/aboutSyncTabs.js
@@ -21,20 +21,20 @@ if (AppConstants.MOZ_SERVICES_CLOUDSYNC)
   XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
                                     "resource://gre/modules/CloudSync.jsm");
 }
 
 var RemoteTabViewer = {
   _tabsList: null,
 
   init() {
-    Services.obs.addObserver(this, "weave:service:login:finish", false);
-    Services.obs.addObserver(this, "weave:engine:sync:finish", false);
+    Services.obs.addObserver(this, "weave:service:login:finish");
+    Services.obs.addObserver(this, "weave:engine:sync:finish");
 
-    Services.obs.addObserver(this, "cloudsync:tabs:update", false);
+    Services.obs.addObserver(this, "cloudsync:tabs:update");
 
     this._tabsList = document.getElementById("tabsList");
 
     this.buildList(true);
   },
 
   uninit() {
     Services.obs.removeObserver(this, "weave:service:login:finish");
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -6,17 +6,16 @@
 /* This content script contains code that requires a tab browser. */
 
 /* eslint-env mozilla/frame-script */
 
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/ExtensionContent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
   "resource:///modules/E10SUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
   "resource://gre/modules/BrowserUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutReader",
@@ -598,17 +597,17 @@ function gKeywordURIFixup(fixupInfo) {
       data[f] = fixupInfo[f].spec;
     } else {
       data[f] = fixupInfo[f];
     }
   }
 
   sendAsyncMessage("Browser:URIFixup", data);
 }
-Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
+Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup");
 addEventListener("unload", () => {
   Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
 }, false);
 
 addMessageListener("Browser:AppTab", function(message) {
   if (docShell) {
     docShell.isAppTab = message.data.isAppTab;
   }
@@ -879,17 +878,17 @@ var RefreshBlocker = {
   // otherwise, null is set as the value of the mapping.
   blockedWindows: new WeakMap(),
 
   init() {
     if (Services.prefs.getBoolPref(this.PREF)) {
       this.enable();
     }
 
-    Services.prefs.addObserver(this.PREF, this, false);
+    Services.prefs.addObserver(this.PREF, this);
   },
 
   uninit() {
     if (Services.prefs.getBoolPref(this.PREF)) {
       this.disable();
     }
 
     Services.prefs.removeObserver(this.PREF, this);
@@ -1040,19 +1039,19 @@ var UserContextIdNotifier = {
     let userContextId = loadContext.originAttributes.userContextId;
 
     sendAsyncMessage("Browser:WindowCreated", { userContextId });
   }
 };
 
 UserContextIdNotifier.init();
 
-ExtensionContent.init(this);
+Services.obs.notifyObservers(this, "tab-content-frameloader-created");
+
 addEventListener("unload", () => {
-  ExtensionContent.uninit(this);
   RefreshBlocker.uninit();
 });
 
 addMessageListener("AllowScriptsToClose", () => {
   content.QueryInterface(Ci.nsIInterfaceRequestor)
          .getInterface(Ci.nsIDOMWindowUtils)
          .allowScriptsToClose();
 });
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -5152,17 +5152,17 @@
         ]]></body>
       </method>
 
       <constructor>
         <![CDATA[
           this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
           this.mCurrentBrowser.permanentKey = {};
 
-          Services.obs.addObserver(this, "contextual-identity-updated", false);
+          Services.obs.addObserver(this, "contextual-identity-updated");
 
           this.mCurrentTab = this.tabContainer.firstChild;
           const nsIEventListenerService =
             Components.interfaces.nsIEventListenerService;
           let els = Components.classes["@mozilla.org/eventlistenerservice;1"]
                               .getService(nsIEventListenerService);
           els.addSystemEventListener(document, "keydown", this, false);
           if (AppConstants.platform == "macosx") {
@@ -5222,17 +5222,17 @@
           }
           messageManager.addMessageListener("DOMWindowFocus", this);
           messageManager.addMessageListener("RefreshBlocker:Blocked", this);
           messageManager.addMessageListener("Browser:WindowCreated", this);
 
           // To correctly handle keypresses for potential FindAsYouType, while
           // the tab's find bar is not yet initialized.
           this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
-          Services.prefs.addObserver("accessibility.typeaheadfind", this, false);
+          Services.prefs.addObserver("accessibility.typeaheadfind", this);
           messageManager.addMessageListener("Findbar:Keypress", this);
 
           // Add listeners for prerender messages
           messageManager.addMessageListener("Prerender:Request", this);
           messageManager.addMessageListener("Prerender:Cancel", this);
           messageManager.addMessageListener("Prerender:Swap", this);
         ]]>
       </constructor>
@@ -5702,17 +5702,17 @@
           tab.label = this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle");
           tab.setAttribute("onerror", "this.removeAttribute('image');");
 
           window.addEventListener("resize", this);
           window.addEventListener("load", this);
 
           this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled", false);
           this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
-          Services.prefs.addObserver("privacy.userContext", this, false);
+          Services.prefs.addObserver("privacy.userContext", this);
           this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
         ]]>
       </constructor>
 
       <destructor>
         <![CDATA[
           Services.prefs.removeObserver("privacy.userContext", this);
         ]]>
--- a/browser/base/content/test/alerts/browser_notification_open_settings.js
+++ b/browser/base/content/test/alerts/browser_notification_open_settings.js
@@ -7,17 +7,17 @@ add_task(function* test_settingsOpen_obs
   yield BrowserTestUtils.withNewTab({
     gBrowser,
     url: "about:robots"
   }, function* dummyTabTask(aBrowser) {
     let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#privacy");
     info("simulate a notifications-open-settings notification");
     let uri = NetUtil.newURI("https://example.com");
     let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-    Services.obs.notifyObservers(principal, "notifications-open-settings", null);
+    Services.obs.notifyObservers(principal, "notifications-open-settings");
     let tab = yield tabPromise;
     ok(tab, "The notification settings tab opened");
     yield BrowserTestUtils.removeTab(tab);
   });
 });
 
 add_task(function* test_settingsOpen_button() {
   let pm = Services.perms;
--- a/browser/base/content/test/alerts/browser_notification_remove_permission.js
+++ b/browser/base/content/test/alerts/browser_notification_remove_permission.js
@@ -35,17 +35,17 @@ function onAlertShowing() {
     ok(true, "Notifications don't use XUL windows on all platforms.");
     closeNotification(tab.linkedBrowser).then(finish);
     return;
   }
   ok(Services.perms.testExactPermission(makeURI(notificationURL), "desktop-notification"),
      "Permission should exist prior to removal");
   let disableForOriginMenuItem = alertWindow.document.getElementById("disableForOriginMenuItem");
   is(disableForOriginMenuItem.localName, "menuitem", "menuitem found");
-  Services.obs.addObserver(permObserver, "perm-changed", false);
+  Services.obs.addObserver(permObserver, "perm-changed");
   alertWindow.addEventListener("beforeunload", onAlertClosing);
   disableForOriginMenuItem.click();
   info("Clicked on disable-for-origin menuitem")
 }
 
 function permObserver(subject, topic, data) {
   if (topic != "perm-changed") {
     return;
--- a/browser/base/content/test/appUpdate/head.js
+++ b/browser/base/content/test/appUpdate/head.js
@@ -236,17 +236,17 @@ function processStep({notificationId, bu
 function waitForEvent(topic, status = null) {
   return new Promise(resolve => Services.obs.addObserver({
     observe(subject, innerTopic, innerStatus) {
       if (!status || status == innerStatus) {
         Services.obs.removeObserver(this, topic);
         resolve(innerStatus);
       }
     }
-  }, topic, false))
+  }, topic))
 }
 
 /**
  * Ensures that the "What's new" link with the provided ID is displayed and
  * matches the url parameter provided. If no URL is provided, it will instead
  * ensure that the link matches the default link URL.
  *
  * @param  id
--- a/browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js
+++ b/browser/base/content/test/captivePortal/browser_captivePortal_certErrorUI.js
@@ -11,17 +11,17 @@ add_task(function* checkCaptivePortalCer
   yield SpecialPowers.pushPrefEnv({
     set: [["captivedetect.canonicalURL", CANONICAL_URL],
           ["captivedetect.canonicalContent", CANONICAL_CONTENT]],
   });
 
   let captivePortalStatePropagated = TestUtils.topicObserved("ipc:network:captive-portal-set-state");
 
   info("Checking that the alternate about:certerror UI is shown when we are behind a captive portal.");
-  Services.obs.notifyObservers(null, "captive-portal-login", null);
+  Services.obs.notifyObservers(null, "captive-portal-login");
 
   info("Waiting for captive portal state to be propagated to the content process.");
   yield captivePortalStatePropagated;
 
   // Open a page with a cert error.
   let browser;
   let certErrorLoaded;
   let errorTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
@@ -62,17 +62,17 @@ add_task(function* checkCaptivePortalCer
   });
 
   let portalTab2 = yield portalTabPromise;
   is(portalTab2, portalTab, "The existing portal tab should be focused.");
 
   let portalTabRemoved = BrowserTestUtils.tabRemoved(portalTab);
   let errorTabReloaded = BrowserTestUtils.waitForErrorPage(browser);
 
-  Services.obs.notifyObservers(null, "captive-portal-login-success", null);
+  Services.obs.notifyObservers(null, "captive-portal-login-success");
   yield portalTabRemoved;
 
   info("Waiting for error tab to be reloaded after the captive portal was freed.");
   yield errorTabReloaded;
   yield ContentTask.spawn(browser, null, () => {
     let doc = content.document;
     ok(!doc.body.classList.contains("captiveportal"),
        "Captive portal error page UI is not visible.");
--- a/browser/base/content/test/captivePortal/head.js
+++ b/browser/base/content/test/captivePortal/head.js
@@ -35,25 +35,25 @@ function* setupPrefsAndRecentWindowBehav
 
   registerCleanupFunction(function* cleanUp() {
     RecentWindow.getMostRecentBrowserWindow = getMostRecentBrowserWindowCopy;
     window.CaptivePortalWatcher.init();
   });
 }
 
 function* portalDetected() {
-  Services.obs.notifyObservers(null, "captive-portal-login", null);
+  Services.obs.notifyObservers(null, "captive-portal-login");
   yield BrowserTestUtils.waitForCondition(() => {
     return cps.state == cps.LOCKED_PORTAL;
   }, "Waiting for Captive Portal Service to update state after portal detected.");
 }
 
 function* freePortal(aSuccess) {
   Services.obs.notifyObservers(null,
-    "captive-portal-login-" + (aSuccess ? "success" : "abort"), null);
+    "captive-portal-login-" + (aSuccess ? "success" : "abort"));
   yield BrowserTestUtils.waitForCondition(() => {
     return cps.state != cps.LOCKED_PORTAL;
   }, "Waiting for Captive Portal Service to update state after portal freed.");
 }
 
 // If a window is provided, it will be focused. Otherwise, a new window
 // will be opened and focused.
 function* focusWindowAndWaitForPortalUI(aLongRecheck, win) {
@@ -71,17 +71,17 @@ function* focusWindowAndWaitForPortalUI(
   }
   yield SimpleTest.promiseFocus(win);
 
   // After a new window is opened, CaptivePortalWatcher asks for a recheck, and
   // waits for it to complete. We need to manually tell it a recheck completed.
   yield BrowserTestUtils.waitForCondition(() => {
     return win.CaptivePortalWatcher._waitingForRecheck;
   }, "Waiting for CaptivePortalWatcher to trigger a recheck.");
-  Services.obs.notifyObservers(null, "captive-portal-check-complete", null);
+  Services.obs.notifyObservers(null, "captive-portal-check-complete");
 
   let notification = ensurePortalNotification(win);
 
   if (aLongRecheck) {
     ensureNoPortalTab(win);
     testShowLoginPageButtonVisibility(notification, "visible");
     return win;
   }
@@ -144,17 +144,17 @@ function ensureNoPortalNotification(win)
  * unfortunate intermittent timing issue, we wait for the notification from
  * the original window every time we close a window that we opened.
  */
 function waitForXulWindowVisible() {
   return new Promise(resolve => {
     Services.obs.addObserver(function observe() {
       Services.obs.removeObserver(observe, "xul-window-visible");
       resolve();
-    }, "xul-window-visible", false);
+    }, "xul-window-visible");
   });
 }
 
 function* closeWindowAndWaitForXulWindowVisible(win) {
   let p = waitForXulWindowVisible();
   yield BrowserTestUtils.closeWindow(win);
   yield p;
 }
--- a/browser/base/content/test/general/browser_aboutHome.js
+++ b/browser/base/content/test/general/browser_aboutHome.js
@@ -255,17 +255,17 @@ add_task(function* () {
         });
 
         Services.search.defaultEngine = currEngine;
         try {
           Services.search.removeEngine(engine);
         } catch (ex) {}
         resolve();
       });
-      Services.obs.addObserver(searchObserver, "browser-search-engine-modified", false);
+      Services.obs.addObserver(searchObserver, "browser-search-engine-modified");
       Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
                                 null, null, false);
     });
   });
 });
 
 add_task(function* () {
   info("Make sure that a page can't imitate about:home");
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -291,17 +291,17 @@ function* test_swapped_browser_while_not
   let AttrChangePromise = BrowserTestUtils.waitForEvent(newTab, "TabAttrModified", false, event => {
     return event.detail.changed.includes("muted");
   });
 
   let AudioPlaybackPromise = new Promise(resolve => {
     let observer = (subject, topic, data) => {
       ok(false, "Should not see an audio-playback notification");
     };
-    Services.obs.addObserver(observer, "audiochannel-activity-normal", false);
+    Services.obs.addObserver(observer, "audiochannel-activity-normal");
     setTimeout(() => {
       Services.obs.removeObserver(observer, "audiochannel-activity-normal");
       resolve();
     }, 100);
   });
 
   gBrowser.swapBrowsersAndCloseOther(newTab, oldTab);
   yield AttrChangePromise;
--- a/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
+++ b/browser/base/content/test/general/browser_beforeunload_duplicate_dialogs.js
@@ -16,17 +16,17 @@ function onTabModalDialogLoaded(node) {
   if (resolveDialogPromise) {
     resolveDialogPromise();
   }
 }
 
 SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
 
 // Listen for the dialog being created
-Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
+Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("browser.tabs.warnOnClose");
   Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
 });
 
 add_task(function* closeLastTabInWindow() {
   let newWin = yield promiseOpenAndLoadWindow({}, true);
   let firstTab = newWin.gBrowser.selectedTab;
--- a/browser/base/content/test/general/browser_bug435325.js
+++ b/browser/base/content/test/general/browser_bug435325.js
@@ -49,17 +49,17 @@ function checkPage(data) {
   // the actual example.com.
   Services.prefs.setIntPref("network.proxy.type", proxyPrefValue);
 
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
                              "online.");
     Services.obs.removeObserver(observer, "network:offline-status-changed");
     finish();
-  }, "network:offline-status-changed", false);
+  }, "network:offline-status-changed");
 
   ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
     content.document.getElementById("errorTryAgain").click();
   });
 }
 
 registerCleanupFunction(function() {
   Services.prefs.setBoolPref("browser.cache.disk.enable", true);
--- a/browser/base/content/test/general/browser_bug553455.js
+++ b/browser/base/content/test/general/browser_bug553455.js
@@ -50,17 +50,17 @@ function waitForProgressNotification(aPa
       Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
         // Ignore the progress notification unless that is the notification we want
         if (notificationId != PROGRESS_NOTIFICATION &&
             aTopic == getObserverTopic(PROGRESS_NOTIFICATION)) {
           return;
         }
         Services.obs.removeObserver(observer, topic);
         resolve();
-      }, topic, false);
+      }, topic);
     });
 
     let panelEventPromise;
     if (aPanelOpen) {
       panelEventPromise = Promise.resolve();
     } else {
       panelEventPromise = new Promise(resolve => {
         PopupNotifications.panel.addEventListener("popupshowing", function() {
@@ -97,17 +97,17 @@ function waitForNotification(aId, aExpec
       Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
         // Ignore the progress notification unless that is the notification we want
         if (aId != PROGRESS_NOTIFICATION &&
             aTopic == getObserverTopic(PROGRESS_NOTIFICATION)) {
           return;
         }
         Services.obs.removeObserver(observer, topic);
         resolve();
-      }, topic, false);
+      }, topic);
     });
 
     let panelEventPromise = new Promise(resolve => {
       PopupNotifications.panel.addEventListener("PanelUpdated", function eventListener(e) {
         // Skip notifications that are not the one that we are supposed to be looking for
         if (e.detail.indexOf(aId) == -1) {
           return;
         }
@@ -502,17 +502,17 @@ function test_sequential() {
     is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
 
     // Wait for the install to complete, we won't see a new confirmation
     // notification
     yield new Promise(resolve => {
       Services.obs.addObserver(function observer() {
         Services.obs.removeObserver(observer, "addon-install-confirmation");
         resolve();
-      }, "addon-install-confirmation", false);
+      }, "addon-install-confirmation");
     });
 
     // Make sure browser-addons.js executes first
     yield new Promise(resolve => executeSoon(resolve));
 
     // Should have dropped the progress notification
     is(PopupNotifications.panel.childNodes.length, 1, "Should be the right number of notifications");
     is(PopupNotifications.panel.childNodes[0].id, "addon-install-confirmation-notification",
@@ -625,17 +625,17 @@ function test_localFile() {
     } catch (ex) {
       path = CHROMEROOT + "corrupt.xpi";
     }
 
     let failPromise = new Promise(resolve => {
       Services.obs.addObserver(function observer() {
         Services.obs.removeObserver(observer, "addon-install-failed");
         resolve();
-      }, "addon-install-failed", false);
+      }, "addon-install-failed");
     });
     gBrowser.selectedTab = gBrowser.addTab("about:blank");
     yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
     gBrowser.loadURI(path);
     yield failPromise;
 
     // Wait for the browser code to add the failure notification
     yield waitForSingleNotification();
@@ -1012,17 +1012,17 @@ function test_failedSecurity() {
     notification = panel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
 
     // Wait for it to fail
     yield new Promise(resolve => {
       Services.obs.addObserver(function observer() {
         Services.obs.removeObserver(observer, "addon-install-failed");
         resolve();
-      }, "addon-install-failed", false);
+      }, "addon-install-failed");
     });
 
     // Allow the browser code to add the failure notification and then wait
     // for the progress notification to dismiss itself
     yield waitForSingleNotification();
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     notification = panel.childNodes[0];
     is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
@@ -1048,19 +1048,19 @@ var XPInstallObserver = {
 add_task(function* () {
   requestLongerTimeout(4);
 
   Services.prefs.setBoolPref("extensions.logging.enabled", true);
   Services.prefs.setBoolPref("extensions.strictCompatibility", true);
   Services.prefs.setBoolPref("extensions.install.requireSecureOrigin", false);
   Services.prefs.setIntPref("security.dialog_enable_delay", 0);
 
-  Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
-  Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
-  Services.obs.addObserver(XPInstallObserver, "addon-install-failed", false);
+  Services.obs.addObserver(XPInstallObserver, "addon-install-started");
+  Services.obs.addObserver(XPInstallObserver, "addon-install-blocked");
+  Services.obs.addObserver(XPInstallObserver, "addon-install-failed");
 
   registerCleanupFunction(function() {
     // Make sure no more test parts run in case we were timed out
     TESTS = [];
 
     AddonManager.getAllInstalls(function(aInstalls) {
       aInstalls.forEach(function(aInstall) {
         aInstall.cancel();
--- a/browser/base/content/test/general/browser_bug561636.js
+++ b/browser/base/content/test/general/browser_bug561636.js
@@ -277,17 +277,17 @@ add_task(function* () {
 
         // Clean-up
         Services.obs.removeObserver(gObserver, "invalidformsubmit");
         gObserver.notifyInvalidSubmit = function() {};
         resolve();
       });
     };
 
-    Services.obs.addObserver(gObserver, "invalidformsubmit", false);
+    Services.obs.addObserver(gObserver, "invalidformsubmit");
 
     executeSoon(function() {
       browser.contentDocument.getElementById("s").click();
     });
   });
 
   yield notifierPromise;
 
--- a/browser/base/content/test/general/browser_contentSearchUI.js
+++ b/browser/base/content/test/general/browser_contentSearchUI.js
@@ -334,17 +334,17 @@ add_task(function* formHistory() {
   checkState(state, "x", ["xfoo", "xbar"], -1);
   // Wait for Satchel to say it's been added to form history.
   let deferred = Promise.defer();
   Services.obs.addObserver(function onAdd(subj, topic, data) {
     if (data == "formhistory-add") {
       Services.obs.removeObserver(onAdd, "satchel-storage-changed");
       executeSoon(() => deferred.resolve());
     }
-  }, "satchel-storage-changed", false);
+  }, "satchel-storage-changed");
   yield Promise.all([msg("addInputValueToFormHistory"), deferred.promise]);
 
   // Reset the input.
   state = yield msg("reset");
   checkState(state, "", [], -1);
 
   // Type an X again.  The form history entry should appear.
   state = yield msg("key", { key: "x", waitForSuggestions: true });
@@ -358,17 +358,17 @@ add_task(function* formHistory() {
 
   // Wait for Satchel.
   deferred = Promise.defer();
   Services.obs.addObserver(function onRemove(subj, topic, data) {
     if (data == "formhistory-remove") {
       Services.obs.removeObserver(onRemove, "satchel-storage-changed");
       executeSoon(() => deferred.resolve());
     }
-  }, "satchel-storage-changed", false);
+  }, "satchel-storage-changed");
 
   state = yield msg("key", "VK_DELETE");
   checkState(state, "x", ["xfoo", "xbar"], -1);
 
   yield deferred.promise;
 
   // Reset the input.
   state = yield msg("reset");
@@ -389,17 +389,17 @@ add_task(function* cycleEngines() {
     let deferred = Promise.defer();
     Services.obs.addObserver(function resolver(subj, topic, data) {
       if (data != "engine-current") {
         return;
       }
       SimpleTest.is(subj.name, newEngineName, "Engine cycled correctly");
       Services.obs.removeObserver(resolver, "browser-search-engine-modified");
       deferred.resolve();
-    }, "browser-search-engine-modified", false);
+    }, "browser-search-engine-modified");
     return deferred.promise;
   }
 
   let p = promiseEngineChange(TEST_ENGINE_PREFIX + " " + TEST_ENGINE_2_BASENAME);
   yield msg("key", { key: "VK_DOWN", modifiers: { accelKey: true }});
   yield p;
 
   p = promiseEngineChange(TEST_ENGINE_PREFIX + " " + TEST_ENGINE_BASENAME);
@@ -603,17 +603,17 @@ add_task(function* search() {
   Services.obs.addObserver(function onRemove(subj, topic, data) {
     if (data == "formhistory-remove") {
       if (--historyCount) {
         return;
       }
       Services.obs.removeObserver(onRemove, "satchel-storage-changed");
       executeSoon(() => deferred.resolve());
     }
-  }, "satchel-storage-changed", false);
+  }, "satchel-storage-changed");
 
   yield msg("key", { key: "x", waitForSuggestions: true });
   yield msg("key", "VK_DOWN");
   yield msg("key", "VK_DOWN");
   yield msg("key", "VK_DELETE");
   yield msg("key", "VK_DOWN");
   yield msg("key", "VK_DELETE");
   yield deferred.promise;
--- a/browser/base/content/test/general/browser_double_close_tab.js
+++ b/browser/base/content/test/general/browser_double_close_tab.js
@@ -6,17 +6,17 @@ SpecialPowers.pushPrefEnv({"set": [["dom
 
 function waitForDialog(callback) {
   function onTabModalDialogLoaded(node) {
     Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
     callback(node);
   }
 
   // Listen for the dialog being created
-  Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
+  Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
 }
 
 function waitForDialogDestroyed(node, callback) {
   // Now listen for the dialog going away again...
   let observer = new MutationObserver(function(muts) {
     if (!node.parentNode) {
       ok(true, "Dialog is gone");
       done();
--- a/browser/base/content/test/general/browser_fxa_web_channel.js
+++ b/browser/base/content/test/general/browser_fxa_web_channel.js
@@ -186,17 +186,17 @@ function makeObserver(aObserveTopic, aOb
       aObserveFunc(aSubject, aTopic, aData);
     }
   };
 
   function removeMe() {
     Services.obs.removeObserver(callback, aObserveTopic);
   }
 
-  Services.obs.addObserver(callback, aObserveTopic, false);
+  Services.obs.addObserver(callback, aObserveTopic);
   return removeMe;
 }
 
 function test() {
   waitForExplicitFinish();
 
   Task.spawn(function* () {
     for (let testCase of gTests) {
--- a/browser/base/content/test/general/browser_fxaccounts.js
+++ b/browser/base/content/test/general/browser_fxaccounts.js
@@ -13,25 +13,25 @@ const TEST_ROOT = "http://example.com/br
 // what it does.
 (function() {
   let unstubs = {}; // The original functions we stub out.
 
   // The stub functions.
   let stubs = {
     updateUI() {
       return unstubs["updateUI"].call(gFxAccounts).then(() => {
-        Services.obs.notifyObservers(null, "test:browser_fxaccounts:updateUI", null);
+        Services.obs.notifyObservers(null, "test:browser_fxaccounts:updateUI");
       });
     },
     // Opening preferences is trickier than it should be as leaks are reported
     // due to the promises it fires off at load time  and there's no clear way to
     // know when they are done.
     // So just ensure openPreferences is called rather than whether it opens.
     openPreferences() {
-      Services.obs.notifyObservers(null, "test:browser_fxaccounts:openPreferences", null);
+      Services.obs.notifyObservers(null, "test:browser_fxaccounts:openPreferences");
     }
   };
 
   for (let name in stubs) {
     unstubs[name] = gFxAccounts[name];
     gFxAccounts[name] = stubs[name];
   }
   // and undo our damage at the end.
@@ -68,17 +68,17 @@ var panelUILabel = document.getElementBy
 var panelUIStatus = document.getElementById("PanelUI-fxa-status");
 var panelUIFooter = document.getElementById("PanelUI-footer-fxa");
 
 // The tests
 add_task(function* test_nouser() {
   let user = yield fxAccounts.getSignedInUser();
   Assert.strictEqual(user, null, "start with no user signed in");
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI");
-  Services.obs.notifyObservers(null, this.FxAccountsCommon.ONLOGOUT_NOTIFICATION, null);
+  Services.obs.notifyObservers(null, this.FxAccountsCommon.ONLOGOUT_NOTIFICATION);
   yield promiseUpdateDone;
 
   // Check the world - the FxA footer area is visible as it is offering a signin.
   Assert.ok(isFooterVisible())
 
   Assert.equal(panelUILabel.getAttribute("label"), panelUIStatus.getAttribute("defaultlabel"));
   Assert.equal(panelUIStatus.getAttribute("tooltiptext"), panelUIStatus.getAttribute("signedinTooltiptext"));
   Assert.ok(!panelUIFooter.hasAttribute("fxastatus"), "no fxsstatus when signed out");
@@ -147,17 +147,17 @@ add_task(function* test_verifiedUserDisp
                panelUIStatus.getAttribute("signedinTooltiptext"));
   Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
   yield signOut();
 });
 
 add_task(function* test_profileNotificationsClearsCache() {
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 1);
   gFxAccounts._cachedProfile = { foo: "bar" };
-  Services.obs.notifyObservers(null, this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION, null);
+  Services.obs.notifyObservers(null, this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION);
   Assert.ok(!gFxAccounts._cachedProfile);
   yield promiseUpdateDone;
 });
 
 add_task(function* test_verifiedUserProfileFailure() {
   // profile failure means only one observer fires.
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 1);
   gFxAccounts._cachedProfile = null;
@@ -195,17 +195,17 @@ function configureProfileURL(profile, re
 function promiseObserver(topic, count = 1) {
   return new Promise(resolve => {
     let obs = (aSubject, aTopic, aData) => {
       if (--count == 0) {
         Services.obs.removeObserver(obs, aTopic);
         resolve(aSubject);
       }
     }
-    Services.obs.addObserver(obs, topic, false);
+    Services.obs.addObserver(obs, topic);
   });
 }
 
 var promiseTabOpen = Task.async(function*(urlBase) {
   info("Waiting for tab to open...");
   let event = yield promiseWaitForEvent(gBrowser.tabContainer, "TabOpen", true);
   let tab = event.target;
   yield promiseTabLoadEvent(tab);
--- a/browser/base/content/test/general/browser_homeDrop.js
+++ b/browser/base/content/test/general/browser_homeDrop.js
@@ -39,17 +39,17 @@ add_task(function*() {
           is(modified, homepage, "homepage is set correctly");
           Services.prefs.removeObserver(HOMEPAGE_PREF, observer);
 
           Services.prefs.setStringPref(HOMEPAGE_PREF, "about:mozilla;");
 
           resolve();
         }
       };
-      Services.prefs.addObserver(HOMEPAGE_PREF, observer, false);
+      Services.prefs.addObserver(HOMEPAGE_PREF, observer);
     });
 
     setHomepageDialog.document.documentElement.acceptDialog();
 
     yield setHomepagePromise;
   }
 
   function dropInvalidURI() {
--- a/browser/base/content/test/general/browser_keywordSearch_postData.js
+++ b/browser/base/content/test/general/browser_keywordSearch_postData.js
@@ -36,17 +36,17 @@ function test() {
     registerCleanupFunction(function() {
       Services.search.removeEngine(engine);
     });
 
     // ready to execute the tests!
     executeSoon(nextTest);
   };
 
-  Services.obs.addObserver(searchObserver, "browser-search-engine-modified", false);
+  Services.obs.addObserver(searchObserver, "browser-search-engine-modified");
 
   registerCleanupFunction(function() {
     gBrowser.removeTab(tab);
 
     Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
   });
 
   Services.search.addEngine("http://test:80/browser/browser/base/content/test/general/POSTSearchEngine.xml",
--- a/browser/base/content/test/general/browser_restore_isAppTab.js
+++ b/browser/base/content/test/general/browser_restore_isAppTab.js
@@ -39,17 +39,17 @@ var CrashObserver = {
       file.append(dumpID + ".dmp");
       file.remove(true);
       file = minidumpDirectory.clone();
       file.append(dumpID + ".extra");
       file.remove(true);
     }
   }
 }
-Services.obs.addObserver(CrashObserver, "ipc:content-shutdown", false);
+Services.obs.addObserver(CrashObserver, "ipc:content-shutdown");
 
 registerCleanupFunction(() => {
   Services.obs.removeObserver(CrashObserver, "ipc:content-shutdown");
 });
 
 function frameScript() {
   addMessageListener("Test:GetIsAppTab", function() {
     sendAsyncMessage("Test:IsAppTab", { isAppTab: docShell.isAppTab });
--- a/browser/base/content/test/general/browser_sanitize-timespans.js
+++ b/browser/base/content/test/general/browser_sanitize-timespans.js
@@ -18,17 +18,17 @@ var Sanitizer = tempScope.Sanitizer;
 var FormHistory = (Components.utils.import("resource://gre/modules/FormHistory.jsm", {})).FormHistory;
 var Downloads = (Components.utils.import("resource://gre/modules/Downloads.jsm", {})).Downloads;
 
 function promiseFormHistoryRemoved() {
   let deferred = Promise.defer();
   Services.obs.addObserver(function onfh() {
     Services.obs.removeObserver(onfh, "satchel-storage-changed");
     deferred.resolve();
-  }, "satchel-storage-changed", false);
+  }, "satchel-storage-changed");
   return deferred.promise;
 }
 
 function promiseDownloadRemoved(list) {
   let deferred = Promise.defer();
 
   let view = {
     onDownloadRemoved(download) {
--- a/browser/base/content/test/general/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_link-perwindowpb.js
@@ -88,17 +88,17 @@ function test() {
     info("whenDelayedStartupFinished");
     Services.obs.addObserver(function obs(aSubject, aTopic) {
       info("whenDelayedStartupFinished, got topic: " + aTopic + ", got subject: " + aSubject + ", waiting for " + aWindow);
       if (aWindow == aSubject) {
         Services.obs.removeObserver(obs, aTopic);
         executeSoon(aCallback);
         info("whenDelayedStartupFinished found our window");
       }
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
   }
 
   mockTransferRegisterer.register();
 
   registerCleanupFunction(function() {
     info("Running the cleanup code");
     mockTransferRegisterer.unregister();
     MockFilePicker.cleanup();
@@ -156,18 +156,18 @@ function test() {
       if (ex.result == Cr.NS_ERROR_NOT_AVAILABLE) {
         info("onModifyRequest caught NOTAVAIL" + ex);
       } else {
         info("ionModifyRequest caught " + ex);
       }
     }
   }
 
-  Services.obs.addObserver(observer, "http-on-modify-request", false);
-  Services.obs.addObserver(observer, "http-on-examine-response", false);
+  Services.obs.addObserver(observer, "http-on-modify-request");
+  Services.obs.addObserver(observer, "http-on-examine-response");
 
   testOnWindow(undefined, function(win) {
     // The first save from a regular window sets a cookie.
     triggerSave(win, function() {
       is(gNumSet, 1, "1 cookie should be set");
 
       // The second save from a private window also sets a cookie.
       testOnWindow({private: true}, function(win2) {
--- a/browser/base/content/test/general/browser_save_link_when_window_navigates.js
+++ b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
@@ -135,17 +135,17 @@ function test() {
     info("whenDelayedStartupFinished");
     Services.obs.addObserver(function observer(aSubject, aTopic) {
       info("whenDelayedStartupFinished, got topic: " + aTopic + ", got subject: " + aSubject + ", waiting for " + aWindow);
       if (aWindow == aSubject) {
         Services.obs.removeObserver(observer, aTopic);
         executeSoon(aCallback);
         info("whenDelayedStartupFinished found our window");
       }
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
   }
 
   mockTransferRegisterer.register();
 
   registerCleanupFunction(function() {
     info("Running the cleanup code");
     mockTransferRegisterer.unregister();
     MockFilePicker.cleanup();
--- a/browser/base/content/test/general/browser_ssl_error_reports.js
+++ b/browser/base/content/test/general/browser_ssl_error_reports.js
@@ -157,17 +157,17 @@ function createReportResponseStatusPromi
     let observer = (subject, topic, data) => {
       subject.QueryInterface(Ci.nsIHttpChannel);
       let requestURI = subject.URI.spec;
       if (requestURI == expectedURI) {
         Services.obs.removeObserver(observer, "http-on-examine-response");
         resolve(subject.responseStatus);
       }
     };
-    Services.obs.addObserver(observer, "http-on-examine-response", false);
+    Services.obs.addObserver(observer, "http-on-examine-response");
   });
 }
 
 function checkErrorPage(browser, suffix) {
   return ContentTask.spawn(browser, { suffix }, function* (args) {
     let uri = content.document.documentURI;
     Assert.ok(uri.startsWith(`about:${args.suffix}`), "correct error page loaded");
   });
--- a/browser/base/content/test/general/browser_syncui.js
+++ b/browser/base/content/test/general/browser_syncui.js
@@ -21,17 +21,17 @@ function notifyAndPromiseUIUpdated(topic
       return oldPromiseUpdateUI().then(() => {
         // Restore our override.
         gSyncUI._promiseUpdateUI = oldPromiseUpdateUI;
         // Resolve the promise so the caller knows the update is done.
         resolve();
       });
     };
     // Now send the notification.
-    Services.obs.notifyObservers(null, topic, null);
+    Services.obs.notifyObservers(null, topic);
   });
 }
 
 // Sync manages 3 broadcasters so the menus correctly reflect the Sync state.
 // Only one of these 3 should ever be visible - pass the ID of the broadcaster
 // you expect to be visible and it will check it's the only one that is.
 function checkBroadcasterVisible(broadcasterId) {
   let all = ["sync-reauth-state", "sync-setup-state", "sync-syncnow-state"];
@@ -43,17 +43,17 @@ function checkBroadcasterVisible(broadca
 }
 
 function promiseObserver(topic) {
   return new Promise(resolve => {
     let obs = (aSubject, aTopic, aData) => {
       Services.obs.removeObserver(obs, aTopic);
       resolve(aSubject);
     }
-    Services.obs.addObserver(obs, topic, false);
+    Services.obs.addObserver(obs, topic);
   });
 }
 
 function checkButtonTooltips(stringPrefix) {
   for (let butId of ["PanelUI-remotetabs-syncnow", "PanelUI-fxa-icon"]) {
     let text = document.getElementById(butId).getAttribute("tooltiptext");
     let desc = `Text is "${text}", expecting it to start with "${stringPrefix}"`
     Assert.ok(text.startsWith(stringPrefix), desc);
@@ -79,17 +79,17 @@ add_task(function* prepare() {
   checkButtonTooltips("Sign In To Sync");
   // mock out the "_needsSetup()" function so we don't short-circuit.
   let oldNeedsSetup = window.gSyncUI._needsSetup;
   window.gSyncUI._needsSetup = () => Promise.resolve(false);
   registerCleanupFunction(() => {
     window.gSyncUI._needsSetup = oldNeedsSetup;
     // and an observer to set the state back to what it should be now we've
     // restored the stub.
-    Services.obs.notifyObservers(null, "weave:service:login:finish", null);
+    Services.obs.notifyObservers(null, "weave:service:login:finish");
   });
   // and a notification to have the state change away from "needs setup"
   yield notifyAndPromiseUIUpdated("weave:service:login:finish");
   checkBroadcasterVisible("sync-syncnow-state");
   // open the sync-button panel so we can check elements in that.
   document.getElementById("sync-button").click();
 });
 
--- a/browser/base/content/test/general/browser_unknownContentType_title.js
+++ b/browser/base/content/test/general/browser_unknownContentType_title.js
@@ -5,17 +5,17 @@ function waitForNewWindow() {
   return new Promise(resolve => {
     let listener = (win) => {
       Services.obs.removeObserver(listener, "toplevel-window-ready");
       win.addEventListener("load", () => {
         resolve(win);
       });
     };
 
-    Services.obs.addObserver(listener, "toplevel-window-ready", false)
+    Services.obs.addObserver(listener, "toplevel-window-ready")
   });
 }
 
 add_task(function*() {
   let tab = gBrowser.selectedTab = gBrowser.addTab(url);
   let browser = tab.linkedBrowser;
   yield promiseTabLoaded(gBrowser.selectedTab);
 
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -53,17 +53,17 @@ function closeAllNotifications() {
 }
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       executeSoon(aCallback);
     }
-  }, "browser-delayed-startup-finished", false);
+  }, "browser-delayed-startup-finished");
 }
 
 function updateTabContextMenu(tab, onOpened) {
   let menu = document.getElementById("tabContextMenu");
   if (!tab)
     tab = gBrowser.selectedTab;
   var evt = new Event("");
   tab.dispatchEvent(evt);
@@ -194,17 +194,17 @@ function pushPrefs(...aPrefs) {
 
 function updateBlocklist(aCallback) {
   var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
                           .getService(Ci.nsITimerCallback);
   var observer = function() {
     Services.obs.removeObserver(observer, "blocklist-updated");
     SimpleTest.executeSoon(aCallback);
   };
-  Services.obs.addObserver(observer, "blocklist-updated", false);
+  Services.obs.addObserver(observer, "blocklist-updated");
   blocklistNotifier.notify(null);
 }
 
 var _originalTestBlocklistURL = null;
 function setAndUpdateBlocklist(aURL, aCallback) {
   if (!_originalTestBlocklistURL)
     _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
   Services.prefs.setCharPref("extensions.blocklist.url", aURL);
@@ -224,17 +224,17 @@ function whenNewWindowLoaded(aOptions, a
 
 function promiseWindowWillBeClosed(win) {
   return new Promise((resolve, reject) => {
     Services.obs.addObserver(function observe(subject, topic) {
       if (subject == win) {
         Services.obs.removeObserver(observe, topic);
         resolve();
       }
-    }, "domwindowclosed", false);
+    }, "domwindowclosed");
   });
 }
 
 function promiseWindowClosed(win) {
   let promise = promiseWindowWillBeClosed(win);
   win.close();
   return promise;
 }
@@ -244,17 +244,17 @@ function promiseOpenAndLoadWindow(aOptio
   let win = OpenBrowserWindow(aOptions);
   if (aWaitForDelayedStartup) {
     Services.obs.addObserver(function onDS(aSubject, aTopic, aData) {
       if (aSubject != win) {
         return;
       }
       Services.obs.removeObserver(onDS, "browser-delayed-startup-finished");
       deferred.resolve(win);
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
 
   } else {
     win.addEventListener("load", function() {
       deferred.resolve(win);
     }, {once: true});
   }
   return deferred.promise;
 }
@@ -501,17 +501,17 @@ var FullZoomHelper = {
     return Promise.resolve();
   },
 
   waitForLocationChange: function waitForLocationChange() {
     return new Promise(resolve => {
       Services.obs.addObserver(function obs(subj, topic, data) {
         Services.obs.removeObserver(obs, topic);
         resolve();
-      }, "browser-fullZoom:location-change", false);
+      }, "browser-fullZoom:location-change");
     });
   },
 
   load: function load(tab, url) {
     return new Promise(resolve => {
       let didLoad = false;
       let didZoom = false;
 
@@ -716,17 +716,17 @@ function promiseNotificationShown(notifi
  * @rejects Never.
  */
 function promiseTopicObserved(aTopic) {
   return new Promise((resolve) => {
     Services.obs.addObserver(
       function PTO_observe(aSubject, aTopic2, aData) {
         Services.obs.removeObserver(PTO_observe, aTopic2);
         resolve({subject: aSubject, data: aData});
-      }, aTopic, false);
+      }, aTopic);
   });
 }
 
 function promiseNewSearchEngine(basename) {
   return new Promise((resolve, reject) => {
     info("Waiting for engine to be added: " + basename);
     let url = getRootDirectory(gTestPath) + basename;
     Services.search.addEngine(url, null, "", false, {
@@ -764,17 +764,17 @@ function promiseOnBookmarkItemAdded(aExp
       onItemChanged() {},
       onItemVisited() {},
       onItemMoved() {},
       QueryInterface: XPCOMUtils.generateQI([
         Ci.nsINavBookmarkObserver,
       ])
     };
     info("Waiting for a bookmark to be added");
-    PlacesUtils.bookmarks.addObserver(bookmarksObserver, false);
+    PlacesUtils.bookmarks.addObserver(bookmarksObserver);
   });
 }
 
 function* loadBadCertPage(url) {
   const EXCEPTION_DIALOG_URI = "chrome://pippki/content/exceptionDialog.xul";
   let exceptionDialogResolved = new Promise(function(resolve) {
     // When the certificate exception dialog has opened, click the button to add
     // an exception.
@@ -788,17 +788,17 @@ function* loadBadCertPage(url) {
             certExceptionDialog.documentElement.getButton("extra1").click();
             resolve();
           });
         }
       }
     };
 
     Services.obs.addObserver(certExceptionDialogObserver,
-                             "cert-exception-ui-ready", false);
+                             "cert-exception-ui-ready");
   });
 
   let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
   yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   yield loaded;
 
   yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
     content.document.getElementById("exceptionDialogButton").click();
--- a/browser/base/content/test/newtab/browser_newtab_background_captures.js
+++ b/browser/base/content/test/newtab/browser_newtab_background_captures.js
@@ -44,17 +44,17 @@ add_task(function* () {
     // Showing the preloaded tab should trigger thumbnail capture.
     Services.obs.addObserver(function onCreate(subj, topic, data) {
       if (data != url)
         return;
       Services.obs.removeObserver(onCreate, "page-thumbnail:create");
       ok(true, "thumbnail created after preloaded tab was shown");
 
       resolve();
-    }, "page-thumbnail:create", false);
+    }, "page-thumbnail:create");
   });
 
   // Enable captures.
   yield pushPrefs([CAPTURE_PREF, false]);
 
   yield thumbnailCreatedPromise;
 
   // Test finished!
--- a/browser/base/content/test/pageinfo/browser_pageInfo.js
+++ b/browser/base/content/test/pageinfo/browser_pageInfo.js
@@ -1,16 +1,16 @@
 function test() {
   waitForExplicitFinish();
 
   var pageInfo;
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
-    Services.obs.addObserver(observer, "page-info-dialog-loaded", false);
+    Services.obs.addObserver(observer, "page-info-dialog-loaded");
     pageInfo = BrowserPageInfo();
   }, {capture: true, once: true});
   content.location =
     "https://example.com/browser/browser/base/content/test/pageinfo/feed_tab.html";
 
   function observer(win, topic, data) {
     Services.obs.removeObserver(observer, "page-info-dialog-loaded");
     pageInfo.onFinished.push(handlePageInfo);
--- a/browser/base/content/test/plugins/browser_pageInfo_plugins.js
+++ b/browser/base/content/test/plugins/browser_pageInfo_plugins.js
@@ -18,17 +18,17 @@ function doOnPageLoad(url, continuation)
 function pageLoad() {
   gTestBrowser.removeEventListener("load", pageLoad);
   // The plugin events are async dispatched and can come after the load event
   // This just allows the events to fire before we then go on to test the states
   executeSoon(gNextTest);
 }
 
 function doOnOpenPageInfo(continuation) {
-  Services.obs.addObserver(pageInfoObserve, "page-info-dialog-loaded", false);
+  Services.obs.addObserver(pageInfoObserve, "page-info-dialog-loaded");
   gNextTest = continuation;
   // An explanation: it looks like the test harness complains about leaked
   // windows if we don't keep a reference to every window we've opened.
   // So, don't reuse pointers to opened Page Info windows - simply append
   // to this list.
   gPageInfo = BrowserPageInfo(null, "permTab");
 }
 
--- a/browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js
+++ b/browser/base/content/test/plugins/browser_pluginCrashReportNonDeterminism.js
@@ -104,17 +104,17 @@ add_task(function* setup() {
 
     ok(pluginDumpFile.exists(), "Found minidump");
     ok(extraFile.exists(), "Found extra file");
 
     pluginDumpFile.remove(false);
     extraFile.remove(false);
   };
 
-  Services.obs.addObserver(crashObserver, "plugin-crashed", false);
+  Services.obs.addObserver(crashObserver, "plugin-crashed");
   // plugins.testmode will make BrowserPlugins:Test:ClearCrashData work.
   Services.prefs.setBoolPref("plugins.testmode", true);
   registerCleanupFunction(() => {
     Services.prefs.clearUserPref("plugins.testmode");
     Services.obs.removeObserver(crashObserver, "plugin-crashed");
   });
 });
 
--- a/browser/base/content/test/plugins/head.js
+++ b/browser/base/content/test/plugins/head.js
@@ -233,17 +233,17 @@ function clearAllPluginPermissions() {
 
 function updateBlocklist(aCallback) {
   let blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
                           .getService(Ci.nsITimerCallback);
   let observer = function() {
     Services.obs.removeObserver(observer, "blocklist-updated");
     SimpleTest.executeSoon(aCallback);
   };
-  Services.obs.addObserver(observer, "blocklist-updated", false);
+  Services.obs.addObserver(observer, "blocklist-updated");
   blocklistNotifier.notify(null);
 }
 
 var _originalTestBlocklistURL = null;
 function setAndUpdateBlocklist(aURL, aCallback) {
   if (!_originalTestBlocklistURL) {
     _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
   }
--- a/browser/base/content/test/popupNotifications/head.js
+++ b/browser/base/content/test/popupNotifications/head.js
@@ -18,17 +18,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
  * @rejects Never.
  */
 function promiseTopicObserved(topic) {
   let deferred = Promise.defer();
   info("Waiting for observer topic " + topic);
   Services.obs.addObserver(function PTO_observe(obsSubject, obsTopic, obsData) {
     Services.obs.removeObserver(PTO_observe, obsTopic);
     deferred.resolve([obsSubject, obsData]);
-  }, topic, false);
+  }, topic);
   return deferred.promise;
 }
 
 /**
  * Called after opening a new window or switching windows, this will wait until
  * we are sure that an attempt to display a notification will not fail.
  */
 function* waitForWindowReadyForPopupNotifications(win) {
--- a/browser/base/content/test/referrer/head.js
+++ b/browser/base/content/test/referrer/head.js
@@ -124,17 +124,17 @@ function referrerResultExtracted(aWindow
  */
 function delayedStartupFinished(aWindow) {
   return new Promise(function(resolve) {
     Services.obs.addObserver(function observer(aSubject, aTopic) {
       if (aWindow == aSubject) {
         Services.obs.removeObserver(observer, aTopic);
         resolve();
       }
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
   });
 }
 
 /**
  * Waits for some (any) tab to load. The caller triggers the load.
  * @param aWindow The window where to wait for a tab to load.
  * @return {Promise}
  * @resolves With the tab once it's loaded.
--- a/browser/base/content/test/siteIdentity/head.js
+++ b/browser/base/content/test/siteIdentity/head.js
@@ -293,17 +293,17 @@ function* loadBadCertPage(url) {
             certExceptionDialog.documentElement.getButton("extra1").click();
             resolve();
           });
         }
       }
     };
 
     Services.obs.addObserver(certExceptionDialogObserver,
-                             "cert-exception-ui-ready", false);
+                             "cert-exception-ui-ready");
   });
 
   let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
   yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   yield loaded;
 
   yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
     content.document.getElementById("exceptionDialogButton").click();
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -11,17 +11,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 
 function promiseObserverNotified(aTopic) {
   return new Promise(resolve => {
     Services.obs.addObserver(function onNotification(subject, topic, data) {
       dump("notification promised " + topic);
       Services.obs.removeObserver(onNotification, topic);
       TestUtils.executeSoon(() => resolve({subject, data}));
-    }, aTopic, false);
+    }, aTopic);
   });
 }
 
 // Check that a specified (string) URL hasn't been "remembered" (ie, is not
 // in history, will not appear in about:newtab or auto-complete, etc.)
 function promiseSocialUrlNotRemembered(url) {
   return new Promise(resolve => {
     let uri = Services.io.newURI(url);
@@ -236,17 +236,17 @@ function toggleOfflineStatus(goOfflineSt
     if (goOfflineState != Services.io.offline) {
       info("initial offline state " + Services.io.offline);
       let expect = !Services.io.offline;
       Services.obs.addObserver(function offlineChange(subject, topic, data) {
         Services.obs.removeObserver(offlineChange, "network:offline-status-changed");
         info("offline state changed to " + Services.io.offline);
         is(expect, Services.io.offline, "network:offline-status-changed successful toggle");
         resolve();
-      }, "network:offline-status-changed", false);
+      }, "network:offline-status-changed");
       BrowserOffline.toggleOfflineStatus();
     } else {
       resolve();
     }
     if (goOfflineState) {
       Services.prefs.setIntPref("network.proxy.type", 0);
       // LOAD_FLAGS_BYPASS_CACHE isn't good enough. So clear the cache.
       Services.cache2.clear();
--- a/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
+++ b/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
@@ -27,17 +27,17 @@ add_task(function*() {
     let unopenedPromptCount = PROMPTCOUNT;
     Services.obs.addObserver(function observer() {
       unopenedPromptCount--;
       if (!unopenedPromptCount) {
         Services.obs.removeObserver(observer, "tabmodal-dialog-loaded");
         info("Prompts opened.");
         resolve();
       }
-    }, "tabmodal-dialog-loaded", false);
+    }, "tabmodal-dialog-loaded");
   });
 
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, true);
   info("Tab loaded");
 
   yield promptsOpenedPromise;
 
   let promptsCount = PROMPTCOUNT;
@@ -55,17 +55,17 @@ add_task(function*() {
       }
 
       is(prompt.hidden, false, "The last prompt should not be hidden.");
       prompt.onButtonClick(0);
 
       // The click is handled async; wait for an event loop turn for that to
       // happen.
       yield new Promise(function(resolve) {
-        Services.tm.mainThread.dispatch(resolve, Ci.nsIThread.DISPATCH_NORMAL);
+        Services.tm.dispatchToMainThread(resolve);
       });
     }
   }
 
   let prompts = tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
   is(prompts.length, 0, "Prompts should all be dismissed.");
 
   yield BrowserTestUtils.removeTab(tab);
--- a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
+++ b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
@@ -38,17 +38,17 @@ add_task(function*() {
   let checkbox = row.querySelector("checkbox[label*='example.com']");
   ok(checkbox, "The checkbox should be there");
   ok(!checkbox.checked, "Checkbox shouldn't be checked");
   // tick box and accept dialog
   checkbox.checked = true;
   ourPrompt.onButtonClick(0);
   // Wait for that click to actually be handled completely.
   yield new Promise(function(resolve) {
-    Services.tm.mainThread.dispatch(resolve, Ci.nsIThread.DISPATCH_NORMAL);
+    Services.tm.dispatchToMainThread(resolve);
   });
   // check permission is set
   let ps = Services.perms;
   is(ps.ALLOW_ACTION, ps.testPermission(makeURI(pageWithAlert), "focus-tab-by-prompt"),
      "Tab switching should now be allowed");
 
   // Check if the control center shows the correct permission.
   let shown = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
--- a/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
+++ b/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
@@ -120,18 +120,17 @@ function loadTab(tab, url) {
   let visited = new Promise(resolve => {
     Services.obs.addObserver(
       function observer(aSubject, aTopic, aData) {
         if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
           return;
         Services.obs.removeObserver(observer, aTopic);
         resolve();
       },
-      "uri-visit-saved",
-      false
+      "uri-visit-saved"
     );
   });
 
   info("Loading page: " + url);
   tab.linkedBrowser.loadURI(url);
   return Promise.all([ loaded, visited ]);
 }
 
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSuggestionsNotification.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSuggestionsNotification.js
@@ -205,17 +205,17 @@ add_task(function* enableOutsideNotifica
  */
 function setUserMadeChoicePref(userMadeChoice) {
   return new Promise(resolve => {
     let currentUserMadeChoice = Services.prefs.getBoolPref(CHOICE_PREF);
     if (currentUserMadeChoice != userMadeChoice) {
       Services.prefs.addObserver(CHOICE_PREF, function obs(subj, topic, data) {
         Services.prefs.removeObserver(CHOICE_PREF, obs);
         resolve();
-      }, false);
+      });
     }
     Services.prefs.setBoolPref(CHOICE_PREF, userMadeChoice);
     if (currentUserMadeChoice == userMadeChoice) {
       resolve();
     }
   });
 }
 
--- a/browser/base/content/test/webextensions/browser_update_checkForUpdates.js
+++ b/browser/base/content/test/webextensions/browser_update_checkForUpdates.js
@@ -3,15 +3,15 @@ function checkAll(win) {
   win.gViewController.doCommand("cmd_findAllUpdates");
   return new Promise(resolve => {
     let observer = {
       observe(subject, topic, data) {
         Services.obs.removeObserver(observer, "EM-update-check-finished");
         resolve();
       },
     };
-    Services.obs.addObserver(observer, "EM-update-check-finished", false);
+    Services.obs.addObserver(observer, "EM-update-check-finished");
   });
 }
 
 // Test "Check for Updates" with both auto-update settings
 add_task(() => interactiveUpdateTest(true, checkAll));
 add_task(() => interactiveUpdateTest(false, checkAll));
--- a/browser/base/content/test/webrtc/get_user_media_content_script.js
+++ b/browser/base/content/test/webrtc/get_user_media_content_script.js
@@ -35,17 +35,17 @@ function observer(aSubject, aTopic, aDat
 
   if (!(aTopic in gObservedTopics))
     gObservedTopics[aTopic] = 1;
   else
     ++gObservedTopics[aTopic];
 }
 
 kObservedTopics.forEach(topic => {
-  Services.obs.addObserver(observer, topic, false);
+  Services.obs.addObserver(observer, topic);
 });
 
 addMessageListener("Test:ExpectObserverCalled", ({data}) => {
   sendAsyncMessage("Test:ExpectObserverCalled:Reply",
                    {count: gObservedTopics[data]});
   if (data in gObservedTopics)
     --gObservedTopics[data];
 });
@@ -95,16 +95,16 @@ addMessageListener("Test:WaitForObserver
     Services.obs.removeObserver(obs, topic);
 
     if (kObservedTopics.indexOf(topic) != -1) {
       if (!(topic in gObservedTopics))
         gObservedTopics[topic] = -1;
       else
         --gObservedTopics[topic];
     }
-  }, topic, false);
+  }, topic);
 });
 
 addMessageListener("Test:WaitForMessage", () => {
   content.addEventListener("message", ({data}) => {
     sendAsyncMessage("Test:MessageReceived", data);
   }, {once: true});
 });
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -53,29 +53,29 @@ function promiseWindow(url) {
         if (win.location.href !== url) {
           info("ignoring a window with this url: " + win.location.href);
           return;
         }
 
         Services.obs.removeObserver(obs, "domwindowopened");
         resolve(win);
       }, {once: true});
-    }, "domwindowopened", false);
+    }, "domwindowopened");
   });
 }
 
 function whenDelayedStartupFinished(aWindow) {
   return new Promise(resolve => {
     info("Waiting for delayed startup to finish");
     Services.obs.addObserver(function observer(aSubject, aTopic) {
       if (aWindow == aSubject) {
         Services.obs.removeObserver(observer, aTopic);
         resolve();
       }
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
   });
 }
 
 function promiseIndicatorWindow() {
   // We don't show the indicator window on Mac.
   if ("nsISystemStatusBar" in Ci)
     return Promise.resolve();
 
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -59,17 +59,17 @@ file, You can obtain one at http://mozil
         (Components.utils.import("resource://gre/modules/ExtensionSearchHandler.jsm", {})).ExtensionSearchHandler;
       </field>
 
       <constructor><![CDATA[
         this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
                                 .getService(Components.interfaces.nsIPrefService)
                                 .getBranch("browser.urlbar.");
 
-        this._prefs.addObserver("", this, false);
+        this._prefs.addObserver("", this);
         this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
         this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
         this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
         this.timeout = this._prefs.getIntPref("delay");
         this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
         this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
         this._cacheUserMadeSearchSuggestionsChoice();
         this.inputField.controllers.insertControllerAt(0, this._copyCutController);
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -304,25 +304,25 @@ function openLinkIn(url, where, params) 
     var referrerPolicySupports = Cc["@mozilla.org/supports-PRUint32;1"].
                                  createInstance(Ci.nsISupportsPRUint32);
     referrerPolicySupports.data = aReferrerPolicy;
 
     var userContextIdSupports = Cc["@mozilla.org/supports-PRUint32;1"].
                                  createInstance(Ci.nsISupportsPRUint32);
     userContextIdSupports.data = aUserContextId;
 
-    sa.appendElement(wuri, /* weak =*/ false);
-    sa.appendElement(charset, /* weak =*/ false);
-    sa.appendElement(referrerURISupports, /* weak =*/ false);
-    sa.appendElement(aPostData, /* weak =*/ false);
-    sa.appendElement(allowThirdPartyFixupSupports, /* weak =*/ false);
-    sa.appendElement(referrerPolicySupports, /* weak =*/ false);
-    sa.appendElement(userContextIdSupports, /* weak =*/ false);
-    sa.appendElement(aPrincipal, /* weak =*/ false);
-    sa.appendElement(aTriggeringPrincipal, /* weak =*/ false);
+    sa.appendElement(wuri);
+    sa.appendElement(charset);
+    sa.appendElement(referrerURISupports);
+    sa.appendElement(aPostData);
+    sa.appendElement(allowThirdPartyFixupSupports);
+    sa.appendElement(referrerPolicySupports);
+    sa.appendElement(userContextIdSupports);
+    sa.appendElement(aPrincipal);
+    sa.appendElement(aTriggeringPrincipal);
 
     let features = "chrome,dialog=no,all";
     if (aIsPrivate) {
       features += ",private";
     }
 
     const sourceWindow = (w || window);
     let win;
@@ -337,20 +337,20 @@ function openLinkIn(url, where, params) 
           Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
           Services.obs.notifyObservers({
             wrappedJSObject: {
               url,
               createdTabBrowser: win.gBrowser.selectedBrowser,
               sourceTabBrowser,
               sourceFrameOuterWindowID: params.frameOuterWindowID,
             },
-          }, "webNavigation-createdNavigationTarget", null);
+          }, "webNavigation-createdNavigationTarget");
         }
       };
-      Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished", false);
+      Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished");
     }
     win = Services.ww.openWindow(sourceWindow, getBrowserURL(), null, features, sa);
     return;
   }
 
   // We're now committed to loading the link in an existing browser window.
 
   // Raise the target window before loading the URI, since loading it may
@@ -457,17 +457,17 @@ function openLinkIn(url, where, params) 
       // opening a new tab using the keyboard shortcut).
       Services.obs.notifyObservers({
         wrappedJSObject: {
           url,
           createdTabBrowser: targetBrowser,
           sourceTabBrowser: w.gBrowser.selectedBrowser,
           sourceFrameOuterWindowID: params.frameOuterWindowID,
         },
-      }, "webNavigation-createdNavigationTarget", null);
+      }, "webNavigation-createdNavigationTarget");
     }
     break;
   }
 
   // Focus the content, but only if the browser used for the load is selected.
   if (targetBrowser == w.gBrowser.selectedBrowser) {
     targetBrowser.focus();
   }
@@ -742,17 +742,17 @@ function openPreferences(paneID, extraAr
   if (!win) {
     const Cc = Components.classes;
     const Ci = Components.interfaces;
     let windowArguments = Cc["@mozilla.org/array;1"]
                             .createInstance(Ci.nsIMutableArray);
     let supportsStringPrefURL = Cc["@mozilla.org/supports-string;1"]
                                   .createInstance(Ci.nsISupportsString);
     supportsStringPrefURL.data = preferencesURL;
-    windowArguments.appendElement(supportsStringPrefURL, /* weak =*/ false);
+    windowArguments.appendElement(supportsStringPrefURL);
 
     win = Services.ww.openWindow(null, Services.prefs.getCharPref("browser.chromeURL"),
                                  "_blank", "chrome,dialog=no,all", windowArguments);
   } else {
     let shouldReplaceFragment = friendlyCategoryName ? "whenComparingAndReplace" : "whenComparing";
     newLoad = !win.switchToTabHavingURI(preferencesURL, true, { ignoreFragment: shouldReplaceFragment, replaceQueryString: true });
     browser = win.gBrowser.selectedBrowser;
   }
@@ -762,17 +762,17 @@ function openPreferences(paneID, extraAr
       if (!browser) {
         browser = win.gBrowser.selectedBrowser;
       }
       if (prefWin != browser.contentWindow) {
         return;
       }
       Services.obs.removeObserver(advancedPaneLoadedObs, "advanced-pane-loaded");
       switchToAdvancedSubPane(browser.contentDocument);
-    }, "advanced-pane-loaded", false);
+    }, "advanced-pane-loaded");
   } else {
     if (paneID) {
       browser.contentWindow.gotoPref(paneID);
     }
     switchToAdvancedSubPane(browser.contentDocument);
   }
 }
 
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -4008,17 +4008,17 @@ function OverflowableToolbar(aToolbarNod
   this._list = doc.getElementById(this._toolbar.getAttribute("overflowtarget"));
   this._list.toolbox = this._toolbar.toolbox;
   this._list.customizationTarget = this._list;
 
   let window = this._toolbar.ownerGlobal;
   if (window.gBrowserInit.delayedStartupFinished) {
     this.init();
   } else {
-    Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
+    Services.obs.addObserver(this, "browser-delayed-startup-finished");
   }
 }
 
 OverflowableToolbar.prototype = {
   initialized: false,
   _forceOnOverflow: false,
 
   observe(aSubject, aTopic, aData) {
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -347,17 +347,17 @@ const CustomizableWidgets = [
         let link = Services.prefs.getCharPref(`identity.mobilepromo.${os}`) + "synced-tabs";
         doc.defaultView.openUILinkIn(link, "tab");
         CustomizableUI.hidePanelForNode(e.target);
       });
     },
     onViewShowing(aEvent) {
       let doc = aEvent.target.ownerDocument;
       this._tabsList = doc.getElementById("PanelUI-remotetabs-tabslist");
-      Services.obs.addObserver(this, SyncedTabs.TOPIC_TABS_CHANGED, false);
+      Services.obs.addObserver(this, SyncedTabs.TOPIC_TABS_CHANGED);
 
       if (SyncedTabs.isConfiguredToSyncTabs) {
         if (SyncedTabs.hasSyncedThisSession) {
           this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
         } else {
           // Sync hasn't synced tabs yet, so show the "fetching" panel.
           this.setDeckIndex(this.deckIndices.DECKINDEX_FETCHING);
         }
@@ -437,17 +437,17 @@ const CustomizableWidgets = [
             this._appendClient(client, fragment);
           }
         }
         this._tabsList.appendChild(fragment);
       }).catch(err => {
         Cu.reportError(err);
       }).then(() => {
         // an observer for tests.
-        Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated", null);
+        Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated");
       });
     },
     _clearTabList() {
       let list = this._tabsList;
       while (list.lastChild) {
         list.lastChild.remove();
       }
     },
@@ -618,24 +618,24 @@ const CustomizableWidgets = [
       node.setAttribute("observes", "Social:PageShareable");
       node.setAttribute("command", "Social:SharePage");
 
       let listener = {
         onWidgetAdded: (aWidgetId) => {
           if (aWidgetId != this.id)
             return;
 
-          Services.obs.notifyObservers(null, "social:" + this.id + "-added", null);
+          Services.obs.notifyObservers(null, "social:" + this.id + "-added");
         },
 
         onWidgetRemoved: aWidgetId => {
           if (aWidgetId != this.id)
             return;
 
-          Services.obs.notifyObservers(null, "social:" + this.id + "-removed", null);
+          Services.obs.notifyObservers(null, "social:" + this.id + "-removed");
         },
 
         onWidgetInstanceRemoved: (aWidgetId, aDoc) => {
           if (aWidgetId != this.id || aDoc != aDocument)
             return;
 
           CustomizableUI.removeListener(listener);
         }
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -104,17 +104,17 @@ function CustomizeMode(aWindow) {
   this.paletteEmptyNotice = this.document.getElementById("customization-empty");
   this.tipPanel = this.document.getElementById("customization-tipPanel");
   if (Services.prefs.getCharPref("general.skins.selectedSkin") != "classic/1.0") {
     let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
     lwthemeButton.setAttribute("hidden", "true");
   }
   if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
     this._updateTitlebarButton();
-    Services.prefs.addObserver(kDrawInTitlebarPref, this, false);
+    Services.prefs.addObserver(kDrawInTitlebarPref, this);
   }
   this.window.addEventListener("unload", this);
 }
 
 CustomizeMode.prototype = {
   _changed: false,
   _transitioning: false,
   window: null,
@@ -249,17 +249,17 @@ CustomizeMode.prototype = {
         yield new Promise(resolve => {
           let delayedStartupObserver = aSubject => {
             if (aSubject == this.window) {
               Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
               resolve();
             }
           };
 
-          Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished", false);
+          Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished");
         });
       }
 
       let toolbarVisibilityBtn = document.getElementById(kToolbarVisibilityBtn);
       let togglableToolbars = window.getTogglableToolbars();
       if (togglableToolbars.length == 0) {
         toolbarVisibilityBtn.setAttribute("hidden", "true");
       } else {
@@ -321,17 +321,17 @@ CustomizeMode.prototype = {
       this._wrapToolbarItemSync(CustomizableUI.AREA_TABSTRIP);
 
       let customizableToolbars = document.querySelectorAll("toolbar[customizable=true]:not([autohide=true]):not([collapsed=true])");
       for (let toolbar of customizableToolbars)
         toolbar.setAttribute("customizing", true);
 
       yield this._doTransition(true);
 
-      Services.obs.addObserver(this, "lightweight-theme-window-updated", false);
+      Services.obs.addObserver(this, "lightweight-theme-window-updated");
 
       // Let everybody in this window know that we're about to customize.
       CustomizableUI.dispatchToolboxEvent("customizationstarting", {}, window);
 
       this._mainViewContext = mainView.getAttribute("context");
       if (this._mainViewContext) {
         mainView.removeAttribute("context");
       }
@@ -2289,10 +2289,10 @@ function __dumpDragData(aEvent, caller) 
       str += "  dataTransfer[" + prop + "]: " + aEvent.dataTransfer[prop] + "\n";
     }
   }
   str += "}";
   log.debug(str);
 }
 
 function dispatchFunction(aFunc) {
-  Services.tm.currentThread.dispatch(aFunc, Ci.nsIThread.DISPATCH_NORMAL);
+  Services.tm.dispatchToMainThread(aFunc);
 }
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -53,19 +53,19 @@ const PanelUI = {
       });
     }
 
     this.notifications = [];
     this.menuButton.addEventListener("mousedown", this);
     this.menuButton.addEventListener("keypress", this);
     this._overlayScrollListenerBoundFn = this._overlayScrollListener.bind(this);
 
-    Services.obs.addObserver(this, "fullscreen-nav-toolbox", false);
-    Services.obs.addObserver(this, "panelUI-notification-main-action", false);
-    Services.obs.addObserver(this, "panelUI-notification-dismissed", false);
+    Services.obs.addObserver(this, "fullscreen-nav-toolbox");
+    Services.obs.addObserver(this, "panelUI-notification-main-action");
+    Services.obs.addObserver(this, "panelUI-notification-dismissed");
 
     window.addEventListener("fullscreen", this);
     window.matchMedia("(-moz-overlay-scrollbars)").addListener(this._overlayScrollListenerBoundFn);
     CustomizableUI.addListener(this);
 
     for (let event of this.kEvents) {
       this.notificationPanel.addEventListener(event, this);
     }
@@ -344,17 +344,17 @@ const PanelUI = {
       if (!this._initialized) {
         yield new Promise(resolve => {
           let delayedStartupObserver = (aSubject, aTopic, aData) => {
             if (aSubject == window) {
               Services.obs.removeObserver(delayedStartupObserver, "browser-delayed-startup-finished");
               resolve();
             }
           };
-          Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished", false);
+          Services.obs.addObserver(delayedStartupObserver, "browser-delayed-startup-finished");
         });
       }
 
       this.contents.setAttributeNS("http://www.w3.org/XML/1998/namespace", "lang",
                                    getLocale());
       if (!this._scrollWidth) {
         // In order to properly center the contents of the panel, while ensuring
         // that we have enough space on either side to show a scrollbar, we have to
--- a/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js
+++ b/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js
@@ -64,17 +64,17 @@ function promiseObserverNotification(aOb
     Services.obs.removeObserver(notificationCallback, aObserver);
     clearTimeout(timeoutId);
     deferred.resolve();
   }
   let timeoutId = setTimeout(() => {
     Services.obs.removeObserver(notificationCallback, aObserver);
     deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
   }, kTimeoutInMS);
-  Services.obs.addObserver(notificationCallback, aObserver, false);
+  Services.obs.addObserver(notificationCallback, aObserver);
   return deferred.promise;
 }
 
 function promiseTabSelect() {
   let deferred = Promise.defer();
   let container = window.gBrowser.tabContainer;
   let timeoutId = setTimeout(() => {
     container.removeEventListener("TabSelect", callback);
--- a/browser/components/customizableui/test/browser_synced_tabs_menu.js
+++ b/browser/components/customizableui/test/browser_synced_tabs_menu.js
@@ -19,17 +19,17 @@ const DECKINDEX_NOCLIENTS = 3;
 
 var initialLocation = gBrowser.currentURI.spec;
 var newTab = null;
 
 // A helper to notify there are new tabs. Returns a promise that is resolved
 // once the UI has been updated.
 function updateTabsPanel() {
   let promiseTabsUpdated = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
-  Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED, null);
+  Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED);
   return promiseTabsUpdated;
 }
 
 // This is the mock we use for SyncedTabs.jsm - tests may override various
 // functions.
 let mockedInternal = {
   get isConfiguredToSyncTabs() { return true; },
   getTabClients() { return Promise.resolve([]); },
--- a/browser/components/customizableui/test/head.js
+++ b/browser/components/customizableui/test/head.js
@@ -231,31 +231,31 @@ function startCustomizing(aWindow = wind
   return deferred.promise;
 }
 
 function promiseObserverNotified(aTopic) {
   let deferred = Promise.defer();
   Services.obs.addObserver(function onNotification(subject, topic, data) {
     Services.obs.removeObserver(onNotification, topic);
       deferred.resolve({subject, data});
-    }, aTopic, false);
+    }, aTopic);
   return deferred.promise;
 }
 
 function openAndLoadWindow(aOptions, aWaitForDelayedStartup = false) {
   let deferred = Promise.defer();
   let win = OpenBrowserWindow(aOptions);
   if (aWaitForDelayedStartup) {
     Services.obs.addObserver(function onDS(aSubject, aTopic, aData) {
       if (aSubject != win) {
         return;
       }
       Services.obs.removeObserver(onDS, "browser-delayed-startup-finished");
       deferred.resolve(win);
-    }, "browser-delayed-startup-finished", false);
+    }, "browser-delayed-startup-finished");
 
   } else {
     win.addEventListener("load", function() {
       deferred.resolve(win);
     }, {once: true});
   }
   return deferred.promise;
 }
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -454,17 +454,17 @@ DistributionCustomizer.prototype = {
       } catch (e) {}
     }
 
     let prefDefaultsApplied = this._prefDefaultsApplied || !this._ini;
     if (this._customizationsApplied && this._bookmarksApplied &&
         prefDefaultsApplied) {
       let os = Cc["@mozilla.org/observer-service;1"].
                getService(Ci.nsIObserverService);
-      os.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, null);
+      os.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC);
     }
   }
 };
 
 function parseValue(value) {
   try {
     value = JSON.parse(value);
   } catch (e) {
--- a/browser/components/downloads/DownloadsTaskbar.jsm
+++ b/browser/components/downloads/DownloadsTaskbar.jsm
@@ -84,17 +84,17 @@ this.DownloadsTaskbar = {
     if (!this._taskbarProgress) {
       if (gMacTaskbarProgress) {
         // On Mac OS X, we have to register the global indicator only once.
         this._taskbarProgress = gMacTaskbarProgress;
         // Free the XPCOM reference on shutdown, to prevent detecting a leak.
         Services.obs.addObserver(() => {
           this._taskbarProgress = null;
           gMacTaskbarProgress = null;
-        }, "quit-application-granted", false);
+        }, "quit-application-granted");
       } else if (gWinTaskbar) {
         // On Windows, the indicator is currently hidden because we have no
         // previous browser window, thus we should attach the indicator now.
         this._attachIndicator(aBrowserWindow);
       } else {
         // The taskbar indicator is not available on this platform.
         return;
       }
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -907,17 +907,17 @@ DownloadsPlacesView.prototype = {
     let queries = { }, options = { };
     history.queryStringToQueries(val, queries, { }, options);
     if (!queries.value.length) {
       queries.value = [history.getNewQuery()];
     }
 
     let result = history.executeQueries(queries.value, queries.value.length,
                                         options.value);
-    result.addObserver(this, false);
+    result.addObserver(this);
     return val;
   },
 
   _result: null,
   get result() {
     return this._result;
   },
   set result(val) {
@@ -1087,21 +1087,21 @@ DownloadsPlacesView.prototype = {
     if (this._richlistbox.selectedItem == this._initiallySelectedElement) {
       let firstDownloadElement = this._richlistbox.firstChild;
       if (firstDownloadElement != this._initiallySelectedElement) {
         // We may be called before _ensureVisibleElementsAreActive,
         // or before the download binding is attached. Therefore, ensure the
         // first item is activated, and pass the item to the richlistbox
         // setters only at a point we know for sure the binding is attached.
         firstDownloadElement._shell.ensureActive();
-        Services.tm.mainThread.dispatch(() => {
+        Services.tm.dispatchToMainThread(() => {
           this._richlistbox.selectedItem = firstDownloadElement;
           this._richlistbox.currentItem = firstDownloadElement;
           this._initiallySelectedElement = firstDownloadElement;
-        }, Ci.nsIThread.DISPATCH_NORMAL);
+        });
       }
     }
   },
 
   onDataLoadStarting() {},
   onDataLoadCompleted() {
     this._ensureInitialSelection();
   },
--- a/browser/components/downloads/test/browser/browser_iframe_gone_mid_download.js
+++ b/browser/components/downloads/test/browser/browser_iframe_gone_mid_download.js
@@ -17,17 +17,17 @@ function test_deleted_iframe(perSitePref
     let gDownloadLastDir = new DownloadLastDir(iframe.contentWindow);
     let cw = iframe.contentWindow;
     let promiseIframeWindowGone = new Promise((resolve, reject) => {
       Services.obs.addObserver(function obs(subject, topic) {
         if (subject == cw) {
           Services.obs.removeObserver(obs, topic);
           resolve();
         }
-      }, "dom-window-destroyed", false);
+      }, "dom-window-destroyed");
     });
     iframe.remove();
     yield promiseIframeWindowGone;
     cw = null;
     ok(!iframe.contentWindow, "Managed to destroy iframe");
 
     let someDir = "blah";
     try {
--- a/browser/components/downloads/test/browser/head.js
+++ b/browser/components/downloads/test/browser/head.js
@@ -98,17 +98,17 @@ function promiseTabLoadEvent(tab, url, e
 
 function promiseWindowClosed(win) {
   let promise = new Promise((resolve, reject) => {
     Services.obs.addObserver(function obs(subject, topic) {
       if (subject == win) {
         Services.obs.removeObserver(obs, topic);
         resolve();
       }
-    }, "domwindowclosed", false);
+    }, "domwindowclosed");
   });
   win.close();
   return promise;
 }
 
 
 function promiseFocus() {
   let deferred = Promise.defer();
@@ -243,17 +243,17 @@ function httpUrl(aFileName) {
     aFileName;
 }
 
 function task_clearHistory() {
   return new Promise(function(resolve) {
     Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
       Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
       resolve();
-    }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
+    }, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
     PlacesUtils.history.clear();
   });
 }
 
 function openLibrary(aLeftPaneRoot) {
   let library = window.openDialog("chrome://browser/content/places/places.xul",
                                   "", "chrome,toolbar=yes,dialog=no,resizable",
                                   aLeftPaneRoot);
--- a/browser/components/extensions/ext-bookmarks.js
+++ b/browser/components/extensions/ext-bookmarks.js
@@ -1,16 +1,12 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-var {
-  SingletonEventManager,
-} = ExtensionUtils;
-
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 
 let listenerCount = 0;
 
 function getTree(rootGuid, onlyChildren) {
@@ -169,17 +165,17 @@ function decrementListeners() {
   if (!listenerCount) {
     PlacesUtils.bookmarks.removeObserver(observer);
   }
 }
 
 function incrementListeners() {
   listenerCount++;
   if (listenerCount == 1) {
-    PlacesUtils.bookmarks.addObserver(observer, false);
+    PlacesUtils.bookmarks.addObserver(observer);
   }
 }
 
 this.bookmarks = class extends ExtensionAPI {
   getAPI(context) {
     return {
       bookmarks: {
         get: function(idOrIdList) {
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -15,17 +15,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/inspector/dom-utils;1",
                                    "inIDOMUtils");
 
 Cu.import("resource://devtools/shared/event-emitter.js");
 Cu.import("resource://gre/modules/Task.jsm");
 
 var {
   IconDetails,
-  SingletonEventManager,
 } = ExtensionUtils;
 
 const POPUP_PRELOAD_TIMEOUT_MS = 200;
 
 var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 function isAncestorOrSelf(target, node) {
   for (; node; node = node.parentNode) {
--- a/browser/components/extensions/ext-c-devtools-panels.js
+++ b/browser/components/extensions/ext-c-devtools-panels.js
@@ -2,17 +2,16 @@
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
                                   "resource://devtools/shared/event-emitter.js");
 
 var {
   promiseDocumentLoaded,
-  SingletonEventManager,
 } = ExtensionUtils;
 
 /**
  * Represents an addon devtools panel in the child process.
  *
  * @param {DevtoolsExtensionContext}
  *   A devtools extension context running in a child process.
  * @param {object} panelOptions
--- a/browser/components/extensions/ext-c-omnibox.js
+++ b/browser/components/extensions/ext-c-omnibox.js
@@ -1,16 +1,12 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-var {
-  SingletonEventManager,
-} = ExtensionUtils;
-
 this.omnibox = class extends ExtensionAPI {
   getAPI(context) {
     return {
       omnibox: {
         onInputChanged: new SingletonEventManager(context, "omnibox.onInputChanged", fire => {
           let listener = (text, id) => {
             fire.asyncWithoutClone(text, suggestions => {
               context.childManager.callParentFunctionNoReturn("omnibox_internal.addSuggestions", [
--- a/browser/components/extensions/ext-commands.js
+++ b/browser/components/extensions/ext-commands.js
@@ -1,14 +1,13 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 var {
-  SingletonEventManager,
   PlatformInfo,
 } = ExtensionUtils;
 
 var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 this.commands = class extends ExtensionAPI {
   onManifestEntry(entryName) {
     let {extension} = this;
--- a/browser/components/extensions/ext-contextMenus.js
+++ b/browser/components/extensions/ext-contextMenus.js
@@ -7,17 +7,16 @@ Cu.import("resource://gre/modules/MatchP
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 
 var {
   ExtensionError,
   IconDetails,
-  SingletonEventManager,
 } = ExtensionUtils;
 
 const ACTION_MENU_TOP_LEVEL_LIMIT = 6;
 
 // Map[Extension -> Map[ID -> MenuItem]]
 // Note: we want to enumerate all the menu items so
 // this cannot be a weak map.
 var gContextMenuMap = new Map();
@@ -554,17 +553,17 @@ MenuItem.prototype = {
     return true;
   },
 };
 
 // While any extensions are active, this Tracker registers to observe/listen
 // for contex-menu events from both content and chrome.
 const contextMenuTracker = {
   register() {
-    Services.obs.addObserver(this, "on-build-contextmenu", false);
+    Services.obs.addObserver(this, "on-build-contextmenu");
     for (const window of windowTracker.browserWindows()) {
       this.onWindowOpen(window);
     }
     windowTracker.addOpenListener(this.onWindowOpen);
   },
 
   unregister() {
     Services.obs.removeObserver(this, "on-build-contextmenu");
--- a/browser/components/extensions/ext-devtools-network.js
+++ b/browser/components/extensions/ext-devtools-network.js
@@ -1,16 +1,12 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-var {
-  SingletonEventManager,
-} = ExtensionUtils;
-
 this.devtools_network = class extends ExtensionAPI {
   getAPI(context) {
     return {
       devtools: {
         network: {
           onNavigated: new SingletonEventManager(context, "devtools.onNavigated", fire => {
             let listener = (event, data) => {
               fire.async(data.url);
--- a/browser/components/extensions/ext-history.js
+++ b/browser/components/extensions/ext-history.js
@@ -4,17 +4,16 @@
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 var {
   normalizeTime,
-  SingletonEventManager,
 } = ExtensionUtils;
 
 let nsINavHistoryService = Ci.nsINavHistoryService;
 const TRANSITION_TO_TRANSITION_TYPES_MAP = new Map([
   ["link", nsINavHistoryService.TRANSITION_LINK],
   ["typed", nsINavHistoryService.TRANSITION_TYPED],
   ["auto_bookmark", nsINavHistoryService.TRANSITION_BOOKMARK],
   ["auto_subframe", nsINavHistoryService.TRANSITION_EMBED],
@@ -116,17 +115,17 @@ function getObserver() {
       onPageChanged: function() {},
       onFrecencyChanged: function() {},
       onManyFrecenciesChanged: function() {},
       onDeleteVisits: function(uri, time, guid, reason) {
         this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
       },
     };
     EventEmitter.decorate(_observer);
-    PlacesUtils.history.addObserver(_observer, false);
+    PlacesUtils.history.addObserver(_observer);
   }
   return _observer;
 }
 
 this.history = class extends ExtensionAPI {
   getAPI(context) {
     return {
       history: {
--- a/browser/components/extensions/ext-omnibox.js
+++ b/browser/components/extensions/ext-omnibox.js
@@ -1,17 +1,14 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSearchHandler",
                                   "resource://gre/modules/ExtensionSearchHandler.jsm");
-var {
-  SingletonEventManager,
-} = ExtensionUtils;
 
 this.omnibox = class extends ExtensionAPI {
   onManifestEntry(entryName) {
     let {extension} = this;
     let {manifest} = extension;
 
     let keyword = manifest.omnibox.keyword;
     try {
--- a/browser/components/extensions/ext-pageAction.js
+++ b/browser/components/extensions/ext-pageAction.js
@@ -3,17 +3,16 @@
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "PanelPopup",
                                   "resource:///modules/ExtensionPopups.jsm");
 
 Cu.import("resource://gre/modules/Task.jsm");
 
 var {
-  SingletonEventManager,
   IconDetails,
 } = ExtensionUtils;
 
 // WeakMap[Extension -> PageAction]
 let pageActionMap = new WeakMap();
 
 this.pageAction = class extends ExtensionAPI {
   static for(extension) {
--- a/browser/components/extensions/ext-sessions.js
+++ b/browser/components/extensions/ext-sessions.js
@@ -1,15 +1,14 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 var {
   promiseObserved,
-  SingletonEventManager,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
                                   "resource:///modules/sessionstore/SessionStore.jsm");
 
 const SS_ON_CLOSED_OBJECTS_CHANGED = "sessionstore-closed-objects-changed";
 
 function getRecentlyClosed(maxResults, extension) {
@@ -92,17 +91,17 @@ this.sessions = class extends ExtensionA
           return createSession(session, extension, closedId);
         },
 
         onChanged: new SingletonEventManager(context, "sessions.onChanged", fire => {
           let observer = () => {
             fire.async();
           };
 
-          Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED, false);
+          Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
           return () => {
             Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
           };
         }).api(),
       },
     };
   }
 };
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -10,20 +10,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/MatchPattern.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
-var {
-  SingletonEventManager,
-} = ExtensionUtils;
-
 let tabListener = {
   tabReadyInitialized: false,
   tabReadyPromises: new WeakMap(),
   initializingTabs: new WeakSet(),
 
   initTabReady() {
     if (!this.tabReadyInitialized) {
       windowTracker.addListener("progress", this);
@@ -302,17 +298,17 @@ this.tabs = class extends ExtensionAPI {
             if (!window.gBrowser) {
               let obs = (finishedWindow, topic, data) => {
                 if (finishedWindow != window) {
                   return;
                 }
                 Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
                 resolve(window);
               };
-              Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
+              Services.obs.addObserver(obs, "browser-delayed-startup-finished");
             } else {
               resolve(window);
             }
           }).then(window => {
             let url;
 
             if (createProperties.url !== null) {
               url = context.uri.resolve(createProperties.url);
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -9,17 +9,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 Cu.import("resource://gre/modules/ExtensionTabs.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "styleSheetService",
                                    "@mozilla.org/content/style-sheet-service;1",
                                    "nsIStyleSheetService");
 
 var {
   ExtensionError,
-  SingletonEventManager,
   defineLazyGetter,
 } = ExtensionUtils;
 
 let tabTracker;
 let windowTracker;
 
 // This file provides some useful code for the |tabs| and |windows|
 // modules. All of the code is installed on |global|, which is a scope
@@ -389,19 +388,19 @@ class TabTracker extends TabTrackerBase 
     // addon-invoked calls are asynchronous since they go through a proxy
     // context via the message manager. This includes event registrations such
     // as `tabs.onRemoved.addListener`.
     //
     // So, even if `window.close()` were to be called (in-process) after calling
     // `tabs.onRemoved.addListener`, then the tab would be closed before the
     // event listener is registered. To make sure that the event listener is
     // notified, we dispatch `tabs.onRemoved` asynchronously.
-    Services.tm.mainThread.dispatch(() => {
+    Services.tm.dispatchToMainThread(() => {
       this.emit("tab-removed", {nativeTab, tabId, windowId, isWindowClosing});
-    }, Ci.nsIThread.DISPATCH_NORMAL);
+    });
   }
 
   getBrowserData(browser) {
     if (browser.ownerGlobal.location.href === "about:addons") {
       // When we're loaded into a <browser> inside about:addons, we need to go up
       // one more level.
       browser = browser.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell)
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -6,17 +6,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 var {
-  SingletonEventManager,
   promiseObserved,
 } = ExtensionUtils;
 
 function onXULFrameLoaderCreated({target}) {
   target.messageManager.sendAsyncMessage("AllowScriptsToClose", {});
 }
 
 this.windows = class extends ExtensionAPI {
@@ -118,29 +117,29 @@ this.windows = class extends ExtensionAP
             // Private browsing tabs can only be moved to private browsing
             // windows.
             let incognito = PrivateBrowsingUtils.isBrowserPrivate(tab.linkedBrowser);
             if (createData.incognito !== null && createData.incognito != incognito) {
               return Promise.reject({message: "`incognito` property must match the incognito state of tab"});
             }
             createData.incognito = incognito;
 
-            args.appendElement(tab, /* weak = */ false);
+            args.appendElement(tab);
           } else if (createData.url !== null) {
             if (Array.isArray(createData.url)) {
               let array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
               for (let url of createData.url) {
-                array.appendElement(mkstr(url), /* weak = */ false);
+                array.appendElement(mkstr(url));
               }
-              args.appendElement(array, /* weak = */ false);
+              args.appendElement(array);
             } else {
-              args.appendElement(mkstr(createData.url), /* weak = */ false);
+              args.appendElement(mkstr(createData.url));
             }
           } else {
-            args.appendElement(mkstr(aboutNewTabService.newTabURL), /* weak = */ false);
+            args.appendElement(mkstr(aboutNewTabService.newTabURL));
           }
 
           let features = ["chrome"];
 
           if (createData.type === null || createData.type == "normal") {
             features.push("dialog=no", "all");
           } else {
             // All other types create "popup"-type windows by default.
--- a/browser/components/extensions/test/browser/browser_ext_runtime_setUninstallURL.js
+++ b/browser/components/extensions/test/browser/browser_ext_runtime_setUninstallURL.js
@@ -4,17 +4,17 @@ let {AddonManager} = Components.utils.im
 let {Extension} = Components.utils.import("resource://gre/modules/Extension.jsm", {});
 
 function* makeAndInstallXPI(id, backgroundScript, loadedURL) {
   let xpi = Extension.generateXPI({
     manifest: {applications: {gecko: {id}}},
     background: backgroundScript,
   });
   SimpleTest.registerCleanupFunction(function cleanupXPI() {
-    Services.obs.notifyObservers(xpi, "flush-cache-entry", null);
+    Services.obs.notifyObservers(xpi, "flush-cache-entry");
     xpi.remove(false);
   });
 
   let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, loadedURL);
 
 
   info(`installing ${xpi.path}`);
   let addon = yield AddonManager.installTemporaryAddon(xpi);
--- a/browser/components/feeds/WebContentConverter.js
+++ b/browser/components/feeds/WebContentConverter.js
@@ -432,17 +432,17 @@ WebContentConverterRegistrar.prototype =
           let handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
                         createInstance(Ci.nsIWebHandlerApp);
           handler.name = name;
           handler.uriTemplate = aButtonInfo.protocolInfo.uri;
 
           let eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                     getService(Ci.nsIExternalProtocolService);
           let handlerInfo = eps.getProtocolHandlerInfo(protocol);
-          handlerInfo.possibleApplicationHandlers.appendElement(handler, false);
+          handlerInfo.possibleApplicationHandlers.appendElement(handler);
 
           // Since the user has agreed to add a new handler, chances are good
           // that the next time they see a handler of this type, they're going
           // to want to use it.  Reset the handlerInfo to ask before the next
           // use.
           handlerInfo.alwaysAskBeforeHandling = true;
 
           let hs = Cc["@mozilla.org/uriloader/handler-service;1"].
@@ -836,17 +836,17 @@ WebContentConverterRegistrar.prototype =
 
   /**
    * See nsIObserver
    */
   observe(subject, topic, data) {
     let os = Services.obs;
     switch (topic) {
     case "app-startup":
-      os.addObserver(this, "browser-ui-startup-complete", false);
+      os.addObserver(this, "browser-ui-startup-complete");
       break;
     case "browser-ui-startup-complete":
       os.removeObserver(this, "browser-ui-startup-complete");
       this._init();
       break;
     }
   },
 
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -121,18 +121,18 @@ const AutoMigrate = {
         AsyncShutdown.profileBeforeChange.addBlocker(
           "AutoMigrate Undo saving", this.saveUndoState(), () => {
             return {state: this._saveUndoStateTrackerForShutdown};
           });
       }
     };
 
     MigrationUtils.initializeUndoData();
-    Services.obs.addObserver(migrationObserver, "Migration:Ended", false);
-    Services.obs.addObserver(migrationObserver, "Migration:ItemError", false);
+    Services.obs.addObserver(migrationObserver, "Migration:Ended");
+    Services.obs.addObserver(migrationObserver, "Migration:ItemError");
     migrator.migrate(this.resourceTypesToUse, profileStartup, profileToMigrate);
     histogram.add(20);
   },
 
   /**
    * Pick and return a migrator to use for automatically migrating.
    *
    * @param {String} migratorKey   optional, a migrator key to prefer/pick.
--- a/browser/components/migration/ESEDBReader.jsm
+++ b/browser/components/migration/ESEDBReader.jsm
@@ -226,17 +226,17 @@ function unloadLibraries() {
   }
   gLibs.ese.close();
   gLibs.kernel.close();
   delete gLibs.ese;
   delete gLibs.kernel;
 }
 
 function loadLibraries() {
-  Services.obs.addObserver(unloadLibraries, "xpcom-shutdown", false);
+  Services.obs.addObserver(unloadLibraries, "xpcom-shutdown");
   gLibs.ese = ctypes.open("esent.dll");
   gLibs.kernel = ctypes.open("kernel32.dll");
   KERNEL.FileTimeToSystemTime = gLibs.kernel.declare("FileTimeToSystemTime",
     ctypes.default_abi, ctypes.int, KERNEL.FILETIME.ptr, KERNEL.SYSTEMTIME.ptr);
 
   declareESEFunctions();
 }
 
--- a/browser/components/migration/MigrationUtils.jsm
+++ b/browser/components/migration/MigrationUtils.jsm
@@ -230,17 +230,17 @@ this.MigratorPrototype = {
       throw new Error("migrate called for a non-existent source");
 
     if (aItems != Ci.nsIBrowserProfileMigrator.ALL)
       resources = resources.filter(r => aItems & r.type);
 
     // Used to periodically give back control to the main-thread loop.
     let unblockMainThread = function() {
       return new Promise(resolve => {
-        Services.tm.mainThread.dispatch(resolve, Ci.nsIThread.DISPATCH_NORMAL);
+        Services.tm.dispatchToMainThread(resolve);
       });
     };
 
     let getHistogramIdForResourceType = (resourceType, template) => {
       if (resourceType == MigrationUtils.resourceTypes.HISTORY) {
         return template.replace("*", "HISTORY");
       }
       if (resourceType == MigrationUtils.resourceTypes.BOOKMARKS) {
@@ -394,17 +394,17 @@ this.MigratorPrototype = {
         // We'll tell nsBrowserGlue we've imported bookmarks, but before that
         // we need to make sure we're going to know when it's finished
         // initializing places:
         let placesInitedPromise = new Promise(resolve => {
           let onPlacesInited = function() {
             Services.obs.removeObserver(onPlacesInited, TOPIC_PLACES_DEFAULTS_FINISHED);
             resolve();
           };
-          Services.obs.addObserver(onPlacesInited, TOPIC_PLACES_DEFAULTS_FINISHED, false);
+          Services.obs.addObserver(onPlacesInited, TOPIC_PLACES_DEFAULTS_FINISHED);
         });
         browserGlue.observe(null, TOPIC_DID_IMPORT_BOOKMARKS, "");
         yield placesInitedPromise;
         doMigrate();
       });
       return;
     }
     doMigrate();
@@ -860,17 +860,17 @@ this.MigrationUtils = Object.freeze({
                 break;
               }
               /* intentionally falling through to error out here for
                  non-null/undefined things: */
             default:
               throw new Error("Unexpected parameter type " + (typeof item) + ": " + item);
           }
         }
-        params.appendElement(comtaminatedVal, false);
+        params.appendElement(comtaminatedVal);
       }
     } else {
       params = aParams;
     }
 
     Services.ww.openWindow(aOpener,
                            "chrome://browser/content/migration/migration.xul",
                            "_blank",
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -19,21 +19,21 @@ var MigrationWizard = { /* exported Migr
   _itemsFlags: kIMig.ALL,       // Selected Import Data Sources (16-bit bitfield)
   _selectedProfile: null,       // Selected Profile name to import from
   _wiz: null,
   _migrator: null,
   _autoMigrate: null,
 
   init() {
     let os = Services.obs;
-    os.addObserver(this, "Migration:Started", false);
-    os.addObserver(this, "Migration:ItemBeforeMigrate", false);
-    os.addObserver(this, "Migration:ItemAfterMigrate", false);
-    os.addObserver(this, "Migration:ItemError", false);
-    os.addObserver(this, "Migration:Ended", false);
+    os.addObserver(this, "Migration:Started");
+    os.addObserver(this, "Migration:ItemBeforeMigrate");
+    os.addObserver(this, "Migration:ItemAfterMigrate");
+    os.addObserver(this, "Migration:ItemError");
+    os.addObserver(this, "Migration:Ended");
 
     this._wiz = document.documentElement;
 
     let args = window.arguments;
     let entryPointId = args[0] || MigrationUtils.MIGRATION_ENTRYPOINT_UNKNOWN;
     Services.telemetry.getHistogramById("FX_MIGRATION_ENTRY_POINT").add(entryPointId);
     this.isInitialMigration = entryPointId == MigrationUtils.MIGRATION_ENTRYPOINT_FIRSTRUN;
 
--- a/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js
+++ b/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js
@@ -56,17 +56,17 @@ add_task(function* checkNotificationsDis
     bmObserver = {
       onItemRemoved(itemId, parentId, index, itemType, uri, removedGuid) {
         if (guid == removedGuid) {
           haveRemovedBookmark = true;
           resolve();
         }
       },
     };
-    PlacesUtils.bookmarks.addObserver(bmObserver, false);
+    PlacesUtils.bookmarks.addObserver(bmObserver);
     registerCleanupFunction(() => PlacesUtils.bookmarks.removeObserver(bmObserver));
   });
 
   let firstTabNotificationRemovedPromise = new Promise(resolve => {
     let notification = getNotification(firstTab.linkedBrowser);
     // Save this reference because notification.parentNode will be null once it's removed.
     let notificationBox = notification.parentNode;
     let mut = new MutationObserver(mutations => {
@@ -98,17 +98,17 @@ add_task(function* checkNotificationsDis
   let prefResetPromise = new Promise(resolve => {
     const kObservedPref = "browser.migrate.automigrate.browser";
     let obs = () => {
       Services.prefs.removeObserver(kObservedPref, obs);
       ok(!Services.prefs.prefHasUserValue(kObservedPref),
          "Pref should have been reset");
       resolve();
     };
-    Services.prefs.addObserver(kObservedPref, obs, false);
+    Services.prefs.addObserver(kObservedPref, obs);
   });
 
   // Click "Don't keep" button:
   let notificationToActivate = getNotification(secondTab.linkedBrowser);
   notificationToActivate.querySelector("button:not(.notification-button-default)").click();
   info("Waiting for notification to be removed in first (background) tab");
   yield firstTabNotificationRemovedPromise;
   info("Waiting for bookmark to be removed");
--- a/browser/components/migration/tests/unit/head_migration.js
+++ b/browser/components/migration/tests/unit/head_migration.js
@@ -35,17 +35,17 @@ function promiseMigration(migrator, reso
   // Ensure resource migration is available.
   let availableSources = migrator.getMigrateData(aProfile, false);
   Assert.ok((availableSources & resourceType) > 0, "Resource supported by migrator");
 
   return new Promise(resolve => {
     Services.obs.addObserver(function onMigrationEnded() {
       Services.obs.removeObserver(onMigrationEnded, "Migration:Ended");
       resolve();
-    }, "Migration:Ended", false);
+    }, "Migration:Ended");
 
     migrator.migrate(resourceType, null, aProfile);
   });
 }
 
 /**
  * Replaces a directory service entry with a given nsIFile.
  */
--- a/browser/components/migration/tests/unit/test_Chrome_bookmarks.js
+++ b/browser/components/migration/tests/unit/test_Chrome_bookmarks.js
@@ -86,17 +86,17 @@ add_task(function* () {
     onBeginUpdateBatch() {},
     onEndUpdateBatch() {},
     onItemRemoved() {},
     onItemChanged() {},
     onItemVisited() {},
     onItemMoved() {},
   };
 
-  PlacesUtils.bookmarks.addObserver(bmObserver, false);
+  PlacesUtils.bookmarks.addObserver(bmObserver);
   const PROFILE = {
     id: "Default",
     name: "Default",
   };
   yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS, PROFILE);
   PlacesUtils.bookmarks.removeObserver(bmObserver);
 
   Assert.equal(itemsSeen.bookmarks, 200, "Should have seen 200 bookmarks.");
--- a/browser/components/migration/tests/unit/test_Edge_db_migration.js
+++ b/browser/components/migration/tests/unit/test_Edge_db_migration.js
@@ -432,17 +432,17 @@ add_task(function*() {
     },
     onBeginUpdateBatch() {},
     onEndUpdateBatch() {},
     onItemRemoved() {},
     onItemChanged() {},
     onItemVisited() {},
     onItemMoved() {},
   };
-  PlacesUtils.bookmarks.addObserver(bookmarkObserver, false);
+  PlacesUtils.bookmarks.addObserver(bookmarkObserver);
 
   let migrateResult = yield new Promise(resolve => bookmarksMigrator.migrate(resolve)).catch(ex => {
     Cu.reportError(ex);
     Assert.ok(false, "Got an exception trying to migrate data! " + ex);
     return false;
   });
   PlacesUtils.bookmarks.removeObserver(bookmarkObserver);
   Assert.ok(migrateResult, "Migration should succeed");
@@ -508,17 +508,17 @@ add_task(function*() {
     },
     onBeginUpdateBatch() {},
     onEndUpdateBatch() {},
     onItemRemoved() {},
     onItemChanged() {},
     onItemVisited() {},
     onItemMoved() {},
   };
-  PlacesUtils.bookmarks.addObserver(bookmarkObserver, false);
+  PlacesUtils.bookmarks.addObserver(bookmarkObserver);
 
   let readingListMigrator = migrator.wrappedJSObject.getReadingListMigratorForTesting(db);
   Assert.ok(readingListMigrator.exists, "Should recognize db we just created");
   migrateResult = yield new Promise(resolve => readingListMigrator.migrate(resolve)).catch(ex => {
     Cu.reportError(ex);
     Assert.ok(false, "Got an exception trying to migrate data! " + ex);
     return false;
   });
--- a/browser/components/migration/tests/unit/test_IE_bookmarks.js
+++ b/browser/components/migration/tests/unit/test_IE_bookmarks.js
@@ -27,17 +27,17 @@ add_task(function* () {
     },
     onBeginUpdateBatch() {},
     onEndUpdateBatch() {},
     onItemRemoved() {},
     onItemChanged() {},
     onItemVisited() {},
     onItemMoved() {},
   };
-  PlacesUtils.bookmarks.addObserver(bmObserver, false);
+  PlacesUtils.bookmarks.addObserver(bmObserver);
 
   yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
   PlacesUtils.bookmarks.removeObserver(bmObserver);
   Assert.equal(MigrationUtils._importQuantities.bookmarks, itemCount,
                "Ensure telemetry matches actual number of imported items.");
 
   // Check the bookmarks have been imported to all the expected parents.
   Assert.equal(expectedParents.length, 0, "Got all the expected parents");
--- a/browser/components/migration/tests/unit/test_Safari_bookmarks.js
+++ b/browser/components/migration/tests/unit/test_Safari_bookmarks.js
@@ -32,17 +32,17 @@ add_task(function* () {
     },
     onBeginUpdateBatch() {},
     onEndUpdateBatch() {},
     onItemRemoved() {},
     onItemChanged() {},
     onItemVisited() {},
     onItemMoved() {},
   };
-  PlacesUtils.bookmarks.addObserver(bmObserver, false);
+  PlacesUtils.bookmarks.addObserver(bmObserver);
 
   yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
   PlacesUtils.bookmarks.removeObserver(bmObserver);
 
   // Check the bookmarks have been imported to all the expected parents.
   Assert.ok(!expectedParents.length, "No more expected parents");
   Assert.ok(gotFolder, "Should have seen the folder get imported");
   Assert.equal(itemCount, 13, "Should import all 13 items.");
--- a/browser/components/migration/tests/unit/test_automigration.js
+++ b/browser/components/migration/tests/unit/test_automigration.js
@@ -251,17 +251,17 @@ add_task(function* checkUndoRemoval() {
   let visitedURI = Services.io.newURI("http://www.example.com/");
   let frecencyUpdatePromise = new Promise(resolve => {
     let observer = {
       onManyFrecenciesChanged() {
         PlacesUtils.history.removeObserver(observer);
         resolve();
       },
     };
-    PlacesUtils.history.addObserver(observer, false);
+    PlacesUtils.history.addObserver(observer);
   });
   yield MigrationUtils.insertVisitsWrapper([{
     uri: visitedURI,
     visits: [
       {
         transitionType: PlacesUtils.history.TRANSITION_LINK,
         visitDate: now_uSec,
       },
@@ -575,17 +575,17 @@ add_task(function* checkUndoVisitsState(
   // We have to wait until frecency updates have been handled in order
   // to accurately determine whether we're doing the right thing.
   let frecencyUpdatesHandled = new Promise(resolve => {
     PlacesUtils.history.addObserver({
       onManyFrecenciesChanged() {
         PlacesUtils.history.removeObserver(this);
         resolve();
       }
-    }, false);
+    });
   });
   yield PlacesUtils.history.insertMany([{
     url: "http://www.example.com/",
     title: "Example",
     visits: [{
       date: new Date("2015-08-16"),
     }],
   }, {
@@ -641,17 +641,17 @@ add_task(function* checkUndoVisitsState(
     },
     onDeleteURI(aURI) {
       do_print("delete uri");
       Assert.ok(uriDeletedExpected.has(aURI.spec),
                 "Should be expecting uri deletion for " + aURI.spec);
       uriDeletedExpected.get(aURI.spec).resolve();
     },
   };
-  PlacesUtils.history.addObserver(observer, false);
+  PlacesUtils.history.addObserver(observer);
 
   yield AutoMigrate._removeSomeVisits(undoVisitData);
   PlacesUtils.history.removeObserver(observer);
   yield Promise.all(uriDeletedExpected.values());
   yield Promise.all(frecencyChangesExpected.values());
 
   Assert.equal(yield visitsForURL("http://www.example.com/"), 1,
                "1 example.com visit (out of 5) should have persisted despite being within the range, due to limiting");
--- a/browser/components/newtab/NewTabPrefsProvider.jsm
+++ b/browser/components/newtab/NewTabPrefsProvider.jsm
@@ -83,17 +83,17 @@ PrefsProvider.prototype = {
   },
 
   get prefsMap() {
     return gPrefsMap;
   },
 
   init() {
     for (let pref of gPrefsMap.keys()) {
-      Services.prefs.addObserver(pref, this, false);
+      Services.prefs.addObserver(pref, this);
     }
   },
 
   uninit() {
     for (let pref of gPrefsMap.keys()) {
       Services.prefs.removeObserver(pref, this);
     }
   }
--- a/browser/components/newtab/tests/xpcshell/test_AboutNewTabService.js
+++ b/browser/components/newtab/tests/xpcshell/test_AboutNewTabService.js
@@ -132,11 +132,11 @@ add_task(function* test_updates() {
 });
 
 function nextChangeNotificationPromise(aNewURL, testMessage) {
   return new Promise(resolve => {
     Services.obs.addObserver(function observer(aSubject, aTopic, aData) {  // jshint unused:false
       Services.obs.removeObserver(observer, aTopic);
       Assert.equal(aData, aNewURL, testMessage);
       resolve();
-    }, "newtab-url-changed", false);
+    }, "newtab-url-changed");
   });
 }
--- a/browser/components/newtab/tests/xpcshell/test_NewTabSearchProvider.js
+++ b/browser/components/newtab/tests/xpcshell/test_NewTabSearchProvider.js
@@ -28,17 +28,17 @@ function hasProp(obj) {
 add_task(function* test_search() {
   ContentSearch.init();
   let observerPromise = new Promise(resolve => {
     Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
       if (aData === "init-complete" && aTopic === "browser-search-service") {
         Services.obs.removeObserver(observer, "browser-search-service");
         resolve();
       }
-    }, "browser-search-service", false);
+    }, "browser-search-service");
   });
   Services.search.init();
   yield observerPromise;
   do_check_true(Services.search.isInitialized);
 
   // get initial state of search and check it has correct properties
   let state = yield NewTabSearchProvider.search.asyncGetState();
   let stateProps = hasProp(state);
--- a/browser/components/newtab/tests/xpcshell/test_NewTabURL.js
+++ b/browser/components/newtab/tests/xpcshell/test_NewTabURL.js
@@ -42,11 +42,11 @@ add_task(function*() {
 });
 
 function promiseNewtabURLNotification(aNewURL) {
   return new Promise(resolve => {
     Services.obs.addObserver(function observer(aSubject, aTopic, aData) { // jshint ignore:line
       Services.obs.removeObserver(observer, aTopic);
       Assert.equal(aData, aNewURL, "Data for newtab-url-changed notification should be new URL.");
       resolve();
-    }, "newtab-url-changed", false);
+    }, "newtab-url-changed");
   });
 }
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -192,43 +192,43 @@ function openWindow(parent, url, target,
   if (stringArgs) {
     // put the URIs into argArray
     var uriArray = Components.classes["@mozilla.org/array;1"]
                        .createInstance(Components.interfaces.nsIMutableArray);
     stringArgs.forEach(function(uri) {
       var sstring = Components.classes["@mozilla.org/supports-string;1"]
                               .createInstance(nsISupportsString);
       sstring.data = uri;
-      uriArray.appendElement(sstring, /* weak = */ false);
+      uriArray.appendElement(sstring);
     });
-    argArray.appendElement(uriArray, /* weak =*/ false);
+    argArray.appendElement(uriArray);
   } else {
-    argArray.appendElement(null, /* weak =*/ false);
+    argArray.appendElement(null);
   }
 
   // Pass these as null to ensure that we always trigger the "single URL"
   // behavior in browser.js's gBrowserInit.onLoad (which handles the window
   // arguments)
-  argArray.appendElement(null, /* weak =*/ false); // charset
-  argArray.appendElement(null, /* weak =*/ false); // referer
-  argArray.appendElement(null, /* weak =*/ false); // postData
-  argArray.appendElement(null, /* weak =*/ false); // allowThirdPartyFixup
+  argArray.appendElement(null); // charset
+  argArray.appendElement(null); // referer
+  argArray.appendElement(null); // postData
+  argArray.appendElement(null); // allowThirdPartyFixup
 
   return Services.ww.openWindow(parent, url, target, features, argArray);
 }
 
 function openPreferences() {
   var args = Components.classes["@mozilla.org/array;1"]
                      .createInstance(Components.interfaces.nsIMutableArray);
 
   var wuri = Components.classes["@mozilla.org/supports-string;1"]
                        .createInstance(Components.interfaces.nsISupportsString);
   wuri.data = "about:preferences";
 
-  args.appendElement(wuri, /* weak = */ false);
+  args.appendElement(wuri);
 
   Services.ww.openWindow(null, gBrowserContentHandler.chromeURL,
                          "_blank",
                          "chrome,dialog=no,all",
                          args);
 }
 
 function logSystemBasedSearch(engine) {
@@ -246,20 +246,20 @@ function doSearch(searchTerm, cmdLine) {
   // fill our nsIMutableArray with uri-as-wstring, null, null, postData
   var args = Components.classes["@mozilla.org/array;1"]
                      .createInstance(Components.interfaces.nsIMutableArray);
 
   var wuri = Components.classes["@mozilla.org/supports-string;1"]
                        .createInstance(Components.interfaces.nsISupportsString);
   wuri.data = submission.uri.spec;
 
-  args.appendElement(wuri, /* weak =*/ false);
-  args.appendElement(null, /* weak =*/ false);
-  args.appendElement(null, /* weak =*/ false);
-  args.appendElement(submission.postData, /* weak =*/ false);
+  args.appendElement(wuri);
+  args.appendElement(null);
+  args.appendElement(null);
+  args.appendElement(submission.postData);
 
   // XXXbsmedberg: use handURIToExistingBrowser to obey tabbed-browsing
   // preferences, but need nsIBrowserDOMWindow extensions
 
   return Services.ww.openWindow(null, gBrowserContentHandler.chromeURL,
                                 "_blank",
                                 "chrome,dialog=no,all" +
                                 gBrowserContentHandler.getFeatures(cmdLine),
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -300,17 +300,17 @@ BrowserGlue.prototype = {
         } else if (data == "force-distribution-customization") {
           this._distributionCustomizer.applyPrefDefaults();
           this._distributionCustomizer.applyCustomizations();
           // To apply distribution bookmarks use "places-init-complete".
         } else if (data == "force-places-init") {
           this._initPlaces(false);
         } else if (data == "smart-bookmarks-init") {
           this.ensurePlacesDefaultQueriesInitialized().then(() => {
-            Services.obs.notifyObservers(null, "test-smart-bookmarks-done", null);
+            Services.obs.notifyObservers(null, "test-smart-bookmarks-done");
           });
         } else if (data == "mock-fxaccounts") {
           Object.defineProperty(this, "fxAccounts", {
             value: subject.wrappedJSObject
           });
         }
         break;
       case "initial-migration-will-import-default-bookmarks":
@@ -386,48 +386,48 @@ BrowserGlue.prototype = {
         this._sanitizer.onStartup();
         break;
     }
   },
 
   // initialization (called on application startup)
   _init: function BG__init() {
     let os = Services.obs;
-    os.addObserver(this, "notifications-open-settings", false);
-    os.addObserver(this, "prefservice:after-app-defaults", false);
-    os.addObserver(this, "final-ui-startup", false);
-    os.addObserver(this, "browser-delayed-startup-finished", false);
-    os.addObserver(this, "sessionstore-windows-restored", false);
-    os.addObserver(this, "browser:purge-session-history", false);
-    os.addObserver(this, "quit-application-requested", false);
-    os.addObserver(this, "quit-application-granted", false);
+    os.addObserver(this, "notifications-open-settings");
+    os.addObserver(this, "prefservice:after-app-defaults");
+    os.addObserver(this, "final-ui-startup");
+    os.addObserver(this, "browser-delayed-startup-finished");
+    os.addObserver(this, "sessionstore-windows-restored");
+    os.addObserver(this, "browser:purge-session-history");
+    os.addObserver(this, "quit-application-requested");
+    os.addObserver(this, "quit-application-granted");
     if (OBSERVE_LASTWINDOW_CLOSE_TOPICS) {
-      os.addObserver(this, "browser-lastwindow-close-requested", false);
-      os.addObserver(this, "browser-lastwindow-close-granted", false);
+      os.addObserver(this, "browser-lastwindow-close-requested");
+      os.addObserver(this, "browser-lastwindow-close-granted");
     }
-    os.addObserver(this, "weave:service:ready", false);
-    os.addObserver(this, "fxaccounts:onverified", false);
-    os.addObserver(this, "fxaccounts:device_connected", false);
-    os.addObserver(this, "fxaccounts:device_disconnected", false);
-    os.addObserver(this, "weave:engine:clients:display-uris", false);
-    os.addObserver(this, "session-save", false);
-    os.addObserver(this, "places-init-complete", false);
+    os.addObserver(this, "weave:service:ready");
+    os.addObserver(this, "fxaccounts:onverified");
+    os.addObserver(this, "fxaccounts:device_connected");
+    os.addObserver(this, "fxaccounts:device_disconnected");
+    os.addObserver(this, "weave:engine:clients:display-uris");
+    os.addObserver(this, "session-save");
+    os.addObserver(this, "places-init-complete");
     this._isPlacesInitObserver = true;
-    os.addObserver(this, "places-database-locked", false);
+    os.addObserver(this, "places-database-locked");
     this._isPlacesLockedObserver = true;
-    os.addObserver(this, "distribution-customization-complete", false);
-    os.addObserver(this, "handle-xul-text-link", false);
-    os.addObserver(this, "profile-before-change", false);
+    os.addObserver(this, "distribution-customization-complete");
+    os.addObserver(this, "handle-xul-text-link");
+    os.addObserver(this, "profile-before-change");
     if (AppConstants.MOZ_TELEMETRY_REPORTING) {
-      os.addObserver(this, "keyword-search", false);
+      os.addObserver(this, "keyword-search");
     }
-    os.addObserver(this, "browser-search-engine-modified", false);
-    os.addObserver(this, "restart-in-safe-mode", false);
-    os.addObserver(this, "flash-plugin-hang", false);
-    os.addObserver(this, "xpi-signature-changed", false);
+    os.addObserver(this, "browser-search-engine-modified");
+    os.addObserver(this, "restart-in-safe-mode");
+    os.addObserver(this, "flash-plugin-hang");
+    os.addObserver(this, "xpi-signature-changed");
 
     this._flashHangCount = 0;
     this._firstWindowReady = new Promise(resolve => this._firstWindowLoaded = resolve);
 
     if (AppConstants.platform == "macosx") {
       // Handles prompting to inform about incompatibilites when accessibility
       // and e10s are active together.
       E10SAccessibilityCheck.init();
@@ -556,17 +556,17 @@ BrowserGlue.prototype = {
     }
 
     TabCrashHandler.init();
     if (AppConstants.MOZ_CRASHREPORTER) {
       PluginCrashReporter.init();
       UnsubmittedCrashHandler.init();
     }
 
-    Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
+    Services.obs.notifyObservers(null, "browser-ui-startup-complete");
   },
 
   _checkForOldBuildUpdates() {
     // check for update if our build is old
     if (AppConstants.MOZ_UPDATER &&
         Services.prefs.getBoolPref("app.update.enabled") &&
         Services.prefs.getBoolPref("app.update.checkInstallTime")) {
 
@@ -1028,19 +1028,19 @@ BrowserGlue.prototype = {
                           .add(isDefaultError);
         Services.telemetry.getHistogramById("BROWSER_SET_DEFAULT_ALWAYS_CHECK")
                           .add(shouldCheck);
         Services.telemetry.getHistogramById("BROWSER_SET_DEFAULT_DIALOG_PROMPT_RAWCOUNT")
                           .add(promptCount);
       } catch (ex) { /* Don't break the default prompt if telemetry is broken. */ }
 
       if (willPrompt) {
-        Services.tm.mainThread.dispatch(function() {
+        Services.tm.dispatchToMainThread(function() {
           DefaultBrowserCheck.prompt(RecentWindow.getMostRecentBrowserWindow());
-        }, Ci.nsIThread.DISPATCH_NORMAL);
+        });
       }
     }
 
     E10SAccessibilityCheck.onWindowsRestored();
   },
 
   _createExtraDefaultProfile() {
     if (!AppConstants.MOZ_DEV_EDITION) {
@@ -1490,17 +1490,17 @@ BrowserGlue.prototype = {
         this._idleService.addIdleObserver(this, this._bookmarksBackupIdleTime);
       }
 
     }.bind(this)).catch(ex => {
       Cu.reportError(ex);
     }).then(() => {
       // NB: deliberately after the catch so that we always do this, even if
       // we threw halfway through initializing in the Task above.
-      Services.obs.notifyObservers(null, "places-browser-init-complete", "");
+      Services.obs.notifyObservers(null, "places-browser-init-complete");
     });
   },
 
   /**
    * If a backup for today doesn't exist, this creates one.
    */
   _backupBookmarks: function BG__backupBookmarks() {
     return Task.spawn(function*() {
--- a/browser/components/originattributes/test/browser/browser_clientAuth.js
+++ b/browser/components/originattributes/test/browser/browser_clientAuth.js
@@ -2,17 +2,17 @@ let certCached = true;
 let secondTabStarted = false;
 
 function onCertDialogLoaded(subject) {
   certCached = false;
   // Click OK.
   subject.acceptDialog();
 }
 
-Services.obs.addObserver(onCertDialogLoaded, "cert-dialog-loaded", false);
+Services.obs.addObserver(onCertDialogLoaded, "cert-dialog-loaded");
 
 registerCleanupFunction(() => {
   Services.obs.removeObserver(onCertDialogLoaded, "cert-dialog-loaded");
 });
 
 function* setup() {
   yield SpecialPowers.pushPrefEnv({
     set: [["security.default_personal_cert", "Ask Every Time"]]
--- a/browser/components/originattributes/test/browser/browser_favicon_firstParty.js
+++ b/browser/components/originattributes/test/browser/browser_favicon_firstParty.js
@@ -42,17 +42,17 @@ function clearAllPlacesFavicons() {
       observe(aSubject, aTopic, aData) {
         if (aTopic === "places-favicons-expired") {
           resolve();
           Services.obs.removeObserver(observer, "places-favicons-expired");
         }
       }
     };
 
-    Services.obs.addObserver(observer, "places-favicons-expired", false);
+    Services.obs.addObserver(observer, "places-favicons-expired");
     faviconService.expireAllFavicons();
   });
 }
 
 function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
   let faviconReqXUL = false;
   let faviconReqPlaces = false;
   let expectedPrincipal = Services.scriptSecurityManager
@@ -103,17 +103,17 @@ function observeFavicon(aFirstPartyDomai
 
         if (faviconReqXUL && faviconReqPlaces) {
           Services.obs.removeObserver(observer, "http-on-modify-request");
           resolve();
         }
       }
     };
 
-    Services.obs.addObserver(observer, "http-on-modify-request", false);
+    Services.obs.addObserver(observer, "http-on-modify-request");
   });
 }
 
 function waitOnFaviconResponse(aFaviconURL) {
   return new Promise(resolve => {
     let observer = {
       observe(aSubject, aTopic, aData) {
         if (aTopic === "http-on-examine-response" ||
@@ -133,35 +133,35 @@ function waitOnFaviconResponse(aFaviconU
 
           resolve(result);
           Services.obs.removeObserver(observer, "http-on-examine-response");
           Services.obs.removeObserver(observer, "http-on-examine-cached-response");
         }
       }
     };
 
-    Services.obs.addObserver(observer, "http-on-examine-response", false);
-    Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
+    Services.obs.addObserver(observer, "http-on-examine-response");
+    Services.obs.addObserver(observer, "http-on-examine-cached-response");
   });
 }
 
 function waitOnFaviconLoaded(aFaviconURL) {
   return new Promise(resolve => {
     let observer = {
       onPageChanged(uri, attr, value, id) {
 
         if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
             value === aFaviconURL) {
           resolve();
           PlacesUtils.history.removeObserver(observer, false);
         }
       },
     };
 
-    PlacesUtils.history.addObserver(observer, false);
+    PlacesUtils.history.addObserver(observer);
   });
 }
 
 function* openTab(aURL) {
   let tab = gBrowser.addTab(aURL);
 
   // Select tab and make sure its browser is focused.
   gBrowser.selectedTab = tab;
--- a/browser/components/originattributes/test/browser/browser_favicon_userContextId.js
+++ b/browser/components/originattributes/test/browser/browser_favicon_userContextId.js
@@ -42,17 +42,17 @@ function clearAllPlacesFavicons() {
       observe(aSubject, aTopic, aData) {
         if (aTopic === "places-favicons-expired") {
           resolve();
           Services.obs.removeObserver(observer, "places-favicons-expired");
         }
       }
     };
 
-    Services.obs.addObserver(observer, "places-favicons-expired", false);
+    Services.obs.addObserver(observer, "places-favicons-expired");
     faviconService.expireAllFavicons();
   });
 }
 
 function FaviconObserver(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL) {
   this.reset(aUserContextId, aExpectedCookie, aPageURI, aFaviconURL);
 }
 
@@ -132,17 +132,17 @@ function waitOnFaviconLoaded(aFaviconURL
         if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
             value === aFaviconURL) {
           resolve();
           PlacesUtils.history.removeObserver(observer, false);
         }
       },
     };
 
-    PlacesUtils.history.addObserver(observer, false);
+    PlacesUtils.history.addObserver(observer);
   });
 }
 
 function* generateCookies(aHost) {
   // we generate two different cookies for two userContextIds.
   let cookies = [];
   cookies.push(Math.random().toString());
   cookies.push(Math.random().toString());
@@ -171,17 +171,17 @@ function* doTest(aTestPage, aFaviconHost
 
   // Create the observer object for observing request channels of the personal
   // container.
   let observer = new FaviconObserver(USER_CONTEXT_ID_PERSONAL, cookies[0], pageURI, aFaviconURL);
 
   // Add the observer earlier in case we miss it.
   let promiseWaitOnFaviconLoaded = waitOnFaviconLoaded(aFaviconURL);
 
-  Services.obs.addObserver(observer, "http-on-modify-request", false);
+  Services.obs.addObserver(observer, "http-on-modify-request");
 
   // Open the tab with the personal container.
   let tabInfo = yield openTabInUserContext(aTestPage, USER_CONTEXT_ID_PERSONAL);
 
   // Waiting for favicon requests are all made.
   yield observer.promise;
   // Waiting for favicon loaded.
   yield promiseWaitOnFaviconLoaded;
--- a/browser/components/originattributes/test/browser/browser_httpauth.js
+++ b/browser/components/originattributes/test/browser/browser_httpauth.js
@@ -30,17 +30,17 @@ function fileHandler(metadata, response)
 function onCommonDialogLoaded(subject) {
   // Submit random account and password
   let dialog = subject.Dialog;
   dialog.ui.loginTextbox.setAttribute("value", Math.random());
   dialog.ui.password1Textbox.setAttribute("value", Math.random());
   dialog.ui.button0.click();
 }
 
-Services.obs.addObserver(onCommonDialogLoaded, "common-dialog-loaded", false);
+Services.obs.addObserver(onCommonDialogLoaded, "common-dialog-loaded");
 
 registerCleanupFunction(() => {
   Services.obs.removeObserver(onCommonDialogLoaded, "common-dialog-loaded");
   server.stop(() => {
     server = null;
   });
 });
 
--- a/browser/components/places/PlacesUIUtils.jsm
+++ b/browser/components/places/PlacesUIUtils.jsm
@@ -196,17 +196,17 @@ let InternalFaviconLoader = {
   },
 
   ensureInitialized() {
     if (this._initialized) {
       return;
     }
     this._initialized = true;
 
-    Services.obs.addObserver(this, "inner-window-destroyed", false);
+    Services.obs.addObserver(this, "inner-window-destroyed");
     Services.ppmm.addMessageListener("Toolkit:inner-window-destroyed", msg => {
       this.removeRequestsForInner(msg.data);
     });
   },
 
   loadFavicon(browser, principal, uri) {
     this.ensureInitialized();
     let win = browser.ownerGlobal;
@@ -942,17 +942,17 @@ this.PlacesUIUtils = {
     // open (Bug 630255).
     var where = browserWindow ?
                 browserWindow.whereToOpenLink(aEvent, false, true) : "window";
     if (where == "window") {
       // There is no browser window open, thus open a new one.
       var uriList = PlacesUtils.toISupportsString(urls.join("|"));
       var args = Cc["@mozilla.org/array;1"].
                   createInstance(Ci.nsIMutableArray);
-      args.appendElement(uriList, /* weak =*/ false);
+      args.appendElement(uriList);
       browserWindow = Services.ww.openWindow(aWindow,
                                              "chrome://browser/content/browser.xul",
                                              null, "chrome,dialog=no,all", args);
       return;
     }
 
     var loadInBackground = where == "tabshifted" ? true : false;
     // For consistency, we want all the bookmarks to open in new tabs, instead
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -55,17 +55,17 @@ PlacesViewBase.prototype = {
     let history = PlacesUtils.history;
     let queries = { }, options = { };
     history.queryStringToQueries(val, queries, { }, options);
     if (!queries.value.length)
       queries.value = [history.getNewQuery()];
 
     let result = history.executeQueries(queries.value, queries.value.length,
                                         options.value);
-    result.addObserver(this, false);
+    result.addObserver(this);
     return val;
   },
 
   _result: null,
   get result() {
     return this._result;
   },
   set result(val) {
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -272,17 +272,17 @@ var gEditItemOverlay = {
       this._element("itemsCountText").value =
         PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
                                       uris.length,
                                       [uris.length]);
     }
 
     // Observe changes.
     if (!this._observersAdded) {
-      PlacesUtils.bookmarks.addObserver(this, false);
+      PlacesUtils.bookmarks.addObserver(this);
       window.addEventListener("unload", this);
       this._observersAdded = true;
     }
 
     let focusElement = () => {
       // The focusedElement possible values are:
       //  * preferred: focus the field that the user touched first the last
       //    time the pane was shown (either namePicker or tagsField)
@@ -812,17 +812,17 @@ var gEditItemOverlay = {
           containerId != PlacesUtils.toolbarFolderId &&
           containerId != PlacesUtils.bookmarksMenuFolderId) {
         this._markFolderAsRecentlyUsed(containerId)
             .catch(Components.utils.reportError);
       }
 
       // Auto-show the bookmarks toolbar when adding / moving an item there.
       if (containerId == PlacesUtils.toolbarFolderId) {
-        Services.obs.notifyObservers(null, "autoshow-bookmarks-toolbar", null);
+        Services.obs.notifyObservers(null, "autoshow-bookmarks-toolbar");
       }
     }
 
     // Update folder-tree selection
     var folderTreeRow = this._element("folderTreeRow");
     if (!folderTreeRow.collapsed) {
       var selectedNode = this._folderTree.selectedNode;
       if (!selectedNode ||
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -109,17 +109,17 @@
             this.controllers.appendController(this._controller);
           }
 
           let treeView = new PlacesTreeView(this.flatList, callback, this._controller);
 
           // Observer removal is done within the view itself.  When the tree
           // goes away, treeboxobject calls view.setTree(null), which then
           // calls removeObserver.
-          result.addObserver(treeView, false);
+          result.addObserver(treeView);
           this.view = treeView;
 
           if (this.getAttribute("selectfirstnode") == "true" && treeView.rowCount > 0) {
             treeView.selection.select(0);
           }
 
           this._cachedInsertionPoint = undefined;
         ]]></body>
--- a/browser/components/places/tests/browser/browser_library_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_library_views_liveupdate.js
@@ -27,18 +27,18 @@ function test() {
 }
 
 /**
  * Adds bookmarks observer, and executes a bunch of bookmarks operations.
  */
 function startTest() {
   var bs = PlacesUtils.bookmarks;
   // Add observers.
-  bs.addObserver(bookmarksObserver, false);
-  PlacesUtils.annotations.addObserver(bookmarksObserver, false);
+  bs.addObserver(bookmarksObserver);
+  PlacesUtils.annotations.addObserver(bookmarksObserver);
   var addedBookmarks = [];
 
   // MENU
   ok(true, "*** Acting on menu bookmarks");
   var id = bs.insertBookmark(bs.bookmarksMenuFolder,
                              PlacesUtils._uri("http://bm1.mozilla.org/"),
                              bs.DEFAULT_INDEX,
                              "bm1");
--- a/browser/components/places/tests/browser/browser_markPageAsFollowedLink.js
+++ b/browser/components/places/tests/browser/browser_markPageAsFollowedLink.js
@@ -22,17 +22,17 @@ add_task(function* test() {
       } else if (url == RIGHT_URL ) {
         is((yield getTransitionForUrl(url)),
            PlacesUtils.history.TRANSITION_FRAMED_LINK,
            "User activated visits should get a FRAMED_LINK transition.");
         Services.obs.removeObserver(observe, "uri-visit-saved");
         deferredRightFrameVisit.resolve();
       }
     });
-  }, "uri-visit-saved", false);
+  }, "uri-visit-saved");
 
   // Open a tab and wait for all the subframes to load.
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE_URL);
 
   // Wait for the left frame visit to be registered.
   info("Waiting left frame visit");
   yield deferredLeftFrameVisit.promise;
 
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -93,18 +93,18 @@ function test() {
 
           aSubject.Dialog.ui.button0.click();
 
           executeSoon(function() {
               SidebarUI.hide();
               currentTest.cleanup(postFunc);
             });
         }
-        Services.obs.addObserver(observer, "common-dialog-loaded", false);
-        Services.obs.addObserver(observer, "tabmodal-dialog-loaded", false);
+        Services.obs.addObserver(observer, "common-dialog-loaded");
+        Services.obs.addObserver(observer, "tabmodal-dialog-loaded");
 
         let tree = sidebar.contentDocument.getElementById(currentTest.treeName);
 
         // Select the inserted places item.
         currentTest.selectNode(tree);
 
         synthesizeClickOnSelectedTreeCell(tree);
         // Now, wait for the observer to catch the alert dialog.
--- a/browser/components/places/tests/browser/browser_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_views_liveupdate.js
@@ -52,18 +52,18 @@ function fakeOpenPopup(aPopup) {
 }
 
 /**
  * Adds bookmarks observer, and executes a bunch of bookmarks operations.
  */
 function startTest() {
   var bs = PlacesUtils.bookmarks;
   // Add observers.
-  bs.addObserver(bookmarksObserver, false);
-  PlacesUtils.annotations.addObserver(bookmarksObserver, false);
+  bs.addObserver(bookmarksObserver);
+  PlacesUtils.annotations.addObserver(bookmarksObserver);
   var addedBookmarks = [];
 
   // MENU
   info("*** Acting on menu bookmarks");
   var id = bs.insertBookmark(bs.bookmarksMenuFolder,
                              PlacesUtils._uri("http://bm1.mozilla.org/"),
                              bs.DEFAULT_INDEX,
                              "bm1");
--- a/browser/components/places/tests/browser/head.js
+++ b/browser/components/places/tests/browser/head.js
@@ -173,17 +173,17 @@ function promiseBookmarksNotification(no
               executeSoon(resolve);
             } else {
               info(`promiseBookmarksNotification: skip cause condition doesn't apply to ${JSON.stringify(args)}`);
             }
           }
         return () => {};
       }
     });
-    PlacesUtils.bookmarks.addObserver(proxifiedObserver, false);
+    PlacesUtils.bookmarks.addObserver(proxifiedObserver);
   });
 }
 
 function promiseHistoryNotification(notification, conditionFn) {
   info(`Waiting for ${notification}`);
   return new Promise((resolve) => {
     let proxifiedObserver = new Proxy({}, {
       get: (target, name) => {
@@ -194,17 +194,17 @@ function promiseHistoryNotification(noti
             if (conditionFn.apply(this, args)) {
               PlacesUtils.history.removeObserver(proxifiedObserver, false);
               executeSoon(resolve);
             }
           }
         return () => {};
       }
     });
-    PlacesUtils.history.addObserver(proxifiedObserver, false);
+    PlacesUtils.history.addObserver(proxifiedObserver);
   });
 }
 
 /**
  * Makes the specified toolbar visible or invisible and returns a Promise object
  * that is resolved when the toolbar has completed any animations associated
  * with hiding or showing the toolbar.
  *
--- a/browser/components/places/tests/chrome/test_bug549192.xul
+++ b/browser/components/places/tests/chrome/test_bug549192.xul
@@ -52,17 +52,17 @@
          onDeleteURI(aURI, aGUID, aReason) {
            PlacesUtils.history.removeObserver(historyObserver);
            resolve();
          },
          onPageChanged() {},
          onDeleteVisits(aURI, aTime) { },
        };
 
-       PlacesUtils.history.addObserver(historyObserver, false);
+       PlacesUtils.history.addObserver(historyObserver);
      });
     }
 
     function runTest() {
       SimpleTest.waitForExplicitFinish();
 
       Task.spawn(function* () {
         yield PlacesTestUtils.clearHistory();
--- a/browser/components/places/tests/unit/test_PUIU_makeTransaction.js
+++ b/browser/components/places/tests/unit/test_PUIU_makeTransaction.js
@@ -53,17 +53,17 @@ function waitForBookmarkNotification(aNo
       return this.validate(arguments.callee.name, arguments);
     },
     onItemMoved: function onItemMoved(aItemId, aOldParentId, aOldIndex,
                                       aNewParentId, aNewIndex, aItemType) {
       this.validate(arguments.callee.name, { id: aItemId,
                                              index: aNewIndex,
                                              type: aItemType });
     }
-  }, false);
+  });
 }
 
 function wrapNodeByIdAndParent(aItemId, aParentId) {
   let wrappedNode;
   let root = PlacesUtils.getFolderContents(aParentId, false, false).root;
   for (let i = 0; i < root.childCount; ++i) {
     let node = root.getChild(i);
     if (node.itemId == aItemId) {
--- a/browser/components/places/tests/unit/test_browserGlue_bookmarkshtml.js
+++ b/browser/components/places/tests/unit/test_browserGlue_bookmarkshtml.js
@@ -24,10 +24,10 @@ add_task(function* () {
 
   // Initialize Places through the History Service.
   Cc["@mozilla.org/browser/nav-history-service;1"]
     .getService(Ci.nsINavHistoryService);
 
   Services.obs.addObserver(function observer() {
     Services.obs.removeObserver(observer, "profile-before-change");
     check_bookmarks_html();
-  }, "profile-before-change", false);
+  }, "profile-before-change");
 });
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/components/preferences/SiteDataManager.jsm
@@ -38,17 +38,17 @@ this.SiteDataManager = {
 
   _updateQuotaPromise: null,
 
   _updateDiskCachePromise: null,
 
   _quotaUsageRequests: null,
 
   updateSites() {
-    Services.obs.notifyObservers(null, "sitedatamanager:updating-sites", null);
+    Services.obs.notifyObservers(null, "sitedatamanager:updating-sites");
 
     // Clear old data and requests first
     this._sites.clear();
     this._cancelQuotaUpdate();
 
     // Collect sites granted/rejected with the persistent-storage permission
     let perm = null;
     let status = null;
@@ -69,17 +69,17 @@ this.SiteDataManager = {
     }
 
     this._updateQuota();
     this._updateAppCache();
     this._updateDiskCache();
 
     Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise])
            .then(() => {
-             Services.obs.notifyObservers(null, "sitedatamanager:sites-updated", null);
+             Services.obs.notifyObservers(null, "sitedatamanager:sites-updated");
            });
   },
 
   _updateQuota() {
     this._quotaUsageRequests = [];
     let promises = [];
     for (let site of this._sites.values()) {
       promises.push(new Promise(resolve => {
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -21,18 +21,18 @@ var gCookiesWindow = {
   _hosts: {},
   _hostOrder: [],
   _tree: null,
   _bundle: null,
 
   init() {
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
-    os.addObserver(this, "cookie-changed", false);
-    os.addObserver(this, "perm-changed", false);
+    os.addObserver(this, "cookie-changed");
+    os.addObserver(this, "perm-changed");
 
     this._bundle = document.getElementById("bundlePreferences");
     this._tree = document.getElementById("cookiesList");
 
     let removeAllCookies = document.getElementById("removeAllCookies");
     removeAllCookies.setAttribute("accesskey", this._bundle.getString("removeAllCookies.accesskey"));
     let removeSelectedCookies = document.getElementById("removeSelectedCookies");
     removeSelectedCookies.setAttribute("accesskey", this._bundle.getString("removeSelectedCookies.accesskey"));
--- a/browser/components/preferences/in-content-old/advanced.js
+++ b/browser/components/preferences/in-content-old/advanced.js
@@ -34,33 +34,33 @@ var gAdvancedPane = {
         advancedPrefs.selectedIndex = preference.value;
 
     if (AppConstants.MOZ_UPDATER) {
       let onUnload = function() {
         window.removeEventListener("unload", onUnload);
         Services.prefs.removeObserver("app.update.", this);
       }.bind(this);
       window.addEventListener("unload", onUnload);
-      Services.prefs.addObserver("app.update.", this, false);
+      Services.prefs.addObserver("app.update.", this);
       this.updateReadPrefs();
     }
     if (AppConstants.MOZ_CRASHREPORTER) {
       this.initSubmitCrashes();
     }
     this.initTelemetry();
     if (AppConstants.MOZ_TELEMETRY_REPORTING) {
       this.initSubmitHealthReport();
     }
     this.updateOnScreenKeyboardVisibility();
     this.updateCacheSizeInputField();
     this.updateActualCacheSize();
 
     if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
-      Services.obs.addObserver(this, "sitedatamanager:sites-updated", false);
-      Services.obs.addObserver(this, "sitedatamanager:updating-sites", false);
+      Services.obs.addObserver(this, "sitedatamanager:sites-updated");
+      Services.obs.addObserver(this, "sitedatamanager:updating-sites");
       let unload = () => {
         window.removeEventListener("unload", unload);
         Services.obs.removeObserver(this, "sitedatamanager:sites-updated");
         Services.obs.removeObserver(this, "sitedatamanager:updating-sites");
       };
       window.addEventListener("unload", unload);
       SiteDataManager.updateSites();
       setEventListener("clearSiteDataButton", "command",
--- a/browser/components/preferences/in-content-old/applications.js
+++ b/browser/components/preferences/in-content-old/applications.js
@@ -217,17 +217,17 @@ HandlerInfoWrapper.prototype = {
   },
 
   addPossibleApplicationHandler(aNewHandler) {
     var possibleApps = this.possibleApplicationHandlers.enumerate();
     while (possibleApps.hasMoreElements()) {
       if (possibleApps.getNext().equals(aNewHandler))
         return;
     }
-    this.possibleApplicationHandlers.appendElement(aNewHandler, false);
+    this.possibleApplicationHandlers.appendElement(aNewHandler);
   },
 
   removePossibleApplicationHandler(aHandler) {
     var defaultApp = this.preferredApplicationHandler;
     if (defaultApp && aHandler.equals(defaultApp)) {
       // If the app we remove was the default app, we must make sure
       // it won't be used anymore
       this.alwaysAskBeforeHandling = true;
@@ -567,23 +567,23 @@ FeedHandlerInfo.prototype = {
     // only a single path.  But we display all the local apps the user chooses
     // while the prefpane is open, only dropping the list when the user closes
     // the prefpane, for maximum usability and consistency with other types.
     var preferredAppFile = this.element(this._prefSelectedApp).value;
     if (preferredAppFile) {
       let preferredApp = getLocalHandlerApp(preferredAppFile);
       let defaultApp = this._defaultApplicationHandler;
       if (!defaultApp || !defaultApp.equals(preferredApp))
-        this._possibleApplicationHandlers.appendElement(preferredApp, false);
+        this._possibleApplicationHandlers.appendElement(preferredApp);
     }
 
     // Add the registered web handlers.  There can be any number of these.
     var webHandlers = this._converterSvc.getContentHandlers(this.type);
     for (let webHandler of webHandlers)
-      this._possibleApplicationHandlers.appendElement(webHandler, false);
+      this._possibleApplicationHandlers.appendElement(webHandler);
 
     return this._possibleApplicationHandlers;
   },
 
   __defaultApplicationHandler: undefined,
   get _defaultApplicationHandler() {
     if (typeof this.__defaultApplicationHandler != "undefined")
       return this.__defaultApplicationHandler;
@@ -794,17 +794,17 @@ function InternalHandlerInfoWrapper(aMIM
 
 InternalHandlerInfoWrapper.prototype = {
   __proto__: HandlerInfoWrapper.prototype,
 
   // Override store so we so we can notify any code listening for registration
   // or unregistration of this handler.
   store() {
     HandlerInfoWrapper.prototype.store.call(this);
-    Services.obs.notifyObservers(null, this._handlerChanged, null);
+    Services.obs.notifyObservers(null, this._handlerChanged);
   },
 
   get enabled() {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
   get description() {
     return this.element("bundlePreferences").getString(this._appPrefLabel);
@@ -880,32 +880,32 @@ var gApplicationsPane = {
     this._brandShortName =
       document.getElementById("bundleBrand").getString("brandShortName");
     this._prefsBundle = document.getElementById("bundlePreferences");
     this._list = document.getElementById("handlersView");
     this._filter = document.getElementById("filter");
 
     // Observe preferences that influence what we display so we can rebuild
     // the view when they change.
-    this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this, false);
-    this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this, false);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this, false);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_WEB, this, false);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_ACTION, this, false);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_READER, this, false);
+    this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
+    this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_READER, this);
 
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this, false);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this, false);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this, false);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this, false);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
 
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this, false);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this, false);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this, false);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this, false);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
 
 
     setEventListener("focusSearch1", "command", gApplicationsPane.focusFilterBox);
     setEventListener("focusSearch2", "command", gApplicationsPane.focusFilterBox);
     setEventListener("filter", "command", gApplicationsPane.filter);
     setEventListener("handlersView", "select",
       gApplicationsPane.onSelectionChanged);
     setEventListener("typeColumn", "click", gApplicationsPane.sort);
@@ -937,17 +937,17 @@ var gApplicationsPane = {
     var _delayedPaneLoad = function(self) {
       self._loadData();
       self._rebuildVisibleTypes();
       self._sortVisibleTypes();
       self._rebuildView();
 
       // Notify observers that the UI is now ready
       Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService).
-      notifyObservers(window, "app-handler-pane-loaded", null);
+      notifyObservers(window, "app-handler-pane-loaded");
     }
     setTimeout(_delayedPaneLoad, 0, this);
   },
 
   destroy() {
     window.removeEventListener("unload", this);
     this._prefSvc.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
     this._prefSvc.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
--- a/browser/components/preferences/in-content-old/main.js
+++ b/browser/components/preferences/in-content-old/main.js
@@ -122,17 +122,17 @@ var gMainPane = {
       fxAccounts.getSignedInUser().then(data => {
         document.getElementById("getStarted").selectedIndex = data ? 1 : 0;
       });
     }
 
     // Notify observers that the UI is now ready
     Components.classes["@mozilla.org/observer-service;1"]
               .getService(Components.interfaces.nsIObserverService)
-              .notifyObservers(window, "main-pane-loaded", null);
+              .notifyObservers(window, "main-pane-loaded");
   },
 
   enableE10SChange() {
     if (AppConstants.E10S_TESTING_ONLY) {
       let e10sCheckbox = document.getElementById("e10sAutoStart");
       let e10sPref = document.getElementById("browser.tabs.remote.autostart");
       let e10sTempPref = document.getElementById("e10sTempPref");
 
--- a/browser/components/preferences/in-content-old/preferences.js
+++ b/browser/components/preferences/in-content-old/preferences.js
@@ -94,17 +94,17 @@ function init_all() {
     let name = internalPrefCategoryNameToFriendlyName(category.value);
     let helpSelector = `#header-${name} > .help-button`;
     let helpButton = document.querySelector(helpSelector);
     helpButton.setAttribute("href", getHelpLinkURL(category.getAttribute("helpTopic")));
   }
 
   // Wait until initialization of all preferences are complete before
   // notifying observers that the UI is now ready.
-  Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
+  Services.obs.notifyObservers(window, "advanced-pane-loaded");
 }
 
 // Make the space above the categories list shrink on low window heights
 function init_dynamic_padding() {
   let categories = document.getElementById("categories");
   let catPadding = Number.parseInt(getComputedStyle(categories)
                                      .getPropertyValue("padding-top"));
   let fullHeight = categories.lastElementChild.getBoundingClientRect().bottom;
--- a/browser/components/preferences/in-content-old/privacy.js
+++ b/browser/components/preferences/in-content-old/privacy.js
@@ -654,17 +654,17 @@ var gPrivacyPane = {
     }
 
     gSubDialog.open("chrome://browser/content/sanitize.xul", "resizable=no", null, () => {
       // reset the timeSpan pref
       if (aClearEverything) {
         ts.value = timeSpanOrig;
       }
 
-      Services.obs.notifyObservers(null, "clear-private-data", null);
+      Services.obs.notifyObservers(null, "clear-private-data");
     });
   },
 
   /**
    * Enables or disables the "Settings..." button depending
    * on the privacy.sanitize.sanitizeOnShutdown preference value
    */
   _updateSanitizeSettingsButton() {
--- a/browser/components/preferences/in-content-old/search.js
+++ b/browser/components/preferences/in-content-old/search.js
@@ -36,17 +36,17 @@ var gSearchPane = {
 
     window.addEventListener("click", this);
     window.addEventListener("command", this);
     window.addEventListener("dragstart", this);
     window.addEventListener("keypress", this);
     window.addEventListener("select", this);
     window.addEventListener("blur", this, true);
 
-    Services.obs.addObserver(this, "browser-search-engine-modified", false);
+    Services.obs.addObserver(this, "browser-search-engine-modified");
     window.addEventListener("unload", () => {
       Services.obs.removeObserver(this, "browser-search-engine-modified");
     });
 
     this._initAutocomplete();
 
     let suggestsPref =
       document.getElementById("browser.search.suggest.enabled");
--- a/browser/components/preferences/in-content-old/sync.js
+++ b/browser/components/preferences/in-content-old/sync.js
@@ -62,17 +62,17 @@ var gSyncPane = {
     };
 
     let onReady = function() {
       Services.obs.removeObserver(onReady, "weave:service:ready");
       window.removeEventListener("unload", onUnload);
       this._init();
     }.bind(this);
 
-    Services.obs.addObserver(onReady, "weave:service:ready", false);
+    Services.obs.addObserver(onReady, "weave:service:ready");
     window.addEventListener("unload", onUnload);
 
     xps.ensureLoaded();
   },
 
   _showLoadPage(xps) {
     let username = Services.prefs.getCharPref("services.sync.username", "");
     if (!username) {
--- a/browser/components/preferences/in-content-old/tests/browser_advanced_siteData.js
+++ b/browser/components/preferences/in-content-old/tests/browser_advanced_siteData.js
@@ -245,24 +245,24 @@ add_task(function *() {
   yield SiteDataManager.getTotalUsage()
                        .then(usage => {
                          actual = totalSiteDataSizeLabel.textContent;
                          expected = prefStrBundle.getFormattedString(
                            "totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
                           is(actual, expected, "Should show the right total site data size");
                        });
 
-  Services.obs.notifyObservers(null, "sitedatamanager:updating-sites", null);
+  Services.obs.notifyObservers(null, "sitedatamanager:updating-sites");
   is(clearBtn.disabled, true, "