Merge mozilla-inbound to mozilla-central. a=merge
authorAndreea Pavel <apavel@mozilla.com>
Thu, 31 May 2018 13:04:21 +0300
changeset 420661 763f30c3421233a45ef9e67a695c5c241a2c8a3a
parent 420660 d5eed637f5dd1f04bf0b4366c2ad91a3482a0686 (current diff)
parent 420659 74279538a616fe15723f71d9181dca590792a983 (diff)
child 420662 437a8d7c128abf04b0a0d2d366cc5b58f292bc87
child 420758 0336998b51de99bb534c82dfb0fe854f03e4e3a0
push id64689
push userapavel@mozilla.com
push dateThu, 31 May 2018 10:06:23 +0000
treeherderautoland@437a8d7c128a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
763f30c34212 / 62.0a1 / 20180531101452 / files
nightly linux64
763f30c34212 / 62.0a1 / 20180531101452 / files
nightly mac
763f30c34212 / 62.0a1 / 20180531101452 / files
nightly win32
763f30c34212 / 62.0a1 / 20180531101452 / files
nightly win64
763f30c34212 / 62.0a1 / 20180531101452 / 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 mozilla-inbound to mozilla-central. a=merge
build/build-clang/r332092.patch
build/build-clang/r332095.patch
devtools/client/accessibility/test/.eslintrc.js
devtools/client/accessibility/test/browser.ini
devtools/client/accessibility/test/browser_accessibility_context_menu_browser.js
devtools/client/accessibility/test/browser_accessibility_context_menu_inspector.js
devtools/client/accessibility/test/browser_accessibility_mutations.js
devtools/client/accessibility/test/browser_accessibility_reload.js
devtools/client/accessibility/test/browser_accessibility_sidebar.js
devtools/client/accessibility/test/browser_accessibility_tree.js
devtools/client/accessibility/test/browser_accessibility_tree_nagivation.js
devtools/client/accessibility/test/head.js
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorUtils.h
editor/libeditor/HTMLEditor.cpp
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -285,17 +285,17 @@ bool HasDefinedARIAHidden(nsIContent* aC
  /**
   * Represents a simple enumerator for iterating through ARIA attributes
   * exposed as object attributes on a given accessible.
   */
 class AttrIterator
 {
 public:
   explicit AttrIterator(nsIContent* aContent)
-    : mElement(aContent->IsElement() ? aContent->AsElement() : nullptr)
+    : mElement(Element::FromNode(aContent))
     , mAttrIdx(0)
   {
     mAttrCount = mElement ? mElement->GetAttrCount() : 0;
   }
 
   bool Next(nsAString& aAttrName, nsAString& aAttrValue);
 
 private:
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -163,18 +163,18 @@ public:
   virtual nsIFrame* GetFrame() const;
 
   /**
    * Return DOM node associated with the accessible.
    */
   virtual nsINode* GetNode() const;
 
   nsIContent* GetContent() const { return mContent; }
-  mozilla::dom::Element* Elm() const
-    { return mContent && mContent->IsElement() ? mContent->AsElement() : nullptr; }
+  dom::Element* Elm() const
+    { return dom::Element::FromNodeOrNull(mContent); }
 
   /**
    * Return node type information of DOM node associated with the accessible.
    */
   bool IsContent() const
     { return GetNode() && GetNode()->IsContent(); }
 
   /**
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -329,21 +329,20 @@ HyperTextAccessible::TransformOffset(Acc
  * or includes aNode.
  *
  * XXX This method is enough to retrieve ::before or ::after pseudo element.
  *     So, if you want to use this for other purpose, you might need to check
  *     ancestors too.
  */
 static nsIContent* GetElementAsContentOf(nsINode* aNode)
 {
-  if (aNode->IsElement()) {
-    return aNode->AsContent();
+  if (Element* element = Element::FromNode(aNode)) {
+    return element;
   }
-  nsIContent* parent = aNode->GetParent();
-  return parent && parent->IsElement() ? parent : nullptr;
+  return aNode->GetParentElement();
 }
 
 bool
 HyperTextAccessible::OffsetsToDOMRange(int32_t aStartOffset, int32_t aEndOffset,
                                        nsRange* aRange)
 {
   DOMPoint startPoint = OffsetToDOMPoint(aStartOffset);
   if (!startPoint.node)
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -24,115 +24,74 @@ const GECKOVIEW_MESSAGE = {
   PREVIOUS: "GeckoView:AccessibilityPrevious",
   SCROLL_BACKWARD: "GeckoView:AccessibilityScrollBackward",
   SCROLL_FORWARD: "GeckoView:AccessibilityScrollForward",
   EXPLORE_BY_TOUCH: "GeckoView:AccessibilityExploreByTouch"
 };
 
 var AccessFu = {
   /**
-   * Initialize chrome-layer accessibility functionality.
-   * If accessibility is enabled on the platform, then a special accessibility
-   * mode is started.
-   */
-  attach: function attach(aWindow, aInTest = false) {
-    Utils.init(aWindow);
-
-    if (!aInTest) {
-      this._enable();
-    }
-  },
-
-  /**
-   * Shut down chrome-layer accessibility functionality from the outside.
-   */
-  detach: function detach() {
-    // Avoid disabling twice.
-    if (this._enabled) {
-      this._disable();
-    }
-
-    Utils.uninit();
-  },
-
-  /**
    * A lazy getter for event handler that binds the scope to AccessFu object.
    */
   get handleEvent() {
     delete this.handleEvent;
     this.handleEvent = this._handleEvent.bind(this);
     return this.handleEvent;
   },
 
   /**
-   * Start AccessFu mode, this primarily means controlling the virtual cursor
-   * with arrow keys.
+   * Start AccessFu mode.
    */
-  _enable: function _enable() {
+  enable: function enable() {
     if (this._enabled) {
       return;
     }
     this._enabled = true;
 
     ChromeUtils.import("resource://gre/modules/accessibility/Utils.jsm");
     ChromeUtils.import("resource://gre/modules/accessibility/Presentation.jsm");
 
-    for (let mm of Utils.AllMessageManagers) {
-      this._addMessageListeners(mm);
-      this._loadFrameScript(mm);
-    }
-
     // Check for output notification
     this._notifyOutputPref =
       new PrefCache("accessibility.accessfu.notify_output");
 
-    if (Utils.MozBuildApp === "mobile/android") {
-      Utils.win.WindowEventDispatcher.registerListener(this,
-        Object.values(GECKOVIEW_MESSAGE));
-    }
-
     Services.obs.addObserver(this, "remote-browser-shown");
     Services.obs.addObserver(this, "inprocess-browser-shown");
-    Utils.win.addEventListener("TabOpen", this);
-    Utils.win.addEventListener("TabClose", this);
-    Utils.win.addEventListener("TabSelect", this);
+    Services.ww.registerNotification(this);
+
+    let windows = Services.wm.getEnumerator(null);
+    while (windows.hasMoreElements()) {
+      this._attachWindow(windows.getNext());
+    }
 
     if (this.readyCallback) {
       this.readyCallback();
       delete this.readyCallback;
     }
 
     Logger.info("AccessFu:Enabled");
   },
 
   /**
    * Disable AccessFu and return to default interaction mode.
    */
-  _disable: function _disable() {
+  disable: function disable() {
     if (!this._enabled) {
       return;
     }
 
     this._enabled = false;
 
-    for (let mm of Utils.AllMessageManagers) {
-      mm.sendAsyncMessage("AccessFu:Stop");
-      this._removeMessageListeners(mm);
-    }
-
-    Utils.win.removeEventListener("TabOpen", this);
-    Utils.win.removeEventListener("TabClose", this);
-    Utils.win.removeEventListener("TabSelect", this);
-
     Services.obs.removeObserver(this, "remote-browser-shown");
     Services.obs.removeObserver(this, "inprocess-browser-shown");
+    Services.ww.unregisterNotification(this);
 
-    if (Utils.MozBuildApp === "mobile/android") {
-      Utils.win.WindowEventDispatcher.unregisterListener(this,
-        Object.values(GECKOVIEW_MESSAGE));
+    let windows = Services.wm.getEnumerator(null);
+    while (windows.hasMoreElements()) {
+      this._detachWindow(windows.getNext());
     }
 
     delete this._notifyOutputPref;
 
     if (this.doneCallback) {
       this.doneCallback();
       delete this.doneCallback;
     }
@@ -152,40 +111,83 @@ var AccessFu = {
           mm.sendAsyncMessage("AccessFu:Start",
                               {method: "start", buildApp: Utils.MozBuildApp});
         }
         break;
       case "AccessFu:Present":
         this._output(aMessage.json, aMessage.target);
         break;
       case "AccessFu:DoScroll":
-        this.Input.doScroll(aMessage.json);
+        this.Input.doScroll(aMessage.json, aMessage.target);
         break;
     }
   },
 
+  _attachWindow: function _attachWindow(win) {
+    let wtype = win.document.documentElement.getAttribute("windowtype");
+    if (wtype != "navigator:browser" && wtype != "navigator:geckoview") {
+      // Don't attach to non-browser or geckoview windows.
+      return;
+    }
+
+    for (let mm of Utils.getAllMessageManagers(win)) {
+      this._addMessageListeners(mm);
+      this._loadFrameScript(mm);
+    }
+
+    win.addEventListener("TabOpen", this);
+    win.addEventListener("TabClose", this);
+    win.addEventListener("TabSelect", this);
+    if (win.WindowEventDispatcher) {
+      // desktop mochitests don't have this.
+      win.WindowEventDispatcher.registerListener(this,
+        Object.values(GECKOVIEW_MESSAGE));
+    }
+  },
+
+  _detachWindow: function _detachWindow(win) {
+    for (let mm of Utils.getAllMessageManagers(win)) {
+      mm.sendAsyncMessage("AccessFu:Stop");
+      this._removeMessageListeners(mm);
+    }
+
+    win.removeEventListener("TabOpen", this);
+    win.removeEventListener("TabClose", this);
+    win.removeEventListener("TabSelect", this);
+    if (win.WindowEventDispatcher) {
+      // desktop mochitests don't have this.
+      win.WindowEventDispatcher.unregisterListener(this,
+        Object.values(GECKOVIEW_MESSAGE));
+    }
+  },
+
   _output: function _output(aPresentationData, aBrowser) {
     if (!aPresentationData) {
       // Either no android events to send or a string used for testing only.
       return;
     }
 
     if (!Utils.isAliveAndVisible(Utils.AccService.getAccessibleFor(aBrowser))) {
       return;
     }
 
+    let win = aBrowser.ownerGlobal;
+
     for (let evt of aPresentationData) {
       if (typeof evt == "string") {
         continue;
       }
 
-      Utils.win.WindowEventDispatcher.sendRequest({
-        ...evt,
-        type: "GeckoView:AccessibilityEvent"
-      });
+      if (win.WindowEventDispatcher) {
+        // desktop mochitests don't have this.
+        win.WindowEventDispatcher.sendRequest({
+          ...evt,
+          type: "GeckoView:AccessibilityEvent"
+        });
+      }
     }
 
     if (this._notifyOutputPref.value) {
       Services.obs.notifyObservers(null, "accessibility-output",
                                    JSON.stringify(aPresentationData));
     }
   },
 
@@ -276,16 +278,20 @@ var AccessFu = {
         // Ignore notifications that aren't from a Browser
         let frameLoader = aSubject;
         if (!frameLoader.ownerIsMozBrowserFrame) {
           return;
         }
         this._handleMessageManager(frameLoader.messageManager);
         break;
       }
+      case "domwindowopened": {
+        this._attachWindow(aSubject.QueryInterface(Ci.nsIDOMWindow));
+        break;
+      }
     }
   },
 
   _handleEvent: function _handleEvent(aEvent) {
     switch (aEvent.type) {
       case "TabOpen":
       {
         let mm = Utils.getMessageManager(aEvent.target);
@@ -317,109 +323,103 @@ var AccessFu = {
         break;
       }
       default:
         break;
     }
   },
 
   autoMove: function autoMove(aOptions) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:AutoMove", aOptions);
   },
 
   announce: function announce(aAnnouncement) {
-    this._output(Presentation.announce(aAnnouncement), Utils.CurrentBrowser);
+    this._output(Presentation.announce(aAnnouncement), Utils.getCurrentBrowser());
   },
 
   // So we don't enable/disable twice
   _enabled: false,
 
   // Layerview is focused
   _focused: false,
 
   // Keep track of message managers tha already have a 'content-script.js'
   // injected.
   _processedMessageManagers: [],
 
   /**
    * Adjusts the given bounds that are defined in device display pixels
    * to client-relative CSS pixels of the chrome window.
    * @param {Rect} aJsonBounds the bounds to adjust
+   * @param {Window} aWindow the window containing the item
    */
-  screenToClientBounds(aJsonBounds) {
+  screenToClientBounds(aJsonBounds, aWindow) {
       let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
                             aJsonBounds.right - aJsonBounds.left,
                             aJsonBounds.bottom - aJsonBounds.top);
-      let win = Utils.win;
-      let dpr = win.devicePixelRatio;
+      let { devicePixelRatio, mozInnerScreenX, mozInnerScreenY } = aWindow;
 
-      bounds = bounds.scale(1 / dpr, 1 / dpr);
-      bounds = bounds.translate(-win.mozInnerScreenX, -win.mozInnerScreenY);
+      bounds = bounds.scale(1 / devicePixelRatio, 1 / devicePixelRatio);
+      bounds = bounds.translate(-mozInnerScreenX, -mozInnerScreenY);
       return bounds.expandToIntegers();
     }
 };
 
 var Input = {
   moveToPoint: function moveToPoint(aRule, aX, aY) {
-    // XXX: Bug 1013408 - There is no alignment between the chrome window's
-    // viewport size and the content viewport size in Android. This makes
-    // sending mouse events beyond its bounds impossible.
-    if (Utils.MozBuildApp === "mobile/android") {
-      let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-      mm.sendAsyncMessage("AccessFu:MoveToPoint",
-        {rule: aRule, x: aX, y: aY, origin: "top"});
-    } else {
-      let win = Utils.win;
-      Utils.winUtils.sendMouseEvent("mousemove",
-        aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
-    }
+    let mm = Utils.getMessageManager();
+    mm.sendAsyncMessage("AccessFu:MoveToPoint",
+      {rule: aRule, x: aX, y: aY, origin: "top"});
   },
 
   moveCursor: function moveCursor(aAction, aRule, aInputType, aAdjustRange) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:MoveCursor",
                         { action: aAction, rule: aRule,
                           origin: "top", inputType: aInputType,
                           adjustRange: aAdjustRange });
   },
 
   androidScroll: function androidScroll(aDirection) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:AndroidScroll",
                         { direction: aDirection, origin: "top" });
   },
 
   moveByGranularity: function moveByGranularity(aDetails) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:MoveByGranularity", aDetails);
   },
 
   activateCurrent: function activateCurrent(aData, aActivateIfKey = false) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     let offset = 0;
 
     mm.sendAsyncMessage("AccessFu:Activate",
                         {offset, activateIfKey: aActivateIfKey});
   },
 
   // XXX: This is here for backwards compatability with screen reader simulator
   // it should be removed when the extension is updated on amo.
   scroll: function scroll(aPage, aHorizontal) {
     this.sendScrollMessage(aPage, aHorizontal);
   },
 
   sendScrollMessage: function sendScrollMessage(aPage, aHorizontal) {
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
+    let mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:Scroll",
       {page: aPage, horizontal: aHorizontal, origin: "top"});
   },
 
