Merge inbound to mozilla-central r=merge a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Wed, 20 Dec 2017 11:47:11 +0200
changeset 396981 a235bf4868ab9e48c7b2f4bf4cc9bd949ca23c35
parent 396980 b0cba9689022688677f200928b99afc21c60c822 (current diff)
parent 396937 b22b826e89dcee1f63042b02e463933b568e93da (diff)
child 396982 26927d4b8975345b805f942d5a569fe256264265
child 396989 cdc112ad2452d71d801ea7a779b194d945901a47
push id98408
push userebalazs@mozilla.com
push dateWed, 20 Dec 2017 10:14:47 +0000
treeherdermozilla-inbound@26927d4b8975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
a235bf4868ab / 59.0a1 / 20171220121833 / files
nightly linux64
a235bf4868ab / 59.0a1 / 20171220121833 / files
nightly mac
a235bf4868ab / 59.0a1 / 20171220121833 / files
nightly win32
a235bf4868ab / 59.0a1 / 20171220121833 / files
nightly win64
a235bf4868ab / 59.0a1 / 20171220121833 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central r=merge a=merge
browser/base/content/test/performance/browser_windowopen_reflows.js
browser/components/nsBrowserGlue.js
browser/components/tests/browser/browser_urlbar_matchBuckets.js
security/nss/lib/ssl/ssl3encode.c
security/nss/lib/ssl/ssl3encode.h
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/script-for-event.html.ini
third_party/rust/error-chain/src/quick_error.rs
--- a/accessible/xul/XULMenuAccessible.cpp
+++ b/accessible/xul/XULMenuAccessible.cpp
@@ -209,19 +209,19 @@ XULMenuitemAccessible::KeyboardShortcut(
   uint32_t key = 0;
 
   nsAutoString keyStr;
   keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr);
   if (keyStr.IsEmpty()) {
     nsAutoString keyCodeStr;
     keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeStr);
     nsresult errorCode;
-    key = keyStr.ToInteger(&errorCode, kRadix10);
+    key = keyStr.ToInteger(&errorCode, /* aRadix = */ 10);
     if (NS_FAILED(errorCode)) {
-      key = keyStr.ToInteger(&errorCode, kRadix16);
+      key = keyStr.ToInteger(&errorCode, /* aRadix = */ 16);
     }
   } else {
     key = keyStr[0];
   }
 
   nsAutoString modifiersStr;
   keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr);
 
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -239,26 +239,26 @@ var gXPInstallObserver = {
       timeout: Date.now() + 30000,
     };
 
     switch (aTopic) {
     case "addon-install-disabled": {
       notificationID = "xpinstall-disabled";
       let secondaryActions = null;
 
-      if (gPrefService.prefIsLocked("xpinstall.enabled")) {
+      if (Services.prefs.prefIsLocked("xpinstall.enabled")) {
         messageString = gNavigatorBundle.getString("xpinstallDisabledMessageLocked");
       } else {
         messageString = gNavigatorBundle.getString("xpinstallDisabledMessage");
 
         action = {
           label: gNavigatorBundle.getString("xpinstallDisabledButton"),
           accessKey: gNavigatorBundle.getString("xpinstallDisabledButton.accesskey"),
           callback: function editPrefs() {
-            gPrefService.setBoolPref("xpinstall.enabled", true);
+            Services.prefs.setBoolPref("xpinstall.enabled", true);
           }
         };
 
         secondaryActions = [{
           label: gNavigatorBundle.getString("addonInstall.cancelButton.label"),
           accessKey: gNavigatorBundle.getString("addonInstall.cancelButton.accesskey"),
           callback: () => {},
         }];
--- a/browser/base/content/browser-ctrlTab.js
+++ b/browser/base/content/browser-ctrlTab.js
@@ -211,18 +211,18 @@ var ctrlTab = {
       this._recentlyUsedTabs = null;
       this._init(false);
     }
   },
 
   prefName: "browser.ctrlTab.previews",
   readPref: function ctrlTab_readPref() {
     var enable =
-      gPrefService.getBoolPref(this.prefName) &&
-      !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders", false);
+      Services.prefs.getBoolPref(this.prefName) &&
+      !Services.prefs.getBoolPref("browser.ctrlTab.disallowForScreenReaders", false);
 
     if (enable)
       this.init();
     else
       this.uninit();
   },
   observe(aSubject, aTopic, aPrefName) {
     this.readPref();
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -38,24 +38,24 @@ var PointerlockFsWarning = {
     }
     get delay() {
       return this._delay;
     }
   },
 
   showPointerLock(aOrigin) {
     if (!document.fullscreen) {
-      let timeout = gPrefService.getIntPref("pointer-lock-api.warning.timeout");
+      let timeout = Services.prefs.getIntPref("pointer-lock-api.warning.timeout");
       this.show(aOrigin, "pointerlock-warning", timeout, 0);
     }
   },
 
   showFullScreen(aOrigin) {
-    let timeout = gPrefService.getIntPref("full-screen-api.warning.timeout");
-    let delay = gPrefService.getIntPref("full-screen-api.warning.delay");
+    let timeout = Services.prefs.getIntPref("full-screen-api.warning.timeout");
+    let delay = Services.prefs.getIntPref("full-screen-api.warning.delay");
     this.show(aOrigin, "fullscreen-warning", timeout, delay);
   },
 
   // Shows a warning that the site has entered fullscreen or
   // pointer lock for a short duration.
   show(aOrigin, elementId, timeout, delay) {
 
     if (!this._element) {
@@ -524,17 +524,17 @@ var FullScreen = {
       FullScreen.showNavToolbox();
     }
   },
 
   // Checks whether we are allowed to collapse the chrome
   _isPopupOpen: false,
   _isChromeCollapsed: false,
   _safeToCollapse() {
-    if (!gPrefService.getBoolPref("browser.fullscreen.autohide"))
+    if (!Services.prefs.getBoolPref("browser.fullscreen.autohide"))
       return false;
 
     // a popup menu is open in chrome: don't collapse chrome
     if (this._isPopupOpen)
       return false;
 
     // On OS X Lion we don't want to hide toolbars.
     if (this.useLionFullScreen)
@@ -568,20 +568,20 @@ var FullScreen = {
   },
 
   get navToolboxHidden() {
     return this._isChromeCollapsed;
   },
 
   // Autohide helpers for the context menu item
   getAutohide(aItem) {
-    aItem.setAttribute("checked", gPrefService.getBoolPref("browser.fullscreen.autohide"));
+    aItem.setAttribute("checked", Services.prefs.getBoolPref("browser.fullscreen.autohide"));
   },
   setAutohide() {
-    gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide"));
+    Services.prefs.setBoolPref("browser.fullscreen.autohide", !Services.prefs.getBoolPref("browser.fullscreen.autohide"));
     // Try again to hide toolbar when we change the pref.
     FullScreen.hideNavToolbox(true);
   },
 
   showNavToolbox(trackMouse = true) {
     this._fullScrToggler.hidden = true;
     gNavToolbox.removeAttribute("fullscreenShouldAnimate");
     gNavToolbox.style.marginTop = "";
@@ -607,17 +607,17 @@ var FullScreen = {
   },
 
   hideNavToolbox(aAnimate = false) {
     if (this._isChromeCollapsed || !this._safeToCollapse())
       return;
 
     this._fullScrToggler.hidden = false;
 
-    if (aAnimate && gPrefService.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
+    if (aAnimate && Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
       gNavToolbox.setAttribute("fullscreenShouldAnimate", true);
       // Hide the fullscreen toggler until the transition ends.
       let listener = () => {
         gNavToolbox.removeEventListener("transitionend", listener, true);
         if (this._isChromeCollapsed)
           this._fullScrToggler.hidden = false;
       };
       gNavToolbox.addEventListener("transitionend", listener, true);
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -26,18 +26,18 @@ var FullZoom = {
 
   // Stores initial locations if we receive onLocationChange
   // events before we're initialized.
   _initialLocations: new WeakMap(),
 
   get siteSpecific() {
     if (this._siteSpecificPref === undefined) {
       this._siteSpecificPref =
-        !gPrefService.getBoolPref("privacy.resistFingerprinting") &&
-        gPrefService.getBoolPref("browser.zoom.siteSpecific");
+        !Services.prefs.getBoolPref("privacy.resistFingerprinting") &&
+        Services.prefs.getBoolPref("browser.zoom.siteSpecific");
     }
     return this._siteSpecificPref;
   },
 
   // nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
                                          Ci.nsIObserver,
@@ -51,40 +51,40 @@ var FullZoom = {
     gBrowser.addEventListener("ZoomChangeUsingMouseWheel", this);
 
     // Register ourselves with the service so we know when our pref changes.
     this._cps2 = Cc["@mozilla.org/content-pref/service;1"].
                  getService(Ci.nsIContentPrefService2);
     this._cps2.addObserverForName(this.name, this);
 
     this.updateBackgroundTabs =
-      gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
+      Services.prefs.getBoolPref("browser.zoom.updateBackgroundTabs");
 
     // Listen for changes to the browser.zoom branch so we can enable/disable
     // updating background tabs and per-site saving and restoring of zoom levels.
-    gPrefService.addObserver("browser.zoom.", this, true);
+    Services.prefs.addObserver("browser.zoom.", this, true);
 
     // Also need to listen to privacy.resistFingerprinting in order to update
     // this._siteSpecificPref.
-    gPrefService.addObserver("privacy.resistFingerprinting", this, true);
+    Services.prefs.addObserver("privacy.resistFingerprinting", this, true);
 
     // If we received onLocationChange events for any of the current browsers
     // before we were initialized we want to replay those upon initialization.
     for (let browser of gBrowser.browsers) {
       if (this._initialLocations.has(browser)) {
         this.onLocationChange(...this._initialLocations.get(browser), browser);
       }
     }
 
     // This should be nulled after initialization.
     this._initialLocations = null;
   },
 
   destroy: function FullZoom_destroy() {
-    gPrefService.removeObserver("browser.zoom.", this);
+    Services.prefs.removeObserver("browser.zoom.", this);
     this._cps2.removeObserverForName(this.name, this);
     gBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this);
   },
 
 
   // Event Handlers
 
   // nsIDOMEventListener
@@ -108,17 +108,17 @@ var FullZoom = {
           case "privacy.resistFingerprinting":
             // fall through
           case "browser.zoom.siteSpecific":
             // Invalidate pref cache.
             this._siteSpecificPref = undefined;
             break;
           case "browser.zoom.updateBackgroundTabs":
             this.updateBackgroundTabs =
-              gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
+              Services.prefs.getBoolPref("browser.zoom.updateBackgroundTabs");
             break;
         }
         break;
     }
   },
 
   // nsIContentPrefObserver
 
--- a/browser/base/content/browser-gestureSupport.js
+++ b/browser/base/content/browser-gestureSupport.js
@@ -428,17 +428,17 @@ var gGestureSupport = {
     try {
       // Determine what type of data to load based on default value's type
       let type = typeof aDef;
       let getFunc = "Char";
       if (type == "boolean")
         getFunc = "Bool";
       else if (type == "number")
         getFunc = "Int";
-      return gPrefService["get" + getFunc + "Pref"](branch + aPref);
+      return Services.prefs["get" + getFunc + "Pref"](branch + aPref);
     } catch (e) {
       return aDef;
     }
   },
 
   /**
    * Perform rotation for ImageDocuments
    *
@@ -1009,17 +1009,17 @@ var gHistorySwipeAnimation = {
     }
   },
 
   /**
    * Retrieves the maximum number of snapshots that should be kept in memory.
    * This limit is a global limit and is valid across all open tabs.
    */
   _getMaxSnapshots: function HSA__getMaxSnapshots() {
-    return gPrefService.getIntPref("browser.snapshots.limit");
+    return Services.prefs.getIntPref("browser.snapshots.limit");
   },
 
   /**
    * Adds a snapshot to the list and initiates the compression of said snapshot.
    * Once the compression is completed, it will replace the uncompressed
    * snapshot in the list.
    *
    * @param aCanvas
--- a/browser/base/content/browser-trackingprotection.js
+++ b/browser/base/content/browser-trackingprotection.js
@@ -103,20 +103,20 @@ var TrackingProtection = {
 
     if (isBlocking) {
       this.icon.setAttribute("tooltiptext", this.activeTooltipText);
       this.icon.setAttribute("state", "blocked-tracking-content");
       this.content.setAttribute("state", "blocked-tracking-content");
 
       // Open the tracking protection introduction panel, if applicable.
       if (this.enabledGlobally) {
-        let introCount = gPrefService.getIntPref("privacy.trackingprotection.introCount");
+        let introCount = Services.prefs.getIntPref("privacy.trackingprotection.introCount");
         if (introCount < TrackingProtection.MAX_INTROS) {
-          gPrefService.setIntPref("privacy.trackingprotection.introCount", ++introCount);
-          gPrefService.savePrefFile(null);
+          Services.prefs.setIntPref("privacy.trackingprotection.introCount", ++introCount);
+          Services.prefs.savePrefFile(null);
           this.showIntroPanel();
         }
       }
 
       this.shieldHistogramAdd(2);
     } else if (isAllowing) {
       this.icon.setAttribute("tooltiptext", this.disabledTooltipText);
       this.icon.setAttribute("state", "loaded-tracking-content");
@@ -183,19 +183,19 @@ var TrackingProtection = {
 
     BrowserReload();
   },
 
   dontShowIntroPanelAgain() {
     // This function may be called in private windows, but it does not change
     // any preference unless Tracking Protection is enabled globally.
     if (this.enabledGlobally) {
-      gPrefService.setIntPref("privacy.trackingprotection.introCount",
-                              this.MAX_INTROS);
-      gPrefService.savePrefFile(null);
+      Services.prefs.setIntPref("privacy.trackingprotection.introCount",
+                                this.MAX_INTROS);
+      Services.prefs.savePrefFile(null);
     }
   },
 
   async showIntroPanel() {
     let brandBundle = document.getElementById("bundle_brand");
     let brandShortName = brandBundle.getString("brandShortName");
 
     let openStep2 = () => {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -144,20 +144,16 @@ XPCOMUtils.defineLazyGetter(this, "gTabB
 });
 
 XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
   let scope = {};
   Cu.import("resource:///modules/CustomizeMode.jsm", scope);
   return new scope.CustomizeMode(window);
 });
 
-XPCOMUtils.defineLazyGetter(this, "gPrefService", function() {
-  return Services.prefs;
-});
-
 XPCOMUtils.defineLazyGetter(this, "InlineSpellCheckerUI", function() {
   let tmp = {};
   Cu.import("resource://gre/modules/InlineSpellChecker.jsm", tmp);
   return new tmp.InlineSpellChecker();
 });
 
 XPCOMUtils.defineLazyGetter(this, "PageMenuParent", function() {
   let tmp = {};
@@ -601,17 +597,17 @@ var gPopupBlockerObserver = {
       }
       return;
     }
 
     // Only show the notification again if we've not already shown it. Since
     // notifications are per-browser, we don't need to worry about re-adding
     // it.
     if (!gBrowser.selectedBrowser.blockedPopups.reported) {
-      if (gPrefService.getBoolPref("privacy.popups.showBrowserMessage")) {
+      if (Services.prefs.getBoolPref("privacy.popups.showBrowserMessage")) {
         var brandBundle = document.getElementById("bundle_brand");
         var brandShortName = brandBundle.getString("brandShortName");
         var popupCount = gBrowser.selectedBrowser.blockedPopups.length;
 
         var stringKey = AppConstants.platform == "win"
                         ? "popupWarningButton"
                         : "popupWarningButtonUnix";
 
@@ -694,17 +690,17 @@ var gPopupBlockerObserver = {
     }
 
     if (PrivateBrowsingUtils.isWindowPrivate(window))
       blockedPopupAllowSite.setAttribute("disabled", "true");
     else
       blockedPopupAllowSite.removeAttribute("disabled");
 
     let blockedPopupDontShowMessage = document.getElementById("blockedPopupDontShowMessage");
-    let showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
+    let showMessage = Services.prefs.getBoolPref("privacy.popups.showBrowserMessage");
     blockedPopupDontShowMessage.setAttribute("checked", !showMessage);
     blockedPopupDontShowMessage.setAttribute("label", gNavigatorBundle.getString("popupWarningDontShowFromMessage"));
 
     let blockedPopupsSeparator =
         document.getElementById("blockedPopupsSeparator");
     blockedPopupsSeparator.setAttribute("hidden", true);
 
     gBrowser.selectedBrowser.retrieveListOfBlockedPopups().then(blockedPopups => {
@@ -812,18 +808,18 @@ var gPopupBlockerObserver = {
       existingWindow.initWithParams(params);
       existingWindow.focus();
     } else
       window.openDialog("chrome://browser/content/preferences/permissions.xul",
                         "_blank", "resizable,dialog=no,centerscreen", params);
   },
 
   dontShowMessage() {
-    var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
-    gPrefService.setBoolPref("privacy.popups.showBrowserMessage", !showMessage);
+    var showMessage = Services.prefs.getBoolPref("privacy.popups.showBrowserMessage");
+    Services.prefs.setBoolPref("privacy.popups.showBrowserMessage", !showMessage);
     gBrowser.getNotificationBox().removeCurrentNotification();
   }
 };
 
 function gKeywordURIFixup({ target: browser, data: fixupInfo }) {
   let deserializeURI = (spec) => spec ? makeURI(spec) : null;
 
   // We get called irrespective of whether we did a keyword search, or
@@ -1274,17 +1270,17 @@ var gBrowserInit = {
     Services.obs.notifyObservers(window, "browser-window-before-show");
 
     gUIDensity.init();
 
     if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
       gDragSpaceObserver.init();
     }
 
-    let isResistFingerprintingEnabled = gPrefService.getBoolPref("privacy.resistFingerprinting");
+    let isResistFingerprintingEnabled = Services.prefs.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");
     } else if (!document.documentElement.hasAttribute("width")) {
       const TARGET_WIDTH = 1280;
@@ -1440,17 +1436,17 @@ var gBrowserInit = {
     UpdateUrlbarSearchSplitterState();
 
     // Enable/Disable auto-hide tabbar
     gBrowser.tabContainer.updateVisibility();
 
     BookmarkingUI.init();
     AutoShowBookmarksToolbar.init();
 
-    gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton);
+    Services.prefs.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");
@@ -1471,17 +1467,17 @@ var gBrowserInit = {
       SetClickAndHoldHandlers();
 
     Cu.import("resource:///modules/UpdateTopLevelContentWindowIDHelper.jsm", {})
       .trackBrowserWindow(window);
 
     PlacesToolbarHelper.init();
 
     ctrlTab.readPref();
-    gPrefService.addObserver(ctrlTab.prefName, ctrlTab);
+    Services.prefs.addObserver(ctrlTab.prefName, ctrlTab);
 
     // The object handling the downloads indicator is initialized here in the
     // delayed startup function, but the actual indicator element is not loaded
     // unless there are downloads to be displayed.
     DownloadsButton.initializeIndicator();
 
     if (AppConstants.platform != "macosx") {
       updateEditUIVisibility();
@@ -1827,17 +1823,17 @@ var gBrowserInit = {
     // Now either cancel delayedStartup, or clean up the services initialized from
     // it.
     if (this._boundDelayedStartup) {
       this._cancelDelayedStartup();
     } else {
       if (Win7Features)
         Win7Features.onCloseWindow();
 
-      gPrefService.removeObserver(ctrlTab.prefName, ctrlTab);
+      Services.prefs.removeObserver(ctrlTab.prefName, ctrlTab);
       ctrlTab.uninit();
       gBrowserThumbnails.uninit();
       FullZoom.destroy();
 
       Services.obs.removeObserver(gIdentityHandler, "perm-changed");
       Services.obs.removeObserver(gRemoteControl, "remote-active");
       Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
       Services.obs.removeObserver(gStoragePressureObserver, "QuotaManager::StoragePressure");
@@ -1847,17 +1843,17 @@ var gBrowserInit = {
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-origin-blocked");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-confirmation");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete");
       window.messageManager.removeMessageListener("Browser:URIFixup", gKeywordURIFixup);
       window.messageManager.removeMessageListener("Browser:LoadURI", RedirectLoad);
 
       try {
-        gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton);
+        Services.prefs.removeObserver(gHomeButton.prefDomain, gHomeButton);
       } catch (ex) {
         Cu.reportError(ex);
       }
 
       if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
         MenuTouchModeObserver.uninit();
       }
       BrowserOffline.uninit();
@@ -2080,28 +2076,28 @@ function BrowserBack(aEvent) {
     } catch (ex) {
     }
   } else {
     duplicateTabIn(gBrowser.selectedTab, where, -1);
   }
 }
 
 function BrowserHandleBackspace() {
-  switch (gPrefService.getIntPref("browser.backspace_action")) {
+  switch (Services.prefs.getIntPref("browser.backspace_action")) {
   case 0:
     BrowserBack();
     break;
   case 1:
     goDoCommand("cmd_scrollPageUp");
     break;
   }
 }
 
 function BrowserHandleShiftBackspace() {
-  switch (gPrefService.getIntPref("browser.backspace_action")) {
+  switch (Services.prefs.getIntPref("browser.backspace_action")) {
   case 0:
     BrowserForward();
     break;
   case 1:
     goDoCommand("cmd_scrollPageDown");
     break;
   }
 }
@@ -2287,18 +2283,18 @@ function BrowserOpenTab(event) {
   openUILinkIn(BROWSER_NEW_TAB_URL, where, { relatedToCurrent });
 }
 
 var gLastOpenDirectory = {
   _lastDir: null,
   get path() {
     if (!this._lastDir || !this._lastDir.exists()) {
       try {
-        this._lastDir = gPrefService.getComplexValue("browser.open.lastDir",
-                                                     Ci.nsIFile);
+        this._lastDir = Services.prefs.getComplexValue("browser.open.lastDir",
+                                                       Ci.nsIFile);
         if (!this._lastDir.exists())
           this._lastDir = null;
       } catch (e) {}
     }
     return this._lastDir;
   },
   set path(val) {
     try {
@@ -2306,18 +2302,18 @@ var gLastOpenDirectory = {
         return;
     } catch (e) {
       return;
     }
     this._lastDir = val.clone();
 
     // Don't save the last open directory pref inside the Private Browsing mode
     if (!PrivateBrowsingUtils.isWindowPrivate(window))
-      gPrefService.setComplexValue("browser.open.lastDir", Ci.nsIFile,
-                                   this._lastDir);
+      Services.prefs.setComplexValue("browser.open.lastDir", Ci.nsIFile,
+                                     this._lastDir);
   },
   reset() {
     this._lastDir = null;
   }
 };
 
 function BrowserOpenFileWindow() {
   // Get filepicker component.
@@ -2873,17 +2869,17 @@ function UpdatePopupNotificationsVisibil
 
   // Notify PopupNotifications that the visible anchors may have changed. This
   // also checks the suppression state according to the "shouldSuppress"
   // function defined earlier in this file.
   PopupNotifications.anchorVisibilityChange();
 }
 
 function PageProxyClickHandler(aEvent) {
-  if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
+  if (aEvent.button == 1 && Services.prefs.getBoolPref("middlemouse.paste"))
     middleMousePaste(aEvent);
 }
 
 // Values for telemtery bins: see TLS_ERROR_REPORT_UI in Histograms.json
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_CHECKED   = 2;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_UNCHECKED = 3;
 const TLS_ERROR_REPORT_TELEMETRY_MANUAL_SEND    = 4;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_SEND      = 5;
@@ -3080,17 +3076,17 @@ var BrowserOnClick = {
     switch (elementId) {
       case "goBackButton":
         if (sendTelemetry) {
           secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
         }
         getMeOutOfHere();
         break;
       case "ignore_warning_link":
-        if (gPrefService.getBoolPref("browser.safebrowsing.allowOverride")) {
+        if (Services.prefs.getBoolPref("browser.safebrowsing.allowOverride")) {
           if (sendTelemetry) {
             secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
           }
           this.ignoreWarningLink(reason, blockedInfo);
         }
         break;
     }
   },
@@ -3512,17 +3508,17 @@ var homeButtonObserver = {
       // disallow setting home pages that inherit the principal
       let links = browserDragAndDrop.dropLinks(aEvent, true);
       if (links.length) {
         setTimeout(openHomeDialog, 0, links.map(link => link.url).join("|"));
       }
     },
 
   onDragOver(aEvent) {
-      if (gPrefService.prefIsLocked("browser.startup.homepage")) {
+      if (Services.prefs.prefIsLocked("browser.startup.homepage")) {
         return;
       }
       browserDragAndDrop.dragOver(aEvent);
       aEvent.dropEffect = "link";
     },
   onDragExit(aEvent) {
     }
 };
@@ -3537,17 +3533,17 @@ function openHomeDialog(aURL) {
   }
 
   var pressedVal  = Services.prompt.confirmEx(window, promptTitle, promptMsg,
                           Services.prompt.STD_YES_NO_BUTTONS,
                           null, null, null, null, {value: 0});
 
   if (pressedVal == 0) {
     try {
-      gPrefService.setStringPref("browser.startup.homepage", aURL);
+      Services.prefs.setStringPref("browser.startup.homepage", aURL);
     } catch (ex) {
       dump("Failed to set the home page.\n" + ex + "\n");
     }
   }
 }
 
 var newTabButtonObserver = {
   onDragOver(aEvent) {
@@ -3841,17 +3837,17 @@ const BrowserSearch = {
     return document.getElementById("searchbar");
   },
 
   get searchEnginesURL() {
     return formatURL("browser.search.searchEnginesURL", true);
   },
 
   loadAddEngines: function BrowserSearch_loadAddEngines() {
-    var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
+    var newWindowPref = Services.prefs.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
     openUILinkIn(this.searchEnginesURL, where);
   },
 
   _getSearchEngineId(engine) {
     if (engine && engine.identifier) {
       return engine.identifier;
     }
@@ -5141,17 +5137,17 @@ nsBrowserAccess.prototype = {
     }
 
     if (aIsExternal && (!aURI || aURI.spec == "about:blank")) {
       win.BrowserOpenTab(); // this also focuses the location bar
       win.focus();
       return win.gBrowser.selectedBrowser;
     }
 
-    let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
+    let loadInBackground = Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground");
 
     let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
                                       triggeringPrincipal: aTriggeringPrincipal,
                                       referrerURI: aReferrer,
                                       referrerPolicy: aReferrerPolicy,
                                       userContextId: aUserContextId,
                                       fromExternal: aIsExternal,
                                       inBackground: loadInBackground,
@@ -5203,20 +5199,20 @@ nsBrowserAccess.prototype = {
 
     if (isExternal && aURI && aURI.schemeIs("chrome")) {
       dump("use --chrome command-line option to load external chrome urls\n");
       return null;
     }
 
     if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
       if (isExternal &&
-          gPrefService.prefHasUserValue("browser.link.open_newwindow.override.external"))
-        aWhere = gPrefService.getIntPref("browser.link.open_newwindow.override.external");
+          Services.prefs.prefHasUserValue("browser.link.open_newwindow.override.external"))
+        aWhere = Services.prefs.getIntPref("browser.link.open_newwindow.override.external");
       else
-        aWhere = gPrefService.getIntPref("browser.link.open_newwindow");
+        aWhere = Services.prefs.getIntPref("browser.link.open_newwindow");
     }
 
     let referrer = aOpener ? makeURI(aOpener.location.href) : null;
     let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
     if (aOpener && aOpener.document) {
       referrerPolicy = aOpener.document.referrerPolicy;
     }
     let isPrivate = aOpener
@@ -5263,17 +5259,17 @@ nsBrowserAccess.prototype = {
                             Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
           gBrowser.loadURIWithFlags(aURI.spec, {
                                     aTriggeringPrincipal,
                                     flags: loadflags,
                                     referrerURI: referrer,
                                     referrerPolicy,
                                     });
         }
-        if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"))
+        if (!Services.prefs.getBoolPref("browser.tabs.loadDivertedInBackground"))
           window.focus();
     }
     return newWindow;
   },
 
   createContentWindowInFrame: function browser_createContentWindowInFrame(
                               aURI, aParams, aWhere, aFlags, aNextTabParentId,
                               aName) {
@@ -5547,33 +5543,33 @@ function displaySecurityInfo() {
 
 // Adds additional drag space to the window by listening to
 // the corresponding preference.
 var gDragSpaceObserver = {
   pref: "browser.tabs.extraDragSpace",
 
   init() {
     this.update();
-    gPrefService.addObserver(this.pref, this);
+    Services.prefs.addObserver(this.pref, this);
   },
 
   uninit() {
-    gPrefService.removeObserver(this.pref, this);
+    Services.prefs.removeObserver(this.pref, this);
   },
 
   observe(aSubject, aTopic, aPrefName) {
     if (aTopic != "nsPref:changed" || aPrefName != this.pref) {
       return;
     }
 
     this.update();
   },
 
   update() {
-    if (gPrefService.getBoolPref(this.pref)) {
+    if (Services.prefs.getBoolPref(this.pref)) {
       document.documentElement.setAttribute("extradragspace", "true");
     } else {
       document.documentElement.removeAttribute("extradragspace");
     }
     TabsInTitlebar.updateAppearance(true);
   },
 };
 
@@ -5582,47 +5578,47 @@ var gUIDensity = {
   MODE_NORMAL: 0,
   MODE_COMPACT: 1,
   MODE_TOUCH: 2,
   uiDensityPref: "browser.uidensity",
   autoTouchModePref: "browser.touchmode.auto",
 
   init() {
     this.update();
-    gPrefService.addObserver(this.uiDensityPref, this);
-    gPrefService.addObserver(this.autoTouchModePref, this);
+    Services.prefs.addObserver(this.uiDensityPref, this);
+    Services.prefs.addObserver(this.autoTouchModePref, this);
   },
 
   uninit() {
-    gPrefService.removeObserver(this.uiDensityPref, this);
-    gPrefService.removeObserver(this.autoTouchModePref, this);
+    Services.prefs.removeObserver(this.uiDensityPref, this);
+    Services.prefs.removeObserver(this.autoTouchModePref, this);
   },
 
   observe(aSubject, aTopic, aPrefName) {
     if (aTopic != "nsPref:changed" ||
         (aPrefName != this.uiDensityPref &&
          aPrefName != this.autoTouchModePref)) {
       return;
     }
 
     this.update();
   },
 
   getCurrentDensity() {
     // Automatically override the uidensity to touch in Windows tablet mode.
     if (AppConstants.isPlatformAndVersionAtLeast("win", "10") &&
         WindowsUIUtils.inTabletMode &&
-        gPrefService.getBoolPref(this.autoTouchModePref)) {
+        Services.prefs.getBoolPref(this.autoTouchModePref)) {
       return { mode: this.MODE_TOUCH, overridden: true };
     }
-    return { mode: gPrefService.getIntPref(this.uiDensityPref), overridden: false };
+    return { mode: Services.prefs.getIntPref(this.uiDensityPref), overridden: false };
   },
 
   setCurrentMode(mode) {
-    gPrefService.setIntPref(this.uiDensityPref, mode);
+    Services.prefs.setIntPref(this.uiDensityPref, mode);
   },
 
   update(mode) {
     if (mode == null) {
       mode = this.getCurrentDensity().mode;
     }
 
     let docs = [
@@ -5675,18 +5671,18 @@ var gHomeButton = {
       else
         homeButton.setAttribute("tooltiptext", homePage);
     }
   },
 
   getHomePage() {
     var url;
     try {
-      url = gPrefService.getComplexValue(this.prefDomain,
-                                Components.interfaces.nsIPrefLocalizedString).data;
+      url = Services.prefs.getComplexValue(this.prefDomain,
+                                  Components.interfaces.nsIPrefLocalizedString).data;
     } catch (e) {
     }
 
     // use this if we can't find the pref
     if (!url) {
       var configBundle = Services.strings
                                  .createBundle("chrome://branding/locale/browserconfig.properties");
       url = configBundle.GetStringFromName(this.prefDomain);
@@ -5862,18 +5858,18 @@ function hrefAndLinkNodeForClickEvent(ev
 function contentAreaClick(event, isPanelClick) {
   if (!event.isTrusted || event.defaultPrevented || event.button == 2)
     return;
 
   let [href, linkNode] = hrefAndLinkNodeForClickEvent(event);
   if (!href) {
     // Not a link, handle middle mouse navigation.
     if (event.button == 1 &&
-        gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
-        !gPrefService.getBoolPref("general.autoScroll")) {
+        Services.prefs.getBoolPref("middlemouse.contentLoadURL") &&
+        !Services.prefs.getBoolPref("general.autoScroll")) {
       middleMousePaste(event);
       event.preventDefault();
     }
     return;
   }
 
   // This code only applies if we have a linkNode (i.e. clicks on real anchor
   // elements, as opposed to XLink).
@@ -6336,17 +6332,17 @@ var BrowserOffline = {
     } catch (ex) {
     }
 
     return true;
   },
 
   _uiElement: null,
   _updateOfflineUI(aOffline) {
-    var offlineLocked = gPrefService.prefIsLocked("network.online");
+    var offlineLocked = Services.prefs.prefIsLocked("network.online");
     if (offlineLocked)
       this._uiElement.setAttribute("disabled", "true");
 
     this._uiElement.setAttribute("checked", aOffline);
   }
 };
 
 var OfflineApps = {
@@ -8162,17 +8158,17 @@ function getTabModalPromptBox(aWindow) {
 /* DEPRECATED */
 function getBrowser() {
   return gBrowser;
 }
 
 const gAccessibilityServiceIndicator = {
   init() {
     // Pref to enable accessibility service indicator.
-    gPrefService.addObserver("accessibility.indicator.enabled", this);
+    Services.prefs.addObserver("accessibility.indicator.enabled", this);
     // Accessibility service init/shutdown event.
     Services.obs.addObserver(this, "a11y-init-or-shutdown");
     this.update(Services.appinfo.accessibilityEnabled);
   },
 
   update(accessibilityEnabled = false) {
     if (this.enabled && accessibilityEnabled) {
       this._active = true;
@@ -8197,31 +8193,31 @@ const gAccessibilityServiceIndicator = {
     } else if (topic === "a11y-init-or-shutdown") {
       // When "a11y-init-or-shutdown" event is fired, "1" indicates that
       // accessibility service is started and "0" that it is shut down.
       this.update(data === "1");
     }
   },
 
   get enabled() {
-    return gPrefService.getBoolPref("accessibility.indicator.enabled");
+    return Services.prefs.getBoolPref("accessibility.indicator.enabled");
   },
 
   handleEvent({ key, type }) {
     if ((type === "keypress" && [" ", "Enter"].includes(key)) ||
          type === "click") {
       let a11yServicesSupportURL =
         Services.urlFormatter.formatURLPref("accessibility.support.url");
       gBrowser.selectedTab = gBrowser.addTab(a11yServicesSupportURL);
       Services.telemetry.scalarSet("a11y.indicator_acted_on", true);
     }
   },
 
   uninit() {
-    gPrefService.removeObserver("accessibility.indicator.enabled", this);
+    Services.prefs.removeObserver("accessibility.indicator.enabled", this);
     Services.obs.removeObserver(this, "a11y-init-or-shutdown");
     this.update();
   }
 };
 
 var gPrivateBrowsingUI = {
   init: function PBUI_init() {
     // Do nothing for normal windows
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -128,18 +128,18 @@ nsContextMenu.prototype = {
       };
       subject.wrappedJSObject = subject;
       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;
+      this.ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
+                                                     Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
 
     // Reset after "on-build-contextmenu" notification in case selection was
     // changed during the notification.
     this.isContentSelected = !this.selectionInfo.docSelectionIsCollapsed;
     this.onPlainTextLink = false;
 
     let bookmarkPage = document.getElementById("context-bookmarkpage");
@@ -428,17 +428,17 @@ nsContextMenu.prototype = {
                   this.onMathML && !this.isContentSelected);
 
     var shouldShow = !(this.isContentSelected ||
                        this.onImage || this.onCanvas ||
                        this.onVideo || this.onAudio ||
                        this.onLink || this.onTextInput);
 
     var showInspect = this.inTabBrowser &&
-                      gPrefService.getBoolPref("devtools.inspector.enabled", true);
+                      Services.prefs.getBoolPref("devtools.inspector.enabled", true);
 
     this.showItem("context-viewsource", shouldShow);
     this.showItem("context-viewinfo", shouldShow);
     // The page info is broken for WebExtension popups, as the browser is
     // destroyed when the popup is closed.
     this.setItemAttr("context-viewinfo", "disabled", this.webExtBrowserType === "popup");
     this.showItem("inspect-separator", showInspect);
     this.showItem("context-inspect", showInspect);
@@ -1174,17 +1174,17 @@ nsContextMenu.prototype = {
     if (channel instanceof Ci.nsIHttpChannel) {
       channel.referrer = docURI;
       if (channel instanceof Ci.nsIHttpChannelInternal)
         channel.forceAllowThirdPartyCookie = true;
     }
 
     // fallback to the old way if we don't see the headers quickly
     var timeToWait =
-      gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
+      Services.prefs.getIntPref("browser.download.saveLinkAsFilenameTimeout");
     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     timer.initWithCallback(new timerCallback(), timeToWait,
                            timer.TYPE_ONE_SHOT);
 
     // kick off the channel with our proxy object as the listener
     channel.asyncOpen2(new saveAsListener());
   },
 
@@ -1378,28 +1378,28 @@ nsContextMenu.prototype = {
     return false;
   },
 
   addDictionaries() {
     var uri = formatURL("browser.dictionaries.download.url", true);
 
     var locale = "-";
     try {
-      locale = gPrefService.getComplexValue("intl.accept_languages",
-                                            Ci.nsIPrefLocalizedString).data;
+      locale = Services.prefs.getComplexValue("intl.accept_languages",
+                                              Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
 
     var version = "-";
     try {
       version = Services.appinfo.version;
     } catch (e) { }
 
     uri = uri.replace(/%LOCALE%/, escape(locale)).replace(/%VERSION%/, version);
 
-    var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
+    var newWindowPref = Services.prefs.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
 
     openUILinkIn(uri, where);
   },
 
   bookmarkThisPage: function CM_bookmarkThisPage() {
     window.top.PlacesCommandHook
               .bookmarkPage(this.browser, true)
--- a/browser/base/content/test/general/browser_bug419612.js
+++ b/browser/base/content/test/general/browser_bug419612.js
@@ -12,21 +12,21 @@ function test() {
 
     FullZoom.enlarge();
     let tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
 
     await FullZoomHelper.selectTabAndWaitForLocationChange(tab2);
     let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
     is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs");
 
-    gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false);
+    Services.prefs.setBoolPref("browser.zoom.updateBackgroundTabs", false);
     await FullZoom.reset();
     gBrowser.selectedTab = tab1;
     tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
     tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
     isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs");
 
-    if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
-      gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
+    if (Services.prefs.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
+      Services.prefs.clearUserPref("browser.zoom.updateBackgroundTabs");
     await FullZoomHelper.removeTabAndWaitForLocationChange(tab1);
     await FullZoomHelper.removeTabAndWaitForLocationChange(tab2);
   })().then(finish, FullZoomHelper.failAndContinue(finish));
 }
--- a/browser/base/content/test/general/browser_bug431826.js
+++ b/browser/base/content/test/general/browser_bug431826.js
@@ -19,26 +19,26 @@ add_task(async function() {
     let div = content.document.getElementById("badCertAdvancedPanel");
     // Confirm that the expert section is collapsed
     Assert.ok(div, "Advanced content div should exist");
     Assert.equal(div.ownerGlobal.getComputedStyle(div).display,
       "none", "Advanced content should not be visible by default");
   });
 
   // Tweak the expert mode pref
-  gPrefService.setBoolPref("browser.xul.error_pages.expert_bad_cert", true);
+  Services.prefs.setBoolPref("browser.xul.error_pages.expert_bad_cert", true);
 
   promise = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
   gBrowser.reload();
   await promise;
 
   await remote(() => {
     let div = content.document.getElementById("badCertAdvancedPanel");
     Assert.ok(div, "Advanced content div should exist");
     Assert.equal(div.ownerGlobal.getComputedStyle(div).display,
       "block", "Advanced content should be visible by default");
   });
 
   // Clean up
   gBrowser.removeCurrentTab();
-  if (gPrefService.prefHasUserValue("browser.xul.error_pages.expert_bad_cert"))
-    gPrefService.clearUserPref("browser.xul.error_pages.expert_bad_cert");
+  if (Services.prefs.prefHasUserValue("browser.xul.error_pages.expert_bad_cert"))
+    Services.prefs.clearUserPref("browser.xul.error_pages.expert_bad_cert");
 });
--- a/browser/base/content/test/general/browser_bug455852.js
+++ b/browser/base/content/test/general/browser_bug455852.js
@@ -1,20 +1,20 @@
 add_task(async function() {
   is(gBrowser.tabs.length, 1, "one tab is open");
 
   gBrowser.selectedBrowser.focus();
   isnot(document.activeElement, gURLBar.inputField, "location bar is not focused");
 
   var tab = gBrowser.selectedTab;
-  gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
+  Services.prefs.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
 
   let tabClosedPromise = BrowserTestUtils.tabRemoved(tab);
   EventUtils.synthesizeKey("w", { accelKey: true });
   await tabClosedPromise;
 
   is(tab.parentNode, null, "ctrl+w removes the tab");
   is(gBrowser.tabs.length, 1, "a new tab has been opened");
   is(document.activeElement, gURLBar.inputField, "location bar is focused for the new tab");
 
-  if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
-    gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
+  if (Services.prefs.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
+    Services.prefs.clearUserPref("browser.tabs.closeWindowWithLastTab");
 });
--- a/browser/base/content/test/general/browser_bug484315.js
+++ b/browser/base/content/test/general/browser_bug484315.js
@@ -1,23 +1,23 @@
 function test() {
   var contentWin = window.open("about:blank", "", "width=100,height=100");
   var enumerator = Services.wm.getEnumerator("navigator:browser");
 
   while (enumerator.hasMoreElements()) {
     let win = enumerator.getNext();
     if (win.content == contentWin) {
-      gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
+      Services.prefs.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
       win.gBrowser.removeCurrentTab();
       ok(win.closed, "popup is closed");
 
       // clean up
       if (!win.closed)
         win.close();
-      if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
-        gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
+      if (Services.prefs.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
+        Services.prefs.clearUserPref("browser.tabs.closeWindowWithLastTab");
 
       return;
     }
   }
 
   throw "couldn't find the content window";
 }
--- a/browser/base/content/test/general/browser_bug559991.js
+++ b/browser/base/content/test/general/browser_bug559991.js
@@ -2,18 +2,18 @@ var tab;
 
 function test() {
 
   // ----------
   // Test setup
 
   waitForExplicitFinish();
 
-  gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", true);
-  gPrefService.setBoolPref("browser.zoom.siteSpecific", true);
+  Services.prefs.setBoolPref("browser.zoom.updateBackgroundTabs", true);
+  Services.prefs.setBoolPref("browser.zoom.siteSpecific", true);
 
   let uri = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
 
   (async function() {
     tab = BrowserTestUtils.addTab(gBrowser);
     await FullZoomHelper.load(tab, uri);
 
     // -------------------------------------------------------------------
@@ -26,17 +26,17 @@ function test() {
 // -------------
 // Test clean-up
 function endTest() {
   (async function() {
     await FullZoomHelper.removeTabAndWaitForLocationChange(tab);
 
     tab = null;
 
-    if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
-      gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
+    if (Services.prefs.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
+      Services.prefs.clearUserPref("browser.zoom.updateBackgroundTabs");
 
-    if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific"))
-      gPrefService.clearUserPref("browser.zoom.siteSpecific");
+    if (Services.prefs.prefHasUserValue("browser.zoom.siteSpecific"))
+      Services.prefs.clearUserPref("browser.zoom.siteSpecific");
 
     finish();
   })();
 }
--- a/browser/base/content/test/general/browser_bug580956.js
+++ b/browser/base/content/test/general/browser_bug580956.js
@@ -5,18 +5,18 @@ function numClosedTabs() {
 function isUndoCloseEnabled() {
   updateTabContextMenu();
   return !document.getElementById("context_undoCloseTab").disabled;
 }
 
 function test() {
   waitForExplicitFinish();
 
-  gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", 0);
-  gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+  Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", 0);
+  Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo");
   is(numClosedTabs(), 0, "There should be 0 closed tabs.");
   ok(!isUndoCloseEnabled(), "Undo Close Tab should be disabled.");
 
   var tab = BrowserTestUtils.addTab(gBrowser, "http://mochi.test:8888/");
   var browser = gBrowser.getBrowserForTab(tab);
   BrowserTestUtils.browserLoaded(browser).then(() => {
     BrowserTestUtils.removeTab(tab).then(() => {
       ok(isUndoCloseEnabled(), "Undo Close Tab should be enabled.");
--- a/browser/base/content/test/general/browser_contentAltClick.js
+++ b/browser/base/content/test/general/browser_contentAltClick.js
@@ -13,17 +13,17 @@
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
                                   "resource://testing-common/PlacesTestUtils.jsm");
 
 function setup() {
-  gPrefService.setBoolPref("browser.altClickSave", true);
+  Services.prefs.setBoolPref("browser.altClickSave", true);
 
   let testPage =
     "data:text/html," +
     '<p><a id="commonlink" href="http://mochi.test/moz/">Common link</a></p>' +
     '<p><math id="mathxlink" xmlns="http://www.w3.org/1998/Math/MathML" xlink:type="simple" xlink:href="http://mochi.test/moz/"><mtext>MathML XLink</mtext></math></p>' +
     '<p><svg id="svgxlink" xmlns="http://www.w3.org/2000/svg" width="100px" height="50px" version="1.1"><a xlink:type="simple" xlink:href="http://mochi.test/moz/"><text transform="translate(10, 25)">SVG XLink</text></a></svg></p>';
 
   return BrowserTestUtils.openNewForegroundTab(gBrowser, testPage);
@@ -35,17 +35,17 @@ async function clean_up() {
   let downloads = await downloadList.getAll();
   for (let download of downloads) {
     await downloadList.remove(download);
     await download.finalize(true);
   }
   // Remove download history.
   await PlacesTestUtils.clearHistory();
 
-  gPrefService.clearUserPref("browser.altClickSave");
+  Services.prefs.clearUserPref("browser.altClickSave");
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 }
 
 add_task(async function test_alt_click() {
   await setup();
 
   let downloadList = await Downloads.getList(Downloads.ALL);
   let downloads = [];
--- a/browser/base/content/test/general/browser_contentAreaClick.js
+++ b/browser/base/content/test/general/browser_contentAreaClick.js
@@ -37,35 +37,35 @@ var gTests = [
     preventDefault: true,
   },
 
   // The next test was once handling feedService.forcePreview().  Now it should
   // just be like Alt click.
   {
     desc: "Shift+Alt left click",
     setup() {
-      gPrefService.setBoolPref("browser.altClickSave", true);
+      Services.prefs.setBoolPref("browser.altClickSave", true);
     },
     clean() {
-      gPrefService.clearUserPref("browser.altClickSave");
+      Services.prefs.clearUserPref("browser.altClickSave");
     },
     event: { shiftKey: true,
              altKey: true },
     targets: [ "commonlink", "maplink" ],
     expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
     preventDefault: true,
   },
 
   {
     desc: "Shift+Alt left click on XLinks",
     setup() {
-      gPrefService.setBoolPref("browser.altClickSave", true);
+      Services.prefs.setBoolPref("browser.altClickSave", true);
     },
     clean() {
-      gPrefService.clearUserPref("browser.altClickSave");
+      Services.prefs.clearUserPref("browser.altClickSave");
     },
     event: { shiftKey: true,
              altKey: true },
     targets: [ "mathxlink", "svgxlink"],
     expectedInvokedMethods: [ "saveURL" ],
     preventDefault: true,
   },
 
@@ -77,34 +77,34 @@ var gTests = [
     targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
     expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
     preventDefault: true,
   },
 
   {
     desc: "Alt click",
     setup() {
-      gPrefService.setBoolPref("browser.altClickSave", true);
+      Services.prefs.setBoolPref("browser.altClickSave", true);
     },
     clean() {
-      gPrefService.clearUserPref("browser.altClickSave");
+      Services.prefs.clearUserPref("browser.altClickSave");
     },
     event: { altKey: true },
     targets: [ "commonlink", "maplink" ],
     expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
     preventDefault: true,
   },
 
   {
     desc: "Alt click on XLinks",
     setup() {
-      gPrefService.setBoolPref("browser.altClickSave", true);
+      Services.prefs.setBoolPref("browser.altClickSave", true);
     },
     clean() {
-      gPrefService.clearUserPref("browser.altClickSave");
+      Services.prefs.clearUserPref("browser.altClickSave");
     },
     event: { altKey: true },
     targets: [ "mathxlink", "svgxlink" ],
     expectedInvokedMethods: [ "saveURL" ],
     preventDefault: true,
   },
 
   {
@@ -125,36 +125,36 @@ var gTests = [
     targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
     expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
     preventDefault: true,
   },
 
   {
     desc: "Simple middle click openwin",
     setup() {
-      gPrefService.setBoolPref("browser.tabs.opentabfor.middleclick", false);
+      Services.prefs.setBoolPref("browser.tabs.opentabfor.middleclick", false);
     },
     clean() {
-      gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick");
+      Services.prefs.clearUserPref("browser.tabs.opentabfor.middleclick");
     },
     event: { button: 1 },
     targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
     expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
     preventDefault: true,
   },
 
   {
     desc: "Middle mouse paste",
     setup() {
-      gPrefService.setBoolPref("middlemouse.contentLoadURL", true);
-      gPrefService.setBoolPref("general.autoScroll", false);
+      Services.prefs.setBoolPref("middlemouse.contentLoadURL", true);
+      Services.prefs.setBoolPref("general.autoScroll", false);
     },
     clean() {
-      gPrefService.clearUserPref("middlemouse.contentLoadURL");
-      gPrefService.clearUserPref("general.autoScroll");
+      Services.prefs.clearUserPref("middlemouse.contentLoadURL");
+      Services.prefs.clearUserPref("general.autoScroll");
     },
     event: { button: 1 },
     targets: [ "emptylink" ],
     expectedInvokedMethods: [ "middleMousePaste" ],
     preventDefault: true,
   },
 
 ];
--- a/browser/base/content/test/general/browser_ctrlTab.js
+++ b/browser/base/content/test/general/browser_ctrlTab.js
@@ -1,10 +1,10 @@
 add_task(async function() {
-  gPrefService.setBoolPref("browser.ctrlTab.previews", true);
+  Services.prefs.setBoolPref("browser.ctrlTab.previews", true);
 
   BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.addTab(gBrowser);
 
   // While doing this test, we should make sure the selected tab in the tab
   // preview is not changed by mouse events.  That may happen after closing
   // the selected tab with ctrl+W.  Disable all mouse events to prevent it.
@@ -107,18 +107,18 @@ add_task(async function() {
     await pressCtrlTab();
     document.removeEventListener("keypress", detectKeyEvent);
     ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
     is(focusedWindow, document.commandDispatcher.focusedWindow,
        "Ctrl+Tab doesn't change focus if one tab is open");
   }
 
   // cleanup
-  if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
-    gPrefService.clearUserPref("browser.ctrlTab.previews");
+  if (Services.prefs.prefHasUserValue("browser.ctrlTab.previews"))
+    Services.prefs.clearUserPref("browser.ctrlTab.previews");
 
   /* private utility functions */
 
   function pressCtrlTab(aShiftKey) {
     let promise;
     if (!isOpen() && canOpen()) {
       promise = BrowserTestUtils.waitForEvent(ctrlTab.panel, "popupshown");
     } else {
@@ -145,17 +145,17 @@ add_task(async function() {
     return promise;
   }
 
   function isOpen() {
     return ctrlTab.isOpen;
   }
 
   function canOpen() {
-    return gPrefService.getBoolPref("browser.ctrlTab.previews") && gBrowser.tabs.length > 2;
+    return Services.prefs.getBoolPref("browser.ctrlTab.previews") && gBrowser.tabs.length > 2;
   }
 
   function checkTabs(aTabs) {
     is(gBrowser.tabs.length, aTabs, "number of open tabs should be " + aTabs);
   }
 
   function selectTabs(tabs) {
     tabs.forEach(function(index) {
--- a/browser/base/content/test/general/browser_gestureSupport.js
+++ b/browser/base/content/test/general/browser_gestureSupport.js
@@ -337,62 +337,62 @@ function test_emitLatchedEvents(eventPre
 }
 
 function test_addCommand(prefName, id) {
   let cmd = test_commandset.appendChild(document.createElement("command"));
   cmd.setAttribute("id", id);
   cmd.setAttribute("oncommand", "this.callCount++;");
 
   cmd.origPrefName = prefName;
-  cmd.origPrefValue = gPrefService.getCharPref(prefName);
-  gPrefService.setCharPref(prefName, id);
+  cmd.origPrefValue = Services.prefs.getCharPref(prefName);
+  Services.prefs.setCharPref(prefName, id);
 
   return cmd;
 }
 
 function test_removeCommand(cmd) {
-  gPrefService.setCharPref(cmd.origPrefName, cmd.origPrefValue);
+  Services.prefs.setCharPref(cmd.origPrefName, cmd.origPrefValue);
   test_commandset.removeChild(cmd);
 }
 
 // Test whether latched events are only called once per direction of motion.
 function test_latchedGesture(gesture, inc, dec, eventPrefix) {
   let branch = test_prefBranch + gesture + ".";
 
   // Put the gesture into latched mode.
-  let oldLatchedValue = gPrefService.getBoolPref(branch + "latched");
-  gPrefService.setBoolPref(branch + "latched", true);
+  let oldLatchedValue = Services.prefs.getBoolPref(branch + "latched");
+  Services.prefs.setBoolPref(branch + "latched", true);
 
   // Install the test commands for increasing and decreasing motion.
   let cmd = {
     inc: test_addCommand(branch + inc, "test:incMotion"),
     dec: test_addCommand(branch + dec, "test:decMotion"),
   };
 
   // Test the gestures in each direction.
   test_emitLatchedEvents(eventPrefix, 500, cmd);
   test_emitLatchedEvents(eventPrefix, -500, cmd);
 
   // Restore the gesture to its original configuration.
-  gPrefService.setBoolPref(branch + "latched", oldLatchedValue);
+  Services.prefs.setBoolPref(branch + "latched", oldLatchedValue);
   for (let dir in cmd)
     test_removeCommand(cmd[dir]);
 }
 
 // Test whether non-latched events are triggered upon sufficient motion.
 function test_thresholdGesture(gesture, inc, dec, eventPrefix) {
   let branch = test_prefBranch + gesture + ".";
 
   // Disable latched mode for this gesture.
-  let oldLatchedValue = gPrefService.getBoolPref(branch + "latched");
-  gPrefService.setBoolPref(branch + "latched", false);
+  let oldLatchedValue = Services.prefs.getBoolPref(branch + "latched");
+  Services.prefs.setBoolPref(branch + "latched", false);
 
   // Set the triggering threshold value to 50.
-  let oldThresholdValue = gPrefService.getIntPref(branch + "threshold");
-  gPrefService.setIntPref(branch + "threshold", 50);
+  let oldThresholdValue = Services.prefs.getIntPref(branch + "threshold");
+  Services.prefs.setIntPref(branch + "threshold", 50);
 
   // Install the test commands for increasing and decreasing motion.
   let cmdInc = test_addCommand(branch + inc, "test:incMotion");
   let cmdDec = test_addCommand(branch + dec, "test:decMotion");
 
   // Send the start event but stop short of triggering threshold.
   cmdInc.callCount = cmdDec.callCount = 0;
   test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, 49.5, 0);
@@ -420,18 +420,18 @@ function test_thresholdGesture(gesture, 
 
   // Send the wrap-up event. No commands should trigger.
   cmdInc.callCount = cmdDec.callCount = 0;
   test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, -0.5, 0);
   ok(cmdInc.callCount == 0, "Increasing command was triggered");
   ok(cmdDec.callCount == 0, "Decreasing command was triggered");
 
   // Restore the gesture to its original configuration.
-  gPrefService.setBoolPref(branch + "latched", oldLatchedValue);
-  gPrefService.setIntPref(branch + "threshold", oldThresholdValue);
+  Services.prefs.setBoolPref(branch + "latched", oldLatchedValue);
+  Services.prefs.setIntPref(branch + "threshold", oldThresholdValue);
   test_removeCommand(cmdInc);
   test_removeCommand(cmdDec);
 }
 
 function test_swipeGestures() {
   // easier to type names for the direction constants
   let up = SimpleGestureEvent.DIRECTION_UP;
   let down = SimpleGestureEvent.DIRECTION_DOWN;
--- a/browser/base/content/test/general/browser_sanitize-passwordDisabledHosts.js
+++ b/browser/base/content/test/general/browser_sanitize-passwordDisabledHosts.js
@@ -14,17 +14,17 @@ add_task(async function() {
   // Sanity check
   is(Services.logins.getLoginSavingEnabled("http://example.com"), false,
      "example.com should be disabled for password saving since we haven't cleared that yet.");
 
   // Set up the sanitizer to just clear siteSettings
   let s = new Sanitizer();
   s.ignoreTimespan = false;
   s.prefDomain = "privacy.cpd.";
-  var itemPrefs = gPrefService.getBranch(s.prefDomain);
+  var itemPrefs = Services.prefs.getBranch(s.prefDomain);
   itemPrefs.setBoolPref("history", false);
   itemPrefs.setBoolPref("downloads", false);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", false);
   itemPrefs.setBoolPref("formdata", false);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
--- a/browser/base/content/test/general/browser_sanitize-sitepermissions.js
+++ b/browser/base/content/test/general/browser_sanitize-sitepermissions.js
@@ -15,17 +15,17 @@ function countPermissions() {
 }
 
 add_task(async function test() {
   // sanitize before we start so we have a good baseline.
   // Set up the sanitizer to just clear siteSettings
   let s = new Sanitizer();
   s.ignoreTimespan = false;
   s.prefDomain = "privacy.cpd.";
-  var itemPrefs = gPrefService.getBranch(s.prefDomain);
+  var itemPrefs = Services.prefs.getBranch(s.prefDomain);
   itemPrefs.setBoolPref("history", false);
   itemPrefs.setBoolPref("downloads", false);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", false);
   itemPrefs.setBoolPref("formdata", false);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
--- a/browser/base/content/test/general/browser_sanitize-timespans.js
+++ b/browser/base/content/test/general/browser_sanitize-timespans.js
@@ -77,17 +77,17 @@ async function onHistoryReady() {
   var minutesSinceMidnight = hoursSinceMidnight * 60 + new Date().getMinutes();
 
   // Should test cookies here, but nsICookieManager/nsICookieService
   // doesn't let us fake creation times.  bug 463127
 
   let s = new Sanitizer();
   s.ignoreTimespan = false;
   s.prefDomain = "privacy.cpd.";
-  var itemPrefs = gPrefService.getBranch(s.prefDomain);
+  var itemPrefs = Services.prefs.getBranch(s.prefDomain);
   itemPrefs.setBoolPref("history", true);
   itemPrefs.setBoolPref("downloads", true);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", false);
   itemPrefs.setBoolPref("formdata", true);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
--- a/browser/base/content/test/general/browser_sanitizeDialog.js
+++ b/browser/base/content/test/general/browser_sanitizeDialog.js
@@ -960,17 +960,17 @@ async function blankSlate() {
  * @param aPrefName
  *        The pref's sub-branch under the privacy branch
  * @param aExpectedVal
  *        The pref's expected value
  * @param aMsg
  *        Passed to is()
  */
 function boolPrefIs(aPrefName, aExpectedVal, aMsg) {
-  is(gPrefService.getBoolPref("privacy." + aPrefName), aExpectedVal, aMsg);
+  is(Services.prefs.getBoolPref("privacy." + aPrefName), aExpectedVal, aMsg);
 }
 
 /**
  * Checks to see if the download with the specified path exists.
  *
  * @param  aPath
  *         The path of the download to check
  * @return True if the download exists, false otherwise
@@ -1003,17 +1003,17 @@ async function ensureDownloadsClearedSta
  * @param aPrefName
  *        The pref's sub-branch under the privacy branch
  * @param aExpectedVal
  *        The pref's expected value
  * @param aMsg
  *        Passed to is()
  */
 function intPrefIs(aPrefName, aExpectedVal, aMsg) {
-  is(gPrefService.getIntPref("privacy." + aPrefName), aExpectedVal, aMsg);
+  is(Services.prefs.getIntPref("privacy." + aPrefName), aExpectedVal, aMsg);
 }
 
 /**
  * Creates a visit time.
  *
  * @param aMinutesAgo
  *        The visit will be visited this many minutes ago
  */
--- a/browser/base/content/test/general/browser_visibleTabs_tabPreview.js
+++ b/browser/base/content/test/general/browser_visibleTabs_tabPreview.js
@@ -1,14 +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/. */
 
 add_task(async function test() {
-  gPrefService.setBoolPref("browser.ctrlTab.previews", true);
+  Services.prefs.setBoolPref("browser.ctrlTab.previews", true);
 
   let [origTab] = gBrowser.visibleTabs;
   let tabOne = BrowserTestUtils.addTab(gBrowser);
   let tabTwo = BrowserTestUtils.addTab(gBrowser);
 
   // test the ctrlTab.tabList
   pressCtrlTab();
   ok(ctrlTab.tabList.length, 3, "Show 3 tabs in tab preview");
@@ -23,18 +23,18 @@ add_task(async function test() {
   pressCtrlTab();
   ok(ctrlTab.isOpen, "With 3 tabs open, Ctrl+Tab does open the preview panel");
   releaseCtrl();
 
   // cleanup
   gBrowser.removeTab(tabOne);
   gBrowser.removeTab(tabTwo);
 
-  if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
-    gPrefService.clearUserPref("browser.ctrlTab.previews");
+  if (Services.prefs.prefHasUserValue("browser.ctrlTab.previews"))
+    Services.prefs.clearUserPref("browser.ctrlTab.previews");
 });
 
 function pressCtrlTab(aShiftKey) {
   EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
 }
 
 function releaseCtrl() {
   EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
--- a/browser/base/content/test/newtab/browser_newtab_bug722273.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug722273.js
@@ -51,17 +51,17 @@ function promiseAddFakeVisits() {
     });
   });
 }
 
 function promiseSanitizeHistory() {
   let s = new Sanitizer();
   s.prefDomain = "privacy.cpd.";
 
-  let prefs = gPrefService.getBranch(s.prefDomain);
+  let prefs = Services.prefs.getBranch(s.prefDomain);
   prefs.setBoolPref("history", true);
   prefs.setBoolPref("downloads", false);
   prefs.setBoolPref("cache", false);
   prefs.setBoolPref("cookies", false);
   prefs.setBoolPref("formdata", false);
   prefs.setBoolPref("offlineApps", false);
   prefs.setBoolPref("passwords", false);
   prefs.setBoolPref("sessions", false);
--- a/browser/base/content/test/performance/browser_startup_flicker.js
+++ b/browser/base/content/test/performance/browser_startup_flicker.js
@@ -43,23 +43,16 @@ add_task(async function() {
         {name: "bug 1403648 - urlbar down arrow shouldn't flicker",
          condition: r => // 5x9px area, sometimes less at the end of the opacity transition
                          inRange(r.h, 3, 5) && inRange(r.w, 7, 9) &&
                          inRange(r.y1, 40, 80) && // in the toolbar
                          // at ~80% of the window width
                          inRange(r.x1, width * .75, width * .9)
         },
 
-        {name: "bug 1394914 - sidebar toolbar icon should be visible at first paint",
-         condition: r => r.h == 13 && inRange(r.w, 14, 16) && // icon size
-                         inRange(r.y1, 40, 80) && // in the toolbar
-                         // near the right end of screen
-                         inRange(r.x1, width - 100, width - 50)
-        },
-
         {name: "bug 1403648 - urlbar should be focused at first paint",
          condition: r => inRange(r.y2, 60, 80) && // in the toolbar
                          // taking 50% to 75% of the window width
                          inRange(r.w, width * .5, width * .75) &&
                          // starting at 15 to 25% of the window width
                          inRange(r.x1, width * .15, width * .25)
         },
 
--- a/browser/base/content/test/performance/browser_windowopen_flicker.js
+++ b/browser/base/content/test/performance/browser_windowopen_flicker.js
@@ -93,23 +93,16 @@ add_task(async function() {
         {name: "bug 1403648 - urlbar down arrow shouldn't flicker",
          condition: r => // 5x9px area, sometimes less at the end of the opacity transition
                          inRange(r.h, 3, 5) && inRange(r.w, 7, 9) &&
                          inRange(r.y1, 40, 80) && // in the toolbar
                          // at ~80% of the window width
                          inRange(r.x1, width * .75, width * .9)
         },
 
-        {name: "bug 1394914 - sidebar toolbar icon should be visible at first paint",
-         condition: r => r.h == 13 && inRange(r.w, 14, 16) && // icon size
-                         inRange(r.y1, 40, 80) && // in the toolbar
-                         // near the right end of screen
-                         inRange(r.x1, width - 100, width - 50)
-        },
-
         {name: "bug 1403648 - urlbar should be focused at first paint",
          condition: r => inRange(r.y2, 60, 80) && // in the toolbar
                          // taking 50% to 75% of the window width
                          inRange(r.w, width * .5, width * .75) &&
                          // starting at 15 to 25% of the window width
                          inRange(r.x1, width * .15, width * .25)
         },
 
--- a/browser/base/content/test/performance/browser_windowopen_reflows.js
+++ b/browser/base/content/test/performance/browser_windowopen_reflows.js
@@ -40,16 +40,25 @@ if (Services.appinfo.OS == "WINNT" || Se
       stack: [
         "rect@chrome://browser/content/browser-tabsintitlebar.js",
         "_update@chrome://browser/content/browser-tabsintitlebar.js",
         "init@chrome://browser/content/browser-tabsintitlebar.js",
         "handleEvent@chrome://browser/content/tabbrowser.xml",
       ],
       times: 4, // This number should only ever go down - never up.
     },
+    {
+      stack: [
+        "onOverflow@resource:///modules/CustomizableUI.jsm",
+        "init@resource:///modules/CustomizableUI.jsm",
+        "observe@resource:///modules/CustomizableUI.jsm",
+        "_delayedStartup@chrome://browser/content/browser.js",
+      ],
+      times: 2, // This number should only ever go down - never up.
+    },
   );
 }
 
 /*
  * This test ensures that there are no unexpected
  * uninterruptible reflows when opening new windows.
  */
 add_task(async function() {
--- a/browser/base/content/test/plugins/browser_clearplugindata.js
+++ b/browser/base/content/test/plugins/browser_clearplugindata.js
@@ -51,17 +51,17 @@ add_task(async function() {
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
 });
 
 function setPrefs(cookies, pluginData) {
   sanitizer = new Sanitizer();
   sanitizer.ignoreTimespan = false;
   sanitizer.prefDomain = "privacy.cpd.";
-  let itemPrefs = gPrefService.getBranch(sanitizer.prefDomain);
+  let itemPrefs = Services.prefs.getBranch(sanitizer.prefDomain);
   itemPrefs.setBoolPref("history", false);
   itemPrefs.setBoolPref("downloads", false);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", cookies);
   itemPrefs.setBoolPref("formdata", false);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
--- a/browser/base/content/test/urlbar/browser_bug304198.js
+++ b/browser/base/content/test/urlbar/browser_bug304198.js
@@ -55,46 +55,46 @@ add_task(async function() {
     });
   }
 
   async function prepareDeletedURLTab() {
     await BrowserTestUtils.switchTab(gBrowser, deletedURLTab);
     is(gURLBar.textValue, testURL, "gURLBar.textValue should be testURL after initial switch to deletedURLTab");
 
     // simulate the user removing the whole url from the location bar
-    gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", true);
+    Services.prefs.setBoolPref("browser.urlbar.clickSelectsAll", true);
 
     await urlbarBackspace();
     is(gURLBar.textValue, "", 'gURLBar.textValue should be "" (just set)');
-    if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll")) {
-      gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
+    if (Services.prefs.prefHasUserValue("browser.urlbar.clickSelectsAll")) {
+      Services.prefs.clearUserPref("browser.urlbar.clickSelectsAll");
     }
   }
 
   async function prepareFullURLTab() {
     await BrowserTestUtils.switchTab(gBrowser, fullURLTab);
     is(gURLBar.textValue, testURL, "gURLBar.textValue should be testURL after initial switch to fullURLTab");
   }
 
   async function preparePartialURLTab() {
     await BrowserTestUtils.switchTab(gBrowser, partialURLTab);
     is(gURLBar.textValue, testURL, "gURLBar.textValue should be testURL after initial switch to partialURLTab");
 
     // simulate the user removing part of the url from the location bar
-    gPrefService.setBoolPref("browser.urlbar.clickSelectsAll", false);
+    Services.prefs.setBoolPref("browser.urlbar.clickSelectsAll", false);
 
     let deleted = 0;
     while (deleted < charsToDelete) {
       await urlbarBackspace();
       deleted++;
     }
 
     is(gURLBar.textValue, testPartialURL, "gURLBar.textValue should be testPartialURL (just set)");
-    if (gPrefService.prefHasUserValue("browser.urlbar.clickSelectsAll")) {
-      gPrefService.clearUserPref("browser.urlbar.clickSelectsAll");
+    if (Services.prefs.prefHasUserValue("browser.urlbar.clickSelectsAll")) {
+      Services.prefs.clearUserPref("browser.urlbar.clickSelectsAll");
     }
   }
 
   // prepare the three tabs required by this test
 
   // First tab
   await prepareFullURLTab();
   await preparePartialURLTab();
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -832,17 +832,17 @@ file, You can obtain one at http://mozil
             case (accel && shift):
               suffix = ".org/";
               break;
             case (shift):
               suffix = ".net/";
               break;
             case (accel):
               try {
-                suffix = gPrefService.getCharPref("browser.fixup.alternate.suffix");
+                suffix = Services.prefs.getCharPref("browser.fixup.alternate.suffix");
                 if (suffix.charAt(suffix.length - 1) != "/")
                   suffix += "/";
               } catch (e) {
                 suffix = ".com/";
               }
               break;
           }
 
--- a/browser/components/customizableui/content/toolbar.xml
+++ b/browser/components/customizableui/content/toolbar.xml
@@ -13,43 +13,24 @@
       <stylesheet src="chrome://global/skin/toolbar.css"/>
     </resources>
     <implementation>
       <field name="overflowedDuringConstruction">null</field>
 
       <constructor><![CDATA[
           let scope = {};
           Cu.import("resource:///modules/CustomizableUI.jsm", scope);
+          let CustomizableUI = scope.CustomizableUI;
           // Add an early overflow event listener that will mark if the
           // toolbar overflowed during construction.
-          if (scope.CustomizableUI.isAreaOverflowable(this.id)) {
+          if (CustomizableUI.isAreaOverflowable(this.id)) {
             this.addEventListener("overflow", this);
             this.addEventListener("underflow", this);
           }
 
-          if (document.readyState == "complete") {
-            this._init();
-          } else {
-            // Need to wait until XUL overlays are loaded. See bug 554279.
-            let self = this;
-            document.addEventListener("readystatechange", function onReadyStateChange() {
-              if (document.readyState != "complete")
-                return;
-              document.removeEventListener("readystatechange", onReadyStateChange);
-              self._init();
-            });
-          }
-      ]]></constructor>
-
-      <method name="_init">
-        <body><![CDATA[
-          let scope = {};
-          Cu.import("resource:///modules/CustomizableUI.jsm", scope);
-          let CustomizableUI = scope.CustomizableUI;
-
           // Bug 989289: Forcibly set the now unsupported "mode" and "iconsize"
           // attributes, just in case they accidentally get restored from
           // persistence from a user that's been upgrading and downgrading.
           if (CustomizableUI.isBuiltinToolbar(this.id)) {
             const kAttributes = new Map([["mode", "icons"], ["iconsize", "small"]]);
             for (let [attribute, value] of kAttributes) {
               if (this.getAttribute(attribute) != value) {
                 this.setAttribute(attribute, value);
@@ -78,18 +59,17 @@
             }
           }
 
           // pass the current set of children for comparison with placements:
           let children = Array.from(this.childNodes)
                               .filter(node => node.getAttribute("skipintoolbarset") != "true" && node.id)
                               .map(node => node.id);
           CustomizableUI.registerToolbarNode(this, children);
-        ]]></body>
-      </method>
+      ]]></constructor>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           if (aEvent.type == "overflow" && aEvent.detail > 0) {
             if (this.overflowable && this.overflowable.initialized) {
               this.overflowable.onOverflow(aEvent);
             } else {
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -27,17 +27,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
   AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
   AutoCompletePopup: "resource://gre/modules/AutoCompletePopup.jsm",
   BookmarkHTMLUtils: "resource://gre/modules/BookmarkHTMLUtils.jsm",
   BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.jsm",
   BrowserUITelemetry: "resource:///modules/BrowserUITelemetry.jsm",
   BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
   ContentClick: "resource:///modules/ContentClick.jsm",
   ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
-  CustomizableUI: "resource:///modules/CustomizableUI.jsm",
   DateTimePickerHelper: "resource://gre/modules/DateTimePickerHelper.jsm",
   DirectoryLinksProvider: "resource:///modules/DirectoryLinksProvider.jsm",
   ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
   Feeds: "resource:///modules/Feeds.jsm",
   FileUtils: "resource://gre/modules/FileUtils.jsm",
   FileSource: "resource://gre/modules/L10nRegistry.jsm",
   FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
   Integration: "resource://gre/modules/Integration.jsm",
@@ -1165,20 +1164,16 @@ BrowserGlue.prototype = {
       Services.tm.idleDispatchToMainThread(() => {
         JawsScreenReaderVersionCheck.onWindowsRestored();
       });
     }
 
     Services.tm.idleDispatchToMainThread(() => {
       LanguagePrompt.init();
     });
-
-    Services.tm.idleDispatchToMainThread(() => {
-      this._urlbarMatchBuckets.init();
-    });
   },
 
   /**
    * Use this function as an entry point to schedule tasks that need
    * to run once per session, at any arbitrary point in time.
    * This function will be called from an idle observer. Check the value of
    * LATE_TASKS_IDLE_TIME_SEC to see the current value for this idle
    * observer.
@@ -2341,59 +2336,16 @@ BrowserGlue.prototype = {
                         .add(promptCount);
     } catch (ex) { /* Don't break the default prompt if telemetry is broken. */ }
 
     if (willPrompt) {
       DefaultBrowserCheck.prompt(RecentWindow.getMostRecentBrowserWindow());
     }
   },
 
-  // This keeps the browser.urlbar.matchBuckets pref updated depending on the
-  // placement of the searchbar.
-  _urlbarMatchBuckets: {
-    searchbarWidgetID: "search-container",
-    prefName: "browser.urlbar.matchBuckets",
-    searchbarPresentPrefValue: "general:5,suggestion:Infinity",
-
-    init() {
-      this._updatePref();
-      let checkWidget = widgetID => {
-        if (widgetID == this.searchbarWidgetID) {
-          this._updatePref();
-        }
-      };
-      CustomizableUI.addListener({
-        onWidgetAdded: checkWidget,
-        onWidgetRemoved: checkWidget,
-      });
-    },
-
-    _checkWidget(widgetID) {
-      if (widgetID == this.searchbarWidgetID) {
-        this._updatePref();
-      }
-    },
-
-    _updatePref() {
-      let pref = Services.prefs.getCharPref(this.prefName, "");
-      if (pref && pref != this.searchbarPresentPrefValue) {
-        // The user has customized the pref.  Don't touch it.
-        return;
-      }
-      let placement =
-        CustomizableUI.getPlacementOfWidget(this.searchbarWidgetID);
-      if (placement) {
-        Services.prefs.setCharPref(this.prefName,
-                                   this.searchbarPresentPrefValue);
-      } else {
-        Services.prefs.clearUserPref(this.prefName);
-      }
-    },
-  },
-
   // ------------------------------
   // public nsIBrowserGlue members
   // ------------------------------
 
   sanitize: function BG_sanitize(aParentWindow) {
     this._sanitizer.sanitize(aParentWindow);
   },
 
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -302,23 +302,19 @@ var gEditItemOverlay = {
     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)
       //  * first: focus the first non collapsed textbox
       // Note: since all controls are collapsed by default, we don't get the
       // default XUL dialog behavior, that selects the first control, so we set
       // the focus explicitly.
-      // Note: If focusedElement === "preferred", this file expects gPrefService
-      // to be defined in the global scope.
       let elt;
       if (focusedElement === "preferred") {
-        /* eslint-disable no-undef */
-        elt = this._element(gPrefService.getCharPref("browser.bookmarks.editDialog.firstEditField"));
-        /* eslint-enable no-undef */
+        elt = this._element(Services.prefs.getCharPref("browser.bookmarks.editDialog.firstEditField"));
       } else if (focusedElement === "first") {
         elt = document.querySelector("textbox:not([collapsed=true])");
       }
       if (elt) {
         elt.focus();
         elt.select();
       }
     };
--- a/browser/components/places/tests/browser/browser.ini
+++ b/browser/components/places/tests/browser/browser.ini
@@ -48,16 +48,17 @@ skip-if = (os == 'win' && ccov) # Bug 14
 subsuite = clipboard
 [browser_cutting_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_drag_bookmarks_on_toolbar.js]
 [browser_forgetthissite_single.js]
 [browser_history_sidebar_search.js]
 [browser_library_add_tags.js]
+skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_batch_delete.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_commands.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_delete_bookmarks_in_tags.js]
 [browser_library_delete_tags.js]
 [browser_library_downloads.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
@@ -71,16 +72,18 @@ skip-if = (os == 'win' && ccov) # Bug 14
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_move_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_open_leak.js]
 [browser_library_openFlatContainer.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_panel_leak.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
+[browser_library_remove_bookmark.js]
+skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_search.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_views_liveupdate.js]
 [browser_markPageAsFollowedLink.js]
 [browser_paste_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_paste_into_tags.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_library_remove_bookmark.js
@@ -0,0 +1,67 @@
+/**
+ * Test deleting bookmarks from library.
+ */
+"use strict";
+
+add_task(async function test_remove_bookmark() {
+  const uris = [
+    "http://example.com/1",
+    "http://example.com/2",
+    "http://example.com/3",
+  ];
+
+  let children = uris.map((uri, index) => {
+    return {
+      title: `bm${index}`,
+      url: uri,
+    };
+  });
+
+  // Insert Bookmarks.
+  await PlacesUtils.bookmarks.insertTree({
+    guid: PlacesUtils.bookmarks.unfiledGuid,
+    children
+  });
+
+  // Open the Library and select the "UnfiledBookmarks".
+  let library = await promiseLibrary("UnfiledBookmarks");
+
+  let PO = library.PlacesOrganizer;
+
+  Assert.equal(PlacesUtils.getConcreteItemGuid(PO._places.selectedNode),
+    PlacesUtils.bookmarks.unfiledGuid, "Should have selected unfiled bookmarks.");
+
+  let contextMenu = library.document.getElementById("placesContext");
+  let contextMenuDeleteItem = library.document.getElementById("placesContext_delete");
+
+  let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
+
+  let treeBoxObject = library.ContentTree.view.treeBoxObject;
+  let firstColumn = library.ContentTree.view.columns[0];
+  let firstBookmarkRect = treeBoxObject.getCoordsForCellItem(0, firstColumn, "bm0");
+
+  EventUtils.synthesizeMouse(
+    library.ContentTree.view.body,
+    firstBookmarkRect.x,
+    firstBookmarkRect.y,
+    { type: "contextmenu", button: 2 },
+    library
+  );
+
+  await popupShownPromise;
+
+  Assert.equal(library.ContentTree.view.result.root.childCount, 3, "Number of bookmarks before removal is right");
+
+  let removePromise = PlacesTestUtils.waitForNotification("onItemRemoved", (itemId, parentId, index, type, uri, guid) => uri.spec == uris[0]);
+  EventUtils.synthesizeMouseAtCenter(contextMenuDeleteItem, {}, library);
+
+  await removePromise;
+
+  Assert.equal(library.ContentTree.view.result.root.childCount, 2, "Should have removed the bookmark from the display");
+
+  // Cleanup
+  registerCleanupFunction(async function() {
+    await promiseLibraryClosed(library);
+    await PlacesUtils.bookmarks.eraseEverything();
+  });
+});
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js
@@ -42,17 +42,17 @@ function cleanup() {
 }
 
 function sanitizeCache() {
 
   let s = new Sanitizer();
   s.ignoreTimespan = false;
   s.prefDomain = "privacy.cpd.";
 
-  let prefs = gPrefService.getBranch(s.prefDomain);
+  let prefs = Services.prefs.getBranch(s.prefDomain);
   prefs.setBoolPref("history", false);
   prefs.setBoolPref("downloads", false);
   prefs.setBoolPref("cache", true);
   prefs.setBoolPref("cookies", false);
   prefs.setBoolPref("formdata", false);
   prefs.setBoolPref("offlineApps", false);
   prefs.setBoolPref("passwords", false);
   prefs.setBoolPref("sessions", false);
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
@@ -28,17 +28,17 @@ function test() {
   let file = dir2.clone();
   file.append("pbtest.file");
   file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   const kPrefName = "browser.open.lastDir";
 
   function setupCleanSlate(win) {
     win.gLastOpenDirectory.reset();
-    gPrefService.clearUserPref(kPrefName);
+    Services.prefs.clearUserPref(kPrefName);
   }
 
   setupCleanSlate(window);
 
   // open one regular and one private window
   testOnWindow(undefined, function(nonPrivateWindow) {
     setupCleanSlate(nonPrivateWindow);
     testOnWindow({private: true}, function(privateWindow) {
@@ -86,27 +86,27 @@ function test() {
          "The path set inside the private browsing mode should not leak when leaving that mode");
 
       setupCleanSlate(nonPrivateWindow);
       setupCleanSlate(privateWindow);
 
       // Test 3: the last open directory is set from a previous session, it should be used
       // in normal mode
 
-      gPrefService.setComplexValue(kPrefName, Ci.nsIFile, dir1);
+      Services.prefs.setComplexValue(kPrefName, Ci.nsIFile, dir1);
       is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
          "The pref set from last session should take effect outside the private browsing mode");
 
       setupCleanSlate(nonPrivateWindow);
       setupCleanSlate(privateWindow);
 
       // Test 4: the last open directory is set from a previous session, it should be used
       // in private browsing mode mode
 
-      gPrefService.setComplexValue(kPrefName, Ci.nsIFile, dir1);
+      Services.prefs.setComplexValue(kPrefName, Ci.nsIFile, dir1);
       // test the private window
       is(privateWindow.gLastOpenDirectory.path.path, dir1.path,
          "The pref set from last session should take effect inside the private browsing mode");
       // test the non-private window
       is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
          "The pref set from last session should remain in effect after leaving the private browsing mode");
 
       setupCleanSlate(nonPrivateWindow);
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
@@ -1,21 +1,21 @@
 /* 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/. */
 
 // This test makes sure that private browsing mode disables the remember option
 // for the popup blocker menu.
 add_task(async function test() {
   let testURI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/popup.html";
-  let oldPopupPolicy = gPrefService.getBoolPref("dom.disable_open_during_load");
-  gPrefService.setBoolPref("dom.disable_open_during_load", true);
+  let oldPopupPolicy = Services.prefs.getBoolPref("dom.disable_open_during_load");
+  Services.prefs.setBoolPref("dom.disable_open_during_load", true);
 
   registerCleanupFunction(() => {
-    gPrefService.setBoolPref("dom.disable_open_during_load", oldPopupPolicy);
+    Services.prefs.setBoolPref("dom.disable_open_during_load", oldPopupPolicy);
   });
 
   function testPopupBlockerMenuItem(aExpectedDisabled, aWindow, aCallback) {
 
     aWindow.gBrowser.addEventListener("DOMUpdatePageReport", function() {
       executeSoon(function() {
         let notification = aWindow.gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked");
         ok(notification, "The notification box should be displayed");
--- a/browser/components/sessionstore/test/browser_350525.js
+++ b/browser/components/sessionstore/test/browser_350525.js
@@ -64,28 +64,28 @@ add_task(async function() {
   await promiseRemoveTab(tab);
 
   /**
    * getClosedTabCount, undoCloseTab
    */
 
   // get closed tab count
   let count = ss.getClosedTabCount(window);
-  let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
+  let max_tabs_undo = Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
   ok(0 <= count && count <= max_tabs_undo,
      "getClosedTabCount returns zero or at most max_tabs_undo");
 
   // create a new tab
   let testURL = "about:mozilla";
   tab = BrowserTestUtils.addTab(gBrowser, testURL);
   await promiseBrowserLoaded(tab.linkedBrowser);
 
   // make sure that the next closed tab will increase getClosedTabCount
-  gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
-  registerCleanupFunction(() => gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo"));
+  Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
+  registerCleanupFunction(() => Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo"));
 
   // remove tab
   await promiseRemoveTab(tab);
 
   // getClosedTabCount
   let newcount = ss.getClosedTabCount(window);
   ok(newcount > count, "after closing a tab, getClosedTabCount has been incremented");
 
--- a/browser/components/sessionstore/test/browser_367052.js
+++ b/browser/components/sessionstore/test/browser_367052.js
@@ -1,19 +1,19 @@
 /* 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";
 
 add_task(async function() {
   // make sure that the next closed tab will increase getClosedTabCount
-  let max_tabs_undo = gPrefService.getIntPref("browser.sessionstore.max_tabs_undo");
-  gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
-  registerCleanupFunction(() => gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo"));
+  let max_tabs_undo = Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
+  Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", max_tabs_undo + 1);
+  registerCleanupFunction(() => Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo"));
 
   // Empty the list of closed tabs.
   while (ss.getClosedTabCount(window)) {
     ss.forgetClosedTab(window, 0);
   }
 
   // restore a blank tab
   let tab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
--- a/browser/components/sessionstore/test/browser_447951.js
+++ b/browser/components/sessionstore/test/browser_447951.js
@@ -5,27 +5,27 @@
 function test() {
   /** Test for Bug 447951 **/
 
   waitForExplicitFinish();
   const baseURL = "http://mochi.test:8888/browser/" +
     "browser/components/sessionstore/test/browser_447951_sample.html#";
 
   // Make sure the functionality added in bug 943339 doesn't affect the results
-  gPrefService.setIntPref("browser.sessionstore.max_serialize_back", -1);
-  gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", -1);
+  Services.prefs.setIntPref("browser.sessionstore.max_serialize_back", -1);
+  Services.prefs.setIntPref("browser.sessionstore.max_serialize_forward", -1);
   registerCleanupFunction(function() {
-    gPrefService.clearUserPref("browser.sessionstore.max_serialize_back");
-    gPrefService.clearUserPref("browser.sessionstore.max_serialize_forward");
+    Services.prefs.clearUserPref("browser.sessionstore.max_serialize_back");
+    Services.prefs.clearUserPref("browser.sessionstore.max_serialize_forward");
   });
 
   let tab = BrowserTestUtils.addTab(gBrowser);
   promiseBrowserLoaded(tab.linkedBrowser).then(() => {
     let tabState = { entries: [] };
-    let max_entries = gPrefService.getIntPref("browser.sessionhistory.max_entries");
+    let max_entries = Services.prefs.getIntPref("browser.sessionhistory.max_entries");
     for (let i = 0; i < max_entries; i++)
       tabState.entries.push({ url: baseURL + i, triggeringPrincipal_base64});
 
     promiseTabState(tab, tabState).then(() => {
       return TabStateFlusher.flush(tab.linkedBrowser);
     }).then(() => {
       tabState = JSON.parse(ss.getTabState(tab));
       is(tabState.entries.length, max_entries, "session history filled to the limit");
--- a/browser/components/sessionstore/test/browser_461634.js
+++ b/browser/components/sessionstore/test/browser_461634.js
@@ -29,18 +29,18 @@ function test() {
     } catch (ex) {
       return ex.name == "NS_ERROR_ILLEGAL_VALUE";
     }
   }
 
   // Open a window and add the above closed tab list.
   let newWin = openDialog(location, "", "chrome,all,dialog=no");
   promiseWindowLoaded(newWin).then(() => {
-    gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
-                            test_state.windows[0]._closedTabs.length);
+    Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo",
+                              test_state.windows[0]._closedTabs.length);
     ss.setWindowState(newWin, JSON.stringify(test_state), true);
 
     let closedTabs = SessionStore.getClosedTabData(newWin, false);
 
     // Verify that non JSON serialized data is the same as JSON serialized data.
     is(JSON.stringify(closedTabs), SessionStore.getClosedTabData(newWin),
        "Non-serialized data is the same as serialized data");
 
@@ -73,12 +73,12 @@ function test() {
     is(closedTabs.length, remember_count,
        "The correct amout of tabs was removed");
     is(countByTitle(closedTabs, FORGET), 0,
        "All tabs specifically forgotten were indeed removed");
     is(countByTitle(closedTabs, REMEMBER), remember_count,
        "... and tabs not specifically forgetten weren't");
 
     // Clean up.
-    gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+    Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo");
     BrowserTestUtils.closeWindow(newWin).then(finish);
   });
 }
--- a/browser/components/sessionstore/test/browser_464199.js
+++ b/browser/components/sessionstore/test/browser_464199.js
@@ -49,18 +49,18 @@ add_task(async function() {
 
   function countByTitle(aClosedTabList, aTitle) {
     return aClosedTabList.filter(aData => aData.title == aTitle).length;
   }
 
   // open a window and add the above closed tab list
   let newWin = openDialog(location, "", "chrome,all,dialog=no");
   await promiseWindowLoaded(newWin);
-  gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
-                          test_state.windows[0]._closedTabs.length);
+  Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo",
+                            test_state.windows[0]._closedTabs.length);
   ss.setWindowState(newWin, JSON.stringify(test_state), true);
 
   let closedTabs = JSON.parse(ss.getClosedTabData(newWin));
   is(closedTabs.length, test_state.windows[0]._closedTabs.length,
      "Closed tab list has the expected length");
   is(countByTitle(closedTabs, FORGET),
      test_state.windows[0]._closedTabs.length - remember_count,
      "The correct amout of tabs are to be forgotten");
@@ -72,11 +72,11 @@ add_task(async function() {
   closedTabs = JSON.parse(ss.getClosedTabData(newWin));
   is(closedTabs.length, remember_count,
      "The correct amout of tabs was removed");
   is(countByTitle(closedTabs, FORGET), 0,
      "All tabs to be forgotten were indeed removed");
   is(countByTitle(closedTabs, REMEMBER), remember_count,
      "... and tabs to be remembered weren't.");
   // clean up
-  gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+  Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo");
   await BrowserTestUtils.closeWindow(newWin);
 });
--- a/browser/components/sessionstore/test/browser_491577.js
+++ b/browser/components/sessionstore/test/browser_491577.js
@@ -76,18 +76,18 @@ function test() {
     } catch (ex) {
       return ex.name == "NS_ERROR_ILLEGAL_VALUE";
     }
   }
 
   // open a window and add the above closed window list
   let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
   promiseWindowLoaded(newWin).then(() => {
-    gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
-                            test_state._closedWindows.length);
+    Services.prefs.setIntPref("browser.sessionstore.max_windows_undo",
+                              test_state._closedWindows.length);
     ss.setWindowState(newWin, JSON.stringify(test_state), true);
 
     let closedWindows = JSON.parse(ss.getClosedWindowData());
     is(closedWindows.length, test_state._closedWindows.length,
        "Closed window list has the expected length");
     is(countByTitle(closedWindows, FORGET),
        test_state._closedWindows.length - remember_count,
        "The correct amount of windows are to be forgotten");
@@ -108,12 +108,12 @@ function test() {
     is(closedWindows.length, remember_count,
        "The correct amount of windows were removed");
     is(countByTitle(closedWindows, FORGET), 0,
        "All windows specifically forgotten were indeed removed");
     is(countByTitle(closedWindows, REMEMBER), remember_count,
        "... and windows not specifically forgetten weren't.");
 
     // clean up
-    gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
+    Services.prefs.clearUserPref("browser.sessionstore.max_windows_undo");
     BrowserTestUtils.closeWindow(newWin).then(finish);
   });
 }
--- a/browser/components/sessionstore/test/browser_506482.js
+++ b/browser/components/sessionstore/test/browser_506482.js
@@ -33,17 +33,17 @@ function test() {
   // test content URL
   const TEST_URL = "data:text/html;charset=utf-8,"
     + "<body style='width: 100000px; height: 100000px;'><p>top</p></body>";
 
   // preferences that we use
   const PREF_INTERVAL = "browser.sessionstore.interval";
 
   // make sure sessionstore.js is saved ASAP on all events
-  gPrefService.setIntPref(PREF_INTERVAL, 0);
+  Services.prefs.setIntPref(PREF_INTERVAL, 0);
 
   // get the initial sessionstore.js mtime (-1 if it doesn't exist yet)
   let mtime0 = getSessionstorejsModificationTime();
 
   // create and select a first tab
   let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
   promiseBrowserLoaded(tab.linkedBrowser).then(() => {
     // step1: the above has triggered some saveStateDelayed(), sleep until
@@ -57,16 +57,16 @@ function test() {
       gBrowser.selectedTab = tab;
       tab.linkedBrowser.contentWindow.scrollTo(1100, 1200);
       setTimeout(function step2() {
         let mtime2 = getSessionstorejsModificationTime();
         is(mtime2, mtime1,
            "tab selection and scrolling: sessionstore.js not updated");
 
         // ok, done, cleanup and finish
-        if (gPrefService.prefHasUserValue(PREF_INTERVAL))
-          gPrefService.clearUserPref(PREF_INTERVAL);
+        if (Services.prefs.prefHasUserValue(PREF_INTERVAL))
+          Services.prefs.clearUserPref(PREF_INTERVAL);
         gBrowser.removeTab(tab);
         finish();
       }, 3500); // end of sleep after tab selection and scrolling
     }, 3500); // end of sleep after initial saveStateDelayed()
   });
 }
--- a/browser/components/sessionstore/test/browser_589246.js
+++ b/browser/components/sessionstore/test/browser_589246.js
@@ -2,18 +2,18 @@
  * 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/. */
 
 // Mirrors WINDOW_ATTRIBUTES IN nsSessionStore.js
 const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
 
 var stateBackup = ss.getBrowserState();
 
-var originalWarnOnClose = gPrefService.getBoolPref("browser.tabs.warnOnClose");
-var originalStartupPage = gPrefService.getIntPref("browser.startup.page");
+var originalWarnOnClose = Services.prefs.getBoolPref("browser.tabs.warnOnClose");
+var originalStartupPage = Services.prefs.getIntPref("browser.startup.page");
 var originalWindowType = document.documentElement.getAttribute("windowtype");
 
 var gotLastWindowClosedTopic = false;
 var shouldPinTab = false;
 var shouldOpenTabs = false;
 var shouldCloseTab = false;
 var testNum = 0;
 var afterTestCallback;
@@ -103,31 +103,31 @@ tests.push({
 function test() {
   /** Test for Bug 589246 - Closed window state getting corrupted when closing
       and reopening last browser window without exiting browser **/
   waitForExplicitFinish();
   // windows opening & closing, so extending the timeout
   requestLongerTimeout(2);
 
   // We don't want the quit dialog pref
-  gPrefService.setBoolPref("browser.tabs.warnOnClose", false);
+  Services.prefs.setBoolPref("browser.tabs.warnOnClose", false);
   // Ensure that we would restore the session (important for Windows)
-  gPrefService.setIntPref("browser.startup.page", 3);
+  Services.prefs.setIntPref("browser.startup.page", 3);
 
   runNextTestOrFinish();
 }
 
 function runNextTestOrFinish() {
   if (tests.length) {
     setupForTest(tests.shift());
   } else {
     // some state is cleaned up at the end of each test, but not all
     ["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
-      if (gPrefService.prefHasUserValue(p))
-        gPrefService.clearUserPref(p);
+      if (Services.prefs.prefHasUserValue(p))
+        Services.prefs.clearUserPref(p);
     });
 
     ss.setBrowserState(stateBackup);
     executeSoon(finish);
   }
 }
 
 function setupForTest(aConditions) {
--- a/browser/components/sessionstore/test/browser_merge_closed_tabs.js
+++ b/browser/components/sessionstore/test/browser_merge_closed_tabs.js
@@ -27,17 +27,17 @@ add_task(async function() {
         { state: { entries: [{ ID: 1002, url: "about:robots", triggeringPrincipal_base64 }]} },
         { state: { entries: [{ ID: 1003, url: "about:robots", triggeringPrincipal_base64 }]} },
         { state: { entries: [{ ID: 1004, url: "about:robots", triggeringPrincipal_base64 }]} }
       ]
     }]
   };
 
   const maxTabsUndo = 4;
-  gPrefService.setIntPref("browser.sessionstore.max_tabs_undo", maxTabsUndo);
+  Services.prefs.setIntPref("browser.sessionstore.max_tabs_undo", maxTabsUndo);
 
   // Open a new window and restore it to an initial state.
   let win = await promiseNewWindowLoaded({private: false});
   SessionStore.setWindowState(win, JSON.stringify(initialState), true);
   is(SessionStore.getClosedTabCount(win), 2, "2 closed tabs after restoring initial state");
 
   // Restore the new state but do not overwrite existing tabs (this should
   // cause the closed tabs to be merged).
@@ -59,13 +59,13 @@ add_task(async function() {
          "Closed tab entry matches");
     } else {
       is(cData[i].state.entries[0].ID, iClosed[i - rClosed.length].state.entries[0].ID,
          "Closed tab entry matches");
     }
   }
 
   // Clean up.
-  gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
+  Services.prefs.clearUserPref("browser.sessionstore.max_tabs_undo");
   await BrowserTestUtils.closeWindow(win);
 });
 
 
--- a/browser/components/tests/browser/browser.ini
+++ b/browser/components/tests/browser/browser.ini
@@ -1,8 +1,7 @@
 [DEFAULT]
 
 [browser_bug538331.js]
 skip-if = !updater
 reason = test depends on update channel
 [browser_contentpermissionprompt.js]
 [browser_default_bookmark_toolbar_visibility.js]
-[browser_urlbar_matchBuckets.js]
--- a/browser/components/tests/browser/browser_bug538331.js
+++ b/browser/components/tests/browser/browser_bug538331.js
@@ -112,22 +112,22 @@ this.__defineGetter__("gBG", function() 
 
 function test() {
   waitForExplicitFinish();
 
   // Reset the startup page pref since it may have been set by other tests
   // and we will assume it is default.
   Services.prefs.clearUserPref("browser.startup.page");
 
-  if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
-    gOriginalMStone = gPrefService.getCharPref(PREF_MSTONE);
+  if (Services.prefs.prefHasUserValue(PREF_MSTONE)) {
+    gOriginalMStone = Services.prefs.getCharPref(PREF_MSTONE);
   }
 
-  if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
-    gOriginalOverrideURL = gPrefService.getCharPref(PREF_OVERRIDE_URL);
+  if (Services.prefs.prefHasUserValue(PREF_OVERRIDE_URL)) {
+    gOriginalOverrideURL = Services.prefs.getCharPref(PREF_OVERRIDE_URL);
   }
 
   testDefaultArgs();
 }
 
 var gWindowCatcher = {
   windowsOpen: 0,
   finishCalled: false,
@@ -169,45 +169,45 @@ var gWindowCatcher = {
     }, {once: true});
   }
 };
 
 function finish_test() {
   // Reset browser.startup.homepage_override.mstone to the original value or
   // clear it if it didn't exist.
   if (gOriginalMStone) {
-    gPrefService.setCharPref(PREF_MSTONE, gOriginalMStone);
-  } else if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
-    gPrefService.clearUserPref(PREF_MSTONE);
+    Services.prefs.setCharPref(PREF_MSTONE, gOriginalMStone);
+  } else if (Services.prefs.prefHasUserValue(PREF_MSTONE)) {
+    Services.prefs.clearUserPref(PREF_MSTONE);
   }
 
   // Reset startup.homepage_override_url to the original value or clear it if
   // it didn't exist.
   if (gOriginalOverrideURL) {
-    gPrefService.setCharPref(PREF_OVERRIDE_URL, gOriginalOverrideURL);
-  } else if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
-    gPrefService.clearUserPref(PREF_OVERRIDE_URL);
+    Services.prefs.setCharPref(PREF_OVERRIDE_URL, gOriginalOverrideURL);
+  } else if (Services.prefs.prefHasUserValue(PREF_OVERRIDE_URL)) {
+    Services.prefs.clearUserPref(PREF_OVERRIDE_URL);
   }
 
   writeUpdatesToXMLFile(XML_EMPTY);
   reloadUpdateManagerData();
 
   finish();
 }
 
 // Test the defaultArgs returned by nsBrowserContentHandler after an update
 function testDefaultArgs() {
   // Clear any pre-existing override in defaultArgs that are hanging around.
   // This will also set the browser.startup.homepage_override.mstone preference
   // if it isn't already set.
   Cc["@mozilla.org/browser/clh;1"].getService(Ci.nsIBrowserHandler).defaultArgs;
 
-  let originalMstone = gPrefService.getCharPref(PREF_MSTONE);
+  let originalMstone = Services.prefs.getCharPref(PREF_MSTONE);
 
-  gPrefService.setCharPref(PREF_OVERRIDE_URL, DEFAULT_PREF_URL);
+  Services.prefs.setCharPref(PREF_OVERRIDE_URL, DEFAULT_PREF_URL);
 
   writeUpdatesToXMLFile(XML_EMPTY);
   reloadUpdateManagerData();
 
   for (let i = 0; i < BCH_TESTS.length; i++) {
     let testCase = BCH_TESTS[i];
     ok(true, "Test nsBrowserContentHandler " + (i + 1) + ": " + testCase.description);
 
@@ -235,35 +235,35 @@ function testDefaultArgs() {
 
     if (overrideArgs == "" && noOverrideArgs) {
       overrideArgs = noOverrideArgs;
     } else if (noOverrideArgs) {
       overrideArgs += "|" + noOverrideArgs;
     }
 
     if (testCase.noMstoneChange === undefined) {
-      gPrefService.setCharPref(PREF_MSTONE, "PreviousMilestone");
+      Services.prefs.setCharPref(PREF_MSTONE, "PreviousMilestone");
     }
 
     if (testCase.noPostUpdatePref == undefined) {
-      gPrefService.setBoolPref(PREF_POSTUPDATE, true);
+      Services.prefs.setBoolPref(PREF_POSTUPDATE, true);
     }
 
     let defaultArgs = Cc["@mozilla.org/browser/clh;1"].
                       getService(Ci.nsIBrowserHandler).defaultArgs;
     is(defaultArgs, overrideArgs, "correct value returned by defaultArgs");
 
     if (testCase.noMstoneChange === undefined || testCase.noMstoneChange != true) {
-      let newMstone = gPrefService.getCharPref(PREF_MSTONE);
+      let newMstone = Services.prefs.getCharPref(PREF_MSTONE);
       is(originalMstone, newMstone, "preference " + PREF_MSTONE +
          " should have been updated");
     }
 
-    if (gPrefService.prefHasUserValue(PREF_POSTUPDATE)) {
-      gPrefService.clearUserPref(PREF_POSTUPDATE);
+    if (Services.prefs.prefHasUserValue(PREF_POSTUPDATE)) {
+      Services.prefs.clearUserPref(PREF_POSTUPDATE);
     }
   }
 
   testShowNotification();
 }
 
 // nsBrowserGlue.js _showUpdateNotification notification tests
 const BG_NOTIFY_TESTS = [
@@ -319,17 +319,17 @@ function testShowNotification() {
         actionsXML += " notificationButtonAccessKey=\"" + testCase.notificationButtonAccessKey + "\"";
       }
       writeUpdatesToXMLFile(XML_PREFIX + actionsXML + XML_SUFFIX);
     } else {
       writeUpdatesToXMLFile(XML_EMPTY);
     }
 
     reloadUpdateManagerData();
-    gPrefService.setBoolPref(PREF_POSTUPDATE, true);
+    Services.prefs.setBoolPref(PREF_POSTUPDATE, true);
 
     gBG.observe(null, "browser-glue-test", "post-update-notification");
 
     let updateBox = notifyBox.getNotificationWithValue("post-update-notification");
     if (testCase.actions && testCase.actions.indexOf("showNotification") != -1 &&
         testCase.actions.indexOf("silent") == -1) {
       ok(updateBox, "Update notification box should have been displayed");
       if (updateBox) {
@@ -362,17 +362,17 @@ function testShowNotification() {
       } else if (i == (BG_NOTIFY_TESTS.length - 1)) {
         // If updateBox is null the test has already reported errors so bail
         finish_test();
       }
     } else {
       ok(!updateBox, "Update notification box should not have been displayed");
     }
 
-    let prefHasUserValue = gPrefService.prefHasUserValue(PREF_POSTUPDATE);
+    let prefHasUserValue = Services.prefs.prefHasUserValue(PREF_POSTUPDATE);
     is(prefHasUserValue, false, "preference " + PREF_POSTUPDATE +
        " shouldn't have a user value");
   }
 }
 
 // Test opening the url provided by the updates.xml in the last test
 function testNotificationURL() {
   ok(true, "Test testNotificationURL: clicking the notification button " +
deleted file mode 100644
--- a/browser/components/tests/browser/browser_urlbar_matchBuckets.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Makes sure the browser.urlbar.matchBuckets pref is correct and updated when
-// the searchbar is added to or removed from the UI.
-
-const SEARCHBAR_WIDGET_ID = "search-container";
-const PREF_NAME = "browser.urlbar.matchBuckets";
-const SEARCHBAR_PRESENT_PREF_VALUE = "general:5,suggestion:Infinity";
-
-// nsBrowserGlue initializes the relevant code via idleDispatchToMainThread(),
-// so to make sure this test runs after that happens, first run a dummy task
-// that queues an idle callback.
-add_task(async function waitForIdle() {
-  await TestUtils.waitForIdle();
-});
-
-add_task(async function test() {
-  // Initial checks.
-  Assert.equal(CustomizableUI.getPlacementOfWidget(SEARCHBAR_WIDGET_ID), null,
-               "Sanity check: searchbar should not be placed initially");
-  Assert.equal(Services.prefs.getCharPref(PREF_NAME, ""), "",
-               "Sanity check: pref should be cleared initially");
-
-  // Add the searchbar.  The pref should be set.
-  let widgetPromise = promiseWidget("onWidgetAdded");
-  CustomizableUI.addWidgetToArea(SEARCHBAR_WIDGET_ID,
-                                 CustomizableUI.AREA_NAVBAR);
-  info("Waiting for searchbar to be added");
-  await widgetPromise;
-  Assert.equal(Services.prefs.getCharPref(PREF_NAME),
-               SEARCHBAR_PRESENT_PREF_VALUE,
-               "Pref should be set after adding searchbar");
-
-  // Remove the searchbar.  The pref should be cleared.
-  widgetPromise = promiseWidget("onWidgetRemoved");
-  CustomizableUI.removeWidgetFromArea(SEARCHBAR_WIDGET_ID);
-  info("Waiting for searchbar to be removed");
-  await widgetPromise;
-  Assert.equal(Services.prefs.getCharPref(PREF_NAME, ""), "",
-               "Pref should be cleared after removing searchbar");
-
-  // Customize the pref.
-  let customizedPref = "extension:1," + SEARCHBAR_PRESENT_PREF_VALUE;
-  Services.prefs.setCharPref(PREF_NAME, customizedPref);
-
-  // Add the searchbar again.  Since the pref is customized, it shouldn't be
-  // changed.
-  widgetPromise = promiseWidget("onWidgetAdded");
-  CustomizableUI.addWidgetToArea(SEARCHBAR_WIDGET_ID,
-                                 CustomizableUI.AREA_NAVBAR);
-  info("Waiting for searchbar to be added");
-  await widgetPromise;
-  Assert.equal(Services.prefs.getCharPref(PREF_NAME), customizedPref,
-               "Customized pref should remain same after adding searchbar");
-
-  // Remove the searchbar again.  Since the pref is customized, it shouldn't be
-  // changed.
-  widgetPromise = promiseWidget("onWidgetRemoved");
-  CustomizableUI.removeWidgetFromArea(SEARCHBAR_WIDGET_ID);
-  info("Waiting for searchbar to be removed");
-  await widgetPromise;
-  Assert.equal(Services.prefs.getCharPref(PREF_NAME), customizedPref,
-               "Customized pref should remain same after removing searchbar");
-
-  Services.prefs.clearUserPref(PREF_NAME);
-});
-
-function promiseWidget(observerName) {
-  return new Promise(resolve => {
-    let listener = {};
-    listener[observerName] = widgetID => {
-      if (widgetID == SEARCHBAR_WIDGET_ID) {
-        CustomizableUI.removeListener(listener);
-        executeSoon(resolve);
-      }
-    };
-    CustomizableUI.addListener(listener);
-  });
-}
--- a/browser/extensions/shield-recipe-client/test/browser/browser.ini
+++ b/browser/extensions/shield-recipe-client/test/browser/browser.ini
@@ -9,16 +9,17 @@ head = head.js
 [browser_bootstrap.js]
 [browser_CleanupManager.js]
 [browser_NormandyDriver.js]
 [browser_FilterExpressions.js]
 [browser_EventEmitter.js]
 [browser_Storage.js]
 [browser_Heartbeat.js]
 [browser_RecipeRunner.js]
+skip-if = true # bug 1424400
 [browser_LogManager.js]
 [browser_ClientEnvironment.js]
 [browser_ShieldRecipeClient.js]
 [browser_ShieldPreferences.js]
 [browser_PreferenceExperiments.js]
 [browser_about_studies.js]
 [browser_about_preferences.js]
 # Skip this test when FHR/Telemetry aren't available.
--- a/browser/modules/test/browser/browser_taskbar_preview.js
+++ b/browser/modules/test/browser/browser_taskbar_preview.js
@@ -14,35 +14,35 @@ function test() {
   const ENABLE_PREF_NAME = "browser.taskbar.previews.enable";
 
   let temp = {};
   Cu.import("resource:///modules/WindowsPreviewPerTab.jsm", temp);
   let AeroPeek = temp.AeroPeek;
 
   waitForExplicitFinish();
 
-  gPrefService.setBoolPref(ENABLE_PREF_NAME, true);
+  Services.prefs.setBoolPref(ENABLE_PREF_NAME, true);
 
   is(1, AeroPeek.windows.length, "Got the expected number of windows");
 
   checkPreviews(1, "Browser starts with one preview");
 
   BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.addTab(gBrowser);
 
   checkPreviews(4, "Correct number of previews after adding");
 
   for (let preview of AeroPeek.previews)
     ok(preview.visible, "Preview is shown as expected");
 
-  gPrefService.setBoolPref(ENABLE_PREF_NAME, false);
+  Services.prefs.setBoolPref(ENABLE_PREF_NAME, false);
   is(0, AeroPeek.previews.length, "Should have 0 previews when disabled");
 
-  gPrefService.setBoolPref(ENABLE_PREF_NAME, true);
+  Services.prefs.setBoolPref(ENABLE_PREF_NAME, true);
   checkPreviews(4, "Previews are back when re-enabling");
   for (let preview of AeroPeek.previews)
     ok(preview.visible, "Preview is shown as expected after re-enabling");
 
   [1, 2, 3, 4].forEach(function(idx) {
     gBrowser.selectedTab = gBrowser.tabs[idx];
     ok(checkSelectedTab(), "Current tab is correctly selected");
   });
@@ -73,18 +73,18 @@ function test() {
 
   // Change selection
   gBrowser.selectedTab = gBrowser.tabs[0];
   checkSelectedTab();
   // Close nonselected tab via controller
   getPreviewForTab(gBrowser.tabs[1]).controller.onClose();
   checkPreviews(1);
 
-  if (gPrefService.prefHasUserValue(ENABLE_PREF_NAME))
-    gPrefService.setBoolPref(ENABLE_PREF_NAME, !gPrefService.getBoolPref(ENABLE_PREF_NAME));
+  if (Services.prefs.prefHasUserValue(ENABLE_PREF_NAME))
+    Services.prefs.setBoolPref(ENABLE_PREF_NAME, !Services.prefs.getBoolPref(ENABLE_PREF_NAME));
 
   finish();
 
   function checkPreviews(aPreviews, msg) {
     let nPreviews = AeroPeek.previews.length;
     is(aPreviews, gBrowser.tabs.length, "Browser has expected number of tabs - " + msg);
     is(nPreviews, gBrowser.tabs.length, "Browser has one preview per tab - " + msg);
     is(nPreviews, aPreviews, msg || "Got expected number of previews");
--- a/build/build-clang/clang-win32.json
+++ b/build/build-clang/clang-win32.json
@@ -7,12 +7,13 @@
     "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
     "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
     "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
     "python_path": "c:/mozilla-build/python/python.exe",
     "cc": "cl.exe",
     "cxx": "cl.exe",
     "patches": [
+      "r318309.patch",
       "msvc-host-x64.patch",
       "loosen-msvc-detection.patch"
     ]
 }
--- a/build/build-clang/clang-win64.json
+++ b/build/build-clang/clang-win64.json
@@ -8,13 +8,14 @@
     "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
     "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
     "python_path": "c:/mozilla-build/python/python.exe",
     "cc": "cl.exe",
     "cxx": "cl.exe",
     "ml": "ml64.exe",
     "patches": [
+      "r318309.patch",
       "loosen-msvc-detection.patch",
       "hide-gcda-profiling-symbols.patch",
       "fflush-before-unlocking.patch"
     ]
 }
new file mode 100644
--- /dev/null
+++ b/build/build-clang/r318309.patch
@@ -0,0 +1,279 @@
+From a53ee5453ba652fc640467847415dd44c24fed02 Mon Sep 17 00:00:00 2001
+From: Hans Wennborg <hans@hanshq.net>
+Date: Wed, 15 Nov 2017 17:11:53 +0000
+Subject: [PATCH] BuiltinOperatorOverloadBuilder: Don't consider types that are
+ unavailable on the target (PR35174)
+
+In the PR, Clang ended up in a situation where it tried to mangle the
+__float128 type, which isn't supported when targetingt MSVC, because
+Clang instantiated a variable template with that type when searching for
+a conversion to use in an arithmetic expression.
+
+Differential revision: https://reviews.llvm.org/D39579
+
+git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@318309 91177308-0d34-0410-b5e6-96231b3b80d8
+
+diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
+index f4b8b4e34a8..fa6279800dc 100644
+--- a/clang/lib/Sema/SemaOverload.cpp
++++ b/clang/lib/Sema/SemaOverload.cpp
+@@ -7615,53 +7615,62 @@ class BuiltinOperatorOverloadBuilder {
+   SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
+   OverloadCandidateSet &CandidateSet;
+ 
+-  // Define some constants used to index and iterate over the arithemetic types
+-  // provided via the getArithmeticType() method below.
+-  // The "promoted arithmetic types" are the arithmetic
++  static constexpr int ArithmeticTypesCap = 24;
++  SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
++
++  // Define some indices used to iterate over the arithemetic types in
++  // ArithmeticTypes.  The "promoted arithmetic types" are the arithmetic
+   // types are that preserved by promotion (C++ [over.built]p2).
+-  static const unsigned FirstIntegralType = 4;
+-  static const unsigned LastIntegralType = 21;
+-  static const unsigned FirstPromotedIntegralType = 4,
+-                        LastPromotedIntegralType = 12;
+-  static const unsigned FirstPromotedArithmeticType = 0,
+-                        LastPromotedArithmeticType = 12;
+-  static const unsigned NumArithmeticTypes = 21;
+-
+-  /// \brief Get the canonical type for a given arithmetic type index.
+-  CanQualType getArithmeticType(unsigned index) {
+-    assert(index < NumArithmeticTypes);
+-    static CanQualType ASTContext::* const
+-      ArithmeticTypes[NumArithmeticTypes] = {
+-      // Start of promoted types.
+-      &ASTContext::FloatTy,
+-      &ASTContext::DoubleTy,
+-      &ASTContext::LongDoubleTy,
+-      &ASTContext::Float128Ty,
+-
+-      // Start of integral types.
+-      &ASTContext::IntTy,
+-      &ASTContext::LongTy,
+-      &ASTContext::LongLongTy,
+-      &ASTContext::Int128Ty,
+-      &ASTContext::UnsignedIntTy,
+-      &ASTContext::UnsignedLongTy,
+-      &ASTContext::UnsignedLongLongTy,
+-      &ASTContext::UnsignedInt128Ty,
+-      // End of promoted types.
+-
+-      &ASTContext::BoolTy,
+-      &ASTContext::CharTy,
+-      &ASTContext::WCharTy,
+-      &ASTContext::Char16Ty,
+-      &ASTContext::Char32Ty,
+-      &ASTContext::SignedCharTy,
+-      &ASTContext::ShortTy,
+-      &ASTContext::UnsignedCharTy,
+-      &ASTContext::UnsignedShortTy,
+-      // End of integral types.
+-      // FIXME: What about complex? What about half?
+-    };
+-    return S.Context.*ArithmeticTypes[index];
++  unsigned FirstIntegralType,
++           LastIntegralType;
++  unsigned FirstPromotedIntegralType,
++           LastPromotedIntegralType;
++  unsigned FirstPromotedArithmeticType,
++           LastPromotedArithmeticType;
++  unsigned NumArithmeticTypes;
++
++  void InitArithmeticTypes() {
++    // Start of promoted types.
++    FirstPromotedArithmeticType = 0;
++    ArithmeticTypes.push_back(S.Context.FloatTy);
++    ArithmeticTypes.push_back(S.Context.DoubleTy);
++    ArithmeticTypes.push_back(S.Context.LongDoubleTy);
++    if (S.Context.getTargetInfo().hasFloat128Type())
++      ArithmeticTypes.push_back(S.Context.Float128Ty);
++
++    // Start of integral types.
++    FirstIntegralType = ArithmeticTypes.size();
++    FirstPromotedIntegralType = ArithmeticTypes.size();
++    ArithmeticTypes.push_back(S.Context.IntTy);
++    ArithmeticTypes.push_back(S.Context.LongTy);
++    ArithmeticTypes.push_back(S.Context.LongLongTy);
++    if (S.Context.getTargetInfo().hasInt128Type())
++      ArithmeticTypes.push_back(S.Context.Int128Ty);
++    ArithmeticTypes.push_back(S.Context.UnsignedIntTy);
++    ArithmeticTypes.push_back(S.Context.UnsignedLongTy);
++    ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy);
++    if (S.Context.getTargetInfo().hasInt128Type())
++      ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
++    LastPromotedIntegralType = ArithmeticTypes.size();
++    LastPromotedArithmeticType = ArithmeticTypes.size();
++    // End of promoted types.
++
++    ArithmeticTypes.push_back(S.Context.BoolTy);
++    ArithmeticTypes.push_back(S.Context.CharTy);
++    ArithmeticTypes.push_back(S.Context.WCharTy);
++    ArithmeticTypes.push_back(S.Context.Char16Ty);
++    ArithmeticTypes.push_back(S.Context.Char32Ty);
++    ArithmeticTypes.push_back(S.Context.SignedCharTy);
++    ArithmeticTypes.push_back(S.Context.ShortTy);
++    ArithmeticTypes.push_back(S.Context.UnsignedCharTy);
++    ArithmeticTypes.push_back(S.Context.UnsignedShortTy);
++    LastIntegralType = ArithmeticTypes.size();
++    NumArithmeticTypes = ArithmeticTypes.size();
++    // End of integral types.
++    // FIXME: What about complex? What about half?
++
++    assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
++           "Enough inline storage for all arithmetic types.");
+   }
+ 
+   /// \brief Helper method to factor out the common pattern of adding overloads
+@@ -7720,18 +7729,8 @@ class BuiltinOperatorOverloadBuilder {
+         HasArithmeticOrEnumeralCandidateType),
+       CandidateTypes(CandidateTypes),
+       CandidateSet(CandidateSet) {
+-    // Validate some of our static helper constants in debug builds.
+-    assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
+-           "Invalid first promoted integral type");
+-    assert(getArithmeticType(LastPromotedIntegralType - 1)
+-             == S.Context.UnsignedInt128Ty &&
+-           "Invalid last promoted integral type");
+-    assert(getArithmeticType(FirstPromotedArithmeticType)
+-             == S.Context.FloatTy &&
+-           "Invalid first promoted arithmetic type");
+-    assert(getArithmeticType(LastPromotedArithmeticType - 1)
+-             == S.Context.UnsignedInt128Ty &&
+-           "Invalid last promoted arithmetic type");
++
++    InitArithmeticTypes();
+   }
+ 
+   // C++ [over.built]p3:
+@@ -7758,7 +7757,7 @@ class BuiltinOperatorOverloadBuilder {
+     for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
+          Arith < NumArithmeticTypes; ++Arith) {
+       addPlusPlusMinusMinusStyleOverloads(
+-        getArithmeticType(Arith),
++        ArithmeticTypes[Arith],
+         VisibleTypeConversionsQuals.hasVolatile(),
+         VisibleTypeConversionsQuals.hasRestrict());
+     }
+@@ -7831,7 +7830,7 @@ class BuiltinOperatorOverloadBuilder {
+ 
+     for (unsigned Arith = FirstPromotedArithmeticType;
+          Arith < LastPromotedArithmeticType; ++Arith) {
+-      QualType ArithTy = getArithmeticType(Arith);
++      QualType ArithTy = ArithmeticTypes[Arith];
+       S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet);
+     }
+ 
+@@ -7871,7 +7870,7 @@ class BuiltinOperatorOverloadBuilder {
+ 
+     for (unsigned Int = FirstPromotedIntegralType;
+          Int < LastPromotedIntegralType; ++Int) {
+-      QualType IntTy = getArithmeticType(Int);
++      QualType IntTy = ArithmeticTypes[Int];
+       S.AddBuiltinCandidate(&IntTy, Args, CandidateSet);
+     }
+ 
+@@ -8099,8 +8098,8 @@ class BuiltinOperatorOverloadBuilder {
+          Left < LastPromotedArithmeticType; ++Left) {
+       for (unsigned Right = FirstPromotedArithmeticType;
+            Right < LastPromotedArithmeticType; ++Right) {
+-        QualType LandR[2] = { getArithmeticType(Left),
+-                              getArithmeticType(Right) };
++        QualType LandR[2] = { ArithmeticTypes[Left],
++                              ArithmeticTypes[Right] };
+         S.AddBuiltinCandidate(LandR, Args, CandidateSet);
+       }
+     }
+@@ -8143,8 +8142,8 @@ class BuiltinOperatorOverloadBuilder {
+          Left < LastPromotedIntegralType; ++Left) {
+       for (unsigned Right = FirstPromotedIntegralType;
+            Right < LastPromotedIntegralType; ++Right) {
+-        QualType LandR[2] = { getArithmeticType(Left),
+-                              getArithmeticType(Right) };
++        QualType LandR[2] = { ArithmeticTypes[Left],
++                              ArithmeticTypes[Right] };
+         S.AddBuiltinCandidate(LandR, Args, CandidateSet);
+       }
+     }
+@@ -8324,18 +8323,18 @@ class BuiltinOperatorOverloadBuilder {
+       for (unsigned Right = FirstPromotedArithmeticType;
+            Right < LastPromotedArithmeticType; ++Right) {
+         QualType ParamTypes[2];
+-        ParamTypes[1] = getArithmeticType(Right);
++        ParamTypes[1] = ArithmeticTypes[Right];
+ 
+         // Add this built-in operator as a candidate (VQ is empty).
+         ParamTypes[0] =
+-          S.Context.getLValueReferenceType(getArithmeticType(Left));
++          S.Context.getLValueReferenceType(ArithmeticTypes[Left]);
+         S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
+                               /*IsAssigmentOperator=*/isEqualOp);
+ 
+         // Add this built-in operator as a candidate (VQ is 'volatile').
+         if (VisibleTypeConversionsQuals.hasVolatile()) {
+           ParamTypes[0] =
+-            S.Context.getVolatileType(getArithmeticType(Left));
++            S.Context.getVolatileType(ArithmeticTypes[Left]);
+           ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+           S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
+                                 /*IsAssigmentOperator=*/isEqualOp);
+@@ -8390,15 +8389,15 @@ class BuiltinOperatorOverloadBuilder {
+       for (unsigned Right = FirstPromotedIntegralType;
+            Right < LastPromotedIntegralType; ++Right) {
+         QualType ParamTypes[2];
+-        ParamTypes[1] = getArithmeticType(Right);
++        ParamTypes[1] = ArithmeticTypes[Right];
+ 
+         // Add this built-in operator as a candidate (VQ is empty).
+         ParamTypes[0] =
+-          S.Context.getLValueReferenceType(getArithmeticType(Left));
++          S.Context.getLValueReferenceType(ArithmeticTypes[Left]);
+         S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
+         if (VisibleTypeConversionsQuals.hasVolatile()) {
+           // Add this built-in operator as a candidate (VQ is 'volatile').
+-          ParamTypes[0] = getArithmeticType(Left);
++          ParamTypes[0] = ArithmeticTypes[Left];
+           ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
+           ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+           S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
+diff --git a/test/SemaCXX/microsoft-vs-float128.cpp b/test/SemaCXX/microsoft-vs-float128.cpp
+new file mode 100644
+index 00000000000..d271e470032
+--- /dev/null
++++ b/test/SemaCXX/microsoft-vs-float128.cpp
+@@ -0,0 +1,34 @@
++// RUN: %clang_cc1 -triple x86_64-linux-gnu -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
++// RUN: %clang_cc1 -triple i686-pc-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 -DMS %s
++
++template <bool> struct enable_if {};
++template<> struct enable_if<true> { typedef void type; };
++
++template <typename, typename> struct is_same { static constexpr bool value = false; };
++template <typename T> struct is_same<T, T> { static constexpr bool value = true; };
++
++
++
++
++struct S {
++  // The only numeric types S can be converted to is __int128 and __float128.
++  template <typename T, typename = typename enable_if<
++                            !((__is_integral(T) && sizeof(T) != 16) ||
++                              is_same<T, float>::value ||
++                              is_same<T, double>::value ||
++                              is_same<T, long double>::value)>::type>
++  operator T() { return T(); }
++};
++
++void f() {
++#ifdef MS
++  // When targeting Win32, __float128 and __int128 do not exist, so the S
++  // object cannot be converted to anything usable in the expression.
++  // expected-error@+2{{invalid operands to binary expression ('S' and 'double')}}
++#endif
++  double d = S() + 1.0;
++#ifndef MS
++  // expected-error@-2{{use of overloaded operator '+' is ambiguous}}
++  // expected-note@-3 36{{built-in candidate operator+}}
++#endif
++}
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -835,17 +835,17 @@ nsScriptSecurityManager::CheckLoadURIFla
         if (reportErrors) {
             ReportError(nullptr, errorTag, aSourceURI, aTargetURI);
         }
         return rv;
     }
 
     // Check for chrome target URI
     bool hasFlags = false;
-    rv = NS_URIChainHasFlags(aTargetBaseURI,
+    rv = NS_URIChainHasFlags(aTargetURI,
                              nsIProtocolHandler::URI_IS_UI_RESOURCE,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     if (hasFlags) {
         if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
             // Allow a URI_IS_UI_RESOURCE source to link to a URI_IS_UI_RESOURCE
             // target if ALLOW_CHROME is set.
             //
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,11 +1,11 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Taken from upstream commit: 95faec6ebf536f313288cd67868d560b52b1dc5b
+Taken from upstream commit: 53faca589b021f01c7af5980c8c0e98b58c02e4c
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.0
 - babel-preset-react @6.24.1
 - react @15.6.2
 - react-dom @15.6.2
 - webpack @3.8.1
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -1626,63 +1626,93 @@ html[dir="rtl"] .managed-tree .tree .nod
 
 .function-signature .paren {
   color: var(--object-color);
 }
 
 .function-signature .comma {
   color: var(--object-color);
 }
+.command-bar-button {
+  appearance: none;
+  background: transparent;
+  border: none;
+  display: inline-block;
+  text-align: center;
+  position: relative;
+  padding: 0px 5px;
+  margin-inline-end: 0.3em;
+  fill: currentColor;
+}
+
+.command-bar-button:focus {
+  outline: none;
+}
+
+.command-bar-button:disabled {
+  opacity: 0.8;
+  cursor: default;
+}
+
+.command-bar-button:not(.disabled):hover {
+  background: var(--theme-toolbar-background-hover);
+}
+
+:root.theme-dark .command-bar-button {
+  color: var(--theme-body-color);
+}
+
+.command-bar-button > * {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  vertical-align: middle;
+}
 /* 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/>. */
 
-.toggle-button-start,
-.toggle-button-end {
+.toggle-button {
   transform: translate(0, 0px);
   transition: transform 0.25s ease-in-out;
   padding: 5px;
 }
 
-.toggle-button-start.vertical,
-.toggle-button-end.vertical {
+.toggle-button.vertical {
   padding: 2.5px 2.5px;
 }
 
-.toggle-button-start svg,
-.toggle-button-end svg {
-  width: 16px;
+.toggle-button svg {
   fill: var(--theme-comment);
 }
 
-.theme-dark .toggle-button-start svg,
-.theme-dark .toggle-button-end svg {
+:root.theme-dark .toggle-button svg {
   fill: var(--theme-comment-alt);
 }
 
-.toggle-button-end {
+.toggle-button.end {
   margin-inline-end: 0px;
   margin-inline-start: auto;
 }
 
-.toggle-button-start {
+.toggle-button.start {
   margin-inline-start: 0px;
 }
 
-html:not([dir="rtl"]) .toggle-button-end svg,
-html[dir="rtl"] .toggle-button-start svg {
+html:not([dir="rtl"]) .toggle-button.end svg,
+html[dir="rtl"] .toggle-button.start svg {
   transform: rotate(180deg);
 }
 
-html .toggle-button-end.vertical svg {
+html .toggle-button.end.vertical svg {
   transform: rotate(-90deg);
 }
 
-.toggle-button-start.collapsed,
-.toggle-button-end.collapsed {
+.toggle-button.start.collapsed,
+.toggle-button.end.collapsed {
   transform: rotate(180deg);
 }
 /* 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/>. */
 
 .source-footer {
   background: var(--theme-body-background);
@@ -3237,116 +3267,72 @@ html .breakpoints-list .breakpoint.pause
 html[dir="rtl"] .command-bar {
   border-right: 1px solid var(--theme-splitter-color);
 }
 
 .theme-dark .command-bar {
   background-color: var(--theme-tab-toolbar-background);
 }
 
-.command-bar > button {
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  appearance: none;
-  background: transparent;
-  border: none;
-  display: inline-block;
-  text-align: center;
-  padding: 8px 5px;
-  position: relative;
-  fill: currentColor;
-}
-
-.command-bar > button:not(.disabled):hover {
-  background: var(--theme-toolbar-background-hover);
-}
-
-:root.theme-dark .command-bar > button {
-  color: var(--theme-body-color);
-}
-
-.command-bar > button {
-  margin-inline-end: 0.3em;
-}
-
-.command-bar > button:focus {
-  outline: none;
-}
-
-html .command-bar > button:disabled {
-  opacity: 0.8;
-  cursor: default;
-}
-
 img.pause,
 img.stepOver,
 img.stepIn,
 img.stepOut,
 img.resume {
   background-color: var(--theme-body-color);
 }
 
-.command-bar > button > img {
-  width: 16px;
-  height: 16px;
-  display: inline-block;
-}
-
-.command-bar > button > img.pause {
+.command-bar img.pause {
   mask: url("chrome://devtools/skin/images/debugger/pause.svg") no-repeat;
 }
 
-.command-bar > button > img.stepOver {
+.command-bar img.stepOver {
   mask: url("chrome://devtools/skin/images/debugger/stepOver.svg") no-repeat;
 }
 
-.command-bar > button > img.stepIn {
+.command-bar img.stepIn {
   mask: url("chrome://devtools/skin/images/debugger/stepIn.svg") no-repeat;
 }
 
-.command-bar > button > img.stepOut {
+.command-bar img.stepOut {
   mask: url("chrome://devtools/skin/images/debugger/stepOut.svg") no-repeat;
 }
 
-.command-bar > button > img.resume {
+.command-bar img.resume {
   mask: url("chrome://devtools/skin/images/debugger/resume.svg") no-repeat;
 }
 
-.command-bar > button.pause-exceptions.uncaught.enabled > img.pause-exceptions {
+.command-bar > .pause-exceptions.uncaught.enabled > img.pause-exceptions {
   background-color: var(--theme-highlight-purple);
 }
 
-.command-bar > button.pause-exceptions.all.enabled > img.pause-exceptions {
+.command-bar > .pause-exceptions.all.enabled > img.pause-exceptions {
   background-color: var(--theme-highlight-blue);
 }
 
-.command-bar > button.pause-exceptions.enabled > img.pause-exceptions {
+.command-bar > .pause-exceptions.enabled > img.pause-exceptions {
   background-color: var(--theme-body-color);
 }
 
-.command-bar > button > img.pause-exceptions {
+.command-bar img.pause-exceptions {
   mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
   margin-inline-start: 0.2em;
 }
 
 .command-bar .subSettings {
   float: right;
 }
 
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
   flex: 0 0 27px;
 }
 
-.command-bar > button {
-  padding: 6px 5px;
-}
-
 .command-bar.bottom {
   justify-content: flex-end;
 }
 
 .command-bar.bottom > button {
   color: var(--theme-comment);
   width: 26px;
 }
@@ -3678,17 +3664,16 @@ html .welcomebox .toggle-button-end.coll
  * 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/>. */
 
 .source-header {
   border-bottom: 1px solid var(--theme-splitter-color);
   width: 100%;
   height: 30px;
   display: flex;
-  align-items: flex-end;
 }
 
 .source-header * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .source-header .new-tab-btn {
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -8754,17 +8754,17 @@ module.exports = invariant;
 
 (function() {
   var AcronymResult, computeScore, emptyAcronymResult, isAcronymFullWord, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_size, wm;
 
   wm = 150;
 
   pos_bonus = 20;
 
-  tau_size = 85;
+  tau_size = 150;
 
   miss_coeff = 0.75;
 
   exports.score = function(string, query, options) {
     var allowErrors, preparedQuery, score, string_lw;
     preparedQuery = options.preparedQuery, allowErrors = options.allowErrors;
     if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) {
       return 0;
@@ -8795,17 +8795,17 @@ module.exports = invariant;
       if (i === m) {
         return false;
       }
     }
     return true;
   };
 
   exports.computeScore = computeScore = function(subject, subject_lw, preparedQuery) {
-    var acro, acro_score, align, csc_diag, csc_invalid, csc_row, csc_score, i, j, m, miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz;
+    var acro, acro_score, align, csc_diag, csc_row, csc_score, csc_should_rebuild, i, j, m, miss_budget, miss_left, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz;
     query = preparedQuery.query;
     query_lw = preparedQuery.query_lw;
     m = subject.length;
     n = query.length;
     acro = scoreAcronyms(subject, subject_lw, query, query_lw);
     acro_score = acro.score;
     if (acro.count === n) {
       return scoreExact(n, m, acro_score, acro.pos);
@@ -8814,64 +8814,57 @@ module.exports = invariant;
     if (pos > -1) {
       return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m);
     }
     score_row = new Array(n);
     csc_row = new Array(n);
     sz = scoreSize(n, m);
     miss_budget = Math.ceil(miss_coeff * n) + 5;
     miss_left = miss_budget;
+    csc_should_rebuild = true;
     j = -1;
     while (++j < n) {
       score_row[j] = 0;
       csc_row[j] = 0;
     }
-    i = subject_lw.indexOf(query_lw[0]);
-    if (i > -1) {
-      i--;
-    }
-    mm = subject_lw.lastIndexOf(query_lw[n - 1], m);
-    if (mm > i) {
-      m = mm + 1;
-    }
-    csc_invalid = true;
+    i = -1;
     while (++i < m) {
       si_lw = subject_lw[i];
-      if (preparedQuery.charCodes[si_lw.charCodeAt(0)] == null) {
-        if (csc_invalid !== true) {
+      if (!si_lw.charCodeAt(0) in preparedQuery.charCodes) {
+        if (csc_should_rebuild) {
           j = -1;
           while (++j < n) {
             csc_row[j] = 0;
           }
-          csc_invalid = true;
+          csc_should_rebuild = false;
         }
         continue;
       }
       score = 0;
       score_diag = 0;
       csc_diag = 0;
       record_miss = true;
-      csc_invalid = false;
+      csc_should_rebuild = true;
       j = -1;
       while (++j < n) {
         score_up = score_row[j];
         if (score_up > score) {
           score = score_up;
         }
         csc_score = 0;
         if (query_lw[j] === si_lw) {
           start = isWordStart(i, subject, subject_lw);
           csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
           align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score);
           if (align > score) {
             score = align;
             miss_left = miss_budget;
           } else {
             if (record_miss && --miss_left <= 0) {
-              return score_row[n - 1] * sz;
+              return Math.max(score, score_row[n - 1]) * sz;
             }
             record_miss = false;
           }
         }
         score_diag = score_up;
         csc_diag = csc_row[j];
         csc_row[j] = csc_score;
         score_row[j] = score;
@@ -8972,16 +8965,19 @@ module.exports = invariant;
     if (query[j] === subject[i]) {
       sameCase++;
     }
     while (++sz < k && query_lw[++j] === subject_lw[++i]) {
       if (query[j] === subject[i]) {
         sameCase++;
       }
     }
+    if (sz < k) {
+      i--;
+    }
     if (sz === 1) {
       return 1 + 2 * sameCase;
     }
     return scorePattern(sz, n, sameCase, startOfWord, isWordEnd(i, subject, subject_lw, m));
   };
 
   exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) {
     var end, i, pos2, sameCase, start;
@@ -9089,19 +9085,19 @@ module.exports = invariant;
 /* 164 */
 /***/ (function(module, exports, __webpack_require__) {
 
 (function() {
   var computeScore, countDir, file_coeff, getExtension, getExtensionScore, isMatch, scorePath, scoreSize, tau_depth, _ref;
 
   _ref = __webpack_require__(163), isMatch = _ref.isMatch, computeScore = _ref.computeScore, scoreSize = _ref.scoreSize;
 
-  tau_depth = 13;
-
-  file_coeff = 1.2;
+  tau_depth = 20;
+
+  file_coeff = 2.5;
 
   exports.score = function(string, query, options) {
     var allowErrors, preparedQuery, score, string_lw;
     preparedQuery = options.preparedQuery, allowErrors = options.allowErrors;
     if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) {
       return 0;
     }
     string_lw = string.toLowerCase();
@@ -9332,17 +9328,17 @@ module.exports = invariant;
       matchPos++;
       if (matchPos > strPos) {
         output += tagOpen;
         output += string.substring(strPos, matchPos);
         output += tagClose;
         strPos = matchPos;
       }
     }
-    if (strPos < string.length - 1) {
+    if (strPos <= string.length - 1) {
       output += string.substring(strPos);
     }
     return output;
   };
 
   basenameMatch = function(subject, subject_lw, preparedQuery, pathSeparator) {
     var basePos, depth, end;
     end = subject.length - 1;
@@ -12269,169 +12265,17 @@ module.exports = {
 /* 338 */,
 /* 339 */,
 /* 340 */,
 /* 341 */,
 /* 342 */,
 /* 343 */,
 /* 344 */,
 /* 345 */,
-/* 346 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, '__esModule', {
-    value: true
-});
-
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-
-var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
-
-var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
-
-function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-var DOMParser = typeof window !== 'undefined' && window.DOMParser;
-var process = process || {};
-process.env = process.env || {};
-var parserAvailable = typeof DOMParser !== 'undefined' && DOMParser.prototype != null && DOMParser.prototype.parseFromString != null;
-
-function isParsable(src) {
-    // kinda naive but meh, ain't gonna use full-blown parser for this
-    return parserAvailable && typeof src === 'string' && src.trim().substr(0, 4) === '<svg';
-}
-
-// parse SVG string using `DOMParser`
-function parseFromSVGString(src) {
-    var parser = new DOMParser();
-    return parser.parseFromString(src, "image/svg+xml");
-}
-
-// Transform DOM prop/attr names applicable to `<svg>` element but react-limited
-function switchSVGAttrToReactProp(propName) {
-    switch (propName) {
-        case 'class':
-            return 'className';
-        default:
-            return propName;
-    }
-}
-
-var InlineSVG = (function (_React$Component) {
-    _inherits(InlineSVG, _React$Component);
-
-    _createClass(InlineSVG, null, [{
-        key: 'defaultProps',
-        value: {
-            element: 'i',
-            raw: false,
-            src: ''
-        },
-        enumerable: true
-    }, {
-        key: 'propTypes',
-        value: {
-            src: _react2['default'].PropTypes.string.isRequired,
-            element: _react2['default'].PropTypes.string,
-            raw: _react2['default'].PropTypes.bool
-        },
-        enumerable: true
-    }]);
-
-    function InlineSVG(props) {
-        _classCallCheck(this, InlineSVG);
-
-        _get(Object.getPrototypeOf(InlineSVG.prototype), 'constructor', this).call(this, props);
-        this._extractSVGProps = this._extractSVGProps.bind(this);
-    }
-
-    // Serialize `Attr` objects in `NamedNodeMap`
-
-    _createClass(InlineSVG, [{
-        key: '_serializeAttrs',
-        value: function _serializeAttrs(map) {
-            var ret = {};
-            var prop = undefined;
-            for (var i = 0; i < map.length; i++) {
-                prop = switchSVGAttrToReactProp(map[i].name);
-                ret[prop] = map[i].value;
-            }
-            return ret;
-        }
-
-        // get <svg /> element props
-    }, {
-        key: '_extractSVGProps',
-        value: function _extractSVGProps(src) {
-            var map = parseFromSVGString(src).documentElement.attributes;
-            return map.length > 0 ? this._serializeAttrs(map) : null;
-        }
-
-        // get content inside <svg> element.
-    }, {
-        key: '_stripSVG',
-        value: function _stripSVG(src) {
-            return parseFromSVGString(src).documentElement.innerHTML;
-        }
-    }, {
-        key: 'componentWillReceiveProps',
-        value: function componentWillReceiveProps(_ref) {
-            var children = _ref.children;
-
-            if ("production" !== process.env.NODE_ENV && children != null) {
-                console.info('<InlineSVG />: `children` prop will be ignored.');
-            }
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var Element = undefined,
-                __html = undefined,
-                svgProps = undefined;
-            var _props = this.props;
-            var element = _props.element;
-            var raw = _props.raw;
-            var src = _props.src;
-
-            var otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
-
-            if (raw === true && isParsable(src)) {
-                Element = 'svg';
-                svgProps = this._extractSVGProps(src);
-                __html = this._stripSVG(src);
-            }
-            __html = __html || src;
-            Element = Element || element;
-            svgProps = svgProps || {};
-
-            return _react2['default'].createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
-                dangerouslySetInnerHTML: { __html: __html } }));
-        }
-    }]);
-
-    return InlineSVG;
-})(_react2['default'].Component);
-
-exports['default'] = InlineSVG;
-module.exports = exports['default'];
-
-/***/ }),
+/* 346 */,
 /* 347 */
 /***/ (function(module, exports) {
 
 module.exports = "<!-- 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/. --><svg viewBox=\"-1 73 16 11\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"Shape-Copy-3-+-Shape-Copy-4\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(0.000000, 74.000000)\"><path d=\"M0.749321284,4.16081709 L4.43130681,0.242526751 C4.66815444,-0.00952143591 5.06030999,-0.0211407611 5.30721074,0.216574262 C5.55411149,0.454289284 5.56226116,0.851320812 5.32541353,1.103369 L1.95384971,4.69131519 L5.48809879,8.09407556 C5.73499955,8.33179058 5.74314922,8.72882211 5.50630159,8.9808703 C5.26945396,9.23291849 4.87729841,9.24453781 4.63039766,9.00682279 L0.827097345,5.34502101 C0.749816996,5.31670099 0.677016974,5.27216098 0.613753508,5.21125118 C0.427367989,5.03179997 0.377040713,4.7615583 0.465458792,4.53143559 C0.492371834,4.43667624 0.541703274,4.34676528 0.613628034,4.27022448 C0.654709457,4.22650651 0.70046335,4.19002189 0.749321284,4.16081709 Z\" id=\"Shape-Copy-3\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path><path d=\"M13.7119065,5.44453032 L9.77062746,9.09174784 C9.51677479,9.3266604 9.12476399,9.31089603 8.89504684,9.05653714 C8.66532968,8.80217826 8.68489539,8.40554539 8.93874806,8.17063283 L12.5546008,4.82456128 L9.26827469,1.18571135 C9.03855754,0.931352463 9.05812324,0.534719593 9.31197591,0.299807038 C9.56582858,0.0648944831 9.95783938,0.0806588502 10.1875565,0.335017737 L13.72891,4.25625178 C13.8013755,4.28980469 13.8684335,4.3382578 13.9254821,4.40142604 C14.0883019,4.58171146 14.1258883,4.83347168 14.0435812,5.04846202 C14.0126705,5.15680232 13.9526426,5.2583679 13.8641331,5.34027361 C13.8174417,5.38348136 13.7660763,5.41820853 13.7119065,5.44453032 Z\" id=\"Shape-Copy-4\" stroke=\"#FFFFFF\" stroke-width=\"0.05\" fill=\"#DDE1E4\"></path></g></svg>"
 
 /***/ }),
 /* 348 */
 /***/ (function(module, exports) {
@@ -12521,17 +12365,17 @@ module.exports = "<!-- This Source Code 
 /***/ (function(module, exports) {
 
 module.exports = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 20 16\" stroke=\"none\" fillrule=\"evenodd\"><rect x=\"3\" y=\"10\" width=\"3\" height=\"3\" rx=\"1\"></rect><rect x=\"12\" y=\"3\" width=\"2\" height=\"9\" rx=\"1\"></rect><rect transform=\"translate(13.000000, 7.500000) rotate(60.000000) translate(-13.000000, -7.500000) \" x=\"12\" y=\"3\" width=\"2\" height=\"9\" rx=\"1\"></rect><rect transform=\"translate(13.000000, 7.500000) rotate(-60.000000) translate(-13.000000, -7.500000) \" x=\"12\" y=\"3\" width=\"2\" height=\"9\" rx=\"1\"></rect></svg>"
 
 /***/ }),
 /* 363 */
 /***/ (function(module, exports) {
 
-module.exports = "<!-- 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/. --><svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.925 12.5l7.4-5-7.4-5v10zM6 12.5v-10c0-.785.8-1.264 1.415-.848l7.4 5c.58.392.58 1.304 0 1.696l-7.4 5C6.8 13.764 6 13.285 6 12.5z\" fill-rule=\"evenodd\"></path></svg>"
+module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\"><path fill=\"black\" id=\"svg_1\" fill-rule=\"evenodd\" d=\"m4.55195,12.97461l7.4,-5l-7.4,-5l0,10zm-0.925,0l0,-10c0,-0.785 0.8,-1.264 1.415,-0.848l7.4,5c0.58,0.392 0.58,1.304 0,1.696l-7.4,5c-0.615,0.416 -1.415,-0.063 -1.415,-0.848z\"></path></svg>"
 
 /***/ }),
 /* 364 */
 /***/ (function(module, exports) {
 
 module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 33 12\"><path id=\"base-path\" d=\"M27.1,0H1C0.4,0,0,0.4,0,1v10c0,0.6,0.4,1,1,1h26.1 c0.6,0,1.2-0.3,1.5-0.7L33,6l-4.4-5.3C28.2,0.3,27.7,0,27.1,0z\"></path></svg>"
 
 /***/ }),
@@ -22999,49 +22843,51 @@ var _react2 = _interopRequireDefault(_re
 var _classnames = __webpack_require__(175);
 
 var _classnames2 = _interopRequireDefault(_classnames);
 
 var _Svg = __webpack_require__(1359);
 
 var _Svg2 = _interopRequireDefault(_Svg);
 
+var _CommandBarButton = __webpack_require__(1787);
+
+var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton);
+
 __webpack_require__(1321);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-/* 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/>. */
-
 class PaneToggleButton extends _react.Component {
   shouldComponentUpdate(nextProps) {
     const { collapsed, horizontal } = this.props;
 
     return horizontal !== nextProps.horizontal || collapsed !== nextProps.collapsed;
   }
 
   render() {
     const { position, collapsed, horizontal, handleClick } = this.props;
     const title = !collapsed ? L10N.getStr("expandPanes") : L10N.getStr("collapsePanes");
 
     return _react2.default.createElement(
-      "button",
-      {
-        className: (0, _classnames2.default)(`toggle-button-${position}`, {
+      _CommandBarButton2.default,
+      {
+        className: (0, _classnames2.default)("toggle-button", position, {
           collapsed,
           vertical: horizontal != null ? !horizontal : false
         }),
         onClick: () => handleClick(position, collapsed),
         title: title
       },
       _react2.default.createElement(_Svg2.default, { name: "togglePanes" })
     );
   }
-}
+} /* 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/>. */
 
 exports.default = PaneToggleButton;
 
 /***/ }),
 /* 1408 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -23398,17 +23244,17 @@ module.exports = Grip;
 "use strict";
 
 
 /* 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 React = __webpack_require__(0);
-const InlineSVG = __webpack_require__(346);
+const InlineSVG = __webpack_require__(1793);
 
 const svg = {
   "arrow": __webpack_require__(1152),
   "open-inspector": __webpack_require__(1153)
 };
 
 Svg.propTypes = {
   className: React.PropTypes.string
@@ -29580,17 +29426,17 @@ module.exports = connect(mapStateToProps
 
 "use strict";
 
 
 /* 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 { score } = __webpack_require__(161);
+const { score } = __webpack_require__(1788);
 
 function getTabs(state) {
   let tabs = state.tabs.get("tabs");
   let filterString = getFilterString(state);
 
   if (filterString === "") {
     return tabs;
   }
@@ -29985,17 +29831,17 @@ module.exports = Sidebar;
 /***/ }),
 /* 1494 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 const React = __webpack_require__(0);
-const { default: InlineSVG } = __webpack_require__(1769);
+const { default: InlineSVG } = __webpack_require__(1786);
 const { isDevelopment } = __webpack_require__(1355);
 
 const svg = {
   rocket: __webpack_require__(1126)
 };
 
 function Svg({ name, className, onClick, "aria-label": ariaLabel }) {
   className = `${name} ${className || ""}`;
@@ -33124,89 +32970,93 @@ exports.ShortcutsModal = ShortcutsModal;
 
 /* 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 React = __webpack_require__(0);
 const ReactDOM = __webpack_require__(4);
 const Draggable = React.createFactory(__webpack_require__(1537));
-const { DOM: dom, PropTypes } = React;
+const { Component } = React;
+const PropTypes = __webpack_require__(20);
+const dom = __webpack_require__(1759);
 
 __webpack_require__(1309);
 
 /**
  * This component represents a Splitter. The splitter supports vertical
  * as well as horizontal mode.
  */
-const SplitBox = React.createClass({
-  propTypes: {
-    // Custom class name. You can use more names separated by a space.
-    className: PropTypes.string,
-    // Initial size of controlled panel.
-    initialSize: PropTypes.any,
-    // Optional initial width of controlled panel.
-    initialWidth: PropTypes.number,
-    // Optional initial height of controlled panel.
-    initialHeight: PropTypes.number,
-    // Left/top panel
-    startPanel: PropTypes.any,
-    // Left/top panel collapse state.
-    startPanelCollapsed: PropTypes.bool,
-    // Min panel size.
-    minSize: PropTypes.any,
-    // Max panel size.
-    maxSize: PropTypes.any,
-    // Right/bottom panel
-    endPanel: PropTypes.any,
-    // Right/bottom panel collapse state.
-    endPanelCollapsed: PropTypes.bool,
-    // True if the right/bottom panel should be controlled.
-    endPanelControl: PropTypes.bool,
-    // Size of the splitter handle bar.
-    splitterSize: PropTypes.number,
-    // True if the splitter bar is vertical (default is vertical).
-    vert: PropTypes.bool,
-    // Optional style properties passed into the splitbox
-    style: PropTypes.object,
-    // Optional callback when splitbox resize stops
-    onResizeEnd: PropTypes.func
-  },
-
-  displayName: "SplitBox",
-
-  getDefaultProps() {
+class SplitBox extends Component {
+  static get propTypes() {
+    return {
+      // Custom class name. You can use more names separated by a space.
+      className: PropTypes.string,
+      // Initial size of controlled panel.
+      initialSize: PropTypes.any,
+      // Optional initial width of controlled panel.
+      initialWidth: PropTypes.number,
+      // Optional initial height of controlled panel.
+      initialHeight: PropTypes.number,
+      // Left/top panel
+      startPanel: PropTypes.any,
+      // Left/top panel collapse state.
+      startPanelCollapsed: PropTypes.bool,
+      // Min panel size.
+      minSize: PropTypes.any,
+      // Max panel size.
+      maxSize: PropTypes.any,
+      // Right/bottom panel
+      endPanel: PropTypes.any,
+      // Right/bottom panel collapse state.
+      endPanelCollapsed: PropTypes.bool,
+      // True if the right/bottom panel should be controlled.
+      endPanelControl: PropTypes.bool,
+      // Size of the splitter handle bar.
+      splitterSize: PropTypes.number,
+      // True if the splitter bar is vertical (default is vertical).
+      vert: PropTypes.bool,
+      // Optional style properties passed into the splitbox
+      style: PropTypes.object,
+      // Optional callback when splitbox resize stops
+      onResizeEnd: PropTypes.func
+    };
+  }
+
+  static get defaultProps() {
     return {
       splitterSize: 5,
       vert: true,
       endPanelControl: false,
       endPanelCollapsed: false,
       startPanelCollapsed: false
     };
-  },
-
-  /**
-   * The state stores the current orientation (vertical or horizontal)
-   * and the current size (width/height). All these values can change
-   * during the component's life time.
-   */
-  getInitialState() {
-    return {
-      vert: this.props.vert,
+  }
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      vert: props.vert,
       // We use integers for these properties
-      width: parseInt(this.props.initialWidth || this.props.initialSize),
-      height: parseInt(this.props.initialHeight || this.props.initialSize)
-    };
-  },
+      width: parseInt(props.initialWidth || props.initialSize, 10),
+      height: parseInt(props.initialHeight || props.initialSize, 10)
+    };
+
+    this.onStartMove = this.onStartMove.bind(this);
+    this.onStopMove = this.onStopMove.bind(this);
+    this.onMove = this.onMove.bind(this);
+    this.preparePanelStyles = this.preparePanelStyles.bind(this);
+  }
 
   componentWillReceiveProps(nextProps) {
     if (this.props.vert !== nextProps.vert) {
       this.setState({ vert: nextProps.vert });
     }
-  },
+  }
 
   // Dragging Events
 
   /**
    * Set 'resizing' cursor on entire document during splitter dragging.
    * This avoids cursor-flickering that happens when the mouse leaves
    * the splitter bar area (happens frequently).
    */
@@ -33216,29 +33066,29 @@ const SplitBox = React.createClass({
     let defaultCursor = doc.documentElement.style.cursor;
     doc.documentElement.style.cursor = this.state.vert ? "ew-resize" : "ns-resize";
 
     splitBox.classList.add("dragging");
 
     this.setState({
       defaultCursor: defaultCursor
     });
-  },
+  }
 
   onStopMove() {
     const splitBox = ReactDOM.findDOMNode(this);
     const doc = splitBox.ownerDocument;
     doc.documentElement.style.cursor = this.state.defaultCursor;
 
     splitBox.classList.remove("dragging");
 
     if (this.props.onResizeEnd) {
       this.props.onResizeEnd(this.state.vert ? this.state.width : this.state.height);
     }
-  },
+  }
 
   /**
    * Adjust size of the controlled panel. Depending on the current
    * orientation we either remember the width or height of
    * the splitter box.
    */
   onMove({ movementX, movementY }) {
     const node = ReactDOM.findDOMNode(this);
@@ -33262,17 +33112,17 @@ const SplitBox = React.createClass({
       this.setState((state, props) => ({
         width: state.width + movementX
       }));
     } else {
       this.setState((state, props) => ({
         height: state.height + movementY
       }));
     }
-  },
+  }
 
   // Rendering
   preparePanelStyles() {
     const vert = this.state.vert;
     const {
       minSize,
       maxSize,
       startPanelCollapsed,
@@ -33308,17 +33158,17 @@ const SplitBox = React.createClass({
       rightPanelStyle = {
         maxHeight: endPanelControl ? maxSize : null,
         minHeight: endPanelControl ? minSize : null,
         height: startPanelCollapsed ? maxSize : endHeight
       };
     }
 
     return { leftPanelStyle, rightPanelStyle };
-  },
+  }
 
   render() {
     const vert = this.state.vert;
     const {
       startPanelCollapsed,
       startPanel,
       endPanel,
       endPanelControl,
@@ -33354,74 +33204,83 @@ const SplitBox = React.createClass({
       onStart: this.onStartMove,
       onStop: this.onStopMove,
       onMove: this.onMove
     }), !endPanelCollapsed ? dom.div({
       className: endPanelControl ? "controlled" : "uncontrolled",
       style: rightPanelStyle
     }, endPanel) : null);
   }
-});
+}
 
 module.exports = SplitBox;
 
 /***/ }),
 /* 1537 */
 /***/ (function(module, exports, __webpack_require__) {
 
 /* 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,
+ * 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 React = __webpack_require__(0);
 const ReactDOM = __webpack_require__(4);
-const { DOM: dom, PropTypes } = React;
-
-const Draggable = React.createClass({
-  displayName: "Draggable",
-
-  propTypes: {
-    onMove: PropTypes.func.isRequired,
-    onStart: PropTypes.func,
-    onStop: PropTypes.func,
-    style: PropTypes.object,
-    className: PropTypes.string
-  },
+const { Component } = React;
+const PropTypes = __webpack_require__(20);
+const dom = __webpack_require__(1759);
+
+class Draggable extends Component {
+  static get propTypes() {
+    return {
+      onMove: PropTypes.func.isRequired,
+      onStart: PropTypes.func,
+      onStop: PropTypes.func,
+      style: PropTypes.object,
+      className: PropTypes.string
+    };
+  }
+
+  constructor(props) {
+    super(props);
+    this.startDragging = this.startDragging.bind(this);
+    this.onMove = this.onMove.bind(this);
+    this.onUp = this.onUp.bind(this);
+  }
 
   startDragging(ev) {
     ev.preventDefault();
     const doc = ReactDOM.findDOMNode(this).ownerDocument;
     doc.addEventListener("mousemove", this.onMove);
     doc.addEventListener("mouseup", this.onUp);
     this.props.onStart && this.props.onStart();
-  },
+  }
 
   onMove(ev) {
     ev.preventDefault();
     // We pass the whole event because we don't know which properties
     // the callee needs.
     this.props.onMove(ev);
-  },
+  }
 
   onUp(ev) {
     ev.preventDefault();
     const doc = ReactDOM.findDOMNode(this).ownerDocument;
     doc.removeEventListener("mousemove", this.onMove);
     doc.removeEventListener("mouseup", this.onUp);
     this.props.onStop && this.props.onStop();
-  },
+  }
 
   render() {
     return dom.div({
       style: this.props.style,
       className: this.props.className,
       onMouseDown: this.startDragging
     });
   }
-});
+}
 
 module.exports = Draggable;
 
 /***/ }),
 /* 1538 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -33805,18 +33664,24 @@ TextSearch.contextTypes = {
 
 /***/ }),
 /* 1540 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
+var _svgInlineReact = __webpack_require__(1786);
+
+var _svgInlineReact2 = _interopRequireDefault(_svgInlineReact);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
 const React = __webpack_require__(0);
-const InlineSVG = __webpack_require__(346);
+
 const { isDevelopment } = __webpack_require__(1355);
 
 const svg = {
   "angle-brackets": __webpack_require__(347),
   angular: __webpack_require__(247),
   arrow: __webpack_require__(348),
   backbone: __webpack_require__(997),
   blackBox: __webpack_require__(349),
@@ -33892,17 +33757,17 @@ function Svg({ name, className, onClick,
 
   const props = {
     className,
     onClick,
     ["aria-label"]: ariaLabel,
     src: svg[name]
   };
 
-  return React.createElement(InlineSVG, props);
+  return React.createElement(_svgInlineReact2.default, props);
 }
 
 Svg.displayName = "Svg";
 
 module.exports = Svg;
 
 /***/ }),
 /* 1541 */
@@ -35511,16 +35376,18 @@ var _classnames2 = _interopRequireDefaul
 var _devtoolsLaunchpad = __webpack_require__(1362);
 
 var _source = __webpack_require__(1356);
 
 var _devtoolsConfig = __webpack_require__(1355);
 
 var _devtoolsSourceEditor = __webpack_require__(1386);
 
+var _prefs = __webpack_require__(226);
+
 var _selectors = __webpack_require__(1352);
 
 var _redux = __webpack_require__(3);
 
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
@@ -35578,25 +35445,23 @@ var _ui = __webpack_require__(1439);
 
 __webpack_require__(1332);
 
 __webpack_require__(1333);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 // Redux actions
-/* 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 cssVars = {
   searchbarHeight: "var(--editor-searchbar-height)",
   secondSearchbarHeight: "var(--editor-second-searchbar-height)",
   footerHeight: "var(--editor-footer-height)"
-};
+}; /* 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/>. */
 
 class Editor extends _react.PureComponent {
 
   constructor() {
     super();
 
     this.onToggleBreakpoint = (key, e) => {
       e.preventDefault();
@@ -35801,17 +35666,17 @@ class Editor extends _react.PureComponen
     shortcuts.off(searchAgainKey);
   }
 
   componentWillUpdate(nextProps) {
     this.setText(nextProps);
     this.setSize(nextProps);
   }
 
-  componentDidUpdate(prevProps) {
+  componentDidUpdate(prevProps, prevState) {
     // This is in `componentDidUpdate` so helper functions can expect
     // `this.props` to be the current props. This lifecycle method is
     // responsible for updating the editor annotations.
     const { selectedLocation, selectedSource } = this.props;
 
     // If the location is different and a new line is requested,
     // update the pending jump line. Note that if jumping to a line in
     // a source where the text hasn't been loaded yet, we will set the
@@ -35826,16 +35691,24 @@ class Editor extends _react.PureComponen
     }
 
     // Only update and jump around in real source texts. This will
     // keep the jump state around until the real source text is
     // loaded.
     if (selectedSource && (0, _source.isLoaded)(selectedSource.toJS())) {
       this.highlightLine();
     }
+
+    // NOTE: when devtools are opened, the editor is not set when
+    // the source loads so we need to wait until the editor is
+    // set to update the text and size.
+    if (!prevState.editor && this.state.editor) {
+      this.setText(this.props);
+      this.setSize(this.props);
+    }
   }
 
   getCurrentLine() {
     const { codeMirror } = this.state.editor;
     const { selectedSource } = this.props;
     const line = (0, _editor.getCursorLine)(codeMirror);
 
     return (0, _editor.toSourceLine)(selectedSource.get("id"), line);
@@ -36004,30 +35877,31 @@ class Editor extends _react.PureComponen
 
   renderItems() {
     const { selectedSource, horizontal } = this.props;
     const { editor } = this.state;
 
     if (!editor || !selectedSource || !(0, _source.isLoaded)(selectedSource.toJS())) {
       return null;
     }
+
     return _react2.default.createElement(
       "div",
       null,
       _react2.default.createElement(_DebugLine2.default, { editor: editor }),
       _react2.default.createElement(_EmptyLines2.default, { editor: editor }),
       _react2.default.createElement(_Breakpoints2.default, { editor: editor }),
-      _react2.default.createElement(_CallSites2.default, { editor: editor }),
       _react2.default.createElement(_Preview2.default, { editor: editor }),
       ";",
       _react2.default.createElement(_Footer2.default, { editor: editor, horizontal: horizontal }),
       _react2.default.createElement(_HighlightLines2.default, { editor: editor }),
       _react2.default.createElement(_EditorMenu2.default, { editor: editor }),
       _react2.default.createElement(_GutterMenu2.default, { editor: editor }),
       _react2.default.createElement(_ConditionalPanel2.default, { editor: editor }),
+      _prefs.features.columnBreakpoints ? _react2.default.createElement(_CallSites2.default, { editor: editor }) : null,
       this.renderHitCounts()
     );
   }
 
   renderSearchBar() {
     const { editor } = this.state;
 
     if (!editor) {
@@ -39998,18 +39872,16 @@ var _extends = Object.assign || function
                                                                                                                                                                                                                                                                    * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 var _react = __webpack_require__(0);
 
 var _react2 = _interopRequireDefault(_react);
 
 var _reactRedux = __webpack_require__(1189);
 
-var _prefs = __webpack_require__(226);
-
 var _lodash = __webpack_require__(2);
 
 var _CallSite = __webpack_require__(1592);
 
 var _CallSite2 = _interopRequireDefault(_CallSite);
 
 var _selectors = __webpack_require__(1352);
 
@@ -40038,32 +39910,28 @@ class CallSites extends _react.Component
       showCallSites: false
     };
   }
 
   componentDidMount() {
     const { editor } = this.props;
     const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
 
-    if (_prefs.features.columnBreakpoints) {
-      codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e));
-      document.body.addEventListener("keydown", this.onKeyDown);
-      document.body.addEventListener("keyup", this.onKeyUp);
-    }
-  }
-
-  componentDidUnMount() {
+    codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e));
+    document.body.addEventListener("keydown", this.onKeyDown);
+    document.body.addEventListener("keyup", this.onKeyUp);
+  }
+
+  componentWillUnmount() {
     const { editor } = this.props;
     const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
 
-    if (_prefs.features.columnBreakpoints) {
-      codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e));
-      document.body.removeEventListener("keydown", e => this.onKeyDown);
-      document.body.removeEventListener("keyup", this.onKeyUp);
-    }
+    codeMirrorWrapper.removeEventListener("click", e => this.onTokenClick(e));
+    document.body.removeEventListener("keydown", this.onKeyDown);
+    document.body.removeEventListener("keyup", this.onKeyUp);
   }
 
   onKeyUp(e) {
     if (e.key === "Alt") {
       e.preventDefault();
       this.setState({ showCallSites: false });
     }
   }
@@ -42754,20 +42622,16 @@ exports.default = Accordion;
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* 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/>. */
-
 var _propTypes = __webpack_require__(20);
 
 var _propTypes2 = _interopRequireDefault(_propTypes);
 
 var _react = __webpack_require__(0);
 
 var _react2 = _interopRequireDefault(_react);
 
@@ -42784,22 +42648,30 @@ var _prefs = __webpack_require__(226);
 var _selectors = __webpack_require__(1352);
 
 var _text = __webpack_require__(1387);
 
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
+var _CommandBarButton = __webpack_require__(1787);
+
+var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton);
+
 __webpack_require__(1295);
 
 var _devtoolsModules = __webpack_require__(1376);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
+/* 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 { appinfo } = _devtoolsModules.Services;
 
 const isMacOS = appinfo.OS === "Darwin";
 
 const COMMANDS = ["resume", "stepOver", "stepIn", "stepOut"];
 
 const KEYS = {
   WINNT: {
@@ -42841,27 +42713,26 @@ function formatKey(action) {
     const winKey = getKeyForOS("WINNT", `${action}Display`) || getKeyForOS("WINNT", action);
     // display both Windows type and Mac specific keys
     return (0, _text.formatKeyShortcut)([key, winKey].join(" "));
   }
   return (0, _text.formatKeyShortcut)(key);
 }
 
 function debugBtn(onClick, type, className, tooltip, disabled = false, ariaPressed = false) {
-  const props = {
-    onClick,
-    key: type,
-    title: tooltip,
-    disabled,
-    "aria-pressed": ariaPressed
-  };
-
   return _react2.default.createElement(
-    "button",
-    _extends({ className: (0, _classnames2.default)(type, className) }, props),
+    _CommandBarButton2.default,
+    {
+      className: (0, _classnames2.default)(type, className),
+      disabled: disabled,
+      key: type,
+      onClick: onClick,
+      pressed: ariaPressed,
+      title: tooltip
+    },
     _react2.default.createElement("img", { className: type })
   );
 }
 
 class CommandBar extends _react.Component {
   componentWillUnmount() {
     const shortcuts = this.context.shortcuts;
     COMMANDS.forEach(action => shortcuts.off(getKey(action)));
@@ -45093,17 +44964,24 @@ class QuickOpenModal extends _react.Comp
           this.selectResultItem(e, results[selectedIndex]);
         }
         return this.closeModal();
       } else if (e.key === "Tab") {
         return this.closeModal();
       }
     };
 
-    this.resultCount = () => this.state.results ? this.state.results.length : 0;
+    this.resultCount = () => {
+      const results = this.state.results;
+
+      if (results && results.length) {
+        return results.length;
+      }
+      return 0;
+    };
 
     this.isSymbolSearch = () => ["functions", "variables"].includes(this.props.searchType);
 
     this.state = {
       results: null,
       selectedIndex: 0
     };
   }
@@ -47142,204 +47020,18 @@ module.exports = KeyShortcuts;
  *
  * Based on nsIMarkupDocumentViewer.fullZoom API
  * https://developer.mozilla.org/en-US/Firefox/Releases/3/Full_page_zoom
  */
 
 exports.register = function (window) {};
 
 /***/ }),
-/* 1769 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-Object.defineProperty(exports, "__esModule", {
-    value: true
-});
-
-var _extends = Object.assign || function (target) {
-    for (var i = 1; i < arguments.length; i++) {
-        var source = arguments[i];for (var key in source) {
-            if (Object.prototype.hasOwnProperty.call(source, key)) {
-                target[key] = source[key];
-            }
-        }
-    }return target;
-};
-
-var _createClass = function () {
-    function defineProperties(target, props) {
-        for (var i = 0; i < props.length; i++) {
-            var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
-        }
-    }return function (Constructor, protoProps, staticProps) {
-        if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
-    };
-}();
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-var _propTypes = __webpack_require__(20);
-
-var _util = __webpack_require__(1770);
-
-function _interopRequireDefault(obj) {
-    return obj && obj.__esModule ? obj : { default: obj };
-}
-
-function _objectWithoutProperties(obj, keys) {
-    var target = {};for (var i in obj) {
-        if (keys.indexOf(i) >= 0) continue;if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;target[i] = obj[i];
-    }return target;
-}
-
-function _classCallCheck(instance, Constructor) {
-    if (!(instance instanceof Constructor)) {
-        throw new TypeError("Cannot call a class as a function");
-    }
-}
-
-function _possibleConstructorReturn(self, call) {
-    if (!self) {
-        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
-    }return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self;
-}
-
-function _inherits(subClass, superClass) {
-    if (typeof superClass !== "function" && superClass !== null) {
-        throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof(superClass)));
-    }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
-}
-
-var process = process || { env: {} };
-
-var InlineSVG = function (_React$Component) {
-    _inherits(InlineSVG, _React$Component);
-
-    function InlineSVG() {
-        _classCallCheck(this, InlineSVG);
-
-        return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments));
-    }
-
-    _createClass(InlineSVG, [{
-        key: 'componentWillReceiveProps',
-        value: function componentWillReceiveProps(_ref) {
-            var children = _ref.children;
-
-            if ("production" !== process.env.NODE_ENV && children != null) {
-                console.info('<InlineSVG />: `children` prop will be ignored.');
-            }
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var Element = void 0,
-                __html = void 0,
-                svgProps = void 0;
-
-            var _props = this.props,
-                element = _props.element,
-                raw = _props.raw,
-                src = _props.src,
-                otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
-
-            if (raw === true) {
-                Element = 'svg';
-                svgProps = (0, _util.extractSVGProps)(src);
-                __html = (0, _util.getSVGFromSource)(src).innerHTML;
-            }
-            __html = __html || src;
-            Element = Element || element;
-            svgProps = svgProps || {};
-
-            return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
-                dangerouslySetInnerHTML: { __html: __html } }));
-        }
-    }]);
-
-    return InlineSVG;
-}(_react2.default.Component);
-
-exports.default = InlineSVG;
-
-InlineSVG.defaultProps = {
-    element: 'i',
-    raw: false,
-    src: ''
-};
-
-InlineSVG.propTypes = {
-    src: _propTypes.string.isRequired,
-    element: _propTypes.string,
-    raw: _propTypes.bool
-};
-
-/***/ }),
-/* 1770 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-    value: true
-});
-exports.convertReactSVGDOMProperty = convertReactSVGDOMProperty;
-exports.startsWith = startsWith;
-exports.serializeAttrs = serializeAttrs;
-exports.getSVGFromSource = getSVGFromSource;
-exports.extractSVGProps = extractSVGProps;
-// Transform DOM prop/attr names applicable to `<svg>` element but react-limited
-
-function convertReactSVGDOMProperty(str) {
-    return str.replace(/[-|:]([a-z])/g, function (g) {
-        return g[1].toUpperCase();
-    });
-}
-
-function startsWith(str, substring) {
-    return str.indexOf(substring) === 0;
-}
-
-var DataPropPrefix = 'data-';
-// Serialize `Attr` objects in `NamedNodeMap`
-function serializeAttrs(map) {
-    var ret = {};
-    for (var prop, i = 0; i < map.length; i++) {
-        var key = map[i].name;
-        if (!startsWith(key, DataPropPrefix)) {
-            prop = convertReactSVGDOMProperty(key);
-        }
-        ret[prop] = map[i].value;
-    }
-    return ret;
-}
-
-function getSVGFromSource(src) {
-    var svgContainer = document.createElement('div');
-    svgContainer.innerHTML = src;
-    var svg = svgContainer.firstElementChild;
-    svg.remove(); // deref from parent element
-    return svg;
-}
-
-// get <svg /> element props
-function extractSVGProps(src) {
-    var map = getSVGFromSource(src).attributes;
-    return map.length > 0 ? serializeAttrs(map) : null;
-}
-
-/***/ }),
+/* 1769 */,
+/* 1770 */,
 /* 1771 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -48113,11 +47805,1331 @@ function getScope(scope, selectedFrame, 
       path: key,
       contents: { value }
     };
   }
 
   return null;
 }
 
+/***/ }),
+/* 1783 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+(function () {
+  var AcronymResult, computeScore, emptyAcronymResult, isAcronymFullWord, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_size, wm;
+
+  wm = 150;
+
+  pos_bonus = 20;
+
+  tau_size = 85;
+
+  miss_coeff = 0.75;
+
+  exports.score = function (string, query, options) {
+    var allowErrors, preparedQuery, score, string_lw;
+    preparedQuery = options.preparedQuery, allowErrors = options.allowErrors;
+    if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) {
+      return 0;
+    }
+    string_lw = string.toLowerCase();
+    score = computeScore(string, string_lw, preparedQuery);
+    return Math.ceil(score);
+  };
+
+  exports.isMatch = isMatch = function (subject, query_lw, query_up) {
+    var i, j, m, n, qj_lw, qj_up, si;
+    m = subject.length;
+    n = query_lw.length;
+    if (!m || n > m) {
+      return false;
+    }
+    i = -1;
+    j = -1;
+    while (++j < n) {
+      qj_lw = query_lw.charCodeAt(j);
+      qj_up = query_up.charCodeAt(j);
+      while (++i < m) {
+        si = subject.charCodeAt(i);
+        if (si === qj_lw || si === qj_up) {
+          break;
+        }
+      }
+      if (i === m) {
+        return false;
+      }
+    }
+    return true;
+  };
+
+  exports.computeScore = computeScore = function (subject, subject_lw, preparedQuery) {
+    var acro, acro_score, align, csc_diag, csc_invalid, csc_row, csc_score, i, j, m, miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz;
+    query = preparedQuery.query;
+    query_lw = preparedQuery.query_lw;
+    m = subject.length;
+    n = query.length;
+    acro = scoreAcronyms(subject, subject_lw, query, query_lw);
+    acro_score = acro.score;
+    if (acro.count === n) {
+      return scoreExact(n, m, acro_score, acro.pos);
+    }
+    pos = subject_lw.indexOf(query_lw);
+    if (pos > -1) {
+      return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m);
+    }
+    score_row = new Array(n);
+    csc_row = new Array(n);
+    sz = scoreSize(n, m);
+    miss_budget = Math.ceil(miss_coeff * n) + 5;
+    miss_left = miss_budget;
+    j = -1;
+    while (++j < n) {
+      score_row[j] = 0;
+      csc_row[j] = 0;
+    }
+    i = subject_lw.indexOf(query_lw[0]);
+    if (i > -1) {
+      i--;
+    }
+    mm = subject_lw.lastIndexOf(query_lw[n - 1], m);
+    if (mm > i) {
+      m = mm + 1;
+    }
+    csc_invalid = true;
+    while (++i < m) {
+      si_lw = subject_lw[i];
+      if (preparedQuery.charCodes[si_lw.charCodeAt(0)] == null) {
+        if (csc_invalid !== true) {
+          j = -1;
+          while (++j < n) {
+            csc_row[j] = 0;
+          }
+          csc_invalid = true;
+        }
+        continue;
+      }
+      score = 0;
+      score_diag = 0;
+      csc_diag = 0;
+      record_miss = true;
+      csc_invalid = false;
+      j = -1;
+      while (++j < n) {
+        score_up = score_row[j];
+        if (score_up > score) {
+          score = score_up;
+        }
+        csc_score = 0;
+        if (query_lw[j] === si_lw) {
+          start = isWordStart(i, subject, subject_lw);
+          csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
+          align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score);
+          if (align > score) {
+            score = align;
+            miss_left = miss_budget;
+          } else {
+            if (record_miss && --miss_left <= 0) {
+              return score_row[n - 1] * sz;
+            }
+            record_miss = false;
+          }
+        }
+        score_diag = score_up;
+        csc_diag = csc_row[j];
+        csc_row[j] = csc_score;
+        score_row[j] = score;
+      }
+    }
+    score = score_row[n - 1];
+    return score * sz;
+  };
+
+  exports.isWordStart = isWordStart = function (pos, subject, subject_lw) {
+    var curr_s, prev_s;
+    if (pos === 0) {
+      return true;
+    }
+    curr_s = subject[pos];
+    prev_s = subject[pos - 1];
+    return isSeparator(prev_s) || curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1];
+  };
+
+  exports.isWordEnd = isWordEnd = function (pos, subject, subject_lw, len) {
+    var curr_s, next_s;
+    if (pos === len - 1) {
+      return true;
+    }
+    curr_s = subject[pos];
+    next_s = subject[pos + 1];
+    return isSeparator(next_s) || curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1];
+  };
+
+  isSeparator = function (c) {
+    return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\';
+  };
+
+  scorePosition = function (pos) {
+    var sc;
+    if (pos < pos_bonus) {
+      sc = pos_bonus - pos;
+      return 100 + sc * sc;
+    } else {
+      return Math.max(100 + pos_bonus - pos, 0);
+    }
+  };
+
+  exports.scoreSize = scoreSize = function (n, m) {
+    return tau_size / (tau_size + Math.abs(m - n));
+  };
+
+  scoreExact = function (n, m, quality, pos) {
+    return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m);
+  };
+
+  exports.scorePattern = scorePattern = function (count, len, sameCase, start, end) {
+    var bonus, sz;
+    sz = count;
+    bonus = 6;
+    if (sameCase === count) {
+      bonus += 2;
+    }
+    if (start) {
+      bonus += 3;
+    }
+    if (end) {
+      bonus += 1;
+    }
+    if (count === len) {
+      if (start) {
+        if (sameCase === len) {
+          sz += 2;
+        } else {
+          sz += 1;
+        }
+      }
+      if (end) {
+        bonus += 1;
+      }
+    }
+    return sameCase + sz * (sz + bonus);
+  };
+
+  exports.scoreCharacter = scoreCharacter = function (i, j, start, acro_score, csc_score) {
+    var posBonus;
+    posBonus = scorePosition(i);
+    if (start) {
+      return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10);
+    }
+    return posBonus + wm * csc_score;
+  };
+
+  exports.scoreConsecutives = scoreConsecutives = function (subject, subject_lw, query, query_lw, i, j, startOfWord) {
+    var k, m, mi, n, nj, sameCase, sz;
+    m = subject.length;
+    n = query.length;
+    mi = m - i;
+    nj = n - j;
+    k = mi < nj ? mi : nj;
+    sameCase = 0;
+    sz = 0;
+    if (query[j] === subject[i]) {
+      sameCase++;
+    }
+    while (++sz < k && query_lw[++j] === subject_lw[++i]) {
+      if (query[j] === subject[i]) {
+        sameCase++;
+      }
+    }
+    if (sz === 1) {
+      return 1 + 2 * sameCase;
+    }
+    return scorePattern(sz, n, sameCase, startOfWord, isWordEnd(i, subject, subject_lw, m));
+  };
+
+  exports.scoreExactMatch = scoreExactMatch = function (subject, subject_lw, query, query_lw, pos, n, m) {
+    var end, i, pos2, sameCase, start;
+    start = isWordStart(pos, subject, subject_lw);
+    if (!start) {
+      pos2 = subject_lw.indexOf(query_lw, pos + 1);
+      if (pos2 > -1) {
+        start = isWordStart(pos2, subject, subject_lw);
+        if (start) {
+          pos = pos2;
+        }
+      }
+    }
+    i = -1;
+    sameCase = 0;
+    while (++i < n) {
+      if (query[pos + i] === subject[i]) {
+        sameCase++;
+      }
+    }
+    end = isWordEnd(pos + n - 1, subject, subject_lw, m);
+    return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos);
+  };
+
+  AcronymResult = function () {
+    function AcronymResult(score, pos, count) {
+      this.score = score;
+      this.pos = pos;
+      this.count = count;
+    }
+
+    return AcronymResult;
+  }();
+
+  emptyAcronymResult = new AcronymResult(0, 0.1, 0);
+
+  exports.scoreAcronyms = scoreAcronyms = function (subject, subject_lw, query, query_lw) {
+    var count, fullWord, i, j, m, n, qj_lw, sameCase, score, sepCount, sumPos;
+    m = subject.length;
+    n = query.length;
+    if (!(m > 1 && n > 1)) {
+      return emptyAcronymResult;
+    }
+    count = 0;
+    sepCount = 0;
+    sumPos = 0;
+    sameCase = 0;
+    i = -1;
+    j = -1;
+    while (++j < n) {
+      qj_lw = query_lw[j];
+      if (isSeparator(qj_lw)) {
+        i = subject_lw.indexOf(qj_lw, i + 1);
+        if (i > -1) {
+          sepCount++;
+          continue;
+        } else {
+          break;
+        }
+      }
+      while (++i < m) {
+        if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) {
+          if (query[j] === subject[i]) {
+            sameCase++;
+          }
+          sumPos += i;
+          count++;
+          break;
+        }
+      }
+      if (i === m) {
+        break;
+      }
+    }
+    if (count < 2) {
+      return emptyAcronymResult;
+    }
+    fullWord = count === n ? isAcronymFullWord(subject, subject_lw, query, count) : false;
+    score = scorePattern(count, n, sameCase, true, fullWord);
+    return new AcronymResult(score, sumPos / count, count + sepCount);
+  };
+
+  isAcronymFullWord = function (subject, subject_lw, query, nbAcronymInQuery) {
+    var count, i, m, n;
+    m = subject.length;
+    n = query.length;
+    count = 0;
+    if (m > 12 * n) {
+      return false;
+    }
+    i = -1;
+    while (++i < m) {
+      if (isWordStart(i, subject, subject_lw) && ++count > nbAcronymInQuery) {
+        return false;
+      }
+    }
+    return true;
+  };
+}).call(undefined);
+
+/***/ }),
+/* 1784 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+(function () {
+  var computeScore, countDir, file_coeff, getExtension, getExtensionScore, isMatch, scorePath, scoreSize, tau_depth, _ref;
+
+  _ref = __webpack_require__(1783), isMatch = _ref.isMatch, computeScore = _ref.computeScore, scoreSize = _ref.scoreSize;
+
+  tau_depth = 13;
+
+  file_coeff = 1.2;
+
+  exports.score = function (string, query, options) {
+    var allowErrors, preparedQuery, score, string_lw;
+    preparedQuery = options.preparedQuery, allowErrors = options.allowErrors;
+    if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) {
+      return 0;
+    }
+    string_lw = string.toLowerCase();
+    score = computeScore(string, string_lw, preparedQuery);
+    score = scorePath(string, string_lw, score, options);
+    return Math.ceil(score);
+  };
+
+  scorePath = function (subject, subject_lw, fullPathScore, options) {
+    var alpha, basePathScore, basePos, depth, end, extAdjust, fileLength, pathSeparator, preparedQuery, useExtensionBonus;
+    if (fullPathScore === 0) {
+      return 0;
+    }
+    preparedQuery = options.preparedQuery, useExtensionBonus = options.useExtensionBonus, pathSeparator = options.pathSeparator;
+    end = subject.length - 1;
+    while (subject[end] === pathSeparator) {
+      end--;
+    }
+    basePos = subject.lastIndexOf(pathSeparator, end);
+    fileLength = end - basePos;
+    extAdjust = 1.0;
+    if (useExtensionBonus) {
+      extAdjust += getExtensionScore(subject_lw, preparedQuery.ext, basePos, end, 2);
+      fullPathScore *= extAdjust;
+    }
+    if (basePos === -1) {
+      return fullPathScore;
+    }
+    depth = preparedQuery.depth;
+    while (basePos > -1 && depth-- > 0) {
+      basePos = subject.lastIndexOf(pathSeparator, basePos - 1);
+    }
+    basePathScore = basePos === -1 ? fullPathScore : extAdjust * computeScore(subject.slice(basePos + 1, end + 1), subject_lw.slice(basePos + 1, end + 1), preparedQuery);
+    alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1, pathSeparator));
+    return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * fileLength);
+  };
+
+  exports.countDir = countDir = function (path, end, pathSeparator) {
+    var count, i;
+    if (end < 1) {
+      return 0;
+    }
+    count = 0;
+    i = -1;
+    while (++i < end && path[i] === pathSeparator) {
+      continue;
+    }
+    while (++i < end) {
+      if (path[i] === pathSeparator) {
+        count++;
+        while (++i < end && path[i] === pathSeparator) {
+          continue;
+        }
+      }
+    }
+    return count;
+  };
+
+  exports.getExtension = getExtension = function (str) {
+    var pos;
+    pos = str.lastIndexOf(".");
+    if (pos < 0) {
+      return "";
+    } else {
+      return str.substr(pos + 1);
+    }
+  };
+
+  getExtensionScore = function (candidate, ext, startPos, endPos, maxDepth) {
+    var m, matched, n, pos;
+    if (!ext.length) {
+      return 0;
+    }
+    pos = candidate.lastIndexOf(".", endPos);
+    if (!(pos > startPos)) {
+      return 0;
+    }
+    n = ext.length;
+    m = endPos - pos;
+    if (m < n) {
+      n = m;
+      m = ext.length;
+    }
+    pos++;
+    matched = -1;
+    while (++matched < n) {
+      if (candidate[pos + matched] !== ext[matched]) {
+        break;
+      }
+    }
+    if (matched === 0 && maxDepth > 0) {
+      return 0.9 * getExtensionScore(candidate, ext, startPos, pos - 2, maxDepth - 1);
+    }
+    return matched / m;
+  };
+}).call(undefined);
+
+/***/ }),
+/* 1785 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+(function () {
+  var Query, coreChars, countDir, getCharCodes, getExtension, opt_char_re, truncatedUpperCase, _ref;
+
+  _ref = __webpack_require__(1784), countDir = _ref.countDir, getExtension = _ref.getExtension;
+
+  module.exports = Query = function () {
+    function Query(query, _arg) {
+      var optCharRegEx, pathSeparator, _ref1;
+      _ref1 = _arg != null ? _arg : {}, optCharRegEx = _ref1.optCharRegEx, pathSeparator = _ref1.pathSeparator;
+      if (!(query && query.length)) {
+        return null;
+      }
+      this.query = query;
+      this.query_lw = query.toLowerCase();
+      this.core = coreChars(query, optCharRegEx);
+      this.core_lw = this.core.toLowerCase();
+      this.core_up = truncatedUpperCase(this.core);
+      this.depth = countDir(query, query.length, pathSeparator);
+      this.ext = getExtension(this.query_lw);
+      this.charCodes = getCharCodes(this.query_lw);
+    }
+
+    return Query;
+  }();
+
+  opt_char_re = /[ _\-:\/\\]/g;
+
+  coreChars = function (query, optCharRegEx) {
+    if (optCharRegEx == null) {
+      optCharRegEx = opt_char_re;
+    }
+    return query.replace(optCharRegEx, '');
+  };
+
+  truncatedUpperCase = function (str) {
+    var char, upper, _i, _len;
+    upper = "";
+    for (_i = 0, _len = str.length; _i < _len; _i++) {
+      char = str[_i];
+      upper += char.toUpperCase()[0];
+    }
+    return upper;
+  };
+
+  getCharCodes = function (str) {
+    var charCodes, i, len;
+    len = str.length;
+    i = -1;
+    charCodes = [];
+    while (++i < len) {
+      charCodes[str.charCodeAt(i)] = true;
+    }
+    return charCodes;
+  };
+}).call(undefined);
+
+/***/ }),
+/* 1786 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _react = __webpack_require__(0);
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = __webpack_require__(20);
+
+var _util = __webpack_require__(1791);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var process = process || { env: {} };
+
+var InlineSVG = function (_React$Component) {
+    _inherits(InlineSVG, _React$Component);
+
+    function InlineSVG() {
+        _classCallCheck(this, InlineSVG);
+
+        return _possibleConstructorReturn(this, (InlineSVG.__proto__ || Object.getPrototypeOf(InlineSVG)).apply(this, arguments));
+    }
+
+    _createClass(InlineSVG, [{
+        key: 'componentWillReceiveProps',
+        value: function componentWillReceiveProps(_ref) {
+            var children = _ref.children;
+
+            if ("production" !== process.env.NODE_ENV && children != null) {
+                console.info('<InlineSVG />: `children` prop will be ignored.');
+            }
+        }
+    }, {
+        key: 'render',
+        value: function render() {
+            var Element = void 0,
+                __html = void 0,
+                svgProps = void 0;
+
+            var _props = this.props,
+                element = _props.element,
+                raw = _props.raw,
+                src = _props.src,
+                otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
+
+            if (raw === true) {
+                Element = 'svg';
+                svgProps = (0, _util.extractSVGProps)(src);
+                __html = (0, _util.getSVGFromSource)(src).innerHTML;
+            }
+            __html = __html || src;
+            Element = Element || element;
+            svgProps = svgProps || {};
+
+            return _react2.default.createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
+                dangerouslySetInnerHTML: { __html: __html } }));
+        }
+    }]);
+
+    return InlineSVG;
+}(_react2.default.Component);
+
+exports.default = InlineSVG;
+
+
+InlineSVG.defaultProps = {
+    element: 'i',
+    raw: false,
+    src: ''
+};
+
+InlineSVG.propTypes = {
+    src: _propTypes.string.isRequired,
+    element: _propTypes.string,
+    raw: _propTypes.bool
+};
+
+/***/ }),
+/* 1787 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _classnames = __webpack_require__(175);
+
+var _classnames2 = _interopRequireDefault(_classnames);
+
+var _react = __webpack_require__(0);
+
+var _react2 = _interopRequireDefault(_react);
+
+__webpack_require__(1792);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+const CommandBarButton = props => {
+  const { children, className, pressed = false } = props,
+        rest = _objectWithoutProperties(props, ["children", "className", "pressed"]);
+
+  return _react2.default.createElement(
+    "button",
+    _extends({
+      "aria-pressed": pressed,
+      className: (0, _classnames2.default)("command-bar-button", className)
+    }, rest),
+    children
+  );
+};
+
+exports.default = CommandBarButton;
+
+/***/ }),
+/* 1788 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(process) {
+
+(function () {
+  var Query, defaultPathSeparator, filter, matcher, parseOptions, pathScorer, preparedQueryCache, scorer;
+
+  filter = __webpack_require__(1789);
+
+  matcher = __webpack_require__(1790);
+
+  scorer = __webpack_require__(1783);
+
+  pathScorer = __webpack_require__(1784);
+
+  Query = __webpack_require__(1785);
+
+  preparedQueryCache = null;
+
+  defaultPathSeparator = (typeof process !== "undefined" && process !== null ? process.platform : void 0) === "win32" ? '\\' : '/';
+
+  module.exports = {
+    filter: function (candidates, query, options) {
+      if (options == null) {
+        options = {};
+      }
+      if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) {
+        return [];
+      }
+      options = parseOptions(options, query);
+      return filter(candidates, query, options);
+    },
+    score: function (string, query, options) {
+      if (options == null) {
+        options = {};
+      }
+      if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) {
+        return 0;
+      }
+      options = parseOptions(options, query);
+      if (options.usePathScoring) {
+        return pathScorer.score(string, query, options);
+      } else {
+        return scorer.score(string, query, options);
+      }
+    },
+    match: function (string, query, options) {
+      var _i, _ref, _results;
+      if (options == null) {
+        options = {};
+      }
+      if (!string) {
+        return [];
+      }
+      if (!query) {
+        return [];
+      }
+      if (string === query) {
+        return function () {
+          _results = [];
+          for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--) {
+            _results.push(_i);
+          }
+          return _results;
+        }.apply(this);
+      }
+      options = parseOptions(options, query);
+      return matcher.match(string, query, options);
+    },
+    wrap: function (string, query, options) {
+      if (options == null) {
+        options = {};
+      }
+      if (!string) {
+        return [];
+      }
+      if (!query) {
+        return [];
+      }
+      options = parseOptions(options, query);
+      return matcher.wrap(string, query, options);
+    },
+    prepareQuery: function (query, options) {
+      if (options == null) {
+        options = {};
+      }
+      options = parseOptions(options, query);
+      return options.preparedQuery;
+    }
+  };
+
+  parseOptions = function (options, query) {
+    if (options.allowErrors == null) {
+      options.allowErrors = false;
+    }
+    if (options.usePathScoring == null) {
+      options.usePathScoring = true;
+    }
+    if (options.useExtensionBonus == null) {
+      options.useExtensionBonus = false;
+    }
+    if (options.pathSeparator == null) {
+      options.pathSeparator = defaultPathSeparator;
+    }
+    if (options.optCharRegEx == null) {
+      options.optCharRegEx = null;
+    }
+    if (options.wrap == null) {
+      options.wrap = null;
+    }
+    if (options.preparedQuery == null) {
+      options.preparedQuery = preparedQueryCache && preparedQueryCache.query === query ? preparedQueryCache : preparedQueryCache = new Query(query, options);
+    }
+    return options;
+  };
+}).call(undefined);
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(120)))
+
+/***/ }),
+/* 1789 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+(function () {
+  var Query, pathScorer, pluckCandidates, scorer, sortCandidates;
+
+  scorer = __webpack_require__(1783);
+
+  pathScorer = __webpack_require__(1784);
+
+  Query = __webpack_require__(1785);
+
+  pluckCandidates = function (a) {
+    return a.candidate;
+  };
+
+  sortCandidates = function (a, b) {
+    return b.score - a.score;
+  };
+
+  module.exports = function (candidates, query, options) {
+    var bKey, candidate, key, maxInners, maxResults, score, scoreProvider, scoredCandidates, spotLeft, string, usePathScoring, _i, _len;
+    scoredCandidates = [];
+    key = options.key, maxResults = options.maxResults, maxInners = options.maxInners, usePathScoring = options.usePathScoring;
+    spotLeft = maxInners != null && maxInners > 0 ? maxInners : candidates.length + 1;
+    bKey = key != null;
+    scoreProvider = usePathScoring ? pathScorer : scorer;
+    for (_i = 0, _len = candidates.length; _i < _len; _i++) {
+      candidate = candidates[_i];
+      string = bKey ? candidate[key] : candidate;
+      if (!string) {
+        continue;
+      }
+      score = scoreProvider.score(string, query, options);
+      if (score > 0) {
+        scoredCandidates.push({
+          candidate: candidate,
+          score: score
+        });
+        if (! --spotLeft) {
+          break;
+        }
+      }
+    }
+    scoredCandidates.sort(sortCandidates);
+    candidates = scoredCandidates.map(pluckCandidates);
+    if (maxResults != null) {
+      candidates = candidates.slice(0, maxResults);
+    }
+    return candidates;
+  };
+}).call(undefined);
+
+/***/ }),
+/* 1790 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+(function () {
+  var basenameMatch, computeMatch, isMatch, isWordStart, match, mergeMatches, scoreAcronyms, scoreCharacter, scoreConsecutives, _ref;
+
+  _ref = __webpack_require__(1783), isMatch = _ref.isMatch, isWordStart = _ref.isWordStart, scoreConsecutives = _ref.scoreConsecutives, scoreCharacter = _ref.scoreCharacter, scoreAcronyms = _ref.scoreAcronyms;
+
+  exports.match = match = function (string, query, options) {
+    var allowErrors, baseMatches, matches, pathSeparator, preparedQuery, string_lw;
+    allowErrors = options.allowErrors, preparedQuery = options.preparedQuery, pathSeparator = options.pathSeparator;
+    if (!(allowErrors || isMatch(string, preparedQuery.core_lw, preparedQuery.core_up))) {
+      return [];
+    }
+    string_lw = string.toLowerCase();
+    matches = computeMatch(string, string_lw, preparedQuery);
+    if (matches.length === 0) {
+      return matches;
+    }
+    if (string.indexOf(pathSeparator) > -1) {
+      baseMatches = basenameMatch(string, string_lw, preparedQuery, pathSeparator);
+      matches = mergeMatches(matches, baseMatches);
+    }
+    return matches;
+  };
+
+  exports.wrap = function (string, query, options) {
+    var matchIndex, matchPos, matchPositions, output, strPos, tagClass, tagClose, tagOpen, _ref1;
+    if (options.wrap != null) {
+      _ref1 = options.wrap, tagClass = _ref1.tagClass, tagOpen = _ref1.tagOpen, tagClose = _ref1.tagClose;
+    }
+    if (tagClass == null) {
+      tagClass = 'highlight';
+    }
+    if (tagOpen == null) {
+      tagOpen = '<strong class="' + tagClass + '">';
+    }
+    if (tagClose == null) {
+      tagClose = '</strong>';
+    }
+    if (string === query) {
+      return tagOpen + string + tagClose;
+    }
+    matchPositions = match(string, query, options);
+    if (matchPositions.length === 0) {
+      return string;
+    }
+    output = '';
+    matchIndex = -1;
+    strPos = 0;
+    while (++matchIndex < matchPositions.length) {
+      matchPos = matchPositions[matchIndex];
+      if (matchPos > strPos) {
+        output += string.substring(strPos, matchPos);
+        strPos = matchPos;
+      }
+      while (++matchIndex < matchPositions.length) {
+        if (matchPositions[matchIndex] === matchPos + 1) {
+          matchPos++;
+        } else {
+          matchIndex--;
+          break;
+        }
+      }
+      matchPos++;
+      if (matchPos > strPos) {
+        output += tagOpen;
+        output += string.substring(strPos, matchPos);
+        output += tagClose;
+        strPos = matchPos;
+      }
+    }
+    if (strPos < string.length - 1) {
+      output += string.substring(strPos);
+    }
+    return output;
+  };
+
+  basenameMatch = function (subject, subject_lw, preparedQuery, pathSeparator) {
+    var basePos, depth, end;
+    end = subject.length - 1;
+    while (subject[end] === pathSeparator) {
+      end--;
+    }
+    basePos = subject.lastIndexOf(pathSeparator, end);
+    if (basePos === -1) {
+      return [];
+    }
+    depth = preparedQuery.depth;
+    while (depth-- > 0) {
+      basePos = subject.lastIndexOf(pathSeparator, basePos - 1);
+      if (basePos === -1) {
+        return [];
+      }
+    }
+    basePos++;
+    end++;
+    return computeMatch(subject.slice(basePos, end), subject_lw.slice(basePos, end), preparedQuery, basePos);
+  };
+
+  mergeMatches = function (a, b) {
+    var ai, bj, i, j, m, n, out;
+    m = a.length;
+    n = b.length;
+    if (n === 0) {
+      return a.slice();
+    }
+    if (m === 0) {
+      return b.slice();
+    }
+    i = -1;
+    j = 0;
+    bj = b[j];
+    out = [];
+    while (++i < m) {
+      ai = a[i];
+      while (bj <= ai && ++j < n) {
+        if (bj < ai) {
+          out.push(bj);
+        }
+        bj = b[j];
+      }
+      out.push(ai);
+    }
+    while (j < n) {
+      out.push(b[j++]);
+    }
+    return out;
+  };
+
+  computeMatch = function (subject, subject_lw, preparedQuery, offset) {
+    var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace;
+    if (offset == null) {
+      offset = 0;
+    }
+    query = preparedQuery.query;
+    query_lw = preparedQuery.query_lw;
+    m = subject.length;
+    n = query.length;
+    acro_score = scoreAcronyms(subject, subject_lw, query, query_lw).score;
+    score_row = new Array(n);
+    csc_row = new Array(n);
+    STOP = 0;
+    UP = 1;
+    LEFT = 2;
+    DIAGONAL = 3;
+    trace = new Array(m * n);
+    pos = -1;
+    j = -1;
+    while (++j < n) {
+      score_row[j] = 0;
+      csc_row[j] = 0;
+    }
+    i = -1;
+    while (++i < m) {
+      score = 0;
+      score_up = 0;
+      csc_diag = 0;
+      si_lw = subject_lw[i];
+      j = -1;
+      while (++j < n) {
+        csc_score = 0;
+        align = 0;
+        score_diag = score_up;
+        if (query_lw[j] === si_lw) {
+          start = isWordStart(i, subject, subject_lw);
+          csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start);
+          align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score);
+        }
+        score_up = score_row[j];
+        csc_diag = csc_row[j];
+        if (score > score_up) {
+          move = LEFT;
+        } else {
+          score = score_up;
+          move = UP;
+        }
+        if (align > score) {
+          score = align;
+          move = DIAGONAL;
+        } else {
+          csc_score = 0;
+        }
+        score_row[j] = score;
+        csc_row[j] = csc_score;
+        trace[++pos] = score > 0 ? move : STOP;
+      }
+    }
+    i = m - 1;
+    j = n - 1;
+    pos = i * n + j;
+    backtrack = true;
+    matches = [];
+    while (backtrack && i >= 0 && j >= 0) {
+      switch (trace[pos]) {
+        case UP:
+          i--;
+          pos -= n;
+          break;
+        case LEFT:
+          j--;
+          pos--;
+          break;
+        case DIAGONAL:
+          matches.push(i + offset);
+          j--;
+          i--;
+          pos -= n + 1;
+          break;
+        default:
+          backtrack = false;
+      }
+    }
+    matches.reverse();
+    return matches;
+  };
+}).call(undefined);
+
+/***/ }),
+/* 1791 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.convertReactSVGDOMProperty = convertReactSVGDOMProperty;
+exports.startsWith = startsWith;
+exports.serializeAttrs = serializeAttrs;
+exports.getSVGFromSource = getSVGFromSource;
+exports.extractSVGProps = extractSVGProps;
+// Transform DOM prop/attr names applicable to `<svg>` element but react-limited
+
+function convertReactSVGDOMProperty(str) {
+    return str.replace(/[-|:]([a-z])/g, function (g) {
+        return g[1].toUpperCase();
+    });
+}
+
+function startsWith(str, substring) {
+    return str.indexOf(substring) === 0;
+}
+
+var DataPropPrefix = 'data-';
+// Serialize `Attr` objects in `NamedNodeMap`
+function serializeAttrs(map) {
+    var ret = {};
+    for (var prop, i = 0; i < map.length; i++) {
+        var key = map[i].name;
+        if (!startsWith(key, DataPropPrefix)) {
+            prop = convertReactSVGDOMProperty(key);
+        }
+        ret[prop] = map[i].value;
+    }
+    return ret;
+}
+
+function getSVGFromSource(src) {
+    var svgContainer = document.createElement('div');
+    svgContainer.innerHTML = src;
+    var svg = svgContainer.firstElementChild;
+    svg.remove(); // deref from parent element
+    return svg;
+}
+
+// get <svg /> element props
+function extractSVGProps(src) {
+    var map = getSVGFromSource(src).attributes;
+    return map.length > 0 ? serializeAttrs(map) : null;
+}
+
+/***/ }),
+/* 1792 */
+/***/ (function(module, exports) {
+
+// removed by extract-text-webpack-plugin
+
+/***/ }),
+/* 1793 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, '__esModule', {
+    value: true
+});
+
+var _extends = Object.assign || function (target) {
+    for (var i = 1; i < arguments.length; i++) {
+        var source = arguments[i];for (var key in source) {
+            if (Object.prototype.hasOwnProperty.call(source, key)) {
+                target[key] = source[key];
+            }
+        }
+    }return target;
+};
+
+var _createClass = function () {
+    function defineProperties(target, props) {
+        for (var i = 0; i < props.length; i++) {
+            var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ('value' in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
+        }
+    }return function (Constructor, protoProps, staticProps) {
+        if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
+    };
+}();
+
+var _get = function get(_x, _x2, _x3) {
+    var _again = true;_function: while (_again) {
+        var object = _x,
+            property = _x2,
+            receiver = _x3;_again = false;if (object === null) object = Function.prototype;var desc = Object.getOwnPropertyDescriptor(object, property);if (desc === undefined) {
+            var parent = Object.getPrototypeOf(object);if (parent === null) {
+                return undefined;
+            } else {
+                _x = parent;_x2 = property;_x3 = receiver;_again = true;desc = parent = undefined;continue _function;
+            }
+        } else if ('value' in desc) {
+            return desc.value;
+        } else {
+            var getter = desc.get;if (getter === undefined) {
+                return undefined;
+            }return getter.call(receiver);
+        }
+    }
+};
+
+function _interopRequireDefault(obj) {
+    return obj && obj.__esModule ? obj : { 'default': obj };
+}
+
+function _objectWithoutProperties(obj, keys) {
+    var target = {};for (var i in obj) {
+        if (keys.indexOf(i) >= 0) continue;if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;target[i] = obj[i];
+    }return target;
+}
+
+function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+        throw new TypeError('Cannot call a class as a function');
+    }
+}
+
+function _inherits(subClass, superClass) {
+    if (typeof superClass !== 'function' && superClass !== null) {
+        throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
+    }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
+}
+
+var _react = __webpack_require__(0);
+
+var _react2 = _interopRequireDefault(_react);
+
+var DOMParser = typeof window !== 'undefined' && window.DOMParser;
+var process = process || {};
+process.env = process.env || {};
+var parserAvailable = typeof DOMParser !== 'undefined' && DOMParser.prototype != null && DOMParser.prototype.parseFromString != null;
+
+function isParsable(src) {
+    // kinda naive but meh, ain't gonna use full-blown parser for this
+    return parserAvailable && typeof src === 'string' && src.trim().substr(0, 4) === '<svg';
+}
+
+// parse SVG string using `DOMParser`
+function parseFromSVGString(src) {
+    var parser = new DOMParser();
+    return parser.parseFromString(src, "image/svg+xml");
+}
+
+// Transform DOM prop/attr names applicable to `<svg>` element but react-limited
+function switchSVGAttrToReactProp(propName) {
+    switch (propName) {
+        case 'class':
+            return 'className';
+        default:
+            return propName;
+    }
+}
+
+var InlineSVG = function (_React$Component) {
+    _inherits(InlineSVG, _React$Component);
+
+    _createClass(InlineSVG, null, [{
+        key: 'defaultProps',
+        value: {
+            element: 'i',
+            raw: false,
+            src: ''
+        },
+        enumerable: true
+    }, {
+        key: 'propTypes',
+        value: {
+            src: _react2['default'].PropTypes.string.isRequired,
+            element: _react2['default'].PropTypes.string,
+            raw: _react2['default'].PropTypes.bool
+        },
+        enumerable: true
+    }]);
+
+    function InlineSVG(props) {
+        _classCallCheck(this, InlineSVG);
+
+        _get(Object.getPrototypeOf(InlineSVG.prototype), 'constructor', this).call(this, props);
+        this._extractSVGProps = this._extractSVGProps.bind(this);
+    }
+
+    // Serialize `Attr` objects in `NamedNodeMap`
+
+    _createClass(InlineSVG, [{
+        key: '_serializeAttrs',
+        value: function _serializeAttrs(map) {
+            var ret = {};
+            var prop = undefined;
+            for (var i = 0; i < map.length; i++) {
+                prop = switchSVGAttrToReactProp(map[i].name);
+                ret[prop] = map[i].value;
+            }
+            return ret;
+        }
+
+        // get <svg /> element props
+    }, {
+        key: '_extractSVGProps',
+        value: function _extractSVGProps(src) {
+            var map = parseFromSVGString(src).documentElement.attributes;
+            return map.length > 0 ? this._serializeAttrs(map) : null;
+        }
+
+        // get content inside <svg> element.
+    }, {
+        key: '_stripSVG',
+        value: function _stripSVG(src) {
+            return parseFromSVGString(src).documentElement.innerHTML;
+        }
+    }, {
+        key: 'componentWillReceiveProps',
+        value: function componentWillReceiveProps(_ref) {
+            var children = _ref.children;
+
+            if ("production" !== process.env.NODE_ENV && children != null) {
+                console.info('<InlineSVG />: `children` prop will be ignored.');
+            }
+        }
+    }, {
+        key: 'render',
+        value: function render() {
+            var Element = undefined,
+                __html = undefined,
+                svgProps = undefined;
+            var _props = this.props;
+            var element = _props.element;
+            var raw = _props.raw;
+            var src = _props.src;
+
+            var otherProps = _objectWithoutProperties(_props, ['element', 'raw', 'src']);
+
+            if (raw === true && isParsable(src)) {
+                Element = 'svg';
+                svgProps = this._extractSVGProps(src);
+                __html = this._stripSVG(src);
+            }
+            __html = __html || src;
+            Element = Element || element;
+            svgProps = svgProps || {};
+
+            return _react2['default'].createElement(Element, _extends({}, svgProps, otherProps, { src: null, children: null,
+                dangerouslySetInnerHTML: { __html: __html } }));
+        }
+    }]);
+
+    return InlineSVG;
+}(_react2['default'].Component);
+
+exports['default'] = InlineSVG;
+module.exports = exports['default'];
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -31648,50 +31648,29 @@ module.exports = isEmpty;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-
-function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
-
-var babylon = __webpack_require__(435);
-var types = __webpack_require__(493);
-
-var startScript = /<script[^>]*>/im;
-var endScript = /<\/script\s*>/im;
-// https://stackoverflow.com/questions/5034781/js-regex-to-split-by-line#comment5633979_5035005
-var newLines = /\r\n|[\n\v\f\r\x85\u2028\u2029]/;
-
-function getCandidateScriptLocations(source, index) {
-  var i = index || 0;
-  var str = source.substring(i);
-
-  var startMatch = startScript.exec(str);
-  if (startMatch) {
-    var startsAt = startMatch.index + startMatch[0].length;
-    var afterStart = str.substring(startsAt);
-    var endMatch = endScript.exec(afterStart);
-    if (endMatch) {
-      var locLength = endMatch.index;
-      var locIndex = i + startsAt;
-
-      return [adjustForLineAndColumn(source, {
-        index: locIndex,
-        length: locLength,
-        source: source.substring(locIndex, locIndex + locLength)
-      })].concat(_toConsumableArray(getCandidateScriptLocations(source, locIndex + locLength + endMatch[0].length)));
-    }
-  }
-
-  return [];
-}
+exports.parseScriptTags = exports.parseScripts = exports.parseScript = exports.getCandidateScriptLocations = exports.generateWhitespace = exports.extractScriptTags = undefined;
+
+var _babelTypes = __webpack_require__(493);
+
+var types = _interopRequireWildcard(_babelTypes);
+
+var _babylon = __webpack_require__(435);
+
+var babylon = _interopRequireWildcard(_babylon);
+
+var _customParse = __webpack_require__(1794);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
 function parseScript(_ref) {
   var source = _ref.source,
       line = _ref.line;
 
   // remove empty or only whitespace scripts
   if (source.length === 0 || /^\s+$/.test(source)) {
     return null;
@@ -31705,93 +31684,41 @@ function parseScript(_ref) {
   } catch (e) {
     return null;
   }
 }
 
 function parseScripts(locations) {
   var parser = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : parseScript;
 
-  return locations.map(parser);
-}
-
-function generateWhitespace(length) {
-  return Array.from(new Array(length + 1)).join(" ");
-}
-
-function calcLineAndColumn(source, index) {
-  var lines = source.substring(0, index).split(newLines);
-  var line = lines.length;
-  var column = lines.pop().length + 1;
-
-  return {
-    column: column,
-    line: line
-  };
-}
-
-function adjustForLineAndColumn(fullSource, location) {
-  var _calcLineAndColumn = calcLineAndColumn(fullSource, location.index),
-      column = _calcLineAndColumn.column,
-      line = _calcLineAndColumn.line;
-
-  return Object.assign({}, location, {
-    line: line,
-    column: column,
-    // prepend whitespace for scripts that do not start on the first column
-    source: generateWhitespace(column) + location.source
-  });
-}
-
-function parseScriptTags(source, parser) {
-  var scripts = parseScripts(getCandidateScriptLocations(source), parser).filter(types.isFile).reduce(function (main, script) {
-    return {
-      statements: main.statements.concat(script.program.body),
-      comments: main.comments.concat(script.comments),
-      tokens: main.tokens.concat(script.tokens)
-    };
-  }, {
-    statements: [],
-    comments: [],
-    tokens: []
-  });
-
-  var program = types.program(scripts.statements);
-  var file = types.file(program, scripts.comments, scripts.tokens);
-
-  var end = calcLineAndColumn(source, source.length);
-  file.start = program.start = 0;
-  file.end = program.end = source.length;
-  file.loc = program.loc = {
-    start: {
-      line: 1,
-      column: 0
-    },
-    end: end
-  };
-
-  return file;
+  return (0, _customParse.parseScripts)(locations, parser);
 }
 
 function extractScriptTags(source) {
-  return parseScripts(getCandidateScriptLocations(source), function (loc) {
+  return parseScripts((0, _customParse.getCandidateScriptLocations)(source), function (loc) {
     var ast = parseScript(loc);
 
     if (ast) {
       return loc;
     }
 
     return null;
   }).filter(types.isFile);
 }
 
+function parseScriptTags(source) {
+  var parser = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : parseScript;
+
+  return (0, _customParse.parseScriptTags)(source, parser);
+}
+
 exports.default = parseScriptTags;
 exports.extractScriptTags = extractScriptTags;
-exports.generateWhitespace = generateWhitespace;
-exports.getCandidateScriptLocations = getCandidateScriptLocations;
+exports.generateWhitespace = _customParse.generateWhitespace;
+exports.getCandidateScriptLocations = _customParse.getCandidateScriptLocations;
 exports.parseScript = parseScript;
 exports.parseScripts = parseScripts;
 exports.parseScriptTags = parseScriptTags;
 
 /***/ }),
 /* 1024 */,
 /* 1025 */,
 /* 1026 */,
@@ -35983,16 +35910,17 @@ function extractSymbols(source) {
   const functions = [];
   const variables = [];
   const memberExpressions = [];
   const callExpressions = [];
   const objectProperties = [];
   const identifiers = [];
   const classes = [];
   const imports = [];
+  let hasJsx = false;
 
   const ast = (0, _ast.traverseAst)(source, {
     enter(path) {
       if ((0, _helpers.isVariable)(path)) {
         variables.push(...getVariableNames(path));
       }
 
       if ((0, _helpers.isFunction)(path)) {
@@ -36000,16 +35928,20 @@ function extractSymbols(source) {
           name: (0, _getFunctionName2.default)(path),
           klass: (0, _inferClassName.inferClassName)(path),
           location: path.node.loc,
           parameterNames: getFunctionParameterNames(path),
           identifier: path.node.id
         });
       }
 
+      if (t.isJSXElement(path)) {
+        hasJsx = true;
+      }
+
       if (t.isClassDeclaration(path)) {
         classes.push({
           name: path.node.id.name,
           parent: path.node.superClass,
           location: path.node.loc
         });
       }
 
@@ -36097,17 +36029,18 @@ function extractSymbols(source) {
     functions,
     variables,
     callExpressions,
     memberExpressions,
     objectProperties,
     comments,
     identifiers,
     classes,
-    imports
+    imports,
+    hasJsx
   };
 }
 
 function getSymbols(source) {
   if (symbolDeclarations.has(source.id)) {
     const symbols = symbolDeclarations.get(source.id);
     if (symbols) {
       return symbols;
@@ -41871,11 +41804,349 @@ function baseToPairs(object, props) {
   return arrayMap(props, function(key) {
     return [key, object[key]];
   });
 }
 
 module.exports = baseToPairs;
 
 
+/***/ }),
+/* 1758 */,
+/* 1759 */,
+/* 1760 */,
+/* 1761 */,
+/* 1762 */,
+/* 1763 */,
+/* 1764 */,
+/* 1765 */,
+/* 1766 */,
+/* 1767 */,
+/* 1768 */,
+/* 1769 */,
+/* 1770 */,
+/* 1771 */,
+/* 1772 */,
+/* 1773 */,
+/* 1774 */,
+/* 1775 */,
+/* 1776 */,
+/* 1777 */,
+/* 1778 */,
+/* 1779 */,
+/* 1780 */,
+/* 1781 */,
+/* 1782 */,
+/* 1783 */,
+/* 1784 */,
+/* 1785 */,
+/* 1786 */,
+/* 1787 */,
+/* 1788 */,
+/* 1789 */,
+/* 1790 */,
+/* 1791 */,
+/* 1792 */,
+/* 1793 */,
+/* 1794 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.parseScriptTags = exports.parseScripts = exports.getCandidateScriptLocations = exports.generateWhitespace = undefined;
+
+var _babelTypes = __webpack_require__(493);
+
+var types = _interopRequireWildcard(_babelTypes);
+
+var _parseScriptFragment = __webpack_require__(1795);
+
+var _parseScriptFragment2 = _interopRequireDefault(_parseScriptFragment);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var startScript = /<script[^>]*>/im;
+var endScript = /<\/script\s*>/im;
+// https://stackoverflow.com/questions/5034781/js-regex-to-split-by-line#comment5633979_5035005
+var newLines = /\r\n|[\n\v\f\r\x85\u2028\u2029]/;
+
+function getType(tag) {
+  var fragment = (0, _parseScriptFragment2.default)(tag);
+
+  if (fragment) {
+    var type = fragment.attributes.type;
+
+    return type ? type.toLowerCase() : null;
+  }
+
+  return null;
+}
+
+function getCandidateScriptLocations(source, index) {
+  var i = index || 0;
+  var str = source.substring(i);
+
+  var startMatch = startScript.exec(str);
+  if (startMatch) {
+    var startsAt = startMatch.index + startMatch[0].length;
+    var afterStart = str.substring(startsAt);
+    var endMatch = endScript.exec(afterStart);
+    if (endMatch) {
+      var locLength = endMatch.index;
+      var locIndex = i + startsAt;
+      var endIndex = locIndex + locLength + endMatch[0].length;
+
+      // extract the complete tag (incl start and end tags and content). if the
+      // type is invalid (= not JS), skip this tag and continue
+      var tag = source.substring(i + startMatch.index, endIndex);
+      var type = getType(tag);
+      if (type && type !== "javascript" && type !== "text/javascript") {
+        return getCandidateScriptLocations(source, endIndex);
+      }
+
+      return [adjustForLineAndColumn(source, {
+        index: locIndex,
+        length: locLength,
+        source: source.substring(locIndex, locIndex + locLength)
+      })].concat(_toConsumableArray(getCandidateScriptLocations(source, endIndex)));
+    }
+  }
+
+  return [];
+}
+
+function parseScripts(locations, parser) {
+  return locations.map(parser);
+}
+
+function generateWhitespace(length) {
+  return Array.from(new Array(length + 1)).join(" ");
+}
+
+function calcLineAndColumn(source, index) {
+  var lines = source.substring(0, index).split(newLines);
+  var line = lines.length;
+  var column = lines.pop().length + 1;
+
+  return {
+    column: column,
+    line: line
+  };
+}
+
+function adjustForLineAndColumn(fullSource, location) {
+  var _calcLineAndColumn = calcLineAndColumn(fullSource, location.index),
+      column = _calcLineAndColumn.column,
+      line = _calcLineAndColumn.line;
+
+  return Object.assign({}, location, {
+    line: line,
+    column: column,
+    // prepend whitespace for scripts that do not start on the first column
+    source: generateWhitespace(column) + location.source
+  });
+}
+
+function parseScriptTags(source, parser) {
+  var scripts = parseScripts(getCandidateScriptLocations(source), parser).filter(types.isFile).reduce(function (main, script) {
+    return {
+      statements: main.statements.concat(script.program.body),
+      comments: main.comments.concat(script.comments),
+      tokens: main.tokens.concat(script.tokens)
+    };
+  }, {
+    statements: [],
+    comments: [],
+    tokens: []
+  });
+
+  var program = types.program(scripts.statements);
+  var file = types.file(program, scripts.comments, scripts.tokens);
+
+  var end = calcLineAndColumn(source, source.length);
+  file.start = program.start = 0;
+  file.end = program.end = source.length;
+  file.loc = program.loc = {
+    start: {
+      line: 1,
+      column: 0
+    },
+    end: end
+  };
+
+  return file;
+}
+
+exports.default = parseScriptTags;
+exports.generateWhitespace = generateWhitespace;
+exports.getCandidateScriptLocations = getCandidateScriptLocations;
+exports.parseScripts = parseScripts;
+exports.parseScriptTags = parseScriptTags;
+
+/***/ }),
+/* 1795 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var alphanum = /[a-z0-9\-]/i;
+
+function parseToken(str, start) {
+  var i = start;
+  while (i < str.length && alphanum.test(str.charAt(i++))) {
+    continue;
+  }
+
+  if (i !== start) {
+    return {
+      token: str.substring(start, i - 1),
+      index: i
+    };
+  }
+
+  return null;
+}
+
+function parseAttributes(str, start) {
+  var i = start;
+  var attributes = {};
+  var attribute = null;
+
+  while (i < str.length) {
+    var c = str.charAt(i);
+
+    if (attribute === null && c == ">") {
+      break;
+    } else if (attribute === null && alphanum.test(c)) {
+      attribute = {
+        name: null,
+        value: true,
+        bool: true,
+        terminator: null
+      };
+
+      var attributeNameNode = parseToken(str, i);
+      if (attributeNameNode) {
+        attribute.name = attributeNameNode.token;
+        i = attributeNameNode.index - 2;
+      }
+    } else if (attribute !== null) {
+      if (c === "=") {
+        // once we've started an attribute, look for = to indicate
+        // it's a non-boolean attribute
+        attribute.bool = false;
+        if (attribute.value === true) {
+          attribute.value = "";
+        }
+      } else if (!attribute.bool && attribute.terminator === null && (c === '"' || c === "'")) {
+        // once we've determined it's non-boolean, look for a
+        // value terminator (", ')
+        attribute.terminator = c;
+      } else if (attribute.terminator) {
+        if (c === attribute.terminator) {
+          // if we had a terminator and found another, we've
+          // reach the end of the attribute
+          attributes[attribute.name] = attribute.value;
+          attribute = null;
+        } else {
+          // otherwise, append the character to the attribute value
+          attribute.value += c;
+
+          // check for an escaped terminator and push it as well
+          // to avoid terminating prematurely
+          if (c === "\\") {
+            var next = str.charAt(i + 1);
+            if (next === attribute.terminator) {
+              attribute.value += next;
+              i += 1;
+            }
+          }
+        }
+      } else if (!/\s/.test(c)) {
+        // if we've hit a non-space character and aren't processing a value,
+        // we're starting a new attribute so push the attribute and clear the
+        // local variable
+        attributes[attribute.name] = attribute.value;
+        attribute = null;
+
+        // move the cursor back to re-find the start of the attribute
+        i -= 1;
+      }
+    }
+
+    i++;
+  }
+
+  if (i !== start) {
+    return {
+      attributes: attributes,
+      index: i
+    };
+  }
+
+  return null;
+}
+
+function parseFragment(str) {
+  var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+
+  var tag = null;
+  var open = false;
+  var attributes = {};
+
+  var i = start;
+  while (i < str.length) {
+    var c = str.charAt(i++);
+
+    if (!open && !tag && c === "<") {
+      // Open Start Tag
+      open = true;
+
+      var tagNode = parseToken(str, i);
+      if (!tagNode) {
+        return null;
+      }
+
+      i = tagNode.index - 1;
+      tag = tagNode.token;
+    } else if (open && c === ">") {
+      // Close Start Tag
+      break;
+    } else if (open) {
+      // Attributes
+      var attributeNode = parseAttributes(str, i - 1);
+
+      if (attributeNode) {
+        i = attributeNode.index;
+        attributes = attributeNode.attributes || attributes;
+      }
+    }
+  }
+
+  if (tag) {
+    return {
+      tag: tag,
+      attributes: attributes
+    };
+  }
+
+  return null;
+}
+
+exports.default = parseFragment;
+exports.parseFragment = parseFragment;
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/themes/images/debugger/resume.svg
+++ b/devtools/client/themes/images/debugger/resume.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-  <path d="M6.925 12.5l7.4-5-7.4-5v10zM6 12.5v-10c0-.785.8-1.264 1.415-.848l7.4 5c.58.392.58 1.304 0 1.696l-7.4 5C6.8 13.764 6 13.285 6 12.5z" fill-rule="evenodd"/>
+<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+  <path fill="black" id="svg_1" fill-rule="evenodd" d="m4.55195,12.97461l7.4,-5l-7.4,-5l0,10zm-0.925,0l0,-10c0,-0.785 0.8,-1.264 1.415,-0.848l7.4,5c0.58,0.392 0.58,1.304 0,1.696l-7.4,5c-0.615,0.416 -1.415,-0.063 -1.415,-0.848z"/>
 </svg>
--- a/devtools/server/actors/webconsole/listeners.js
+++ b/devtools/server/actors/webconsole/listeners.js
@@ -278,17 +278,17 @@ ConsoleAPIListener.prototype =
     let workerType = WebConsoleUtils.getWorkerType(message);
 
     if (this.window && workerType === "ServiceWorker") {
       // For messages from Service Workers, message.ID is the
       // scope, which can be used to determine whether it's controlling
       // a window.
       let scope = message.ID;
 
-      if (!swm.shouldReportToWindow(this.window, scope)) {
+      if (!this.window.shouldReportForServiceWorkerScope(scope)) {
         return false;
       }
     }
 
     if (this.window && !workerType) {
       let msgWindow = Services.wm.getCurrentInnerWindowWithId(message.innerID);
       if (!msgWindow || !isWindowIncluded(this.window, msgWindow)) {
         // Not the same window!
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -38,16 +38,17 @@
 #include "nsISizeOfEventTarget.h"
 #include "nsDOMJSUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsDOMWindowList.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "nsIDocShellTreeOwner.h"
+#include "nsIDocumentLoader.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptTimeoutHandler.h"
 #include "nsITimeoutHandler.h"
 #include "nsIController.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsISlowScriptDebug.h"
@@ -2326,16 +2327,120 @@ nsPIDOMWindowInner::GetClientState() con
 
 Maybe<ServiceWorkerDescriptor>
 nsPIDOMWindowInner::GetController() const
 {
   return Move(nsGlobalWindowInner::Cast(this)->GetController());
 }
 
 void
+nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(aScope);
+}
+
+bool
+nsGlobalWindowInner::ShouldReportForServiceWorkerScope(const nsAString& aScope)
+{
+  bool result = false;
+
+  nsPIDOMWindowOuter* topOuter = GetScriptableTop();
+  NS_ENSURE_TRUE(topOuter, false);
+
+  nsGlobalWindowInner* topInner =
+    nsGlobalWindowInner::Cast(topOuter->GetCurrentInnerWindow());
+  NS_ENSURE_TRUE(topInner, false);
+
+  topInner->ShouldReportForServiceWorkerScopeInternal(NS_ConvertUTF16toUTF8(aScope),
+                                                      &result);
+  return result;
+}
+
+nsGlobalWindowInner::CallState
+nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal(const nsACString& aScope,
+                                                               bool* aResultOut)
+{
+  MOZ_DIAGNOSTIC_ASSERT(aResultOut);
+
+  // First check to see if this window is controlled.  If so, then we have
+  // found a match and are done.
+  const Maybe<ServiceWorkerDescriptor> swd = GetController();
+  if (swd.isSome() && swd.ref().Scope() == aScope) {
+    *aResultOut = true;
+    return CallState::Stop;
+  }
+
+  // Next, check to see if this window has called navigator.serviceWorker.register()
+  // for this scope.  If so, then treat this as a match so console reports
+  // appear in the devtools console.
+  if (mClientSource && mClientSource->CalledRegisterForServiceWorkerScope(aScope)) {
+    *aResultOut = true;
+    return CallState::Stop;
+  }
+
+  // Finally check the current docshell nsILoadGroup to see if there are any
+  // outstanding navigation requests.  If so, match the scope against the
+  // channel's URL.  We want to show console reports during the FetchEvent
+  // intercepting the navigation itself.
+  nsCOMPtr<nsIDocumentLoader> loader(do_QueryInterface(GetDocShell()));
+  if (loader) {
+    nsCOMPtr<nsILoadGroup> loadgroup;
+    Unused << loader->GetLoadGroup(getter_AddRefs(loadgroup));
+    if (loadgroup) {
+      nsCOMPtr<nsISimpleEnumerator> iter;
+      Unused << loadgroup->GetRequests(getter_AddRefs(iter));
+      if (iter) {
+        nsCOMPtr<nsISupports> tmp;
+        bool hasMore = true;
+        // Check each network request in the load group.
+        while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
+          iter->GetNext(getter_AddRefs(tmp));
+          nsCOMPtr<nsIChannel> loadingChannel(do_QueryInterface(tmp));
+          // Ignore subresource requests.  Logging for a subresource
+          // FetchEvent should be handled above since the client is
+          // already controlled.
+          if (!loadingChannel ||
+              !nsContentUtils::IsNonSubresourceRequest(loadingChannel)) {
+            continue;
+          }
+          nsCOMPtr<nsIURI> loadingURL;
+          Unused << loadingChannel->GetURI(getter_AddRefs(loadingURL));
+          if (!loadingURL) {
+            continue;
+          }
+          nsAutoCString loadingSpec;
+          Unused << loadingURL->GetSpec(loadingSpec);
+          // Perform a simple substring comparison to match the scope
+          // against the channel URL.
+          if (StringBeginsWith(loadingSpec, aScope)) {
+            *aResultOut = true;
+            return CallState::Stop;
+          }
+        }
+      }
+    }
+  }
+
+  // The current window doesn't care about this service worker, but maybe
+  // one of our child frames does.
+  return CallOnChildren(&nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal,
+                        aScope, aResultOut);
+}
+
+void
+nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  if (!mClientSource) {
+    return;
+  }
+
+  mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
+}
+
+void
 nsGlobalWindowInner::UpdateTopInnerWindow()
 {
   if (IsTopInnerWindow() || !mTopInnerWindow) {
     return;
   }
 
   mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
 }
@@ -6109,26 +6214,28 @@ nsGlobalWindowInner::SyncStateFromParent
 
   // Now apply only the number of Suspend() calls to reach the target
   // suspend count after applying the Freeze() calls.
   for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
     Suspend();
   }
 }
 
-template<typename Method>
-void
-nsGlobalWindowInner::CallOnChildren(Method aMethod)
+template<typename Method, typename... Args>
+nsGlobalWindowInner::CallState
+nsGlobalWindowInner::CallOnChildren(Method aMethod, Args& ...aArgs)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(IsCurrentInnerWindow());
 
+  CallState state = CallState::Continue;
+
   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   if (!docShell) {
-    return;
+    return state;
   }
 
   int32_t childCount = 0;
   docShell->GetChildCount(&childCount);
 
   for (int32_t i = 0; i < childCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> childShell;
     docShell->GetChildAt(i, getter_AddRefs(childShell));
@@ -6144,18 +6251,29 @@ nsGlobalWindowInner::CallOnChildren(Meth
 
     // This is a bit hackish. Only freeze/suspend windows which are truly our
     // subwindows.
     nsCOMPtr<Element> frame = pWin->GetFrameElementInternal();
     if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
       continue;
     }
 
-    (inner->*aMethod)();
-  }
+    // Call the child method using our helper CallChild() template method.
+    // This allows us to handle both void returning methods and methods
+    // that return CallState explicitly.  For void returning methods we
+    // assume CallState::Continue.
+    typedef decltype((inner->*aMethod)(aArgs...)) returnType;
+    state = CallChild<returnType>(inner, aMethod, aArgs...);
+
+    if (state == CallState::Stop) {
+      return state;
+    }
+  }
+
+  return state;
 }
 
 Maybe<ClientInfo>
 nsGlobalWindowInner::GetClientInfo() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   Maybe<ClientInfo> clientInfo;
   if (mClientSource) {
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -346,16 +346,18 @@ public:
   void Thaw();
   virtual bool IsFrozen() const override;
   void SyncStateFromParentWindow();
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
+  void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
   virtual nsresult FireDelayedDOMEvents() override;
 
   virtual nsresult SetNewDocument(nsIDocument *aDocument,
                                   nsISupports *aState,
                                   bool aForceReuseInnerWindow) override;
 
   virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
                                bool aOriginalOpener) override;
@@ -966,16 +968,18 @@ public:
                       mozilla::ErrorResult& aError);
 
   void GetInterface(JSContext* aCx, nsIJSID* aIID,
                     JS::MutableHandle<JS::Value> aRetval,
                     mozilla::ErrorResult& aError);
 
   already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
 
+  bool ShouldReportForServiceWorkerScope(const nsAString& aScope);
+
   void UpdateTopInnerWindow();
 
   virtual bool IsInSyncOperation() override
   {
     return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
   }
 
 protected:
@@ -1090,22 +1094,60 @@ protected:
   // Get the parent, returns null if this is a toplevel window
   nsPIDOMWindowOuter* GetParentInternal();
 
 public:
   // popup tracking
   bool IsPopupSpamWindow();
 
 private:
-  template<typename Method>
-  void CallOnChildren(Method aMethod);
+  // A type that methods called by CallOnChildren can return.  If Stop
+  // is returned then CallOnChildren will stop calling further children.
+  // If Continue is returned then CallOnChildren will keep calling further
+  // children.
+  enum class CallState
+  {
+    Continue,
+    Stop,
+  };
+
+  // Call the given method on the immediate children of this window.  The
+  // CallState returned by the last child method invocation is returned or
+  // CallState::Continue if the method returns void.
+  template<typename Method, typename... Args>
+  CallState CallOnChildren(Method aMethod, Args& ...aArgs);
+
+  // Helper to convert a void returning child method into an implicit
+  // CallState::Continue value.
+  template<typename Return, typename Method, typename... Args>
+  typename std::enable_if<std::is_void<Return>::value,
+                          nsGlobalWindowInner::CallState>::type
+  CallChild(nsGlobalWindowInner* aWindow, Method aMethod, Args& ...aArgs)
+  {
+    (aWindow->*aMethod)(aArgs...);
+    return nsGlobalWindowInner::CallState::Continue;
+  }
+
+  // Helper that passes through the CallState value from a child method.
+  template<typename Return, typename Method, typename... Args>
+  typename std::enable_if<std::is_same<Return,
+                                       nsGlobalWindowInner::CallState>::value,
+                          nsGlobalWindowInner::CallState>::type
+  CallChild(nsGlobalWindowInner* aWindow, Method aMethod, Args& ...aArgs)
+  {
+    return (aWindow->*aMethod)(aArgs...);
+  }
 
   void FreezeInternal();
   void ThawInternal();
 
+  CallState ShouldReportForServiceWorkerScopeInternal(const nsACString& aScope,
+                                                      bool* aResultOut);
+
+
 public:
   // Timeout Functions
   // |interval| is in milliseconds.
   int32_t SetTimeoutOrInterval(JSContext* aCx,
                                mozilla::dom::Function& aFunction,
                                int32_t aTimeout,
                                const mozilla::dom::Sequence<JS::Value>& aArguments,
                                bool aIsInterval, mozilla::ErrorResult& aError);
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -326,16 +326,18 @@ public:
   // Return true if there are any open WebSockets that could block
   // timeout-throttling.
   bool HasOpenWebSockets() const;
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
+  void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
   mozilla::dom::TabGroup* TabGroup();
 
   virtual nsPIDOMWindowOuter* GetPrivateRoot() = 0;
 
   virtual mozilla::dom::CustomElementRegistry* CustomElements() = 0;
 
   // XXX: This is called on inner windows
   virtual nsPIDOMWindowOuter* GetScriptableTop() = 0;
--- a/dom/canvas/TexUnpackBlob.cpp
+++ b/dom/canvas/TexUnpackBlob.cpp
@@ -618,17 +618,16 @@ TexUnpackImage::TexOrSubImage(bool isSub
                               GLint yOffset, GLint zOffset, const webgl::PackingInfo& pi,
                               GLenum* const out_error) const
 {
     MOZ_ASSERT_IF(needsRespec, !isSubImage);
 
     WebGLContext* webgl = tex->mContext;
 
     gl::GLContext* gl = webgl->GL();
-    gl->MakeCurrent();
 
     if (needsRespec) {
         *out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
                                      yOffset, zOffset, mWidth, mHeight, mDepth,
                                      nullptr);
         if (*out_error)
             return true;
     }
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -78,17 +78,16 @@ WebGL2Context::CopyBufferSubData(GLenum 
                               funcName,
                               (readType == WebGLBuffer::Kind::OtherData) ? "other"
                                                                          : "element",
                               (writeType == WebGLBuffer::Kind::OtherData) ? "other"
                                                                           : "element");
         return;
     }
 
-    gl->MakeCurrent();
     const ScopedLazyBind readBind(gl, readTarget, readBuffer);
     const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
     gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
 }
 
 void
 WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
                                 const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
@@ -123,17 +122,36 @@ WebGL2Context::GetBufferSubData(GLenum t
     if (!CheckedInt<GLsizeiptr>(byteLen).isValid()) {
         ErrorOutOfMemory("%s: Size too large.", funcName);
         return;
     }
     const GLsizeiptr glByteLen(byteLen);
 
     ////
 
-    gl->MakeCurrent();
+    switch (buffer->mUsage) {
+    case LOCAL_GL_STATIC_READ:
+    case LOCAL_GL_STREAM_READ:
+    case LOCAL_GL_DYNAMIC_READ:
+        if (mCompletedFenceId < buffer->mLastUpdateFenceId) {
+            GeneratePerfWarning("%s: Reading from a buffer without checking for previous"
+                                " command completion likely causes pipeline stalls."
+                                " Please use FenceSync.",
+                                funcName);
+        }
+        break;
+    default:
+        GeneratePerfWarning("%s: Reading from a buffer with usage other than *_READ"
+                            " causes pipeline stalls. Copy through a STREAM_READ buffer.",
+                            funcName);
+        break;
+    }
+
+    ////
+
     const ScopedLazyBind readBind(gl, target, buffer);
 
     if (byteLen) {
         const bool isTF = (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER);
         GLenum mapTarget = target;
         if (isTF) {
             gl->fBindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, mEmptyTFO);
             gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, buffer->mGLName);
--- a/dom/canvas/WebGL2ContextFramebuffers.cpp
+++ b/dom/canvas/WebGL2ContextFramebuffers.cpp
@@ -161,18 +161,16 @@ WebGLContext::ValidateInvalidateFramebuf
                                             ErrorResult* const out_rv,
                                             std::vector<GLenum>* const scopedVector,
                                             GLsizei* const out_glNumAttachments,
                                             const GLenum** const out_glAttachments)
 {
     if (IsContextLost())
         return false;
 
-    gl->MakeCurrent();
-
     if (!ValidateFramebufferTarget(target, funcName))
         return false;
 
     const WebGLFramebuffer* fb;
     bool isDefaultFB;
     switch (target) {
     case LOCAL_GL_FRAMEBUFFER:
     case LOCAL_GL_DRAW_FRAMEBUFFER:
@@ -311,18 +309,16 @@ WebGL2Context::InvalidateSubFramebuffer(
 
 void
 WebGL2Context::ReadBuffer(GLenum mode)
 {
     const char funcName[] = "readBuffer";
     if (IsContextLost())
         return;
 
-    gl->MakeCurrent();
-
     if (mBoundReadFramebuffer) {
         mBoundReadFramebuffer->ReadBuffer(funcName, mode);
         return;
     }
 
     // Operating on the default framebuffer.
     if (mode != LOCAL_GL_NONE &&
         mode != LOCAL_GL_BACK)
--- a/dom/canvas/WebGL2ContextMRTs.cpp
+++ b/dom/canvas/WebGL2ContextMRTs.cpp
@@ -57,18 +57,16 @@ WebGL2Context::ValidateClearBuffer(const
     if (availElemCount < requiredElements) {
         ErrorInvalidValue("%s: Not enough elements. Require %zu. Given %zu.",
                           funcName, requiredElements, availElemCount);
         return false;
     }
 
     ////
 
-    MakeContextCurrent();
-
     const auto& fb = mBoundDrawFramebuffer;
     if (fb) {
         if (!fb->ValidateAndInitAttachments(funcName))
             return false;
 
         if (!fb->ValidateClearBufferType(funcName, buffer, drawBuffer, funcType))
             return false;
     } else if (buffer == LOCAL_GL_COLOR) {
--- a/dom/canvas/WebGL2ContextSamplers.cpp
+++ b/dom/canvas/WebGL2ContextSamplers.cpp
@@ -11,17 +11,16 @@ namespace mozilla {
 
 already_AddRefed<WebGLSampler>
 WebGL2Context::CreateSampler()
 {
     if (IsContextLost())
         return nullptr;
 
     GLuint sampler;
-    MakeContextCurrent();
     gl->fGenSamplers(1, &sampler);
 
     RefPtr<WebGLSampler> globj = new WebGLSampler(this, sampler);
     return globj.forget();
 }
 
 void
 WebGL2Context::DeleteSampler(WebGLSampler* sampler)
@@ -41,17 +40,16 @@ WebGL2Context::DeleteSampler(WebGLSample
 }
 
 bool
 WebGL2Context::IsSampler(const WebGLSampler* sampler)
 {
     if (!ValidateIsObject("isSampler", sampler))
         return false;
 
-    MakeContextCurrent();
     return gl->fIsSampler(sampler->mGLName);
 }
 
 void
 WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
 {
     if (IsContextLost())
         return;
@@ -59,17 +57,16 @@ WebGL2Context::BindSampler(GLuint unit, 
     if (sampler && !ValidateObject("bindSampler", *sampler))
         return;
 
     if (unit >= mGLMaxTextureUnits)
         return ErrorInvalidValue("bindSampler: unit must be < %u", mGLMaxTextureUnits);
 
     ////
 
-    gl->MakeCurrent();
     gl->fBindSampler(unit, sampler ? sampler->mGLName : 0);
 
     InvalidateResolveCacheForTextureWithTexUnit(unit);
     mBoundSamplers[unit] = sampler;
 }
 
 void
 WebGL2Context::SamplerParameteri(WebGLSampler& sampler, GLenum pname, GLint param)
@@ -107,18 +104,16 @@ WebGL2Context::GetSamplerParameter(JSCon
     if (IsContextLost())
         return;
 
     if (!ValidateObject(funcName, sampler))
         return;
 
     ////
 
-    gl->MakeCurrent();
-
     switch (pname) {
     case LOCAL_GL_TEXTURE_MIN_FILTER:
     case LOCAL_GL_TEXTURE_MAG_FILTER:
     case LOCAL_GL_TEXTURE_WRAP_S:
     case LOCAL_GL_TEXTURE_WRAP_T:
     case LOCAL_GL_TEXTURE_WRAP_R:
     case LOCAL_GL_TEXTURE_COMPARE_MODE:
     case LOCAL_GL_TEXTURE_COMPARE_FUNC:
--- a/dom/canvas/WebGL2ContextState.cpp
+++ b/dom/canvas/WebGL2ContextState.cpp
@@ -22,18 +22,16 @@ WebGL2Context::GetParameter(JSContext* c
   // The following cases are handled in WebGLContext::GetParameter():
   //     case LOCAL_GL_MAX_COLOR_ATTACHMENTS:
   //     case LOCAL_GL_MAX_DRAW_BUFFERS:
   //     case LOCAL_GL_DRAW_BUFFERi:
 
   if (IsContextLost())
     return JS::NullValue();
 
-  MakeContextCurrent();
-
   switch (pname) {
     /* GLboolean */
     case LOCAL_GL_RASTERIZER_DISCARD:
     case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
     case LOCAL_GL_SAMPLE_COVERAGE: {
       realGLboolean b = 0;
       gl->fGetBooleanv(pname, &b);
       return JS::BooleanValue(bool(b));
--- a/dom/canvas/WebGL2ContextSync.cpp
+++ b/dom/canvas/WebGL2ContextSync.cpp
@@ -24,17 +24,16 @@ WebGL2Context::FenceSync(GLenum conditio
         return nullptr;
     }
 
     if (flags != 0) {
         ErrorInvalidValue("fenceSync: flags must be 0");
         return nullptr;
     }
 
-    MakeContextCurrent();
     RefPtr<WebGLSync> globj = new WebGLSync(this, condition, flags);
     return globj.forget();
 }
 
 bool
 WebGL2Context::IsSync(const WebGLSync* sync)
 {
     if (!ValidateIsObject("isSync", sync))
@@ -68,18 +67,25 @@ WebGL2Context::ClientWaitSync(const WebG
     }
 
     if (timeout > kMaxClientWaitSyncTimeoutNS) {
         ErrorInvalidOperation("%s: `timeout` must not exceed %s nanoseconds.", funcName,
                               "MAX_CLIENT_WAIT_TIMEOUT_WEBGL");
         return LOCAL_GL_WAIT_FAILED;
     }
 
-    MakeContextCurrent();
-    return gl->fClientWaitSync(sync.mGLName, flags, timeout);
+    const auto ret = gl->fClientWaitSync(sync.mGLName, flags, timeout);
+
+    if (ret == LOCAL_GL_CONDITION_SATISFIED ||
+        ret == LOCAL_GL_ALREADY_SIGNALED)
+    {
+        sync.MarkSignaled();
+    }
+
+    return ret;
 }
 
 void
 WebGL2Context::WaitSync(const WebGLSync& sync, GLbitfield flags, GLint64 timeout)
 {
     const char funcName[] = "waitSync";
     if (IsContextLost())
         return;
@@ -92,17 +98,16 @@ WebGL2Context::WaitSync(const WebGLSync&
         return;
     }
 
     if (timeout != -1) {
         ErrorInvalidValue("%s: `timeout` must be TIMEOUT_IGNORED.", funcName);
         return;
     }
 
-    MakeContextCurrent();
     gl->fWaitSync(sync.mGLName, flags, LOCAL_GL_TIMEOUT_IGNORED);
 }
 
 void
 WebGL2Context::GetSyncParameter(JSContext*, const WebGLSync& sync, GLenum pname,
                                 JS::MutableHandleValue retval)
 {
     const char funcName[] = "getSyncParameter";
@@ -110,25 +115,30 @@ WebGL2Context::GetSyncParameter(JSContex
     if (IsContextLost())
         return;
 
     if (!ValidateObject(funcName, sync))
         return;
 
     ////
 
-    gl->MakeCurrent();
-
     GLint result = 0;
     switch (pname) {
     case LOCAL_GL_OBJECT_TYPE:
     case LOCAL_GL_SYNC_STATUS:
     case LOCAL_GL_SYNC_CONDITION:
     case LOCAL_GL_SYNC_FLAGS:
         gl->fGetSynciv(sync.mGLName, pname, 1, nullptr, &result);
+
+        if (pname == LOCAL_GL_SYNC_STATUS &&
+            result == LOCAL_GL_SIGNALED)
+        {
+            sync.MarkSignaled();
+        }
+
         retval.set(JS::Int32Value(result));
         return;
 
     default:
         ErrorInvalidEnum("%s: Invalid pname 0x%04x", funcName, pname);
         return;
     }
 }
--- a/dom/canvas/WebGL2ContextTransformFeedback.cpp
+++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp
@@ -15,17 +15,16 @@ namespace mozilla {
 // Transform Feedback
 
 already_AddRefed<WebGLTransformFeedback>
 WebGL2Context::CreateTransformFeedback()
 {
     if (IsContextLost())
         return nullptr;
 
-    MakeContextCurrent();
     GLuint tf = 0;
     gl->fGenTransformFeedbacks(1, &tf);
 
     RefPtr<WebGLTransformFeedback> ret = new WebGLTransformFeedback(this, tf);
     return ret.forget();
 }
 
 void
@@ -48,17 +47,16 @@ WebGL2Context::DeleteTransformFeedback(W
 }
 
 bool
 WebGL2Context::IsTransformFeedback(const WebGLTransformFeedback* tf)
 {
     if (!ValidateIsObject("isTransformFeedback", tf))
         return false;
 
-    MakeContextCurrent();
     return gl->fIsTransformFeedback(tf->mGLName);
 }
 
 void
 WebGL2Context::BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf)
 {
     const char funcName[] = "bindTransformFeedback";
     if (IsContextLost())
@@ -82,17 +80,16 @@ WebGL2Context::BindTransformFeedback(GLe
     ////
 
     if (mBoundTransformFeedback) {
         mBoundTransformFeedback->AddBufferBindCounts(-1);
     }
 
     mBoundTransformFeedback = (tf ? tf : mDefaultTransformFeedback);
 
-    MakeContextCurrent();
     gl->fBindTransformFeedback(target, mBoundTransformFeedback->mGLName);
 
     if (mBoundTransformFeedback) {
         mBoundTransformFeedback->AddBufferBindCounts(+1);
     }
 }
 
 void
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -21,48 +21,44 @@ namespace mozilla {
 // Uniforms
 
 void
 WebGLContext::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
 {
     if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui"))
         return;
 
-    MakeContextCurrent();
     gl->fUniform1ui(loc->mLoc, v0);
 }
 
 void
 WebGLContext::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
 {
     if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui"))
         return;
 
-    MakeContextCurrent();
     gl->fUniform2ui(loc->mLoc, v0, v1);
 }
 
 void
 WebGLContext::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
 {
     if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui"))
         return;
 
-    MakeContextCurrent();
     gl->fUniform3ui(loc->mLoc, v0, v1, v2);
 }
 
 void
 WebGLContext::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
                          GLuint v3)
 {
     if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui"))
         return;
 
-    MakeContextCurrent();
     gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3);
 }
 
 // -------------------------------------------------------------------------
 // Uniform Buffer Objects and Transform Feedback Buffers
 
 void
 WebGL2Context::GetIndexedParameter(JSContext* cx, GLenum target, GLuint index,
@@ -189,17 +185,16 @@ WebGL2Context::GetActiveUniforms(JSConte
     JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
     UniquePtr<GLint[]> samples(new GLint[count]);
     if (!array || !samples) {
         ErrorOutOfMemory("%s: Failed to allocate buffers.", funcName);
         return;
     }
     retval.setObject(*array);
 
-    MakeContextCurrent();
     gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(), pname,
                              samples.get());
 
     switch (pname) {
     case LOCAL_GL_UNIFORM_TYPE:
     case LOCAL_GL_UNIFORM_SIZE:
     case LOCAL_GL_UNIFORM_BLOCK_INDEX:
     case LOCAL_GL_UNIFORM_OFFSET:
@@ -247,18 +242,16 @@ WebGL2Context::GetActiveUniformBlockPara
 {
     out_retval.setNull();
     if (IsContextLost())
         return;
 
     if (!ValidateObject("getActiveUniformBlockParameter: program", program))
         return;
 
-    MakeContextCurrent();
-
     switch(pname) {
     case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
     case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
     case LOCAL_GL_UNIFORM_BLOCK_BINDING:
     case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE:
     case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
         out_retval.set(program.GetActiveUniformBlockParam(uniformBlockIndex, pname));
         return;
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -52,17 +52,16 @@ WebGLBuffer::SetContentAfterBind(GLenum 
     default:
         MOZ_CRASH("GFX: invalid target");
     }
 }
 
 void
 WebGLBuffer::Delete()
 {
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteBuffers(1, &mGLName);
 
     mByteLength = 0;
     mFetchInvalidator.InvalidateCaches();
 
     mIndexCache = nullptr;
     mIndexRanges.clear();
     LinkedListElement<WebGLBuffer>::remove(); // remove from mContext->mBuffers
@@ -131,17 +130,16 @@ WebGLBuffer::BufferData(GLenum target, s
             mContext->ErrorOutOfMemory("%s: Failed to alloc index cache.", funcName);
             return;
         }
         memcpy(newIndexCache.get(), data, size);
         uploadData = newIndexCache.get();
     }
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     const ScopedLazyBind lazyBind(gl, target, this);
 
     const bool sizeChanges = (size != ByteLength());
     if (sizeChanges) {
         gl::GLContext::LocalErrorScope errorScope(*gl);
         gl->fBufferData(target, size, uploadData, usage);
         const auto error = errorScope.GetError();
 
@@ -191,17 +189,16 @@ WebGLBuffer::BufferSubData(GLenum target
         uploadData = cachedDataBegin;
 
         InvalidateCacheRange(dstByteOffset, dataLen);
     }
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     const ScopedLazyBind lazyBind(gl, target, this);
 
     gl->fBufferSubData(target, dstByteOffset, dataLen, uploadData);
 }
 
 bool
 WebGLBuffer::ValidateRange(const char* funcName, size_t byteOffset, size_t byteLen) const
 {
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -100,16 +100,17 @@ protected:
 
     void InvalidateCacheRange(uint64_t byteOffset, uint64_t byteLength) const;
 
     Kind mContent;
     GLenum mUsage;
     size_t mByteLength;
     size_t mTFBindCount;
     size_t mNonTFBindCount;
+    uint64_t mLastUpdateFenceId = 0;
 
     struct IndexRange final {
         GLenum type;
         uint64_t byteOffset;
         uint32_t indexCount;
 
         bool operator<(const IndexRange& x) const {
             if (type != x.type)
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -207,18 +207,16 @@ ClearLinkedList(LinkedList<T>& list)
 }
 
 void
 WebGLContext::DestroyResourcesAndContext()
 {
     if (!gl)
         return;
 
-    gl->MakeCurrent();
-
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
     mBound3DTextures.Clear();
     mBound2DArrayTextures.Clear();
     mBoundSamplers.Clear();
     mBoundArrayBuffer = nullptr;
     mBoundCopyReadBuffer = nullptr;
     mBoundCopyWriteBuffer = nullptr;
@@ -893,18 +891,16 @@ WebGLContext::SetDimensions(int32_t sign
             (uint32_t)mHeight == height)
         {
             return NS_OK;
         }
 
         if (IsContextLost())
             return NS_OK;
 
-        MakeContextCurrent();
-
         // If we've already drawn, we should commit the current buffer.
         PresentScreenBuffer();
 
         if (IsContextLost()) {
             GenerateWarning("WebGL context was lost due to swap failure.");
             return NS_OK;
         }
 
@@ -1485,18 +1481,16 @@ WebGLContext::GetContextAttributes(dom::
 NS_IMETHODIMP
 WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
 {
     if (IsContextLost())
         return NS_OK;
 
     retval.SetIsVoid(true);
 
-    MakeContextCurrent();
-
     switch (pname) {
     case LOCAL_GL_VENDOR:
     case LOCAL_GL_RENDERER:
     case LOCAL_GL_VERSION:
     case LOCAL_GL_SHADING_LANGUAGE_VERSION:
     case LOCAL_GL_EXTENSIONS:
         {
             const char* s = (const char*)gl->fGetString(pname);
@@ -1509,17 +1503,16 @@ WebGLContext::MozGetUnderlyingParamStrin
     }
 
     return NS_OK;
 }
 
 void
 WebGLContext::ClearScreen()
 {
-    MakeContextCurrent();
     ScopedBindFramebuffer autoFB(gl, 0);
 
     const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
     if (changeDrawBuffers) {
         gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
     }
 
     GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
@@ -1534,18 +1527,16 @@ WebGLContext::ClearScreen()
         gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0);
     }
 }
 
 void
 WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
                                                      bool fakeNoAlpha)
 {
-    MakeContextCurrent();
-
     const bool initializeColorBuffer = bool(clearBits & LOCAL_GL_COLOR_BUFFER_BIT);
     const bool initializeDepthBuffer = bool(clearBits & LOCAL_GL_DEPTH_BUFFER_BIT);
     const bool initializeStencilBuffer = bool(clearBits & LOCAL_GL_STENCIL_BUFFER_BIT);
 
     // Fun GL fact: No need to worry about the viewport here, glViewport is just
     // setting up a coordinates transformation, it doesn't affect glClear at all.
     AssertCachedGlobalState();
 
@@ -1634,18 +1625,16 @@ WebGLContext::PresentScreenBuffer()
         return false;
     }
 
     if (!mShouldPresent) {
         return false;
     }
     MOZ_ASSERT(!mBackbufferNeedsClear);
 
-    gl->MakeCurrent();
-
     GLScreenBuffer* screen = gl->Screen();
     MOZ_ASSERT(screen);
 
     if (!screen->PublishFrame(screen->Size())) {
         ForceLoseContext();
         return false;
     }
 
@@ -1974,17 +1963,16 @@ WebGLContext::GetSurfaceSnapshot(gfxAlph
                                            : SurfaceFormat::B8G8R8X8;
     RefPtr<DataSourceSurface> surf;
     surf = Factory::CreateDataSourceSurfaceWithStride(IntSize(mWidth, mHeight),
                                                       surfFormat,
                                                       mWidth * 4);
     if (NS_WARN_IF(!surf))
         return nullptr;
 
-    gl->MakeCurrent();
     {
         ScopedBindFramebuffer autoFB(gl, 0);
         ClearBackbufferIfNeeded();
 
         // Save, override, then restore glReadBuffer.
         const GLenum readBufferMode = gl->Screen()->GetReadBufferMode();
 
         if (readBufferMode != LOCAL_GL_BACK) {
@@ -2437,17 +2425,16 @@ WebGLContext::ValidateArrayBufferView(co
     return true;
 }
 
 ////
 
 void
 WebGLContext::UpdateMaxDrawBuffers()
 {
-    gl->MakeCurrent();
     mGLMaxColorAttachments = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_COLOR_ATTACHMENTS);
     mGLMaxDrawBuffers = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_DRAW_BUFFERS);
 
     // WEBGL_draw_buffers:
     // "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
     //  equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
     mGLMaxDrawBuffers = std::min(mGLMaxDrawBuffers, mGLMaxColorAttachments);
 }
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -309,16 +309,19 @@ class WebGLContext
         UNMASKED_VENDOR_WEBGL = 0x9245,
         UNMASKED_RENDERER_WEBGL = 0x9246
     };
 
     const uint32_t mMaxPerfWarnings;
     mutable uint64_t mNumPerfWarnings;
     const uint32_t mMaxAcceptableFBStatusInvals;
 
+    uint64_t mNextFenceId = 1;
+    uint64_t mCompletedFenceId = 0;
+
 public:
     WebGLContext();
 
 protected:
     virtual ~WebGLContext();
 
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -1702,18 +1705,16 @@ public:
                                  uint8_t** const out_bytes, size_t* const out_byteLen);
 
 protected:
     ////
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
-    void MakeContextCurrent() const { } // MakeCurrent is implicit now.
-
     // helpers
 
     bool ConvertImage(size_t width, size_t height, size_t srcStride,
                       size_t dstStride, const uint8_t* src, uint8_t* dst,
                       WebGLTexelFormat srcFormat, bool srcPremultiplied,
                       WebGLTexelFormat dstFormat, bool dstPremultiplied,
                       size_t dstTexelSize);
 
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -144,17 +144,16 @@ WebGLContext::BindBuffer(GLenum target, 
 
     const auto& slot = ValidateBufferSlot(funcName, target);
     if (!slot)
         return;
 
     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
         return;
 
-    gl->MakeCurrent();
     gl->fBindBuffer(target, buffer ? buffer->mGLName : 0);
 
     WebGLBuffer::SetSlot(target, buffer, slot);
     if (buffer) {
         buffer->SetContentAfterBind(target);
     }
 
     switch (target) {
@@ -211,17 +210,16 @@ WebGLContext::BindBufferBase(GLenum targ
         return;
     }
 
     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
         return;
 
     ////
 
-    gl->MakeCurrent();
     gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0);
 
     ////
 
     WebGLBuffer::SetSlot(target, buffer, genericBinding);
     WebGLBuffer::SetSlot(target, buffer, &indexedBinding->mBufferBinding);
     indexedBinding->mRangeStart = 0;
     indexedBinding->mRangeSize = 0;
@@ -261,18 +259,16 @@ WebGLContext::BindBufferRange(GLenum tar
 
     if (buffer && !size) {
         ErrorInvalidValue("%s: size must be non-zero for non-null buffer.", funcName);
         return;
     }
 
     ////
 
-    gl->MakeCurrent();
-
     switch (target) {
     case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
         if (offset % 4 != 0 || size % 4 != 0) {
             ErrorInvalidValue("%s: For %s, `offset` and `size` must be multiples of 4.",
                               funcName, "TRANSFORM_FEEDBACK_BUFFER");
             return;
         }
         break;
@@ -443,17 +439,16 @@ WebGLContext::BufferSubData(GLenum targe
 
 already_AddRefed<WebGLBuffer>
 WebGLContext::CreateBuffer()
 {
     if (IsContextLost())
         return nullptr;
 
     GLuint buf = 0;
-    MakeContextCurrent();
     gl->fGenBuffers(1, &buf);
 
     RefPtr<WebGLBuffer> globj = new WebGLBuffer(this, buf);
     return globj.forget();
 }
 
 void
 WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
@@ -504,13 +499,12 @@ WebGLContext::DeleteBuffer(WebGLBuffer* 
 }
 
 bool
 WebGLContext::IsBuffer(WebGLBuffer* buffer)
 {
     if (!ValidateIsObject("isBuffer", buffer))
         return false;
 
-    MakeContextCurrent();
     return gl->fIsBuffer(buffer->mGLName);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -516,18 +516,16 @@ WebGLContext::DrawArrays_check(const cha
 void
 WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
                                   GLsizei instanceCount, const char* const funcName)
 {
     AUTO_PROFILER_LABEL("WebGLContext::DrawArraysInstanced", GRAPHICS);
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
-
     bool error = false;
     ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
     if (error)
         return;
 
     Maybe<uint32_t> lastVert;
     if (!DrawArrays_check(funcName, first, vertCount, instanceCount, &lastVert))
         return;
@@ -674,18 +672,16 @@ void
 WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei indexCount, GLenum type,
                                     WebGLintptr byteOffset, GLsizei instanceCount,
                                     const char* const funcName)
 {
     AUTO_PROFILER_LABEL("WebGLContext::DrawElementsInstanced", GRAPHICS);
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
-
     bool error = false;
     ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
     if (error)
         return;
 
     Maybe<uint32_t> lastVert;
     if (!DrawElements_check(funcName, indexCount, type, byteOffset, instanceCount,
                             &lastVert))
@@ -994,13 +990,12 @@ WebGLContext::FakeBlackTexture::Create(g
 WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl)
     : mGL(gl)
     , mGLName(CreateGLTexture(gl))
 {
 }
 
 WebGLContext::FakeBlackTexture::~FakeBlackTexture()
 {
-    mGL->MakeCurrent();
     mGL->fDeleteTextures(1, &mGLName);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextFramebufferOperations.cpp
+++ b/dom/canvas/WebGLContextFramebufferOperations.cpp
@@ -15,18 +15,16 @@ namespace mozilla {
 void
 WebGLContext::Clear(GLbitfield mask)
 {
     const char funcName[] = "clear";
 
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
-
     uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
     if (mask != m)
         return ErrorInvalidValue("%s: invalid mask bits", funcName);
 
     if (mask == 0) {
         GenerateWarning("Calling gl.clear(0) has no effect.");
     } else if (mRasterizerDiscardEnabled) {
         GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
@@ -74,18 +72,16 @@ GLClampFloat(GLfloat val)
 }
 
 void
 WebGLContext::ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
 {
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
-
     const bool supportsFloatColorBuffers = (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_float) ||
                                             IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) ||
                                             IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float));
     if (!supportsFloatColorBuffers) {
         r = GLClampFloat(r);
         g = GLClampFloat(g);
         b = GLClampFloat(b);
         a = GLClampFloat(a);
@@ -100,53 +96,49 @@ WebGLContext::ClearColor(GLfloat r, GLfl
 }
 
 void
 WebGLContext::ClearDepth(GLclampf v)
 {
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
     mDepthClearValue = GLClampFloat(v);
     gl->fClearDepth(mDepthClearValue);
 }
 
 void
 WebGLContext::ClearStencil(GLint v)
 {
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
     mStencilClearValue = v;
     gl->fClearStencil(v);
 }
 
 void
 WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
 {
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
     mColorWriteMask[0] = r;
     mColorWriteMask[1] = g;
     mColorWriteMask[2] = b;
     mColorWriteMask[3] = a;
     gl->fColorMask(r, g, b, a);
 }
 
 void
 WebGLContext::DepthMask(WebGLboolean b)
 {
     if (IsContextLost())
         return;
 
-    MakeContextCurrent();
     mDepthWriteMask = b;
     gl->fDepthMask(b);
 }
 
 void
 WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
 {
     const char funcName[] = "drawBuffers";
@@ -190,17 +182,16 @@ void
 WebGLContext::StencilMask(GLuint mask)
 {
     if (IsContextLost())
         return;
 
     mStencilWriteMaskFront = mask;
     mStencilWriteMaskBack = mask;
 
-    MakeContextCurrent();
     gl->fStencilMask(mask);
 }
 
 void
 WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask)
 {
     if (IsContextLost())
         return;
@@ -216,13 +207,12 @@ WebGLContext::StencilMaskSeparate(GLenum
         case LOCAL_GL_FRONT:
             mStencilWriteMaskFront = mask;
             break;
         case LOCAL_GL_BACK:
             mStencilWriteMaskBack = mask;
             break;
     }
 
-    MakeContextCurrent();
     gl->fStencilMaskSeparate(face, mask);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -88,17 +88,16 @@ WebGLContext::ActiveTexture(GLenum textu
     {
         return ErrorInvalidEnum(
             "ActiveTexture: texture unit %d out of range. "
             "Accepted values range from TEXTURE0 to TEXTURE0 + %d. "
             "Notice that TEXTURE0 != 0.",
             texture, mGLMaxTextureUnits);
     }
 
-    MakeContextCurrent();
     mActiveTexture = texture - LOCAL_GL_TEXTURE0;
     gl->fActiveTexture(texture);
 }
 
 void
 WebGLContext::AttachShader(WebGLProgram& program, WebGLShader& shader)
 {
     if (IsContextLost())
@@ -133,18 +132,16 @@ WebGLContext::BindFramebuffer(GLenum tar
         return;
 
     if (!ValidateFramebufferTarget(target, "bindFramebuffer"))
         return;
 
     if (wfb && !ValidateObject("bindFramebuffer", *wfb))
         return;
 
-    MakeContextCurrent();
-
     if (!wfb) {
         gl->fBindFramebuffer(target, 0);
     } else {
         GLuint framebuffername = wfb->mGLName;
         gl->fBindFramebuffer(target, framebuffername);
 #ifdef ANDROID
         wfb->mIsFB = true;
 #endif
@@ -193,30 +190,28 @@ WebGLContext::BindRenderbuffer(GLenum ta
 void WebGLContext::BlendEquation(GLenum mode)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateBlendEquationEnum(mode, "blendEquation: mode"))
         return;
 
-    MakeContextCurrent();
     gl->fBlendEquation(mode);
 }
 
 void WebGLContext::BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateBlendEquationEnum(modeRGB, "blendEquationSeparate: modeRGB") ||
         !ValidateBlendEquationEnum(modeAlpha, "blendEquationSeparate: modeAlpha"))
         return;
 
-    MakeContextCurrent();
     gl->fBlendEquationSeparate(modeRGB, modeAlpha);
 }
 
 static bool
 ValidateBlendFuncEnum(WebGLContext* webgl, GLenum factor, const char* funcName, const char* varName)
 {
     switch (factor) {
     case LOCAL_GL_ZERO:
@@ -275,17 +270,16 @@ void WebGLContext::BlendFunc(GLenum sfac
         return;
 
     if (!ValidateBlendFuncEnums(this, sfactor, sfactor, dfactor, dfactor, "blendFunc"))
        return;
 
     if (!ValidateBlendFuncEnumsCompatibility(sfactor, dfactor, "blendFuncSeparate: srcRGB and dstRGB"))
         return;
 
-    MakeContextCurrent();
     gl->fBlendFunc(sfactor, dfactor);
 }
 
 void
 WebGLContext::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
                                 GLenum srcAlpha, GLenum dstAlpha)
 {
     if (IsContextLost())
@@ -294,17 +288,16 @@ WebGLContext::BlendFuncSeparate(GLenum s
     if (!ValidateBlendFuncEnums(this, srcRGB, srcAlpha, dstRGB, dstAlpha, "blendFuncSeparate"))
        return;
 
     // note that we only check compatibity for the RGB enums, no need to for the Alpha enums, see
     // "Section 6.8 forgetting to mention alpha factors?" thread on the public_webgl mailing list
     if (!ValidateBlendFuncEnumsCompatibility(srcRGB, dstRGB, "blendFuncSeparate: srcRGB and dstRGB"))
         return;
 
-    MakeContextCurrent();
     gl->fBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
 }
 
 GLenum
 WebGLContext::CheckFramebufferStatus(GLenum target)
 {
     const char funcName[] = "checkFramebufferStatus";
     if (IsContextLost())
@@ -364,17 +357,16 @@ void
 WebGLContext::CullFace(GLenum face)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateFaceEnum(face, "cullFace"))
         return;
 
-    MakeContextCurrent();
     gl->fCullFace(face);
 }
 
 void
 WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
 {
     if (!ValidateDeleteObject("deleteFramebuffer", fbuf))
         return;
@@ -484,30 +476,28 @@ void
 WebGLContext::DepthFunc(GLenum func)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateComparisonEnum(func, "depthFunc"))
         return;
 
-    MakeContextCurrent();
     gl->fDepthFunc(func);
 }
 
 void
 WebGLContext::DepthRange(GLfloat zNear, GLfloat zFar)
 {
     if (IsContextLost())
         return;
 
     if (zNear > zFar)
         return ErrorInvalidOperation("depthRange: the near value is greater than the far value!");
 
-    MakeContextCurrent();
     gl->fDepthRange(zNear, zFar);
 }
 
 void
 WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
                                       GLenum rbtarget, WebGLRenderbuffer* wrb)
 {
     const char funcName[] = "framebufferRenderbuffer";
@@ -582,17 +572,16 @@ WebGLContext::FrontFace(GLenum mode)
     switch (mode) {
         case LOCAL_GL_CW:
         case LOCAL_GL_CCW:
             break;
         default:
             return ErrorInvalidEnumInfo("frontFace: mode", mode);
     }
 
-    MakeContextCurrent();
     gl->fFrontFace(mode);
 }
 
 already_AddRefed<WebGLActiveInfo>
 WebGLContext::GetActiveAttrib(const WebGLProgram& prog, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
@@ -696,18 +685,16 @@ WebGLContext::GetFramebufferAttachmentPa
     case LOCAL_GL_READ_FRAMEBUFFER:
         fb = mBoundReadFramebuffer;
         break;
 
     default:
         MOZ_CRASH("GFX: Bad target.");
     }
 
-    MakeContextCurrent();
-
     if (fb)
         return fb->GetAttachmentParameter(funcName, cx, target, attachment, pname, &rv);
 
     ////////////////////////////////////
 
     if (!IsWebGL2()) {
         ErrorInvalidOperation("%s: Querying against the default framebuffer is not"
                               " allowed in WebGL 1.",
@@ -836,18 +823,16 @@ WebGLContext::GetRenderbufferParameter(G
         return JS::NullValue();
     }
 
     if (!mBoundRenderbuffer) {
         ErrorInvalidOperation("getRenderbufferParameter: no render buffer is bound");
         return JS::NullValue();
     }
 
-    MakeContextCurrent();
-
     switch (pname) {
     case LOCAL_GL_RENDERBUFFER_SAMPLES:
         if (!IsWebGL2())
             break;
         MOZ_FALLTHROUGH;
 
     case LOCAL_GL_RENDERBUFFER_WIDTH:
     case LOCAL_GL_RENDERBUFFER_HEIGHT:
@@ -874,17 +859,16 @@ WebGLContext::GetRenderbufferParameter(G
 
 already_AddRefed<WebGLTexture>
 WebGLContext::CreateTexture()
 {
     if (IsContextLost())
         return nullptr;
 
     GLuint tex = 0;
-    MakeContextCurrent();
     gl->fGenTextures(1, &tex);
 
     RefPtr<WebGLTexture> globj = new WebGLTexture(this, tex);
     return globj.forget();
 }
 
 static GLenum
 GetAndClearError(GLenum* errorVar)
@@ -924,17 +908,16 @@ WebGLContext::GetError()
         return err;
 
     if (IsContextLost())
         return LOCAL_GL_NO_ERROR;
 
     // Either no WebGL-side error, or it's already been cleared.
     // UnderlyingGL-side errors, now.
 
-    MakeContextCurrent();
     GetAndFlushUnderlyingGLErrors();
 
     err = GetAndClearError(&mUnderlyingGLError);
     return err;
 }
 
 JS::Value
 WebGLContext::GetProgramParameter(const WebGLProgram& prog, GLenum pname)
@@ -1019,17 +1002,16 @@ WebGLContext::Hint(GLenum target, GLenum
             isValid = true;
         }
         break;
     }
 
     if (!isValid)
         return ErrorInvalidEnum("hint: invalid hint");
 
-    MakeContextCurrent();
     gl->fHint(target, mode);
 }
 
 bool
 WebGLContext::IsFramebuffer(const WebGLFramebuffer* fb)
 {
     if (!ValidateIsObject("isFramebuffer", fb))
         return false;
@@ -1037,17 +1019,16 @@ WebGLContext::IsFramebuffer(const WebGLF
 #ifdef ANDROID
     if (gl->WorkAroundDriverBugs() &&
         gl->Renderer() == GLRenderer::AndroidEmulator)
     {
         return fb->mIsFB;
     }
 #endif
 
-    MakeContextCurrent();
     return gl->fIsFramebuffer(fb->mGLName);
 }
 
 bool
 WebGLContext::IsProgram(const WebGLProgram* prog)
 {
     if (!ValidateIsObject("isProgram", prog))
         return false;
@@ -1144,17 +1125,16 @@ WebGLContext::PixelStorei(GLenum pname, 
         }
 
         if (pValueSlot) {
             if (param < 0) {
                 ErrorInvalidValue("pixelStorei: param must be >= 0.");
                 return;
             }
 
-            MakeContextCurrent();
             gl->fPixelStorei(pname, param);
             *pValueSlot = param;
             return;
         }
     }
 
     switch (pname) {
     case UNPACK_FLIP_Y_WEBGL:
@@ -1192,17 +1172,16 @@ WebGLContext::PixelStorei(GLenum pname, 
         case 2:
         case 4:
         case 8:
             if (pname == LOCAL_GL_PACK_ALIGNMENT)
                 mPixelStore_PackAlignment = param;
             else if (pname == LOCAL_GL_UNPACK_ALIGNMENT)
                 mPixelStore_UnpackAlignment = param;
 
-            MakeContextCurrent();
             gl->fPixelStorei(pname, param);
             return;
 
         default:
             ErrorInvalidValue("pixelStorei: invalid pack/unpack alignment value");
             return;
         }
 
@@ -1436,17 +1415,16 @@ WebGLContext::ReadPixels(GLint x, GLint 
     const auto bytesAvailable = buffer->ByteLength();
     const auto checkedBytesAfterOffset = CheckedUint32(bytesAvailable) - offset;
 
     uint32_t bytesAfterOffset = 0;
     if (checkedBytesAfterOffset.isValid()) {
         bytesAfterOffset = checkedBytesAfterOffset.value();
     }
 
-    gl->MakeCurrent();
     const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, buffer);
 
     ReadPixelsImpl(x, y, width, height, format, type, (void*)offset, bytesAfterOffset);
 }
 
 static webgl::PackingInfo
 DefaultReadPixelPI(const webgl::FormatUsageInfo* usage)
 {
@@ -1573,18 +1551,16 @@ WebGLContext::ReadPixelsImpl(GLint x, GL
         return;
     }
 
     const uint32_t width(rawWidth);
     const uint32_t height(rawHeight);
 
     //////
 
-    MakeContextCurrent();
-
     const webgl::FormatUsageInfo* srcFormat;
     uint32_t srcWidth;
     uint32_t srcHeight;
     if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
         return;
 
     //////
 
@@ -1727,17 +1703,16 @@ void
 WebGLContext::Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("scissor: negative size");
 
-    MakeContextCurrent();
     gl->fScissor(x, y, width, height);
 }
 
 void
 WebGLContext::StencilFunc(GLenum func, GLint ref, GLuint mask)
 {
     if (IsContextLost())
         return;
@@ -1745,17 +1720,16 @@ WebGLContext::StencilFunc(GLenum func, G
     if (!ValidateComparisonEnum(func, "stencilFunc: func"))
         return;
 
     mStencilRefFront = ref;
     mStencilRefBack = ref;
     mStencilValueMaskFront = mask;
     mStencilValueMaskBack = mask;
 
-    MakeContextCurrent();
     gl->fStencilFunc(func, ref, mask);
 }
 
 void
 WebGLContext::StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
 {
     if (IsContextLost())
         return;
@@ -1776,48 +1750,45 @@ WebGLContext::StencilFuncSeparate(GLenum
             mStencilValueMaskFront = mask;
             break;
         case LOCAL_GL_BACK:
             mStencilRefBack = ref;
             mStencilValueMaskBack = mask;
             break;
     }
 
-    MakeContextCurrent();
     gl->fStencilFuncSeparate(face, func, ref, mask);
 }
 
 void
 WebGLContext::StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateStencilOpEnum(sfail, "stencilOp: sfail") ||
         !ValidateStencilOpEnum(dpfail, "stencilOp: dpfail") ||
         !ValidateStencilOpEnum(dppass, "stencilOp: dppass"))
         return;
 
-    MakeContextCurrent();
     gl->fStencilOp(sfail, dpfail, dppass);
 }
 
 void
 WebGLContext::StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateFaceEnum(face, "stencilOpSeparate: face") ||
         !ValidateStencilOpEnum(sfail, "stencilOpSeparate: sfail") ||
         !ValidateStencilOpEnum(dpfail, "stencilOpSeparate: dpfail") ||
         !ValidateStencilOpEnum(dppass, "stencilOpSeparate: dppass"))
         return;
 
-    MakeContextCurrent();
     gl->fStencilOpSeparate(face, sfail, dpfail, dppass);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Uniform setters.
 
 class ValidateIfSampler
 {
@@ -1880,99 +1851,91 @@ WebGLContext::Uniform1i(WebGLUniformLoca
     if (!ValidateUniformSetter(loc, 1, LOCAL_GL_INT, funcName))
         return;
 
     bool error;
     const ValidateIfSampler validate(this, funcName, loc, 1, &a1, &error);
     if (error)
         return;
 
-    MakeContextCurrent();
     gl->fUniform1i(loc->mLoc, a1);
 }
 
 void
 WebGLContext::Uniform2i(WebGLUniformLocation* loc, GLint a1, GLint a2)
 {
     const char funcName[] = "uniform2i";
     if (!ValidateUniformSetter(loc, 2, LOCAL_GL_INT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform2i(loc->mLoc, a1, a2);
 }
 
 void
 WebGLContext::Uniform3i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3)
 {
     const char funcName[] = "uniform3i";
     if (!ValidateUniformSetter(loc, 3, LOCAL_GL_INT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform3i(loc->mLoc, a1, a2, a3);
 }
 
 void
 WebGLContext::Uniform4i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3,
                         GLint a4)
 {
     const char funcName[] = "uniform4i";
     if (!ValidateUniformSetter(loc, 4, LOCAL_GL_INT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform4i(loc->mLoc, a1, a2, a3, a4);
 }
 
 //////////
 
 void
 WebGLContext::Uniform1f(WebGLUniformLocation* loc, GLfloat a1)
 {
     const char funcName[] = "uniform1f";
     if (!ValidateUniformSetter(loc, 1, LOCAL_GL_FLOAT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform1f(loc->mLoc, a1);
 }
 
 void
 WebGLContext::Uniform2f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2)
 {
     const char funcName[] = "uniform2f";
     if (!ValidateUniformSetter(loc, 2, LOCAL_GL_FLOAT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform2f(loc->mLoc, a1, a2);
 }
 
 void
 WebGLContext::Uniform3f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2,
                         GLfloat a3)
 {
     const char funcName[] = "uniform3f";
     if (!ValidateUniformSetter(loc, 3, LOCAL_GL_FLOAT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform3f(loc->mLoc, a1, a2, a3);
 }
 
 void
 WebGLContext::Uniform4f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2,
                         GLfloat a3, GLfloat a4)
 {
     const char funcName[] = "uniform4f";
     if (!ValidateUniformSetter(loc, 4, LOCAL_GL_FLOAT, funcName))
         return;
 
-    MakeContextCurrent();
     gl->fUniform4f(loc->mLoc, a1, a2, a3, a4);
 }
 
 ////////////////////////////////////////
 // Array
 
 static bool
 ValidateArrOffsetAndCount(WebGLContext* webgl, const char* funcName, size_t elemsAvail,
@@ -2025,17 +1988,16 @@ WebGLContext::UniformNiv(const char* fun
     static const decltype(&gl::GLContext::fUniform1iv) kFuncList[] = {
         &gl::GLContext::fUniform1iv,
         &gl::GLContext::fUniform2iv,
         &gl::GLContext::fUniform3iv,
         &gl::GLContext::fUniform4iv
     };
     const auto func = kFuncList[N-1];
 
-    MakeContextCurrent();
     (gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
 }
 
 void
 WebGLContext::UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
                           const Uint32Arr& arr, GLuint elemOffset,
                           GLuint elemCountOverride)
 {
@@ -2058,17 +2020,16 @@ WebGLContext::UniformNuiv(const char* fu
     static const decltype(&gl::GLContext::fUniform1uiv) kFuncList[] = {
         &gl::GLContext::fUniform1uiv,
         &gl::GLContext::fUniform2uiv,
         &gl::GLContext::fUniform3uiv,
         &gl::GLContext::fUniform4uiv
     };
     const auto func = kFuncList[N-1];
 
-    MakeContextCurrent();
     (gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
 }
 
 void
 WebGLContext::UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
                          const Float32Arr& arr, GLuint elemOffset,
                          GLuint elemCountOverride)
 {
@@ -2091,17 +2052,16 @@ WebGLContext::UniformNfv(const char* fun
     static const decltype(&gl::GLContext::fUniform1fv) kFuncList[] = {
         &gl::GLContext::fUniform1fv,
         &gl::GLContext::fUniform2fv,
         &gl::GLContext::fUniform3fv,
         &gl::GLContext::fUniform4fv
     };
     const auto func = kFuncList[N-1];
 
-    MakeContextCurrent();
     (gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
 }
 
 static inline void
 MatrixAxBToRowMajor(const uint8_t width, const uint8_t height,
                     const float* __restrict srcColMajor,
                     float* __restrict dstRowMajor)
 {
@@ -2179,17 +2139,16 @@ WebGLContext::UniformMatrixAxBfv(const c
         &gl::GLContext::fUniformMatrix3x4fv,
 
         &gl::GLContext::fUniformMatrix4x2fv,
         &gl::GLContext::fUniformMatrix4x3fv,
         &gl::GLContext::fUniformMatrix4fv
     };
     const auto func = kFuncList[3*(A-2) + (B-2)];
 
-    MakeContextCurrent();
     (gl->*func)(loc->mLoc, numMatsToUpload, uploadTranspose, uploadBytes);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void
 WebGLContext::UseProgram(WebGLProgram* prog)
 {
@@ -2225,47 +2184,44 @@ WebGLContext::ValidateProgram(const WebG
 
 already_AddRefed<WebGLFramebuffer>
 WebGLContext::CreateFramebuffer()
 {
     if (IsContextLost())
         return nullptr;
 
     GLuint fbo = 0;
-    MakeContextCurrent();
     gl->fGenFramebuffers(1, &fbo);
 
     RefPtr<WebGLFramebuffer> globj = new WebGLFramebuffer(this, fbo);
     return globj.forget();
 }
 
 already_AddRefed<WebGLRenderbuffer>
 WebGLContext::CreateRenderbuffer()
 {
     if (IsContextLost())
         return nullptr;
 
-    MakeContextCurrent();
     RefPtr<WebGLRenderbuffer> globj = new WebGLRenderbuffer(this);
     return globj.forget();
 }
 
 void
 WebGLContext::Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("viewport: negative size");
 
     width = std::min(width, (GLsizei)mGLMaxViewportDims[0]);
     height = std::min(height, (GLsizei)mGLMaxViewportDims[1]);
 
-    MakeContextCurrent();
     gl->fViewport(x, y, width, height);
 
     mViewportX = x;
     mViewportY = y;
     mViewportWidth = width;
     mViewportHeight = height;
 }
 
@@ -2330,17 +2286,16 @@ WebGLContext::GetShaderPrecisionFormat(G
         case LOCAL_GL_MEDIUM_INT:
         case LOCAL_GL_HIGH_INT:
             break;
         default:
             ErrorInvalidEnumInfo("getShaderPrecisionFormat: precisiontype", precisiontype);
             return nullptr;
     }
 
-    MakeContextCurrent();
     GLint range[2], precision;
 
     if (mDisableFragHighP &&
         shadertype == LOCAL_GL_FRAGMENT_SHADER &&
         (precisiontype == LOCAL_GL_HIGH_FLOAT ||
          precisiontype == LOCAL_GL_HIGH_INT))
     {
       precision = 0;
@@ -2406,37 +2361,43 @@ WebGLContext::RestoreContext()
 
     if (!mAllowContextRestore)
         return ErrorInvalidOperation("restoreContext: Context cannot be restored.");
 
     ForceRestoreContext();
 }
 
 void
-WebGLContext::BlendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+WebGLContext::BlendColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
     if (IsContextLost())
         return;
-    MakeContextCurrent();
+
     gl->fBlendColor(r, g, b, a);
 }
 
 void
-WebGLContext::Flush() {
+WebGLContext::Flush()
+{
     if (IsContextLost())
         return;
-    MakeContextCurrent();
+
     gl->fFlush();
 }
 
 void
-WebGLContext::Finish() {
+WebGLContext::Finish()
+{
     if (IsContextLost())
         return;
-    MakeContextCurrent();
+
     gl->fFinish();
+
+    mCompletedFenceId = mNextFenceId;
+    mNextFenceId += 1;
 }
 
 void
 WebGLContext::LineWidth(GLfloat width)
 {
     if (IsContextLost())
         return;
 
@@ -2448,29 +2409,30 @@ WebGLContext::LineWidth(GLfloat width)
     }
 
     mLineWidth = width;
 
     if (gl->IsCoreProfile() && width > 1.0) {
         width = 1.0;
     }
 
-    MakeContextCurrent();
     gl->fLineWidth(width);
 }
 
 void
-WebGLContext::PolygonOffset(GLfloat factor, GLfloat units) {
+WebGLContext::PolygonOffset(GLfloat factor, GLfloat units)
+{
     if (IsContextLost())
         return;
-    MakeContextCurrent();
+
     gl->fPolygonOffset(factor, units);
 }
 
 void
-WebGLContext::SampleCoverage(GLclampf value, WebGLboolean invert) {
+WebGLContext::SampleCoverage(GLclampf value, WebGLboolean invert)
+{
     if (IsContextLost())
         return;
-    MakeContextCurrent();
+
     gl->fSampleCoverage(value, invert);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -32,17 +32,16 @@ WebGLContext::Disable(GLenum cap)
 
     realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
 
     if (trackingSlot)
     {
         *trackingSlot = 0;
     }
 
-    MakeContextCurrent();
     gl->fDisable(cap);
 }
 
 void
 WebGLContext::Enable(GLenum cap)
 {
     if (IsContextLost())
         return;
@@ -52,17 +51,16 @@ WebGLContext::Enable(GLenum cap)
 
     realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
 
     if (trackingSlot)
     {
         *trackingSlot = 1;
     }
 
-    MakeContextCurrent();
     gl->fEnable(cap);
 }
 
 bool
 WebGLContext::GetStencilBits(GLint* const out_stencilBits)
 {
     *out_stencilBits = 0;
     if (mBoundDrawFramebuffer) {
@@ -174,18 +172,16 @@ WebGLContext::GetChannelBits(const char*
 JS::Value
 WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
 {
     const char funcName[] = "getParameter";
 
     if (IsContextLost())
         return JS::NullValue();
 
-    MakeContextCurrent();
-
     if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
         if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
             return JS::Int32Value(mGLMaxColorAttachments);
 
         } else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
             return JS::Int32Value(mGLMaxDrawBuffers);
 
         } else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
@@ -612,18 +608,16 @@ void
 WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
                                   JS::MutableHandle<JS::Value> retval)
 {
     if (IsContextLost()) {
         retval.setNull();
         return;
     }
 
-    MakeContextCurrent();
-
     switch (pname) {
         case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
         {
             if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
                 ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
                 retval.setNull();
                 return;
             }
@@ -643,17 +637,16 @@ bool
 WebGLContext::IsEnabled(GLenum cap)
 {
     if (IsContextLost())
         return false;
 
     if (!ValidateCapabilityEnum(cap, "isEnabled"))
         return false;
 
-    MakeContextCurrent();
     return gl->fIsEnabled(cap);
 }
 
 bool
 WebGLContext::ValidateCapabilityEnum(GLenum cap, const char* info)
 {
     switch (cap) {
         case LOCAL_GL_BLEND:
--- a/dom/canvas/WebGLContextTextures.cpp
+++ b/dom/canvas/WebGLContextTextures.cpp
@@ -236,19 +236,16 @@ WebGLContext::BindTexture(GLenum rawTarg
     }
 
     if (!currentTexPtr) {
         ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
         return;
     }
 
     const TexTarget texTarget(rawTarget);
-
-    MakeContextCurrent();
-
     if (newTex) {
         if (!newTex->BindTexture(texTarget))
             return;
     } else {
         gl->fBindTexture(texTarget.get(), 0);
     }
 
     *currentTexPtr = newTex;
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -737,18 +737,16 @@ AssertUintParamCorrect(gl::GLContext*, G
 {
 }
 #endif
 
 void
 WebGLContext::AssertCachedBindings()
 {
 #ifdef DEBUG
-    MakeContextCurrent();
-
     GetAndFlushUnderlyingGLErrors();
 
     if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
         GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
         AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
     }
 
     // Framebuffers
@@ -804,18 +802,16 @@ WebGLContext::AssertCachedBindings()
 
     // We do not check the renderbuffer binding, because we never rely on it matching.
 }
 
 void
 WebGLContext::AssertCachedGlobalState()
 {
 #ifdef DEBUG
-    MakeContextCurrent();
-
     GetAndFlushUnderlyingGLErrors();
 
     ////////////////
 
     // Draw state
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DEPTH_TEST) == mDepthTestEnabled);
     MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
     MOZ_ASSERT_IF(IsWebGL2(),
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -481,18 +481,16 @@ WebGLContext::InitAndValidateGL(FailureR
 
     mBoundArrayBuffer = nullptr;
     mCurrentProgram = nullptr;
 
     mBoundDrawFramebuffer = nullptr;
     mBoundReadFramebuffer = nullptr;
     mBoundRenderbuffer = nullptr;
 
-    MakeContextCurrent();
-
     gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
 
     if (mGLMaxVertexAttribs < 8) {
         const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
                                      mGLMaxVertexAttribs);
         *out_failReason = { "FEATURE_FAILURE_WEBGL_V_ATRB", reason };
         return false;
     }
--- a/dom/canvas/WebGLContextVertexArray.cpp
+++ b/dom/canvas/WebGLContextVertexArray.cpp
@@ -16,18 +16,16 @@ void
 WebGLContext::BindVertexArray(WebGLVertexArray* array)
 {
     if (IsContextLost())
         return;
 
     if (array && !ValidateObject("bindVertexArrayObject", *array))
         return;
 
-    MakeContextCurrent();
-
     if (mBoundVertexArray) {
         mBoundVertexArray->AddBufferBindCounts(-1);
     }
 
     if (array == nullptr) {
         array = mDefaultVertexArray;
     }
 
@@ -42,17 +40,16 @@ WebGLContext::BindVertexArray(WebGLVerte
 already_AddRefed<WebGLVertexArray>
 WebGLContext::CreateVertexArray()
 {
     if (IsContextLost())
         return nullptr;
 
     RefPtr<WebGLVertexArray> globj = CreateVertexArrayImpl();
 
-    MakeContextCurrent();
     globj->GenVertexArray();
 
     return globj.forget();
 }
 
 WebGLVertexArray*
 WebGLContext::CreateVertexArrayImpl()
 {
@@ -72,13 +69,12 @@ WebGLContext::DeleteVertexArray(WebGLVer
 }
 
 bool
 WebGLContext::IsVertexArray(const WebGLVertexArray* array)
 {
     if (!ValidateIsObject("isVertexArray", array))
         return false;
 
-    MakeContextCurrent();
     return array->IsVertexArray();
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextVertices.cpp
+++ b/dom/canvas/WebGLContextVertices.cpp
@@ -69,17 +69,16 @@ WebGLContext::VertexAttrib4f(GLuint inde
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, funcName))
         return;
 
     ////
 
-    gl->MakeCurrent();
     if (index || !gl->IsCompatibilityProfile()) {
         gl->fVertexAttrib4f(index, x, y, z, w);
     }
 
     ////
 
     mGenericVertexAttribTypes[index] = LOCAL_GL_FLOAT;
     mGenericVertexAttribTypeInvalidator.InvalidateCaches();
@@ -101,17 +100,16 @@ WebGL2Context::VertexAttribI4i(GLuint in
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, funcName))
         return;
 
     ////
 
-    gl->MakeCurrent();
     if (index || !gl->IsCompatibilityProfile()) {
         gl->fVertexAttribI4i(index, x, y, z, w);
     }
 
     ////
 
     mGenericVertexAttribTypes[index] = LOCAL_GL_INT;
     mGenericVertexAttribTypeInvalidator.InvalidateCaches();
@@ -133,17 +131,16 @@ WebGL2Context::VertexAttribI4ui(GLuint i
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, funcName))
         return;
 
     ////
 
-    gl->MakeCurrent();
     if (index || !gl->IsCompatibilityProfile()) {
         gl->fVertexAttribI4ui(index, x, y, z, w);
     }
 
     ////
 
     mGenericVertexAttribTypes[index] = LOCAL_GL_UNSIGNED_INT;
     mGenericVertexAttribTypeInvalidator.InvalidateCaches();
@@ -160,36 +157,32 @@ void
 WebGLContext::EnableVertexAttribArray(GLuint index)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
         return;
 
-    MakeContextCurrent();
-
     gl->fEnableVertexAttribArray(index);
 
     MOZ_ASSERT(mBoundVertexArray);
     mBoundVertexArray->mAttribs[index].mEnabled = true;
     mBoundVertexArray->InvalidateCaches();
 }
 
 void
 WebGLContext::DisableVertexAttribArray(GLuint index)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, "disableVertexAttribArray"))
         return;
 
-    MakeContextCurrent();
-
     if (index || !gl->IsCompatibilityProfile()) {
         gl->fDisableVertexAttribArray(index);
     }
 
     MOZ_ASSERT(mBoundVertexArray);
     mBoundVertexArray->mAttribs[index].mEnabled = false;
     mBoundVertexArray->InvalidateCaches();
 }
@@ -202,18 +195,16 @@ WebGLContext::GetVertexAttrib(JSContext*
     if (IsContextLost())
         return JS::NullValue();
 
     if (!ValidateAttribIndex(index, funcName))
         return JS::NullValue();
 
     MOZ_ASSERT(mBoundVertexArray);
 
-    MakeContextCurrent();
-
     switch (pname) {
     case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
         return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].mBuf.get(), rv);
 
     case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
         return JS::Int32Value(mBoundVertexArray->mAttribs[index].Stride());
 
     case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
@@ -412,17 +403,16 @@ WebGLContext::VertexAttribAnyPointer(con
     if (!buffer && byteOffset) {
         ErrorInvalidOperation("%s: If ARRAY_BUFFER is null, byteOffset must be zero.",
                               funcName);
         return;
     }
 
     ////
 
-    gl->MakeCurrent();
     if (isFuncInt) {
         gl->fVertexAttribIPointer(index, size, type, stride,
                                   reinterpret_cast<void*>(byteOffset));
     } else {
         gl->fVertexAttribPointer(index, size, type, normalized, stride,
                                  reinterpret_cast<void*>(byteOffset));
     }
 
@@ -441,14 +431,12 @@ WebGLContext::VertexAttribDivisor(GLuint
 
     if (!ValidateAttribIndex(index, "vertexAttribDivisor"))
         return;
 
     MOZ_ASSERT(mBoundVertexArray);
     mBoundVertexArray->mAttribs[index].mDivisor = divisor;
     mBoundVertexArray->InvalidateCaches();
 
-    MakeContextCurrent();
-
     gl->fVertexAttribDivisor(index, divisor);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -112,17 +112,16 @@ WebGLExtensionDisjointTimerQuery::GetQue
         return;
 
     mContext->GetQueryParameter(cx, query, pname, retval, funcName);
 }
 
 bool
 WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl)
 {
-    webgl->MakeContextCurrent();
     gl::GLContext* gl = webgl->GL();
     return gl->IsSupported(gl::GLFeature::query_objects) &&
            gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
            gl->IsSupported(gl::GLFeature::query_counter); // provides GL_TIMESTAMP
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery, EXT_disjoint_timer_query)
 
--- a/dom/canvas/WebGLExtensionMOZDebug.cpp
+++ b/dom/canvas/WebGLExtensionMOZDebug.cpp
@@ -22,17 +22,16 @@ WebGLExtensionMOZDebug::~WebGLExtensionM
 }
 
 void
 WebGLExtensionMOZDebug::GetParameter(JSContext* cx, GLenum pname,
                                      JS::MutableHandle<JS::Value> retval,
                                      ErrorResult& er) const
 {
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
 
     switch (pname) {
     case LOCAL_GL_EXTENSIONS:
         {
             nsString ret;
             if (!gl->IsCoreProfile()) {
                 const auto rawExts = (const char*)gl->fGetString(LOCAL_GL_EXTENSIONS);
                 ret = NS_ConvertUTF8toUTF16(rawExts);
--- a/dom/canvas/WebGLExtensionSRGB.cpp
+++ b/dom/canvas/WebGLExtensionSRGB.cpp
@@ -16,17 +16,16 @@ WebGLExtensionSRGB::WebGLExtensionSRGB(W
     : WebGLExtensionBase(webgl)
 {
     MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 
     gl::GLContext* gl = webgl->GL();
     if (!gl->IsGLES()) {
         // Desktop OpenGL requires the following to be enabled in order to
         // support sRGB operations on framebuffers.
-        gl->MakeCurrent();
         gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
     }
 
     auto& fua = webgl->mFormatUsage;
 
     RefPtr<gl::GLContext> gl_ = gl; // Bug 1201275
     const auto fnAdd = [&fua, &gl_](webgl::EffectiveFormat effFormat, GLenum format,
                                     GLenum desktopUnpackFormat)
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -650,17 +650,16 @@ WebGLFramebuffer::Delete()
     mDepthAttachment.Clear(funcName);
     mStencilAttachment.Clear(funcName);
     mDepthStencilAttachment.Clear(funcName);
 
     for (auto& cur : mColorAttachments) {
         cur.Clear(funcName);
     }
 
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteFramebuffers(1, &mGLName);
 
     LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
 
 #ifdef ANDROID
     mIsFB = false;
 #endif
 }
@@ -1082,18 +1081,16 @@ WebGLFramebuffer::ResolveAttachmentData(
             }
 
             mContext->gl->fDrawBuffers(enumList.size(), enumList.data());
         };
 
         ////
         // Clear
 
-        mContext->MakeContextCurrent();
-
         const bool hasDrawBuffers = mContext->HasDrawBuffers();
         if (hasDrawBuffers) {
             fnDrawBuffers(colorAttachmentsToClear);
         }
 
         {
             gl::ScopedBindFramebuffer autoBind(mContext->gl, mGLName);
 
@@ -1198,17 +1195,16 @@ WebGLFramebuffer::CheckFramebufferStatus
     nsCString statusInfo;
     FBStatus ret = PrecheckFramebufferStatus(&statusInfo);
     do {
         if (ret != LOCAL_GL_FRAMEBUFFER_COMPLETE)
             break;
 
         // Looks good on our end. Let's ask the driver.
         gl::GLContext* const gl = mContext->gl;
-        gl->MakeCurrent();
 
         const ScopedFBRebinder autoFB(mContext);
         gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGLName);
 
         ////
 
         ResolveAttachments(); // OK, attach everything properly!
         RefreshDrawBuffers();
@@ -1328,18 +1324,16 @@ WebGLFramebuffer::DrawBuffers(const char
                                             " COLOR_ATTACHMENTi.",
                                             funcName);
             return;
         }
     }
 
     ////
 
-    mContext->MakeContextCurrent();
-
     mColorDrawBuffers.swap(newColorDrawBuffers);
     RefreshDrawBuffers(); // Calls glDrawBuffers.
     RefreshResolvedData();
 }
 
 void
 WebGLFramebuffer::ReadBuffer(const char* funcName, GLenum attachPoint)
 {
@@ -1353,18 +1347,16 @@ WebGLFramebuffer::ReadBuffer(const char*
             mContext->ErrorInvalidEnum(text, funcName);
         }
         return;
     }
     const auto& attach = maybeAttach.value(); // Might be nullptr.
 
     ////
 
-    mContext->MakeContextCurrent();
-
     mColorReadBuffer = attach;
     RefreshReadBuffer(); // Calls glReadBuffer.
     RefreshResolvedData();
 }
 
 ////
 
 void
@@ -1931,17 +1923,16 @@ WebGLFramebuffer::BlitFramebuffer(WebGLC
         }
     } else if (!srcFB && !dstFB) {
         webgl->ErrorInvalidOperation("%s: Feedback with default framebuffer.", funcName);
         return;
     }
 
     ////
 
-    gl->MakeCurrent();
     webgl->OnBeforeReadCall();
     WebGLContext::ScopedDrawCallWrapper wrapper(*webgl);
     gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
                          dstX0, dstY0, dstX1, dstY1,
                          mask, filter);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -555,43 +555,34 @@ webgl::LinkedProgramInfo::GetDrawFetchLi
     // --
 
     return mDrawFetchCache.Insert(vao.get(), Move(fetchLimits), Move(cacheDeps));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // WebGLProgram
 
-static GLuint
-CreateProgram(gl::GLContext* gl)
-{
-    gl->MakeCurrent();
-    return gl->fCreateProgram();
-}
-
 WebGLProgram::WebGLProgram(WebGLContext* webgl)
     : WebGLRefCountedObject(webgl)
-    , mGLName(CreateProgram(webgl->GL()))
+    , mGLName(webgl->gl->fCreateProgram())
     , mNumActiveTFOs(0)
     , mNextLink_TransformFeedbackBufferMode(LOCAL_GL_INTERLEAVED_ATTRIBS)
 {
     mContext->mPrograms.insertBack(this);
 }
 
 WebGLProgram::~WebGLProgram()
 {
     DeleteOnce();
 }
 
 void
 WebGLProgram::Delete()
 {
     gl::GLContext* gl = mContext->GL();
-
-    gl->MakeCurrent();
     gl->fDeleteProgram(mGLName);
 
     mVertShader = nullptr;
     mFragShader = nullptr;
 
     mMostRecentLinkInfo = nullptr;
 
     LinkedListElement<WebGLProgram>::removeFrom(mContext->mPrograms);
@@ -623,17 +614,16 @@ WebGLProgram::AttachShader(WebGLShader* 
             mContext->ErrorInvalidOperation("attachShader: Only one of each type of"
                                             " shader may be attached to a program.");
         }
         return;
     }
 
     *shaderSlot = shader;
 
-    mContext->MakeContextCurrent();
     mContext->gl->fAttachShader(mGLName, shader->mGLName);
 }
 
 void
 WebGLProgram::BindAttribLocation(GLuint loc, const nsAString& name)
 {
     if (!ValidateGLSLVariableName(name, mContext, "bindAttribLocation"))
         return;
@@ -681,17 +671,16 @@ WebGLProgram::DetachShader(const WebGLSh
 
     if (*shaderSlot != shader) {
         mContext->ErrorInvalidOperation("detachShader: `shader` is not attached.");
         return;
     }
 
     *shaderSlot = nullptr;
 
-    mContext->MakeContextCurrent();
     mContext->gl->fDetachShader(mGLName, shader->mGLName);
 }
 
 already_AddRefed<WebGLActiveInfo>
 WebGLProgram::GetActiveAttrib(GLuint index) const
 {
     if (!mMostRecentLinkInfo) {
         RefPtr<WebGLActiveInfo> ret = WebGLActiveInfo::CreateInvalid(mContext);
@@ -780,22 +769,19 @@ WebGLProgram::GetFragDataLocation(const 
     if (!ValidateGLSLVariableName(userName_wide, mContext, "getFragDataLocation"))
         return -1;
 
     if (!IsLinked()) {
         mContext->ErrorInvalidOperation("getFragDataLocation: `program` must be linked.");
         return -1;
     }
 
-
-    const auto& gl = mContext->gl;
-    gl->MakeCurrent();
-
     const NS_LossyConvertUTF16toASCII userName(userName_wide);
 #ifdef XP_MACOSX
+    const auto& gl = mContext->gl;
     if (gl->WorkAroundDriverBugs()) {
         // OSX doesn't return locs for indexed names, just the base names.
         // Indicated by failure in: conformance2/programs/gl-get-frag-data-location.html
         bool isArray;
         size_t arrayIndex;
         nsCString baseUserName;
         if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
             return -1;
@@ -824,17 +810,16 @@ GetProgramiv(gl::GLContext* gl, GLuint p
     gl->fGetProgramiv(program, pname, &ret);
     return ret;
 }
 
 JS::Value
 WebGLProgram::GetProgramParameter(GLenum pname) const
 {
     gl::GLContext* gl = mContext->gl;
-    gl->MakeCurrent();
 
     if (mContext->IsWebGL2()) {
         switch (pname) {
         case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS:
             if (!IsLinked())
                 return JS::NumberValue(0);
             return JS::NumberValue(LinkInfo()->uniformBlocks.size());
 
@@ -907,17 +892,16 @@ WebGLProgram::GetUniformBlockIndex(const
         }
     }
     if (!info)
         return LOCAL_GL_INVALID_INDEX;
 
     const auto& mappedName = info->mMappedName;
 
     gl::GLContext* gl = mContext->GL();
-    gl->MakeCurrent();
     return gl->fGetUniformBlockIndex(mGLName, mappedName.BeginReading());
 }
 
 void
 WebGLProgram::GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& retval) const
 {
     if (!IsLinked()) {
         mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked.");
@@ -1029,17 +1013,16 @@ WebGLProgram::GetUniformLocation(const n
     // uniform array, or the name of the uniform array appended with "[0]".
     nsCString mappedName;
     size_t arrayIndex;
     webgl::UniformInfo* info;
     if (!LinkInfo()->FindUniform(userName, &mappedName, &arrayIndex, &info))
         return nullptr;
 
     gl::GLContext* gl = mContext->GL();
-    gl->MakeCurrent();
 
     GLint loc = gl->fGetUniformLocation(mGLName, mappedName.BeginReading());
     if (loc == -1)
         return nullptr;
 
     RefPtr<WebGLUniformLocation> locObj = new WebGLUniformLocation(mContext, LinkInfo(),
                                                                    info, loc, arrayIndex);
     return locObj.forget();
@@ -1054,17 +1037,16 @@ WebGLProgram::GetUniformIndices(const do
         mContext->ErrorInvalidOperation("%s: `program` must be linked.", funcName);
         return;
     }
 
     size_t count = uniformNames.Length();
     nsTArray<GLuint>& arr = retval.SetValue();
 
     gl::GLContext* gl = mContext->GL();
-    gl->MakeCurrent();
 
     for (size_t i = 0; i < count; i++) {
         const NS_LossyConvertUTF16toASCII userName(uniformNames[i]);
 
         nsCString mappedName;
         size_t arrayIndex;
         webgl::UniformInfo* info;
         if (!LinkInfo()->FindUniform(userName, &mappedName, &arrayIndex, &info)) {
@@ -1103,17 +1085,16 @@ WebGLProgram::UniformBlockBinding(GLuint
                                     uniformBlockBinding);
         return;
     }
     const auto& indexedBinding = indexedBindings[uniformBlockBinding];
 
     ////
 
     gl::GLContext* gl = mContext->GL();
-    gl->MakeCurrent();
     gl->fUniformBlockBinding(mGLName, uniformBlockIndex, uniformBlockBinding);
 
     ////
 
     uniformBlock->mBinding = &indexedBinding;
 }
 
 bool
@@ -1165,17 +1146,16 @@ WebGLProgram::LinkProgram()
 
     if (mNumActiveTFOs) {
         mContext->ErrorInvalidOperation("%s: Program is in-use by one or more active"
                                         " transform feedback objects.",
                                         funcName);
         return;
     }
 
-    mContext->MakeContextCurrent();
     // as some of the validation changes program state
 
     mLinkLog.Truncate();
     mMostRecentLinkInfo = nullptr;
 
     if (!ValidateForLink()) {
         mContext->GenerateWarning("%s: %s", funcName, mLinkLog.BeginReading());
         return;
@@ -1459,26 +1439,23 @@ WebGLProgram::UseProgram() const
         mContext->mBoundTransformFeedback->mIsActive &&
         !mContext->mBoundTransformFeedback->mIsPaused)
     {
         mContext->ErrorInvalidOperation("%s: Transform feedback active and not paused.",
                                         funcName);
         return false;
     }
 
-    mContext->MakeContextCurrent();
-
     mContext->gl->fUseProgram(mGLName);
     return true;
 }
 
 void
 WebGLProgram::ValidateProgram() const
 {
-    mContext->MakeContextCurrent();
     gl::GLContext* gl = mContext->gl;
 
 #ifdef XP_MACOSX
     // See bug 593867 for NVIDIA and bug 657201 for ATI. The latter is confirmed
     // with Mac OS 10.6.7.
     if (gl->WorkAroundDriverBugs()) {
         mContext->GenerateWarning("validateProgram: Implemented as a no-op on"
                                   " Mac to work around crashes.");
@@ -1557,17 +1534,16 @@ WebGLProgram::FindUniformByMappedName(co
 
 void
 WebGLProgram::TransformFeedbackVaryings(const dom::Sequence<nsString>& varyings,
                                         GLenum bufferMode)
 {
     const char funcName[] = "transformFeedbackVaryings";
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
 
     switch (bufferMode) {
     case LOCAL_GL_INTERLEAVED_ATTRIBS:
         break;
 
     case LOCAL_GL_SEPARATE_ATTRIBS:
         {
             GLuint maxAttribs = 0;
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -31,18 +31,16 @@ public:
     }
 };
 
 ////
 
 static GLuint
 GenQuery(gl::GLContext* gl)
 {
-    gl->MakeCurrent();
-
     GLuint ret = 0;
     gl->fGenQueries(1, &ret);
     return ret;
 }
 
 WebGLQuery::WebGLQuery(WebGLContext* webgl)
     : WebGLRefCountedObject(webgl)
     , mGLName(GenQuery(mContext->gl))
@@ -51,17 +49,16 @@ WebGLQuery::WebGLQuery(WebGLContext* web
     , mCanBeAvailable(false)
 {
     mContext->mQueries.insertBack(this);
 }
 
 void
 WebGLQuery::Delete()
 {
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteQueries(1, &mGLName);
     LinkedListElement<WebGLQuery>::removeFrom(mContext->mQueries);
 }
 
 static void
 DispatchAvailableRunnable(WebGLQuery* query)
 {
     RefPtr<AvailableRunnable> runnable = new AvailableRunnable(query);
@@ -111,33 +108,31 @@ WebGLQuery::BeginQuery(GLenum target, We
 
     mTarget = target;
     mActiveSlot = &slot;
     *mActiveSlot = this;
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
 
     const auto driverTarget = TargetForDriver(gl, mTarget);
     gl->fBeginQuery(driverTarget, mGLName);
 }
 
 void
 WebGLQuery::EndQuery()
 {
     *mActiveSlot = nullptr;
     mActiveSlot = nullptr;
     mCanBeAvailable = false;
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
 
     const auto driverTarget = TargetForDriver(gl, mTarget);
     gl->fEndQuery(driverTarget);
 
     ////
 
     DispatchAvailableRunnable(this);
 }
@@ -173,17 +168,16 @@ WebGLQuery::GetQueryParameter(GLenum pna
     if (!canBeAvailable) {
         if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
             retval.set(JS::BooleanValue(false));
         }
         return;
     }
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
 
     uint64_t val = 0;
     switch (pname) {
     case LOCAL_GL_QUERY_RESULT_AVAILABLE:
         gl->fGetQueryObjectuiv(mGLName, pname, (GLuint*)&val);
         retval.set(JS::BooleanValue(bool(val)));
         return;
 
@@ -256,17 +250,16 @@ WebGLQuery::QueryCounter(const char* fun
         mContext->ErrorInvalidOperation("%s: Queries cannot change targets.", funcName);
         return;
     }
 
     mTarget = target;
     mCanBeAvailable = false;
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     gl->fQueryCounter(mGLName, mTarget);
 
     DispatchAvailableRunnable(this);
 }
 
 ////
 
 JSObject*
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -57,18 +57,16 @@ WebGLRenderbuffer::WebGLRenderbuffer(Web
     , mHasBeenBound(false)
 {
     mContext->mRenderbuffers.insertBack(this);
 }
 
 void
 WebGLRenderbuffer::Delete()
 {
-    mContext->MakeContextCurrent();
-
     mContext->gl->fDeleteRenderbuffers(1, &mPrimaryRB);
     if (mSecondaryRB)
         mContext->gl->fDeleteRenderbuffers(1, &mSecondaryRB);
 
     LinkedListElement<WebGLRenderbuffer>::removeFrom(mContext->mRenderbuffers);
 }
 
 int64_t
@@ -192,18 +190,16 @@ WebGLRenderbuffer::RenderbufferStorage(c
         height > mContext->mGLMaxRenderbufferSize)
     {
         mContext->ErrorInvalidValue("%s: Width or height exceeds maximum renderbuffer"
                                     " size.",
                                     funcName);
         return;
     }
 
-    mContext->MakeContextCurrent();
-
     if (!usage->maxSamplesKnown) {
         const_cast<webgl::FormatUsageInfo*>(usage)->ResolveMaxSamples(mContext->gl);
     }
     MOZ_ASSERT(usage->maxSamplesKnown);
 
     if (samples > usage->maxSamples) {
         mContext->ErrorInvalidOperation("%s: `samples` is out of the valid range.", funcName);
         return;
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -30,17 +30,16 @@ WebGLSampler::WebGLSampler(WebGLContext*
 WebGLSampler::~WebGLSampler()
 {
     DeleteOnce();
 }
 
 void
 WebGLSampler::Delete()
 {
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteSamplers(1, &mGLName);
 
     removeFrom(mContext->mSamplers);
 }
 
 WebGLContext*
 WebGLSampler::GetParentObject() const
 {
@@ -192,17 +191,16 @@ WebGLSampler::SamplerParameter(const cha
 
     for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
         if (this == mContext->mBoundSamplers[i])
             mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
     }
 
     ////
 
-    mContext->gl->MakeCurrent();
     if (param.isFloat) {
         mContext->gl->fSamplerParameterf(mGLName, pname, param.f);
     } else {
         mContext->gl->fSamplerParameteri(mGLName, pname, param.i);
     }
 }
 
 ////
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -128,26 +128,19 @@ GetCompilationStatusAndLog(gl::GLContext
         out_log->SetLength(0);
     }
 
     *out_success = (compileStatus == LOCAL_GL_TRUE);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static GLuint
-CreateShader(gl::GLContext* gl, GLenum type)
-{
-    gl->MakeCurrent();
-    return gl->fCreateShader(type);
-}
-
 WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
     : WebGLRefCountedObject(webgl)
-    , mGLName(CreateShader(webgl->GL(), type))
+    , mGLName(webgl->gl->fCreateShader(type))
     , mType(type)
     , mTranslationSuccessful(false)
     , mCompilationSuccessful(false)
 {
     mContext->mShaders.insertBack(this);
 }
 
 WebGLShader::~WebGLShader()
@@ -224,18 +217,16 @@ WebGLShader::CompileShader()
                                              &mValidationLog, &mTranslatedSource);
     }
 
     if (!success)
         return;
 
     mTranslationSuccessful = true;
 
-    gl->MakeCurrent();
-
     const char* const parts[] = {
         mTranslatedSource.BeginReading()
     };
     gl->fShaderSource(mGLName, ArrayLength(parts), parts, nullptr);
 
     gl->fCompileShader(mGLName);
 
     GetCompilationStatusAndLog(gl, mGLName, &mCompilationSuccessful, &mCompilationLog);
@@ -443,17 +434,16 @@ WebGLShader::SizeOfIncludingThis(MallocS
            mCompilationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf);
 }
 
 void
 WebGLShader::Delete()
 {
     gl::GLContext* gl = mContext->GL();
 
-    gl->MakeCurrent();
     gl->fDeleteShader(mGLName);
 
     LinkedListElement<WebGLShader>::removeFrom(mContext->mShaders);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLShader)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLShader, AddRef)
--- a/dom/canvas/WebGLSync.cpp
+++ b/dom/canvas/WebGLSync.cpp
@@ -8,41 +8,49 @@
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
 WebGLSync::WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags)
     : WebGLRefCountedObject(webgl)
+    , mGLName(mContext->gl->fFenceSync(condition, flags))
+    , mFenceId(mContext->mNextFenceId)
 {
-   mContext->mSyncs.insertBack(this);
-   mGLName = mContext->gl->fFenceSync(condition, flags);
+    mContext->mNextFenceId += 1;
+    mContext->mSyncs.insertBack(this);
 }
 
 WebGLSync::~WebGLSync()
 {
     DeleteOnce();
 }
 
 void
 WebGLSync::Delete()
 {
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteSync(mGLName);
-    mGLName = 0;
     LinkedListElement<WebGLSync>::removeFrom(mContext->mSyncs);
 }
 
 WebGLContext*
 WebGLSync::GetParentObject() const
 {
     return mContext;
 }
 
+void
+WebGLSync::MarkSignaled() const
+{
+    if (mContext->mCompletedFenceId < mFenceId) {
+        mContext->mCompletedFenceId = mFenceId;
+    }
+}
+
 // -------------------------------------------------------------------------
 // IMPLEMENT NS
 JSObject*
 WebGLSync::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLSyncBinding::Wrap(cx, this, givenProto);
 }
 
--- a/dom/canvas/WebGLSync.h
+++ b/dom/canvas/WebGLSync.h
@@ -14,28 +14,31 @@ namespace mozilla {
 
 class WebGLSync final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLSync>
     , public LinkedListElement<WebGLSync>
 {
     friend class WebGL2Context;
 
+    const GLsync mGLName;
+    const uint64_t mFenceId;
+
 public:
     WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags);
 
     void Delete();
     WebGLContext* GetParentObject() const;
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSync)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSync)
 
+    void MarkSignaled() const;
+
 private:
     ~WebGLSync();
-
-    GLsync mGLName;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_SYNC_H_
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -147,17 +147,16 @@ WebGLTexture::WebGLTexture(WebGLContext*
 void
 WebGLTexture::Delete()
 {
     const char funcName[] = "WebGLTexture::Delete";
     for (auto& cur : mImageInfoArr) {
         cur.Clear(funcName);
     }
 
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteTextures(1, &mGLName);
 
     LinkedListElement<WebGLTexture>::removeFrom(mContext->mTextures);
 }
 
 size_t
 WebGLTexture::MemoryUsage() const
 {
@@ -642,17 +641,16 @@ ZeroTextureData(WebGLContext* webgl, con
     // We have no sympathy for any of these cases.
 
     // "Doctor, it hurts when I do this!" "Well don't do that!"
     webgl->GenerateWarning("%s: This operation requires zeroing texture data. This is"
                            " slow.",
                            funcName);
 
     gl::GLContext* gl = webgl->GL();
-    gl->MakeCurrent();
 
     GLenum scopeBindTarget;
     switch (target.get()) {
     case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
     case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
     case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
     case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
     case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
@@ -933,17 +931,16 @@ WebGLTexture::GenerateMipmap(TexTarget t
                                         " internal format or is not"
                                         " color-renderable or texture-filterable.",
                                         funcName);
         return;
     }
 
     // Done with validation. Do the operation.
 
-    mContext->MakeContextCurrent();
     gl::GLContext* gl = mContext->gl;
 
     if (gl->WorkAroundDriverBugs()) {
         // bug 696495 - to work around failures in the texture-mips.html test on various drivers, we
         // set the minification filter before calling glGenerateMipmap. This should not carry a significant performance
         // overhead so we do it unconditionally.
         //
         // note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See Chromium bug 101105.
@@ -961,18 +958,16 @@ WebGLTexture::GenerateMipmap(TexTarget t
     // mBaseMipmapLevel if the min filter doesn't require mipmaps.
     const uint32_t maxLevel = mBaseMipmapLevel + baseImageInfo.PossibleMipmapLevels() - 1;
     PopulateMipChain(funcName, mBaseMipmapLevel, maxLevel);
 }
 
 JS::Value
 WebGLTexture::GetTexParameter(TexTarget texTarget, GLenum pname)
 {
-    mContext->MakeContextCurrent();
-
     GLint i = 0;
     GLfloat f = 0.0f;
 
     switch (pname) {
     case LOCAL_GL_TEXTURE_MIN_FILTER:
         return JS::NumberValue(uint32_t(mMinFilter.get()));
 
     case LOCAL_GL_TEXTURE_MAG_FILTER:
@@ -1218,17 +1213,16 @@ WebGLTexture::TexParameter(TexTarget tex
 
     default:
         InvalidateResolveCache();
         break;
     }
 
     ////////////////
 
-    mContext->MakeContextCurrent();
     if (!clamped.isFloat)
         mContext->gl->fTexParameteri(texTarget.get(), pname, clamped.i);
     else
         mContext->gl->fTexParameterf(texTarget.get(), pname, clamped.f);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1150,18 +1150,16 @@ WebGLTexture::TexStorage(const char* fun
                                         " depth: %u)",
                                         funcName, levels, width, height, depth);
         return;
     }
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
-
     GLenum error = DoTexStorage(mContext->gl, target.get(), levels, sizedFormat, width,
                                 height, depth);
 
     mContext->OnDataAllocCall();
 
     if (error == LOCAL_GL_OUT_OF_MEMORY) {
         mContext->ErrorOutOfMemory("%s: Ran out of memory during texture allocation.",
                                    funcName);
@@ -1264,19 +1262,16 @@ WebGLTexture::TexImage(const char* funcN
                                             funcName, dstFormat->name);
             return;
         }
     }
 
     ////////////////////////////////////
     // Do the thing!
 
-    MOZ_ALWAYS_TRUE( mContext->gl->MakeCurrent() );
-    MOZ_ASSERT(mContext->gl->IsCurrent());
-
     // It's tempting to do allocation first, and TexSubImage second, but this is generally
     // slower.
 
     const ImageInfo newImageInfo(dstUsage, blob->mWidth, blob->mHeight, blob->mDepth,
                                  blob->HasData());
 
     const bool isSubImage = false;
     const bool needsRespec = (imageInfo->mWidth  != newImageInfo.mWidth ||
@@ -1358,18 +1353,16 @@ WebGLTexture::TexSubImage(const char* fu
                                         " %s and 0x%04x/0x%04x",
                                         funcName, dstFormat->name, pi.format, pi.type);
         return;
     }
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
-
     bool uploadWillInitialize;
     if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
                                              yOffset, zOffset, blob->mWidth,
                                              blob->mHeight, blob->mDepth, imageInfo,
                                              &uploadWillInitialize))
     {
         return;
     }
@@ -1491,17 +1484,16 @@ WebGLTexture::CompressedTexImage(const c
                                                 blob->mDepth))
     {
         return;
     }
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
     const ScopedLazyBind bindPBO(mContext->gl, LOCAL_GL_PIXEL_UNPACK_BUFFER,
                                  mContext->mBoundPixelUnpackBuffer);
 
     // Warning: Possibly shared memory.  See bug 1225033.
     GLenum error = DoCompressedTexImage(mContext->gl, target, level, internalFormat,
                                         blob->mWidth, blob->mHeight, blob->mDepth,
                                         blob->mAvailBytes, blob->mPtr);
     mContext->OnDataAllocCall();
@@ -1634,18 +1626,16 @@ WebGLTexture::CompressedTexSubImage(cons
             return;
         }
         break;
     }
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
-
     bool uploadWillInitialize;
     if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
                                              yOffset, zOffset, blob->mWidth,
                                              blob->mHeight, blob->mDepth, imageInfo,
                                              &uploadWillInitialize))
     {
         return;
     }
@@ -2160,17 +2150,16 @@ WebGLTexture::CopyTexImage2D(TexImageTar
     }
 
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
     mContext->OnBeforeReadCall();
 
     const bool isSubImage = false;
     if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
                              srcTotalWidth, srcTotalHeight, srcUsage, 0, 0, 0, width,
                              height, dstUsage))
     {
         return;
@@ -2240,17 +2229,16 @@ WebGLTexture::CopyTexSubImage(const char
 
     auto srcFormat = srcUsage->format;
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
-    mContext->gl->MakeCurrent();
     mContext->OnBeforeReadCall();
 
     bool uploadWillInitialize;
     if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
                                              yOffset, zOffset, width, height, depth,
                                              imageInfo, &uploadWillInitialize))
     {
         return;
--- a/dom/canvas/WebGLTransformFeedback.cpp
+++ b/dom/canvas/WebGLTransformFeedback.cpp
@@ -26,17 +26,16 @@ WebGLTransformFeedback::~WebGLTransformF
 {
     DeleteOnce();
 }
 
 void
 WebGLTransformFeedback::Delete()
 {
     if (mGLName) {
-        mContext->MakeContextCurrent();
         mContext->gl->fDeleteTransformFeedbacks(1, &mGLName);
     }
     removeFrom(mContext->mTransformFeedbacks);
 }
 
 ////////////////////////////////////////
 
 void
@@ -88,17 +87,16 @@ WebGLTransformFeedback::BeginTransformFe
 
         const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert;
         minVertCapacity = std::min(minVertCapacity, vertCapacity);
     }
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     gl->fBeginTransformFeedback(primMode);
 
     ////
 
     mIsActive = true;
     MOZ_ASSERT(!mIsPaused);
 
     mActive_Program = prog;
@@ -118,17 +116,16 @@ WebGLTransformFeedback::EndTransformFeed
     const char funcName[] = "endTransformFeedback";
 
     if (!mIsActive)
         return mContext->ErrorInvalidOperation("%s: Not active.", funcName);
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     gl->fEndTransformFeedback();
 
     ////
 
     mIsActive = false;
     mIsPaused = false;
 
     ////
@@ -146,17 +143,16 @@ WebGLTransformFeedback::PauseTransformFe
     {
         mContext->ErrorInvalidOperation("%s: Not active or is paused.", funcName);
         return;
     }
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     gl->fPauseTransformFeedback();
 
     ////
 
     mIsPaused = true;
 }
 
 void
@@ -171,17 +167,16 @@ WebGLTransformFeedback::ResumeTransformF
         mContext->ErrorInvalidOperation("%s: Active program differs from original.",
                                         funcName);
         return;
     }
 
     ////
 
     const auto& gl = mContext->gl;
-    gl->MakeCurrent();
     gl->fResumeTransformFeedback();
 
     ////
 
     MOZ_ASSERT(mIsActive);
     mIsPaused = false;
 }
 
--- a/dom/canvas/WebGLUniformLocation.cpp
+++ b/dom/canvas/WebGLUniformLocation.cpp
@@ -184,17 +184,16 @@ WebGLUniformLocation::GetUniform(JSConte
 
     const uint8_t elemSize = mInfo->mActiveInfo->mElemSize;
     static const uint8_t kMaxElemSize = 16;
     MOZ_ASSERT(elemSize <= kMaxElemSize);
 
     GLuint prog = mLinkInfo->prog->mGLName;
 
     gl::GLContext* gl = mContext->GL();
-    gl->MakeCurrent();
 
     switch (mInfo->mActiveInfo->mElemType) {
     case LOCAL_GL_INT:
     case LOCAL_GL_INT_VEC2:
     case LOCAL_GL_INT_VEC3:
     case LOCAL_GL_INT_VEC4:
     case LOCAL_GL_SAMPLER_2D:
     case LOCAL_GL_SAMPLER_3D:
--- a/dom/canvas/WebGLVertexArrayGL.cpp
+++ b/dom/canvas/WebGLVertexArrayGL.cpp
@@ -20,17 +20,16 @@ WebGLVertexArrayGL::~WebGLVertexArrayGL(
     DeleteOnce();
 }
 
 void
 WebGLVertexArrayGL::DeleteImpl()
 {
     mElementArrayBuffer = nullptr;
 
-    mContext->MakeContextCurrent();
     mContext->gl->fDeleteVertexArrays(1, &mGLName);
 
     mIsVAO = false;
 }
 
 void
 WebGLVertexArrayGL::BindVertexArrayImpl()
 {
@@ -50,13 +49,12 @@ bool
 WebGLVertexArrayGL::IsVertexArrayImpl() const
 {
     gl::GLContext* gl = mContext->gl;
     if (gl->WorkAroundDriverBugs())
     {
         return mIsVAO;
     }
 
-    mContext->MakeContextCurrent();
     return mContext->gl->fIsVertexArray(mGLName) != 0;
 }
 
 } // namespace mozilla
--- a/dom/canvas/test/webgl-mochitest/mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest/mochitest.ini
@@ -104,8 +104,9 @@ skip-if = toolkit == 'android' #bug 8654
 [test_video_fastpath_mp4.html]
 [test_video_fastpath_theora.html]
 [test_video_fastpath_vp8.html]
 [test_video_fastpath_vp9.html]
 [test_webglcontextcreationerror.html]
 [test_webgl_fingerprinting_resistance.html]
 fail-if = (os == 'mac') # on try server, LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE = 512 on mac
 [test_without_index_validation.html]
+[test_vertexattrib4f_update.html]
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_vertexattrib4f_update.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Bug 1426289 - vertexAttrib4f should actually update.</title>
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' href='/tests/SimpleTest/test.css'>
+    <script src='webgl-util.js'></script>
+  </head>
+  <body>
+    <script id='eVertSource' type='none'>
+attribute vec4 aColor;
+varying vec4 vColor;
+
+void main() {
+  gl_PointSize = 64.0;
+  gl_Position = vec4(vec3(0.0), 1.0);
+  vColor = aColor;
+}
+    </script>
+    <script id='eFragSource' type='none'>
+precision mediump float;
+varying vec4 vColor;
+
+void main() {
+  gl_FragColor = vColor;
+}
+    </script>
+    <script>
+const canvas = document.createElement('canvas');
+canvas.width = 1;
+canvas.height = 1;
+const gl = canvas.getContext('webgl');
+
+const prog = WebGLUtil.linkProgramByIds(gl, eVertSource, eFragSource);
+gl.useProgram(prog);
+
+function getRgb() {
+  const data = new Uint32Array(1);
+  gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(data.buffer));
+  return data[0] & 0xffffff;
+}
+
+gl.clearColor(0.0, 0.0, 0.0, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+let was = getRgb();
+ok(was == 0x000000, '0x'+was.toString(16));
+
+gl.disableVertexAttribArray(prog.aColor);
+
+gl.vertexAttrib4f(prog.aColor, 1, 0, 0, 1);
+gl.drawArrays(gl.POINTS, 0, 1);
+was = getRgb();
+ok(was == 0x0000ff, '0x'+was.toString(16));
+
+gl.vertexAttrib4f(prog.aColor, 0, 1, 0, 1);
+gl.drawArrays(gl.POINTS, 0, 1);
+was = getRgb();
+ok(was == 0x00ff00, '0x'+was.toString(16));
+    </script>
+  </body>
+</html>
--- a/dom/canvas/test/webgl-mochitest/webgl-util.js
+++ b/dom/canvas/test/webgl-mochitest/webgl-util.js
@@ -161,10 +161,49 @@ WebGLUtil = (function() {
   return {
     setErrorFunc: setErrorFunc,
     setWarningFunc: setWarningFunc,
 
     getWebGL: getWebGL,
     withWebGL2: withWebGL2,
     createShaderById: createShaderById,
     createProgramByIds: createProgramByIds,
+
+
+    linkProgramByIds: function(gl, vertSrcElem, fragSrcElem) {
+      const prog = gl.createProgram();
+
+      function attachShaderById(type, srcElem) {
+        const shader = gl.createShader(type);
+        gl.shaderSource(shader, srcElem.innerHTML.trim() + '\n');
+        gl.compileShader(shader);
+        gl.attachShader(prog, shader);
+        prog[type] = shader;
+      }
+      attachShaderById(gl.VERTEX_SHADER, vertSrcElem);
+      attachShaderById(gl.FRAGMENT_SHADER, fragSrcElem);
+
+      gl.linkProgram(prog);
+      const success = gl.getProgramParameter(prog, gl.LINK_STATUS);
+      if (!success) {
+        console.error('Error linking program:');
+        console.error('\nLink log: ' + gl.getProgramInfoLog(prog));
+        console.error('\nVert shader log: ' + gl.getShaderInfoLog(prog[gl.VERTEX_SHADER]));
+        console.error('\nFrag shader log: ' + gl.getShaderInfoLog(prog[gl.FRAGMENT_SHADER]));
+        return null;
+      }
+      gl.deleteShader(prog[gl.VERTEX_SHADER]);
+      gl.deleteShader(prog[gl.FRAGMENT_SHADER]);
+
+      let count = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
+      for (let i = 0; i < count; i++) {
+        const info = gl.getActiveAttrib(prog, i);
+        prog[info.name] = gl.getAttribLocation(prog, info.name);
+      }
+      count = gl.getProgramParameter(prog, gl.ACTIVE_UNIFORMS);
+      for (let i = 0; i < count; i++) {
+        const info = gl.getActiveUniform(prog, i);
+        prog[info.name] = gl.getUniformLocation(prog, info.name);
+      }
+      return prog;
+    },
   };
 })();
--- a/dom/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -672,10 +672,25 @@ ClientSource::Traverse(nsCycleCollection
                                 aName, aFlags);
   } else if (mOwner.is<nsCOMPtr<nsIDocShell>>()) {
     ImplCycleCollectionTraverse(aCallback,
                                 mOwner.as<nsCOMPtr<nsIDocShell>>(),
                                 aName, aFlags);
   }
 }
 
+void
+ClientSource::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  if (mRegisteringScopeList.Contains(aScope)) {
+    return;
+  }
+  mRegisteringScopeList.AppendElement(aScope);
+}
+
+bool
+ClientSource::CalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  return mRegisteringScopeList.Contains(aScope);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientSource.h
+++ b/dom/clients/manager/ClientSource.h
@@ -58,16 +58,22 @@ class ClientSource final : public Client
   Variant<Nothing,
           RefPtr<nsPIDOMWindowInner>,
           nsCOMPtr<nsIDocShell>,
           mozilla::dom::workers::WorkerPrivate*> mOwner;
 
   ClientInfo mClientInfo;
   Maybe<ServiceWorkerDescriptor> mController;
 
+  // Contained a de-duplicated list of ServiceWorker scope strings
+  // for which this client has called navigator.serviceWorker.register().
+  // Typically there will be either be zero or one scope strings, but
+  // there could be more.  We keep this list until the client is closed.
+  AutoTArray<nsCString, 1> mRegisteringScopeList;
+
   void
   Shutdown();
 
   void
   ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs);
 
   mozilla::dom::workers::WorkerPrivate*
   GetWorkerPrivate() const;
@@ -158,16 +164,22 @@ public:
 
   nsISerialEventTarget*
   EventTarget() const;
 
   void
   Traverse(nsCycleCollectionTraversalCallback& aCallback,
            const char* aName,
            uint32_t aFlags);
+
+  void
+  NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
+  bool
+  CalledRegisterForServiceWorkerScope(const nsACString& aScope);
 };
 
 inline void
 ImplCycleCollectionUnlink(UniquePtr<ClientSource>& aField)
 {
   aField.reset();
 }
 
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -4919,17 +4919,17 @@ EventStateManager::CheckForAndDispatchCl
     bool fireAuxClick = notDispatchToContents;
 
     nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
     if (presShell) {
       nsCOMPtr<nsIContent> mouseContent = GetEventTargetContent(aEvent);
       // Click events apply to *elements* not nodes. At this point the target
       // content may have been reset to some non-element content, and so we need
       // to walk up the closest ancestor element, just like we do in
-      // nsPresShell::HandlePositionedEvent.
+      // nsPresShell::HandleEvent.
       while (mouseContent && !mouseContent->IsElement()) {
         mouseContent = mouseContent->GetParent();
       }
 
       if (!mouseContent && !mCurrentTarget) {
         return NS_OK;
       }
 
--- a/dom/events/PointerEventHandler.cpp
+++ b/dom/events/PointerEventHandler.cpp
@@ -190,46 +190,100 @@ PointerEventHandler::GetPointerInfo(uint
   if (sActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
     aActiveState = pointerInfo->mActiveState;
     return true;
   }
   return false;
 }
 
 /* static */ void
+PointerEventHandler::MaybeProcessPointerCapture(WidgetGUIEvent* aEvent)
+{
+  switch (aEvent->mClass) {
+  case eMouseEventClass:
+    ProcessPointerCaptureForMouse(aEvent->AsMouseEvent());
+    break;
+  case eTouchEventClass:
+    ProcessPointerCaptureForTouch(aEvent->AsTouchEvent());
+    break;
+  default:
+    break;
+  }
+}
+
+/* static */ void
+PointerEventHandler::ProcessPointerCaptureForMouse(WidgetMouseEvent* aEvent)
+{
+  if (!ShouldGeneratePointerEventFromMouse(aEvent)) {
+    return;
+  }
+
+  PointerCaptureInfo* info = GetPointerCaptureInfo(aEvent->pointerId);
+  if (!info || info->mPendingContent == info->mOverrideContent) {
+    return;
+  }
+  WidgetPointerEvent localEvent(*aEvent);
+  InitPointerEventFromMouse(&localEvent, aEvent, eVoidEvent);
+  CheckPointerCaptureState(&localEvent);
+}
+
+/* static */ void
+PointerEventHandler::ProcessPointerCaptureForTouch(WidgetTouchEvent* aEvent)
+{
+  if (!ShouldGeneratePointerEventFromTouch(aEvent)) {
+    return;
+  }
+
+  for (uint32_t i = 0; i < aEvent->mTouches.Length(); ++i) {
+    Touch* touch = aEvent->mTouches[i];
+    if (!TouchManager::ShouldConvertTouchToPointer(touch, aEvent)) {
+      continue;
+    }
+    PointerCaptureInfo* info = GetPointerCaptureInfo(touch->Identifier());
+    if (!info || info->mPendingContent == info->mOverrideContent) {
+      continue;
+    }
+    WidgetPointerEvent event(aEvent->IsTrusted(), eVoidEvent, aEvent->mWidget);
+    InitPointerEventFromTouch(&event, aEvent, touch, i == 0);
+    CheckPointerCaptureState(&event);
+  }
+}
+
+/* static */ void
 PointerEventHandler::CheckPointerCaptureState(WidgetPointerEvent* aEvent)
 {
   // Handle pending pointer capture before any pointer events except
   // gotpointercapture / lostpointercapture.
   if (!aEvent) {
     return;
   }
   MOZ_ASSERT(IsPointerEventEnabled());
   MOZ_ASSERT(aEvent->mClass == ePointerEventClass);
 
   PointerCaptureInfo* captureInfo = GetPointerCaptureInfo(aEvent->pointerId);
 
-  if (captureInfo &&
-      captureInfo->mPendingContent != captureInfo->mOverrideContent) {
-    // cache captureInfo->mPendingContent since it may be changed in the pointer
-    // event listener
-    nsIContent* pendingContent = captureInfo->mPendingContent.get();
-    if (captureInfo->mOverrideContent) {
-      DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false, aEvent,
-                                           captureInfo->mOverrideContent);
-    }
-    if (pendingContent) {
-      DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aEvent,
-                                           pendingContent);
-    }
+  if (!captureInfo ||
+      captureInfo->mPendingContent == captureInfo->mOverrideContent) {
+    return;
+  }
+  // cache captureInfo->mPendingContent since it may be changed in the pointer
+  // event listener
+  nsIContent* pendingContent = captureInfo->mPendingContent.get();
+  if (captureInfo->mOverrideContent) {
+    DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ false, aEvent,
+                                         captureInfo->mOverrideContent);
+  }
+  if (pendingContent) {
+    DispatchGotOrLostPointerCaptureEvent(/* aIsGotCapture */ true, aEvent,
+                                         pendingContent);
+  }
 
-    captureInfo->mOverrideContent = pendingContent;
-    if (captureInfo->Empty()) {
-      sPointerCaptureList->Remove(aEvent->pointerId);
-    }
+  captureInfo->mOverrideContent = pendingContent;
+  if (captureInfo->Empty()) {
+    sPointerCaptureList->Remove(aEvent->pointerId);
   }
 }
 
 /* static */ void
 PointerEventHandler::ImplicitlyCapturePointer(nsIFrame* aFrame,
                                               WidgetEvent* aEvent)
 {
   MOZ_ASSERT(aEvent->mMessage == ePointerDown);
@@ -272,43 +326,32 @@ PointerEventHandler::GetPointerCapturing
 {
   PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId);
   if (pointerCaptureInfo) {
     return pointerCaptureInfo->mOverrideContent;
   }
   return nullptr;
 }
 
-/* static */ nsIFrame*
-PointerEventHandler::GetPointerCapturingFrame(nsIFrame* aFrameUnderCursor,
-                                              WidgetGUIEvent* aEvent)
+/* static */ nsIContent*
+PointerEventHandler::GetPointerCapturingContent(WidgetGUIEvent* aEvent)
 {
   if (!IsPointerEventEnabled() || (aEvent->mClass != ePointerEventClass &&
                                    aEvent->mClass != eMouseEventClass) ||
       aEvent->mMessage == ePointerDown || aEvent->mMessage == eMouseDown) {
     // Pointer capture should only be applied to all pointer events and mouse
     // events except ePointerDown and eMouseDown;
-    return aFrameUnderCursor;
+    return nullptr;
   }
 
   WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   if (!mouseEvent) {
-    return aFrameUnderCursor;
+    return nullptr;
   }
-
-  // Find the content which captures the pointer.
-  nsIContent* capturingContent =
-    GetPointerCapturingContent(mouseEvent->pointerId);
-
-  if (!capturingContent) {
-    return aFrameUnderCursor;
-  }
-  // Return the content's primary frame as the target frame.
-  nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
-  return capturingFrame ? capturingFrame : aFrameUnderCursor;
+  return GetPointerCapturingContent(mouseEvent->pointerId);
 }
 
 /* static */ void
 PointerEventHandler::ReleaseIfCaptureByDescendant(nsIContent* aContent)
 {
   // We should check that aChild does not contain pointer capturing elements.
   // If it does we should release the pointer capture for the elements.
   for (auto iter = sPointerCaptureList->Iter(); !iter.Done(); iter.Next()) {
@@ -430,23 +473,24 @@ PointerEventHandler::InitPointerEventFro
   aPointerEvent->buttons = buttons;
   aPointerEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
 }
 
 /* static */ void
 PointerEventHandler::DispatchPointerFromMouseOrTouch(
                        PresShell* aShell,
                        nsIFrame* aFrame,
+                       nsIContent* aContent,
                        WidgetGUIEvent* aEvent,
                        bool aDontRetargetEvents,
                        nsEventStatus* aStatus,
                        nsIContent** aTargetContent)
 {
   MOZ_ASSERT(IsPointerEventEnabled());
-  MOZ_ASSERT(aFrame);
+  MOZ_ASSERT(aFrame || aContent);
   MOZ_ASSERT(aEvent);
 
   EventMessage pointerMessage = eVoidEvent;
   if (aEvent->mClass == eMouseEventClass) {
     WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
     // 1. If it is not mouse then it is likely will come as touch event
     // 2. We don't synthesize pointer events for those events that are not
     //    dispatched to DOM.
@@ -470,20 +514,28 @@ PointerEventHandler::DispatchPointerFrom
       break;
     default:
       return;
     }
 
     WidgetPointerEvent event(*mouseEvent);
     InitPointerEventFromMouse(&event, mouseEvent, pointerMessage);
     event.convertToPointer = mouseEvent->convertToPointer = false;
+    RefPtr<PresShell> shell(aShell);
+    if (!aFrame) {
+      shell = PresShell::GetShellForEventTarget(nullptr, aContent);
+      if (!shell) {
+        return;
+      }
+    }
     PreHandlePointerEventsPreventDefault(&event, aEvent);