-  doScroll: function doScroll(aDetails) {
+  doScroll: function doScroll(aDetails, aBrowser) {
     let horizontal = aDetails.horizontal;
     let page = aDetails.page;
-    let p = AccessFu.screenToClientBounds(aDetails.bounds).center();
-    Utils.winUtils.sendWheelEvent(p.x, p.y,
+    let win = aBrowser.ownerGlobal;
+    let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
+      Ci.nsIDOMWindowUtils);
+    let p = AccessFu.screenToClientBounds(aDetails.bounds, win).center();
+    winUtils.sendWheelEvent(p.x, p.y,
       horizontal ? page : 0, horizontal ? 0 : page, 0,
-      Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
+      win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
   }
 };
 AccessFu.Input = Input;
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -14,16 +14,20 @@ ChromeUtils.defineModuleGetter(this, "Lo
 ChromeUtils.defineModuleGetter(this, "Presentation",
   "resource://gre/modules/accessibility/Presentation.jsm");
 ChromeUtils.defineModuleGetter(this, "Roles",
   "resource://gre/modules/accessibility/Constants.jsm");
 ChromeUtils.defineModuleGetter(this, "Events",
   "resource://gre/modules/accessibility/Constants.jsm");
 ChromeUtils.defineModuleGetter(this, "States",
   "resource://gre/modules/accessibility/Constants.jsm");
+ChromeUtils.defineModuleGetter(this, "clearTimeout",
+  "resource://gre/modules/Timer.jsm");
+ChromeUtils.defineModuleGetter(this, "setTimeout",
+  "resource://gre/modules/Timer.jsm");
 
 var EXPORTED_SYMBOLS = ["EventManager"];
 
 function EventManager(aContentScope, aContentControl) {
   this.contentScope = aContentScope;
   this.contentControl = aContentControl;
   this.addEventListener = this.contentScope.addEventListener.bind(
     this.contentScope);
@@ -442,32 +446,32 @@ this.EventManager.prototype = {
   },
 
   _dequeueLiveEvent: function _dequeueLiveEvent(aEventType, aLiveRegion) {
     let domNode = aLiveRegion.DOMNode;
     if (this._liveEventQueue && this._liveEventQueue.has(domNode)) {
       let queue = this._liveEventQueue.get(domNode);
       let nextEvent = queue[0];
       if (nextEvent.eventType === aEventType) {
-        Utils.win.clearTimeout(nextEvent.timeoutID);
+        clearTimeout(nextEvent.timeoutID);
         queue.shift();
         if (queue.length === 0) {
           this._liveEventQueue.delete(domNode);
         }
       }
     }
   },
 
   _queueLiveEvent: function _queueLiveEvent(aEventType, aLiveRegion, aIsPolite, aModifiedText) {
     if (!this._liveEventQueue) {
       this._liveEventQueue = new WeakMap();
     }
     let eventHandler = {
       eventType: aEventType,
-      timeoutID: Utils.win.setTimeout(this.present.bind(this),
+      timeoutID: setTimeout(this.present.bind(this),
         20, // Wait for a possible EVENT_SHOW or EVENT_TEXT_INSERTED event.
         Presentation.liveRegion(aLiveRegion, aIsPolite, true, aModifiedText))
     };
 
     let domNode = aLiveRegion.DOMNode;
     if (this._liveEventQueue.has(domNode)) {
       this._liveEventQueue.get(domNode).push(eventHandler);
     } else {
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -27,47 +27,16 @@ var EXPORTED_SYMBOLS = ["Utils", "Logger
 var Utils = { // jshint ignore:line
   _buildAppMap: {
     "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}": "b2g",
     "{d1bfe7d9-c01e-4237-998b-7b5f960a4314}": "graphene",
     "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "browser",
     "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android"
   },
 
-  init: function Utils_init(aWindow) {
-    if (this._win) {
-      // XXX: only supports attaching to one window now.
-      throw new Error("Only one top-level window could used with AccessFu");
-    }
-    this._win = Cu.getWeakReference(aWindow);
-  },
-
-  uninit: function Utils_uninit() {
-    if (!this._win) {
-      return;
-    }
-    delete this._win;
-  },
-
-  get win() {
-    if (!this._win) {
-      return null;
-    }
-    return this._win.get();
-  },
-
-  get winUtils() {
-    let win = this.win;
-    if (!win) {
-      return null;
-    }
-    return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
-      Ci.nsIDOMWindowUtils);
-  },
-
   get AccService() {
     if (!this._AccService) {
       this._AccService = Cc["@mozilla.org/accessibilityService;1"].
         getService(Ci.nsIAccessibilityService);
     }
 
     return this._AccService;
   },
@@ -78,30 +47,16 @@ var Utils = { // jshint ignore:line
 
   get MozBuildApp() {
     if (!this._buildApp) {
       this._buildApp = this._buildAppMap[Services.appinfo.ID];
     }
     return this._buildApp;
   },
 
-  get OS() {
-    if (!this._OS) {
-      this._OS = Services.appinfo.OS;
-    }
-    return this._OS;
-  },
-
-  get widgetToolkit() {
-    if (!this._widgetToolkit) {
-      this._widgetToolkit = Services.appinfo.widgetToolkit;
-    }
-    return this._widgetToolkit;
-  },
-
   get ScriptName() {
     if (!this._ScriptName) {
       this._ScriptName =
         (Services.appinfo.processType == 2) ? "AccessFuContent" : "AccessFu";
     }
     return this._ScriptName;
   },
 
@@ -118,75 +73,44 @@ var Utils = { // jshint ignore:line
     return this._AndroidSdkVersion;
   },
 
   set AndroidSdkVersion(value) {
     // When we want to mimic another version.
     this._AndroidSdkVersion = value;
   },
 
-  get BrowserApp() {
-    if (!this.win) {
-      return null;
-    }
-    switch (this.MozBuildApp) {
-      case "mobile/android":
-        return this.win.BrowserApp;
-      case "browser":
-        return this.win.gBrowser;
-      case "b2g":
-        return this.win.shell;
-      default:
-        return null;
-    }
+  getCurrentBrowser: function getCurrentBrowser(aWindow) {
+    let win = aWindow ||
+      Services.wm.getMostRecentWindow("navigator:browser") ||
+      Services.wm.getMostRecentWindow("navigator:geckoview");
+    return win.document.querySelector("browser[type=content][primary=true]");
   },
 
-  get CurrentBrowser() {
-    if (!this.BrowserApp) {
-      // Get the first content browser element when no 'BrowserApp' exists.
-      return this.win.document.querySelector("browser[type=content]");
-    }
-    if (this.MozBuildApp == "b2g") {
-      return this.BrowserApp.contentBrowser;
-    }
-    return this.BrowserApp.selectedBrowser;
-  },
-
-  get CurrentContentDoc() {
-    let browser = this.CurrentBrowser;
-    return browser ? browser.contentDocument : null;
-  },
-
-  get AllMessageManagers() {
+  getAllMessageManagers: function getAllMessageManagers(aWindow) {
     let messageManagers = new Set();
 
     function collectLeafMessageManagers(mm) {
       for (let i = 0; i < mm.childCount; i++) {
         let childMM = mm.getChildAt(i);
 
         if ("sendAsyncMessage" in childMM) {
           messageManagers.add(childMM);
         } else {
           collectLeafMessageManagers(childMM);
         }
       }
     }
 
-    collectLeafMessageManagers(this.win.messageManager);
+    collectLeafMessageManagers(aWindow.messageManager);
 
-    let document = this.CurrentContentDoc;
+    let browser = this.getCurrentBrowser(aWindow);
+    let document = browser ? browser.contentDocument : null;
 
     if (document) {
-      if (document.location.host === "b2g") {
-        // The document is a b2g app chrome (ie. Mulet).
-        let contentBrowser = this.win.content.shell.contentBrowser;
-        messageManagers.add(this.getMessageManager(contentBrowser));
-        document = contentBrowser.contentDocument;
-      }
-
       let remoteframes = document.querySelectorAll("iframe");
 
       for (let i = 0; i < remoteframes.length; ++i) {
         let mm = this.getMessageManager(remoteframes[i]);
         if (mm) {
           messageManagers.add(mm);
         }
       }
@@ -244,18 +168,19 @@ var Utils = { // jshint ignore:line
           return str;
         }
       }
     };
     return this.stringBundle;
   },
 
   getMessageManager: function getMessageManager(aBrowser) {
+    let browser = aBrowser || this.getCurrentBrowser();
     try {
-      return aBrowser.frameLoader.messageManager;
+      return browser.frameLoader.messageManager;
     } catch (x) {
       return null;
     }
   },
 
   getState: function getState(aAccessibleOrEvent) {
     if (aAccessibleOrEvent instanceof Ci.nsIAccessibleStateChangeEvent) {
       return new State(
@@ -314,25 +239,16 @@ var Utils = { // jshint ignore:line
     let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
     let objX = {}, objY = {}, objW = {}, objH = {};
     accText.getRangeExtents(aStart, aEnd, objX, objY, objW, objH,
       Ci.nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE);
 
     return new Rect(objX.value, objY.value, objW.value, objH.value);
   },
 
-  /**
-   * Get current display DPI.
-   */
-  get dpi() {
-    delete this.dpi;
-    this.dpi = this.winUtils.displayDPI;
-    return this.dpi;
-  },
-
   isInSubtree: function isInSubtree(aAccessible, aSubTreeRoot) {
     let acc = aAccessible;
 
     // If aSubTreeRoot is an accessible document, we will only walk up the
     // ancestry of documents and skip everything else.
     if (aSubTreeRoot instanceof Ci.nsIAccessibleDocument) {
       while (acc) {
         let parentDoc = acc instanceof Ci.nsIAccessibleDocument ?
@@ -473,39 +389,16 @@ var Utils = { // jshint ignore:line
     if (aExcludeOrdered && parent.parent.DOMNode.nodeName === "OL") {
       return false;
     }
 
     return parent.role === Roles.LISTITEM && parent.childCount > 1 &&
       aStaticText.indexInParent === 0;
   },
 
-  dispatchChromeEvent: function dispatchChromeEvent(aType, aDetails) {
-    let details = {
-      type: aType,
-      details: JSON.stringify(
-        typeof aDetails === "string" ? { eventType: aDetails } : aDetails)
-    };
-    let window = this.win;
-    let shell = window.shell || window.content.shell;
-    if (shell) {
-      // On B2G device.
-      shell.sendChromeEvent(details);
-    } else {
-      // Dispatch custom event to have support for desktop and screen reader
-      // emulator add-on.
-      window.dispatchEvent(new window.CustomEvent(aType, {
-        bubbles: true,
-        cancelable: true,
-        detail: details
-      }));
-    }
-
-  },
-
   isActivatableOnFingerUp: function isActivatableOnFingerUp(aAccessible) {
     if (aAccessible.role === Roles.KEY) {
       return true;
     }
     let quick_activate = this.getAttributes(aAccessible)["moz-quick-activate"];
     return quick_activate && JSON.parse(quick_activate);
   }
 };
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -104,17 +104,18 @@ var AccessFuTest = {
   },
 
   finish: function AccessFuTest_finish() {
     // Disable the console service logging.
     Logger.test = false;
     Logger.logLevel = Logger.INFO;
     // Finish through idle callback to let AccessFu._disable complete.
     SimpleTest.executeSoon(function() {
-      AccessFu.detach();
+      // May be redundant, but for cleanup's sake.
+      AccessFu.disable();
       SimpleTest.finish();
     });
   },
 
   nextTest: function AccessFuTest_nextTest() {
     var result = gIterator.next();
     if (result.done) {
       this.finish();
@@ -136,30 +137,22 @@ var AccessFuTest = {
       for (var testFunc of gTestFuncs) {
         yield testFunc;
       }
     })();
 
     // Start AccessFu and put it in stand-by.
     ChromeUtils.import("resource://gre/modules/accessibility/AccessFu.jsm");
 
-    let chromeWin = getMainChromeWindow(window);
-    chromeWin.WindowEventDispatcher = {
-      dispatch: () => {},
-      sendRequest: () => {}
-    };
-
     AccessFu.readyCallback = function readyCallback() {
       // Enable logging to the console service.
       Logger.test = true;
       Logger.logLevel = Logger.DEBUG;
     };
 
-    AccessFu.attach(chromeWin, true);
-
     var prefs = [["accessibility.accessfu.notify_output", 1]];
     prefs.push.apply(prefs, aAdditionalPrefs);
 
     SpecialPowers.pushPrefEnv({ "set": prefs }, function() {
       if (AccessFuTest._waitForExplicitFinish) {
         // Run all test functions asynchronously.
         AccessFuTest.nextTest();
       } else {
--- a/accessible/tests/mochitest/jsat/test_alive.html
+++ b/accessible/tests/mochitest/jsat/test_alive.html
@@ -18,30 +18,30 @@
       isnot(AccessFu._enabled, true, "AccessFu was disabled.");
       // XXX: Bug 978076 - test start with SettingsManager.
       // navigator.mozSettings.createLock().set(
       //  {'accessibility.screenreader': false});
       AccessFuTest.once_log("EventManager.start", () => {
         ok(AccessFu._enabled, "AccessFu was enabled again.");
         AccessFuTest.nextTest();
       });
-      AccessFu._enable();
+      AccessFu.enable();
     }
 
     // Make sure EventManager is started again.
     function settingsStop() {
       ok(AccessFu._enabled, "AccessFu was enabled again.");
       // XXX: Bug 978076 - test stop with SettingsManager.
       // navigator.mozSettings.createLock().set(
       //  {'accessibility.screenreader': false});
       AccessFuTest.once_log("EventManager.stop", () => {
         isnot(AccessFu._enabled, "AccessFu was disabled.");
         AccessFuTest.finish();
       });
-      AccessFu._disable();
+      AccessFu.disable();
     }
 
     function doTest() {
       AccessFuTest.addFunc(settingsStart);
       AccessFuTest.addFunc(settingsStop);
       AccessFuTest.waitForExplicitFinish();
       AccessFuTest.runTests(); // Will call SimpleTest.finish();
     }
--- a/accessible/tests/mochitest/jsat/test_live_regions.html
+++ b/accessible/tests/mochitest/jsat/test_live_regions.html
@@ -9,22 +9,22 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="./jsatcommon.js"></script>
   <script type="application/javascript">
     function startAccessFu() {
       AccessFuTest.once_log("EventManager.start", AccessFuTest.nextTest);
-      AccessFu._enable();
+      AccessFu.enable();
     }
 
     function stopAccessFu() {
       AccessFuTest.once_log("EventManager.stop", () => AccessFuTest.finish());
-      AccessFu._disable();
+      AccessFu.disable();
     }
 
     function hide(id) {
       var element = document.getElementById(id);
       element.style.display = "none";
     }
 
     function show(id) {
--- a/build/build-clang/clang-win64.json
+++ b/build/build-clang/clang-win64.json
@@ -1,21 +1,19 @@
 {
-    "llvm_revision": "328769",
+    "llvm_revision": "333414",
     "stages": "3",
     "build_libcxx": false,
     "build_type": "Release",
     "assertions": false,
     "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
     "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
     "lld_repo": "https://llvm.org/svn/llvm-project/lld/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": [
-      "r332092.patch",
-      "r332095.patch",
       "loosen-msvc-detection.patch"
     ]
 }
deleted file mode 100644
--- a/build/build-clang/r332092.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-Bug 1458325: Fix copy/paste error in AddrIsInHighShadow that breaks Win64 jit-tests
-
-https://reviews.llvm.org/D46291
-https://github.com/llvm-mirror/compiler-rt/commit/d55f7bdbe7079a3d331d8ac7d0e82352eaf26af1
-
---- a/compiler-rt/lib/asan/asan_mapping.h
-+++ b/compiler-rt/lib/asan/asan_mapping.h
-@@ -319,12 +319,12 @@
- 
- static inline bool AddrIsInHighShadow(uptr a) {
-   PROFILE_ASAN_MAPPING();
--  return a >= kHighShadowBeg && a <= kHighMemEnd;
-+  return a >= kHighShadowBeg && a <= kHighShadowEnd;
- }
- 
- static inline bool AddrIsInMidShadow(uptr a) {
-   PROFILE_ASAN_MAPPING();
--  return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd;
-+  return kMidMemBeg && a >= kMidShadowBeg && a <= kMidShadowEnd;
- }
- 
- static inline bool AddrIsInShadow(uptr a) {
deleted file mode 100644
--- a/build/build-clang/r332095.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-r332095 | dmajor | 2018-05-11 10:31:14 -0400 (Fri, 11 May 2018) | 9 lines
-
-[winasan] Update GetInstructionSize for Win10 1803
-
-In Windows version 1803, the first instruction of ntdll!strchr is:
-8a01 mov al,byte ptr [rcx]
-
-This is the only needed change for this version as far as I can tell.
-
-Differential Revision: https://reviews.llvm.org/D46458
-
---- a/compiler-rt/lib/interception/interception_win.cc
-+++ b/compiler-rt/lib/interception/interception_win.cc
-@@ -453,6 +453,7 @@
-   }
-
-   switch (*(u16*)(address)) {
-+    case 0x018A:  // 8A 01 : mov al, byte ptr [ecx]
-     case 0xFF8B:  // 8B FF : mov edi, edi
-     case 0xEC8B:  // 8B EC : mov ebp, esp
-     case 0xc889:  // 89 C8 : mov eax, ecx
--- a/devtools/client/accessibility/components/Accessible.js
+++ b/devtools/client/accessibility/components/Accessible.js
@@ -169,19 +169,45 @@ class Accessible extends Component {
     if (!gToolbox) {
       return;
     }
 
     gToolbox.selectTool("inspector").then(() =>
       gToolbox.selection.setNodeFront(nodeFront, reason));
   }
 
+  openLink(link, e) {
+    if (!gToolbox) {
+      return;
+    }
+
+    // Avoid using Services.appinfo.OS in order to keep accessible pane's frontend free of
+    // priveleged code.
+    const os = window.navigator.userAgent;
+    const isOSX =  os && os.includes("Mac");
+    let where = "tab";
+    if (e && (e.button === 1 || (e.button === 0 && (isOSX ? e.metaKey : e.ctrlKey)))) {
+      where = "tabshifted";
+    } else if (e && e.shiftKey) {
+      where = "window";
+    }
+
+    const win = gToolbox.doc.defaultView.top;
+    win.openWebLinkIn(link, where);
+  }
+
   renderItem(item, depth, focused, arrow, expanded) {
     const object = item.contents;
-    let valueProps = { object, mode: MODE.TINY, title: "Object" };
+    let valueProps = {
+      object,
+      mode: MODE.TINY,
+      title: "Object",
+      openLink: this.openLink
+    };
+
     if (isNode(object)) {
       valueProps.defaultRep = ElementNode;
       valueProps.onDOMNodeMouseOut = () => this.hideHighlighter();
       valueProps.onDOMNodeMouseOver = () => this.showHighlighter(this.props.DOMNode);
       valueProps.onInspectIconClick = () => this.selectNode(this.props.DOMNode);
     }
 
     let classList = [ "node", "object-node" ];
--- a/devtools/client/accessibility/moz.build
+++ b/devtools/client/accessibility/moz.build
@@ -1,13 +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/.
 
-BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
+MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
+BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 
 DIRS += [
     'actions',
     'components',
     'reducers',
     'utils'
 ]
 
deleted file mode 100644
--- a/devtools/client/accessibility/test/.eslintrc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-"use strict";
-
-module.exports = {
-  // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests.js"
-};
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/browser/.eslintrc.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = {
+  // Extend from the shared list of defined globals for mochitests.
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
rename from devtools/client/accessibility/test/browser.ini
rename to devtools/client/accessibility/test/browser/browser.ini
rename from devtools/client/accessibility/test/browser_accessibility_context_menu_browser.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_context_menu_browser.js
rename from devtools/client/accessibility/test/browser_accessibility_context_menu_inspector.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_context_menu_inspector.js
rename from devtools/client/accessibility/test/browser_accessibility_mutations.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_mutations.js
rename from devtools/client/accessibility/test/browser_accessibility_reload.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_reload.js
rename from devtools/client/accessibility/test/browser_accessibility_sidebar.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_sidebar.js
rename from devtools/client/accessibility/test/browser_accessibility_tree.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_tree.js
rename from devtools/client/accessibility/test/browser_accessibility_tree_nagivation.js
rename to devtools/client/accessibility/test/browser/browser_accessibility_tree_nagivation.js
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/browser/head.js
@@ -0,0 +1,306 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* import-globals-from ../../../shared/test/shared-head.js */
+/* import-globals-from ../../../inspector/test/shared-head.js */
+
+/* global waitUntilState, gBrowser */
+/* exported addTestTab, checkTreeState, checkSidebarState, selectRow,
+            toggleRow, addA11yPanelTestsTask, reload, navigate */
+
+"use strict";
+
+// Import framework's shared head.
+Services.scriptloader.loadSubScript(
+  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
+  this);
+
+// Import inspector's shared head.
+Services.scriptloader.loadSubScript(
+  "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js",
+  this);
+
+// Load the shared Redux helpers into this compartment.
+Services.scriptloader.loadSubScript(
+  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-redux-head.js",
+  this);
+
+const { ORDERED_PROPS } = require("devtools/client/accessibility/constants");
+
+// Enable the Accessibility panel
+Services.prefs.setBoolPref("devtools.accessibility.enabled", true);
+
+/**
+ * Wait for accessibility service to shut down. We consider it shut down when
+ * an "a11y-init-or-shutdown" event is received with a value of "0".
+ */
+function shutdownA11y() {
+  if (!Services.appinfo.accessibilityEnabled) {
+    return Promise.resolve();
+  }
+
+  // Force collections to speed up accessibility service shutdown.
+  Cu.forceGC();
+  Cu.forceCC();
+  Cu.forceShrinkingGC();
+
+  return new Promise(resolve => {
+    let observe = (subject, topic, data) => {
+      if (data === "0") {
+        Services.obs.removeObserver(observe, "a11y-init-or-shutdown");
+        resolve();
+      }
+    };
+    // This event is coming from Gecko accessibility module when the
+    // accessibility service is shutdown or initialzied. We attempt to shutdown
+    // accessibility service naturally if there are no more XPCOM references to
+    // a11y related objects (after GC/CC).
+    Services.obs.addObserver(observe, "a11y-init-or-shutdown");
+  });
+}
+
+registerCleanupFunction(async () => {
+  info("Cleaning up...");
+  await shutdownA11y();
+  Services.prefs.clearUserPref("devtools.accessibility.enabled");
+});
+
+const EXPANDABLE_PROPS = ["actions", "states", "attributes"];
+
+/**
+ * Add a new test tab in the browser and load the given url.
+ * @param {String} url
+ *        The url to be loaded in the new tab
+ * @return a promise that resolves to the tab object when
+ *        the url is loaded
+ */
+async function addTestTab(url) {
+  info("Adding a new test tab with URL: '" + url + "'");
+
+  let tab = await addTab(url);
+  let panel = await initAccessibilityPanel(tab);
+  let win = panel.panelWin;
+  let doc = win.document;
+  let store = win.view.store;
+
+  EventUtils.sendMouseEvent({ type: "click" },
+    doc.getElementById("accessibility-enable-button"), win);
+
+  await waitUntilState(store, state =>
+    state.accessibles.size === 1 && state.details.accessible &&
+    state.details.accessible.role === "document");
+
+  // Wait for inspector load here to avoid protocol errors on shutdown, since
+  // accessibility panel test can be too fast.
+  await win.gToolbox.loadTool("inspector");
+
+  return {
+    tab,
+    browser: tab.linkedBrowser,
+    panel,
+    win,
+    toolbox: panel._toolbox,
+    doc,
+    store
+  };
+}
+
+/**
+ * Turn off accessibility features from within the panel. We call it before the
+ * cleanup function to make sure that the panel is still present.
+ */
+async function disableAccessibilityInspector(env) {
+  let { doc, win, panel } = env;
+  // Disable accessibility service through the panel and wait for the shutdown
+  // event.
+  let shutdown = panel._front.once("shutdown");
+  EventUtils.sendMouseEvent({ type: "click" },
+    doc.getElementById("accessibility-disable-button"), win);
+  await shutdown;
+}
+
+/**
+ * Open the Accessibility panel for the given tab.
+ *
+ * @param {Element} tab
+ *        Optional tab element for which you want open the Accessibility panel.
+ *        The default tab is taken from the global variable |tab|.
+ * @return a promise that is resolved once the panel is open.
+ */
+async function initAccessibilityPanel(tab = gBrowser.selectedTab) {
+  let target = TargetFactory.forTab(tab);
+  let toolbox = await gDevTools.showToolbox(target, "accessibility");
+  return toolbox.getCurrentPanel();
+}
+
+/**
+ * Check the state of the accessibility tree.
+ * @param  {document} doc       panel documnent.
+ * @param  {Array}    expected  an array that represents an expected row list.
+ */
+async function checkTreeState(doc, expected) {
+  info("Checking tree state.");
+  let hasExpectedStructure = await BrowserTestUtils.waitForCondition(() =>
+    [...doc.querySelectorAll(".treeRow")].every((row, i) =>
+      row.querySelector(".treeLabelCell").textContent === expected[i].role &&
+      row.querySelector(".treeValueCell").textContent === expected[i].name),
+    "Wait for the right tree update.");
+
+  ok(hasExpectedStructure, "Tree structure is correct.");
+}
+
+/**
+ * Check the state of the accessibility sidebar.
+ * @param  {Object} store         React store for the panel (includes store for
+ *                                the sidebar).
+ * @param  {Object} expectedState Expected state of the sidebar.
+ */
+async function checkSidebarState(store, expectedState) {
+  info("Checking sidebar state.");
+  await waitUntilState(store, ({ details }) => {
+    for (let key of ORDERED_PROPS) {
+      let expected = expectedState[key];
+      if (expected === undefined) {
+        continue;
+      }
+
+      if (EXPANDABLE_PROPS.includes(key)) {
+        if (JSON.stringify(details.accessible[key]) !== JSON.stringify(expected)) {
+          return false;
+        }
+      } else if (details.accessible && details.accessible[key] !== expected) {
+        return false;
+      }
+    }
+
+    ok(true, "Sidebar state is correct.");
+    return true;
+  });
+}
+
+/**
+ * Select tree row.
+ * @param  {document} doc       panel documnent.
+ * @param  {Number}   rowNumber number of the row/tree node to be selected.
+ */
+function selectRow(doc, rowNumber) {
+  info(`Selecting row ${rowNumber}.`);
+  EventUtils.sendMouseEvent({ type: "click" },
+    doc.querySelectorAll(".treeRow")[rowNumber], doc.defaultView);
+}
+
+/**
+ * Toggle an expandable tree row.
+ * @param  {document} doc       panel documnent.
+ * @param  {Number}   rowNumber number of the row/tree node to be toggled.
+ */
+async function toggleRow(doc, rowNumber) {
+  let win = doc.defaultView;
+  let twisty = doc.querySelectorAll(".theme-twisty")[rowNumber];
+  let expected = !twisty.classList.contains("open");
+
+  info(`${expected ? "Expanding" : "Collapsing"} row ${rowNumber}.`);
+
+  EventUtils.sendMouseEvent({ type: "click" }, twisty, win);
+  await BrowserTestUtils.waitForCondition(() =>
+    !twisty.classList.contains("devtools-throbber") &&
+    expected === twisty.classList.contains("open"), "Twisty updated.");
+}
+
+/**
+ * Iterate over actions/tests structure and test the state of the
+ * accessibility panel.
+ * @param  {JSON}   tests test data that has the format of:
+ *                    {
+ *                      desc     {String}    description for better logging
+ *                      action   {Function}  An optional action that needs to be
+ *                                           performed before the state of the
+ *                                           tree and the sidebar can be checked
+ *                      expected {JSON}      An expected states for the tree and
+ *                                           the sidebar
+ *                    }
+ * @param  {Object} env  contains all relevant environment objects (same
+ *                       structure as the return value of 'addTestTab' funciton)
+ */
+async function runA11yPanelTests(tests, env) {
+  for (let { desc, action, expected } of tests) {
+    info(desc);
+
+    if (action) {
+      await action(env);
+    }
+
+    let { tree, sidebar } = expected;
+    if (tree) {
+      await checkTreeState(env.doc, tree);
+    }
+
+    if (sidebar) {
+      await checkSidebarState(env.store, sidebar);
+    }
+  }
+}
+
+/**
+ * Build a valid URL from an HTML snippet.
+ * @param  {String} uri HTML snippet
+ * @return {String}     built URL
+ */
+function buildURL(uri) {
+  return `data:text/html;charset=UTF-8,${encodeURIComponent(uri)}`;
+}
+
+/**
+ * Add a test task based on the test structure and a test URL.
+ * @param  {JSON}   tests  test data that has the format of:
+ *                    {
+ *                      desc     {String}    description for better logging
+ *                      action   {Function}  An optional action that needs to be
+ *                                           performed before the state of the
+ *                                           tree and the sidebar can be checked
+ *                      expected {JSON}      An expected states for the tree and
+ *                                           the sidebar
+ *                    }
+ * @param {String}  uri    test URL
+ * @param {String}  msg    a message that is printed for the test
+ */
+function addA11yPanelTestsTask(tests, uri, msg) {
+  addA11YPanelTask(msg, uri, env => runA11yPanelTests(tests, env));
+}
+
+/**
+ * A wrapper function around add_task that sets up the test environment, runs
+ * the test and then disables accessibility tools.
+ * @param {String}   msg    a message that is printed for the test
+ * @param {String}   uri    test URL
+ * @param {Function} task   task function containing the tests.
+ */
+function addA11YPanelTask(msg, uri, task) {
+  add_task(async function a11YPanelTask() {
+    info(msg);
+    let env = await addTestTab(buildURL(uri));
+    await task(env);
+    await disableAccessibilityInspector(env);
+  });
+}
+
+/**
+ * Reload panel target.
+ * @param  {Object} target             Panel target.
+ * @param  {String} waitForTargetEvent Event to wait for after reload.
+ */
+function reload(target, waitForTargetEvent = "navigate") {
+  executeSoon(() => target.activeTab.reload());
+  return once(target, waitForTargetEvent);
+}
+
+/**
+ * Navigate to a new URL within the panel target.
+ * @param  {Object} target             Panel target.
+ * @param  {Srting} url                URL to navigate to.
+ * @param  {String} waitForTargetEvent Event to wait for after reload.
+ */
+function navigate(target, url, waitForTargetEvent = "navigate") {
+  executeSoon(() => target.activeTab.navigateTo(url));
+  return once(target, waitForTargetEvent);
+}
deleted file mode 100644
--- a/devtools/client/accessibility/test/head.js
+++ /dev/null
@@ -1,306 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/* import-globals-from ../../shared/test/shared-head.js */
-/* import-globals-from ../../inspector/test/shared-head.js */
-
-/* global waitUntilState, gBrowser */
-/* exported addTestTab, checkTreeState, checkSidebarState, selectRow,
-            toggleRow, addA11yPanelTestsTask, reload, navigate */
-
-"use strict";
-
-// Import framework's shared head.
-Services.scriptloader.loadSubScript(
-  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
-  this);
-
-// Import inspector's shared head.
-Services.scriptloader.loadSubScript(
-  "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js",
-  this);
-
-// Load the shared Redux helpers into this compartment.
-Services.scriptloader.loadSubScript(
-  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-redux-head.js",
-  this);
-
-const { ORDERED_PROPS } = require("devtools/client/accessibility/constants");
-
-// Enable the Accessibility panel
-Services.prefs.setBoolPref("devtools.accessibility.enabled", true);
-
-/**
- * Wait for accessibility service to shut down. We consider it shut down when
- * an "a11y-init-or-shutdown" event is received with a value of "0".
- */
-function shutdownA11y() {
-  if (!Services.appinfo.accessibilityEnabled) {
-    return Promise.resolve();
-  }
-
-  // Force collections to speed up accessibility service shutdown.
-  Cu.forceGC();
-  Cu.forceCC();
-  Cu.forceShrinkingGC();
-
-  return new Promise(resolve => {
-    let observe = (subject, topic, data) => {
-      if (data === "0") {
-        Services.obs.removeObserver(observe, "a11y-init-or-shutdown");
-        resolve();
-      }
-    };
-    // This event is coming from Gecko accessibility module when the
-    // accessibility service is shutdown or initialzied. We attempt to shutdown
-    // accessibility service naturally if there are no more XPCOM references to
-    // a11y related objects (after GC/CC).
-    Services.obs.addObserver(observe, "a11y-init-or-shutdown");
-  });
-}
-
-registerCleanupFunction(async () => {
-  info("Cleaning up...");
-  await shutdownA11y();
-  Services.prefs.clearUserPref("devtools.accessibility.enabled");
-});
-
-const EXPANDABLE_PROPS = ["actions", "states", "attributes"];
-
-/**
- * Add a new test tab in the browser and load the given url.
- * @param {String} url
- *        The url to be loaded in the new tab
- * @return a promise that resolves to the tab object when
- *        the url is loaded
- */
-async function addTestTab(url) {
-  info("Adding a new test tab with URL: '" + url + "'");
-
-  let tab = await addTab(url);
-  let panel = await initAccessibilityPanel(tab);
-  let win = panel.panelWin;
-  let doc = win.document;
-  let store = win.view.store;
-
-  EventUtils.sendMouseEvent({ type: "click" },
-    doc.getElementById("accessibility-enable-button"), win);
-
-  await waitUntilState(store, state =>
-    state.accessibles.size === 1 && state.details.accessible &&
-    state.details.accessible.role === "document");
-
-  // Wait for inspector load here to avoid protocol errors on shutdown, since
-  // accessibility panel test can be too fast.
-  await win.gToolbox.loadTool("inspector");
-
-  return {
-    tab,
-    browser: tab.linkedBrowser,
-    panel,
-    win,
-    toolbox: panel._toolbox,
-    doc,
-    store
-  };
-}
-
-/**
- * Turn off accessibility features from within the panel. We call it before the
- * cleanup function to make sure that the panel is still present.
- */
-async function disableAccessibilityInspector(env) {
-  let { doc, win, panel } = env;
-  // Disable accessibility service through the panel and wait for the shutdown
-  // event.
-  let shutdown = panel._front.once("shutdown");
-  EventUtils.sendMouseEvent({ type: "click" },
-    doc.getElementById("accessibility-disable-button"), win);
-  await shutdown;
-}
-
-/**
- * Open the Accessibility panel for the given tab.
- *
- * @param {Element} tab
- *        Optional tab element for which you want open the Accessibility panel.
- *        The default tab is taken from the global variable |tab|.
- * @return a promise that is resolved once the panel is open.
- */
-async function initAccessibilityPanel(tab = gBrowser.selectedTab) {
-  let target = TargetFactory.forTab(tab);
-  let toolbox = await gDevTools.showToolbox(target, "accessibility");
-  return toolbox.getCurrentPanel();
-}
-
-/**
- * Check the state of the accessibility tree.
- * @param  {document} doc       panel documnent.
- * @param  {Array}    expected  an array that represents an expected row list.
- */
-async function checkTreeState(doc, expected) {
-  info("Checking tree state.");
-  let hasExpectedStructure = await BrowserTestUtils.waitForCondition(() =>
-    [...doc.querySelectorAll(".treeRow")].every((row, i) =>
-      row.querySelector(".treeLabelCell").textContent === expected[i].role &&
-      row.querySelector(".treeValueCell").textContent === expected[i].name),
-    "Wait for the right tree update.");
-
-  ok(hasExpectedStructure, "Tree structure is correct.");
-}
-
-/**
- * Check the state of the accessibility sidebar.
- * @param  {Object} store         React store for the panel (includes store for
- *                                the sidebar).
- * @param  {Object} expectedState Expected state of the sidebar.
- */
-async function checkSidebarState(store, expectedState) {
-  info("Checking sidebar state.");
-  await waitUntilState(store, ({ details }) => {
-    for (let key of ORDERED_PROPS) {
-      let expected = expectedState[key];
-      if (expected === undefined) {
-        continue;
-      }
-
-      if (EXPANDABLE_PROPS.includes(key)) {
-        if (JSON.stringify(details.accessible[key]) !== JSON.stringify(expected)) {
-          return false;
-        }
-      } else if (details.accessible && details.accessible[key] !== expected) {
-        return false;
-      }
-    }
-
-    ok(true, "Sidebar state is correct.");
-    return true;
-  });
-}
-
-/**
- * Select tree row.
- * @param  {document} doc       panel documnent.
- * @param  {Number}   rowNumber number of the row/tree node to be selected.
- */
-function selectRow(doc, rowNumber) {
-  info(`Selecting row ${rowNumber}.`);
-  EventUtils.sendMouseEvent({ type: "click" },
-    doc.querySelectorAll(".treeRow")[rowNumber], doc.defaultView);
-}
-
-/**
- * Toggle an expandable tree row.
- * @param  {document} doc       panel documnent.
- * @param  {Number}   rowNumber number of the row/tree node to be toggled.
- */
-async function toggleRow(doc, rowNumber) {
-  let win = doc.defaultView;
-  let twisty = doc.querySelectorAll(".theme-twisty")[rowNumber];
-  let expected = !twisty.classList.contains("open");
-
-  info(`${expected ? "Expanding" : "Collapsing"} row ${rowNumber}.`);
-
-  EventUtils.sendMouseEvent({ type: "click" }, twisty, win);
-  await BrowserTestUtils.waitForCondition(() =>
-    !twisty.classList.contains("devtools-throbber") &&
-    expected === twisty.classList.contains("open"), "Twisty updated.");
-}
-
-/**
- * Iterate over actions/tests structure and test the state of the
- * accessibility panel.
- * @param  {JSON}   tests test data that has the format of:
- *                    {
- *                      desc     {String}    description for better logging
- *                      action   {Function}  An optional action that needs to be
- *                                           performed before the state of the
- *                                           tree and the sidebar can be checked
- *                      expected {JSON}      An expected states for the tree and
- *                                           the sidebar
- *                    }
- * @param  {Object} env  contains all relevant environment objects (same
- *                       structure as the return value of 'addTestTab' funciton)
- */
-async function runA11yPanelTests(tests, env) {
-  for (let { desc, action, expected } of tests) {
-    info(desc);
-
-    if (action) {
-      await action(env);
-    }
-
-    let { tree, sidebar } = expected;
-    if (tree) {
-      await checkTreeState(env.doc, tree);
-    }
-
-    if (sidebar) {
-      await checkSidebarState(env.store, sidebar);
-    }
-  }
-}
-
-/**
- * Build a valid URL from an HTML snippet.
- * @param  {String} uri HTML snippet
- * @return {String}     built URL
- */
-function buildURL(uri) {
-  return `data:text/html;charset=UTF-8,${encodeURIComponent(uri)}`;
-}
-
-/**
- * Add a test task based on the test structure and a test URL.
- * @param  {JSON}   tests  test data that has the format of:
- *                    {
- *                      desc     {String}    description for better logging
- *                      action   {Function}  An optional action that needs to be
- *                                           performed before the state of the
- *                                           tree and the sidebar can be checked
- *                      expected {JSON}      An expected states for the tree and
- *                                           the sidebar
- *                    }
- * @param {String}  uri    test URL
- * @param {String}  msg    a message that is printed for the test
- */
-function addA11yPanelTestsTask(tests, uri, msg) {
-  addA11YPanelTask(msg, uri, env => runA11yPanelTests(tests, env));
-}
-
-/**
- * A wrapper function around add_task that sets up the test environment, runs
- * the test and then disables accessibility tools.
- * @param {String}   msg    a message that is printed for the test
- * @param {String}   uri    test URL
- * @param {Function} task   task function containing the tests.
- */
-function addA11YPanelTask(msg, uri, task) {
-  add_task(async function a11YPanelTask() {
-    info(msg);
-    let env = await addTestTab(buildURL(uri));
-    await task(env);
-    await disableAccessibilityInspector(env);
-  });
-}
-
-/**
- * Reload panel target.
- * @param  {Object} target             Panel target.
- * @param  {String} waitForTargetEvent Event to wait for after reload.
- */
-function reload(target, waitForTargetEvent = "navigate") {
-  executeSoon(() => target.activeTab.reload());
-  return once(target, waitForTargetEvent);
-}
-
-/**
- * Navigate to a new URL within the panel target.
- * @param  {Object} target             Panel target.
- * @param  {Srting} url                URL to navigate to.
- * @param  {String} waitForTargetEvent Event to wait for after reload.
- */
-function navigate(target, url, waitForTargetEvent = "navigate") {
-  executeSoon(() => target.activeTab.navigateTo(url));
-  return once(target, waitForTargetEvent);
-}
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/mochitest/.eslintrc.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = {
+  // Extend from the shared list of defined globals for mochitests.
+  "extends": "../../../../.eslintrc.mochitests.js"
+};
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/mochitest/chrome.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+  head.js
+
+[test_accessible_openLink.html]
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/mochitest/head.js
@@ -0,0 +1,28 @@
+/* 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/. */
+/* eslint no-unused-vars: [2, {"vars": "local"}] */
+
+"use strict";
+
+var { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
+var { BrowserLoader } = ChromeUtils.import("resource://devtools/client/shared/browser-loader.js", {});
+var DevToolsUtils = require("devtools/shared/DevToolsUtils");
+
+var { require: browserRequire } = BrowserLoader({
+  baseURI: "resource://devtools/client/shared/",
+  window
+});
+
+window.EVENTS = {};
+window.on = function() {};
+window.off = function() {};
+
+SimpleTest.registerCleanupFunction(() => {
+  window.EVENTS = null;
+  window.on = null;
+  window.off = null;
+});
+
+// All tests are asynchronous.
+SimpleTest.waitForExplicitFinish();
new file mode 100644
--- /dev/null
+++ b/devtools/client/accessibility/test/mochitest/test_accessible_openLink.html
@@ -0,0 +1,96 @@
+<!-- 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/. -->
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that openLink function is called if accessible object property is rendered as a link.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Accessible component test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+  <link rel="stylesheet" href="chrome://devtools/skin/light-theme.css" type="text/css">
+</head>
+<body>
+<pre id="test">
+<script src="head.js" type="application/javascript"></script>
+<script type="application/javascript">
+
+"use strict";
+
+window.onload = async function() {
+  try {
+    const Services = browserRequire("Services");
+    const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
+    const { createFactory, createElement } =
+      browserRequire("devtools/client/shared/vendor/react");
+    const { Provider } = require("devtools/client/shared/vendor/react-redux");
+    const createStore = require("devtools/client/shared/redux/create-store")();
+    const { Simulate } =
+      browserRequire("devtools/client/shared/vendor/react-dom-test-utils");
+    const Accessible = createFactory(
+      browserRequire("devtools/client/accessibility/components/Accessible"));
+
+    function testLinkClicked(link, event, expectedUrl, expectedWhere) {
+      const checker = Symbol();
+      let onClickArgs = checker;
+      const mockToolbox = {
+        doc: {
+          defaultView: {
+            top: {
+              openWebLinkIn: (url, where) => {
+                onClickArgs = { url, where };
+              }
+            }
+          }
+        }
+      };
+
+      window.gToolbox = mockToolbox;
+      Simulate.click(link, event);
+
+      ok(onClickArgs !== checker, "Link was clicked");
+      is(onClickArgs.url, expectedUrl, "Correct URL is opened");
+      is(onClickArgs.where, expectedWhere, "URL was opened correctly");
+
+      window.gToolbox = null;
+    }
+
+    const a = Accessible({ labelledby: "Test Accessible" });
+    ok(a, "Should be able to create Accessible instances");
+
+    let URL = "http://example.com";
+    const mockStore = createStore((state, action) =>
+      action ? { ...state, ...action } : state,
+      { details: { DOMNode: {}, accessible: { value: URL } } });
+    const provider = createElement(Provider, { store: mockStore }, a);
+    const accessible = ReactDOM.render(provider, window.document.body);
+    ok(accessible, "Should be able to mount Accessible instances");
+
+    let link = document.querySelector(".url");
+    testLinkClicked(link, null, URL, "tab");
+
+    let event = { button: 0 };
+    event[Services.appinfo.OS == "Darwin" ? "metaKey" : "ctrlKey"] = true;
+    testLinkClicked(link, event, URL, "tabshifted");
+
+    event = { shiftKey: true };
+    testLinkClicked(link, event, URL, "window");
+
+    URL = "non-URL";
+    await mockStore.dispatch(
+      { type: "update", details: { DOMNode: {}, accessible: { value: URL } } });
+    link = document.querySelector(".url");
+    ok(!link, "Non URL link should not be rendered as a link.");
+  } catch (e) {
+    ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+  } finally {
+    SimpleTest.finish();
+  }
+};
+</script>
+</pre>
+</body>
+</html>
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -126,17 +126,16 @@ skip-if = e10s # Bug 1069044 - destroyIn
 [browser_toolbox_toolbar_reorder_with_extension.js]
 [browser_toolbox_tools_per_toolbox_registration.js]
 [browser_toolbox_view_source_01.js]
 [browser_toolbox_view_source_02.js]
 [browser_toolbox_view_source_03.js]
 [browser_toolbox_view_source_04.js]
 [browser_toolbox_window_reload_target.js]
 [browser_toolbox_window_shortcuts.js]
-skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5.1" # Bug 851129 - Re-enable browser_toolbox_window_shortcuts.js test after leaks are fixed
 [browser_toolbox_window_title_changes.js]
 [browser_toolbox_window_title_frame_select.js]
 [browser_toolbox_zoom.js]
 [browser_toolbox_zoom_popup.js]
 [browser_two_tabs.js]
 # We want these tests to run for mochitest-dt as well, so we include them here:
 [../../../../browser/base/content/test/static/browser_parsable_css.js]
 skip-if = debug || asan || (os == 'linux' && bits == 32) # no point in running on both opt and debug, and will likely intermittently timeout on debug
--- a/devtools/client/shared/components/reps/reps.js
+++ b/devtools/client/shared/components/reps/reps.js
@@ -939,17 +939,17 @@ function getLinkifiedElements(text, crop
       const linkText = getCroppedString(token, currentIndex, startCropIndex, endCropIndex);
       if (linkText) {
         items.push(a({
           className: "url",
           title: token,
           draggable: false,
           onClick: openLink ? e => {
             e.preventDefault();
-            openLink(token);
+            openLink(token, e);
           } : null
         }, linkText));
       }
 
       currentIndex = tokenStart + token.length;
     }
   }
 
--- a/devtools/client/shared/components/tree/TreeView.js
+++ b/devtools/client/shared/components/tree/TreeView.js
@@ -264,16 +264,22 @@ define(function(require, exports, module
           let { hasChildren, open } = row.props.member;
           if (hasChildren && !open) {
             this.toggle(this.state.selected);
           }
           break;
         case "ArrowLeft":
           if (row && row.props.member.open) {
             this.toggle(this.state.selected);
+          } else {
+            let parentRow = this.rows.slice(0, index).reverse().find(
+              r => r.props.member.level < row.props.member.level);
+            if (parentRow) {
+              this.selectRow(parentRow);
+            }
           }
           break;
         case "ArrowDown":
           let nextRow = this.rows[index + 1];
           if (nextRow) {
             this.selectRow(nextRow);
           }
           break;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -220,16 +220,17 @@
 #endif
 
 #ifdef MOZ_TOOLKIT_SEARCH
 #include "nsIBrowserSearchService.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::net;
 
 // Threshold value in ms for META refresh based redirects
 #define REFRESH_REDIRECT_TIMER 15000
 
 // Hint for native dispatch of events on how long to delay after
 // all documents have loaded in milliseconds before favoring normal
 // native event dispatch priorites over performance
 // Can be overridden with docshell.event_starvation_delay_hint pref.
@@ -678,17 +679,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
   Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
   bool loadReplace = false;
   nsCOMPtr<nsIInputStream> postStream;
   nsCOMPtr<nsIInputStream> headersStream;
   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   bool inheritPrincipal = false;
   bool principalIsExplicit = false;
   bool sendReferrer = true;
-  uint32_t referrerPolicy = mozilla::net::RP_Unset;
+  uint32_t referrerPolicy = RP_Unset;
   bool isSrcdoc = false;
   nsCOMPtr<nsISHEntry> shEntry;
   nsString target;
   nsAutoString srcdoc;
   bool forceAllowDataURI = false;
   bool originalFrameSrc = false;
   nsCOMPtr<nsIDocShell> sourceDocShell;
   nsCOMPtr<nsIURI> baseURI;
@@ -4218,17 +4219,17 @@ NS_IMETHODIMP
 nsDocShell::LoadURI(const char16_t* aURI,
                     uint32_t aLoadFlags,
                     nsIURI* aReferringURI,
                     nsIInputStream* aPostStream,
                     nsIInputStream* aHeaderStream,
                     nsIPrincipal* aTriggeringPrincipal)
 {
   return LoadURIWithOptions(aURI, aLoadFlags, aReferringURI,
-                            mozilla::net::RP_Unset, aPostStream,
+                            RP_Unset, aPostStream,
                             aHeaderStream, nullptr, aTriggeringPrincipal);
 }
 
 NS_IMETHODIMP
 nsDocShell::LoadURIWithOptions(const char16_t* aURI,
                                uint32_t aLoadFlags,
                                nsIURI* aReferringURI,
                                uint32_t aReferrerPolicy,
@@ -4914,18 +4915,17 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   // end of the URL, so append it last.
   errorPageUrl.AppendLiteral("&d=");
   errorPageUrl.AppendASCII(escapedDescription.get());
 
   nsCOMPtr<nsIURI> errorPageURI;
   nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return InternalLoad(errorPageURI, nullptr, Nothing(), false, nullptr,
-                      mozilla::net::RP_Unset,
+  return InternalLoad(errorPageURI, nullptr, Nothing(), false, nullptr, RP_Unset,
                       nsContentUtils::GetSystemPrincipal(), nullptr,
                       INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
                       nullptr, VoidString(), nullptr, nullptr,
                       LOAD_ERROR_PAGE, nullptr, true, VoidString(), this,
                       nullptr, nullptr, nullptr);
 }
 
 NS_IMETHODIMP
@@ -7467,18 +7467,17 @@ nsDocShell::EndPageLoad(nsIWebProgress* 
         aStatus = NS_ERROR_OFFLINE;
       }
       DisplayLoadError(aStatus, url, nullptr, aChannel);
     }
   } else if (url && NS_SUCCEEDED(aStatus)) {
     // If we have a host
     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
     if (loadInfo) {
-      mozilla::net::PredictorLearnRedirect(url, aChannel,
-                                           loadInfo->GetOriginAttributes());
+      PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
     }
   }
 
   return NS_OK;
 }
 
 //*****************************************************************************
 // nsDocShell: Content Viewer Management
@@ -10197,20 +10196,20 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 
   bool isTopLevelDoc = mItemType == typeContent &&
                        (isTargetTopLevelDocShell ||
                         GetIsMozBrowser());
 
   OriginAttributes attrs = GetOriginAttributes();
   attrs.SetFirstPartyDomain(isTopLevelDoc, aURI);
 
-  net::PredictorLearn(aURI, nullptr,
-                      nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
-  net::PredictorPredict(aURI, nullptr,
-                        nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
+  PredictorLearn(aURI, nullptr,
+                 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
+  PredictorPredict(aURI, nullptr,
+                   nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
 
   nsCOMPtr<nsIRequest> req;
   rv = DoURILoad(aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace,
                  loadFromExternal,
                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI),
                  (aFlags & INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC),
                  aReferrer,
                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
@@ -10637,17 +10636,17 @@ nsDocShell::DoURILoad(nsIURI* aURI,
     if (upgradeInsecureRequests) {
       // only upgrade if the navigation is same origin
       nsCOMPtr<nsIPrincipal> resultPrincipal;
       rv = nsContentUtils::GetSecurityManager()->
              GetChannelResultPrincipal(channel,
                                        getter_AddRefs(resultPrincipal));
       NS_ENSURE_SUCCESS(rv, rv);
       if (IsConsideredSameOriginForUIR(aTriggeringPrincipal, resultPrincipal)) {
-        static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
+        static_cast<LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
       }
     }
   }
 
 
   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
     do_QueryInterface(channel);
   if (appCacheChannel) {
@@ -11968,17 +11967,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
   }
 
   // Get the post data & referrer
   nsCOMPtr<nsIInputStream> inputStream;
   nsCOMPtr<nsIURI> originalURI;
   nsCOMPtr<nsIURI> resultPrincipalURI;
   bool loadReplace = false;
   nsCOMPtr<nsIURI> referrerURI;
-  uint32_t referrerPolicy = mozilla::net::RP_Unset;
+  uint32_t referrerPolicy = RP_Unset;
   uint32_t cacheKey = 0;
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
   bool expired = false;
   bool discardLayoutState = false;
   nsCOMPtr<nsICacheInfoChannel> cacheChannel;
   if (aChannel) {
     cacheChannel = do_QueryInterface(aChannel);
@@ -13512,18 +13511,19 @@ nsDocShell::OnLinkClickSync(nsIContent* 
 
   nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
   uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
 
   // get referrer attribute from clicked link and parse it
   // if per element referrer is enabled, the element referrer overrules
   // the document wide referrer
   if (IsElementAnchorOrArea(aContent)) {
-    net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
-    if (refPolEnum != net::RP_Unset) {
+    net::ReferrerPolicy refPolEnum =
+      aContent->AsElement()->GetReferrerPolicyAsEnum();
+    if (refPolEnum != RP_Unset) {
       refererPolicy = refPolEnum;
     }
   }
 
   // referer could be null here in some odd cases, but that's ok,
   // we'll just load the link w/o sending a referer in those cases.
 
   nsAutoString target(aTargetSpec);
@@ -13613,20 +13613,20 @@ nsDocShell::OnOverLink(nsIContent* aCont
   }
 
   nsAutoCString spec;
   rv = aURI->GetDisplaySpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ConvertUTF8toUTF16 uStr(spec);
 
-  mozilla::net::PredictorPredict(aURI, mCurrentURI,
-                                 nsINetworkPredictor::PREDICT_LINK,
-                                 aContent->NodePrincipal()->OriginAttributesRef(),
-                                 nullptr);
+  PredictorPredict(aURI, mCurrentURI,
+                   nsINetworkPredictor::PREDICT_LINK,
+                   aContent->NodePrincipal()->OriginAttributesRef(),
+                   nullptr);
 
   if (browserChrome2) {
     rv = browserChrome2->SetStatusWithContext(nsIWebBrowserChrome::STATUS_LINK,
                                               uStr, aContent);
   } else {
     rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK, uStr.get());
   }
   return rv;
--- a/dom/base/CharacterData.h
+++ b/dom/base/CharacterData.h
@@ -220,19 +220,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(CharacterData,
                                                                    nsIContent)
 
 protected:
   virtual ~CharacterData();
 
   virtual Element* GetNameSpaceElement() override
   {
-    nsINode *parent = GetParentNode();
-
-    return parent && parent->IsElement() ? parent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(GetParentNode());
   }
 
   nsresult SetTextInternal(uint32_t aOffset, uint32_t aCount,
                            const char16_t* aBuffer, uint32_t aLength,
                            bool aNotify,
                            CharacterDataChangeInfo::Details* aDetails = nullptr);
 
   /**
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -162,16 +162,18 @@ public:
   }
 
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
 
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
+  NS_IMPL_FROMNODE_HELPER(Element, IsElement())
+
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   /**
    * Method to get the full state of this element.  See mozilla/EventStates.h
    * for the possible bits that could be set here.
    */
   EventStates State() const
   {
@@ -2043,17 +2045,17 @@ inline mozilla::dom::Element* nsINode::A
 inline const mozilla::dom::Element* nsINode::AsElement() const
 {
   MOZ_ASSERT(IsElement());
   return static_cast<const mozilla::dom::Element*>(this);
 }
 
 inline mozilla::dom::Element* nsINode::GetParentElement() const
 {
-  return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
+  return mozilla::dom::Element::FromNodeOrNull(mParent);
 }
 
 /**
  * Macros to implement Clone(). _elementName is the class for which to implement
  * Clone.
  */
 #define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
 nsresult                                                                    \
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3434,19 +3434,17 @@ nsContentUtils::GetContextForContent(con
 
   return presShell->GetPresContext();
 }
 
 // static
 bool
 nsContentUtils::CanLoadImage(nsIURI* aURI, nsINode* aNode,
                              nsIDocument* aLoadingDocument,
-                             nsIPrincipal* aLoadingPrincipal,
-                             int16_t* aImageBlockingStatus,
-                             uint32_t aContentType)
+                             nsIPrincipal* aLoadingPrincipal)
 {
   MOZ_ASSERT(aURI, "Must have a URI");
   MOZ_ASSERT(aLoadingDocument, "Must have a document");
   MOZ_ASSERT(aLoadingPrincipal, "Must have a loading principal");
 
   nsresult rv;
 
   uint32_t appType = nsIDocShell::APP_TYPE_UNKNOWN;
@@ -3468,43 +3466,34 @@ nsContentUtils::CanLoadImage(nsIURI* aUR
   if (appType != nsIDocShell::APP_TYPE_EDITOR) {
     // Editor apps get special treatment here, editors can load images
     // from anywhere.  This allows editor to insert images from file://
     // into documents that are being edited.
     rv = sSecurityManager->
       CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
                                 nsIScriptSecurityManager::ALLOW_CHROME);
     if (NS_FAILED(rv)) {
-      if (aImageBlockingStatus) {
-        // Reject the request itself, not all requests to the relevant
-        // server...
-        *aImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
-      }
       return false;
     }
   }
 
   nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
-    new LoadInfo(aLoadingPrincipal,
-                 aLoadingPrincipal, // triggering principal
-                 aNode,
-                 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
-                 aContentType);
+    new mozilla::net::LoadInfo(aLoadingPrincipal,
+                               aLoadingPrincipal, // triggering principal
+                               aNode,
+                               nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
+                               nsIContentPolicy::TYPE_INTERNAL_IMAGE);
 
   int16_t decision = nsIContentPolicy::ACCEPT;
 
   rv = NS_CheckContentLoadPolicy(aURI, secCheckLoadInfo,
                                  EmptyCString(), //mime guess
                                  &decision,
                                  GetContentPolicy());
 
-  if (aImageBlockingStatus) {
-    *aImageBlockingStatus =
-      NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
-  }
   return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
 }
 
 // static
 mozilla::OriginAttributes
 nsContentUtils::GetOriginAttributes(nsIDocument* aDocument)
 {
   if (!aDocument) {
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -806,19 +806,17 @@ public:
    * @return true if the load can proceed, or false if it is blocked.
    *         Note that aImageBlockingStatus, if set will always be an ACCEPT
    *         status if true is returned and always be a REJECT_* status if
    *         false is returned.
    */
   static bool CanLoadImage(nsIURI* aURI,
                            nsINode* aNode,
                            nsIDocument* aLoadingDocument,
-                           nsIPrincipal* aLoadingPrincipal,
-                           int16_t* aImageBlockingStatus = nullptr,
-                           uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE);
+                           nsIPrincipal* aLoadingPrincipal);
 
   /**
    * Returns true if objects in aDocument shouldn't initiate image loads.
    */
   static bool DocumentInactiveForImageLoads(nsIDocument* aDocument);
 
   /**
    * Convert a CORSMode into the corresponding imgILoader flags for
--- a/dom/base/nsDataDocumentContentPolicy.cpp
+++ b/dom/base/nsDataDocumentContentPolicy.cpp
@@ -37,43 +37,43 @@ HasFlags(nsIURI* aURI, uint32_t aURIFlag
 // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid.
 // nsContentPolicyUtils may not pass all the parameters to ShouldLoad.
 NS_IMETHODIMP
 nsDataDocumentContentPolicy::ShouldLoad(nsIURI *aContentLocation,
                                         nsILoadInfo* aLoadInfo,
                                         const nsACString &aMimeGuess,
                                         int16_t *aDecision)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestingContext = aLoadInfo->GetLoadingContext();
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  nsCOMPtr<nsISupports> requestingContext = aLoadInfo->GetLoadingContext();
 
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aDecision = nsIContentPolicy::ACCEPT;
-  // Look for the document.  In most cases, aRequestingContext is a node.
+  // Look for the document.  In most cases, requestingContext is a node.
   nsCOMPtr<nsIDocument> doc;
-  nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext);
+  nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
   if (node) {
     doc = node->OwnerDoc();
   } else {
-    if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aRequestingContext)) {
+    if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(requestingContext)) {
       doc = window->GetDoc();
     }
   }
 
   // DTDs are always OK to load
-  if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) {
+  if (!doc || contentType == nsIContentPolicy::TYPE_DTD) {
     return NS_OK;
   }
 
   // Nothing else is OK to load for data documents
   if (doc->IsLoadedAsData()) {
     // ...but let static (print/print preview) documents to load fonts.
-    if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) {
+    if (!doc->IsStaticDocument() || contentType != nsIContentPolicy::TYPE_FONT) {
       *aDecision = nsIContentPolicy::REJECT_TYPE;
       return NS_OK;
     }
   }
 
   nsIDocument* docToCheckForImage = doc->GetDisplayDocument();
   if (!docToCheckForImage) {
     docToCheckForImage = doc;
@@ -100,18 +100,18 @@ nsDataDocumentContentPolicy::ShouldLoad(
         RefPtr<nsIURI> principalURI;
         nsresult rv =
           requestingPrincipal->GetURI(getter_AddRefs(principalURI));
         if (NS_SUCCEEDED(rv) && principalURI) {
           nsScriptSecurityManager::ReportError(
             nullptr, "ExternalDataError", principalURI, aContentLocation);
         }
       }
-    } else if ((aContentType == nsIContentPolicy::TYPE_IMAGE ||
-                aContentType == nsIContentPolicy::TYPE_IMAGESET) &&
+    } else if ((contentType == nsIContentPolicy::TYPE_IMAGE ||
+                contentType == nsIContentPolicy::TYPE_IMAGESET) &&
                doc->GetDocumentURI()) {
       // Check for (& disallow) recursive image-loads
       bool isRecursiveLoad;
       nsresult rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(),
                                                       &isRecursiveLoad);
       if (NS_FAILED(rv) || isRecursiveLoad) {
         NS_WARNING("Refusing to recursively load image");
         *aDecision = nsIContentPolicy::REJECT_TYPE;
@@ -121,23 +121,23 @@ nsDataDocumentContentPolicy::ShouldLoad(
   }
 
   // Allow all loads for non-resource documents
   if (!doc->IsResourceDoc()) {
     return NS_OK;
   }
 
   // For resource documents, blacklist some load types
-  if (aContentType == nsIContentPolicy::TYPE_OBJECT ||
-      aContentType == nsIContentPolicy::TYPE_DOCUMENT ||
-      aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
-      aContentType == nsIContentPolicy::TYPE_SCRIPT ||
-      aContentType == nsIContentPolicy::TYPE_XSLT ||
-      aContentType == nsIContentPolicy::TYPE_FETCH ||
-      aContentType == nsIContentPolicy::TYPE_WEB_MANIFEST) {
+  if (contentType == nsIContentPolicy::TYPE_OBJECT ||
+      contentType == nsIContentPolicy::TYPE_DOCUMENT ||
+      contentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
+      contentType == nsIContentPolicy::TYPE_SCRIPT ||
+      contentType == nsIContentPolicy::TYPE_XSLT ||
+      contentType == nsIContentPolicy::TYPE_FETCH ||
+      contentType == nsIContentPolicy::TYPE_WEB_MANIFEST) {
     *aDecision = nsIContentPolicy::REJECT_TYPE;
   }
 
   // If you add more restrictions here, make sure to check that
   // CHECK_PRINCIPAL_AND_DATA in nsContentPolicyUtils is still valid.
   // nsContentPolicyUtils may not pass all the parameters to ShouldLoad
 
   return NS_OK;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3749,29 +3749,29 @@ nsIDocument::SetHeaderData(nsAtom* aHead
       aHeaderField == nsGkAtoms::viewport_height ||
       aHeaderField == nsGkAtoms::viewport_width ||
       aHeaderField ==  nsGkAtoms::viewport_user_scalable) {
     mViewportType = Unknown;
   }
 
   // Referrer policy spec says to ignore any empty referrer policies.
   if (aHeaderField == nsGkAtoms::referrer && !aData.IsEmpty()) {
-     enum ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData);
+     enum mozilla::net::ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData);
     // If policy is not the empty string, then set element's node document's
     // referrer policy to policy
     if (policy != mozilla::net::RP_Unset) {
       // Referrer policy spec (section 6.1) says that we always use the newest
       // referrer policy we find
       mReferrerPolicy = policy;
       mReferrerPolicySet = true;
     }
   }
 
   if (aHeaderField == nsGkAtoms::headerReferrerPolicy && !aData.IsEmpty()) {
-     enum ReferrerPolicy policy = nsContentUtils::GetReferrerPolicyFromHeader(aData);
+     enum mozilla::net::ReferrerPolicy policy = nsContentUtils::GetReferrerPolicyFromHeader(aData);
     if (policy != mozilla::net::RP_Unset) {
       mReferrerPolicy = policy;
       mReferrerPolicySet = true;
     }
   }
 
 }
 void
@@ -3798,24 +3798,25 @@ nsDocument::TryChannelCharset(nsIChannel
 
 static inline void
 AssertNoStaleServoDataIn(const nsINode& aSubtreeRoot)
 {
 #ifdef DEBUG
   for (const nsINode* node = &aSubtreeRoot;
        node;
        node = node->GetNextNode(&aSubtreeRoot)) {
-    if (!node->IsElement()) {
+    const Element* element = Element::FromNode(node);
+    if (!element) {
       continue;
     }
-    MOZ_ASSERT(!node->AsElement()->HasServoData());
-    if (auto* shadow = node->AsElement()->GetShadowRoot()) {
+    MOZ_ASSERT(!element->HasServoData());
+    if (auto* shadow = element->GetShadowRoot()) {
       AssertNoStaleServoDataIn(*shadow);
     }
-    if (nsXBLBinding* binding = node->AsElement()->GetXBLBinding()) {
+    if (nsXBLBinding* binding = element->GetXBLBinding()) {
       if (nsXBLBinding* bindingWithContent = binding->GetBindingWithContent()) {
         nsIContent* content = bindingWithContent->GetAnonymousContent();
         MOZ_ASSERT(!content->AsElement()->HasServoData());
         for (nsINode* child = content->GetFirstChild();
              child;
              child = child->GetNextSibling()) {
           AssertNoStaleServoDataIn(*child);
         }
@@ -4139,20 +4140,19 @@ nsIDocument::GetRootElementInternal() co
   // We invoke GetRootElement() immediately before the servo traversal, so we
   // should always have a cache hit from Servo.
   MOZ_ASSERT(NS_IsMainThread());
 
   // Loop backwards because any non-elements, such as doctypes and PIs
   // are likely to appear before the root element.
   uint32_t i;
   for (i = mChildren.ChildCount(); i > 0; --i) {
-    nsIContent* child = mChildren.ChildAt(i - 1);
-    if (child->IsElement()) {
-      const_cast<nsIDocument*>(this)->mCachedRootElement = child->AsElement();
-      return child->AsElement();
+    if (Element* element = Element::FromNode(mChildren.ChildAt(i - 1))) {
+      const_cast<nsIDocument*>(this)->mCachedRootElement = element;
+      return element;
     }
   }
 
   const_cast<nsIDocument*>(this)->mCachedRootElement = nullptr;
   return nullptr;
 }
 
 nsresult
@@ -5548,17 +5548,17 @@ nsIDocument::GetAnonRootIfInAnonymousCon
 
   // An arbitrary number of elements can be inserted as children of the custom
   // container frame.  We want the one that was added that contains aNode, so
   // we need to keep track of the last child separately using |child| here.
   nsINode* child = aNode;
   nsINode* parent = aNode->GetParentNode();
   while (parent && parent->IsInNativeAnonymousSubtree()) {
     if (parent == customContainer) {
-      return child->IsElement() ? child->AsElement() : nullptr;
+      return Element::FromNode(child);
     }
     child = parent;
     parent = child->GetParentNode();
   }
   return nullptr;
 }
 
 Maybe<ClientInfo>
@@ -6119,24 +6119,23 @@ nsIDocument::GetAnonymousElementByAttrib
   if (!nodeList)
     return nullptr;
 
   uint32_t length = nodeList->Length();
 
   bool universalMatch = aAttrValue.EqualsLiteral("*");
 
   for (uint32_t i = 0; i < length; ++i) {
-    nsIContent* current = nodeList->Item(i);
-    if (!current->IsElement()) {
+    Element* current = Element::FromNode(nodeList->Item(i));
+    if (!current) {
       continue;
     }
 
     Element* matchedElm =
-      GetElementByAttribute(current->AsElement(), aAttrName, aAttrValue,
-                            universalMatch);
+      GetElementByAttribute(current, aAttrName, aAttrValue, universalMatch);
     if (matchedElm)
       return matchedElm;
   }
 
   return nullptr;
 }
 
 Element*
@@ -6928,22 +6927,20 @@ nsIDocument::GetCompatMode(nsString& aCo
   if (mCompatMode == eCompatibility_NavQuirks) {
     aCompatMode.AssignLiteral("BackCompat");
   } else {
     aCompatMode.AssignLiteral("CSS1Compat");
   }
 }
 
 void
-nsDOMAttributeMap::BlastSubtreeToPieces(nsINode *aNode)
-{
-  if (aNode->IsElement()) {
-    Element *element = aNode->AsElement();
-    const nsDOMAttributeMap *map = element->GetAttributeMap();
-    if (map) {
+nsDOMAttributeMap::BlastSubtreeToPieces(nsINode* aNode)
+{
+  if (Element* element = Element::FromNode(aNode)) {
+    if (const nsDOMAttributeMap* map = element->GetAttributeMap()) {
       while (true) {
         nsCOMPtr<nsIAttribute> attr;
         {
           // Use an iterator to get an arbitrary attribute from the
           // cache. The iterator must be destroyed before any other
           // operations on mAttributeCache, to avoid hash table
           // assertions.
           auto iter = map->mAttributeCache.ConstIter();
@@ -7057,18 +7054,18 @@ nsIDocument::AdoptNode(nsINode& aAdopted
         parent->RemoveChildNode(adoptedNode->AsContent(), true);
       } else {
         MOZ_ASSERT(!adoptedNode->IsInUncomposedDoc());
 
         // If we're adopting a node that's not in a document, it might still
         // have a binding applied. Remove the binding from the element now
         // that it's getting adopted into a new document.
         // TODO Fully tear down the binding.
-        if (adoptedNode->IsElement()) {
-          adoptedNode->AsElement()->SetXBLBinding(nullptr);
+        if (Element* element = Element::FromNode(adoptedNode)) {
+          element->SetXBLBinding(nullptr);
         }
       }
 
       break;
     }
     case DOCUMENT_NODE:
     {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@@ -8956,17 +8953,17 @@ nsIDocument::ResolvePreloadImage(nsIURI 
   // this this <picture> share the same <sources> (though this is not valid per
   // spec)
   return uri.forget();
 }
 
 void
 nsIDocument::MaybePreLoadImage(nsIURI* uri,
                                const nsAString &aCrossOriginAttr,
-                               enum ReferrerPolicy aReferrerPolicy,
+                               enum mozilla::net::ReferrerPolicy aReferrerPolicy,
                                bool aIsImgSet)
 {
   // Early exit if the img is already present in the img-cache
   // which indicates that the "real" load has already started and
   // that we shouldn't preload it.
   if (nsContentUtils::IsImageInCache(uri, this)) {
     return;
   }
@@ -9103,17 +9100,17 @@ public:
 NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
 
 } // namespace
 
 void
 nsIDocument::PreloadStyle(nsIURI* uri,
                           const Encoding* aEncoding,
                           const nsAString& aCrossOriginAttr,
-                          const enum ReferrerPolicy aReferrerPolicy,
+                          const enum mozilla::net::ReferrerPolicy aReferrerPolicy,
                           const nsAString& aIntegrity)
 {
   // The CSSLoader will retain this object after we return.
   nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
 
   // Charset names are always ASCII.
   CSSLoader()->LoadSheet(uri,
                          true,
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -368,21 +368,18 @@ nsDocumentEncoder::SerializeNodeStart(ns
     node = aNode;
 
   if (node->IsElement()) {
     if ((mFlags & (nsIDocumentEncoder::OutputPreformatted |
                    nsIDocumentEncoder::OutputDropInvisibleBreak)) &&
         nsLayoutUtils::IsInvisibleBreak(node)) {
       return NS_OK;
     }
-    Element* originalElement =
-      aOriginalNode && aOriginalNode->IsElement() ?
-        aOriginalNode->AsElement() : nullptr;
-    mSerializer->AppendElementStart(node->AsElement(),
-                                    originalElement, aStr);
+    Element* originalElement = Element::FromNodeOrNull(aOriginalNode);
+    mSerializer->AppendElementStart(node->AsElement(), originalElement, aStr);
     return NS_OK;
   }
 
   switch (node->NodeType()) {
     case nsINode::TEXT_NODE:
     {
       mSerializer->AppendText(static_cast<nsIContent*>(node),
                               aStartOffset, aEndOffset, aStr);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1219,17 +1219,17 @@ nsJSContext::GarbageCollectNow(JS::gcrea
     JS::PrepareForFullGC(cx);
   } else {
     CycleCollectedJSRuntime::Get()->PrepareWaitingZonesForGC();
   }
 
   if (aIncremental == IncrementalGC) {
     JS::StartIncrementalGC(cx, gckind, aReason, aSliceMillis);
   } else {
-    JS::GCForReason(cx, gckind, aReason);
+    JS::NonIncrementalGC(cx, gckind, aReason);
   }
 }
 
 static void
 FinishAnyIncrementalGC()
 {
   AUTO_PROFILER_LABEL("FinishAnyIncrementalGC", GC);
 
--- a/dom/base/nsNoDataProtocolContentPolicy.cpp
+++ b/dom/base/nsNoDataProtocolContentPolicy.cpp
@@ -23,31 +23,31 @@
 NS_IMPL_ISUPPORTS(nsNoDataProtocolContentPolicy, nsIContentPolicy)
 
 NS_IMETHODIMP
 nsNoDataProtocolContentPolicy::ShouldLoad(nsIURI *aContentLocation,
                                           nsILoadInfo *aLoadInfo,
                                           const nsACString &aMimeGuess,
                                           int16_t *aDecision)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
 
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aDecision = nsIContentPolicy::ACCEPT;
 
   // Don't block for TYPE_OBJECT since such URIs are sometimes loaded by the
   // plugin, so they don't necessarily open external apps
   // TYPE_WEBSOCKET loads can only go to ws:// or wss://, so we don't need to
   // concern ourselves with them.
-  if (aContentType != TYPE_DOCUMENT &&
-      aContentType != TYPE_SUBDOCUMENT &&
-      aContentType != TYPE_OBJECT &&
-      aContentType != TYPE_WEBSOCKET) {
+  if (contentType != TYPE_DOCUMENT &&
+      contentType != TYPE_SUBDOCUMENT &&
+      contentType != TYPE_OBJECT &&
+      contentType != TYPE_WEBSOCKET) {
 
     // The following are just quick-escapes for the most common cases
     // where we would allow the content to be loaded anyway.
     nsAutoCString scheme;
     aContentLocation->GetScheme(scheme);
     if (scheme.EqualsLiteral("http") ||
         scheme.EqualsLiteral("https") ||
         scheme.EqualsLiteral("ftp") ||
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -349,23 +349,19 @@ nsNodeUtils::LastRelease(nsINode* aNode)
       }
     }
 #endif
 
     nsContentUtils::RemoveListenerManager(aNode);
     aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
-  if (aNode->IsElement()) {
-    nsIDocument* ownerDoc = aNode->OwnerDoc();
-    Element* elem = aNode->AsElement();
-    ownerDoc->ClearBoxObjectFor(elem);
-
-    NS_ASSERTION(!elem->GetXBLBinding(),
-                 "Node has binding on destruction");
+  if (Element* element = Element::FromNode(aNode)) {
+    element->OwnerDoc()->ClearBoxObjectFor(element);
+    NS_ASSERTION(!element->GetXBLBinding(), "Node has binding on destruction");
   }
 
   aNode->ReleaseWrapper(aNode);
 
   FragmentOrElement::RemoveBlackMarkedNode(aNode);
 }
 
 /* static */
@@ -424,17 +420,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
                                                nodeInfo->GetPrefixAtom(),
                                                nodeInfo->NamespaceID(),
                                                nodeInfo->NodeType(),
                                                nodeInfo->GetExtraName());
 
     nodeInfo = newNodeInfo;
   }
 
-  Element *elem = aNode->IsElement() ? aNode->AsElement() : nullptr;
+  Element* elem = Element::FromNode(aNode);
 
   nsCOMPtr<nsINode> clone;
   if (aClone) {
     nsresult rv = aNode->Clone(nodeInfo, getter_AddRefs(clone), aDeep);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aError.Throw(rv);
       return nullptr;
     }
@@ -491,43 +487,39 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
       // the cloned document (somewhat like cloning and importing them into the
       // cloned document).
       nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
     }
   }
   else if (nodeInfoManager) {
     nsIDocument* oldDoc = aNode->OwnerDoc();
     bool wasRegistered = false;
-    if (aNode->IsElement()) {
-      Element* element = aNode->AsElement();
-      oldDoc->ClearBoxObjectFor(element);
-      wasRegistered = oldDoc->UnregisterActivityObserver(element);
+    if (elem) {
+      oldDoc->ClearBoxObjectFor(elem);
+      wasRegistered = oldDoc->UnregisterActivityObserver(elem);
     }
 
     aNode->mNodeInfo.swap(newNodeInfo);
     if (elem) {
       elem->NodeInfoChanged(oldDoc);
     }
 
     nsIDocument* newDoc = aNode->OwnerDoc();
     if (newDoc) {
-      if (CustomElementRegistry::IsCustomElementEnabled(newDoc)) {
+      if (elem && CustomElementRegistry::IsCustomElementEnabled(newDoc)) {
         // Adopted callback must be enqueued whenever a node’s
         // shadow-including inclusive descendants that is custom.
-        Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
-        if (element) {
-          CustomElementData* data = element->GetCustomElementData();
-          if (data && data->mState == CustomElementData::State::eCustom) {
-            LifecycleAdoptedCallbackArgs args = {
-              oldDoc,
-              newDoc
-            };
-            nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAdopted,
-                                                     element, nullptr, &args);
-          }
+        CustomElementData* data = elem->GetCustomElementData();
+        if (data && data->mState == CustomElementData::State::eCustom) {
+          LifecycleAdoptedCallbackArgs args = {
+            oldDoc,
+            newDoc
+          };
+          nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAdopted,
+                                                   elem, nullptr, &args);
         }
       }
 
       // XXX what if oldDoc is null, we don't know if this should be
       // registered or not! Can that really happen?
       if (wasRegistered) {
         newDoc->RegisterActivityObserver(aNode->AsElement());
       }
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -252,17 +252,17 @@ HTMLLabelElement::GetLabeledElement() co
   return nullptr;
 }
 
 nsGenericHTMLElement*
 HTMLLabelElement::GetFirstLabelableDescendant() const
 {
   for (nsIContent* cur = nsINode::GetFirstChild(); cur;
        cur = cur->GetNextNode(this)) {
-    Element* element = cur->IsElement() ? cur->AsElement() : nullptr;
+    Element* element = Element::FromNode(cur);
     if (element && element->IsLabelable()) {
       return static_cast<nsGenericHTMLElement*>(element);
     }
   }
 
   return nullptr;
 }
 
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -36,16 +36,18 @@ namespace net {
 //
 // set MOZ_LOG=TCPSocket:5
 //
 extern LazyLogModule gTCPSocketLog;
 #define TCPSOCKET_LOG(args)     MOZ_LOG(gTCPSocketLog, LogLevel::Debug, args)
 #define TCPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gTCPSocketLog, LogLevel::Debug)
 } // namespace net
 
+using namespace net;
+
 namespace dom {
 
 static void
 FireInteralError(mozilla::net::PTCPSocketParent* aActor, uint32_t aLineNo)
 {
   mozilla::Unused <<
       aActor->SendCallback(NS_LITERAL_STRING("onerror"),
                            TCPError(NS_LITERAL_STRING("InvalidStateError"), NS_LITERAL_STRING("Internal error")),
--- a/dom/network/UDPSocketParent.cpp
+++ b/dom/network/UDPSocketParent.cpp
@@ -15,16 +15,19 @@
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/net/PNeckoParent.h"
 #include "nsIPermissionManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mtransport/runnable_utils.h"
 
 namespace mozilla {
+
+using namespace net;
+
 namespace dom {
 
 NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener)
 
 UDPSocketParent::UDPSocketParent(PBackgroundParent* aManager)
   : mBackgroundManager(aManager)
   , mIPCOpen(true)
 {
--- a/dom/security/nsCSPService.cpp
+++ b/dom/security/nsCSPService.cpp
@@ -124,76 +124,76 @@ CSPService::ShouldLoad(nsIURI *aContentL
                        nsILoadInfo* aLoadInfo,
                        const nsACString &aMimeTypeGuess,
                        int16_t *aDecision)
 {
   if (!aContentLocation) {
     return NS_ERROR_FAILURE;
   }
 
-  uint32_t aContentType = aLoadInfo->InternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestContext = aLoadInfo->GetLoadingContext();
-  nsCOMPtr<nsIPrincipal> aRequestPrincipal = aLoadInfo->TriggeringPrincipal();
-  nsCOMPtr<nsIURI> aRequestOrigin;
+  uint32_t contentType = aLoadInfo->InternalContentPolicyType();
+  nsCOMPtr<nsISupports> requestContext = aLoadInfo->GetLoadingContext();
+  nsCOMPtr<nsIPrincipal> requestPrincipal = aLoadInfo->TriggeringPrincipal();
+  nsCOMPtr<nsIURI> requestOrigin;
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
   if (loadingPrincipal) {
-    loadingPrincipal->GetURI(getter_AddRefs(aRequestOrigin));
+    loadingPrincipal->GetURI(getter_AddRefs(requestOrigin));
   }
 
   if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
     MOZ_LOG(gCspPRLog, LogLevel::Debug,
            ("CSPService::ShouldLoad called for %s",
            aContentLocation->GetSpecOrDefault().get()));
   }
 
   // default decision, CSP can revise it if there's a policy to enforce
   *aDecision = nsIContentPolicy::ACCEPT;
 
   // No need to continue processing if CSP is disabled or if the protocol
   // or type is *not* subject to CSP.
   // Please note, the correct way to opt-out of CSP using a custom
   // protocolHandler is to set one of the nsIProtocolHandler flags
   // that are whitelistet in subjectToCSP()
-  if (!sCSPEnabled || !subjectToCSP(aContentLocation, aContentType)) {
+  if (!sCSPEnabled || !subjectToCSP(aContentLocation, contentType)) {
     return NS_OK;
   }
 
   // Find a principal to retrieve the CSP from. If we don't have a context node
   // (because, for instance, the load originates in a service worker), or the
   // requesting principal's CSP overrides our document CSP, use the request
   // principal. Otherwise, use the document principal.
-  nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
+  nsCOMPtr<nsINode> node(do_QueryInterface(requestContext));
   nsCOMPtr<nsIPrincipal> principal;
-  if (!node || (aRequestPrincipal &&
-                BasePrincipal::Cast(aRequestPrincipal)->OverridesCSP(node->NodePrincipal()))) {
-    principal = aRequestPrincipal;
+  if (!node || (requestPrincipal &&
+                BasePrincipal::Cast(requestPrincipal)->OverridesCSP(node->NodePrincipal()))) {
+    principal = requestPrincipal;
   } else  {
     principal = node->NodePrincipal();
   }
   if (!principal) {
     // if we can't query a principal, then there is nothing to do.
     return NS_OK;
   }
   nsresult rv = NS_OK;
 
   // 1) Apply speculate CSP for preloads
-  bool isPreload = nsContentUtils::IsPreloadType(aContentType);
+  bool isPreload = nsContentUtils::IsPreloadType(contentType);
 
   if (isPreload) {
     nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
     rv = principal->GetPreloadCsp(getter_AddRefs(preloadCsp));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (preloadCsp) {
       // obtain the enforcement decision
       // (don't pass aExtra, we use that slot for redirects)
-      rv = preloadCsp->ShouldLoad(aContentType,
+      rv = preloadCsp->ShouldLoad(contentType,
                                   aContentLocation,
-                                  aRequestOrigin,
-                                  aRequestContext,
+                                  requestOrigin,
+                                  requestContext,
                                   aMimeTypeGuess,
                                   nullptr, // aExtra
                                   aDecision);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // if the preload policy already denied the load, then there
       // is no point in checking the real policy
       if (NS_CP_REJECTED(*aDecision)) {
@@ -205,20 +205,20 @@ CSPService::ShouldLoad(nsIURI *aContentL
   // 2) Apply actual CSP to all loads
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = principal->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (csp) {
     // obtain the enforcement decision
     // (don't pass aExtra, we use that slot for redirects)
-    rv = csp->ShouldLoad(aContentType,
+    rv = csp->ShouldLoad(contentType,
                          aContentLocation,
-                         aRequestOrigin,
-                         aRequestContext,
+                         requestOrigin,
+                         requestContext,
                          aMimeTypeGuess,
                          nullptr,
                          aDecision);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
@@ -226,31 +226,31 @@ NS_IMETHODIMP
 CSPService::ShouldProcess(nsIURI           *aContentLocation,
                           nsILoadInfo*     aLoadInfo,
                           const nsACString &aMimeTypeGuess,
                           int16_t          *aDecision)
 {
   if (!aContentLocation) {
     return NS_ERROR_FAILURE;
   }
-  uint32_t aContentType = aLoadInfo->InternalContentPolicyType();
+  uint32_t contentType = aLoadInfo->InternalContentPolicyType();
 
   if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
     MOZ_LOG(gCspPRLog, LogLevel::Debug,
             ("CSPService::ShouldProcess called for %s",
             aContentLocation->GetSpecOrDefault().get()));
   }
 
   // ShouldProcess is only relevant to TYPE_OBJECT, so let's convert the
   // internal contentPolicyType to the mapping external one.
   // If it is not TYPE_OBJECT, we can return at this point.
   // Note that we should still pass the internal contentPolicyType
-  // (aContentType) to ShouldLoad().
+  // (contentType) to ShouldLoad().
   uint32_t policyType =
-    nsContentUtils::InternalContentPolicyTypeToExternal(aContentType);
+    nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
 
   if (policyType != nsIContentPolicy::TYPE_OBJECT) {
     *aDecision = nsIContentPolicy::ACCEPT;
     return NS_OK;
   }
 
   return ShouldLoad(aContentLocation,
                     aLoadInfo,
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -89,17 +89,18 @@ nsContentSecurityManager::AllowTopLevelN
     return true;
   }
   nsAutoCString dataSpec;
   uri->GetSpec(dataSpec);
   if (dataSpec.Length() > 50) {
     dataSpec.Truncate(50);
     dataSpec.AppendLiteral("...");
   }
-  nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad());
+  nsCOMPtr<nsISupports> context = loadInfo->ContextForTopLevelLoad();
+  nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(context);
   nsCOMPtr<nsIDocument> doc;
   if (tabChild) {
     doc = static_cast<mozilla::dom::TabChild*>(tabChild.get())->GetDocument();
   }
   NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
   const char16_t* params[] = { specUTF16.get() };
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -270,17 +270,17 @@ LogMixedContentMessage(MixedContentTypes
  * in the current context
  */
 NS_IMETHODIMP
 nsMixedContentBlocker::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
                                               nsIChannel* aNewChannel,
                                               uint32_t aFlags,
                                               nsIAsyncVerifyRedirectCallback* aCallback)
 {
-  nsAsyncRedirectAutoCallback autoCallback(aCallback);
+  mozilla::net::nsAsyncRedirectAutoCallback autoCallback(aCallback);
 
   if (!aOldChannel) {
     NS_ERROR("No channel when evaluating mixed content!");
     return NS_ERROR_FAILURE;
   }
 
   // If we are in the parent process in e10s, we don't have access to the
   // document node, and hence ShouldLoad will fail when we try to get
@@ -354,37 +354,37 @@ nsMixedContentBlocker::AsyncOnChannelRed
  * for detailed description of the parameters.
  */
 NS_IMETHODIMP
 nsMixedContentBlocker::ShouldLoad(nsIURI* aContentLocation,
                                   nsILoadInfo* aLoadInfo,
                                   const nsACString& aMimeGuess,
                                   int16_t* aDecision)
 {
-  uint32_t aContentType = aLoadInfo->InternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestingContext = aLoadInfo->GetLoadingContext();
-  nsCOMPtr<nsIPrincipal> aRequestPrincipal = aLoadInfo->TriggeringPrincipal();
-  nsCOMPtr<nsIURI> aRequestingLocation;
+  uint32_t contentType = aLoadInfo->InternalContentPolicyType();
+  nsCOMPtr<nsISupports> requestingContext = aLoadInfo->GetLoadingContext();
+  nsCOMPtr<nsIPrincipal> requestPrincipal = aLoadInfo->TriggeringPrincipal();
+  nsCOMPtr<nsIURI> requestingLocation;
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
   if (loadingPrincipal) {
-    loadingPrincipal->GetURI(getter_AddRefs(aRequestingLocation));
+    loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
   }
 
   // We pass in false as the first parameter to ShouldLoad(), because the
   // callers of this method don't know whether the load went through cached
   // image redirects.  This is handled by direct callers of the static
   // ShouldLoad.
   nsresult rv = ShouldLoad(false,   // aHadInsecureImageRedirect
-                           aContentType,
+                           contentType,
                            aContentLocation,
-                           aRequestingLocation,
-                           aRequestingContext,
+                           requestingLocation,
+                           requestingContext,
                            aMimeGuess,
                            nullptr, // aExtra,
-                           aRequestPrincipal,
+                           requestPrincipal,
                            aDecision);
   return rv;
 }
 
 bool
 nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL) {
   nsAutoCString host;
   nsresult rv = aURL->GetHost(host);
@@ -1055,27 +1055,25 @@ nsMixedContentBlocker::ShouldLoad(bool a
 }
 
 NS_IMETHODIMP
 nsMixedContentBlocker::ShouldProcess(nsIURI* aContentLocation,
                                      nsILoadInfo* aLoadInfo,
                                      const nsACString& aMimeGuess,
                                      int16_t* aDecision)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-
   if (!aContentLocation) {
     // aContentLocation may be null when a plugin is loading without an associated URI resource
-    if (aContentType == TYPE_OBJECT) {
+    if ( aLoadInfo->GetExternalContentPolicyType() == TYPE_OBJECT) {
        *aDecision = ACCEPT;
        return NS_OK;
-    } else {
-       *aDecision = REJECT_REQUEST;
-       return NS_ERROR_FAILURE;
     }
+
+     *aDecision = REJECT_REQUEST;
+     return NS_ERROR_FAILURE;
   }
 
   return ShouldLoad(aContentLocation, aLoadInfo, aMimeGuess, aDecision);
 }
 
 // Record information on when HSTS would have made mixed content not mixed
 // content (regardless of whether it was actually blocked)
 void
--- a/dom/serviceworkers/ServiceWorkerContainer.cpp
+++ b/dom/serviceworkers/ServiceWorkerContainer.cpp
@@ -296,21 +296,21 @@ ServiceWorkerContainer::Register(const n
 
   // The next section of code executes an NS_CheckContentLoadPolicy()
   // check.  This is necessary to enforce the CSP of the calling client.
   // Currently this requires an nsIDocument.  Once bug 965637 lands we
   // should try to move this into ServiceWorkerScopeAndScriptAreValid()
   // using the ClientInfo instead of doing a window-specific check here.
   // See bug 1455077 for further investigation.
   nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
-    new LoadInfo(doc->NodePrincipal(), // loading principal
-                 doc->NodePrincipal(), // triggering principal
-                 doc,                  // loading node
-                 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
-                 nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER);
+    new mozilla::net::LoadInfo(doc->NodePrincipal(), // loading principal
+                               doc->NodePrincipal(), // triggering principal
+                               doc,                  // loading node
+                               nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
+                               nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER);
 
   // Check content policy.
   int16_t decision = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(scriptURI,
                                  secCheckLoadInfo,
                                  NS_LITERAL_CSTRING("application/javascript"),
                                  &decision);
   if (NS_FAILED(rv)) {
--- a/dom/serviceworkers/ServiceWorkerEvents.cpp
+++ b/dom/serviceworkers/ServiceWorkerEvents.cpp
@@ -332,17 +332,17 @@ public:
     }
 
     AutoTArray<InternalHeaders::Entry, 5> entries;
     mInternalResponse->UnfilteredHeaders()->GetEntries(entries);
     for (uint32_t i = 0; i < entries.Length(); ++i) {
        mChannel->SynthesizeHeader(entries[i].mName, entries[i].mValue);
     }
 
-    auto castLoadInfo = static_cast<LoadInfo*>(loadInfo.get());
+    auto castLoadInfo = static_cast<mozilla::net::LoadInfo*>(loadInfo.get());
     castLoadInfo->SynthesizeServiceWorkerTainting(mInternalResponse->GetTainting());
 
     // Get the preferred alternative data type of outter channel
     nsAutoCString preferredAltDataType(EmptyCString());
     nsCOMPtr<nsICacheInfoChannel> outerChannel = do_QueryInterface(underlyingChannel);
     if (outerChannel) {
       outerChannel->GetPreferredAlternativeDataType(preferredAltDataType);
     }
--- a/dom/serviceworkers/ServiceWorkerRegistrar.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrar.cpp
@@ -58,18 +58,18 @@ static const char* gSupportedRegistrarVe
 
 static const uint32_t kInvalidGeneration = static_cast<uint32_t>(-1);
 
 StaticRefPtr<ServiceWorkerRegistrar> gServiceWorkerRegistrar;
 
 nsresult
 GetOrigin(const nsACString& aURL, nsACString& aOrigin)
 {
-  RefPtr<MozURL> url;
-  nsresult rv = MozURL::Init(getter_AddRefs(url), aURL);
+  RefPtr<net::MozURL> url;
+  nsresult rv = net::MozURL::Init(getter_AddRefs(url), aURL);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   url->Origin(aOrigin);
   return NS_OK;
 }
 
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/dom/SVGAnimationElement.h"
 #include "mozilla/dom/SVGSVGElement.h"
+#include "mozilla/dom/ElementInlines.h"
 #include "nsSMILTimeContainer.h"
 #include "nsSMILAnimationController.h"
 #include "nsSMILAnimationFunction.h"
 #include "nsContentUtils.h"
 #include "nsIContentInlines.h"
 #include "nsIURI.h"
 #include "prtime.h"
 
@@ -66,18 +67,17 @@ SVGAnimationElement::GetTargetElementCon
       HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     return mHrefTarget.get();
   }
   MOZ_ASSERT(!mHrefTarget.get(),
              "We shouldn't have a href target "
              "if we don't have an xlink:href or href attribute");
 
   // No "href" or "xlink:href" attribute --> I should target my parent.
-  nsIContent* parent = GetFlattenedTreeParent();
-  return parent && parent->IsElement() ? parent->AsElement() : nullptr;
+  return GetFlattenedTreeParentElement();
 }
 
 bool
 SVGAnimationElement::GetTargetAttributeName(int32_t *aNamespaceID,
                                             nsAtom **aLocalName) const
 {
   const nsAttrValue* nameAttr
     = mAttrsAndChildren.GetAttr(nsGkAtoms::attributeName);
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -156,17 +156,17 @@ ChannelFromScriptURL(nsIPrincipal* princ
 
   bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
     principal, uri, true /* aInheritForAboutBlank */, false /* aForceInherit */);
 
   bool isData = false;
   rv = uri->SchemeIs("data", &isData);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() && isData;
+  bool isURIUniqueOrigin = net::nsIOService::IsDataURIUniqueOpaqueOrigin() && isData;
   if (inheritAttrs && !isURIUniqueOrigin) {
     secFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
   }
 
   if (aWorkerScriptType == DebuggerScript) {
     // A DebuggerScript needs to be a local resource like chrome: or resource:
     bool isUIResource = false;
     rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1191,32 +1191,33 @@ public:
     extras->pathPrefix += nsPrintfCString("zone(0x%p)/", (void *)aZone);
 
     MOZ_ASSERT(StartsWithExplicit(extras->pathPrefix));
 
     aZoneStats->extra = extras;
   }
 
   virtual void
-  initExtraRealmStats(JSCompartment* aCompartment,
+  initExtraRealmStats(JS::Handle<JS::Realm*> aRealm,
                       JS::RealmStats* aRealmStats)
                       override
   {
     MOZ_ASSERT(!aRealmStats->extra);
 
     // ReportJSRuntimeExplicitTreeStats expects that
     // aRealmStats->extra is a xpc::RealmStatsExtras pointer.
     xpc::RealmStatsExtras* extras = new xpc::RealmStatsExtras;
 
     // This is the |jsPathPrefix|.  Each worker has exactly two realms:
     // one for atoms, and one for everything else.
+    JSCompartment* compartment = JS::GetCompartmentForRealm(aRealm);
     extras->jsPathPrefix.Assign(mRtPath);
     extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
-                                            (void *)js::GetCompartmentZone(aCompartment));
-    extras->jsPathPrefix += js::IsAtomsRealm(JS::GetRealmForCompartment(aCompartment))
+                                            (void *)js::GetCompartmentZone(compartment));
+    extras->jsPathPrefix += js::IsAtomsRealm(aRealm)
                             ? NS_LITERAL_CSTRING("realm(web-worker-atoms)/")
                             : NS_LITERAL_CSTRING("realm(web-worker)/");
 
     // This should never be used when reporting with workers (hence the "?!").
     extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");
 
     MOZ_ASSERT(StartsWithExplicit(extras->jsPathPrefix));
     MOZ_ASSERT(StartsWithExplicit(extras->domPathPrefix));
@@ -5092,24 +5093,24 @@ WorkerPrivate::GarbageCollectInternal(JS
     // We haven't compiled anything yet. Just bail out.
     return;
   }
 
   if (aShrinking || aCollectChildren) {
     JS::PrepareForFullGC(aCx);
 
     if (aShrinking) {
-      JS::GCForReason(aCx, GC_SHRINK, JS::gcreason::DOM_WORKER);
+      JS::NonIncrementalGC(aCx, GC_SHRINK, JS::gcreason::DOM_WORKER);
 
       if (!aCollectChildren) {
         LOG(WorkerLog(), ("Worker %p collected idle garbage\n", this));
       }
     }
     else {
-      JS::GCForReason(aCx, GC_NORMAL, JS::gcreason::DOM_WORKER);
+      JS::NonIncrementalGC(aCx, GC_NORMAL, JS::gcreason::DOM_WORKER);
       LOG(WorkerLog(), ("Worker %p collected garbage\n", this));
     }
   }
   else {
     JS_MaybeGC(aCx);
     LOG(WorkerLog(), ("Worker %p collected periodic garbage\n", this));
   }
 
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -399,27 +399,28 @@ EnsureSubtreeStyled(Element* aElement)
     return;
   }
 
   ServoStyleSet* servoSet = presShell->StyleSet();
   StyleChildrenIterator iter(aElement);
   for (nsIContent* child = iter.GetNextChild();
        child;
        child = iter.GetNextChild()) {
-    if (!child->IsElement()) {
+    Element* element = Element::FromNode(child);
+    if (!element) {
       continue;
     }
 
-    if (child->AsElement()->HasServoData()) {
+    if (element->HasServoData()) {
       // If any child was styled, all of them should be styled already, so we
       // can bail out.
       return;
     }
 
-    servoSet->StyleNewSubtree(child->AsElement());
+    servoSet->StyleNewSubtree(element);
   }
 }
 
 // Ensures that EnsureSubtreeStyled is called on the element on destruction.
 class MOZ_RAII AutoEnsureSubtreeStyled
 {
 public:
   explicit AutoEnsureSubtreeStyled(Element* aElement)
@@ -610,18 +611,17 @@ nsXBLService::AttachGlobalKeyHandler(Eve
   EventListenerManager* manager = piTarget->GetOrCreateListenerManager();
   if (!manager)
     return NS_ERROR_FAILURE;
 
   // the listener already exists, so skip this
   if (contentNode && contentNode->GetProperty(nsGkAtoms::listener))
     return NS_OK;
 
-  Element* elt =
-   contentNode && contentNode->IsElement() ? contentNode->AsElement() : nullptr;
+  Element* elt = Element::FromNodeOrNull(contentNode);
 
   // Create the key handler
   RefPtr<nsXBLWindowKeyHandler> handler =
     NS_NewXBLWindowKeyHandler(elt, piTarget);
 
   handler->InstallKeyboardEventListenersTo(manager);
 
   if (contentNode)
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -1414,22 +1414,21 @@ XULDocument::AddElementToDocumentPost(El
     return NS_OK;
 }
 
 nsresult
 XULDocument::AddSubtreeToDocument(nsIContent* aContent)
 {
     NS_ASSERTION(aContent->GetUncomposedDoc() == this, "Element not in doc!");
     // From here on we only care about elements.
-    if (!aContent->IsElement()) {
+    Element* aElement = Element::FromNode(aContent);
+    if (!aElement) {
         return NS_OK;
     }
 
-    Element* aElement = aContent->AsElement();
-
     // Do pre-order addition magic
     nsresult rv = AddElementToDocumentPre(aElement);
     if (NS_FAILED(rv)) return rv;
 
     // Recurse to children
     for (nsIContent* child = aElement->GetLastChild();
          child;
          child = child->GetPreviousSibling()) {
@@ -1442,22 +1441,21 @@ XULDocument::AddSubtreeToDocument(nsICon
     // Do post-order addition magic
     return AddElementToDocumentPost(aElement);
 }
 
 nsresult
 XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent)
 {
     // From here on we only care about elements.
-    if (!aContent->IsElement()) {
+    Element* aElement = Element::FromNode(aContent);
+    if (!aElement) {
         return NS_OK;
     }
 
-    Element* aElement = aContent->AsElement();
-
     // Do a bunch of cleanup to remove an element from the XUL
     // document.
     nsresult rv;
 
     if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
         nsXBLService::DetachGlobalKeyHandler(aElement);
     }
 
@@ -3704,17 +3702,17 @@ XULDocument::FindBroadcaster(Element* aE
 
         // If we're still parented by an 'overlay' tag, then we haven't
         // made it into the real document yet. Defer hookup.
         if (parent->NodeInfo()->Equals(nsGkAtoms::overlay,
                                        kNameSpaceID_XUL)) {
             return NS_FINDBROADCASTER_AWAIT_OVERLAYS;
         }
 
-        *aListener = parent->IsElement() ? parent->AsElement() : nullptr;
+        *aListener = Element::FromNode(parent);
         NS_IF_ADDREF(*aListener);
 
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::element, aBroadcasterID);
         if (aBroadcasterID.IsEmpty()) {
             return NS_FINDBROADCASTER_NOT_FOUND;
         }
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::attribute, aAttribute);
     }
@@ -3836,24 +3834,24 @@ XULDocument::InsertElement(nsINode* aPar
 {
     // Insert aChild appropriately into aParent, accounting for a
     // 'pos' attribute set on aChild.
 
     nsAutoString posStr;
     bool wasInserted = false;
 
     // insert after an element of a given id
-    if (aChild->IsElement()) {
-        aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
+    if (Element* element = Element::FromNode(aChild)) {
+        element->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
     }
 
     bool isInsertAfter = true;
     if (posStr.IsEmpty()) {
-        if (aChild->IsElement()) {
-            aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
+        if (Element* element = Element::FromNode(aChild)) {
+            element->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
         }
         isInsertAfter = false;
     }
 
     if (!posStr.IsEmpty()) {
         nsIDocument *document = aParent->OwnerDoc();
 
         nsIContent *content = nullptr;
--- a/dom/xul/XULPopupElement.cpp
+++ b/dom/xul/XULPopupElement.cpp
@@ -221,26 +221,26 @@ XULPopupElement::GetState(nsString& aSta
 
 nsINode*
 XULPopupElement::GetTriggerNode() const
 {
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
   return nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
 }
 
+// FIXME(emilio): should probably be renamed to GetAnchorElement?
 Element*
 XULPopupElement::GetAnchorNode() const
 {
-  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
+  nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
   if (!menuPopupFrame) {
     return nullptr;
   }
 
-  nsIContent* anchor = menuPopupFrame->GetAnchor();
-  return anchor && anchor->IsElement() ? anchor->AsElement() : nullptr;
+  return Element::FromNodeOrNull(menuPopupFrame->GetAnchor());
 }
 
 already_AddRefed<DOMRect>
 XULPopupElement::GetOuterScreenRect()
 {
   RefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
 
   // Return an empty rectangle if the popup is not open.
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1261,18 +1261,17 @@ EditorBase::RemoveAttributeWithTransacti
 
 NS_IMETHODIMP
 EditorBase::MarkNodeDirty(nsINode* aNode)
 {
   // Mark the node dirty, but not for webpages (bug 599983)
   if (!OutputsMozDirty()) {
     return NS_OK;
   }
-  if (aNode && aNode->IsElement()) {
-    RefPtr<Element> element = aNode->AsElement();
+  if (RefPtr<Element> element = Element::FromNodeOrNull(aNode)) {
     element->SetAttr(kNameSpaceID_None, nsGkAtoms::mozdirty, EmptyString(),
                      false);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::GetInlineSpellChecker(bool autoCreate,
@@ -3916,26 +3915,25 @@ EditorBase::GetEndChildNode(Selection* a
 bool
 EditorBase::IsPreformatted(nsINode* aNode)
 {
   if (NS_WARN_IF(!aNode)) {
     return false;
   }
   // Look at the node (and its parent if it's not an element), and grab its
   // ComputedStyle.
-  RefPtr<ComputedStyle> elementStyle;
-  Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
+  Element* element = Element::FromNode(aNode);
   if (!element) {
     element = aNode->GetParentElement();
     if (!element) {
       return false;
     }
   }
 
-  elementStyle =
+  RefPtr<ComputedStyle> elementStyle =
     nsComputedDOMStyle::GetComputedStyleNoFlush(element, nullptr);
   if (!elementStyle) {
     // Consider nodes without a ComputedStyle to be NOT preformatted:
     // For instance, this is true of JS tags inside the body (which show
     // up as #text nodes but have no ComputedStyle).
     return false;
   }
 
--- a/editor/libeditor/EditorDOMPoint.h
+++ b/editor/libeditor/EditorDOMPoint.h
@@ -165,17 +165,17 @@ public:
   GetContainerAsContent() const
   {
     return mParent && mParent->IsContent() ? mParent->AsContent() : nullptr;
   }
 
   dom::Element*
   GetContainerAsElement() const
   {
-    return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mParent);
   }
 
   dom::Text*
   GetContainerAsText() const
   {
     return mParent ? mParent->GetAsText() : nullptr;
   }
 
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -372,42 +372,39 @@ public:
   /**
    * GetLeftContent() returns new created node before the part of quarried out.
    * This may return nullptr if the method didn't split at start edge of
    * the node.
    */
   nsIContent* GetLeftContent() const { return mLeftContent; }
   dom::Element* GetLeftContentAsElement() const
   {
-    return mLeftContent && mLeftContent->IsElement() ?
-             mLeftContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mLeftContent);
   }
 
   /**
    * GetMiddleContent() returns new created node between left node and right
    * node.  I.e., this is quarried out from the node.  This may return nullptr
    * if the method unwrapped the middle node.
    */
   nsIContent* GetMiddleContent() const { return mMiddleContent; }
   dom::Element* GetMiddleContentAsElement() const
   {
-    return mMiddleContent && mMiddleContent->IsElement() ?
-             mMiddleContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mMiddleContent);
   }
 
   /**
    * GetRightContent() returns the right node after the part of quarried out.
    * This may return nullptr it the method didn't split at end edge of the
    * node.
    */
   nsIContent* GetRightContent() const { return mRightContent; }
   dom::Element* GetRightContentAsElement() const
   {
-    return mRightContent && mRightContent->IsElement() ?
-             mRightContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mRightContent);
   }
 
   SplitRangeOffFromNodeResult(nsIContent* aLeftContent, nsIContent* aMiddleContent,
                    nsIContent* aRightContent)
     : mLeftContent(aLeftContent)
     , mMiddleContent(aMiddleContent)
     , mRightContent(aRightContent)
     , mRv(NS_OK)
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -2617,28 +2617,26 @@ HTMLEditor::GetSelectedElement(const nsA
       NS_ENSURE_SUCCESS(rv, rv);
 
       iter->Init(currange);
       // loop through the content iterator for each content node
       while (!iter->IsDone()) {
         // Query interface to cast nsIContent to Element
         //  then get tagType to compare to  aTagName
         // Clone node of each desired type and append it to the aDomFrag
-        nsINode* currentNode = iter->GetCurrentNode();
-        selectedElement = currentNode && currentNode->IsElement() ?
-          currentNode->AsElement() : nullptr;
+        selectedElement = Element::FromNodeOrNull(iter->GetCurrentNode());
         if (selectedElement) {
           // If we already found a node, then we have another element,
           //  thus there's not just one element selected
           if (bNodeFound) {
             bNodeFound = false;
             break;
           }
 
-          domTagName = currentNode->NodeName();
+          domTagName = selectedElement->NodeName();
           ToLowerCase(domTagName);
 
           if (anyTag) {
             // Get name of first selected element
             selectedElement->GetTagName(TagName);
             ToLowerCase(TagName);
             anyTag = false;
           }
--- a/extensions/permissions/nsContentBlocker.cpp
+++ b/extensions/permissions/nsContentBlocker.cpp
@@ -154,54 +154,54 @@ nsContentBlocker::PrefChanged(nsIPrefBra
 
 // nsIContentPolicy Implementation
 NS_IMETHODIMP
 nsContentBlocker::ShouldLoad(nsIURI           *aContentLocation,
                              nsILoadInfo      *aLoadInfo,
                              const nsACString &aMimeGuess,
                              int16_t          *aDecision)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
-  nsCOMPtr<nsIURI> aRequestingLocation;
+  nsCOMPtr<nsIURI> requestingLocation;
   if (loadingPrincipal) {
-    loadingPrincipal->GetURI(getter_AddRefs(aRequestingLocation));
+    loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
   }
 
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aDecision = nsIContentPolicy::ACCEPT;
   nsresult rv;
 
   // Ony support NUMBER_OF_TYPES content types. that all there is at the
   // moment, but you never know...
-  if (aContentType > NUMBER_OF_TYPES)
+  if (contentType > NUMBER_OF_TYPES)
     return NS_OK;
 
   // we can't do anything without this
   if (!aContentLocation)
     return NS_OK;
 
   // The final type of an object tag may mutate before it reaches
   // shouldProcess, so we cannot make any sane blocking decisions here
-  if (aContentType == nsIContentPolicy::TYPE_OBJECT)
+  if (contentType == nsIContentPolicy::TYPE_OBJECT)
     return NS_OK;
 
   // we only want to check http, https, ftp
   // for chrome:// and resources and others, no need to check.
   nsAutoCString scheme;
   aContentLocation->GetScheme(scheme);
   if (!scheme.LowerCaseEqualsLiteral("ftp") &&
       !scheme.LowerCaseEqualsLiteral("http") &&
       !scheme.LowerCaseEqualsLiteral("https"))
     return NS_OK;
 
   bool shouldLoad, fromPrefs;
-  rv = TestPermission(aContentLocation, aRequestingLocation, aContentType,
+  rv = TestPermission(aContentLocation, requestingLocation, contentType,
                       &shouldLoad, &fromPrefs);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!shouldLoad) {
     if (fromPrefs) {
       *aDecision = nsIContentPolicy::REJECT_TYPE;
     } else {
       *aDecision = nsIContentPolicy::REJECT_SERVER;
     }
@@ -211,50 +211,50 @@ nsContentBlocker::ShouldLoad(nsIURI     
 }
 
 NS_IMETHODIMP
 nsContentBlocker::ShouldProcess(nsIURI           *aContentLocation,
                                 nsILoadInfo      *aLoadInfo,
                                 const nsACString &aMimeGuess,
                                 int16_t          *aDecision)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestingContext = aLoadInfo->GetLoadingContext();
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  nsCOMPtr<nsISupports> requestingContext = aLoadInfo->GetLoadingContext();
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
-  nsCOMPtr<nsIURI> aRequestingLocation;
+  nsCOMPtr<nsIURI> requestingLocation;
   if (loadingPrincipal) {
-    loadingPrincipal->GetURI(getter_AddRefs(aRequestingLocation));
+    loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
   }
 
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
-  // For loads where aRequestingContext is chrome, we should just
+  // For loads where requesting context is chrome, we should just
   // accept.  Those are most likely toplevel loads in windows, and
   // chrome generally knows what it's doing anyway.
   nsCOMPtr<nsIDocShellTreeItem> item =
-    do_QueryInterface(NS_CP_GetDocShellFromContext(aRequestingContext));
+    do_QueryInterface(NS_CP_GetDocShellFromContext(requestingContext));
 
   if (item && item->ItemType() == nsIDocShellTreeItem::typeChrome) {
     *aDecision = nsIContentPolicy::ACCEPT;
     return NS_OK;
   }
 
   // For objects, we only check policy in shouldProcess, as the final type isn't
   // determined until the channel is open -- We don't want to block images in
   // object tags because plugins are disallowed.
   // NOTE that this bypasses the aContentLocation checks in ShouldLoad - this is
   // intentional, as aContentLocation may be null for plugins that load by type
   // (e.g. java)
-  if (aContentType == nsIContentPolicy::TYPE_OBJECT) {
+  if (contentType == nsIContentPolicy::TYPE_OBJECT) {
     *aDecision = nsIContentPolicy::ACCEPT;
 
     bool shouldLoad, fromPrefs;
-    nsresult rv = TestPermission(aContentLocation, aRequestingLocation,
-                                 aContentType, &shouldLoad, &fromPrefs);
+    nsresult rv = TestPermission(aContentLocation, requestingLocation,
+                                 contentType, &shouldLoad, &fromPrefs);
     NS_ENSURE_SUCCESS(rv, rv);
     if (!shouldLoad) {
       if (fromPrefs) {
         *aDecision = nsIContentPolicy::REJECT_TYPE;
       } else {
         *aDecision = nsIContentPolicy::REJECT_SERVER;
       }
     }
--- a/gfx/layers/D3D11YCbCrImage.cpp
+++ b/gfx/layers/D3D11YCbCrImage.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "D3D11YCbCrImage.h"
 #include "YCbCrUtils.h"
 #include "mozilla/gfx/gfxVars.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/TextureD3D11.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
@@ -51,50 +52,55 @@ D3D11YCbCrImage::SetData(KnowsCompositor
   mColorSpace = aData.mYUVColorSpace;
 
   D3D11YCbCrRecycleAllocator* allocator =
     aContainer->GetD3D11YCbCrRecycleAllocator(aAllocator);
   if (!allocator) {
     return false;
   }
 
+  RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
+  if (!device) {
+    return false;
+  }
+
   {
-    DXGIYCbCrTextureAllocationHelper helper(aData, TextureFlags::DEFAULT, allocator->GetDevice());
+    DXGIYCbCrTextureAllocationHelper helper(aData, TextureFlags::DEFAULT, device);
     mTextureClient = allocator->CreateOrRecycle(helper);
   }
 
   if (!mTextureClient) {
     return false;
   }
 
   DXGIYCbCrTextureData* data =
     mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
 
   ID3D11Texture2D* textureY = data->GetD3D11Texture(0);
   ID3D11Texture2D* textureCb = data->GetD3D11Texture(1);
   ID3D11Texture2D* textureCr = data->GetD3D11Texture(2);
 
   RefPtr<ID3D10Multithread> mt;
-  HRESULT hr = allocator->GetDevice()->QueryInterface(
+  HRESULT hr = device->QueryInterface(
     (ID3D10Multithread**)getter_AddRefs(mt));
 
   if (FAILED(hr) || !mt) {
     gfxCriticalError() << "Multithread safety interface not supported. " << hr;
     return false;
   }
 
   if (!mt->GetMultithreadProtected()) {
     gfxCriticalError() << "Device used not marked as multithread-safe.";
     return false;
   }
 
   D3D11MTAutoEnter mtAutoEnter(mt.forget());
 
   RefPtr<ID3D11DeviceContext> ctx;
-  allocator->GetDevice()->GetImmediateContext(getter_AddRefs(ctx));
+  device->GetImmediateContext(getter_AddRefs(ctx));
   if (!ctx) {
     gfxCriticalError() << "Failed to get immediate context.";
     return false;
   }
 
   AutoLockD3D11Texture lockY(textureY);
   AutoLockD3D11Texture lockCb(textureCb);
   AutoLockD3D11Texture lockCr(textureCr);
@@ -318,16 +324,24 @@ DXGIYCbCrTextureAllocationHelper::IsComp
   DXGIYCbCrTextureData* dxgiData = aTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
   if (!dxgiData ||
       aTextureClient->GetSize() != mData.mYSize ||
       dxgiData->GetYSize() != mData.mYSize ||
       dxgiData->GetCbCrSize() != mData.mCbCrSize ||
       dxgiData->GetYUVColorSpace() != mData.mYUVColorSpace) {
     return false;
   }
+
+  RefPtr<ID3D11Texture2D> texY = dxgiData->GetD3D11Texture(0);
+  RefPtr<ID3D11Device> device;
+  texY->GetDevice(getter_AddRefs(device));
+  if (!device || device != gfx::DeviceManagerDx::Get()->GetImageDevice()) {
+    return false;
+  }
+
   return true;
 }
 
 already_AddRefed<TextureClient>
 DXGIYCbCrTextureAllocationHelper::Allocate(KnowsCompositor* aAllocator)
 {
   CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, mData.mYSize.width, mData.mYSize.height,
                                 1, 1);
--- a/gfx/layers/D3D11YCbCrImage.h
+++ b/gfx/layers/D3D11YCbCrImage.h
@@ -20,35 +20,30 @@ namespace layers {
 
 class ImageContainer;
 class DXGIYCbCrTextureClient;
 class DXGIYCbCrTextureData;
 
 class D3D11YCbCrRecycleAllocator : public TextureClientRecycleAllocator
 {
 public:
-  explicit D3D11YCbCrRecycleAllocator(KnowsCompositor* aAllocator,
-                                      ID3D11Device* aDevice)
+  explicit D3D11YCbCrRecycleAllocator(KnowsCompositor* aAllocator)
     : TextureClientRecycleAllocator(aAllocator)
-    , mDevice(aDevice)
   {
   }
 
-  ID3D11Device* GetDevice() const { return mDevice; }
   KnowsCompositor* GetAllocator() const { return mSurfaceAllocator; }
 
 protected:
   already_AddRefed<TextureClient>
   Allocate(gfx::SurfaceFormat aFormat,
            gfx::IntSize aSize,
            BackendSelector aSelector,
            TextureFlags aTextureFlags,
            TextureAllocationFlags aAllocFlags) override;
-
-  RefPtr<ID3D11Device> mDevice;
 };
 
 class D3D11YCbCrImage : public Image
 {
   friend class gl::GLBlitHelper;
 public:
   D3D11YCbCrImage();
   virtual ~D3D11YCbCrImage();
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -467,36 +467,23 @@ ImageContainer::NotifyComposite(const Im
 D3D11YCbCrRecycleAllocator*
 ImageContainer::GetD3D11YCbCrRecycleAllocator(KnowsCompositor* aAllocator)
 {
   if (mD3D11YCbCrRecycleAllocator &&
       aAllocator == mD3D11YCbCrRecycleAllocator->GetAllocator()) {
     return mD3D11YCbCrRecycleAllocator;
   }
 
-  RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetContentDevice();
-  if (!device) {
-    device = gfx::DeviceManagerDx::Get()->GetCompositorDevice();
-  }
-
-  if (!device || !aAllocator->SupportsD3D11()) {
+  if (!aAllocator->SupportsD3D11() ||
+      !gfx::DeviceManagerDx::Get()->GetImageDevice()) {
     return nullptr;
   }
 
-  RefPtr<ID3D10Multithread> multi;
-  HRESULT hr =
-    device->QueryInterface((ID3D10Multithread**)getter_AddRefs(multi));
-  if (FAILED(hr) || !multi) {
-    gfxWarning() << "Multithread safety interface not supported. " << hr;
-    return nullptr;
-  }
-  multi->SetMultithreadProtected(TRUE);
-
   mD3D11YCbCrRecycleAllocator =
-    new D3D11YCbCrRecycleAllocator(aAllocator, device);
+    new D3D11YCbCrRecycleAllocator(aAllocator);
   return mD3D11YCbCrRecycleAllocator;
 }
 #endif
 
 PlanarYCbCrImage::PlanarYCbCrImage()
   : Image(nullptr, ImageFormat::PLANAR_YCBCR)
   , mOffscreenFormat(SurfaceFormat::UNKNOWN)
   , mBufferSize(0)
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -862,16 +862,17 @@ DeviceManagerDx::ResetDevices()
 
   MutexAutoLock lock(mDeviceLock);
 
   mAdapter = nullptr;
   mCompositorAttachments = nullptr;
   mMLGDevice = nullptr;
   mCompositorDevice = nullptr;
   mContentDevice = nullptr;
+  mImageDevice = nullptr;
   mDeviceStatus = Nothing();
   mDeviceResetReason = Nothing();
   Factory::SetDirect3D11Device(nullptr);
 }
 
 bool
 DeviceManagerDx::MaybeResetAndReacquireDevices()
 {
@@ -1049,16 +1050,47 @@ DeviceManagerDx::GetCompositorDevice()
 RefPtr<ID3D11Device>
 DeviceManagerDx::GetContentDevice()
 {
   MutexAutoLock lock(mDeviceLock);
   return mContentDevice;
 }
 
 RefPtr<ID3D11Device>
+DeviceManagerDx::GetImageDevice()
+{
+  MutexAutoLock lock(mDeviceLock);
+  if (mImageDevice) {
+    return mImageDevice;
+  }
+
+  RefPtr<ID3D11Device> device = mContentDevice;
+  if (!device) {
+    device = mCompositorDevice;
+  }
+
+  if (!device) {
+    return nullptr;
+  }
+
+  RefPtr<ID3D10Multithread> multi;
+  HRESULT hr =
+    device->QueryInterface((ID3D10Multithread**)getter_AddRefs(multi));
+  if (FAILED(hr) || !multi) {
+    gfxWarning() << "Multithread safety interface not supported. " << hr;
+    return nullptr;
+  }
+  multi->SetMultithreadProtected(TRUE);
+
+  mImageDevice = device;
+
+  return mImageDevice;
+}
+
+RefPtr<ID3D11Device>
 DeviceManagerDx::GetVRDevice()
 {
   MutexAutoLock lock(mDeviceLock);
   if (!mVRDevice) {
     CreateVRDevice();
   }
   return mVRDevice;
 }
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -53,16 +53,17 @@ public:
   DeviceManagerDx();
 
   static DeviceManagerDx* Get() {
     return sInstance;
   }
 
   RefPtr<ID3D11Device> GetCompositorDevice();
   RefPtr<ID3D11Device> GetContentDevice();
+  RefPtr<ID3D11Device> GetImageDevice();
   RefPtr<IDCompositionDevice> GetDirectCompositionDevice();
   RefPtr<ID3D11Device> GetVRDevice();
   RefPtr<ID3D11Device> CreateDecoderDevice();
   RefPtr<layers::MLGDevice> GetMLGDevice();
   IDirectDraw7* GetDirectDraw();
 
   unsigned GetCompositorFeatureLevel() const;
   bool TextureSharingWorks();
@@ -158,16 +159,17 @@ private:
 
   nsModuleHandle mDcompModule;
 
   mozilla::Mutex mDeviceLock;
   nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
   RefPtr<IDXGIAdapter1> mAdapter;
   RefPtr<ID3D11Device> mCompositorDevice;
   RefPtr<ID3D11Device> mContentDevice;
+  RefPtr<ID3D11Device> mImageDevice;
   RefPtr<ID3D11Device> mVRDevice;
   RefPtr<ID3D11Device> mDecoderDevice;
   RefPtr<IDCompositionDevice> mDirectCompositionDevice;
 
   RefPtr<layers::DeviceAttachmentsD3D11> mCompositorAttachments;
   RefPtr<layers::MLGDevice> mMLGDevice;
   bool mCompositorDeviceSupportsVideo;
 
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -351,28 +351,32 @@ Decoder::AllocateFrameInternal(const gfx
   RawAccessFrameRef ref = frame->RawAccessRef();
   if (!ref) {
     frame->Abort();
     return RawAccessFrameRef();
   }
 
   if (frameNum == 1) {
     MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated");
+    aPreviousFrame->SetRawAccessOnly();
+
     // If we dispose of the first frame by clearing it, then the first frame's
     // refresh area is all of itself.
     // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR).
     DisposalMethod prevDisposal = aPreviousFrame->GetDisposalMethod();
     if (prevDisposal == DisposalMethod::CLEAR ||
         prevDisposal == DisposalMethod::CLEAR_ALL ||
         prevDisposal == DisposalMethod::RESTORE_PREVIOUS) {
       mFirstFrameRefreshArea = aPreviousFrame->GetRect();
     }
   }
 
   if (frameNum > 0) {
+    ref->SetRawAccessOnly();
+
     // Some GIFs are huge but only have a small area that they animate. We only
     // need to refresh that small area when frame 0 comes around again.
     mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, frame->GetRect());
   }
 
   mFrameCount++;
 
   return ref;
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -309,23 +309,16 @@ imgFrame::InitForDecoder(const nsIntSize
 
     if (!ClearSurface(mRawSurface, mFrameRect.Size(), mFormat)) {
       NS_WARNING("Could not clear allocated buffer");
       mAborted = true;
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
-  if (aAnimParams) {
-    // We never want to unlock animated frames because we need the raw frame
-    // buffer for blending with future frames. Adding an extra unmatched lock
-    // here will guarantee that.
-    ++mLockCount;
-  }
-
   return NS_OK;
 }
 
 nsresult
 imgFrame::InitWithDrawable(gfxDrawable* aDrawable,
                            const nsIntSize& aSize,
                            const SurfaceFormat aFormat,
                            SamplingFilter aSamplingFilter,
@@ -502,16 +495,26 @@ imgFrame::DrawableRef()
 }
 
 RawAccessFrameRef
 imgFrame::RawAccessRef(bool aOnlyFinished /*= false*/)
 {
   return RawAccessFrameRef(this, aOnlyFinished);
 }
 
+void
+imgFrame::SetRawAccessOnly()
+{
+  AssertImageDataLocked();
+
+  // Lock our data and throw away the key.
+  LockImageData(false);
+}
+
+
 imgFrame::SurfaceWithFormat
 imgFrame::SurfaceForDrawing(bool               aDoPartialDecode,
                             bool               aDoTile,
                             ImageRegion&       aRegion,
                             SourceSurface*     aSurface)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mMonitor.AssertCurrentThreadOwns();
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -98,16 +98,28 @@ public:
   /**
    * Create a RawAccessFrameRef for the frame.
    *
    * @param aOnlyFinished If true, only return a valid RawAccessFrameRef if
    *                      imgFrame::Finish has been called.
    */
   RawAccessFrameRef RawAccessRef(bool aOnlyFinished = false);
 
+  /**
+   * Make this imgFrame permanently available for raw access.
+   *
+   * This is irrevocable, and should be avoided whenever possible, since it
+   * prevents this imgFrame from being optimized and makes it impossible for its
+   * volatile buffer to be freed.
+   *
+   * It is an error to call this without already holding a RawAccessFrameRef to
+   * this imgFrame.
+   */
+  void SetRawAccessOnly();
+
   bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
             SamplingFilter aSamplingFilter, uint32_t aImageFlags,
             float aOpacity);
 
   nsresult ImageUpdated(const nsIntRect& aUpdateRect);
 
   /**
    * Mark this imgFrame as completely decoded, and set final options.
--- a/ipc/glue/BackgroundUtils.h
+++ b/ipc/glue/BackgroundUtils.h
@@ -49,18 +49,16 @@ struct ParamTraits<mozilla::OriginAttrib
 
 namespace mozilla {
 namespace net {
 class OptionalLoadInfoArgs;
 class ParentLoadInfoForwarderArgs;
 class RedirectHistoryEntryInfo;
 } // namespace net
 
-using namespace mozilla::net;
-
 namespace ipc {
 
 class PrincipalInfo;
 
 /**
  * Convert a PrincipalInfo to an nsIPrincipal.
  *
  * MUST be called on the main thread only.
@@ -85,51 +83,51 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
 bool
 IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo);
 
 /**
  * Convert an RedirectHistoryEntryInfo to a nsIRedirectHistoryEntry.
  */
 
 already_AddRefed<nsIRedirectHistoryEntry>
-RHEntryInfoToRHEntry(const RedirectHistoryEntryInfo& aRHEntryInfo);
+RHEntryInfoToRHEntry(const mozilla::net::RedirectHistoryEntryInfo& aRHEntryInfo);
 
 /**
  * Convert an nsIRedirectHistoryEntry to a RedirectHistoryEntryInfo.
  */
 
 nsresult
 RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry,
-                     RedirectHistoryEntryInfo* aRHEntryInfo);
+                     mozilla::net::RedirectHistoryEntryInfo* aRHEntryInfo);
 
 /**
  * Convert a LoadInfo to LoadInfoArgs struct.
  */
 nsresult
 LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
-                       OptionalLoadInfoArgs* outOptionalLoadInfoArgs);
+                       mozilla::net::OptionalLoadInfoArgs* outOptionalLoadInfoArgs);
 
 /**
  * Convert LoadInfoArgs to a LoadInfo.
  */
 nsresult
-LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
+LoadInfoArgsToLoadInfo(const mozilla::net::OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
                        nsILoadInfo** outLoadInfo);
 
 /**
  * Fills ParentLoadInfoForwarderArgs with properties we want to carry to child processes.
  */
 void
 LoadInfoToParentLoadInfoForwarder(nsILoadInfo *aLoadInfo,
-                                  ParentLoadInfoForwarderArgs* outLoadInfoChildForwardArgs);
+                                  mozilla::net::ParentLoadInfoForwarderArgs* outLoadInfoChildForwardArgs);
 
 /**
  * Merges (replaces) properties of an existing LoadInfo on a child process
  * with properties carried down through ParentLoadInfoForwarderArgs.
  */
 nsresult
-MergeParentLoadInfoForwarder(ParentLoadInfoForwarderArgs const& outLoadInfoChildForwardArgs,
+MergeParentLoadInfoForwarder(mozilla::net::ParentLoadInfoForwarderArgs const& outLoadInfoChildForwardArgs,
                              nsILoadInfo *aLoadInfo);
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_backgroundutils_h__
--- a/ipc/glue/URIUtils.cpp
+++ b/ipc/glue/URIUtils.cpp
@@ -100,17 +100,17 @@ DeserializeURI(const URIParams& aParams)
       mutator = do_CreateInstance(kIconURIMutatorCID);
       break;
 
     case URIParams::TNullPrincipalURIParams:
       mutator = new NullPrincipalURI::Mutator();
       break;
 
     case URIParams::TSimpleNestedURIParams:
-      mutator = new nsSimpleNestedURI::Mutator();
+      mutator = new net::nsSimpleNestedURI::Mutator();
       break;
 
     case URIParams::THostObjectURIParams:
       mutator = new nsHostObjectURI::Mutator();
       break;
 
     default:
       MOZ_CRASH("Unknown params!");
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -34,17 +34,17 @@ MaybeForceDebugGC()
     static bool sDebugGCs = false;
 
     if (!sEnvVarInitialized)
         sDebugGCs = !!PR_GetEnv("MOZ_DEBUG_DEAD_CPOWS");
 
     if (sDebugGCs) {
         JSContext* cx = XPCJSContext::Get()->Context();
         PrepareForFullGC(cx);
-        GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
+        NonIncrementalGC(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
     }
 }
 
 bool
 WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs)
 {
     // By default, we set |undefined| unless we can get a more meaningful
     // exception.
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -480,17 +480,17 @@ SkipZoneForGC(Zone* zone);
  *
  * If the gckind argument is GC_NORMAL, then some objects that are unreachable
  * from the program may still be alive afterwards because of internal
  * references; if GC_SHRINK is passed then caches and other temporary references
  * to objects will be cleared and all unreferenced objects will be removed from
  * the system.
  */
 extern JS_PUBLIC_API(void)
-GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
+NonIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
 
 /*
  * Incremental GC:
  *
  * Incremental GC divides the full mark-and-sweep collection into multiple
  * slices, allowing client JavaScript code to run between each slice. This
  * allows interactive apps to avoid long collection pauses. Incremental GC does
  * not make collection take less time, it merely spreads that time out so that
@@ -529,17 +529,17 @@ StartIncrementalGC(JSContext* cx, JSGCIn
  *       shorter than the requested interval.
  */
 extern JS_PUBLIC_API(void)
 IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
 
 /**
  * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
  * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
- * this is equivalent to GCForReason. When this function returns,
+ * this is equivalent to NonIncrementalGC. When this function returns,
  * IsIncrementalGCInProgress(cx) will always be false.
  */
 extern JS_PUBLIC_API(void)
 FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
 
 /**
  * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
  * performs whatever work needs to be done to return the collector to its idle
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -975,17 +975,17 @@ struct RuntimeStats
 
     RealmStatsVector realmStatsVector;
     ZoneStatsVector zoneStatsVector;
 
     ZoneStats* currZoneStats;
 
     mozilla::MallocSizeOf mallocSizeOf_;
 
-    virtual void initExtraRealmStats(JSCompartment* c, RealmStats* rstats) = 0;
+    virtual void initExtraRealmStats(JS::Handle<JS::Realm*> realm, RealmStats* rstats) = 0;
     virtual void initExtraZoneStats(JS::Zone* zone, ZoneStats* zstats) = 0;
 
 #undef FOR_EACH_SIZE
 };
 
 class ObjectPrivateVisitor
 {
   public:
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -416,17 +416,17 @@ js::DirectEval(JSContext* cx, HandleValu
     // Direct eval can assume it was called from an interpreted or baseline frame.
     ScriptFrameIter iter(cx);
     AbstractFramePtr caller = iter.abstractFramePtr();
 
     MOZ_ASSERT(JSOp(*iter.pc()) == JSOP_EVAL ||
                JSOp(*iter.pc()) == JSOP_STRICTEVAL ||
                JSOp(*iter.pc()) == JSOP_SPREADEVAL ||
                JSOp(*iter.pc()) == JSOP_STRICTSPREADEVAL);
-    MOZ_ASSERT(caller.compartment() == caller.script()->compartment());
+    MOZ_ASSERT(caller.realm() == caller.script()->realm());
 
     RootedObject envChain(cx, caller.environmentChain());
     return EvalKernel(cx, v, DIRECT_EVAL, caller, envChain, iter.pc(), vp);
 }
 
 bool
 js::IsAnyBuiltinEval(JSFunction* fun)
 {
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -343,17 +343,17 @@ GC(JSContext* cx, unsigned argc, Value* 
 #endif
 
     if (zone)
         PrepareForDebugGC(cx->runtime());
     else
         JS::PrepareForFullGC(cx);
 
     JSGCInvocationKind gckind = shrinking ? GC_SHRINK : GC_NORMAL;
-    JS::GCForReason(cx, gckind, JS::gcreason::API);
+    JS::NonIncrementalGC(cx, gckind, JS::gcreason::API);
 
     char buf[256] = { '\0' };
 #ifndef JS_MORE_DETERMINISTIC
     SprintfLiteral(buf, "before %zu, after %zu\n",
                    preBytes, cx->runtime()->gc.usage.gcBytes());
 #endif
     return ReturnStringCopy(cx, args, buf);
 }
@@ -507,17 +507,17 @@ RelazifyFunctions(JSContext* cx, unsigne
     // Relazifying functions on GC is usually only done for compartments that are
     // not active. To aid fuzzing, this testing function allows us to relazify
     // even if the compartment is active.
 
     CallArgs args = CallArgsFromVp(argc, vp);
     SetAllowRelazification(cx, true);
 
     JS::PrepareForFullGC(cx);
-    JS::GCForReason(cx, GC_SHRINK, JS::gcreason::API);
+    JS::NonIncrementalGC(cx, GC_SHRINK, JS::gcreason::API);
 
     SetAllowRelazification(cx, false);
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 IsProxy(JSContext* cx, unsigned argc, Value* vp)
@@ -4207,17 +4207,17 @@ majorGC(JSContext* cx, JSGCStatus status
 {
     auto info = static_cast<MajorGC*>(data);
     if (!(info->phases & (1 << status)))
         return;
 
     if (info->depth > 0) {
         info->depth--;
         JS::PrepareForFullGC(cx);
-        JS::GCForReason(cx, GC_NORMAL, JS::gcreason::API);
+        JS::NonIncrementalGC(cx, GC_NORMAL, JS::gcreason::API);
         info->depth++;
     }
 }
 
 struct MinorGC {
     int32_t phases;
     bool active;
 };
--- a/js/src/fuzz-tests/testBinASTReader.cpp
+++ b/js/src/fuzz-tests/testBinASTReader.cpp
@@ -30,17 +30,17 @@ static int
 testBinASTReaderInit(int *argc, char ***argv) {
   return 0;
 }
 
 static int
 testBinASTReaderFuzz(const uint8_t* buf, size_t size) {
     auto gcGuard = mozilla::MakeScopeExit([&] {
         JS::PrepareForFullGC(gCx);
-        JS::GCForReason(gCx, GC_NORMAL, JS::gcreason::API);
+        JS::NonIncrementalGC(gCx, GC_NORMAL, JS::gcreason::API);
     });
 
     if (!size) return 0;
 
     CompileOptions options(gCx);
     options.setIntroductionType("fuzzing parse")
        .setFileAndLine("<string>", 1);
 
--- a/js/src/fuzz-tests/testExample.cpp
+++ b/js/src/fuzz-tests/testExample.cpp
@@ -35,17 +35,17 @@ testExampleFuzz(const uint8_t* buf, size
 {
     /* If your code directly or indirectly allocates GC memory, then it makes sense
        to attempt and collect that after every iteration. This should detect GC issues
        as soon as possible (right after your iteration), rather than later when your
        code happens to trigger GC coincidentially. You can of course disable this code
        if it is not required in your use case, which will speed up fuzzing. */
     auto gcGuard = mozilla::MakeScopeExit([&] {
         JS::PrepareForFullGC(gCx);
-        JS::GCForReason(gCx, GC_NORMAL, JS::gcreason::API);
+        JS::NonIncrementalGC(gCx, GC_NORMAL, JS::gcreason::API);
     });
 
     /* Add code here that processes the given buffer.
        While doing so, you need to follow these rules:
 
        1. Do not modify or free the buffer. Make a copy if necessary.
        2. This function must always return 0.
        3. Do not crash or abort unless the condition constitutes a bug.
--- a/js/src/fuzz-tests/testStructuredCloneReader.cpp
+++ b/js/src/fuzz-tests/testStructuredCloneReader.cpp
@@ -25,17 +25,17 @@ static int
 testStructuredCloneReaderInit(int *argc, char ***argv) {
   return 0;
 }
 
 static int
 testStructuredCloneReaderFuzz(const uint8_t* buf, size_t size) {
     auto gcGuard = mozilla::MakeScopeExit([&] {
         JS::PrepareForFullGC(gCx);
-        JS::GCForReason(gCx, GC_NORMAL, JS::gcreason::API);
+        JS::NonIncrementalGC(gCx, GC_NORMAL, JS::gcreason::API);
     });
 
     if (!size) return 0;
 
     // Make sure to pad the buffer to a multiple of kSegmentAlignment
     const size_t kSegmentAlignment = 8;
     size_t buf_size = JS_ROUNDUP(size, kSegmentAlignment);
 
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -8540,17 +8540,17 @@ JS::IsGCScheduled(JSContext* cx)
 
 JS_PUBLIC_API(void)
 JS::SkipZoneForGC(Zone* zone)
 {
     zone->unscheduleGC();
 }
 
 JS_PUBLIC_API(void)
-JS::GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason)
+JS::NonIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason)
 {
     MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK);
     cx->runtime()->gc.gc(gckind, reason);
 }
 
 JS_PUBLIC_API(void)
 JS::StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis)
 {
--- a/js/src/gc/GC.h
+++ b/js/src/gc/GC.h
@@ -75,38 +75,37 @@ NotifyGCPostSwap(JSObject* a, JSObject* 
 typedef void (*IterateChunkCallback)(JSRuntime* rt, void* data, gc::Chunk* chunk);
 typedef void (*IterateZoneCallback)(JSRuntime* rt, void* data, JS::Zone* zone);
 typedef void (*IterateArenaCallback)(JSRuntime* rt, void* data, gc::Arena* arena,
                                      JS::TraceKind traceKind, size_t thingSize);
 typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
                                     JS::TraceKind traceKind, size_t thingSize);
 
 /*
- * This function calls |zoneCallback| on every zone, |compartmentCallback| on
- * every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
+ * This function calls |zoneCallback| on every zone, |realmCallback| on
+ * every realm, |arenaCallback| on every in-use arena, and |cellCallback|
  * on every in-use cell in the GC heap.
  *
  * Note that no read barrier is triggered on the cells passed to cellCallback,
  * so no these pointers must not escape the callback.
  */
 extern void
 IterateHeapUnbarriered(JSContext* cx, void* data,
                        IterateZoneCallback zoneCallback,
-                       JSIterateCompartmentCallback compartmentCallback,
+                       JS::IterateRealmCallback realmCallback,
                        IterateArenaCallback arenaCallback,
                        IterateCellCallback cellCallback);
 
 /*
- * This function is like IterateZonesCompartmentsArenasCells, but does it for a
- * single zone.
+ * This function is like IterateHeapUnbarriered, but does it for a single zone.
  */
 extern void
 IterateHeapUnbarrieredForZone(JSContext* cx, JS::Zone* zone, void* data,
                               IterateZoneCallback zoneCallback,
-                              JSIterateCompartmentCallback compartmentCallback,
+                              JS::IterateRealmCallback realmCallback,
                               IterateArenaCallback arenaCallback,
                               IterateCellCallback cellCallback);
 
 /*
  * Invoke chunkCallback on every in-use chunk.
  */
 extern void
 IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback);
--- a/js/src/gc/PrivateIterators-inl.h
+++ b/js/src/gc/PrivateIterators-inl.h
@@ -84,18 +84,18 @@ class GCZonesIter
         MOZ_ASSERT(!done());
         return zone;
     }
 
     operator JS::Zone*() const { return get(); }
     JS::Zone* operator->() const { return get(); }
 };
 
-using GCCompartmentsIter = CompartmentsIterT<GCZonesIter>;
-using GCRealmsIter = RealmsIterT<GCZonesIter>;
+using GCCompartmentsIter = CompartmentsOrRealmsIterT<GCZonesIter, CompartmentsInZoneIter>;
+using GCRealmsIter = CompartmentsOrRealmsIterT<GCZonesIter, RealmsInZoneIter>;
 
 /* Iterates over all zones in the current sweep group. */
 class SweepGroupZonesIter {
     JS::Zone* current;
 
   public:
     explicit SweepGroupZonesIter(JSRuntime* rt) {
         MOZ_ASSERT(CurrentThreadIsPerformingGC());
@@ -113,18 +113,18 @@ class SweepGroupZonesIter {
         MOZ_ASSERT(!done());
         return current;
     }
 
     operator JS::Zone*() const { return get(); }
     JS::Zone* operator->() const { return get(); }
 };
 
-using SweepGroupCompartmentsIter = CompartmentsIterT<SweepGroupZonesIter>;
-using SweepGroupRealmsIter = RealmsIterT<SweepGroupZonesIter>;
+using SweepGroupCompartmentsIter = CompartmentsOrRealmsIterT<SweepGroupZonesIter, CompartmentsInZoneIter>;
+using SweepGroupRealmsIter = CompartmentsOrRealmsIterT<SweepGroupZonesIter, RealmsInZoneIter>;
 
 // Iterate the free cells in an arena. See also ArenaCellIterImpl which iterates
 // the allocated cells.
 class ArenaFreeCellIter
 {
     Arena* arena;
     size_t thingSize;
     FreeSpan span;
--- a/js/src/gc/PublicIterators.cpp
+++ b/js/src/gc/PublicIterators.cpp
@@ -13,23 +13,28 @@
 
 #include "gc/PrivateIterators-inl.h"
 #include "vm/JSContext-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 static void
-IterateCompartmentsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
-                                          JSIterateCompartmentCallback compartmentCallback,
-                                          IterateArenaCallback arenaCallback,
-                                          IterateCellCallback cellCallback)
+IterateRealmsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
+                                    JS::IterateRealmCallback realmCallback,
+                                    IterateArenaCallback arenaCallback,
+                                    IterateCellCallback cellCallback)
 {
-    for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
-        (*compartmentCallback)(cx, data, comp);
+    {
+        Rooted<Realm*> realm(cx);
+        for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
+            realm = r;
+            (*realmCallback)(cx, data, realm);
+        }
+    }
 
     for (auto thingKind : AllAllocKinds()) {
         JS::TraceKind traceKind = MapAllocToTraceKind(thingKind);
         size_t thingSize = Arena::thingSize(thingKind);
 
         for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
             Arena* arena = aiter.get();
             (*arenaCallback)(cx->runtime(), data, arena, traceKind, thingSize);
@@ -37,41 +42,41 @@ IterateCompartmentsArenasCellsUnbarriere
                 (*cellCallback)(cx->runtime(), data, iter.getCell(), traceKind, thingSize);
         }
     }
 }
 
 void
 js::IterateHeapUnbarriered(JSContext* cx, void* data,
                            IterateZoneCallback zoneCallback,
-                           JSIterateCompartmentCallback compartmentCallback,
+                           JS::IterateRealmCallback realmCallback,
                            IterateArenaCallback arenaCallback,
                            IterateCellCallback cellCallback)
 {
     AutoPrepareForTracing prop(cx);
 
     for (ZonesIter zone(cx->runtime(), WithAtoms); !zone.done(); zone.next()) {
         (*zoneCallback)(cx->runtime(), data, zone);
-        IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
-                                                  compartmentCallback, arenaCallback, cellCallback);
+        IterateRealmsArenasCellsUnbarriered(cx, zone, data,
+                                            realmCallback, arenaCallback, cellCallback);
     }
 }
 
 void
 js::IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
                                   IterateZoneCallback zoneCallback,
-                                  JSIterateCompartmentCallback compartmentCallback,
+                                  JS::IterateRealmCallback realmCallback,
                                   IterateArenaCallback arenaCallback,
                                   IterateCellCallback cellCallback)
 {
     AutoPrepareForTracing prop(cx);
 
     (*zoneCallback)(cx->runtime(), data, zone);
-    IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
-                                              compartmentCallback, arenaCallback, cellCallback);
+    IterateRealmsArenasCellsUnbarriered(cx, zone, data,
+                                        realmCallback, arenaCallback, cellCallback);
 }
 
 void
 js::IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback)
 {
     AutoPrepareForTracing prep(cx);
     AutoLockGC lock(cx->runtime());
 
@@ -134,8 +139,20 @@ JS_PUBLIC_API(void)
 JS_IterateCompartments(JSContext* cx, void* data,
                        JSIterateCompartmentCallback compartmentCallback)
 {
     AutoTraceSession session(cx->runtime());
 
     for (CompartmentsIter c(cx->runtime(), WithAtoms); !c.done(); c.next())
         (*compartmentCallback)(cx, data, c);
 }
+
+JS_PUBLIC_API(void)
+JS::IterateRealms(JSContext* cx, void* data, JS::IterateRealmCallback realmCallback)
+{
+    AutoTraceSession session(cx->runtime());
+
+    Rooted<Realm*> realm(cx);
+    for (RealmsIter r(cx->runtime(), WithAtoms); !r.done(); r.next()) {
+        realm = r;
+        (*realmCallback)(cx, data, realm);
+    }
+}
--- a/js/src/gc/PublicIterators.h
+++ b/js/src/gc/PublicIterators.h
@@ -69,16 +69,18 @@ class ZonesIter
     }
 
     operator JS::Zone*() const { return get(); }
     JS::Zone* operator->() const { return get(); }
 };
 
 struct CompartmentsInZoneIter
 {
+    using ItemType = JSCompartment;
+
     explicit CompartmentsInZoneIter(JS::Zone* zone) : zone(zone) {
         it = zone->compartments().begin();
     }
 
     bool done() const {
         MOZ_ASSERT(it);
         return it < zone->compartments().begin() ||
                it >= zone->compartments().end();
@@ -94,23 +96,16 @@ struct CompartmentsInZoneIter
     }
 
     operator JSCompartment*() const { return get(); }
     JSCompartment* operator->() const { return get(); }
 
   private:
     JS::Zone* zone;
     JSCompartment** it;
-
-    CompartmentsInZoneIter()
-      : zone(nullptr), it(nullptr)
-    {}
-
-    // This is for the benefit of CompartmentsIterT::comp.
-    friend class mozilla::Maybe<CompartmentsInZoneIter>;
 };
 
 class RealmsInCompartmentIter
 {
     JSCompartment* comp;
     JS::Realm** it;
 
   public:
@@ -140,16 +135,18 @@ class RealmsInCompartmentIter
 };
 
 class RealmsInZoneIter
 {
     CompartmentsInZoneIter comp;
     mozilla::Maybe<RealmsInCompartmentIter> realm;
 
   public:
+    using ItemType = JS::Realm;
+
     explicit RealmsInZoneIter(JS::Zone* zone)
       : comp(zone)
     {
         settleOnCompartment();
     }
 
     void settleOnCompartment() {
         if (!comp.done()) {
@@ -177,99 +174,64 @@ class RealmsInZoneIter
     JS::Realm* get() const {
         return realm->get();
     }
 
     operator JS::Realm*() const { return get(); }
     JS::Realm* operator->() const { return get(); }
 };
 
-// This iterator iterates over all the compartments in a given set of zones. The
-// set of zones is determined by iterating ZoneIterT.
-template<class ZonesIterT>
-class CompartmentsIterT
+// This iterator iterates over all the compartments or realms in a given set of
+// zones. The set of zones is determined by iterating ZoneIterT. The set of
+// compartments or realms is determined by InnerIterT.
+template<class ZonesIterT, class InnerIterT>
+class CompartmentsOrRealmsIterT
 {
+    using T = typename InnerIterT::ItemType;
+
     gc::AutoEnterIteration iterMarker;
     ZonesIterT zone;
-    mozilla::Maybe<CompartmentsInZoneIter> comp;
+    mozilla::Maybe<InnerIterT> inner;
 
   public:
-    explicit CompartmentsIterT(JSRuntime* rt)
+    explicit CompartmentsOrRealmsIterT(JSRuntime* rt)
       : iterMarker(&rt->gc), zone(rt)
     {
-        if (zone.done())
-            comp.emplace();
-        else
-            comp.emplace(zone);
+        if (!zone.done())
+            inner.emplace(zone);
     }
 
-    CompartmentsIterT(JSRuntime* rt, ZoneSelector selector)
+    CompartmentsOrRealmsIterT(JSRuntime* rt, ZoneSelector selector)
       : iterMarker(&rt->gc), zone(rt, selector)
     {
-        if (zone.done())
-            comp.emplace();
-        else
-            comp.emplace(zone);
+        if (!zone.done())
+            inner.emplace(zone);
     }
 
     bool done() const { return zone.done(); }
 
     void next() {
         MOZ_ASSERT(!done());
-        MOZ_ASSERT(!comp.ref().done());
-        comp->next();
-        if (comp->done()) {
-            comp.reset();
+        MOZ_ASSERT(!inner.ref().done());
+        inner->next();
+        if (inner->done()) {
+            inner.reset();
             zone.next();
             if (!zone.done())
-                comp.emplace(zone);
+                inner.emplace(zone);
         }
     }
 
-    JSCompartment* get() const {
+    T* get() const {
         MOZ_ASSERT(!done());
-        return *comp;
+        return *inner;
     }
 
-    operator JSCompartment*() const { return get(); }
-    JSCompartment* operator->() const { return get(); }
+    operator T*() const { return get(); }
+    T* operator->() const { return get(); }
 };
 
-using CompartmentsIter = CompartmentsIterT<ZonesIter>;
-
-// This iterator iterates over all the realms in a given set of zones. The
-// set of zones is determined by iterating ZoneIterT.
-template<class ZonesIterT>
-class RealmsIterT
-{
-    gc::AutoEnterIteration iterMarker;
-    CompartmentsIterT<ZonesIterT> comp;
-
-  public:
-    explicit RealmsIterT(JSRuntime* rt)
-      : iterMarker(&rt->gc), comp(rt)
-    {}
-
-    RealmsIterT(JSRuntime* rt, ZoneSelector selector)
-      : iterMarker(&rt->gc), comp(rt, selector)
-    {}
-
-    bool done() const { return comp.done(); }
-
-    void next() {
-        MOZ_ASSERT(!done());
-        comp.next();
-    }
-
-    JS::Realm* get() const {
-        MOZ_ASSERT(!done());
-        return JS::GetRealmForCompartment(comp.get());
-    }
-
-    operator JS::Realm*() const { return get(); }
-    JS::Realm* operator->() const { return get(); }
-};
-
-using RealmsIter = RealmsIterT<ZonesIter>;
+using CompartmentsIter = CompartmentsOrRealmsIterT<ZonesIter, CompartmentsInZoneIter>;
+using RealmsIter = CompartmentsOrRealmsIterT<ZonesIter, RealmsInZoneIter>;
 
 } // namespace js
 
 #endif // gc_PublicIterators_h
--- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp
+++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
@@ -43,27 +43,27 @@ BEGIN_TEST(testGCFinalizeCallback)
     JS::RootedObject global3(cx, createTestGlobal());
     CHECK(global1);
     CHECK(global2);
     CHECK(global3);
 
     /* Zone GC, non-incremental, single zone. */
     FinalizeCalls = 0;
     JS::PrepareZoneForGC(global1->zone());
-    JS::GCForReason(cx, GC_NORMAL, JS::gcreason::API);
+    JS::NonIncrementalGC(cx, GC_NORMAL, JS::gcreason::API);
     CHECK(!cx->runtime()->gc.isFullGc());
     CHECK(checkSingleGroup());
     CHECK(checkFinalizeStatus());
 
     /* Zone GC, non-incremental, multiple zones. */
     FinalizeCalls = 0;
     JS::PrepareZoneForGC(global1->zone());
     JS::PrepareZoneForGC(global2->zone());
     JS::PrepareZoneForGC(global3->zone());
-    JS::GCForReason(cx, GC_NORMAL, JS::gcreason::API);
+    JS::NonIncrementalGC(cx, GC_NORMAL, JS::gcreason::API);
     CHECK(!cx->runtime()->gc.isFullGc());
     CHECK(checkSingleGroup());
     CHECK(checkFinalizeStatus());
 
     /* Zone GC, incremental, single zone. */
     FinalizeCalls = 0;
     JS::PrepareZoneForGC(global1->zone());
     JS::StartIncrementalGC(cx, GC_NORMAL, JS::gcreason::API, 1000000);
--- a/js/src/jsapi-tests/testGCUniqueId.cpp
+++ b/js/src/jsapi-tests/testGCUniqueId.cpp
@@ -106,17 +106,17 @@ BEGIN_TEST(testGCUID)
     obj = vec2.back();
     CHECK(obj);
     tenuredAddr = uintptr_t(obj.get());
     CHECK(obj->zone()->getOrCreateUniqueId(obj, &uid));
 
     // Force a compaction to move the object and check that the uid moved to
     // the new tenured heap location.
     JS::PrepareForFullGC(cx);
-    JS::GCForReason(cx, GC_SHRINK, JS::gcreason::API);
+    JS::NonIncrementalGC(cx, GC_SHRINK, JS::gcreason::API);
     MinimizeHeap(cx);
     CHECK(uintptr_t(obj.get()) != tenuredAddr);
     CHECK(obj->zone()->hasUniqueId(obj));
     CHECK(obj->zone()->getOrCreateUniqueId(obj, &tmp));
     CHECK(uid == tmp);
 
     return true;
 }
--- a/js/src/jsapi-tests/testPreserveJitCode.cpp
+++ b/js/src/jsapi-tests/testPreserveJitCode.cpp
@@ -68,20 +68,20 @@ testPreserveJitCode(bool preserveJitCode
 			      source, length, &fun));
 
     RootedValue value(cx);
     for (unsigned i = 0; i < 1500; ++i)
         CHECK(JS_CallFunction(cx, global, fun, JS::HandleValueArray::empty(), &value));
     CHECK_EQUAL(value.toInt32(), 45);
     CHECK_EQUAL(countIonScripts(global), 1u);
 
-    GCForReason(cx, GC_NORMAL, gcreason::API);
+    NonIncrementalGC(cx, GC_NORMAL, gcreason::API);
     CHECK_EQUAL(countIonScripts(global), remainingIonScripts);
 
-    GCForReason(cx, GC_SHRINK, gcreason::API);
+    NonIncrementalGC(cx, GC_SHRINK, gcreason::API);
     CHECK_EQUAL(countIonScripts(global), 0u);
 
     return true;
 }
 
 JSObject*
 createTestGlobal(bool preserveJitCode)
 {
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -479,17 +479,17 @@ class AutoLeaveZeal
     uint32_t frequency_;
 
   public:
     explicit AutoLeaveZeal(JSContext* cx) : cx_(cx) {
         uint32_t dummy;
         JS_GetGCZealBits(cx_, &zealBits_, &frequency_, &dummy);
         JS_SetGCZeal(cx_, 0, 0);
         JS::PrepareForFullGC(cx_);
-        JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
+        JS::NonIncrementalGC(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
     }
     ~AutoLeaveZeal() {
         JS_SetGCZeal(cx_, 0, 0);
         for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
             if (zealBits_ & (1 << i))
                 JS_SetGCZeal(cx_, i, frequency_);
         }
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7539,78 +7539,102 @@ DescribeScriptedCaller(JSContext* cx, Au
     if (lineno)
         *lineno = i.computeLine(column);
     else if (column)
         i.computeLine(column);
 
     return true;
 }
 
-// Fast path to get the activation to use for GetScriptedCallerGlobal. If this
-// returns false, the fast path didn't work out and the caller has to use the
-// (much slower) NonBuiltinFrameIter path.
+// Fast path to get the activation and realm to use for GetScriptedCallerGlobal.
+// If this returns false, the fast path didn't work out and the caller has to
+// use the (much slower) NonBuiltinFrameIter path.
 //
 // The optimization here is that we skip Ion-inlined frames and only look at
-// 'outer' frames. That's fine: each activation is tied to a single compartment,
-// so if an activation contains at least one non-self-hosted frame, we can use
-// the activation's global for GetScriptedCallerGlobal. If, however, all 'outer'
-// frames are self-hosted, it's possible Ion inlined a non-self-hosted script,
-// so we must return false and use the slower path.
+// 'outer' frames. That's fine because Ion doesn't inline cross-realm calls.
+// However, GetScriptedCallerGlobal has to skip self-hosted frames and Ion
+// can inline self-hosted scripts, so we have to be careful:
+//
+// * When we see a non-self-hosted outer script, it's possible we inlined
+//   self-hosted scripts into it but that doesn't matter because these scripts
+//   all have the same realm/global anyway.
+//
+// * When we see a self-hosted outer script, it's possible we inlined
+//   non-self-hosted scripts into it, so we have to give up because in this
+//   case, whether or not to skip the self-hosted frame (to the possibly
+//   different-realm caller) requires the slow path to handle inlining. Baseline
+//   and the interpreter don't inline so this only affects Ion.
 static bool
-GetScriptedCallerActivationFast(JSContext* cx, Activation** activation)
+GetScriptedCallerActivationRealmFast(JSContext* cx, Activation** activation, Realm** realm)
 {
     ActivationIterator activationIter(cx);
 
     if (activationIter.done()) {
         *activation = nullptr;
+        *realm = nullptr;
         return true;
     }
 
-    *activation = activationIter.activation();
-
     if (activationIter->isJit()) {
         for (OnlyJSJitFrameIter iter(activationIter); !iter.done(); ++iter) {
-            if (iter.frame().isScripted() && !iter.frame().script()->selfHosted())
+            if (!iter.frame().isScripted())
+                continue;
+            if (!iter.frame().script()->selfHosted()) {
+                *activation = activationIter.activation();
+                *realm = iter.frame().script()->realm();
                 return true;
+            }
+            if (iter.frame().isIonScripted()) {
+                // Ion might have inlined non-self-hosted scripts in this
+                // self-hosted script.
+                return false;
+            }
         }
     } else if (activationIter->isInterpreter()) {
-        for (InterpreterFrameIterator iter((*activation)->asInterpreter()); !iter.done(); ++iter) {
-            if (!iter.frame()->script()->selfHosted())
+        InterpreterActivation* act = activationIter->asInterpreter();
+        for (InterpreterFrameIterator iter(act); !iter.done(); ++iter) {
+            if (!iter.frame()->script()->selfHosted()) {
+                *activation = act;
+                *realm = iter.frame()->script()->realm();
                 return true;
+            }
         }
     }
 
     return false;
 }
 
 JS_PUBLIC_API(JSObject*)
 GetScriptedCallerGlobal(JSContext* cx)
 {
     Activation* activation;
-
-    if (GetScriptedCallerActivationFast(cx, &activation)) {
+    Realm* realm;
+    if (GetScriptedCallerActivationRealmFast(cx, &activation, &realm)) {
         if (!activation)
             return nullptr;
     } else {
         NonBuiltinFrameIter i(cx);
         if (i.done())
             return nullptr;
         activation = i.activation();
+        realm = i.realm();
     }
 
+    MOZ_ASSERT(realm->compartment() == activation->compartment());
+
     // If the caller is hidden, the embedding wants us to return null here so
     // that it can check its own stack (see HideScriptedCaller).
     if (activation->scriptedCallerIsHidden())
         return nullptr;
 
-    GlobalObject* global = JS::GetRealmForCompartment(activation->compartment())->maybeGlobal();
-
-    // No one should be running code in the atoms realm or running code in
-    // a compartment without any live objects, so there should definitely be a
-    // live global.
+    GlobalObject* global = realm->maybeGlobal();
+
+    // No one should be running code in the atoms realm or running code in a
+    // realm without any live objects, so there should definitely be a live
+    // global.
     MOZ_ASSERT(global);
 
     return global;
 }
 
 JS_PUBLIC_API(void)
 HideScriptedCaller(JSContext* cx)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1093,16 +1093,26 @@ namespace JS {
  * JS::LeaveRealm() call.
  */
 extern JS_PUBLIC_API(JS::Realm*)
 EnterRealm(JSContext* cx, JSObject* target);
 
 extern JS_PUBLIC_API(void)
 LeaveRealm(JSContext* cx, JS::Realm* oldRealm);
 
+using IterateRealmCallback = void (*)(JSContext* cx, void* data, Handle<Realm*> realm);
+
+/**
+ * This function calls |realmCallback| on every realm. Beware that there is no
+ * guarantee that the realm will survive after the callback returns. Also,
+ * barriers are disabled via the TraceSession.
+ */
+extern JS_PUBLIC_API(void)
+IterateRealms(JSContext* cx, void* data, IterateRealmCallback realmCallback);
+
 } // namespace JS
 
 typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data, JSCompartment* compartment);
 
 /**
  * This function calls |compartmentCallback| on every compartment. Beware that
  * there is no guarantee that the compartment will survive after the callback
  * returns. Also, barriers are disabled via the TraceSession.
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -1179,26 +1179,27 @@ MarkDescriptor(void* thing)
 static void
 DumpHeapVisitZone(JSRuntime* rt, void* data, Zone* zone)
 {
     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
     fprintf(dtrc->output, "# zone %p\n", (void*)zone);
 }
 
 static void
-DumpHeapVisitCompartment(JSContext* cx, void* data, JSCompartment* comp)
+DumpHeapVisitRealm(JSContext* cx, void* data, Handle<Realm*> realm)
 {
     char name[1024];
-    if (cx->runtime()->compartmentNameCallback)
-        (*cx->runtime()->compartmentNameCallback)(cx, comp, name, sizeof(name));
+    if (auto nameCallback = cx->runtime()->realmNameCallback)
+        nameCallback(cx, realm, name, sizeof(name));
     else
         strcpy(name, "<unknown>");
 
     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
-    fprintf(dtrc->output, "# compartment %s [in zone %p]\n", name, (void*)comp->zone());
+    fprintf(dtrc->output, "# realm %s [in compartment %p, zone %p]\n", name,
+            (void*)realm->compartment(), (void*)realm->zone());
 }
 
 static void
 DumpHeapVisitArena(JSRuntime* rt, void* data, gc::Arena* arena,
                    JS::TraceKind traceKind, size_t thingSize)
 {
     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
     fprintf(dtrc->output, "# arena allockind=%u size=%u\n",
@@ -1245,20 +1246,20 @@ js::DumpHeap(JSContext* cx, FILE* fp, js
 
     fprintf(dtrc.output, "# Weak maps.\n");
     WeakMapBase::traceAllMappings(&dtrc);
 
     fprintf(dtrc.output, "==========\n");
 
     dtrc.prefix = "> ";
     IterateHeapUnbarriered(cx, &dtrc,
-                                                   DumpHeapVisitZone,
-                                                   DumpHeapVisitCompartment,
-                                                   DumpHeapVisitArena,
-                                                   DumpHeapVisitCell);
+                           DumpHeapVisitZone,
+                           DumpHeapVisitRealm,
+                           DumpHeapVisitArena,
+                           DumpHeapVisitCell);
 
     fflush(dtrc.output);
 }
 
 JS_FRIEND_API(void)
 js::SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg)
 {
     cx->activityCallback = cb;
@@ -1266,22 +1267,22 @@ js::SetActivityCallback(JSContext* cx, A
 }
 
 JS_FRIEND_API(void)
 JS::NotifyGCRootsRemoved(JSContext* cx)
 {
     cx->runtime()->gc.notifyRootsRemoved();
 }
 
-JS_FRIEND_API(JSCompartment*)
-js::GetAnyCompartmentInZone(JS::Zone* zone)
+JS_FRIEND_API(JS::Realm*)
+js::GetAnyRealmInZone(JS::Zone* zone)
 {
-    CompartmentsInZoneIter comp(zone);
-    MOZ_ASSERT(!comp.done());
-    return comp.get();
+    RealmsInZoneIter realm(zone);
+    MOZ_ASSERT(!realm.done());
+    return realm.get();
 }
 
 void
 JS::ObjectPtr::finalize(JSRuntime* rt)
 {
     if (IsIncrementalBarrierNeeded(rt->mainContextFromOwnThread()))
         IncrementalPreWriteBarrier(value);
     value = nullptr;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -548,18 +548,18 @@ extern JS_FRIEND_API(bool)
 CheckGrayMarkingState(JSRuntime* rt);
 #endif
 
 #ifdef JS_HAS_CTYPES
 extern JS_FRIEND_API(size_t)
 SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
 #endif
 
-extern JS_FRIEND_API(JSCompartment*)
-GetAnyCompartmentInZone(JS::Zone* zone);
+extern JS_FRIEND_API(JS::Realm*)
+GetAnyRealmInZone(JS::Zone* zone);
 
 /*
  * Shadow declarations of JS internal structures, for access by inline access
  * functions below. Do not use these structures in any other way. When adding
  * new fields for access by inline methods, make sure to add static asserts to
  * the original header file to ensure that offsets are consistent.
  */
 namespace shadow {
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -43,17 +43,17 @@ skip-if(!this.hasOwnProperty("SIMD")) in
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1415303
 skip-if(!this.hasOwnProperty("SharedArrayBuffer")) script non262/SIMD/load-sab-buffer-compat.js
 skip-if(!this.hasOwnProperty("Atomics")) include test262/built-ins/Atomics/jstests.list
 skip-if(!this.hasOwnProperty("SharedArrayBuffer")) include test262/built-ins/SharedArrayBuffer/jstests.list
 
 # flatMap and flatten are Nightly-only
 skip-if(!Array.prototype.flatMap) include test262/built-ins/Array/prototype/flatMap/jstests.list
-skip-if(!Array.prototype.flatten) include test262/built-ins/Array/prototype/flatten/jstests.list
+skip-if(!Array.prototype.flat) include test262/built-ins/Array/prototype/flat/jstests.list
 
 
 #####################################
 # Test262 tests disabled on browser #
 #####################################
 
 # Defines a non-configurable property on the WindowProxy object.
 skip-if(!xulRuntime.shell) script test262/annexB/language/eval-code/direct/global-block-decl-eval-global-existing-global-update.js
--- a/js/src/tests/lib/jittests.py
+++ b/js/src/tests/lib/jittests.py
@@ -497,16 +497,18 @@ def print_automation_format(ok, res, slo
         result, res.test.relpath_top, message, res.rc, jitflags, res.dt))
 
     details = {
         'message': message,
         'extra': {
             'jitflags': jitflags,
         }
     }
+    if res.extra:
+        details['extra'].update(res.extra)
     slog.test(res.test.relpath_tests, 'PASS' if ok else 'FAIL', res.dt, **details)
 
     # For failed tests, print as much information as we have, to aid debugging.
     if ok:
         return
     print("INFO exit-status     : {}".format(res.rc))
     print("INFO timed-out       : {}".format(res.timed_out))
     for line in res.out.splitlines():
--- a/js/src/tests/lib/results.py
+++ b/js/src/tests/lib/results.py
@@ -7,24 +7,25 @@ from progressbar import NullProgressBar,
 from structuredlog import TestLogger
 
 # subprocess.list2cmdline does not properly escape for sh-like shells
 def escape_cmdline(args):
     return ' '.join([pipes.quote(a) for a in args])
 
 class TestOutput:
     """Output from a test run."""
-    def __init__(self, test, cmd, out, err, rc, dt, timed_out):
+    def __init__(self, test, cmd, out, err, rc, dt, timed_out, extra=None):
         self.test = test   # Test
         self.cmd = cmd     # str:   command line of test
         self.out = out     # str:   stdout
         self.err = err     # str:   stderr
         self.rc = rc       # int:   return code
         self.dt = dt       # float: run time
         self.timed_out = timed_out # bool: did the test time out
+        self.extra = extra # includes the pid on some platforms
 
     def describe_failure(self):
         if self.timed_out:
             return "Timeout"
         lines = self.err.splitlines()
         for line in lines:
             # Skip the asm.js compilation success message.
             if "Successfully compiled asm.js code" not in line:
@@ -207,17 +208,17 @@ class ResultsSink:
                         tup = (sub_ok, result.test.expect, result.test.random)
                         label = self.LABELS[tup][0]
                         if label == 'TEST-UNEXPECTED-PASS':
                             label = 'TEST-PASS (EXPECTED RANDOM)'
                         self.print_automation_result(
                             label, result.test, time=output.dt,
                             message=msg)
                 tup = (result.result, result.test.expect, result.test.random)
-                self.print_automation_result(self.LABELS[tup][0], result.test, time=output.dt)
+                self.print_automation_result(self.LABELS[tup][0], result.test, time=output.dt, extra=getattr(output, 'extra', None))
                 return
 
             if dev_label:
                 def singular(label):
                     return "FIXED" if label == "FIXES" else label[:-1]
                 self.pb.message("{} - {}".format(singular(dev_label),
                                                  output.test.path))
 
@@ -287,34 +288,34 @@ class ResultsSink:
                 any = True
             if not any:
                 print('None')
 
     def all_passed(self):
         return 'REGRESSIONS' not in self.groups and 'TIMEOUTS' not in self.groups
 
     def print_automation_result(self, label, test, message=None, skip=False,
-                                time=None):
+                                time=None, extra=None):
         result = label
         result += " | " + test.path
         args = []
         if self.options.shell_args:
             args.append(self.options.shell_args)
         args += test.jitflags
         result += ' | (args: "{}")'.format(' '.join(args))
         if message:
             result += " | " + message
         if skip:
             result += ' | (SKIP)'
         if time > self.options.timeout:
             result += ' | (TIMEOUT)'
         result += ' [{:.1f} s]'.format(time)
         print(result)
 
-        details = { 'extra': {} }
+        details = { 'extra': extra.copy() if extra else {} }
         if self.options.shell_args:
             details['extra']['shell_args'] = self.options.shell_args
         details['extra']['jitflags'] = test.jitflags
         if message:
             details['message'] = message
         status = 'FAIL' if 'TEST-UNEXPECTED' in label else 'PASS'
 
         self.slog.test(test.path, status, time or 0, **details)
--- a/js/src/tests/lib/structuredlog.py
+++ b/js/src/tests/lib/structuredlog.py
@@ -34,17 +34,17 @@ class TestLogger(object):
 
     def test_start(self, testname):
         self._log(action='test_start', test=testname)
 
     def test_end(self, testname, status):
         self._log(action='test_end', test=testname, status=status)
 
     def test(self, testname, status, duration, **details):
-        record = self._record(action='test_start', test=testname)
+        record = self._record(action='test_start', test=testname, **details.get('extra', {}))
         end_time = record['time']
         record['time'] -= duration
         self._log_obj(record)
 
         record['action'] = 'test_end'
         record['time'] = end_time
         record['status'] = status
         record.update(**details)
--- a/js/src/tests/lib/tasks_unix.py
+++ b/js/src/tests/lib/tasks_unix.py
@@ -173,17 +173,18 @@ def reap_zombies(tasks, timeout):
         finished.append(
             TestOutput(
                 ended.test,
                 ended.cmd,
                 ''.join(ended.out),
                 ''.join(ended.err),
                 returncode,
                 (datetime.now() - ended.start).total_seconds(),
-                timed_out(ended, timeout)))
+                timed_out(ended, timeout),
+                {'pid': ended.pid}))
     return tasks, finished
 
 def kill_undead(tasks, timeout):
     """
     Signal all children that are over the given timeout. Use SIGABRT first to
     generate a stack dump. If it still doesn't die for another 30 seconds, kill
     with SIGKILL.
     """
@@ -223,9 +224,8 @@ def run_all_tests(tests, prefix, pb, opt
         # With Python3.4+ we could use yield from to remove this loop.
         for out in finished:
             yield out
 
         # If we did not finish any tasks, poke the progress bar to show that
         # the test harness is at least not frozen.
         if len(finished) == 0:
             pb.poke()
-
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -844,17 +844,17 @@ CreateBuffer(JSContext* cx, uint32_t ini
     if (!object)
         return false;
 
     maybeSharedObject.set(object);
 
     // See MaximumLiveMappedBuffers comment above.
     if (liveBufferCount > StartSyncFullGCAtLiveBufferCount) {
         JS::PrepareForFullGC(cx);
-        JS::GCForReason(cx, GC_NORMAL, JS::gcreason::TOO_MUCH_WASM_MEMORY);
+        JS::NonIncrementalGC(cx, GC_NORMAL, JS::gcreason::TOO_MUCH_WASM_MEMORY);
         allocatedSinceLastTrigger = 0;
     } else if (liveBufferCount > StartTriggeringAtLiveBufferCount) {
         allocatedSinceLastTrigger++;
         if (allocatedSinceLastTrigger > AllocatedBuffersPerTrigger) {
             Unused << cx->runtime()->gc.triggerGC(JS::gcreason::TOO_MUCH_WASM_MEMORY);
             allocatedSinceLastTrigger = 0;
         }
     } else {
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -2824,17 +2824,17 @@ DebugEnvironments::onPopVar(JSContext* c
         onPopGeneric<VarEnvironmentObject, EvalScope>(cx, ei);
     else
         onPopGeneric<VarEnvironmentObject, VarScope>(cx, ei);
 }
 
 void
 DebugEnvironments::onPopWith(AbstractFramePtr frame)
 {
-    Realm* realm = JS::GetRealmForCompartment(frame.compartment());
+    Realm* realm = frame.realm();
     if (DebugEnvironments* envs = realm->debugEnvs())
         envs->liveEnvs.remove(&frame.environmentChain()->as<WithEnvironmentObject>());
 }
 
 void
 DebugEnvironments::onRealmUnsetIsDebuggee(Realm* realm)
 {
     if (DebugEnvironments* envs = realm->debugEnvs()) {
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -327,29 +327,27 @@ StatsZoneCallback(JSRuntime* rt, void* d
                                  &zStats.baselineStubsOptimized,
                                  &zStats.cachedCFG,
                                  &zStats.uniqueIdMap,
                                  &zStats.shapeTables,
                                  &rtStats->runtime.atomsMarkBitmaps);
 }
 
 static void
-StatsRealmCallback(JSContext* cx, void* data, JSCompartment* compartment)
+StatsRealmCallback(JSContext* cx, void* data, Handle<Realm*> realm)
 {
-    Realm* realm = JS::GetRealmForCompartment(compartment);
-
     // Append a new RealmStats to the vector.
     RuntimeStats* rtStats = static_cast<StatsClosure*>(data)->rtStats;
 
     // CollectRuntimeStats reserves enough space.
     MOZ_ALWAYS_TRUE(rtStats->realmStatsVector.growBy(1));
     RealmStats& realmStats = rtStats->realmStatsVector.back();
     if (!realmStats.initClasses())
         MOZ_CRASH("oom");
-    rtStats->initExtraRealmStats(compartment, &realmStats);
+    rtStats->initExtraRealmStats(realm, &realmStats);
 
     realm->setRealmStats(&realmStats);
 
     // Measure the realm object itself, and things hanging off it.
     realm->addSizeOfIncludingThis(rtStats->mallocSizeOf_,
                                   &realmStats.typeInferenceAllocationSiteTables,
                                   &realmStats.typeInferenceArrayTypeTables,
                                   &realmStats.typeInferenceObjectTypeTables,
@@ -920,18 +918,17 @@ class SimpleJSRuntimeStats : public JS::
     explicit SimpleJSRuntimeStats(MallocSizeOf mallocSizeOf)
       : JS::RuntimeStats(mallocSizeOf)
     {}
 
     virtual void initExtraZoneStats(JS::Zone* zone, JS::ZoneStats* zStats)
         override
     {}
 
-    virtual void initExtraRealmStats(
-        JSCompartment* c, JS::RealmStats* realmStats) override
+    virtual void initExtraRealmStats(Handle<Realm*> realm, JS::RealmStats* realmStats) override
     {}
 };
 
 JS_PUBLIC_API(bool)
 AddSizeOfTab(JSContext* cx, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor* opv,
              TabSizes* sizes)
 {
     SimpleJSRuntimeStats rtStats(mallocSizeOf);
@@ -945,20 +942,20 @@ AddSizeOfTab(JSContext* cx, HandleObject
         return false;
 
     // Take the per-compartment measurements. No need to anonymize because
     // these measurements will be aggregated.
     StatsClosure closure(&rtStats, opv, /* anonymize = */ false);
     if (!closure.init())
         return false;
     IterateHeapUnbarrieredForZone(cx, zone, &closure,
-                                                  StatsZoneCallback,
-                                                  StatsRealmCallback,
-                                                  StatsArenaCallback,
-                                                  StatsCellCallback<CoarseGrained>);
+                                  StatsZoneCallback,
+                                  StatsRealmCallback,
+                                  StatsArenaCallback,
+                                  StatsCellCallback<CoarseGrained>);
 
     MOZ_ASSERT(rtStats.zoneStatsVector.length() == 1);
     rtStats.zTotals.addSizes(rtStats.zoneStatsVector[0]);
 
     for (size_t i = 0; i < rtStats.realmStatsVector.length(); i++)
         rtStats.realmTotals.addSizes(rtStats.realmStatsVector[i]);
 
     for (RealmsInZoneIter realm(zone); !realm.done(); realm.next())
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1476,17 +1476,17 @@ SavedStacks::insertFrames(JSContext* cx,
         {
             AutoRealmUnchecked ar(cx, iter.realm());
             if (!cx->realm()->savedStacks().getLocation(cx, iter, &location))
                 return false;
         }
 
         RootedAtom displayAtom(cx, iter.maybeFunctionDisplayAtom());
 
-        auto principals = JS::GetRealmForCompartment(iter.compartment())->principals();
+        auto principals = iter.realm()->principals();
         MOZ_ASSERT_IF(framePtr && !iter.isWasm(), iter.pc());
 
         if (!stackChain->emplaceBack(location.source(),
                                      location.line(),
                                      location.column(),
                                      displayAtom,
                                      nullptr, // asyncCause
                                      nullptr, // parent (not known yet)
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -488,20 +488,20 @@ AbstractFramePtr::initFunctionEnvironmen
 }
 
 inline bool
 AbstractFramePtr::pushVarEnvironment(JSContext* cx, HandleScope scope)
 {
     return js::PushVarEnvironmentObject(cx, scope, *this);
 }
 
-inline JSCompartment*
-AbstractFramePtr::compartment() const
+inline JS::Realm*
+AbstractFramePtr::realm() const
 {
-    return environmentChain()->compartment();
+    return environmentChain()->realm();
 }
 
 inline unsigned
 AbstractFramePtr::numActualArgs() const
 {
     if (isInterpreterFrame())
         return asInterpreterFrame()->numActualArgs();
     if (isBaselineFrame())
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -642,16 +642,35 @@ OnlyJSJitFrameIter::OnlyJSJitFrameIter(c
 
 void
 FrameIter::popActivation()
 {
     ++data_.activations_;
     settleOnActivation();
 }
 
+bool
+FrameIter::principalsSubsumeFrame() const
+{
+    // If the caller supplied principals, only show frames which are
+    // subsumed (of the same origin or of an origin accessible) by these
+    // principals.
+
+    MOZ_ASSERT(!done());
+
+    if (!data_.principals_)
+        return true;
+
+    JSSubsumesOp subsumes = data_.cx_->runtime()->securityCallbacks->subsumes;
+    if (!subsumes)
+        return true;
+
+    return subsumes(data_.principals_, realm()->principals());
+}
+
 void
 FrameIter::popInterpreterFrame()
 {
     MOZ_ASSERT(data_.state_ == INTERP);
 
     ++data_.interpFrames_;
 
     if (data_.interpFrames_.done())
@@ -668,30 +687,16 @@ FrameIter::settleOnActivation()
     while (true) {
         if (data_.activations_.done()) {
             data_.state_ = DONE;
             return;
         }
 
         Activation* activation = data_.activations_.activation();
 
-        // If the caller supplied principals, only show activations which are
-        // subsumed (of the same origin or of an origin accessible) by these
-        // principals.
-        if (data_.principals_) {
-            JSContext* cx = data_.cx_;
-            if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
-                JS::Realm* realm = JS::GetRealmForCompartment(activation->compartment());
-                if (!subsumes(data_.principals_, realm->principals())) {
-                    ++data_.activations_;
-                    continue;
-                }
-            }
-        }
-
         if (activation->isJit()) {
             data_.jitFrames_ = JitFrameIter(activation->asJit());
             data_.jitFrames_.skipNonScriptedJSFrames();
             if (data_.jitFrames_.done()) {
                 // It's possible to have an JitActivation with no scripted
                 // frames, for instance if we hit an over-recursion during
                 // bailout.
                 ++data_.activations_;
@@ -752,24 +757,32 @@ FrameIter::Data::Data(const FrameIter::D
 
 FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption)
   : data_(cx, debuggerEvalOption, nullptr),
     ionInlineFrames_(cx, (js::jit::JSJitFrameIter*) nullptr)
 {
     // settleOnActivation can only GC if principals are given.
     JS::AutoSuppressGCAnalysis nogc;
     settleOnActivation();
+
+    // No principals so we can see all frames.
+    MOZ_ASSERT_IF(!done(), principalsSubsumeFrame());
 }
 
 FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
                      JSPrincipals* principals)
   : data_(cx, debuggerEvalOption, principals),
     ionInlineFrames_(cx, (js::jit::JSJitFrameIter*) nullptr)
 {
     settleOnActivation();
+
+    // If we're not allowed to see this frame, call operator++ to skip this (and
+    // other) cross-origin frames.
+    if (!done() && !principalsSubsumeFrame())
+        ++*this;
 }
 
 FrameIter::FrameIter(const FrameIter& other)
   : data_(other.data_),
     ionInlineFrames_(other.data_.cx_, isIonScripted() ? &other.ionInlineFrames_ : nullptr)
 {
 }
 
@@ -825,42 +838,48 @@ FrameIter::popJitFrame()
         data_.jitFrames_.reset();
         popActivation();
     }
 }
 
 FrameIter&
 FrameIter::operator++()
 {
-    switch (data_.state_) {
-      case DONE:
-        MOZ_CRASH("Unexpected state");
-      case INTERP:
-        if (interpFrame()->isDebuggerEvalFrame() &&
-            data_.debuggerEvalOption_ == FOLLOW_DEBUGGER_EVAL_PREV_LINK)
-        {
-            AbstractFramePtr eifPrev = interpFrame()->evalInFramePrev();
+    while (true) {
+        switch (data_.state_) {
+          case DONE:
+            MOZ_CRASH("Unexpected state");
+          case INTERP:
+            if (interpFrame()->isDebuggerEvalFrame() &&
+                data_.debuggerEvalOption_ == FOLLOW_DEBUGGER_EVAL_PREV_LINK)
+            {
+                AbstractFramePtr eifPrev = interpFrame()->evalInFramePrev();
+
+                popInterpreterFrame();
 
-            popInterpreterFrame();
+                while (!hasUsableAbstractFramePtr() || abstractFramePtr() != eifPrev) {
+                    if (data_.state_ == JIT)
+                        popJitFrame();
+                    else
+                        popInterpreterFrame();
+                }
 
-            while (!hasUsableAbstractFramePtr() || abstractFramePtr() != eifPrev) {
-                if (data_.state_ == JIT)
-                    popJitFrame();
-                else
-                    popInterpreterFrame();
+                break;
             }
-
+            popInterpreterFrame();
+            break;
+          case JIT:
+            popJitFrame();
             break;
         }
-        popInterpreterFrame();
-        break;
-      case JIT:
-        popJitFrame();
-        break;
+
+        if (done() || principalsSubsumeFrame())
+            break;
     }
+
     return *this;
 }
 
 FrameIter::Data*
 FrameIter::copyData() const
 {
     Data* data = data_.cx_->new_<Data>(data_);
     if (!data)
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -210,17 +210,17 @@ class AbstractFramePtr
     inline CallObject& callObj() const;
     inline bool initFunctionEnvironmentObjects(JSContext* cx);
     inline bool pushVarEnvironment(JSContext* cx, HandleScope scope);
     template <typename SpecificEnvironment>
     inline void pushOnEnvironmentChain(SpecificEnvironment& env);
     template <typename SpecificEnvironment>
     inline void popOffEnvironmentChain();
 
-    inline JSCompartment* compartment() const;
+    inline JS::Realm* realm() const;
 
     inline bool hasInitialEnvironment() const;
     inline bool isGlobalFrame() const;
     inline bool isModuleFrame() const;
     inline bool isEvalFrame() const;
     inline bool isDebuggerEvalFrame() const;
 
     inline bool hasScript() const;
@@ -2173,16 +2173,18 @@ class FrameIter
     const jit::JSJitFrameIter& jsJitFrame() const { return data_.jitFrames_.asJSJit(); }
     const wasm::WasmFrameIter& wasmFrame() const { return data_.jitFrames_.asWasm(); }
 
     jit::JSJitFrameIter& jsJitFrame() { return data_.jitFrames_.asJSJit(); }
     wasm::WasmFrameIter& wasmFrame() { return data_.jitFrames_.asWasm(); }
 
     bool isIonScripted() const { return isJSJit() && jsJitFrame().isIonScripted(); }
 
+    bool principalsSubsumeFrame() const;
+
     void popActivation();
     void popInterpreterFrame();
     void nextJitFrame();
     void popJitFrame();
     void settleOnActivation();
 };
 
 class ScriptFrameIter : public FrameIter
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2277,17 +2277,17 @@ nsXPCComponents_Utils::GetWeakReference(
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceGC()
 {
     JSContext* cx = XPCJSContext::Get()->Context();
     PrepareForFullGC(cx);
-    GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
+    NonIncrementalGC(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceCC(nsICycleCollectorListener* listener)
 {
     nsJSContext::CycleCollectNow(listener);
     return NS_OK;
@@ -2321,17 +2321,17 @@ nsXPCComponents_Utils::ClearMaxCCTime()
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceShrinkingGC()
 {
     JSContext* cx = dom::danger::GetJSContext();
     PrepareForFullGC(cx);
-    GCForReason(cx, GC_SHRINK, gcreason::COMPONENT_UTILS);
+    NonIncrementalGC(cx, GC_SHRINK, gcreason::COMPONENT_UTILS);
     return NS_OK;
 }
 
 class PreciseGCRunnable : public Runnable
 {
   public:
     PreciseGCRunnable(ScheduledGCCallback* aCallback, bool aShrinking)
       : mozilla::Runnable("PreciseGCRunnable")
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2038,44 +2038,44 @@ class JSMainRuntimeRealmsReporter final 
   public:
     NS_DECL_ISUPPORTS
 
     struct Data {
         int anonymizeID;
         js::Vector<nsCString, 0, js::SystemAllocPolicy> paths;
     };
 
-    static void CompartmentCallback(JSContext* cx, void* vdata, JSCompartment* c) {
+    static void RealmCallback(JSContext* cx, void* vdata, Handle<Realm*> realm) {
         // silently ignore OOM errors
+        JSCompartment* c = JS::GetCompartmentForRealm(realm);
         Data* data = static_cast<Data*>(vdata);
         nsCString path;
         GetCompartmentName(c, path, &data->anonymizeID, /* replaceSlashes = */ true);
         path.Insert(js::IsSystemCompartment(c)
                     ? NS_LITERAL_CSTRING("js-main-runtime-realms/system/")
                     : NS_LITERAL_CSTRING("js-main-runtime-realms/user/"),
                     0);
         mozilla::Unused << data->paths.append(path);
     }
 
     NS_IMETHOD CollectReports(nsIHandleReportCallback* handleReport,
                               nsISupports* data, bool anonymize) override
     {
-        // First we collect the compartment paths.  Then we report them.  Doing
+        // First we collect the realm paths.  Then we report them.  Doing
         // the two steps interleaved is a bad idea, because calling
-        // |handleReport| from within CompartmentCallback() leads to all manner
+        // |handleReport| from within RealmCallback() leads to all manner
         // of assertions.
 
         Data d;
         d.anonymizeID = anonymize ? 1 : 0;
-        JS_IterateCompartments(XPCJSContext::Get()->Context(),
-                               &d, CompartmentCallback);
+        JS::IterateRealms(XPCJSContext::Get()->Context(), &d, RealmCallback);
 
         for (size_t i = 0; i < d.paths.length(); i++)
             REPORT(nsCString(d.paths[i]), KIND_OTHER, UNITS_COUNT, 1,
-                "A live compartment in the main JSRuntime.");
+                "A live realm in the main JSRuntime.");
 
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS(JSMainRuntimeRealmsReporter, nsIMemoryReporter)
 
 MOZ_DEFINE_MALLOC_SIZE_OF(OrphanMallocSizeOf)
@@ -2160,18 +2160,17 @@ class XPCJSRuntimeStats : public JS::Run
 
         for (size_t i = 0; i != zoneStatsVector.length(); ++i)
             delete static_cast<xpc::ZoneStatsExtras*>(zoneStatsVector[i].extra);
     }
 
     virtual void initExtraZoneStats(JS::Zone* zone, JS::ZoneStats* zStats) override {
         // Get some global in this zone.
         AutoSafeJSContext cx;
-        JSCompartment* comp = js::GetAnyCompartmentInZone(zone);
-        Rooted<Realm*> realm(cx, JS::GetRealmForCompartment(comp));
+        Rooted<Realm*> realm(cx, js::GetAnyRealmInZone(zone));
         xpc::ZoneStatsExtras* extras = new xpc::ZoneStatsExtras;
         extras->pathPrefix.AssignLiteral("explicit/js-non-window/zones/");
         RootedObject global(cx, JS::GetRealmGlobalOrNull(realm));
         if (global) {
             RefPtr<nsGlobalWindowInner> window;
             if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, global, window))) {
                 // The global is a |window| object.  Use the path prefix that
                 // we should have already created for it.
@@ -2183,27 +2182,27 @@ class XPCJSRuntimeStats : public JS::Run
 
         extras->pathPrefix += nsPrintfCString("zone(0x%p)/", (void*)zone);
 
         MOZ_ASSERT(StartsWithExplicit(extras->pathPrefix));
 
         zStats->extra = extras;
     }
 
-    virtual void initExtraRealmStats(JSCompartment* c,
+    virtual void initExtraRealmStats(Handle<Realm*> realm,
                                      JS::RealmStats* realmStats) override
     {
+        JSCompartment* c = JS::GetCompartmentForRealm(realm);
         xpc::RealmStatsExtras* extras = new xpc::RealmStatsExtras;
         nsCString cName;
         GetCompartmentName(c, cName, &mAnonymizeID, /* replaceSlashes = */ true);
 
-        // Get the compartment's global.
+        // Get the realm's global.
         AutoSafeJSContext cx;
         bool needZone = true;
-        Rooted<Realm*> realm(cx, JS::GetRealmForCompartment(c));
         RootedObject global(cx, JS::GetRealmGlobalOrNull(realm));
         if (global) {
             RefPtr<nsGlobalWindowInner> window;
             if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, global, window))) {
                 // The global is a |window| object.  Use the path prefix that
                 // we should have already created for it.
                 if (mWindowPaths->Get(window->WindowID(),
                                       &extras->jsPathPrefix)) {
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -856,18 +856,17 @@ void
 AccessibleCaretManager::ChangeFocusToOrClearOldFocus(nsIFrame* aFrame) const
 {
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   MOZ_ASSERT(fm);
 
   if (aFrame) {
     nsIContent* focusableContent = aFrame->GetContent();
     MOZ_ASSERT(focusableContent, "Focusable frame must have content!");
-    RefPtr<Element> focusableElement =
-      focusableContent->IsElement() ? focusableContent->AsElement() : nullptr;
+    RefPtr<Element> focusableElement = Element::FromNode(focusableContent);
     fm->SetFocus(focusableElement, nsIFocusManager::FLAG_BYMOUSE);
   } else {
     nsPIDOMWindowOuter* win = mPresShell->GetDocument()->GetWindow();
     if (win) {
       fm->ClearFocus(win);
       fm->SetFocusedWindow(win);
     }
   }
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -157,22 +157,20 @@ static void Shutdown();
 #include "mozilla/dom/PresentationTCPSessionTransport.h"
 
 #include "nsScriptError.h"
 
 #include "mozilla/TextInputProcessor.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::net;
 using mozilla::dom::power::PowerManagerService;
 using mozilla::dom::quota::QuotaManagerService;
-using mozilla::dom::WorkerDebuggerManager;
-using mozilla::dom::UDPSocketChild;
 using mozilla::gmp::GeckoMediaPluginService;
-using mozilla::dom::NotificationTelemetryService;
 
 #define NS_EDITORCOMMANDTABLE_CID \
 { 0x4f5e62b8, 0xd659, 0x4156, \
   { 0x84, 0xfc, 0x2f, 0x60, 0x99, 0x40, 0x03, 0x69 } }
 
 #define NS_EDITINGCOMMANDTABLE_CID \
 { 0xcb38a746, 0xbeb8, 0x43f3, \
   { 0x94, 0x29, 0x77, 0x96, 0xe1, 0xa9, 0x3f, 0xb4 } }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9826,19 +9826,17 @@ GetCorrectedParent(const nsIFrame* aFram
   if (pseudo == nsCSSAnonBoxes::tableWrapper) {
     pseudo = aFrame->PrincipalChildList().FirstChild()->Style()->GetPseudo();
   }
 
   // Prevent a NAC pseudo-element from inheriting from its NAC parent, and
   // inherit from the NAC generator element instead.
   if (pseudo) {
     MOZ_ASSERT(aFrame->GetContent());
-    Element* element =
-      aFrame->GetContent()->IsElement()
-        ? aFrame->GetContent()->AsElement() : nullptr;
+    Element* element = Element::FromNode(aFrame->GetContent());
     // Make sure to avoid doing the fixup for non-element-backed pseudos like
     // ::first-line and such.
     if (element &&
         !element->IsRootOfNativeAnonymousSubtree() &&
         element->GetPseudoElementType() == aFrame->Style()->GetPseudoType()) {
       while (parent->GetContent() &&
              !parent->GetContent()->IsRootOfAnonymousSubtree()) {
         parent = parent->GetInFlowParent();
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -164,17 +164,17 @@ PeerConnectionMedia::InitLocalAddrs()
 
     nsCOMPtr<nsIEventTarget> target = mParent->GetWindow()
       ? mParent->GetWindow()->EventTargetFor(TaskCategory::Other)
       : nullptr;
 
     // We're in the content process, so send a request over IPC for the
     // stun address discovery.
     mStunAddrsRequest =
-      new StunAddrsRequestChild(new StunAddrsHandler(this), target);
+      new net::StunAddrsRequestChild(new StunAddrsHandler(this), target);
     mStunAddrsRequest->SendGetStunAddrs();
   } else {
     // No content process, so don't need to hold up the ice event queue
     // until completion of stun address discovery. We can let the
     // discovery of stun addresses happen in the same process.
     mLocalAddrsCompleted = true;
   }
 }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -484,19 +484,19 @@ var BrowserApp = {
       this.initContextMenu();
       ExternalApps.init();
     }, NativeWindow, "contextmenus");
 
     if (AppConstants.ACCESSIBILITY) {
       InitLater(() => GlobalEventDispatcher.dispatch("GeckoView:AccessibilityReady"));
       GlobalEventDispatcher.registerListener((aEvent, aData, aCallback) => {
         if (aData.enabled) {
-          AccessFu.attach(window);
+          AccessFu.enable();
         } else {
-          AccessFu.detach();
+          AccessFu.disable();
         }
       }, "GeckoView:AccessibilitySettings");
     }
 
     InitLater(() => {
       Task.spawn(function* () {
         let downloadsDir = yield Downloads.getPreferredDownloadsDirectory();
         let logsDir = OS.Path.join(downloadsDir, "memory-reports");
--- a/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewAccessibility.jsm
@@ -14,15 +14,15 @@ XPCOMUtils.defineLazyModuleGetters(this,
   AccessFu: "resource://gre/modules/accessibility/AccessFu.jsm"
 });
 
 class GeckoViewAccessibility extends GeckoViewModule {
   onInit() {
     EventDispatcher.instance.dispatch("GeckoView:AccessibilityReady");
     EventDispatcher.instance.registerListener((aEvent, aData, aCallback) => {
       if (aData.enabled) {
-        AccessFu.attach(this.window);
+        AccessFu.enable();
       } else {
-        AccessFu.detach();
+        AccessFu.disable();
       }
     }, "GeckoView:AccessibilitySettings");
   }
 }
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -637,25 +637,25 @@ LoadInfo::GetLoadingDocument(nsIDocument
 
 nsINode*
 LoadInfo::LoadingNode()
 {
   nsCOMPtr<nsINode> node = do_QueryReferent(mLoadingContext);
   return node;
 }
 
-nsISupports*
+already_AddRefed<nsISupports>
 LoadInfo::ContextForTopLevelLoad()
 {
   // Most likely you want to query LoadingNode() instead of
   // ContextForTopLevelLoad() if this assertion fires.
   MOZ_ASSERT(mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
             "should only query this context for top level document loads");
   nsCOMPtr<nsISupports> context = do_QueryReferent(mContextForTopLevelLoad);
-  return context;
+  return context.forget();
 }
 
 already_AddRefed<nsISupports>
 LoadInfo::GetLoadingContext()
 {
   nsCOMPtr<nsISupports> context;
   if (mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
     context = ContextForTopLevelLoad();
--- a/netwerk/base/nsAsyncStreamCopier.cpp
+++ b/netwerk/base/nsAsyncStreamCopier.cpp
@@ -9,16 +9,17 @@
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsIBufferedStreams.h"
 #include "nsIRequestObserver.h"
 #include "mozilla/Logging.h"
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 #undef LOG
 //
 // MOZ_LOG=nsStreamCopier:5
 //
 static LazyLogModule gStreamCopierLog("nsStreamCopier");
 #define LOG(args) MOZ_LOG(gStreamCopierLog, mozilla::LogLevel::Debug, args)
 
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -86,17 +86,17 @@ nsBaseChannel::Redirect(nsIChannel *newC
   newChannel->SetLoadFlags(mLoadFlags | LOAD_REPLACE);
 
   // make a copy of the loadinfo, append to the redirectchain
   // and set it on the new channel
   if (mLoadInfo) {
     nsSecurityFlags secFlags = mLoadInfo->GetSecurityFlags() &
                                ~nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
     nsCOMPtr<nsILoadInfo> newLoadInfo =
-      static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->CloneWithNewSecFlags(secFlags);
+      static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->CloneWithNewSecFlags(secFlags);
 
     nsCOMPtr<nsIPrincipal> uriPrincipal;
     nsIScriptSecurityManager *sm = nsContentUtils::GetSecurityManager();
     sm->GetChannelURIPrincipal(this, getter_AddRefs(uriPrincipal));
     bool isInternalRedirect =
       (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
                         nsIChannelEventSink::REDIRECT_STS_UPGRADE));
 
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -364,17 +364,17 @@ interface nsILoadInfo : nsISupports
   /**
    * A C++ friendly version of the loadingContext for toplevel loads.
    * Most likely you want to query the ownerDocument or LoadingNode
    * and not this context only available for TYPE_DOCUMENT loads.
    * Please note that except for loads of TYPE_DOCUMENT, this
    * ContextForTopLevelLoad will always return null.
    */
   [noscript, notxpcom, nostdcall, binaryname(ContextForTopLevelLoad)]
-  nsISupports binaryContextForTopLevelLoad();
+  LoadContextRef binaryContextForTopLevelLoad();
 
   /**
    * For all loads except loads of TYPE_DOCUMENT, the loadingContext
    * simply returns the loadingNode. For loads of TYPE_DOCUMENT this
    * will return the context available for top-level loads which
    * do not have a loadingNode.
    */
   [binaryname(LoadingContextXPCOM)]
--- a/netwerk/base/nsIncrementalDownload.cpp
+++ b/netwerk/base/nsIncrementalDownload.cpp
@@ -35,16 +35,17 @@
 #define DEFAULT_INTERVAL    60          // seconds
 
 #define UPDATE_PROGRESS_INTERVAL PRTime(100 * PR_USEC_PER_MSEC) // 100ms
 
 // Number of times to retry a failed byte-range request.
 #define MAX_RETRY_COUNT 20
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 //-----------------------------------------------------------------------------
 
 static nsresult
 WriteToFile(nsIFile *lf, const char *data, uint32_t len, int32_t flags)
 {
   PRFileDesc *fd;
   int32_t mode = 0600;
--- a/netwerk/base/nsInputStreamPump.cpp
+++ b/netwerk/base/nsInputStreamPump.cpp
@@ -107,17 +107,17 @@ nsInputStreamPump::PeekStream(PeekSegmen
   rv = mAsyncStream->Available(&dummy64);
   if (NS_FAILED(rv))
     return rv;
   uint32_t dummy = (uint32_t)std::min(dummy64, (uint64_t)UINT32_MAX);
 
   PeekData data(callback, closure);
   return mAsyncStream->ReadSegments(CallPeekFunc,
                                     &data,
-                                    nsIOService::gDefaultSegmentSize,
+                                    net::nsIOService::gDefaultSegmentSize,
                                     &dummy);
 }
 
 nsresult
 nsInputStreamPump::EnsureWaiting()
 {
     mMutex.AssertCurrentThreadIn();
 
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -762,21 +762,21 @@ NS_NewInputStreamChannelInternal(nsIChan
                                  const nsACString& aContentCharset,
                                  nsINode* aLoadingNode,
                                  nsIPrincipal* aLoadingPrincipal,
                                  nsIPrincipal* aTriggeringPrincipal,
                                  nsSecurityFlags aSecurityFlags,
                                  nsContentPolicyType aContentPolicyType)
 {
   nsCOMPtr<nsILoadInfo> loadInfo =
-    new mozilla::LoadInfo(aLoadingPrincipal,
-                          aTriggeringPrincipal,
-                          aLoadingNode,
-                          aSecurityFlags,
-                          aContentPolicyType);
+    new mozilla::net::LoadInfo(aLoadingPrincipal,
+                               aTriggeringPrincipal,
+                               aLoadingNode,
+                               aSecurityFlags,
+                               aContentPolicyType);
   if (!loadInfo) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsCOMPtr<nsIInputStream> stream = Move(aStream);
 
   return NS_NewInputStreamChannelInternal(outChannel,
                                           aUri,
@@ -853,18 +853,19 @@ NS_NewInputStreamChannelInternal(nsIChan
                                  nsINode            *aLoadingNode,
                                  nsIPrincipal       *aLoadingPrincipal,
                                  nsIPrincipal       *aTriggeringPrincipal,
                                  nsSecurityFlags     aSecurityFlags,
                                  nsContentPolicyType aContentPolicyType,
                                  bool                aIsSrcdocChannel /* = false */)
 {
   nsCOMPtr<nsILoadInfo> loadInfo =
-      new mozilla::LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
-                            aLoadingNode, aSecurityFlags, aContentPolicyType);
+      new mozilla::net::LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
+                                 aLoadingNode, aSecurityFlags,
+                                 aContentPolicyType);
   return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
                                           loadInfo, aIsSrcdocChannel);
 }
 
 nsresult
 NS_NewInputStreamChannel(nsIChannel        **outChannel,
                          nsIURI             *aUri,
                          const nsAString    &aData,
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -3680,10 +3680,10 @@ nsStandardURL::SizeOfIncludingThis(Mallo
 
 } // namespace net
 } // namespace mozilla
 
 // For unit tests.  Including nsStandardURL.h seems to cause problems
 nsresult
 Test_NormalizeIPv4(const nsACString& host, nsCString& result)
 {
-    return nsStandardURL::NormalizeIPv4(host, result);
+    return mozilla::net::nsStandardURL::NormalizeIPv4(host, result);
 }
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -288,16 +288,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Name
 } // namespace net
 } // namespace mozilla
 #endif
 
 // resource
 #include "nsResProtocolHandler.h"
 #include "ExtensionProtocolHandler.h"
 #include "SubstitutingProtocolHandler.h"
+typedef mozilla::net::ExtensionProtocolHandler ExtensionProtocolHandler;
 typedef mozilla::net::SubstitutingURL::Mutator SubstitutingURLMutator;
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsResProtocolHandler, Init)
 
 namespace mozilla {
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ExtensionProtocolHandler,
     ExtensionProtocolHandler::GetSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(SubstitutingURLMutator)
 } // namespace mozilla
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -3508,17 +3508,17 @@ nsCookieService::CanSetCookie(nsIURI*   
   aSetCookie = true;
   return newCookie;
 }
 
 // processes a single cookie, and returns true if there are more cookies
 // to be processed
 bool
 nsCookieService::SetCookieInternal(nsIURI                        *aHostURI,
-                                   const mozilla::nsCookieKey    &aKey,
+                                   const mozilla::net::nsCookieKey &aKey,
                                    bool                           aRequireHostMatch,
                                    CookieStatus                   aStatus,
                                    nsDependentCString            &aCookieHeader,
                                    int64_t                        aServerTime,
                                    bool                           aFromHttp,
                                    nsIChannel                    *aChannel)
 {
   NS_ASSERTION(aHostURI, "null host!");
--- a/netwerk/protocol/data/nsDataChannel.cpp
+++ b/netwerk/protocol/data/nsDataChannel.cpp
@@ -86,17 +86,17 @@ nsDataChannel::OpenContentStream(bool as
     }
 
     nsCOMPtr<nsIInputStream> bufInStream;
     nsCOMPtr<nsIOutputStream> bufOutStream;
 
     // create an unbounded pipe.
     rv = NS_NewPipe(getter_AddRefs(bufInStream),
                     getter_AddRefs(bufOutStream),
-                    nsIOService::gDefaultSegmentSize,
+                    net::nsIOService::gDefaultSegmentSize,
                     UINT32_MAX,
                     async, true);
     if (NS_FAILED(rv))
         return rv;
 
     uint32_t contentLen;
     if (lBase64) {
         nsAutoCString decodedData;
--- a/netwerk/protocol/data/nsDataHandler.cpp
+++ b/netwerk/protocol/data/nsDataHandler.cpp
@@ -82,17 +82,17 @@ nsDataHandler::NewURI(const nsACString &
         if (base64 || (strncmp(contentType.get(),"text/",5) != 0 &&
                        contentType.Find("xml") == kNotFound)) {
             // it's ascii encoded binary, don't let any spaces in
             if (!spec.StripWhitespace(mozilla::fallible)) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
         }
 
-        rv = NS_MutateURI(new nsSimpleURI::Mutator())
+        rv = NS_MutateURI(new mozilla::net::nsSimpleURI::Mutator())
                .SetSpec(spec)
                .Finalize(uri);
     }
 
     if (NS_FAILED(rv))
         return rv;
 
     uri.forget(result);
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -3263,17 +3263,17 @@ HttpBaseChannel::CloneLoadInfoForRedirec
 {
   // make a copy of the loadinfo, append to the redirectchain
   // this will be set on the newly created channel for the redirect target.
   if (!mLoadInfo) {
     return nullptr;
   }
 
   nsCOMPtr<nsILoadInfo> newLoadInfo =
-    static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
+    static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->Clone();
 
   nsContentPolicyType contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
   if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
       contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
     nsCOMPtr<nsIPrincipal> nullPrincipalToInherit = NullPrincipal::CreateWithoutOriginAttributes();
     newLoadInfo->SetPrincipalToInherit(nullPrincipalToInherit);
   }
 
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -43,16 +43,17 @@
 #include "nsISupportsImpl.h"
 #include "nsHttpChannel.h"
 #include "mozilla/LoadInfo.h"
 #include "nsIHttpHeaderVisitor.h"
 #include "nsQueryObject.h"
 #include <algorithm>
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 #define PREFLIGHT_CACHE_SIZE 100
 
 static bool gDisableCORS = false;
 static bool gDisableCORSPrivateData = false;
 
 static void
 LogBlockedRequest(nsIRequest* aRequest,
@@ -1485,19 +1486,19 @@ nsCORSListenerProxy::StartCORSPreflight(
   if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
     aCallback->OnPreflightSucceeded();
     return NS_OK;
   }
 
   // Either it wasn't cached or the cached result has expired. Build a
   // channel for the OPTIONS request.
 
-  nsCOMPtr<nsILoadInfo> loadInfo = static_cast<mozilla::LoadInfo*>
+  nsCOMPtr<nsILoadInfo> loadInfo = static_cast<mozilla::net::LoadInfo*>
     (originalLoadInfo.get())->CloneForNewRequest();
-  static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetIsPreflight();
+  static_cast<mozilla::net::LoadInfo*>(loadInfo.get())->SetIsPreflight();
 
   nsCOMPtr<nsILoadGroup> loadGroup;
   rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We want to give the preflight channel's notification callbacks the same
   // load context as the original channel's notification callbacks had.  We
   // don't worry about a load context provided via the loadgroup here, since
--- a/netwerk/protocol/http/nsIHttpChannelChild.idl
+++ b/netwerk/protocol/http/nsIHttpChannelChild.idl
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 #include "nsISupports.idl"
 
 [ptr] native RequestHeaderTuples(mozilla::net::RequestHeaderTuples);
-[ref] native OptionalCorsPreflightArgsRef(mozilla::OptionalCorsPreflightArgs);
+[ref] native OptionalCorsPreflightArgsRef(mozilla::net::OptionalCorsPreflightArgs);
 
 interface nsIPrincipal;
 interface nsIURI;
 
 [uuid(d02b96ed-2789-4f42-a25c-7abe63de7c18)]
 interface nsIHttpChannelChild : nsISupports
 {
   [must_use] void addCookiesToRequest();
--- a/netwerk/protocol/res/nsResProtocolHandler.h
+++ b/netwerk/protocol/res/nsResProtocolHandler.h
@@ -12,58 +12,58 @@
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
 #include "nsStandardURL.h"
 
 class nsISubstitutionObserver;
 
 struct SubstitutionMapping;
 class nsResProtocolHandler final : public nsIResProtocolHandler,
-                                   public mozilla::SubstitutingProtocolHandler,
+                                   public mozilla::net::SubstitutingProtocolHandler,
                                    public nsSupportsWeakReference
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIRESPROTOCOLHANDLER
 
-    NS_FORWARD_NSIPROTOCOLHANDLER(mozilla::SubstitutingProtocolHandler::)
+    NS_FORWARD_NSIPROTOCOLHANDLER(mozilla::net::SubstitutingProtocolHandler::)
 
     nsResProtocolHandler()
-      : SubstitutingProtocolHandler("resource", URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE,
-                                    /* aEnforceFileOrJar = */ false)
+      : mozilla::net::SubstitutingProtocolHandler("resource", URI_STD | URI_IS_UI_RESOURCE | URI_IS_LOCAL_RESOURCE,
+                                                  /* aEnforceFileOrJar = */ false)
     {}
 
     MOZ_MUST_USE nsresult Init();
 
     NS_IMETHOD SetSubstitution(const nsACString& aRoot, nsIURI* aBaseURI) override;
     NS_IMETHOD SetSubstitutionWithFlags(const nsACString& aRoot, nsIURI* aBaseURI, uint32_t aFlags) override;
 
     NS_IMETHOD GetSubstitution(const nsACString& aRoot, nsIURI** aResult) override
     {
-        return mozilla::SubstitutingProtocolHandler::GetSubstitution(aRoot, aResult);
+        return mozilla::net::SubstitutingProtocolHandler::GetSubstitution(aRoot, aResult);
     }
 
     NS_IMETHOD HasSubstitution(const nsACString& aRoot, bool* aResult) override
     {
-        return mozilla::SubstitutingProtocolHandler::HasSubstitution(aRoot, aResult);
+        return mozilla::net::SubstitutingProtocolHandler::HasSubstitution(aRoot, aResult);
     }
 
     NS_IMETHOD ResolveURI(nsIURI *aResURI, nsACString& aResult) override
     {
-        return mozilla::SubstitutingProtocolHandler::ResolveURI(aResURI, aResult);
+        return mozilla::net::SubstitutingProtocolHandler::ResolveURI(aResURI, aResult);
     }
 
     NS_IMETHOD AddObserver(nsISubstitutionObserver *aObserver) override
     {
-        return mozilla::SubstitutingProtocolHandler::AddObserver(aObserver);
+        return mozilla::net::SubstitutingProtocolHandler::AddObserver(aObserver);
     }
 
     NS_IMETHOD RemoveObserver(nsISubstitutionObserver *aObserver) override
     {
-        return mozilla::SubstitutingProtocolHandler::RemoveObserver(aObserver);
+        return mozilla::net::SubstitutingProtocolHandler::RemoveObserver(aObserver);
     }
 
 protected:
     MOZ_MUST_USE nsresult GetSubstitutionInternal(const nsACString& aRoot, nsIURI** aResult, uint32_t* aFlags) override;
     virtual ~nsResProtocolHandler() = default;
 
     MOZ_MUST_USE bool ResolveSpecialCases(const nsACString& aHost,
                                           const nsACString& aPath,
--- a/security/manager/ssl/PSMContentListener.cpp
+++ b/security/manager/ssl/PSMContentListener.cpp
@@ -266,17 +266,17 @@ PSMContentDownloaderParent::OnStopReques
 }
 
 mozilla::ipc::IPCResult
 PSMContentDownloaderParent::RecvDivertToParentUsing(mozilla::net::PChannelDiverterParent* diverter)
 {
   MOZ_ASSERT(diverter);
   auto p = static_cast<mozilla::net::ChannelDiverterParent*>(diverter);
   p->DivertTo(this);
-  mozilla::Unused << ChannelDiverterParent::Send__delete__(p);
+  mozilla::Unused << mozilla::net::ChannelDiverterParent::Send__delete__(p);
   return IPC_OK();
 }
 
 void
 PSMContentDownloaderParent::ActorDestroy(ActorDestroyReason why)
 {
   mIPCOpen = false;
 }
--- a/testing/web-platform/meta/fetch/api/redirect/redirect-count.any.js.ini
+++ b/testing/web-platform/meta/fetch/api/redirect/redirect-count.any.js.ini
@@ -1,3 +1,3 @@
-[redirect-count.any.js]
+[redirect-count.any.html]
   disabled:
     if (os == "linux"): https://bugzilla.mozilla.org/show_bug.cgi?id=1462836
--- a/toolkit/components/browser/nsWebBrowserContentPolicy.cpp
+++ b/toolkit/components/browser/nsWebBrowserContentPolicy.cpp
@@ -23,34 +23,33 @@ NS_IMPL_ISUPPORTS(nsWebBrowserContentPol
 NS_IMETHODIMP
 nsWebBrowserContentPolicy::ShouldLoad(nsIURI* aContentLocation,
                                       nsILoadInfo* aLoadInfo,
                                       const nsACString& aMimeGuess,
                                       int16_t* aShouldLoad)
 {
   MOZ_ASSERT(aShouldLoad, "Null out param");
 
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestingContext = aLoadInfo->GetLoadingContext();
-
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aShouldLoad = nsIContentPolicy::ACCEPT;
 
-  nsIDocShell* shell = NS_CP_GetDocShellFromContext(aRequestingContext);
+  nsCOMPtr<nsISupports> context = aLoadInfo->GetLoadingContext();
+  nsIDocShell* shell = NS_CP_GetDocShellFromContext(context);
   /* We're going to dereference shell, so make sure it isn't null */
   if (!shell) {
     return NS_OK;
   }
 
   nsresult rv;
   bool allowed = true;
 
-  switch (aContentType) {
+  switch (contentType) {
     case nsIContentPolicy::TYPE_SCRIPT:
       rv = shell->GetAllowJavascript(&allowed);
       break;
     case nsIContentPolicy::TYPE_SUBDOCUMENT:
       rv = shell->GetAllowSubframes(&allowed);
       break;
 #if 0
     /* XXXtw: commented out in old code; add during conpol phase 2 */
@@ -75,30 +74,29 @@ nsWebBrowserContentPolicy::ShouldLoad(ns
 NS_IMETHODIMP
 nsWebBrowserContentPolicy::ShouldProcess(nsIURI* aContentLocation,
                                          nsILoadInfo* aLoadInfo,
                                          const nsACString& aMimeGuess,
                                          int16_t* aShouldProcess)
 {
   MOZ_ASSERT(aShouldProcess, "Null out param");
 
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  nsCOMPtr<nsISupports> aRequestingContext = aLoadInfo->GetLoadingContext();
-
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aShouldProcess = nsIContentPolicy::ACCEPT;
 
   // Object tags will always open channels with TYPE_OBJECT, but may end up
   // loading with TYPE_IMAGE or TYPE_DOCUMENT as their final type, so we block
   // actual-plugins at the process stage
-  if (aContentType != nsIContentPolicy::TYPE_OBJECT) {
+  if (contentType != nsIContentPolicy::TYPE_OBJECT) {
     return NS_OK;
   }
 
-  nsIDocShell* shell = NS_CP_GetDocShellFromContext(aRequestingContext);
+  nsCOMPtr<nsISupports> context = aLoadInfo->GetLoadingContext();
+  nsIDocShell* shell = NS_CP_GetDocShellFromContext(context);
   if (shell && (!shell->PluginsAllowedInCurrentDoc())) {
     *aShouldProcess = nsIContentPolicy::REJECT_TYPE;
   }
 
   return NS_OK;
 }
--- a/toolkit/components/extensions/webrequest/StreamFilterParent.cpp
+++ b/toolkit/components/extensions/webrequest/StreamFilterParent.cpp
@@ -132,17 +132,17 @@ StreamFilterParent::Create(dom::ContentP
 {
   AssertIsMainThread();
 
   auto& webreq = WebRequestService::GetSingleton();
 
   RefPtr<nsAtom> addonId = NS_Atomize(aAddonId);
   nsCOMPtr<nsITraceableChannel> channel = webreq.GetTraceableChannel(aChannelId, addonId, aContentParent);
 
-  RefPtr<nsHttpChannel> chan = do_QueryObject(channel);
+  RefPtr<mozilla::net::nsHttpChannel> chan = do_QueryObject(channel);
   NS_ENSURE_TRUE(chan, false);
 
   auto channelPid = chan->ProcessId();
   NS_ENSURE_TRUE(channelPid, false);
 
   Endpoint<PStreamFilterParent> parent;
   Endpoint<PStreamFilterChild> child;
   nsresult rv = PStreamFilter::CreateEndpoints(channelPid,
@@ -688,17 +688,17 @@ StreamFilterParent::FlushBufferedData()
 
 /*****************************************************************************
  * Thread helpers
  *****************************************************************************/
 
 nsIEventTarget*
 StreamFilterParent::ActorThread()
 {
-  return gSocketTransportService;
+  return net::gSocketTransportService;
 }
 
 bool
 StreamFilterParent::IsActorThread()
 {
   return ActorThread()->IsOnCurrentThread();
 }
 
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -393,18 +393,17 @@ nsWebBrowserFind::SetSelectionAndScroll(
     selCon->GetSelection(nsISelectionController::SELECTION_NORMAL);
   if (selection) {
     selection->RemoveAllRanges(IgnoreErrors());
     selection->AddRange(*aRange, IgnoreErrors());
 
     nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
     if (fm) {
       if (tcFrame) {
-        RefPtr<Element> newFocusedElement =
-          content->IsElement() ? content->AsElement() : nullptr;
+        RefPtr<Element> newFocusedElement = Element::FromNode(content);
         fm->SetFocus(newFocusedElement, nsIFocusManager::FLAG_NOSCROLL);
       } else {
         RefPtr<Element> result;
         fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
                       nsIFocusManager::FLAG_NOSCROLL, getter_AddRefs(result));
       }
     }
 
--- a/toolkit/components/places/nsFaviconService.cpp
+++ b/toolkit/components/places/nsFaviconService.cpp
@@ -544,23 +544,23 @@ nsFaviconService::ReplaceFaviconDataFrom
                                     "APIDeprecationWarning",
                                     params, ArrayLength(params));
 
     loadingPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
   }
   NS_ENSURE_TRUE(loadingPrincipal, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsILoadInfo> loadInfo =
-    new mozilla::LoadInfo(loadingPrincipal,
-                          nullptr, // aTriggeringPrincipal
-                          nullptr, // aLoadingNode
-                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
-                          nsILoadInfo::SEC_ALLOW_CHROME |
-                          nsILoadInfo::SEC_DISALLOW_SCRIPT,
-                          nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON);
+    new mozilla::net::LoadInfo(loadingPrincipal,
+                               nullptr, // aTriggeringPrincipal
+                               nullptr, // aLoadingNode
+                               nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
+                               nsILoadInfo::SEC_ALLOW_CHROME |
+                               nsILoadInfo::SEC_DISALLOW_SCRIPT,
+                               nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON);
 
   nsCOMPtr<nsIChannel> channel;
   rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Blocking stream is OK for data URIs.
   nsCOMPtr<nsIInputStream> stream;
   rv = channel->Open2(getter_AddRefs(stream));
--- a/toolkit/mozapps/extensions/AddonContentPolicy.cpp
+++ b/toolkit/mozapps/extensions/AddonContentPolicy.cpp
@@ -92,70 +92,70 @@ LogMessage(const nsAString &aMessage, ns
 // Content policy enforcement:
 
 NS_IMETHODIMP
 AddonContentPolicy::ShouldLoad(nsIURI* aContentLocation,
                                nsILoadInfo* aLoadInfo,
                                const nsACString& aMimeTypeGuess,
                                int16_t* aShouldLoad)
 {
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  nsCOMPtr<nsISupports> aContext = aLoadInfo->GetLoadingContext();
-  nsCOMPtr<nsIURI> aRequestOrigin;
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  nsCOMPtr<nsIURI> requestOrigin;
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
   if (loadingPrincipal) {
-    loadingPrincipal->GetURI(getter_AddRefs(aRequestOrigin));
+    loadingPrincipal->GetURI(getter_AddRefs(requestOrigin));
   }
 
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 
   *aShouldLoad = nsIContentPolicy::ACCEPT;
 
-  if (!aRequestOrigin) {
+  if (!requestOrigin) {
     return NS_OK;
   }
 
   // Only apply this policy to requests from documents loaded from
   // moz-extension URLs, or to resources being loaded from moz-extension URLs.
   bool equals;
   if (!((NS_SUCCEEDED(aContentLocation->SchemeIs("moz-extension", &equals)) && equals) ||
-        (NS_SUCCEEDED(aRequestOrigin->SchemeIs("moz-extension", &equals)) && equals))) {
+        (NS_SUCCEEDED(requestOrigin->SchemeIs("moz-extension", &equals)) && equals))) {
     return NS_OK;
   }
 
-  if (aContentType == nsIContentPolicy::TYPE_SCRIPT) {
+  if (contentType == nsIContentPolicy::TYPE_SCRIPT) {
     NS_ConvertUTF8toUTF16 typeString(aMimeTypeGuess);
     nsContentTypeParser mimeParser(typeString);
 
     // Reject attempts to load JavaScript scripts with a non-default version.
     nsAutoString mimeType, version;
     if (NS_SUCCEEDED(mimeParser.GetType(mimeType)) &&
         nsContentUtils::IsJavascriptMIMEType(mimeType) &&
         NS_SUCCEEDED(mimeParser.GetParameter("version", version))) {
       *aShouldLoad = nsIContentPolicy::REJECT_REQUEST;
 
+      nsCOMPtr<nsISupports> context = aLoadInfo->GetLoadingContext();
       LogMessage(NS_LITERAL_STRING(VERSIONED_JS_BLOCKED_MESSAGE),
-                 aRequestOrigin, typeString, aContext);
+                 requestOrigin, typeString, context);
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AddonContentPolicy::ShouldProcess(nsIURI* aContentLocation,
                                   nsILoadInfo* aLoadInfo,
                                   const nsACString& aMimeTypeGuess,
                                   int16_t* aShouldProcess)
 {
 #ifdef DEBUG
-  uint32_t aContentType = aLoadInfo->GetExternalContentPolicyType();
-  MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
+  uint32_t contentType = aLoadInfo->GetExternalContentPolicyType();
+  MOZ_ASSERT(contentType == nsContentUtils::InternalContentPolicyTypeToExternal(contentType),
              "We should only see external content policy types here.");
 #endif
 
   *aShouldProcess = nsIContentPolicy::ACCEPT;
   return NS_OK;
 }
 
 
--- a/uriloader/exthandler/ExternalHelperAppParent.cpp
+++ b/uriloader/exthandler/ExternalHelperAppParent.cpp
@@ -191,17 +191,17 @@ ExternalHelperAppParent::RecvDivertToPar
 {
   MOZ_ASSERT(diverter);
   UpdateContentContext(mListener, contentContext);
   auto p = static_cast<mozilla::net::ChannelDiverterParent*>(diverter);
   p->DivertTo(this);
 #ifdef DEBUG
   mDiverted = true;
 #endif
-  Unused << ChannelDiverterParent::Send__delete__(p);
+  Unused << mozilla::net::ChannelDiverterParent::Send__delete__(p);
   return IPC_OK();
 }
 
 //
 // nsIStreamListener
 //
 
 NS_IMETHODIMP
--- a/uriloader/exthandler/nsExternalProtocolHandler.cpp
+++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp
@@ -400,17 +400,17 @@ NS_IMETHODIMP nsExtProtocolChannel::Comp
   // (which is needed for the select dialog).
   return AsyncOpen(listener, context);
 }
 
 ///////////////////////////////////////////////////////////////////////
 // From nsIParentChannel (derives from nsIStreamListener)
 //////////////////////////////////////////////////////////////////////
 
-NS_IMETHODIMP nsExtProtocolChannel::SetParentListener(HttpChannelParentListener* aListener)
+NS_IMETHODIMP nsExtProtocolChannel::SetParentListener(mozilla::net::HttpChannelParentListener* aListener)
 {
   // This is called as part of the connect parent operation from
   // ContentParent::RecvExtProtocolChannelConnectParent.  Setting
   // this flag tells this channel to not proceed and makes AsyncOpen
   // just no-op.  Actual operation will happen from the child process
   // via CompleteRedirectSetup call on the child channel.
   mConnectedParent = true;
   return NS_OK;
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -1249,17 +1249,17 @@ CycleCollectedJSRuntime::AreGCGrayBitsVa
 void
 CycleCollectedJSRuntime::GarbageCollect(uint32_t aReason) const
 {
   MOZ_ASSERT(aReason < JS::gcreason::NUM_REASONS);
   JS::gcreason::Reason gcreason = static_cast<JS::gcreason::Reason>(aReason);
 
   JSContext* cx = CycleCollectedJSContext::Get()->Context();
   JS::PrepareForFullGC(cx);
-  JS::GCForReason(cx, GC_NORMAL, gcreason);
+  JS::NonIncrementalGC(cx, GC_NORMAL, gcreason);
 }
 
 void
 CycleCollectedJSRuntime::JSObjectsTenured()
 {
   for (auto iter = mNurseryObjects.Iter(); !iter.Done(); iter.Next()) {
     nsWrapperCache* cache = iter.Get();
     JSObject* wrapper = cache->GetWrapperMaybeDead();