merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 27 Sep 2017 11:47:52 +0200
changeset 433914 35fbf14b96a633c3f66ea13c1a163a3f3a4219b9
parent 433878 5563e7da39b265ed1ba7796ec058bdbcf6f792f6 (current diff)
parent 433913 feb35ae6b09fe3e74a01b15e0fe68b598304893a (diff)
child 433915 6100472d3aa833dff22a4edb0934fe600f43ddb8
child 433949 f4c8f95554888546a066e98a8e017eb579ca51df
child 434043 d9aeb2853320191a95e7bf235dec5108266c37e0
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
35fbf14b96a6 / 58.0a1 / 20170927100120 / files
nightly mac
35fbf14b96a6 / 58.0a1 / 20170927100120 / files
nightly win32
35fbf14b96a6 / 58.0a1 / 20170927100120 / files
nightly win64
35fbf14b96a6 / 58.0a1 / 20170927100120 / files
nightly linux64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: BGCq2q6xO1S
browser/components/distribution.js
browser/components/tests/unit/test_distribution.js
browser/components/tests/unit/xpcshell.ini
dom/abort/tests/file_abort_controller.html
dom/abort/tests/file_abort_controller_fetch.html
dom/interfaces/html/nsIDOMHTMLAnchorElement.idl
modules/libpref/init/all.js
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/custom-elements/upgrading/Node-cloneNode.html.ini
testing/web-platform/meta/dom/__dir__.ini
testing/web-platform/meta/dom/abort/__dir__.ini
testing/web-platform/meta/dom/nodes/Node-cloneNode.html.ini
toolkit/components/telemetry/docs/data/first-shutdown.rst
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -596,19 +596,23 @@ NotificationController::WillRefresh(mozi
 
   // If the document accessible that notification collector was created for is
   // now shut down, don't process notifications anymore.
   NS_ASSERTION(mDocument,
                "The document was shut down while refresh observer is attached!");
   if (!mDocument)
     return;
 
+  // Wait until an update, we have started, or an interruptible reflow is
+  // finished.
   if (mObservingState == eRefreshProcessing ||
-      mObservingState == eRefreshProcessingForUpdate)
+      mObservingState == eRefreshProcessingForUpdate ||
+      mPresShell->IsReflowInterrupted()) {
     return;
+  }
 
   // Any generic notifications should be queued if we're processing content
   // insertions or generic notifications.
   mObservingState = eRefreshProcessingForUpdate;
 
   // Initial accessible tree construction.
   if (!mDocument->HasLoadState(DocAccessible::eTreeConstructed)) {
     // If document is not bound to parent at this point then the document is not
--- a/accessible/windows/msaa/RootAccessibleWrap.cpp
+++ b/accessible/windows/msaa/RootAccessibleWrap.cpp
@@ -82,16 +82,18 @@ RootAccessibleWrap::GetInternalUnknown()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // RootAccessible
 
 void
 RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
 {
+  // This check will never work with e10s enabled, in other words, as of
+  // Firefox 57.
   if (Compatibility::IsDolphin() &&
       nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
     uint32_t count = mChildDocuments.Length();
     for (uint32_t idx = 0; idx < count; idx++) {
       DocAccessible* childDoc = mChildDocuments[idx];
       HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
       if (childDoc != aDocument)
         nsWinUtils::HideNativeWindow(childDocHWND);
--- a/browser/branding/aurora/pref/firefox-branding.js
+++ b/browser/branding/aurora/pref/firefox-branding.js
@@ -1,16 +1,16 @@
 
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 pref("startup.homepage_override_url", "");
-pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/");
+pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%a2/firstrun/");
 pref("startup.homepage_welcome_url.additional", "");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 28800); // 8 hours
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 // 0 means "download everything at once"
 pref("app.update.download.backgroundInterval", 0);
 // Give the user x seconds to react before showing the big UI. default=192 hours
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -7,55 +7,87 @@ this.EXPORTED_SYMBOLS = [ "DistributionC
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cr = Components.results;
 var Cu = Components.utils;
 
 const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
   "distribution-customization-complete";
 
+const PREF_CACHED_FILE_EXISTENCE  = "distribution.iniFile.exists.value";
+const PREF_CACHED_FILE_APPVERSION = "distribution.iniFile.exists.appversion";
+
+Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
                                   "resource://gre/modules/Preferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 this.DistributionCustomizer = function DistributionCustomizer() {
-  // For parallel xpcshell testing purposes allow loading the distribution.ini
-  // file from the profile folder through an hidden pref.
-  let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
-  let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-               getService(Ci.nsIProperties);
-  try {
-    let iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
-                                  : dirSvc.get("XREAppDist", Ci.nsIFile);
-    if (loadFromProfile) {
-      iniFile.leafName = "distribution";
-    }
-    iniFile.append("distribution.ini");
-    if (iniFile.exists())
-      this._iniFile = iniFile;
-  } catch (ex) {}
 }
 
 DistributionCustomizer.prototype = {
-  _iniFile: null,
+  get _iniFile() {
+    // For parallel xpcshell testing purposes allow loading the distribution.ini
+    // file from the profile folder through an hidden pref.
+    let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
+    let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+                 getService(Ci.nsIProperties);
+
+    let iniFile;
+    try {
+      iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
+                                : dirSvc.get("XREAppDist", Ci.nsIFile);
+      if (loadFromProfile) {
+        iniFile.leafName = "distribution";
+      }
+      iniFile.append("distribution.ini");
+    } catch (ex) {}
+
+    this.__defineGetter__("_iniFile", () => iniFile);
+    return iniFile;
+  },
+
+  get _hasDistributionIni() {
+    if (Services.prefs.prefHasUserValue(PREF_CACHED_FILE_EXISTENCE)) {
+      let knownForVersion = Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown");
+      if (knownForVersion == AppConstants.MOZ_APP_VERSION) {
+        return Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE);
+      }
+    }
+
+    let fileExists = this._iniFile.exists();
+    Services.prefs.setBoolPref(PREF_CACHED_FILE_EXISTENCE, fileExists);
+    Services.prefs.setStringPref(PREF_CACHED_FILE_APPVERSION, AppConstants.MOZ_APP_VERSION);
+
+    this.__defineGetter__("_hasDistributionIni", () => fileExists);
+    return fileExists;
+  },
 
   get _ini() {
     let ini = null;
     try {
-      if (this._iniFile) {
+      if (this._hasDistributionIni) {
         ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
               getService(Ci.nsIINIParserFactory).
               createINIParser(this._iniFile);
       }
     } catch (e) {
-      // Unable to parse INI.
-      Cu.reportError("Unable to parse distribution.ini");
+      if (e.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
+        // We probably had cached the file existence as true,
+        // but it no longer exists. We could set the new cache
+        // value here, but let's just invalidate the cache and
+        // let it be cached by a single code path on the next check.
+        Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
+      } else {
+        // Unable to parse INI.
+        Cu.reportError("Unable to parse distribution.ini");
+      }
     }
     this.__defineGetter__("_ini", () => ini);
     return this._ini;
   },
 
   get _locale() {
     const locale = Services.locale.getRequestedLocale() || "en-US";
     this.__defineGetter__("_locale", () => locale);
--- a/browser/components/tests/unit/test_distribution.js
+++ b/browser/components/tests/unit/test_distribution.js
@@ -81,16 +81,17 @@ function run_test() {
 
 do_register_cleanup(function() {
   // Remove the distribution dir, even if the test failed, otherwise all
   // next tests will use it.
   let distDir = gProfD.clone();
   distDir.append("distribution");
   distDir.remove(true);
   Assert.ok(!distDir.exists());
+  Services.prefs.clearUserPref("distribution.testing.loadFromProfile");
 });
 
 add_task(async function() {
   // Force distribution.
   let glue = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver)
   glue.observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_DISTRIBUTION_CUSTOMIZATION);
 
   var defaultBranch = Services.prefs.getDefaultBranch(null);
new file mode 100644
--- /dev/null
+++ b/browser/components/tests/unit/test_distribution_cachedexistence.js
@@ -0,0 +1,118 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that DistributionCustomizer correctly caches the existence
+ * of the distribution.ini file and just rechecks it after a version
+ * update.
+ */
+
+const PREF_CACHED_FILE_EXISTENCE  = "distribution.iniFile.exists.value";
+const PREF_CACHED_FILE_APPVERSION = "distribution.iniFile.exists.appversion";
+const PREF_LOAD_FROM_PROFILE      = "distribution.testing.loadFromProfile";
+
+const gTestDir = do_get_cwd();
+
+Cu.import("resource://gre/modules/AppConstants.jsm");
+
+add_task(async function() {
+  // Start with a clean slate of the prefs that control this feature.
+  Services.prefs.clearUserPref(PREF_CACHED_FILE_APPVERSION);
+  Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
+  setupTest();
+
+  let {DistributionCustomizer} = Cu.import("resource:///modules/distribution.js", {});
+  let distribution = new DistributionCustomizer();
+
+  copyDistributionToProfile();
+
+  // Check that checking for distribution.ini returns the right value and sets up
+  // the cached prefs.
+  let exists = distribution._hasDistributionIni;
+
+  Assert.ok(exists);
+  Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
+               true);
+  Assert.equal(Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown"),
+               AppConstants.MOZ_APP_VERSION);
+
+  // Check that calling _hasDistributionIni again will use the cached value. We do
+  // this by deleting the file and expecting it to still return true instead of false.
+  // Also, we need to delete _hasDistributionIni from the object because the getter
+  // was replaced with a stored value.
+  deleteDistribution();
+  delete distribution._hasDistributionIni;
+
+  exists = distribution._hasDistributionIni;
+  Assert.ok(exists);
+
+  // Now let's invalidate the PREF_CACHED_FILE_EXISTENCE pref to make sure the
+  // value gets recomputed correctly.
+  Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
+  delete distribution._hasDistributionIni;
+  exists = distribution._hasDistributionIni;
+
+  // It now should return false, as well as storing false in the pref.
+  Assert.ok(!exists);
+  Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
+               false);
+
+  // Check now that it will use the new cached value instead of returning true in
+  // the presence of the file.
+  copyDistributionToProfile();
+  delete distribution._hasDistributionIni;
+  exists = distribution._hasDistributionIni;
+
+  Assert.ok(!exists);
+
+  // Now let's do the same, but invalidating the App Version, as if a version
+  // update occurred.
+  Services.prefs.setStringPref(PREF_CACHED_FILE_APPVERSION, "older version");
+  delete distribution._hasDistributionIni;
+  exists = distribution._hasDistributionIni;
+
+  Assert.ok(exists);
+  Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
+               true);
+  Assert.equal(Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown"),
+               AppConstants.MOZ_APP_VERSION);
+});
+
+
+/*
+ * Helper functions
+ */
+function copyDistributionToProfile() {
+  // Copy distribution.ini file to the profile dir.
+  let distroDir = gProfD.clone();
+  distroDir.leafName = "distribution";
+  let iniFile = distroDir.clone();
+  iniFile.append("distribution.ini");
+  if (iniFile.exists()) {
+    iniFile.remove(false);
+    print("distribution.ini already exists, did some test forget to cleanup?");
+  }
+
+  let testDistributionFile = gTestDir.clone();
+  testDistributionFile.append("distribution.ini");
+  testDistributionFile.copyTo(distroDir, "distribution.ini");
+  Assert.ok(testDistributionFile.exists());
+}
+
+function deleteDistribution() {
+  let distroDir = gProfD.clone();
+  distroDir.leafName = "distribution";
+  let iniFile = distroDir.clone();
+  iniFile.append("distribution.ini");
+  iniFile.remove(false);
+}
+
+function setupTest() {
+  // Set special pref to load distribution.ini from the profile folder.
+  Services.prefs.setBoolPref(PREF_LOAD_FROM_PROFILE, true);
+}
+
+do_register_cleanup(function() {
+  deleteDistribution();
+  Services.prefs.clearUserPref(PREF_LOAD_FROM_PROFILE);
+});
--- a/browser/components/tests/unit/xpcshell.ini
+++ b/browser/components/tests/unit/xpcshell.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 head = head.js
 firefox-appdir = browser
 skip-if = toolkit == 'android'
 support-files =
   distribution.ini
   data/engine-de-DE.xml
 
+[test_browserGlue_migration_loop_cleanup.js]
 [test_distribution.js]
-[test_browserGlue_migration_loop_cleanup.js]
+[test_distribution_cachedexistence.js]
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -170,17 +170,17 @@ PluginContent.prototype = {
   },
 
   getPluginUI(plugin, anonid) {
     return plugin.ownerDocument.
            getAnonymousElementByAttribute(plugin, "anonid", anonid);
   },
 
   _getPluginInfo(pluginElement) {
-    if (pluginElement instanceof Ci.nsIDOMHTMLAnchorElement) {
+    if (ChromeUtils.getClassName(pluginElement) === "HTMLAnchorElement") {
       // Anchor elements are our place holders, and we only have them for Flash
       let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
       return {
         pluginName: "Shockwave Flash",
         mimetype: FLASH_MIME_TYPE,
         permissionString: pluginHost.getPermissionStringForType(FLASH_MIME_TYPE)
       };
     }
@@ -644,17 +644,17 @@ PluginContent.prototype = {
     this.global.content.location.reload();
   },
 
   // Event listener for click-to-play plugins.
   _handleClickToPlayEvent(plugin) {
     let doc = plugin.ownerDocument;
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     let permissionString;
-    if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
+    if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
       // We only have replacement content for Flash installs
       permissionString = pluginHost.getPermissionStringForType(FLASH_MIME_TYPE);
     } else {
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       // guard against giving pluginHost.getPermissionStringForType a type
       // not associated with any known plugin
       if (!this.isKnownPlugin(objLoadingContent))
         return;
@@ -676,20 +676,19 @@ PluginContent.prototype = {
     if (overlay) {
       overlay.addEventListener("click", this, true);
     }
   },
 
   onOverlayClick(event) {
     let document = event.target.ownerDocument;
     let plugin = document.getBindingParent(event.target);
-    let contentWindow = plugin.ownerGlobal.top;
     let overlay = this.getPluginUI(plugin, "main");
     // Have to check that the target is not the link to update the plugin
-    if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
+    if (!(ChromeUtils.getClassName(event.originalTarget) === "HTMLAnchorElement") &&
         (event.originalTarget.getAttribute("anonid") != "closeIcon") &&
         !overlay.hasAttribute("dismissed") &&
         event.button == 0 &&
         event.isTrusted) {
       this._showClickToPlayNotification(plugin, true);
     event.stopPropagation();
     event.preventDefault();
     }
@@ -725,17 +724,17 @@ PluginContent.prototype = {
     let placeHolderFound = false;
     for (let plugin of plugins) {
       plugin.QueryInterface(Ci.nsIObjectLoadingContent);
       if (!this.isKnownPlugin(plugin)) {
         continue;
       }
       if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
         let overlay = this.getPluginUI(plugin, "main");
-        if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
+        if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
           placeHolderFound = true;
         } else {
           pluginFound = true;
         }
         if (newState == "block") {
           if (overlay) {
             overlay.addEventListener("click", this, true);
           }
--- a/devtools/client/shared/curl.js
+++ b/devtools/client/shared/curl.js
@@ -34,18 +34,16 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 "use strict";
 
 const Services = require("Services");
 
-const DEFAULT_HTTP_VERSION = "HTTP/1.1";
-
 const Curl = {
   /**
    * Generates a cURL command string which can be used from the command line etc.
    *
    * @param object data
    *        Datasource to create the command from.
    *        The object must contain the following properties:
    *        - url:string, the URL of the request.
@@ -101,21 +99,16 @@ const Curl = {
 
     // Add -I (HEAD)
     // For servers that supports HEAD.
     // This will fetch the header of a document only.
     if (data.method == "HEAD") {
       command.push("-I");
     }
 
-    // Add http version.
-    if (data.httpVersion && data.httpVersion != DEFAULT_HTTP_VERSION) {
-      command.push("--" + data.httpVersion.split("/")[1]);
-    }
-
     // Add request headers.
     let headers = data.headers;
     if (multipartRequest) {
       let multipartHeaders = utils.getHeadersFromMultipartText(postDataText);
       headers = headers.concat(multipartHeaders);
     }
     for (let i = 0; i < headers.length; i++) {
       let header = headers[i];
--- a/devtools/client/shared/vendor/WasmDis.js
+++ b/devtools/client/shared/vendor/WasmDis.js
@@ -742,9 +742,8 @@ var WasmDisassembler = (function () {
                 default:
                     throw new Error("Expectected state: " + reader.state);
             }
         }
     };
     return WasmDisassembler;
 }());
 exports.WasmDisassembler = WasmDisassembler;
-//# sourceMappingURL=WasmDis.js.map
\ No newline at end of file
--- a/devtools/client/shared/vendor/WasmParser.js
+++ b/devtools/client/shared/vendor/WasmParser.js
@@ -1395,9 +1395,8 @@ if (typeof TextDecoder !== 'undefined') 
     catch (_) { }
 }
 if (!exports.bytesToString) {
     exports.bytesToString = function (b) {
         var str = String.fromCharCode.apply(null, b);
         return decodeURIComponent(escape(str));
     };
 }
-//# sourceMappingURL=WasmParser.js.map
\ No newline at end of file
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -72,90 +72,89 @@ function ObjectActor(obj, {
 
 ObjectActor.prototype = {
   actorPrefix: "obj",
 
   /**
    * Returns a grip for this actor for returning in a protocol message.
    */
   grip: function () {
-    this.hooks.incrementGripDepth();
-
     let g = {
       "type": "object",
       "actor": this.actorID
     };
 
-    // If it's a proxy, lie and tell that it belongs to an invented "Proxy" class.
-    // The `isProxy` function detects them even behind non-opaque security wrappers,
-    // which is useful to avoid running proxy traps through transparent wrappers.
-    if (isProxy(this.obj)) {
+    // Check if the object has a wrapper which denies access. It may be a CPOW or a
+    // security wrapper. Change the class so that this will be visible in the UI.
+    let unwrapped = unwrap(this.obj);
+    if (!unwrapped) {
+      if (DevToolsUtils.isCPOW(this.obj)) {
+        g.class = "CPOW: " + g.class;
+      } else {
+        g.class = "Inaccessible";
+      }
+      return g;
+    }
+
+    // Dead objects also deny access.
+    if (this.obj.class == "DeadObject") {
+      g.class = "DeadObject";
+      return g;
+    }
+
+    // Otherwise, increment grip depth and attempt to create a preview.
+    this.hooks.incrementGripDepth();
+
+    // The `isProxy` getter is called on `unwrapped` instead of `this.obj` in order
+    // to detect proxies behind transparent wrappers, and thus avoid running traps.
+    if (unwrapped.isProxy) {
       g.class = "Proxy";
     } else {
-      try {
-        g.class = this.obj.class;
-        g.extensible = this.obj.isExtensible();
-        g.frozen = this.obj.isFrozen();
-        g.sealed = this.obj.isSealed();
-      } catch (e) {
-        // Handle cases where the underlying object's calls to isExtensible, etc throw.
-        // This is possible with ProxyObjects like CPOWs. Note these are different from
-        // scripted Proxies created via `new Proxy`, which match isProxy(this.obj) above.
-      }
-    }
-
-    // Changing the class so that CPOWs will be visible in the UI
-    let isCPOW = DevToolsUtils.isCPOW(this.obj);
-    if (isCPOW) {
-      g.class = "CPOW: " + g.class;
+      g.class = this.obj.class;
+      g.extensible = this.obj.isExtensible();
+      g.frozen = this.obj.isFrozen();
+      g.sealed = this.obj.isSealed();
     }
 
-    if (g.class != "DeadObject" && !isCPOW) {
-      if (g.class == "Promise") {
-        g.promiseState = this._createPromiseState();
-      }
+    if (g.class == "Promise") {
+      g.promiseState = this._createPromiseState();
+    }
+
+    // FF40+: Allow to know how many properties an object has to lazily display them
+    // when there is a bunch.
+    if (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
+      // Bug 1348761: getOwnPropertyNames is unnecessary slow on TypedArrays
+      let length = DevToolsUtils.getProperty(this.obj, "length");
+      g.ownPropertyLength = length;
+    } else if (g.class != "Proxy") {
+      g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
+    }
+
+    let raw = this.obj.unsafeDereference();
 
-      // FF40+: Allow to know how many properties an object has
-      // to lazily display them when there is a bunch.
-      // Throws on some MouseEvent object in tests.
+    // If Cu is not defined, we are running on a worker thread, where xrays
+    // don't exist.
+    if (Cu) {
+      raw = Cu.unwaiveXrays(raw);
+    }
+
+    if (!DevToolsUtils.isSafeJSObject(raw)) {
+      raw = null;
+    }
+
+    let previewers = DebuggerServer.ObjectActorPreviewers[g.class] ||
+                     DebuggerServer.ObjectActorPreviewers.Object;
+    for (let fn of previewers) {
       try {
-        if (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
-          // Bug 1348761: getOwnPropertyNames is unecessary slow on TypedArrays
-          let length = DevToolsUtils.getProperty(this.obj, "length");
-          g.ownPropertyLength = length;
-        } else if (g.class != "Proxy") {
-          g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
+        if (fn(this, g, raw)) {
+          break;
         }
       } catch (e) {
-        // ignored
-      }
-
-      let raw = this.obj.unsafeDereference();
-
-      // If Cu is not defined, we are running on a worker thread, where xrays
-      // don't exist.
-      if (Cu) {
-        raw = Cu.unwaiveXrays(raw);
-      }
-
-      if (!DevToolsUtils.isSafeJSObject(raw)) {
-        raw = null;
-      }
-
-      let previewers = DebuggerServer.ObjectActorPreviewers[g.class] ||
-                       DebuggerServer.ObjectActorPreviewers.Object;
-      for (let fn of previewers) {
-        try {
-          if (fn(this, g, raw)) {
-            break;
-          }
-        } catch (e) {
-          let msg = "ObjectActor.prototype.grip previewer function";
-          DevToolsUtils.reportException(msg, e);
-        }
+        let msg = "ObjectActor.prototype.grip previewer function";
+        DevToolsUtils.reportException(msg, e);
       }
     }
 
     this.hooks.decrementGripDepth();
     return g;
   },
 
   /**
@@ -285,30 +284,30 @@ ObjectActor.prototype = {
    *                    ownProperties, because we can have multiple symbols with the same
    *                    name in this.obj, e.g. `{[Symbol()]: "a", [Symbol()]: "b"}`.
    *          - {Object} safeGetterValues: an object that maps this.obj's property names
    *                     with safe getters descriptors.
    */
   onPrototypeAndProperties: function () {
     let ownProperties = Object.create(null);
     let ownSymbols = [];
-    let names;
-    let symbols;
-    try {
-      names = this.obj.getOwnPropertyNames();
-      symbols = this.obj.getOwnPropertySymbols();
-    } catch (ex) {
-      // The above can throw if this.obj points to a dead object.
-      // TODO: we should use Cu.isDeadWrapper() - see bug 885800.
+
+    // Inaccessible, proxy and dead objects should not be accessed.
+    let unwrapped = unwrap(this.obj);
+    if (!unwrapped || unwrapped.isProxy || this.obj.class == "DeadObject") {
       return { from: this.actorID,
                prototype: this.hooks.createValueGrip(null),
                ownProperties,
                ownSymbols,
                safeGetterValues: Object.create(null) };
     }
+
+    let names = this.obj.getOwnPropertyNames();
+    let symbols = this.obj.getOwnPropertySymbols();
+
     for (let name of names) {
       ownProperties[name] = this._propertyDescriptor(name);
     }
 
     for (let sym of symbols) {
       ownSymbols.push({
         name: sym.toString(),
         descriptor: this._propertyDescriptor(sym)
@@ -335,33 +334,39 @@ ObjectActor.prototype = {
    *         An object that maps property names to safe getter descriptors as
    *         defined by the remote debugging protocol.
    */
   _findSafeGetterValues: function (ownProperties, limit = 0) {
     let safeGetterValues = Object.create(null);
     let obj = this.obj;
     let level = 0, i = 0;
 
-    // Do not search safe getters in proxy objects.
-    if (isProxy(obj)) {
+    // Do not search safe getters in inaccessible nor proxy objects.
+    let unwrapped = unwrap(obj);
+    if (!unwrapped || unwrapped.isProxy) {
       return safeGetterValues;
     }
 
     // Most objects don't have any safe getters but inherit some from their
     // prototype. Avoid calling getOwnPropertyNames on objects that may have
     // many properties like Array, strings or js objects. That to avoid
     // freezing firefox when doing so.
     if (TYPED_ARRAY_CLASSES.includes(this.obj.class) ||
         ["Array", "Object", "String"].includes(this.obj.class)) {
       obj = obj.proto;
       level++;
     }
 
-    // Stop iterating when the prototype chain ends or a proxy is found.
-    while (obj && !isProxy(obj)) {
+    while (obj) {
+      // Stop iterating when an inaccessible or a proxy object is found.
+      unwrapped = unwrap(obj);
+      if (!unwrapped || unwrapped.isProxy) {
+        break;
+      }
+
       let getters = this._findSafeGetters(obj);
       for (let name of getters) {
         // Avoid overwriting properties from prototypes closer to this.obj. Also
         // avoid providing safeGetterValues from prototypes if property |name|
         // is already defined as an own property.
         if (name in safeGetterValues ||
             (obj != this.obj && ownProperties.indexOf(name) !== -1)) {
           continue;
@@ -2450,48 +2455,43 @@ function arrayBufferGrip(buffer, pool) {
 
   let actor = new ArrayBufferActor(buffer);
   pool.addActor(actor);
   pool.arrayBufferActors.set(buffer, actor);
   return actor.grip();
 }
 
 /**
- * Determines whether the referent of a debuggee object is a scripted proxy.
- * Non-opaque security wrappers are unwrapped first before the check.
+ * Removes all the non-opaque security wrappers of a debuggee object.
+ * Returns null if some wrapper can't be removed.
  *
  * @param obj Debugger.Object
- *        The debuggee object to be checked.
+ *        The debuggee object to be unwrapped.
  */
-function isProxy(obj) {
-  // Check if the object is a proxy without security wrappers.
-  if (obj.isProxy) {
-    return true;
+function unwrap(obj) {
+  // Check if `obj` has an opaque wrapper.
+  if (obj.class === "Opaque") {
+    return obj;
   }
 
-  // No need to remove opaque wrappers since they prevent proxy traps from running.
-  if (obj.class === "Opaque") {
-    return false;
-  }
-
-  // Attempt to unwrap. If the debugger can't unwrap, then proxy traps won't be
-  // allowed to run either, so the object can be safely assumed to not be a proxy.
+  // Attempt to unwrap. If this operation is not allowed, it may return null or throw.
   let unwrapped;
   try {
     unwrapped = obj.unwrap();
   } catch (err) {
-    return false;
+    unwrapped = null;
   }
 
+  // Check if further unwrapping is not possible.
   if (!unwrapped || unwrapped === obj) {
-    return false;
+    return unwrapped;
   }
 
-  // Recursively check whether the unwrapped object is a proxy.
-  return isProxy(unwrapped);
+  // Recursively remove additional security wrappers.
+  return unwrap(unwrapped);
 }
 
 exports.ObjectActor = ObjectActor;
 exports.PropertyIteratorActor = PropertyIteratorActor;
 exports.LongStringActor = LongStringActor;
 exports.createValueGrip = createValueGrip;
 exports.stringIsLong = stringIsLong;
 exports.longStringGrip = longStringGrip;
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -162,17 +162,17 @@ var DebuggerServer = {
   LONG_STRING_INITIAL_LENGTH: 1000,
   LONG_STRING_READ_LENGTH: 65 * 1024,
 
   /**
    * The windowtype of the chrome window to use for actors that use the global
    * window (i.e the global style editor). Set this to your main window type,
    * for example "navigator:browser".
    */
-  chromeWindowType: null,
+  chromeWindowType: "navigator:browser",
 
   /**
    * Allow debugging chrome of (parent or child) processes.
    */
   allowChromeProcess: false,
 
   /**
    * We run a special server in child process whose main actor is an instance
@@ -261,21 +261,23 @@ var DebuggerServer = {
    * @param tab boolean
    *        Registers all the tab actors like console, script, ... all useful
    *        for debugging a target context.
    * @param windowType string
    *        "windowtype" attribute of the main chrome windows. Used by some
    *        actors to retrieve them.
    */
   registerActors({ root = true, browser = true, tab = true,
-                   windowType = "navigator:browser" }) {
-    this.chromeWindowType = windowType;
+                   windowType = null }) {
+    if (windowType) {
+      this.chromeWindowType = windowType;
+    }
 
     if (browser) {
-      this.addBrowserActors(windowType);
+      this.addBrowserActors(this.chromeWindowType);
     }
 
     if (root) {
       this.registerModule("devtools/server/actors/webbrowser");
     }
 
     if (tab) {
       this.addTabActors();
@@ -415,18 +417,20 @@ var DebuggerServer = {
    *
    * /!\ Be careful when adding a new actor, especially global actors.
    * Any new global actor will be exposed and returned by the root actor.
    *
    * That's the reason why tab actors aren't loaded on demand via
    * restrictPrivileges=true, to prevent exposing them on b2g parent process's
    * root actor.
    */
-  addBrowserActors(windowType = "navigator:browser", restrictPrivileges = false) {
-    this.chromeWindowType = windowType;
+  addBrowserActors(windowType = null, restrictPrivileges = false) {
+    if (windowType) {
+      this.chromeWindowType = windowType;
+    }
     this.registerModule("devtools/server/actors/webbrowser");
 
     if (!restrictPrivileges) {
       this.addTabActors();
       this.registerModule("devtools/server/actors/preference", {
         prefix: "preference",
         constructor: "PreferenceActor",
         type: { global: true }
--- a/devtools/server/tests/unit/test_objectgrips-17.js
+++ b/devtools/server/tests/unit/test_objectgrips-17.js
@@ -1,20 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* eslint-disable no-shadow, max-nested-callbacks */
 
 "use strict";
 
 var gServer;
 var gDebuggee;
+var gDebuggeeHasXrays;
 var gClient;
 var gThreadClient;
 var gGlobal;
-var gHasXrays;
+var gGlobalIsInvisible;
+var gSubsumes;
+var gIsOpaque;
 
 function run_test() {
   run_test_with_server(DebuggerServer, function () {
     run_test_with_server(WorkerDebuggerServer, do_test_finished);
   });
   do_test_pending();
 }
 
@@ -26,73 +29,105 @@ async function run_test_with_server(serv
   await run_tests_in_principal(systemPrincipal, "test-grips-system-principal");
 
   // Run tests with a null principal debuggee.
   await run_tests_in_principal(null, "test-grips-null-principal");
 
   callback();
 }
 
-async function run_tests_in_principal(principal, title) {
-  // Prepare the debuggee.
-  gDebuggee = Cu.Sandbox(principal);
-  gDebuggee.__name = title;
-  gServer.addTestGlobal(gDebuggee);
-  gDebuggee.eval(function stopMe(arg1, arg2) {
-    debugger;
-  }.toString());
-  gClient = new DebuggerClient(gServer.connectPipe());
-  await gClient.connect();
-  const [,, threadClient] = await attachTestTabAndResume(gClient, title);
-  gThreadClient = threadClient;
+async function run_tests_in_principal(debuggeePrincipal, title) {
+  for (gDebuggeeHasXrays of [true, false]) {
+    // Prepare the debuggee.
+    let fullTitle = gDebuggeeHasXrays ? title + "-with-xrays" : title;
+    gDebuggee = Cu.Sandbox(debuggeePrincipal, {wantXrays: gDebuggeeHasXrays});
+    gDebuggee.__name = fullTitle;
+    gServer.addTestGlobal(gDebuggee);
+    gDebuggee.eval(function stopMe() {
+      debugger;
+    }.toString());
+    gClient = new DebuggerClient(gServer.connectPipe());
+    await gClient.connect();
+    const [,, threadClient] = await attachTestTabAndResume(gClient, fullTitle);
+    gThreadClient = threadClient;
 
-  // Test objects created in the debuggee.
-  await testPrincipal(undefined, false);
+    // Test objects created in the debuggee.
+    await testPrincipal(undefined);
 
-  // Test objects created in a new system principal with Xrays.
-  await testPrincipal(systemPrincipal, true);
+    // Test objects created in a system principal new global.
+    await testPrincipal(systemPrincipal);
 
-  // Test objects created in a new system principal without Xrays.
-  await testPrincipal(systemPrincipal, false);
+    // Test objects created in a cross-origin null principal new global.
+    await testPrincipal(null);
 
-  // Test objects created in a new null principal with Xrays.
-  await testPrincipal(null, true);
+    if (debuggeePrincipal === null) {
+      // Test objects created in a same-origin null principal new global.
+      await testPrincipal(Cu.getObjectPrincipal(gDebuggee));
+    }
 
-  // Test objects created in a new null principal without Xrays.
-  await testPrincipal(null, false);
-
-  // Finish.
-  await gClient.close();
+    // Finish.
+    await gClient.close();
+  }
 }
 
-function testPrincipal(principal, wantXrays = true) {
+async function testPrincipal(globalPrincipal) {
   // Create a global object with the specified security principal.
   // If none is specified, use the debuggee.
-  if (principal !== undefined) {
-    gGlobal = Cu.Sandbox(principal, {wantXrays});
-    gHasXrays = wantXrays;
-  } else {
+  if (globalPrincipal === undefined) {
     gGlobal = gDebuggee;
-    gHasXrays = false;
+    gSubsumes = true;
+    gIsOpaque = false;
+    gGlobalIsInvisible = false;
+    await test();
+    return;
   }
 
+  let debuggeePrincipal = Cu.getObjectPrincipal(gDebuggee);
+  let sameOrigin = debuggeePrincipal === globalPrincipal;
+  gSubsumes = sameOrigin || debuggeePrincipal === systemPrincipal;
+  for (let globalHasXrays of [true, false]) {
+    gIsOpaque = gSubsumes && globalPrincipal !== systemPrincipal
+                && (sameOrigin && gDebuggeeHasXrays || globalHasXrays);
+    for (gGlobalIsInvisible of [true, false]) {
+      gGlobal = Cu.Sandbox(globalPrincipal, {
+        wantXrays: globalHasXrays,
+        invisibleToDebugger: gGlobalIsInvisible
+      });
+      await test();
+    }
+  }
+}
+
+function test() {
   return new Promise(function (resolve) {
     gThreadClient.addOneTimeListener("paused", async function (event, packet) {
       // Get the grips.
-      let [proxyGrip, inheritsProxyGrip] = packet.frame.arguments;
+      let [proxyGrip, inheritsProxyGrip, inheritsProxy2Grip] = packet.frame.arguments;
 
       // Check the grip of the proxy object.
       check_proxy_grip(proxyGrip);
 
-      // Retrieve the properties of the object which inherits from a proxy,
-      // and check the grip of its prototype.
-      let objClient = gThreadClient.pauseGrip(inheritsProxyGrip);
-      let response = await objClient.getPrototypeAndProperties();
-      check_properties(response.ownProperties);
-      check_prototype(response.prototype);
+      // Check the prototype and properties of the proxy object.
+      let proxyClient = gThreadClient.pauseGrip(proxyGrip);
+      let proxyResponse = await proxyClient.getPrototypeAndProperties();
+      check_properties(proxyResponse.ownProperties, true, false);
+      check_prototype(proxyResponse.prototype, true, false);
+
+      // Check the prototype and properties of the object which inherits from the proxy.
+      let inheritsProxyClient = gThreadClient.pauseGrip(inheritsProxyGrip);
+      let inheritsProxyResponse = await inheritsProxyClient.getPrototypeAndProperties();
+      check_properties(inheritsProxyResponse.ownProperties, false, false);
+      check_prototype(inheritsProxyResponse.prototype, false, false);
+
+      // The prototype chain was not iterated if the object was inaccessible, so now check
+      // another object which inherits from the proxy, but was created in the debuggee.
+      let inheritsProxy2Client = gThreadClient.pauseGrip(inheritsProxy2Grip);
+      let inheritsProxy2Response = await inheritsProxy2Client.getPrototypeAndProperties();
+      check_properties(inheritsProxy2Response.ownProperties, false, true);
+      check_prototype(inheritsProxy2Response.prototype, false, true);
 
       // Check that none of the above ran proxy traps.
       strictEqual(gGlobal.trapDidRun, false, "No proxy trap did run.");
 
       // Resume the debugger and finish the current test.
       await gThreadClient.resume();
       resolve();
     });
@@ -100,86 +135,86 @@ function testPrincipal(principal, wantXr
     // Create objects in `gGlobal`, and debug them in `gDebuggee`. They may get various
     // kinds of security wrappers, or no wrapper at all.
     // To detect that no proxy trap runs, the proxy handler should define all possible
     // traps, but the list is long and may change. Therefore a second proxy is used as
     // the handler, so that a single `get` trap suffices.
     gGlobal.eval(`
       var trapDidRun = false;
       var proxy = new Proxy({}, new Proxy({}, {get: (_, trap) => {
-        return function(_, arg) {
-          trapDidRun = true;
-          throw new Error("proxy trap '" + trap + "' was called.");
-        }
+        trapDidRun = true;
+        throw new Error("proxy trap '" + trap + "' was called.");
       }}));
       var inheritsProxy = Object.create(proxy, {x:{value:1}});
     `);
     let data = Cu.createObjectIn(gDebuggee, {defineAs: "data"});
     data.proxy = gGlobal.proxy;
     data.inheritsProxy = gGlobal.inheritsProxy;
-    gDebuggee.eval("stopMe(data.proxy, data.inheritsProxy);");
+    gDebuggee.eval(`
+      var inheritsProxy2 = Object.create(data.proxy, {x:{value:1}});
+      stopMe(data.proxy, data.inheritsProxy, inheritsProxy2);
+    `);
   });
 }
 
-function isSystemPrincipal(obj) {
-  return Cu.getObjectPrincipal(obj) === systemPrincipal;
-}
-
 function check_proxy_grip(grip) {
   const {preview} = grip;
 
   if (gGlobal === gDebuggee) {
     // The proxy has no security wrappers.
     strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
     ok(grip.proxyTarget, "There is a [[ProxyTarget]] grip.");
     ok(grip.proxyHandler, "There is a [[ProxyHandler]] grip.");
     strictEqual(preview.ownPropertiesLength, 2, "The preview has 2 properties.");
     let target = preview.ownProperties["<target>"].value;
     strictEqual(target, grip.proxyTarget, "<target> contains the [[ProxyTarget]].");
     let handler = preview.ownProperties["<handler>"].value;
     strictEqual(handler, grip.proxyHandler, "<handler> contains the [[ProxyHandler]].");
-  } else if (!isSystemPrincipal(gDebuggee)) {
-    // The debuggee is not allowed to remove the security wrappers.
-    strictEqual(grip.class, "Object", "The grip has an Object class.");
-    ok(!("ownPropertyLength" in grip), "The grip doesn't know the number of properties.");
-  } else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
+  } else if (gIsOpaque) {
+    // The proxy has opaque security wrappers.
+    strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
+    strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
+  } else if (gSubsumes && !gGlobalIsInvisible) {
     // The proxy has non-opaque security wrappers.
     strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
     ok(!("proxyTarget" in grip), "There is no [[ProxyTarget]] grip.");
     ok(!("proxyHandler" in grip), "There is no [[ProxyHandler]] grip.");
     strictEqual(preview.ownPropertiesLength, 0, "The preview has no properties.");
     ok(!("<target>" in preview), "The preview has no <target> property.");
     ok(!("<handler>" in preview), "The preview has no <handler> property.");
   } else {
-    // The proxy has opaque security wrappers.
-    strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
-    strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
+    // The debuggee is not allowed to remove the security wrappers.
+    strictEqual(grip.class, "Inaccessible", "The grip has an Inaccessible class.");
+    ok(!("ownPropertyLength" in grip), "The grip doesn't know the number of properties.");
   }
 }
 
-function check_properties(props) {
+function check_properties(props, isProxy, createdInDebuggee) {
   let ownPropertiesLength = Reflect.ownKeys(props).length;
 
-  if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
-    // The debuggee is not allowed to access the object.
-    strictEqual(ownPropertiesLength, 0, "No own property could be retrieved.");
-  } else {
+  if (createdInDebuggee || !isProxy && gSubsumes && !gGlobalIsInvisible) {
     // The debuggee can access the properties.
     strictEqual(ownPropertiesLength, 1, "1 own property was retrieved.");
     strictEqual(props.x.value, 1, "The property has the right value.");
+  } else {
+    // The debuggee is not allowed to access the object.
+    strictEqual(ownPropertiesLength, 0, "No own property could be retrieved.");
   }
 }
 
-function check_prototype(proto) {
-  if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
-    // The debuggee is not allowed to access the object. It sees a null prototype.
-    strictEqual(proto.type, "null", "The prototype is null.");
-  } else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
-    // The object has no security wrappers or non-opaque ones.
+function check_prototype(proto, isProxy, createdInDebuggee) {
+  if (gIsOpaque && !gGlobalIsInvisible && !createdInDebuggee) {
+    // The object is or inherits from a proxy with opaque security wrappers.
+    // The debuggee sees `Object.prototype` when retrieving the prototype.
+    strictEqual(proto.class, "Object", "The prototype has a Object class.");
+  } else if (isProxy && gIsOpaque && gGlobalIsInvisible) {
+    // The object is a proxy with opaque security wrappers in an invisible global.
+    // The debuggee sees an inaccessible `Object.prototype` when retrieving the prototype.
+    strictEqual(proto.class, "Inaccessible", "The prototype has an Inaccessible class.");
+  } else if (createdInDebuggee || !isProxy && gSubsumes && !gGlobalIsInvisible) {
+    // The object inherits from a proxy and has no security wrappers or non-opaque ones.
     // The debuggee sees the proxy when retrieving the prototype.
     check_proxy_grip(proto);
   } else {
-    // The object has opaque security wrappers.
-    // The debuggee sees `Object.prototype` when retrieving the prototype.
-    strictEqual(proto.class, "Object", "The prototype has a Object class.");
+    // The debuggee is not allowed to access the object. It sees a null prototype.
+    strictEqual(proto.type, "null", "The prototype is null.");
   }
 }
-
--- a/devtools/shared/webconsole/test/test_consoleapi.html
+++ b/devtools/shared/webconsole/test/test_consoleapi.html
@@ -144,17 +144,17 @@ function doConsoleCalls(aState)
       level: "log",
       filename: /test_consoleapi/,
       functionName: "doConsoleCalls",
       timeStamp: /^\d+$/,
       arguments: [
         {
           type: "object",
           actor: /[a-z]/,
-          class: "Object",
+          class: "Inaccessible",
         },
       ],
     },
     {
       level: "error",
       filename: /test_consoleapi/,
       functionName: "fromAsmJS",
       timeStamp: /^\d+$/,
--- a/docshell/base/nsContextMenuInfo.cpp
+++ b/docshell/base/nsContextMenuInfo.cpp
@@ -7,32 +7,35 @@
 #include "nsContextMenuInfo.h"
 
 #include "nsIImageLoadingContent.h"
 #include "imgLoader.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLImageElement.h"
-#include "nsIDOMHTMLAreaElement.h"
-#include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMWindow.h"
 #include "nsICSSDeclaration.h"
 #include "nsIDOMCSSValue.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsIDocument.h"
 #include "nsIPrincipal.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIContentPolicy.h"
 #include "imgRequestProxy.h"
+#include "mozilla/dom/HTMLAnchorElement.h"
+#include "mozilla/dom/HTMLAreaElement.h"
+#include "mozilla/dom/HTMLLinkElement.h"
 
+using mozilla::dom::HTMLAnchorElement;
+using mozilla::dom::HTMLAreaElement;
+using mozilla::dom::HTMLLinkElement;
 using mozilla::dom::Element;
 using mozilla::ErrorResult;
 
 NS_IMPL_ISUPPORTS(nsContextMenuInfo, nsIContextMenuInfo)
 
 nsContextMenuInfo::nsContextMenuInfo()
 {
 }
@@ -58,63 +61,54 @@ nsContextMenuInfo::GetTargetNode(nsIDOMN
 }
 
 NS_IMETHODIMP
 nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
 {
   NS_ENSURE_STATE(mAssociatedLink);
   aHRef.Truncate(0);
 
-  nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
-  nsAutoString localName;
-  if (content) {
-    content->GetLocalName(localName);
-  }
-
-  nsCOMPtr<nsIDOMElement> linkContent;
-  ToLowerCase(localName);
-  if (localName.EqualsLiteral("a") ||
-      localName.EqualsLiteral("area") ||
-      localName.EqualsLiteral("link")) {
-    bool hasAttr;
-    content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
+  nsCOMPtr<nsIContent> content(do_QueryInterface(mAssociatedLink));
+  nsCOMPtr<nsIContent> linkContent;
+  if (content &&
+      content->IsAnyOfHTMLElements(nsGkAtoms::a,
+                                   nsGkAtoms::area,
+                                   nsGkAtoms::link)) {
+    bool hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
     if (hasAttr) {
       linkContent = content;
-      nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
+      RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
       if (anchor) {
         anchor->GetHref(aHRef);
       } else {
-        nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
+        RefPtr<HTMLAreaElement> area = HTMLAreaElement::FromContent(linkContent);
         if (area) {
           area->GetHref(aHRef);
         } else {
-          nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
+          RefPtr<HTMLLinkElement> link = HTMLLinkElement::FromContent(linkContent);
           if (link) {
             link->GetHref(aHRef);
           }
         }
       }
     }
   } else {
     nsCOMPtr<nsIDOMNode> curr;
     mAssociatedLink->GetParentNode(getter_AddRefs(curr));
     while (curr) {
       content = do_QueryInterface(curr);
       if (!content) {
         break;
       }
-      content->GetLocalName(localName);
-      ToLowerCase(localName);
-      if (localName.EqualsLiteral("a")) {
+      if (content->IsHTMLElement(nsGkAtoms::a)) {
         bool hasAttr;
-        content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
+        hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
         if (hasAttr) {
           linkContent = content;
-          nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(
-            do_QueryInterface(linkContent));
+          RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
           if (anchor) {
             anchor->GetHref(aHRef);
           }
         } else {
           linkContent = nullptr; // Links can't be nested.
         }
         break;
       }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -130,17 +130,16 @@
 #include "nsITransportSecurityInfo.h"
 #include "nsINode.h"
 #include "nsINSSErrorsService.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsStreamUtils.h"
 #include "nsIController.h"
 #include "nsPICommandUpdater.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIWebBrowserChrome3.h"
 #include "nsITabChild.h"
 #include "nsISiteSecurityService.h"
 #include "nsStructuredCloneContainer.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsISupportsPrimitives.h"
 #ifdef MOZ_PLACES
 #include "nsIFaviconService.h"
@@ -14430,17 +14429,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
 
   // 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);
 
   // If this is an anchor element, grab its type property to use as a hint
   nsAutoString typeHint;
-  nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
+  RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(aContent);
   if (anchor) {
     anchor->GetType(typeHint);
     NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
     nsAutoCString type, dummy;
     NS_ParseRequestContentType(utf8Hint, type, dummy);
     CopyUTF8toUTF16(type, typeHint);
   }
 
--- a/dom/abort/AbortController.cpp
+++ b/dom/abort/AbortController.cpp
@@ -17,54 +17,16 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Ab
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AbortController)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AbortController)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortController)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-/* static */ bool
-AbortController::IsEnabled(JSContext* aCx, JSObject* aGlobal)
-{
-  if (NS_IsMainThread()) {
-    return Preferences::GetBool("dom.abortController.enabled", false);
-  }
-
-  using namespace workers;
-
-  // Otherwise, check the pref via the WorkerPrivate
-  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
-  if (!workerPrivate) {
-    return false;
-  }
-
-  return workerPrivate->AbortControllerEnabled();
-}
-
-/* static */ bool
-AbortController::IsEnabledInFetch(JSContext* aCx, JSObject* aGlobal)
-{
-  if (NS_IsMainThread()) {
-    return IsEnabled(aCx, aGlobal) &&
-           Preferences::GetBool("dom.abortController.fetch.enabled", false);
-  }
-
-  using namespace workers;
-
-  // Otherwise, check the pref via the WorkerPrivate
-  WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
-  if (!workerPrivate) {
-    return false;
-  }
-
-  return workerPrivate->AbortControllerEnabled() &&
-         workerPrivate->AbortControllerEnabledInFetch();
-}
-
 /* static */ already_AddRefed<AbortController>
 AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
   if (!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
--- a/dom/abort/AbortController.h
+++ b/dom/abort/AbortController.h
@@ -21,22 +21,16 @@ class AbortSignal;
 
 class AbortController final : public nsISupports
                             , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortController)
 
-  static bool
-  IsEnabled(JSContext* aCx, JSObject* aGlobal);
-
-  static bool
-  IsEnabledInFetch(JSContext* aCx, JSObject* aGlobal);
-
   static already_AddRefed<AbortController>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
 
   explicit AbortController(nsIGlobalObject* aGlobal);
 
   JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
deleted file mode 100644
--- a/dom/abort/tests/file_abort_controller.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-function ok(a, msg) {
-  parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
-}
-
-function is(a, b, msg) {
-  ok(a === b, msg);
-}
-
-function testWebIDL() {
-  ok("AbortController" in self, "We have a AbortController prototype");
-  ok("AbortSignal" in self, "We have a AbortSignal prototype");
-
-  var ac = new AbortController();
-  ok(!!ac, "AbortController can be created");
-  ok(ac instanceof AbortController, "AbortController is a AbortController");
-
-  ok(!!ac.signal, "AbortController has a signal");
-  ok(ac.signal instanceof AbortSignal, "abortSignal is a AbortSignal");
-  is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
-  next();
-}
-
-function testUpdateData() {
-  var ac = new AbortController();
-
-  is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
-
-  ac.abort();
-  is(ac.signal.aborted, true, "Signal is aborted");
-
-  next();
-}
-
-function testAbortEvent() {
-  var ac = new AbortController();
-  ac.signal.onabort = function(e) {
-    is(e.type, "abort", "Abort received");
-    next();
-  }
-  ac.abort();
-}
-
-var steps = [
-  // Simple stuff
-  testWebIDL,
-  testUpdateData,
-
-  // Event propagation
-  testAbortEvent,
-];
-
-function next() {
-  if (!steps.length) {
-    parent.postMessage({ type: "finish" }, "*");
-    return;
-  }
-
-  var step = steps.shift();
-  step();
-}
-
-next();
-
-</script>
deleted file mode 100644
--- a/dom/abort/tests/file_abort_controller_fetch.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<script>
-function ok(a, msg) {
-  parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
-}
-
-function is(a, b, msg) {
-  ok(a === b, msg);
-}
-
-function testAbortedFetch() {
-  var ac = new AbortController();
-  ac.abort();
-
-  fetch("slow.sjs", { signal: ac.signal }).then(() => {
-    ok(false, "Fetch should not return a resolved promise");
-  }, e => {
-    is(e.name, "AbortError", "We have an abort error");
-  }).then(next);
-}
-
-function testFetchAndAbort() {
-  var ac = new AbortController();
-
-  var p = fetch("slow.sjs", { signal: ac.signal });
-  ac.abort();
-
-  p.then(() => {
-    ok(false, "Fetch should not return a resolved promise");
-  }, e => {
-    is(e.name, "AbortError", "We have an abort error");
-  }).then(next);
-}
-
-function testWorkerAbortedFetch() {
-  var w = new Worker("worker_abort_controller_fetch.js");
-  w.onmessage = function(e) {
-    ok(e.data, "Abort + Fetch works in workers");
-    next();
-  }
-  w.postMessage("testWorkerAbortedFetch");
-}
-
-function testWorkerFetchAndAbort() {
-  var w = new Worker("worker_abort_controller_fetch.js");
-  w.onmessage = function(e) {
-    ok(e.data, "Abort + Fetch works in workers");
-    next();
-  }
-  w.postMessage("testWorkerFetchAndAbort");
-}
-
-var steps = [
-  // fetch + signaling
-  testAbortedFetch,
-  testFetchAndAbort,
-  testWorkerAbortedFetch,
-  testWorkerFetchAndAbort,
-];
-
-function next() {
-  if (!steps.length) {
-    parent.postMessage({ type: "finish" }, "*");
-    return;
-  }
-
-  var step = steps.shift();
-  step();
-}
-
-next();
-
-</script>
--- a/dom/abort/tests/mochitest.ini
+++ b/dom/abort/tests/mochitest.ini
@@ -1,9 +1,7 @@
 [DEFAULT]
 support-files =
-  file_abort_controller.html
-  file_abort_controller_fetch.html
   worker_abort_controller_fetch.js
   slow.sjs
 
 [test_abort_controller.html]
 [test_abort_controller_fetch.html]
--- a/dom/abort/tests/test_abort_controller.html
+++ b/dom/abort/tests/test_abort_controller.html
@@ -7,34 +7,68 @@
 <head>
   <title>Test AbortController</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script class="testbody" type="text/javascript">
 
-SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ]]}, () => {
-  let ifr = document.createElement("iframe");
-  ifr.src = "file_abort_controller.html";
-  document.body.appendChild(ifr);
+function testWebIDL() {
+  ok("AbortController" in self, "We have a AbortController prototype");
+  ok("AbortSignal" in self, "We have a AbortSignal prototype");
+
+  var ac = new AbortController();
+  ok(!!ac, "AbortController can be created");
+  ok(ac instanceof AbortController, "AbortController is a AbortController");
+
+  ok(!!ac.signal, "AbortController has a signal");
+  ok(ac.signal instanceof AbortSignal, "abortSignal is a AbortSignal");
+  is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
+  next();
+}
+
+function testUpdateData() {
+  var ac = new AbortController();
+
+  is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
+
+  ac.abort();
+  is(ac.signal.aborted, true, "Signal is aborted");
+
+  next();
+}
 
-  window.onmessage = function(e) {
-    if (e.data.type == "finish") {
-      SimpleTest.finish();
-      return;
-    }
+function testAbortEvent() {
+  var ac = new AbortController();
+  ac.signal.onabort = function(e) {
+    is(e.type, "abort", "Abort received");
+    next();
+  }
+  ac.abort();
+}
+
+var steps = [
+  // Simple stuff
+  testWebIDL,
+  testUpdateData,
 
-    if (e.data.type == "check") {
-      ok(e.data.status, e.data.message);
-      return;
-    }
+  // Event propagation
+  testAbortEvent,
+];
 
-    ok(false, "Something when wrong.");
+function next() {
+  if (!steps.length) {
+    SimpleTest.finish();
+    return;
   }
-});
+
+  var step = steps.shift();
+  step();
+}
 
 SimpleTest.waitForExplicitFinish();
+next();
 
 </script>
 </body>
 </html>
 
--- a/dom/abort/tests/test_abort_controller_fetch.html
+++ b/dom/abort/tests/test_abort_controller_fetch.html
@@ -7,35 +7,75 @@
 <head>
   <title>Test AbortController in Fetch API</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script class="testbody" type="text/javascript">
 
-SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ],
-                                   ["dom.abortController.fetch.enabled", true]]}, () => {
-  let ifr = document.createElement("iframe");
-  ifr.src = "file_abort_controller_fetch.html";
-  document.body.appendChild(ifr);
+function testAbortedFetch() {
+  var ac = new AbortController();
+  ac.abort();
+
+  fetch("slow.sjs", { signal: ac.signal }).then(() => {
+    ok(false, "Fetch should not return a resolved promise");
+  }, e => {
+    is(e.name, "AbortError", "We have an abort error");
+  }).then(next);
+}
+
+function testFetchAndAbort() {
+  var ac = new AbortController();
+
+  var p = fetch("slow.sjs", { signal: ac.signal });
+  ac.abort();
+
+  p.then(() => {
+    ok(false, "Fetch should not return a resolved promise");
+  }, e => {
+    is(e.name, "AbortError", "We have an abort error");
+  }).then(next);
+}
 
-  window.onmessage = function(e) {
-    if (e.data.type == "finish") {
-      SimpleTest.finish();
-      return;
-    }
+function testWorkerAbortedFetch() {
+  var w = new Worker("worker_abort_controller_fetch.js");
+  w.onmessage = function(e) {
+    ok(e.data, "Abort + Fetch works in workers");
+    next();
+  }
+  w.postMessage("testWorkerAbortedFetch");
+}
+
+function testWorkerFetchAndAbort() {
+  var w = new Worker("worker_abort_controller_fetch.js");
+  w.onmessage = function(e) {
+    ok(e.data, "Abort + Fetch works in workers");
+    next();
+  }
+  w.postMessage("testWorkerFetchAndAbort");
+}
 
-    if (e.data.type == "check") {
-      ok(e.data.status, e.data.message);
-      return;
-    }
+var steps = [
+  // fetch + signaling
+  testAbortedFetch,
+  testFetchAndAbort,
+  testWorkerAbortedFetch,
+  testWorkerFetchAndAbort,
+];
 
-    ok(false, "Something when wrong.");
+function next() {
+  if (!steps.length) {
+    SimpleTest.finish();
+    return;
   }
-});
+
+  var step = steps.shift();
+  step();
+}
 
 SimpleTest.waitForExplicitFinish();
+next();
 
 </script>
 </body>
 </html>
 
--- a/dom/base/DirectionalityUtils.cpp
+++ b/dom/base/DirectionalityUtils.cpp
@@ -239,36 +239,26 @@ DoesNotParticipateInAutoDirection(const 
   mozilla::dom::NodeInfo* nodeInfo = aElement->NodeInfo();
   return (!aElement->IsHTMLElement() ||
           nodeInfo->Equals(nsGkAtoms::script) ||
           nodeInfo->Equals(nsGkAtoms::style) ||
           nodeInfo->Equals(nsGkAtoms::textarea) ||
           aElement->IsInAnonymousSubtree());
 }
 
-static inline bool
-IsBdiWithoutDirAuto(const Element* aElement)
-{
-  // We are testing for bdi elements without explicit dir="auto", so we can't
-  // use the HasDirAuto() flag, since that will return true for bdi element with
-  // no dir attribute or an invalid dir attribute
-  return (aElement->IsHTMLElement(nsGkAtoms::bdi) &&
-          (!aElement->HasValidDir() || aElement->HasFixedDir()));
-}
-
 /**
  * Returns true if aElement is one of the element whose text content should not
  * affect the direction of ancestors with dir=auto (though it may affect its own
  * direction, e.g. <bdi>)
  */
 static bool
 DoesNotAffectDirectionOfAncestors(const Element* aElement)
 {
   return (DoesNotParticipateInAutoDirection(aElement) ||
-          IsBdiWithoutDirAuto(aElement) ||
+          aElement->IsHTMLElement(nsGkAtoms::bdi) ||
           aElement->HasFixedDir());
 }
 
 /**
  * Returns the directionality of a Unicode character
  */
 static Directionality
 GetDirectionFromChar(uint32_t ch)
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1400701.html
@@ -0,0 +1,15 @@
+<html>
+<script>
+window.onload=function(){
+  document.getElementById('b').textContent='Or';
+  document.getElementById('a').insertBefore(document.getElementById('c'), undefined);
+  document.getElementById('b').dir='ltr';
+  let o=document.getElementById('b');
+  o.parentNode.replaceChild(document.createElement('code'), o);
+}
+</script>
+<body dir='auto' id='a'>
+<bdi id='b' dir='auto'>
+</bdi>
+<q id='c'>
+</html>
\ No newline at end of file
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -219,8 +219,9 @@ pref(dom.IntersectionObserver.enabled,tr
 load 1377826.html
 skip-if(stylo&&isDebugBuild&&winWidget) load structured_clone_container_throws.html # Bug 1383845
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
 load 1383478.html
 load 1383780.html
 pref(clipboard.autocopy,true) load 1385272-1.html
 load 1393806.html
+load 1400701.html
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -20,17 +20,16 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMRange.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLAreaElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsITransferable.h"
 #include "nsComponentManagerUtils.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNetUtil.h"
 #include "nsIFile.h"
 #include "nsFrameLoader.h"
@@ -52,16 +51,17 @@
 #include "imgIContainer.h"
 #include "imgIRequest.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "nsIMIMEInfo.h"
 #include "nsRange.h"
 #include "TabParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLAreaElement.h"
+#include "mozilla/dom/HTMLAnchorElement.h"
 #include "nsVariant.h"
 
 using namespace mozilla::dom;
 
 class MOZ_STACK_CLASS DragDataProducer
 {
 public:
   DragDataProducer(nsPIDOMWindowOuter* aWindow,
@@ -469,19 +469,17 @@ DragDataProducer::Produce(DataTransfer* 
       if (form && !mIsAltKeyPressed && form->ControlType() != NS_FORM_OBJECT) {
         *aCanDrag = false;
         return NS_OK;
       }
 
       draggedNode = mTarget;
     }
 
-    nsCOMPtr<nsIDOMHTMLAreaElement>   area;   // client-side image map
     nsCOMPtr<nsIImageLoadingContent>  image;
-    nsCOMPtr<nsIDOMHTMLAnchorElement> link;
 
     nsCOMPtr<nsIContent> selectedImageOrLinkNode;
     GetDraggableSelectionData(selection, mSelectionTargetNode,
                               getter_AddRefs(selectedImageOrLinkNode),
                               &haveSelectedContent);
 
     // either plain text or anchor text is selected
     if (haveSelectedContent) {
@@ -496,29 +494,26 @@ DragDataProducer::Produce(DataTransfer* 
       //
       // if the alt key is down, don't start a drag if we're in an
       // anchor because we want to do selection.
       parentLink = FindParentLinkNode(draggedNode);
       if (parentLink && mIsAltKeyPressed) {
         *aCanDrag = false;
         return NS_OK;
       }
-
-      area  = do_QueryInterface(draggedNode);
       image = do_QueryInterface(draggedNode);
-      link  = do_QueryInterface(draggedNode);
     }
 
     {
       // set for linked images, and links
       nsCOMPtr<nsIContent> linkNode;
 
-      if (area) {
+      RefPtr<HTMLAreaElement> areaElem = HTMLAreaElement::FromContentOrNull(draggedNode);
+      if (areaElem) {
         // use the alt text (or, if missing, the href) as the title
-        HTMLAreaElement* areaElem = static_cast<HTMLAreaElement*>(area.get());
         areaElem->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
         if (mTitleString.IsEmpty()) {
           // this can be a relative link
           areaElem->GetAttribute(NS_LITERAL_STRING("href"), mTitleString);
         }
 
         // we'll generate HTML like <a href="absurl">alt text</a>
         mIsAnchor = true;
@@ -633,19 +628,19 @@ DragDataProducer::Produce(DataTransfer* 
           // If we are dragging around an image in an anchor, then we
           // are dragging the entire anchor
           linkNode = parentLink;
           nodeToSerialize = linkNode;
         } else {
           nodeToSerialize = do_QueryInterface(draggedNode);
         }
         dragNode = nodeToSerialize;
-      } else if (link) {
+      } else if (draggedNode && draggedNode->IsHTMLElement(nsGkAtoms::a)) {
         // set linkNode. The code below will handle this
-        linkNode = do_QueryInterface(link);    // XXX test this
+        linkNode = do_QueryInterface(draggedNode);    // XXX test this
         GetNodeString(draggedNode, mTitleString);
       } else if (parentLink) {
         // parentLink will always be null if there's selected content
         linkNode = parentLink;
         nodeToSerialize = linkNode;
       } else if (!haveSelectedContent) {
         // nothing draggable
         return NS_OK;
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -661,17 +661,17 @@ BrowserElementChild.prototype = {
       state: e.state,
     };
     sendAsyncMsg('scrollviewchange', detail);
   },
 
   _ClickHandler: function(e) {
 
     let isHTMLLink = node =>
-      ((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
+      ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
        (node instanceof Ci.nsIDOMHTMLAreaElement && node.href) ||
         node instanceof Ci.nsIDOMHTMLLinkElement);
 
     // Open in a new tab if middle click or ctrl/cmd-click,
     // and e.target is a link or inside a link.
     if ((Services.appinfo.OS == 'Darwin' && e.metaKey) ||
         (Services.appinfo.OS != 'Darwin' && e.ctrlKey) ||
          e.button == 1) {
@@ -850,17 +850,17 @@ BrowserElementChild.prototype = {
     } else {
       this._ctxHandlers = {};
     }
   },
 
   _getSystemCtxMenuData: function(elem) {
     let documentURI =
       docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
-    if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
+    if ((ChromeUtils.getClassName(elem) === "HTMLAnchorElement" && elem.href) ||
         (elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
       return {uri: elem.href,
               documentURI: documentURI,
               text: elem.textContent.substring(0, kLongestReturnedString)};
     }
     if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) {
       return {uri: elem.currentURI.spec, documentURI: documentURI};
     }
--- a/dom/file/ipc/IPCBlobInputStream.cpp
+++ b/dom/file/ipc/IPCBlobInputStream.cpp
@@ -3,30 +3,29 @@
 /* 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 "IPCBlobInputStream.h"
 #include "IPCBlobInputStreamChild.h"
 #include "IPCBlobInputStreamStorage.h"
 #include "mozilla/ipc/InputStreamParams.h"
+#include "IPCBlobInputStreamThread.h"
 #include "nsIAsyncInputStream.h"
-#include "nsIStreamTransportService.h"
-#include "nsITransport.h"
-#include "nsNetCID.h"
+#include "nsIAsyncOutputStream.h"
+#include "nsIPipe.h"
+#include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "SlicedInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
-static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
-
 class InputStreamCallbackRunnable final : public CancelableRunnable
 {
 public:
   // Note that the execution can be synchronous in case the event target is
   // null.
   static void
   Execute(nsIInputStreamCallback* aCallback,
           nsIEventTarget* aEventTarget,
@@ -242,17 +241,17 @@ NS_IMETHODIMP
 IPCBlobInputStream::Close()
 {
   if (mActor) {
     mActor->ForgetStream(this);
     mActor = nullptr;
   }
 
   if (mAsyncRemoteStream) {
-    mAsyncRemoteStream->Close();
+    mAsyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
     mAsyncRemoteStream = nullptr;
   }
 
   if (mRemoteStream) {
     mRemoteStream->Close();
     mRemoteStream = nullptr;
   }
 
@@ -498,17 +497,17 @@ IPCBlobInputStream::OnInputStreamReady(n
     return NS_OK;
   }
 
   nsCOMPtr<nsIInputStreamCallback> callback;
   callback.swap(mInputStreamCallback);
 
   nsCOMPtr<nsIEventTarget> callbackEventTarget;
   callbackEventTarget.swap(mInputStreamCallbackEventTarget);
- 
+
   // This must be the last operation because the execution of the callback can
   // be synchronous.
   InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
   return NS_OK;
 }
 
 // nsIIPCSerializableInputStream
 
@@ -638,40 +637,39 @@ IPCBlobInputStream::EnsureAsyncRemoteStr
   bool nonBlocking = false;
   nsresult rv = mRemoteStream->IsNonBlocking(&nonBlocking);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
   if (!asyncStream || !nonBlocking) {
-    nsCOMPtr<nsIStreamTransportService> sts =
-      do_GetService(kStreamTransportServiceCID, &rv);
+    // Let's make the stream async using the DOMFile thread.
+    nsCOMPtr<nsIAsyncInputStream> pipeIn;
+    nsCOMPtr<nsIAsyncOutputStream> pipeOut;
+    rv = NS_NewPipe2(getter_AddRefs(pipeIn),
+                     getter_AddRefs(pipeOut),
+                     true, true);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    nsCOMPtr<nsITransport> transport;
-    rv = sts->CreateInputTransport(mRemoteStream,
-                                   /* aCloseWhenDone */ true,
-                                   getter_AddRefs(transport));
+    RefPtr<IPCBlobInputStreamThread> thread =
+      IPCBlobInputStreamThread::GetOrCreate();
+    if (NS_WARN_IF(!thread)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    rv = NS_AsyncCopy(mRemoteStream, pipeOut, thread,
+                      NS_ASYNCCOPY_VIA_WRITESEGMENTS);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    nsCOMPtr<nsIInputStream> wrapper;
-    rv = transport->OpenInputStream(/* aFlags */ 0,
-                                    /* aSegmentSize */ 0,
-                                    /* aSegmentCount */ 0,
-                                    getter_AddRefs(wrapper));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    asyncStream = do_QueryInterface(wrapper);
+    asyncStream = pipeIn;
   }
 
   MOZ_ASSERT(asyncStream);
   mAsyncRemoteStream = asyncStream;
   mRemoteStream = nullptr;
 
   return NS_OK;
 }
--- a/dom/file/ipc/IPCBlobInputStreamChild.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp
@@ -182,16 +182,18 @@ IPCBlobInputStreamChild::ActorDestroy(IP
     mState = migrating ? eInactiveMigrating : eInactive;
   }
 
   if (migrating) {
     // We were waiting for this! Now we can migrate the actor in the correct
     // thread.
     RefPtr<IPCBlobInputStreamThread> thread =
       IPCBlobInputStreamThread::GetOrCreate();
+    MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
+
     ResetManager();
     thread->MigrateActor(this);
     return;
   }
 
   // Let's cleanup the workerHolder and the pending operation queue.
   Shutdown();
 }
--- a/dom/file/ipc/IPCBlobInputStreamThread.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamThread.cpp
@@ -31,17 +31,17 @@ class ThreadInitializeRunnable final : p
 public:
   ThreadInitializeRunnable() : Runnable("dom::ThreadInitializeRunnable") {}
 
   NS_IMETHOD
   Run() override
   {
      mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
      MOZ_ASSERT(gIPCBlobThread);
-     gIPCBlobThread->Initialize();
+     gIPCBlobThread->InitializeOnMainThread();
      return NS_OK;
   }
 };
 
 class MigrateActorRunnable final : public Runnable
                                  , public nsIIPCBackgroundChildCreateCallback
 {
 public:
@@ -88,17 +88,17 @@ private:
   RefPtr<IPCBlobInputStreamChild> mActor;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED(MigrateActorRunnable, Runnable,
                   nsIIPCBackgroundChildCreateCallback)
 
 } // anonymous
 
-NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver)
+NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver, nsIEventTarget)
 
 /* static */ bool
 IPCBlobInputStreamThread::IsOnFileEventTarget(nsIEventTarget* aEventTarget)
 {
   MOZ_ASSERT(aEventTarget);
 
   mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
   return gIPCBlobThread && aEventTarget == gIPCBlobThread->mThread;
@@ -110,57 +110,68 @@ IPCBlobInputStreamThread::GetOrCreate()
   mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
 
   if (gShutdownHasStarted) {
     return nullptr;
   }
 
   if (!gIPCBlobThread) {
     gIPCBlobThread = new IPCBlobInputStreamThread();
-    gIPCBlobThread->Initialize();
+    if (!gIPCBlobThread->Initialize()) {
+      return nullptr;
+    }
   }
 
   return gIPCBlobThread;
 }
 
-void
+bool
 IPCBlobInputStreamThread::Initialize()
 {
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  mThread = thread;
+
+  if (!mPendingActors.IsEmpty()) {
+    for (uint32_t i = 0; i < mPendingActors.Length(); ++i) {
+      MigrateActorInternal(mPendingActors[i]);
+    }
+
+    mPendingActors.Clear();
+  }
+
   if (!NS_IsMainThread()) {
     RefPtr<Runnable> runnable = new ThreadInitializeRunnable();
     SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
-    return;
+    return true;
   }
 
+  InitializeOnMainThread();
+  return true;
+}
+
+void
+IPCBlobInputStreamThread::InitializeOnMainThread()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (NS_WARN_IF(!obs)) {
     return;
   }
 
   nsresult rv =
     obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
-
-  nsCOMPtr<nsIThread> thread;
-  rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return;
-  }
-
-  mThread = thread;
-
-  if (!mPendingActors.IsEmpty()) {
-    for (uint32_t i = 0; i < mPendingActors.Length(); ++i) {
-      MigrateActorInternal(mPendingActors[i]);
-    }
-
-    mPendingActors.Clear();
-  }
 }
 
 NS_IMETHODIMP
 IPCBlobInputStreamThread::Observe(nsISupports* aSubject,
                                   const char* aTopic,
                                   const char16_t* aData)
 {
   MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
@@ -200,10 +211,53 @@ IPCBlobInputStreamThread::MigrateActor(I
 
 void
 IPCBlobInputStreamThread::MigrateActorInternal(IPCBlobInputStreamChild* aActor)
 {
   RefPtr<Runnable> runnable = new MigrateActorRunnable(aActor);
   mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
 }
 
+// nsIEventTarget
+
+NS_IMETHODIMP_(bool)
+IPCBlobInputStreamThread::IsOnCurrentThreadInfallible()
+{
+  return mThread->IsOnCurrentThread();
+}
+
+NS_IMETHODIMP
+IPCBlobInputStreamThread::IsOnCurrentThread(bool* aRetval)
+{
+  return mThread->IsOnCurrentThread(aRetval);
+}
+
+NS_IMETHODIMP
+IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
+                                   uint32_t aFlags)
+{
+  nsCOMPtr<nsIRunnable> runnable(aRunnable);
+
+  mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
+
+  if (gShutdownHasStarted) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  return mThread->Dispatch(runnable.forget(), aFlags);
+}
+
+NS_IMETHODIMP
+IPCBlobInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
+                                             uint32_t aFlags)
+{
+  nsCOMPtr<nsIRunnable> runnable(aRunnable);
+  return Dispatch(runnable.forget(), aFlags);
+}
+
+NS_IMETHODIMP
+IPCBlobInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 } // dom namespace
 } // mozilla namespace
--- a/dom/file/ipc/IPCBlobInputStreamThread.h
+++ b/dom/file/ipc/IPCBlobInputStreamThread.h
@@ -3,41 +3,47 @@
 /* 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/. */
 
 #ifndef mozilla_dom_IPCBlobInputStreamThread_h
 #define mozilla_dom_IPCBlobInputStreamThread_h
 
 #include "nsIObserverService.h"
+#include "nsIEventTarget.h"
 
 class nsIThread;
 
 namespace mozilla {
 namespace dom {
 
 class IPCBlobInputStreamChild;
 
 class IPCBlobInputStreamThread final : public nsIObserver
+                                     , public nsIEventTarget
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSIEVENTTARGET
 
   static bool
   IsOnFileEventTarget(nsIEventTarget* aEventTarget);
 
   static IPCBlobInputStreamThread*
   GetOrCreate();
 
   void
   MigrateActor(IPCBlobInputStreamChild* aActor);
 
+  bool
+  Initialize();
+
   void
-  Initialize();
+  InitializeOnMainThread();
 
 private:
   ~IPCBlobInputStreamThread() = default;
 
   void
   MigrateActorInternal(IPCBlobInputStreamChild* aActor);
 
   nsCOMPtr<nsIThread> mThread;
--- a/dom/html/HTMLAnchorElement.cpp
+++ b/dom/html/HTMLAnchorElement.cpp
@@ -53,20 +53,23 @@ HTMLAnchorElement::~HTMLAnchorElement()
 
 bool
 HTMLAnchorElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return HasAttr(kNameSpaceID_None, nsGkAtoms::href) ||
          nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
 }
 
-NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement,
-                                             nsGenericHTMLElement,
-                                             nsIDOMHTMLAnchorElement,
-                                             Link)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement)
+  NS_INTERFACE_TABLE_INHERITED(HTMLAnchorElement,
+                               Link)
+NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
+
+NS_IMPL_ADDREF_INHERITED(HTMLAnchorElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLAnchorElement, Element)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAnchorElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLAnchorElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRelList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -78,27 +81,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_ELEMENT_CLONE(HTMLAnchorElement)
 
 JSObject*
 HTMLAnchorElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLAnchorElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Charset, charset)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Coords, coords)
-NS_IMPL_URI_ATTR(HTMLAnchorElement, Href, href)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Hreflang, hreflang)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Name, name)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rel, rel)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rev, rev)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Shape, shape)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Type, type)
-NS_IMPL_STRING_ATTR(HTMLAnchorElement, Download, download)
-
 int32_t
 HTMLAnchorElement::TabIndexDefault()
 {
   return 0;
 }
 
 bool
 HTMLAnchorElement::Draggable() const
@@ -263,98 +255,53 @@ void
 HTMLAnchorElement::GetLinkTarget(nsAString& aTarget)
 {
   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
   if (aTarget.IsEmpty()) {
     GetBaseTarget(aTarget);
   }
 }
 
-NS_IMETHODIMP
+void
 HTMLAnchorElement::GetTarget(nsAString& aValue)
 {
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
     GetBaseTarget(aValue);
   }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLAnchorElement::SetTarget(const nsAString& aValue)
-{
-  return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, true);
 }
 
 nsDOMTokenList*
 HTMLAnchorElement::RelList()
 {
   if (!mRelList) {
     mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
   }
   return mRelList;
 }
 
-#define IMPL_URI_PART(_part)                                 \
-  NS_IMETHODIMP                                              \
-  HTMLAnchorElement::Get##_part(nsAString& a##_part)         \
-  {                                                          \
-    Link::Get##_part(a##_part);                              \
-    return NS_OK;                                            \
-  }                                                          \
-  NS_IMETHODIMP                                              \
-  HTMLAnchorElement::Set##_part(const nsAString& a##_part)   \
-  {                                                          \
-    Link::Set##_part(a##_part);                              \
-    return NS_OK;                                            \
+void
+HTMLAnchorElement::GetText(nsAString& aText, mozilla::ErrorResult& aRv)
+{
+  if (NS_WARN_IF(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible))) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
   }
-
-IMPL_URI_PART(Protocol)
-IMPL_URI_PART(Host)
-IMPL_URI_PART(Hostname)
-IMPL_URI_PART(Pathname)
-IMPL_URI_PART(Search)
-IMPL_URI_PART(Port)
-IMPL_URI_PART(Hash)
-
-#undef IMPL_URI_PART
-
-NS_IMETHODIMP
-HTMLAnchorElement::GetText(nsAString& aText)
-{
-  if(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-HTMLAnchorElement::SetText(const nsAString& aText)
+void
+HTMLAnchorElement::SetText(const nsAString& aText, ErrorResult& aRv)
 {
-  return nsContentUtils::SetNodeTextContent(this, aText, false);
+  aRv = nsContentUtils::SetNodeTextContent(this, aText, false);
 }
 
-NS_IMETHODIMP
+void
 HTMLAnchorElement::ToString(nsAString& aSource)
 {
   return GetHref(aSource);
 }
 
-NS_IMETHODIMP
-HTMLAnchorElement::GetPing(nsAString& aValue)
-{
-  GetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLAnchorElement::SetPing(const nsAString& aValue)
-{
-  return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true);
-}
-
 already_AddRefed<nsIURI>
 HTMLAnchorElement::GetHrefURI() const
 {
   nsCOMPtr<nsIURI> uri = Link::GetCachedURI();
   if (uri) {
     return uri.forget();
   }
 
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -5,26 +5,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLAnchorElement_h
 #define mozilla_dom_HTMLAnchorElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Link.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsDOMTokenList.h"
 
 namespace mozilla {
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 namespace dom {
 
 class HTMLAnchorElement final : public nsGenericHTMLElement,
-                                public nsIDOMHTMLAnchorElement,
                                 public Link
 {
 public:
   using Element::GetText;
   using Element::SetText;
 
   explicit HTMLAnchorElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
@@ -34,25 +32,25 @@ public:
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // CC
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement,
                                            nsGenericHTMLElement)
 
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAnchorElement, a);
+
   virtual int32_t TabIndexDefault() override;
   virtual bool Draggable() const override;
 
   // Element
   virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
 
-  // nsIDOMHTMLAnchorElement
-  NS_DECL_NSIDOMHTMLANCHORELEMENT
-
+  // DOM memory reporter participant
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
@@ -79,77 +77,85 @@ public:
   virtual EventStates IntrinsicState() const override;
 
   virtual void OnDNSPrefetchDeferred() override;
   virtual void OnDNSPrefetchRequested() override;
   virtual bool HasDeferredDNSPrefetchRequest() override;
 
   // WebIDL API
 
-  // The XPCOM GetHref is OK for us
+  void GetHref(nsAString& aValue)
+  {
+    GetURIAttr(nsGkAtoms::href, nullptr, aValue);
+  }
   void SetHref(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::href, aValue, rv);
   }
-  // The XPCOM GetTarget is OK for us
+  void GetTarget(nsAString& aValue);
   void SetTarget(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::target, aValue, rv);
   }
   void GetDownload(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::download, aValue);
   }
   void SetDownload(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::download, aValue, rv);
   }
-  // The XPCOM GetPing is OK for us
+  void GetPing(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::ping, aValue);
+  }
   void SetPing(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::ping, aValue, rv);
   }
   void GetRel(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::rel, aValue);
   }
   void SetRel(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::rel, aValue, rv);
   }
   void SetReferrerPolicy(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv);
   }
-  void GetReferrerPolicy(nsAString& aReferrer)
+  void GetReferrerPolicy(DOMString& aPolicy)
   {
-    GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
+    GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aPolicy);
   }
   nsDOMTokenList* RelList();
   void GetHreflang(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::hreflang, aValue);
   }
   void SetHreflang(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::hreflang, aValue, rv);
   }
+  // Needed for docshell
+  void GetType(nsAString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::type, aValue);
+  }
   void GetType(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::type, aValue);
   }
   void SetType(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::type, aValue, rv);
   }
-  // The XPCOM GetText is OK for us
-  void SetText(const nsAString& aValue, mozilla::ErrorResult& rv)
-  {
-    rv = SetText(aValue);
-  }
+  void GetText(nsAString& aValue, mozilla::ErrorResult& rv);
+  void SetText(const nsAString& aValue, mozilla::ErrorResult& rv);
 
   // Link::GetOrigin is OK for us
 
   // Link::GetProtocol is OK for us
   // Link::SetProtocol is OK for us
 
   // Link::GetUsername is OK for us
   // Link::SetUsername is OK for us
@@ -170,17 +176,16 @@ public:
   // Link::Link::SetPathname is OK for us
 
   // Link::Link::GetSearch is OK for us
   // Link::Link::SetSearch is OK for us
 
   // Link::Link::GetHash is OK for us
   // Link::Link::SetHash is OK for us
 
-  // The XPCOM URI decomposition attributes are fine for us
   void GetCoords(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::coords, aValue);
   }
   void SetCoords(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::coords, aValue, rv);
   }
@@ -215,16 +220,17 @@ public:
   void SetShape(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::shape, aValue, rv);
   }
   void Stringify(nsAString& aResult)
   {
     GetHref(aResult);
   }
+  void ToString(nsAString& aSource);
 
   virtual void NodeInfoChanged(nsIDocument* aOldDoc) final override
   {
     ClearHasPendingLinkUpdate();
     nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
   }
 
   static DOMTokenListSupportedToken sSupportedRelValues[];
--- a/dom/html/HTMLAreaElement.h
+++ b/dom/html/HTMLAreaElement.h
@@ -37,16 +37,17 @@ public:
                                            nsGenericHTMLElement)
 
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
   virtual int32_t TabIndexDefault() override;
 
   // nsIDOMHTMLAreaElement
   NS_DECL_NSIDOMHTMLAREAELEMENT
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAreaElement, area);
 
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
 
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -30,17 +30,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // CC
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLLinkElement,
                                            nsGenericHTMLElement)
 
   // nsIDOMHTMLLinkElement
   NS_DECL_NSIDOMHTMLLINKELEMENT
-
+  NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLinkElement, link);
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
   void LinkAdded();
   void LinkRemoved();
 
   // nsIDOMEventTarget
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -3,17 +3,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 XPIDL_SOURCES += [
-    'nsIDOMHTMLAnchorElement.idl',
     'nsIDOMHTMLAreaElement.idl',
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLButtonElement.idl',
     'nsIDOMHTMLCanvasElement.idl',
     'nsIDOMHTMLCollection.idl',
     'nsIDOMHTMLDocument.idl',
     'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLFormElement.idl',
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLAnchorElement interface is the interface to a [X]HTML
- * a element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[uuid(339c01c8-2d41-4626-b231-eec63f0241b6)]
-interface nsIDOMHTMLAnchorElement : nsISupports
-{
-           attribute DOMString        href;
-           attribute DOMString        target;
-
-           attribute DOMString        ping;
-           attribute DOMString        download;
-
-           attribute DOMString        rel;
-           attribute DOMString        hreflang;
-           attribute DOMString        type;
-
-  /**
-   * An alias for the textContent attribute.
-   */
-  [Null(Stringify)]
-           attribute DOMString        text;
-
-  // URL decomposition IDL attributes
-           attribute DOMString        protocol;
-           attribute DOMString        host;
-           attribute DOMString        hostname;
-           attribute DOMString        port;
-           attribute DOMString        pathname;
-           attribute DOMString        search;
-           attribute DOMString        hash;
-
-
-           attribute DOMString        charset;
-           attribute DOMString        coords;
-           attribute DOMString        name;
-           attribute DOMString        rev;
-           attribute DOMString        shape;
-
-  DOMString                 toString();
-};
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -105,16 +105,17 @@
 #include "NullPrincipal.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PluginWidgetParent.h"
 #endif
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
 #include "mozilla/a11y/AccessibleWrap.h"
+#include "mozilla/a11y/Compatibility.h"
 #include "mozilla/a11y/nsWinUtils.h"
 #endif
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
@@ -2889,16 +2890,33 @@ TabParent::SetDocShellIsActive(bool isAc
   // SetDocShellIsActive requests are ignored.
   mLayerTreeEpoch++;
 
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !isActive;
   mDocShellIsActive = isActive;
   Unused << SendSetDocShellIsActive(isActive, mPreserveLayers, mLayerTreeEpoch);
 
+  // update active accessible documents on windows
+#if defined(XP_WIN) && defined(ACCESSIBILITY)
+  if (a11y::Compatibility::IsDolphin()) {
+    if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) {
+      HWND window = tabDoc->GetEmulatedWindowHandle();
+      MOZ_ASSERT(window);
+      if (window) {
+        if (isActive) {
+          a11y::nsWinUtils::ShowNativeWindow(window);
+        } else {
+          a11y::nsWinUtils::HideNativeWindow(window);
+        }
+      }
+    }
+  }
+#endif
+
   // Let's inform the priority manager. This operation can end up with the
   // changing of the process priority.
   ProcessPriorityManager::TabActivityChanged(this, isActive);
 
   // Ask the child to repaint using the PHangMonitor channel/thread (which may
   // be less congested).
   if (isActive) {
     ContentParent* cp = Manager()->AsContentParent();
--- a/dom/ipc/remote-test.js
+++ b/dom/ipc/remote-test.js
@@ -21,17 +21,17 @@ var dshell = content.QueryInterface(Ci.n
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIDocShell);
 
 
 addEventListener("click",
   function(e) {
     dump(e.target + "\n");
-    if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
+    if (ChromeUtils.getClassName(e.target) === "HTMLAnchorElement" &&
         dshell == docShell) {
       var retval = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                             getInterface(Components.interfaces.nsIContentFrameMessageManager).
                             sendSyncMessage("linkclick", { href: e.target.href });
       dump(uneval(retval[0]) + "\n");
       // Test here also that both retvals are the same
       sendAsyncMessage("linkclick-reply-object", uneval(retval[0]) == uneval(retval[1]) ? retval[0] : "");
     }
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -44,17 +44,17 @@ skip-if = true # needed by test_enumerat
 [test_ondevicechange.html]
 skip-if = os == 'android'
 [test_getUserMedia_active_autoplay.html]
 [test_getUserMedia_audioCapture.html]
 skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator), android(Bug 1264333)
 [test_getUserMedia_addTrackRemoveTrack.html]
 skip-if = android_version == '18' || os == 'linux' # android(Bug 1189784, timeouts on 4.3 emulator), linux bug 1377450
 [test_getUserMedia_addtrack_removetrack_events.html]
-skip-if os == 'linux' && debug # Bug 1389983
+skip-if = os == 'linux' && debug # Bug 1389983
 [test_getUserMedia_basicAudio.html]
 [test_getUserMedia_basicVideo.html]
 [test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
 [test_getUserMedia_basicScreenshare.html]
 skip-if = toolkit == 'android' # no screenshare on android
 [test_getUserMedia_basicTabshare.html]
 skip-if = toolkit == 'android' # no windowshare on android
 [test_getUserMedia_basicWindowshare.html]
new file mode 100644
--- /dev/null
+++ b/dom/svg/crashtests/1402798.html
@@ -0,0 +1,11 @@
+<style>
+    text::first-letter {}
+</style>
+<script>
+    function js() {
+        a.setAttribute("fill", "url()");
+    }
+</script>
+<body onload=js()>
+<svg>
+<text id="a">aa</text>
--- a/dom/svg/crashtests/crashtests.list
+++ b/dom/svg/crashtests/crashtests.list
@@ -88,8 +88,9 @@ load 1329849-3.svg
 load 1329849-4.svg
 load 1329849-5.svg
 load 1329849-6.svg
 load 1329093-1.html
 load 1329093-2.html
 load 1347617-1.svg
 load 1347617-2.svg
 load 1347617-3.svg
+load 1402798.html
--- a/dom/tests/mochitest/fetch/test_fetch_observer.html
+++ b/dom/tests/mochitest/fetch/test_fetch_observer.html
@@ -7,19 +7,17 @@
 <head>
   <title>Test FetchObserver</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script class="testbody" type="text/javascript">
 
-SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ],
-                                   ["dom.abortController.enabled", true ],
-                                   ["dom.abortController.fetch.enabled", true ]]}, () => {
+SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ]]}, () => {
   let ifr = document.createElement('iframe');
   ifr.src = "file_fetch_observer.html";
   document.body.appendChild(ifr);
 
   onmessage = function(e) {
     if (e.data.type == "finish") {
       SimpleTest.finish();
       return;
--- a/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -1,31 +1,31 @@
 /* -*- 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 "WebBrowserPersistLocalDocument.h"
 #include "WebBrowserPersistDocumentParent.h"
 
+#include "mozilla/dom/HTMLAnchorElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/dom/TabParent.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsContentCID.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsFrameLoader.h"
 #include "nsIComponentRegistrar.h"
 #include "nsIContent.h"
 #include "nsIDOMAttr.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLInputElement.h"
@@ -936,17 +936,17 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
     }
 
     nsCOMPtr<nsIContent> content = do_QueryInterface(aNodeIn);
     if (!content) {
         return NS_OK;
     }
 
     // Fix up href and file links in the elements
-    nsCOMPtr<nsIDOMHTMLAnchorElement> nodeAsAnchor = do_QueryInterface(aNodeIn);
+    RefPtr<dom::HTMLAnchorElement> nodeAsAnchor = dom::HTMLAnchorElement::FromContent(content);
     if (nodeAsAnchor) {
         rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAnchor(*aNodeOut);
         }
         return rv;
     }
 
--- a/dom/webidl/AbortController.webidl
+++ b/dom/webidl/AbortController.webidl
@@ -2,15 +2,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/.
  *
  * The origin of this IDL file is
  * https://dom.spec.whatwg.org/#abortcontroller
  */
 
-[Constructor(), Exposed=(Window,Worker),
- Func="AbortController::IsEnabled"]
+[Constructor(), Exposed=(Window,Worker)]
 interface AbortController {
   readonly attribute AbortSignal signal;
 
   void abort();
 };
--- a/dom/webidl/AbortSignal.webidl
+++ b/dom/webidl/AbortSignal.webidl
@@ -2,15 +2,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/.
  *
  * The origin of this IDL file is
  * https://dom.spec.whatwg.org/#abortsignal
  */
 
-[Exposed=(Window,Worker),
- Func="AbortController::IsEnabled"]
+[Exposed=(Window,Worker)]
 interface AbortSignal : EventTarget {
   readonly attribute boolean aborted;
 
   attribute EventHandler onabort;
 };
--- a/dom/webidl/HTMLAnchorElement.webidl
+++ b/dom/webidl/HTMLAnchorElement.webidl
@@ -26,17 +26,17 @@ interface HTMLAnchorElement : HTMLElemen
            attribute DOMString referrerPolicy;
            [PutForwards=value]
   readonly attribute DOMTokenList relList;
            [CEReactions, SetterThrows]
            attribute DOMString hreflang;
            [CEReactions, SetterThrows]
            attribute DOMString type;
 
-           [CEReactions, SetterThrows]
+           [CEReactions, Throws]
            attribute DOMString text;
 };
 
 HTMLAnchorElement implements HTMLHyperlinkElementUtils;
 
 // http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
 partial interface HTMLAnchorElement {
            [CEReactions, SetterThrows]
--- a/dom/webidl/Request.webidl
+++ b/dom/webidl/Request.webidl
@@ -22,18 +22,17 @@ interface Request {
   readonly attribute USVString referrer;
   readonly attribute ReferrerPolicy referrerPolicy;
   readonly attribute RequestMode mode;
   readonly attribute RequestCredentials credentials;
   readonly attribute RequestCache cache;
   readonly attribute RequestRedirect redirect;
   readonly attribute DOMString integrity;
 
-  [Func="AbortController::IsEnabledInFetch",
-   BinaryName="getOrCreateSignal"]
+  [BinaryName="getOrCreateSignal"]
   readonly attribute AbortSignal signal;
 
   [Throws,
    NewObject] Request clone();
 
   // Bug 1124638 - Allow chrome callers to set the context.
   [ChromeOnly]
   void overrideContentPolicyType(nsContentPolicyType context);
@@ -47,17 +46,16 @@ dictionary RequestInit {
   USVString referrer;
   ReferrerPolicy referrerPolicy;
   RequestMode mode;
   RequestCredentials credentials;
   RequestCache cache;
   RequestRedirect redirect;
   DOMString integrity;
 
-  [Func="AbortController::IsEnabledInFetch"]
   AbortSignal? signal;
 
   [Func="FetchObserver::IsEnabled"]
   ObserverCallback observe;
 };
 
 // Gecko currently does not ship RequestContext, so please don't use it in IDL
 // that is exposed to script.
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -37,18 +37,16 @@ WORKER_SIMPLE_PREF("dom.serviceWorkers.o
 WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED)
 WORKER_SIMPLE_PREF("dom.promise_rejection_events.enabled", PromiseRejectionEventsEnabled, PROMISE_REJECTION_EVENTS_ENABLED)
 WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
 WORKER_SIMPLE_PREF("dom.streams.enabled", StreamsEnabled, STREAMS_ENABLED)
 WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
 WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
 WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
 WORKER_SIMPLE_PREF("dom.netinfo.enabled", NetworkInformationEnabled, NETWORKINFORMATION_ENABLED)
-WORKER_SIMPLE_PREF("dom.abortController.enabled", AbortControllerEnabled, ABORTCONTROLLER_ENABLED)
-WORKER_SIMPLE_PREF("dom.abortController.fetch.enabled", AbortControllerEnabledInFetch, ABORTCONTROLLER_FETCH_ENABLED)
 WORKER_SIMPLE_PREF("dom.fetchObserver.enabled", FetchObserverEnabled, FETCHOBSERVER_ENABLED)
 WORKER_SIMPLE_PREF("privacy.resistFingerprinting", ResistFingerprintingEnabled, RESISTFINGERPRINTING_ENABLED)
 WORKER_SIMPLE_PREF("devtools.enabled", DevToolsEnabled, DEVTOOLS_ENABLED)
 WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
 WORKER_PREF("general.appname.override", AppNameOverrideChanged)
 WORKER_PREF("general.appversion.override", AppVersionOverrideChanged)
 WORKER_PREF("general.platform.override", PlatformOverrideChanged)
 #ifdef JS_GC_ZEAL
--- a/editor/libeditor/HTMLEditUtils.cpp
+++ b/editor/libeditor/HTMLEditUtils.cpp
@@ -13,21 +13,21 @@
 #include "nsAString.h"                  // for nsAString::IsEmpty
 #include "nsCOMPtr.h"                   // for nsCOMPtr, operator==, etc.
 #include "nsCaseTreatment.h"
 #include "nsDebug.h"                    // for NS_PRECONDITION, etc.
 #include "nsError.h"                    // for NS_SUCCEEDED
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::a, etc.
 #include "nsHTMLTags.h"
 #include "nsIAtom.h"                    // for nsIAtom
-#include "nsIDOMHTMLAnchorElement.h"    // for nsIDOMHTMLAnchorElement
 #include "nsIDOMNode.h"                 // for nsIDOMNode
 #include "nsNameSpaceManager.h"        // for kNameSpaceID_None
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsString.h"                   // for nsAutoString
+#include "mozilla/dom/HTMLAnchorElement.h"
 
 namespace mozilla {
 
 /**
  * IsInlineStyle() returns true if aNode is an inline style.
  */
 bool
 HTMLEditUtils::IsInlineStyle(nsIDOMNode* aNode)
@@ -331,24 +331,28 @@ HTMLEditUtils::IsLink(nsIDOMNode *aNode)
   return node && IsLink(node);
 }
 
 bool
 HTMLEditUtils::IsLink(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
 
-  nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
-  if (anchor) {
-    nsAutoString tmpText;
-    if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
-      return true;
-    }
+  if (!aNode->IsContent()) {
+    return false;
   }
-  return false;
+
+  RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContentOrNull(aNode->AsContent());
+  if (!anchor) {
+    return false;
+  }
+
+  nsAutoString tmpText;
+  anchor->GetHref(tmpText);
+  return !tmpText.IsEmpty();
 }
 
 bool
 HTMLEditUtils::IsNamedAnchor(nsIDOMNode *aNode)
 {
   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   return node && IsNamedAnchor(node);
 }
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -22,17 +22,16 @@
 #include "TypeInState.h"
 
 #include "nsIDOMMozNamedAttrMap.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMAttr.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMMouseEvent.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsISelectionController.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsILinkHandler.h"
 #include "nsIInlineSpellChecker.h"
 
 #include "mozilla/css/Loader.h"
 #include "nsIDOMStyleSheet.h"
 
@@ -2589,29 +2588,31 @@ HTMLEditor::InsertLinkAroundSelection(ns
   RefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   if (selection->Collapsed()) {
     NS_WARNING("InsertLinkAroundSelection called but there is no selection!!!");
     return NS_OK;
   }
 
+
   // Be sure we were given an anchor element
-  nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aAnchorElement);
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aAnchorElement);
+  RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContentOrNull(content);
   if (!anchor) {
     return NS_OK;
   }
 
   nsAutoString href;
-  nsresult rv = anchor->GetHref(href);
-  NS_ENSURE_SUCCESS(rv, rv);
+  anchor->GetHref(href);
   if (href.IsEmpty()) {
     return NS_OK;
   }
 
+  nsresult rv;
   AutoPlaceholderBatch beginBatching(this);
 
   // Set all attributes found on the supplied anchor element
   nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
   aAnchorElement->GetAttributes(getter_AddRefs(attrMap));
   NS_ENSURE_TRUE(attrMap, NS_ERROR_FAILURE);
 
   uint32_t count;
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -34,17 +34,16 @@
 #include "nsGkAtoms.h"
 #include "nsIClipboard.h"
 #include "nsIContent.h"
 #include "nsIContentFilter.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLScriptElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -603,20 +603,16 @@ GLBlitHelper::BlitImageToFramebuffer(lay
     switch (srcImage->GetFormat()) {
     case ImageFormat::PLANAR_YCBCR:
         return BlitImage(static_cast<PlanarYCbCrImage*>(srcImage), destSize, destOrigin);
 
 #ifdef MOZ_WIDGET_ANDROID
     case ImageFormat::SURFACE_TEXTURE:
         return BlitImage(static_cast<layers::SurfaceTextureImage*>(srcImage), destSize,
                          destOrigin);
-
-    case ImageFormat::EGLIMAGE:
-        return BlitImage(static_cast<layers::EGLImageImage*>(srcImage), destSize,
-                         destOrigin);
 #endif
 #ifdef XP_MACOSX
     case ImageFormat::MAC_IOSURFACE:
         return BlitImage(srcImage->AsMacIOSurfaceImage(), destSize, destOrigin);
 #endif
 #ifdef XP_WIN
     case ImageFormat::GPU_VIDEO:
         return BlitImage(static_cast<layers::GPUVideoImage*>(srcImage), destSize,
@@ -642,51 +638,16 @@ GLBlitHelper::BlitImage(layers::SurfaceT
                         const OriginPos) const
 {
     // FIXME
     const auto& srcOrigin = srcImage->GetOriginPos();
     (void)srcOrigin;
     gfxCriticalError() << "BlitImage(SurfaceTextureImage) not implemented.";
     return false;
 }
-
-bool
-GLBlitHelper::BlitImage(layers::EGLImageImage* const srcImage,
-                        const gfx::IntSize& destSize, const OriginPos destOrigin) const
-{
-    const EGLImage eglImage = srcImage->GetImage();
-    const EGLSync eglSync = srcImage->GetSync();
-    if (eglSync) {
-        EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER);
-        if (status != LOCAL_EGL_CONDITION_SATISFIED) {
-            return false;
-        }
-    }
-
-    GLuint tex = 0;
-    mGL->fGenTextures(1, &tex);
-
-    const ScopedSaveMultiTex saveTex(mGL, 1, LOCAL_GL_TEXTURE_2D);
-    mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, tex);
-    mGL->TexParams_SetClampNoMips();
-    mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, eglImage);
-
-    const auto& srcOrigin = srcImage->GetOriginPos();
-    const bool yFlip = destOrigin != srcOrigin;
-    const gfx::IntRect srcRect(0, 0, 1, 1);
-    const gfx::IntSize srcSize(1, 1);
-    const DrawBlitProg::BaseArgs baseArgs = { destSize, yFlip, srcRect, srcSize };
-
-    const auto& prog = GetDrawBlitProg({kFragHeader_Tex2D, kFragBody_RGBA});
-    MOZ_RELEASE_ASSERT(prog);
-    prog->Draw(baseArgs);
-
-    mGL->fDeleteTextures(1, &tex);
-    return true;
-}
 #endif
 
 // -------------------------------------
 
 bool
 GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
               gfx::IntSize* const out_divisors)
 {
--- a/gfx/gl/GLBlitHelper.h
+++ b/gfx/gl/GLBlitHelper.h
@@ -23,17 +23,16 @@ namespace mozilla {
 
 namespace layers {
 class D3D11YCbCrImage;
 class Image;
 class GPUVideoImage;
 class PlanarYCbCrImage;
 class SurfaceTextureImage;
 class MacIOSurfaceImage;
-class EGLImageImage;
 class SurfaceDescriptorD3D10;
 class SurfaceDescriptorDXGIYCbCr;
 } // namespace layers
 
 namespace gl {
 
 class BindAnglePlanes;
 class GLContext;
@@ -128,18 +127,16 @@ private:
 public:
 
     bool BlitImage(layers::PlanarYCbCrImage* yuvImage, const gfx::IntSize& destSize,
                    OriginPos destOrigin);
 #ifdef MOZ_WIDGET_ANDROID
     // Blit onto the current FB.
     bool BlitImage(layers::SurfaceTextureImage* stImage, const gfx::IntSize& destSize,
                    OriginPos destOrigin) const;
-    bool BlitImage(layers::EGLImageImage* eglImage, const gfx::IntSize& destSize,
-                   OriginPos destOrigin) const;
 #endif
 #ifdef XP_MACOSX
     bool BlitImage(layers::MacIOSurfaceImage* srcImage, const gfx::IntSize& destSize,
                    OriginPos destOrigin) const;
 #endif
 
     explicit GLBlitHelper(GLContext* gl);
 public:
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -11,45 +11,16 @@
 using namespace mozilla;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 static RefPtr<GLContext> sSnapshotContext;
 
-EGLImageImage::EGLImageImage(EGLImage aImage, EGLSync aSync,
-                             const gfx::IntSize& aSize, const gl::OriginPos& aOrigin,
-                             bool aOwns)
- : GLImage(ImageFormat::EGLIMAGE),
-   mImage(aImage),
-   mSync(aSync),
-   mSize(aSize),
-   mPos(aOrigin),
-   mOwns(aOwns)
-{
-}
-
-EGLImageImage::~EGLImageImage()
-{
-  if (!mOwns) {
-    return;
-  }
-
-  if (mImage) {
-    sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mImage);
-    mImage = nullptr;
-  }
-
-  if (mSync) {
-    sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSync);
-    mSync = nullptr;
-  }
-}
-
 already_AddRefed<gfx::SourceSurface>
 GLImage::GetAsSourceSurface()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");
 
   if (!sSnapshotContext) {
     nsCString discardFailureId;
     sSnapshotContext = GLContextProvider::CreateHeadless(CreateContextFlags::NONE,
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -23,48 +23,16 @@ public:
 
   virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
 
   GLImage* AsGLImage() override {
     return this;
   }
 };
 
-class EGLImageImage : public GLImage {
-public:
-  EGLImageImage(EGLImage aImage, EGLSync aSync,
-                const gfx::IntSize& aSize, const gl::OriginPos& aOrigin,
-                bool aOwns);
-
-  gfx::IntSize GetSize() override { return mSize; }
-  gl::OriginPos GetOriginPos() const {
-    return mPos;
-  }
-  EGLImage GetImage() const {
-    return mImage;
-  }
-  EGLSync GetSync() const {
-    return mSync;
-  }
-
-  EGLImageImage* AsEGLImageImage() override {
-    return this;
-  }
-
-protected:
-  virtual ~EGLImageImage();
-
-private:
-  EGLImage mImage;
-  EGLSync mSync;
-  gfx::IntSize mSize;
-  gl::OriginPos mPos;
-  bool mOwns;
-};
-
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureImage : public GLImage {
 public:
   SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
                       const gfx::IntSize& aSize,
                       bool aContinuous,
                       gl::OriginPos aOriginPos);
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -169,17 +169,16 @@ struct ImageBackendData
   virtual ~ImageBackendData() {}
 
 protected:
   ImageBackendData() {}
 };
 
 /* Forward declarations for Image derivatives. */
 class GLImage;
-class EGLImageImage;
 class SharedRGBImage;
 #ifdef MOZ_WIDGET_ANDROID
 class SurfaceTextureImage;
 #elif defined(XP_MACOSX)
 class MacIOSurfaceImage;
 #endif
 
 /**
@@ -228,17 +227,16 @@ public:
 
   /**
    * For use with the TextureForwarder only (so that the later can
    * synchronize the TextureClient with the TextureHost).
    */
   virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) { return nullptr; }
 
   /* Access to derived classes. */
-  virtual EGLImageImage* AsEGLImageImage() { return nullptr; }
   virtual GLImage* AsGLImage() { return nullptr; }
 #ifdef MOZ_WIDGET_ANDROID
   virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
 #endif
 #ifdef XP_MACOSX
   virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
 #endif
   virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
--- a/gfx/layers/ImageTypes.h
+++ b/gfx/layers/ImageTypes.h
@@ -51,21 +51,16 @@ enum class ImageFormat {
 
   /**
    * An Android SurfaceTexture ID that can be shared across threads and
    * processes.
    */
   SURFACE_TEXTURE,
 
   /**
-   * An EGL Image that can be shared across threads.
-   */
-  EGLIMAGE,
-
-  /**
    * The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a
    * IDirect3DTexture9 in RGB32 layout.
    */
   D3D9_RGB32_TEXTURE,
 
   /**
    * An Image type carries an opaque handle once for each stream.
    * The opaque handle would be a platform specific identifier.
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -395,18 +395,16 @@ AppendToString(std::stringstream& aStrea
   case ImageFormat::SHARED_RGB:
     aStream << "ImageFormat::SHARED_RGB"; break;
   case ImageFormat::CAIRO_SURFACE:
     aStream << "ImageFormat::CAIRO_SURFACE"; break;
   case ImageFormat::MAC_IOSURFACE:
     aStream << "ImageFormat::MAC_IOSURFACE"; break;
   case ImageFormat::SURFACE_TEXTURE:
     aStream << "ImageFormat::SURFACE_TEXTURE"; break;
-  case ImageFormat::EGLIMAGE:
-    aStream << "ImageFormat::EGLIMAGE"; break;
   case ImageFormat::D3D9_RGB32_TEXTURE:
     aStream << "ImageFormat::D3D9_RBG32_TEXTURE"; break;
   case ImageFormat::OVERLAY_IMAGE:
     aStream << "ImageFormat::OVERLAY_IMAGE"; break;
   case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE:
     aStream << "ImageFormat::D3D11_SHARE_HANDLE_TEXTURE"; break;
   default:
     NS_ERROR("unknown image format");
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -113,34 +113,24 @@ ImageClient::CreateTextureClientForImage
       return nullptr;
     }
 
     bool status = UpdateYCbCrTextureClient(texture, *data);
     MOZ_ASSERT(status);
     if (!status) {
       return nullptr;
     }
-  } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
-             aImage->GetFormat() == ImageFormat::EGLIMAGE) {
+#ifdef MOZ_WIDGET_ANDROID
+  } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
     gfx::IntSize size = aImage->GetSize();
-
-    if (aImage->GetFormat() == ImageFormat::EGLIMAGE) {
-      EGLImageImage* typedImage = aImage->AsEGLImageImage();
-      texture = EGLImageTextureData::CreateTextureClient(
-        typedImage, size, aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
-#ifdef MOZ_WIDGET_ANDROID
-    } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
-      SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
-      texture = AndroidSurfaceTextureData::CreateTextureClient(
-        typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
-        aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
+    SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
+    texture = AndroidSurfaceTextureData::CreateTextureClient(
+      typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
+      aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
 #endif
-    } else {
-      MOZ_ASSERT(false, "Bad ImageFormat.");
-    }
   } else {
     RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
     MOZ_ASSERT(surface);
     texture = TextureClient::CreateForDrawing(aForwarder, surface->GetFormat(), aImage->GetSize(),
                                               BackendSelector::Content, TextureFlags::DEFAULT);
     if (!texture) {
       return nullptr;
     }
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -13,72 +13,16 @@
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
 
 ////////////////////////////////////////////////////////////////////////
-// EGLImage
-
-EGLImageTextureData::EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize)
-: mImage(aImage)
-, mSize(aSize)
-{
-  MOZ_ASSERT(aImage);
-}
-
-already_AddRefed<TextureClient>
-EGLImageTextureData::CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
-                                         LayersIPCChannel* aAllocator, TextureFlags aFlags)
-{
-  MOZ_ASSERT(XRE_IsParentProcess(),
-             "Can't pass an `EGLImage` between processes.");
-
-  if (!aImage || !XRE_IsParentProcess()) {
-    return nullptr;
-  }
-
-  // XXX - This is quite sad and slow.
-  aFlags |= TextureFlags::DEALLOCATE_CLIENT;
-
-  if (aImage->GetOriginPos() == gl::OriginPos::BottomLeft) {
-    aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
-  }
-
-  return TextureClient::CreateWithData(
-    new EGLImageTextureData(aImage, aSize),
-    aFlags, aAllocator
-  );
-}
-
-void
-EGLImageTextureData::FillInfo(TextureData::Info& aInfo) const
-{
-  aInfo.size = mSize;
-  aInfo.format = gfx::SurfaceFormat::UNKNOWN;
-  aInfo.hasIntermediateBuffer = false;
-  aInfo.hasSynchronization = false;
-  aInfo.supportsMoz2D = false;
-  aInfo.canExposeMappedData = false;
-}
-
-bool
-EGLImageTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
-{
-  const bool hasAlpha = true;
-  aOutDescriptor =
-    EGLImageDescriptor((uintptr_t)mImage->GetImage(),
-                       (uintptr_t)mImage->GetSync(),
-                       mImage->GetSize(), hasAlpha);
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////////
 // AndroidSurface
 
 #ifdef MOZ_WIDGET_ANDROID
 
 already_AddRefed<TextureClient>
 AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
                                                gfx::IntSize aSize,
                                                bool aContinuous,
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -15,44 +15,16 @@
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "AndroidSurfaceTexture.h"
 
 namespace mozilla {
 
 namespace layers {
 
-class EGLImageTextureData : public TextureData
-{
-public:
-
-  static already_AddRefed<TextureClient>
-  CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
-                      LayersIPCChannel* aAllocator, TextureFlags aFlags);
-
-  virtual void FillInfo(TextureData::Info& aInfo) const override;
-
-  virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
-
-  virtual void Deallocate(LayersIPCChannel*) override { mImage = nullptr; }
-
-  virtual void Forget(LayersIPCChannel*) override { mImage = nullptr; }
-
-  // Unused functions.
-  virtual bool Lock(OpenMode) override { return true; }
-
-  virtual void Unlock() override {}
-
-protected:
-  EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize);
-
-  RefPtr<EGLImageImage> mImage;
-  const gfx::IntSize mSize;
-};
-
 #ifdef MOZ_WIDGET_ANDROID
 
 class AndroidSurfaceTextureData : public TextureData
 {
 public:
   static already_AddRefed<TextureClient>
   CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
                       gfx::IntSize aSize,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -603,22 +603,25 @@ void RecordingPrefChanged(const char *aP
 void
 WebRenderDebugPrefChangeCallback(const char* aPrefName, void*)
 {
   int32_t flags = 0;
   // TODO: It would be nice to get the bit patterns directly from the rust code.
   if (Preferences::GetBool(WR_DEBUG_PREF".profiler", false)) {
     flags |= (1 << 0);
   }
-  if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
+  if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
     flags |= (1 << 1);
   }
-  if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
+  if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
     flags |= (1 << 2);
   }
+  if (Preferences::GetBool(WR_DEBUG_PREF".alpha-primitives", false)) {
+    flags |= (1 << 3);
+  }
 
   gfx::gfxVars::SetWebRenderDebugFlags(flags);
 }
 
 
 #if defined(USE_SKIA)
 static uint32_t GetSkiaGlyphCacheSize()
 {
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -595,17 +595,17 @@ JavaScriptShared::fromDescriptor(JSConte
 bool
 UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
     JS_ReportErrorASCII(cx, "getter could not be wrapped via CPOWs");
     return false;
 }
 
 bool
-UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
+UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                           ObjectOpResult& result)
 {
     JS_ReportErrorASCII(cx, "setter could not be wrapped via CPOWs");
     return false;
 }
 
 bool
 JavaScriptShared::toDescriptor(JSContext* cx, const PPropertyDescriptor& in,
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -374,23 +374,21 @@ typedef bool
 
 /** Add a property named by id to obj. */
 typedef bool
 (* JSAddPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
 
 /**
  * Set a property named by id in obj, treating the assignment as strict
  * mode code if strict is true. Note the jsid id type -- id may be a string
- * (Unicode property identifier) or an int (element index). The *vp out
- * parameter, on success, is the new property value after the
- * set.
+ * (Unicode property identifier) or an int (element index).
  */
 typedef bool
 (* JSSetterOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
-               JS::MutableHandleValue vp, JS::ObjectOpResult& result);
+               JS::HandleValue v, JS::ObjectOpResult& result);
 
 /**
  * Delete a property named by id in obj.
  *
  * If an error occurred, return false as per normal JSAPI error practice.
  *
  * If no error occurred, but the deletion attempt wasn't allowed (perhaps
  * because the property was non-configurable), call result.fail() and
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -637,33 +637,33 @@ js::SetLengthProperty(JSContext* cx, Han
 static bool
 array_length_getter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
     vp.setNumber(obj->as<ArrayObject>().length());
     return true;
 }
 
 static bool
-array_length_setter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
+array_length_setter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                     ObjectOpResult& result)
 {
     MOZ_ASSERT(id == NameToId(cx->names().length));
 
     if (!obj->is<ArrayObject>()) {
         // This array .length property was found on the prototype
         // chain. Ideally the setter should not have been called, but since
         // we're here, do an impression of SetPropertyByDefining.
-        return DefineDataProperty(cx, obj, id, vp, JSPROP_ENUMERATE, result);
+        return DefineDataProperty(cx, obj, id, v, JSPROP_ENUMERATE, result);
     }
 
     Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
     MOZ_ASSERT(arr->lengthIsWritable(),
                "setter shouldn't be called if property is non-writable");
 
-    return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, result);
+    return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, v, result);
 }
 
 struct ReverseIndexComparator
 {
     bool operator()(const uint32_t& a, const uint32_t& b, bool* lessOrEqualp) {
         MOZ_ASSERT(a != b, "how'd we get duplicate indexes?");
         *lessOrEqualp = b <= a;
         return true;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1322,17 +1322,16 @@ JSContext::JSContext(JSRuntime* runtime,
     enableAccessValidation(false),
     inUnsafeRegion(0),
     generationalDisabled(0),
     compactingDisabledCount(0),
     keepAtoms(0),
     suppressProfilerSampling(false),
     tempLifoAlloc_((size_t)TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     debuggerMutations(0),
-    propertyRemovals(0),
     ionPcScriptCache(nullptr),
     throwing(false),
     overRecursed_(false),
     propagatingForcedReturn_(false),
     liveVolatileJitFrameIter_(nullptr),
     reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     resolvingList(nullptr),
 #ifdef DEBUG
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -608,23 +608,16 @@ struct JSContext : public JS::RootingCon
   private:
     js::ThreadLocalData<js::LifoAlloc> tempLifoAlloc_;
   public:
     js::LifoAlloc& tempLifoAlloc() { return tempLifoAlloc_.ref(); }
     const js::LifoAlloc& tempLifoAlloc() const { return tempLifoAlloc_.ref(); }
 
     js::ThreadLocalData<uint32_t> debuggerMutations;
 
-    /*
-     * The propertyRemovals counter is incremented for every JSObject::clear,
-     * and for each JSObject::remove method call that frees a slot in the given
-     * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
-     */
-    js::ThreadLocalData<uint32_t> propertyRemovals;
-
     // Cache for jit::GetPcScript().
     js::ThreadLocalData<js::jit::PcScriptCache*> ionPcScriptCache;
 
   private:
     /* Exception state -- the exception member is a GC root by definition. */
     js::ThreadLocalData<bool> throwing;            /* is there a pending exception? */
     js::ThreadLocalData<JS::PersistentRooted<JS::Value>> unwrappedException_; /* most-recently-thrown exception */
 
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -360,24 +360,24 @@ CallJSGetterOp(JSContext* cx, GetterOp o
     assertSameCompartment(cx, obj, id, vp);
     bool ok = op(cx, obj, id, vp);
     if (ok)
         assertSameCompartment(cx, vp);
     return ok;
 }
 
 MOZ_ALWAYS_INLINE bool
-CallJSSetterOp(JSContext* cx, SetterOp op, HandleObject obj, HandleId id, MutableHandleValue vp,
+CallJSSetterOp(JSContext* cx, SetterOp op, HandleObject obj, HandleId id, HandleValue v,
                ObjectOpResult& result)
 {
     if (!CheckRecursionLimit(cx))
         return false;
 
-    assertSameCompartment(cx, obj, id, vp);
-    return op(cx, obj, id, vp, result);
+    assertSameCompartment(cx, obj, id, v);
+    return op(cx, obj, id, v, result);
 }
 
 inline bool
 CallJSAddPropertyOp(JSContext* cx, JSAddPropertyOp op, HandleObject obj, HandleId id,
                     HandleValue v)
 {
     if (!CheckRecursionLimit(cx))
         return false;
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -190,20 +190,18 @@ js::SetPropertyIgnoringNamedGetter(JSCon
         // Steps 5.a-b.
         if (!ownDesc.writable())
             return result.fail(JSMSG_READ_ONLY);
         if (!receiver.isObject())
             return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
         RootedObject receiverObj(cx, &receiver.toObject());
 
         // Nonstandard SpiderMonkey special case: setter ops.
-        if (SetterOp setter = ownDesc.setter()) {
-            RootedValue valCopy(cx, v);
-            return CallJSSetterOp(cx, setter, receiverObj, id, &valCopy, result);
-        }
+        if (SetterOp setter = ownDesc.setter())
+            return CallJSSetterOp(cx, setter, receiverObj, id, v, result);
 
         // Steps 5.c-d.
         Rooted<PropertyDescriptor> existingDescriptor(cx);
         if (!GetOwnPropertyDescriptor(cx, receiverObj, id, &existingDescriptor))
             return false;
 
         // Step 5.e.
         if (existingDescriptor.object()) {
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -471,17 +471,17 @@ MappedArgGetter(JSContext* cx, HandleObj
             else
                 vp.setObject(*callee);
         }
     }
     return true;
 }
 
 static bool
-MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
+MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                 ObjectOpResult& result)
 {
     if (!obj->is<MappedArgumentsObject>())
         return result.succeed();
     Handle<MappedArgumentsObject*> argsobj = obj.as<MappedArgumentsObject>();
 
     Rooted<PropertyDescriptor> desc(cx);
     if (!GetOwnPropertyDescriptor(cx, argsobj, id, &desc))
@@ -494,36 +494,36 @@ MappedArgSetter(JSContext* cx, HandleObj
     RootedFunction callee(cx, &argsobj->callee());
     RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
     if (!script)
         return false;
 
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
-            argsobj->setElement(cx, arg, vp);
+            argsobj->setElement(cx, arg, v);
             if (arg < script->functionNonDelazifying()->nargs())
-                TypeScript::SetArgument(cx, script, arg, vp);
+                TypeScript::SetArgument(cx, script, arg, v);
             return result.succeed();
         }
     } else {
         MOZ_ASSERT(JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().callee));
     }
 
     /*
      * For simplicity we use delete/define to replace the property with a
      * simple data property. Note that we rely on ArgumentsObject::obj_delProperty
      * to set the corresponding override-bit.
      * Note also that we must define the property instead of setting it in case
      * the user has changed the prototype to an object that has a setter for
      * this id.
      */
     ObjectOpResult ignored;
     return NativeDeleteProperty(cx, argsobj, id, ignored) &&
-           NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
+           NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
 }
 
 static bool
 DefineArgumentsIterator(JSContext* cx, Handle<ArgumentsObject*> argsobj)
 {
     RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
     HandlePropertyName shName = cx->names().ArrayValues;
     RootedAtom name(cx, cx->names().values);
@@ -721,17 +721,17 @@ UnmappedArgGetter(JSContext* cx, HandleO
         MOZ_ASSERT(JSID_IS_ATOM(id, cx->names().length));
         if (!argsobj.hasOverriddenLength())
             vp.setInt32(argsobj.initialLength());
     }
     return true;
 }
 
 static bool
-UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
+UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                   ObjectOpResult& result)
 {
     if (!obj->is<UnmappedArgumentsObject>())
         return result.succeed();
     Handle<UnmappedArgumentsObject*> argsobj = obj.as<UnmappedArgumentsObject>();
 
     Rooted<PropertyDescriptor> desc(cx);
     if (!GetOwnPropertyDescriptor(cx, argsobj, id, &desc))
@@ -739,31 +739,31 @@ UnmappedArgSetter(JSContext* cx, HandleO
     MOZ_ASSERT(desc.object());
     unsigned attrs = desc.attributes();
     MOZ_ASSERT(!(attrs & JSPROP_READONLY));
     attrs &= (JSPROP_ENUMERATE | JSPROP_PERMANENT); /* only valid attributes */
 
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj->initialLength()) {
-            argsobj->setElement(cx, arg, vp);
+            argsobj->setElement(cx, arg, v);
             return result.succeed();
         }
     } else {
         MOZ_ASSERT(JSID_IS_ATOM(id, cx->names().length));
     }
 
     /*
      * For simplicity we use delete/define to replace the property with a
      * simple data property. Note that we rely on ArgumentsObject::obj_delProperty
      * to set the corresponding override-bit.
      */
     ObjectOpResult ignored;
     return NativeDeleteProperty(cx, argsobj, id, ignored) &&
-           NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
+           NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
 }
 
 /* static */ bool
 UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
 {
     Rooted<UnmappedArgumentsObject*> argsobj(cx, &obj->as<UnmappedArgumentsObject>());
 
     if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -2498,32 +2498,18 @@ NativeSetExistingDataProperty(JSContext*
         // Bizarre: shared (slotless) property that's writable but has no
         // JSSetterOp. JS code can't define such a property, but it can be done
         // through the JSAPI. Treat it as non-writable.
         return result.fail(JSMSG_GETTER_ONLY);
     }
 
     MOZ_ASSERT(!obj->is<WithEnvironmentObject>());  // See bug 1128681.
 
-    uint32_t sample = cx->propertyRemovals;
     RootedId id(cx, shape->propid());
-    RootedValue value(cx, v);
-    if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
-        return false;
-
-    // Update any slot for the shape with the value produced by the setter,
-    // unless the setter deleted the shape.
-    if (shape->hasSlot() &&
-        (MOZ_LIKELY(cx->propertyRemovals == sample) ||
-         obj->contains(cx, shape)))
-    {
-        obj->setSlot(shape->slot(), value);
-    }
-
-    return true;  // result is populated by CallJSSetterOp above.
+    return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
 }
 
 /*
  * When a [[Set]] operation finds no existing property with the given id
  * or finds a writable data property on the prototype chain, we end up here.
  * Finish the [[Set]] by defining a new property on receiver.
  *
  * This implements ES6 draft rev 28, 9.1.9 [[Set]] steps 5.b-f, but it
@@ -2724,18 +2710,17 @@ SetExistingProperty(JSContext* cx, Handl
         // property causes the setter to be called, instead of shadowing,
         // unless the existing property is JSPROP_SHADOWABLE (see bug 552432).
         if (!shape->hasSlot() && !shape->hasShadowable()) {
             // Even weirder sub-special-case: inherited slotless data property
             // with default setter. Wut.
             if (shape->hasDefaultSetter())
                 return result.succeed();
 
-            RootedValue valCopy(cx, v);
-            return CallJSSetterOp(cx, shape->setterOp(), obj, id, &valCopy, result);
+            return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
         }
 
         // Shadow pobj[id] by defining a new data property receiver[id].
         // Delegate everything to SetPropertyByDefining.
         return SetPropertyByDefining(cx, id, v, receiver, result);
     }
 
     // Steps 6-11.
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -850,23 +850,18 @@ NativeObject::putProperty(JSContext* cx,
     }
 
     /*
      * Can't fail now, so free the previous incarnation's slot if the new shape
      * has no slot. But we do not need to free oldSlot (and must not, as trying
      * to will botch an assertion in JSObject::freeSlot) if the new last
      * property (shape here) has a slotSpan that does not cover it.
      */
-    if (hadSlot && !shape->hasSlot()) {
-        if (oldSlot < obj->slotSpan())
-            obj->freeSlot(cx, oldSlot);
-        /* Note: The optimization based on propertyRemovals is only relevant to the active thread. */
-        if (!cx->helperThread())
-            ++cx->propertyRemovals;
-    }
+    if (hadSlot && !shape->hasSlot() && oldSlot < obj->slotSpan())
+        obj->freeSlot(cx, oldSlot);
 
     obj->checkShapeConsistency();
 
     return shape;
 }
 
 /* static */ Shape*
 NativeObject::changeProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
@@ -954,21 +949,18 @@ NativeObject::removeProperty(JSContext* 
             BaseShape* nbase = BaseShape::getUnowned(cx, base);
             if (!nbase)
                 return false;
             previous->base_ = nbase;
         }
     }
 
     /* If shape has a slot, free its slot number. */
-    if (shape->hasSlot()) {
+    if (shape->hasSlot())
         obj->freeSlot(cx, shape->slot());
-        if (!cx->helperThread())
-            ++cx->propertyRemovals;
-    }
 
     /*
      * A dictionary-mode object owns mutable, unique shapes on a non-circular
      * doubly linked list, hashed by lastProperty()->table. So we can edit the
      * list and hash in place.
      */
     if (obj->inDictionaryMode()) {
         ShapeTable* table = obj->lastProperty()->maybeTable(keep);
@@ -1037,18 +1029,16 @@ NativeObject::clear(JSContext* cx, Handl
     }
     MOZ_ASSERT(shape->isEmptyShape());
 
     if (obj->inDictionaryMode())
         shape->listp = &obj->shape_;
 
     JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
 
-    if (!cx->helperThread())
-        ++cx->propertyRemovals;
     obj->checkShapeConsistency();
 }
 
 /* static */ bool
 NativeObject::rollbackProperties(JSContext* cx, HandleNativeObject obj, uint32_t slotSpan)
 {
     /*
      * Remove properties from this object until it has a matching slot span.
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -435,24 +435,24 @@ sandbox_moved(JSObject* obj, JSObject* o
     if (!sop)
         return 0;
 
     return static_cast<SandboxPrivate*>(sop)->ObjectMoved(obj, old);
 }
 
 static bool
 writeToProto_setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
-                         JS::MutableHandleValue vp, JS::ObjectOpResult& result)
+                         JS::HandleValue v, JS::ObjectOpResult& result)
 {
     RootedObject proto(cx);
     if (!JS_GetPrototype(cx, obj, &proto))
         return false;
 
     RootedValue receiver(cx, ObjectValue(*proto));
-    return JS_ForwardSetPropertyTo(cx, proto, id, vp, receiver, result);
+    return JS_ForwardSetPropertyTo(cx, proto, id, v, receiver, result);
 }
 
 static bool
 writeToProto_getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
                     JS::MutableHandleValue vp)
 {
     RootedObject proto(cx);
     if (!JS_GetPrototype(cx, obj, &proto))
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -757,17 +757,17 @@ nsIPresShell::nsIPresShell()
     , mDidInitialize(false)
     , mIsDestroying(false)
     , mIsReflowing(false)
     , mPaintingSuppressed(false)
     , mIsActive(false)
     , mFrozen(false)
     , mIsFirstPaint(false)
     , mObservesMutationsForPrint(false)
-    , mSuppressInterruptibleReflows(false)
+    , mWasLastReflowInterrupted(false)
     , mScrollPositionClampingScrollPortSizeSet(false)
     , mNeedLayoutFlush(true)
     , mNeedStyleFlush(true)
     , mObservingStyleFlushes(false)
     , mObservingLayoutFlushes(false)
     , mNeedThrottledAnimationFlush(true)
     , mPresShellId(0)
     , mFontSizeInflationEmPerLine(0)
@@ -4192,17 +4192,17 @@ PresShell::DoFlushPendingNotifications(m
 
     didStyleFlush = true;
 
 
     // There might be more pending constructors now, but we're not going to
     // worry about them.  They can't be triggered during reflow, so we should
     // be good.
 
-    if (flushType >= (mSuppressInterruptibleReflows
+    if (flushType >= (SuppressInterruptibleReflows()
                         ? FlushType::Layout
                         : FlushType::InterruptibleLayout) &&
         !mIsDestroying) {
       didLayoutFlush = true;
       mFrameConstructor->RecalcQuotesAndCounters();
       viewManager->FlushDelayedResize(true);
       if (ProcessReflowCommands(flushType < FlushType::Layout) &&
           mContentToScrollTo) {
@@ -4227,17 +4227,17 @@ PresShell::DoFlushPendingNotifications(m
     if (aFlush.mFlushAnimations) {
       SetNeedThrottledAnimationFlush();
     }
   }
 
   if (!didLayoutFlush && flushType >= FlushType::InterruptibleLayout &&
       !mIsDestroying) {
     // We suppressed this flush either due to it not being safe to flush,
-    // or due to mSuppressInterruptibleReflows.  Either way, the
+    // or due to SuppressInterruptibleReflows().  Either way, the
     // mNeedLayoutFlush flag needs to be re-set.
     SetNeedLayoutFlush();
   }
 }
 
 void
 PresShell::CharacterDataChanged(nsIDocument *aDocument,
                                 nsIContent*  aContent,
@@ -9452,17 +9452,17 @@ PresShell::DoReflow(nsIFrame* target, bo
 #ifdef NOISY_INTERRUPTIBLE_REFLOW
     printf("mFramesToDirty.Count() == %u\n", mFramesToDirty.Count());
 #endif /* NOISY_INTERRUPTIBLE_REFLOW */
     mFramesToDirty.Clear();
 
     // Any FlushPendingNotifications with interruptible reflows
     // should be suppressed now. We don't want to do extra reflow work
     // before our reflow event happens.
-    mSuppressInterruptibleReflows = true;
+    mWasLastReflowInterrupted = true;
     MaybeScheduleReflow();
   }
 
   // dump text perf metrics for reflows with significant text processing
   if (tp) {
     if (tp->current.numChars > 100) {
       TimeDuration reflowTime = TimeStamp::Now() - timeStart;
       LogTextPerfStats(tp, this, tp->current,
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1576,16 +1576,31 @@ public:
    * whether font size inflation is enabled on the next call to
    * FontSizeInflationEnabled().
    */
   void NotifyFontSizeInflationEnabledIsDirty()
   {
     mFontSizeInflationEnabledIsDirty = true;
   }
 
+  /**
+   * Return true if the most recent interruptible reflow was interrupted.
+   */
+  bool IsReflowInterrupted() const {
+    return mWasLastReflowInterrupted;
+  }
+
+  /**
+   * Return true if the the interruptible reflows have to be suppressed.
+   * This may happen only if if the most recent reflow was interrupted.
+   */
+  bool SuppressInterruptibleReflows() const {
+    return mWasLastReflowInterrupted;
+  }
+
   //////////////////////////////////////////////////////////////////////////////
   // Approximate frame visibility tracking public API.
   //////////////////////////////////////////////////////////////////////////////
 
   /// Schedule an update of the list of approximately visible frames "soon".
   /// This lets the refresh driver know that we want a visibility update in the
   /// near future. The refresh driver applies its own heuristics and throttling
   /// to decide when to actually perform the visibility update.
@@ -1789,17 +1804,18 @@ protected:
   // For all documents we initially lock down painting.
   bool                      mPaintingSuppressed : 1;
 
   bool                      mIsActive : 1;
   bool                      mFrozen : 1;
   bool                      mIsFirstPaint : 1;
   bool                      mObservesMutationsForPrint : 1;
 
-  bool                      mSuppressInterruptibleReflows : 1;
+  // Whether the most recent interruptible reflow was actually interrupted:
+  bool                      mWasLastReflowInterrupted : 1;
   bool                      mScrollPositionClampingScrollPortSizeSet : 1;
 
   // True if a layout flush might not be a no-op
   bool mNeedLayoutFlush : 1;
 
   // True if a style flush might not be a no-op
   bool mNeedStyleFlush : 1;
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1944,17 +1944,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
 
         if (!tracingLayoutFlush) {
           tracingLayoutFlush.emplace("Paint", "Reflow", Move(mReflowCause));
           mReflowCause = nullptr;
         }
 
         nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
         shell->mObservingLayoutFlushes = false;
-        shell->mSuppressInterruptibleReflows = false;
+        shell->mWasLastReflowInterrupted = false;
         FlushType flushType = HasPendingAnimations(shell)
                                ? FlushType::Layout
                                : FlushType::InterruptibleLayout;
         shell->FlushPendingNotifications(ChangesToFlush(flushType, false));
         // Inform the FontFaceSet that we ticked, so that it can resolve its
         // ready promise if it needs to.
         nsPresContext* presContext = shell->GetPresContext();
         if (presContext) {
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -38,17 +38,16 @@
 #include "nsTransform2D.h"
 #include "nsImageMap.h"
 #include "nsIIOService.h"
 #include "nsILoadGroup.h"
 #include "nsISupportsPriority.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsCSSRendering.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsNameSpaceManager.h"
 #include <algorithm>
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 #include "nsIDOMNode.h"
 #include "nsLayoutUtils.h"
 #include "nsDisplayList.h"
@@ -76,16 +75,17 @@
 #include "mozilla/StyleSetHandleInlines.h"
 #include "nsBlockFrame.h"
 #include "nsStyleStructInlines.h"
 
 #include "mozilla/Preferences.h"
 
 #include "mozilla/dom/Link.h"
 #include "SVGImageContext.h"
+#include "mozilla/dom/HTMLAnchorElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 using namespace mozilla::layers;
 
 // sizes (pixels) for image icon, padding and border frame
@@ -1988,17 +1988,17 @@ nsImageFrame::GetAnchorHREFTargetAndNode
     nsCOMPtr<dom::Link> link(do_QueryInterface(content));
     if (link) {
       nsCOMPtr<nsIURI> href = content->GetHrefURI();
       if (href) {
         href->Clone(aHref);
       }
       status = (*aHref != nullptr);
 
-      nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(content));
+      RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(content);
       if (anchor) {
         anchor->GetTarget(aTarget);
       }
       NS_ADDREF(*aNode = content);
       break;
     }
   }
   return status;
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -99,17 +99,16 @@ static const char kPrintingPromptService
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIBaseWindow.h"
 #include "nsILayoutHistoryState.h"
 #include "nsFrameManager.h"
 #include "mozilla/ReflowInput.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIContentViewer.h"
 #include "nsIDocumentViewerPrint.h"
 
 #include "nsFocusManager.h"
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1408,17 +1408,17 @@ fuzzy-if(Android,5,2800) == 506481-1.htm
 == 507487-1.html 507487-1-ref.html
 == 507487-2.xhtml 507487-2-ref.xhtml
 == 507762-1.html 507762-1-ref.html
 == 507762-2.html 507762-2-ref.html
 == 507762-3.html 507762-1-ref.html
 == 507762-4.html 507762-2-ref.html
 random-if(cocoaWidget||(gtkWidget&&webrender)||winWidget) == 508816-1.xul 508816-1-ref.xul # Bug 631982 and bug 1375012
 == 508816-2.html 508816-2-ref.html
-== 508908-1.xul 508908-1-ref.xul
+skip-if(isDebugBuild) == 508908-1.xul 508908-1-ref.xul
 == 508919-1.xhtml 508919-1-ref.xhtml
 == 509155-1.xhtml 509155-1-ref.xhtml
 fuzzy-if(Android,5,1656) fuzzy-if(skiaContent,1,1200) == 512410.html 512410-ref.html
 == 512631-1.html 512631-1-ref.html
 == 513153-1a.html 513153-1-ref.html
 == 513153-1b.html 513153-1-ref.html
 == 513153-2a.html 513153-2-ref.html
 == 513153-2b.html 513153-2-ref.html
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -367,17 +367,18 @@ include text-svgglyphs/reftest.list
 include text-transform/reftest.list
 
 # theme (osx)
 include ../../toolkit/themes/osx/reftests/reftest.list
 
 include ../../toolkit/content/tests/reftests/reftest.list
 
 # -moz-transform/
-include transform/reftest.list
+# skipping on non-e10s windows because of assertion in bug 1401228
+skip-if(winWidget&&!browserIsRemote) include transform/reftest.list
 
 # 3d transforms
 include transform-3d/reftest.list
 
 # unicode/ (verify that we don't do expend effort doing unicode-aware case checks)
 include unicode/reftest.list
 
 # usercss
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -351,16 +351,19 @@ class RemoteReftest(RefTest):
                                                       binary,
                                                       profile.profile,
                                                       cmdargs,
                                                       utilityPath=options.utilityPath,
                                                       xrePath=options.xrePath,
                                                       debuggerInfo=debuggerInfo,
                                                       symbolsPath=symbolsPath,
                                                       timeout=timeout)
+        if status == 1:
+            # when max run time exceeded, avoid restart
+            lastTestSeen = RefTest.TEST_SEEN_FINAL
         return status, lastTestSeen
 
     def cleanup(self, profileDir):
         # Pull results back from device
         if self.remoteLogFile and \
                 self._devicemanager.fileExists(self.remoteLogFile):
             self._devicemanager.getFile(self.remoteLogFile, self.localLogName)
         else:
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -424,41 +424,63 @@ class RefTest(object):
         Support --verify mode: Run test(s) many times in a variety of
         configurations/environments in an effort to find intermittent
         failures.
         """
 
         self._populate_logger(options)
 
         # Number of times to repeat test(s) when running with --repeat
-        VERIFY_REPEAT = 20
+        VERIFY_REPEAT = 10
         # Number of times to repeat test(s) when running test in separate browser
-        VERIFY_REPEAT_SINGLE_BROWSER = 10
+        VERIFY_REPEAT_SINGLE_BROWSER = 5
 
         def step1():
             stepOptions = copy.deepcopy(options)
             stepOptions.repeat = VERIFY_REPEAT
             stepOptions.runUntilFailure = True
             result = self.runTests(tests, stepOptions)
             return result
 
         def step2():
             stepOptions = copy.deepcopy(options)
             for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
                 result = self.runTests(tests, stepOptions)
                 if result != 0:
                     break
             return result
 
+        def step3():
+            stepOptions = copy.deepcopy(options)
+            stepOptions.repeat = VERIFY_REPEAT
+            stepOptions.runUntilFailure = True
+            stepOptions.environment.append("MOZ_CHAOSMODE=3")
+            result = self.runTests(tests, stepOptions)
+            return result
+
+        def step4():
+            stepOptions = copy.deepcopy(options)
+            stepOptions.environment.append("MOZ_CHAOSMODE=3")
+            for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
+                result = self.runTests(tests, stepOptions)
+                if result != 0:
+                    break
+            return result
+
         steps = [
             ("1. Run each test %d times in one browser." % VERIFY_REPEAT,
              step1),
             ("2. Run each test %d times in a new browser each time." %
              VERIFY_REPEAT_SINGLE_BROWSER,
              step2),
+            ("3. Run each test %d times in one browser, in chaos mode." % VERIFY_REPEAT,
+             step3),
+            ("4. Run each test %d times in a new browser each time, in chaos mode." %
+             VERIFY_REPEAT_SINGLE_BROWSER,
+             step4),
         ]
 
         stepResults = {}
         for (descr, step) in steps:
             stepResults[descr] = "not run / incomplete"
 
         startTime = datetime.now()
         maxTime = timedelta(seconds=options.verify_max_time)
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -479,20 +479,23 @@ public final class IntentHelper implemen
      * is present, we alert the user that we were unable to open the link.
      *
      * @param msg A message with the uri with no handlers as the value for the "uri" key
      * @param callback A callback that will be called with success & no params if Java loads a page, or with error and
      *                 the uri to load if Java does not load a page
      */
     private void openNoHandler(final GeckoBundle msg, final EventCallback callback) {
         final String uri = msg.getString("uri");
+        final GeckoBundle errorResponse = new GeckoBundle();
 
         if (TextUtils.isEmpty(uri)) {
             Log.w(LOGTAG, "Received empty URL - loading about:neterror");
-            callback.sendError(getUnknownProtocolErrorPageUri(""));
+            errorResponse.putString("uri", getUnknownProtocolErrorPageUri(""));
+            errorResponse.putBoolean("isFallback", false);
+            callback.sendError(errorResponse);
             return;
         }
 
         final Intent intent;
         try {
             // TODO (bug 1173626): This will not handle android-app uris on non 5.1 devices.
             intent = Intent.parseUri(uri, 0);
         } catch (final URISyntaxException e) {
@@ -500,27 +503,30 @@ public final class IntentHelper implemen
             try {
                 errorUri = getUnknownProtocolErrorPageUri(URLEncoder.encode(uri, "UTF-8"));
             } catch (final UnsupportedEncodingException encodingE) {
                 errorUri = getUnknownProtocolErrorPageUri("");
             }
 
             // Don't log the exception to prevent leaking URIs.
             Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror");
-            callback.sendError(errorUri);
+            errorResponse.putString("uri", errorUri);
+            errorResponse.putBoolean("isFallback", false);
+            callback.sendError(errorResponse);
             return;
         }
 
         // For this flow, we follow Chrome's lead:
         //   https://developer.chrome.com/multidevice/android/intents
         final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
         if (isFallbackUrlValid(fallbackUrl)) {
+            errorResponse.putString("uri", fallbackUrl);
+            errorResponse.putBoolean("isFallback", true);
             // Opens the page in JS.
-            callback.sendError(fallbackUrl);
-
+            callback.sendError(errorResponse);
         } else if (intent.getPackage() != null) {
             // Note on alternative flows: we could get the intent package from a component, however, for
             // security reasons, components are ignored when opening URIs (bug 1168998) so we should
             // ignore it here too.
             //
             // Our old flow used to prompt the user to search for their app in the market by scheme and
             // while this could help the user find a new app, there is not always a correlation in
             // scheme to application name and we could end up steering the user wrong (potentially to
@@ -547,17 +553,19 @@ public final class IntentHelper implemen
             // many websites have catered to this behavior. For example, the site might set a timeout and load a play
             // store url for their app if the intent link fails to load, i.e. the app is not installed.
             // These work-arounds would often end with our users seeing about:neterror instead of the intended experience.
             // While I feel showing about:neterror is a better solution for users (when not hacked around),
             // we should match the status quo for the good of our users.
             //
             // Don't log the URI to prevent leaking it.
             Log.w(LOGTAG, "Unable to open URI, maybe showing neterror");
-            callback.sendError(getUnknownProtocolErrorPageUri(intent.getData().toString()));
+            errorResponse.putString("uri", getUnknownProtocolErrorPageUri(intent.getData().toString()));
+            errorResponse.putBoolean("isFallback", false);
+            callback.sendError(errorResponse);
         }
     }
 
     private static boolean isFallbackUrlValid(@Nullable final String fallbackUrl) {
         if (fallbackUrl == null) {
             return false;
         }
 
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2730,17 +2730,17 @@ var NativeWindow = {
       return false;
     },
 
     /* Returns a label to be shown in a tabbed ui if there are multiple "contexts". For instance, if this
      * is an image inside an <a> tag, we may have a "link" context and an "image" one.
      */
     _getContextType: function(element) {
       // For anchor nodes, we try to use the scheme to pick a string
-      if (element instanceof Ci.nsIDOMHTMLAnchorElement) {
+      if (ChromeUtils.getClassName(element) === "HTMLAnchorElement") {
         let uri = this.makeURI(this._getLinkURL(element));
         try {
           return Strings.browser.GetStringFromName("browser.menu.context." + uri.scheme);
         } catch(ex) { }
       }
 
       // Otherwise we try the nodeName
       try {
@@ -2815,17 +2815,17 @@ var NativeWindow = {
       if (node.hasAttribute && node.hasAttribute("title")) {
         return node.getAttribute("title");
       }
       return this._getUrl(node);
     },
 
     // Returns a url associated with a node
     _getUrl: function(node) {
-      if ((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
+      if ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
           (node instanceof Ci.nsIDOMHTMLAreaElement && node.href)) {
         return this._getLinkURL(node);
       } else if (node instanceof Ci.nsIImageLoadingContent && node.currentURI) {
         // The image is blocked by Tap-to-load Images
         let originalURL = node.getAttribute("data-ctv-src");
         if (originalURL) {
           return originalURL;
         }
@@ -3046,17 +3046,17 @@ var NativeWindow = {
     },
 
     makeURI: function makeURI(aURL, aOriginCharset, aBaseURI) {
       return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
     },
 
     _getLink: function(aElement) {
       if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
-          ((aElement instanceof Ci.nsIDOMHTMLAnchorElement && aElement.href) ||
+          ((ChromeUtils.getClassName(aElement) === "HTMLAnchorElement" && aElement.href) ||
           (aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href) ||
           aElement instanceof Ci.nsIDOMHTMLLinkElement ||
           aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
         try {
           let url = this._getLinkURL(aElement);
           return Services.io.newURI(url);
         } catch (e) {}
       }
@@ -4770,17 +4770,17 @@ var BrowserEventHandler = {
                                                                                  null);
       } catch (e) {}
     }
     this._doTapHighlight(target);
   },
 
   _getLinkURI: function(aElement) {
     if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
-        ((aElement instanceof Ci.nsIDOMHTMLAnchorElement && aElement.href) ||
+        ((ChromeUtils.getClassName(aElement) === "HTMLAnchorElement" && aElement.href) ||
         (aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href))) {
       try {
         return Services.io.newURI(aElement.href);
       } catch (e) {}
     }
     return null;
   },
 
--- a/mobile/android/chrome/geckoview/geckoview.js
+++ b/mobile/android/chrome/geckoview/geckoview.js
@@ -59,13 +59,15 @@ function startup() {
   ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
                     "GeckoViewContent");
   ModuleManager.add("resource://gre/modules/GeckoViewProgress.jsm",
                     "GeckoViewProgress");
   ModuleManager.add("resource://gre/modules/GeckoViewScroll.jsm",
                     "GeckoViewScroll");
   ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
                     "GeckoViewTab");
+  ModuleManager.add("resource://gre/modules/GeckoViewRemoteDebugger.jsm",
+                    "GeckoViewRemoteDebugger");
 
   // Move focus to the content window at the end of startup,
   // so things like text selection can work properly.
   document.getElementById("content").focus();
 }
--- a/mobile/android/components/ContentDispatchChooser.js
+++ b/mobile/android/components/ContentDispatchChooser.js
@@ -60,24 +60,29 @@ ContentDispatchChooser.prototype =
 
       let msg = {
         type: "Intent:OpenNoHandler",
         uri: aURI.spec,
       };
 
       EventDispatcher.instance.sendRequestForResult(msg).then(() => {
         // Java opens an app on success: take no action.
-      }, (uri) => {
+      }, (data) => {
+        if (data.isFallback) {
+          // We always want to open a fallback url
+          window.location.href = data.uri;
+          return;
+        }
+
         // We couldn't open this. If this was from a click, it's likely that we just
         // want this to fail silently. If the user entered this on the address bar, though,
         // we want to show the neterror page.
-
         let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
         let millis = dwu.millisSinceLastUserInput;
         if (millis > 0 && millis >= 1000) {
-          window.location.href = uri;
+          window.location.href = data.uri;
         }
       });
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentDispatchChooser]);
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
@@ -491,16 +491,19 @@ public class GeckoView extends LayerView
         initializeView();
         mListener.registerListeners();
 
         if (settings == null) {
             mSettings = new GeckoViewSettings(getEventDispatcher());
         } else {
             mSettings = settings;
         }
+        mSettings.setString(GeckoViewSettings.DEBUGGER_SOCKET_DIR,
+                            context.getApplicationInfo().dataDir);
+
     }
 
     @Override
     protected Parcelable onSaveInstanceState() {
         final Parcelable superState = super.onSaveInstanceState();
         mStateSaved = true;
         return new StateBinder(superState, mWindow);
     }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
@@ -60,32 +60,40 @@ public final class GeckoViewSettings {
         new Key<Boolean>("useMultiprocess");
 
     /*
      * Key to specify which display-mode we should use
      */
     public static final Key<Integer> DISPLAY_MODE =
         new Key<Integer>("displayMode");
 
+    public static final Key<Boolean> USE_REMOTE_DEBUGGER =
+        new Key<Boolean>("useRemoteDebugger");
+
+    public static final Key<String> DEBUGGER_SOCKET_DIR =
+        new Key<String>("debuggerSocketDir");
 
     private final EventDispatcher mEventDispatcher;
     private final GeckoBundle mBundle;
 
     public GeckoViewSettings() {
         this(null);
     }
 
     /* package */ GeckoViewSettings(EventDispatcher eventDispatcher) {
         mEventDispatcher = eventDispatcher;
         mBundle = new GeckoBundle();
 
         setBoolean(USE_TRACKING_PROTECTION, false);
         setBoolean(USE_PRIVATE_MODE, false);
         setBoolean(USE_MULTIPROCESS, true);
         setInt(DISPLAY_MODE, DisplayMode.BROWSER.value());
+        setBoolean(USE_REMOTE_DEBUGGER, false);
+        // Set in GeckoView.init().
+        setString(DEBUGGER_SOCKET_DIR, "");
     }
 
     /* package */ GeckoViewSettings(GeckoViewSettings settings, EventDispatcher eventDispatcher) {
         mBundle = new GeckoBundle(settings.mBundle);
         mEventDispatcher = eventDispatcher;
     }
 
     public void setBoolean(final Key<Boolean> key, boolean value) {
@@ -117,16 +125,33 @@ public final class GeckoViewSettings {
     }
 
     public int getInt(final Key<Integer> key) {
         synchronized (mBundle) {
             return mBundle.getInt(key.text);
         }
     }
 
+    public void setString(final Key<String> key, final String value) {
+        synchronized (mBundle) {
+            final Object old = mBundle.get(key.text);
+            if (old != null && old.equals(value)) {
+                return;
+            }
+            mBundle.putString(key.text, value);
+        }
+        dispatchUpdate();
+    }
+
+    public String getString(final Key<String> key) {
+        synchronized (mBundle) {
+            return mBundle.getString(key.text);
+        }
+    }
+
     /* package */ GeckoBundle asBundle() {
         return mBundle;
     }
 
     private void dispatchUpdate() {
         if (mEventDispatcher != null) {
             mEventDispatcher.dispatch("GeckoView:UpdateSettings", null);
         }
--- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
+++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
@@ -21,16 +21,17 @@ import java.util.Locale;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.util.GeckoBundle;
 
 public class GeckoViewActivity extends Activity {
     private static final String LOGTAG = "GeckoViewActivity";
     private static final String DEFAULT_URL = "https://mozilla.org";
     private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
+    private static final String USE_REMOTE_DEBUGGER_EXTRA = "use_remote_debugger";
 
     /* package */ static final int REQUEST_FILE_PICKER = 1;
     private static final int REQUEST_PERMISSIONS = 2;
 
     private GeckoView mGeckoView;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -90,16 +91,19 @@ public class GeckoViewActivity extends A
         final Uri uri = intent.getData();
         mGeckoView.loadUri(uri != null ? uri.toString() : DEFAULT_URL);
     }
 
     private void loadSettings(final Intent intent) {
         mGeckoView.getSettings().setBoolean(
             GeckoViewSettings.USE_MULTIPROCESS,
             intent.getBooleanExtra(USE_MULTIPROCESS_EXTRA, true));
+        mGeckoView.getSettings().setBoolean(
+            GeckoViewSettings.USE_REMOTE_DEBUGGER,
+            intent.getBooleanExtra(USE_REMOTE_DEBUGGER_EXTRA, false));
     }
 
     @Override
     protected void onActivityResult(final int requestCode, final int resultCode,
                                     final Intent data) {
         if (requestCode == REQUEST_FILE_PICKER) {
             final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
                     mGeckoView.getPromptDelegate();
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -438,20 +438,18 @@
 @BINPATH@/components/extensions-toolkit.manifest
 @BINPATH@/components/extensions-mobile.manifest
 @BINPATH@/components/extension-process-script.js
 
 ; Features
 @BINPATH@/features/*
 
 ; DevTools
-#ifndef MOZ_GECKOVIEW_JAR
 @BINPATH@/chrome/devtools@JAREXT@
 @BINPATH@/chrome/devtools.manifest
-#endif
 
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
 @BINPATH@/@PREF_DIR@/mobile.js
 @BINPATH@/@PREF_DIR@/channel-prefs.js
 @BINPATH@/ua-update.json
 @BINPATH@/greprefs.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
new file mode 100644
--- /dev/null
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["GeckoViewRemoteDebugger"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/GeckoViewModule.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+  Cu.import("resource://gre/modules/AndroidLog.jsm", {})
+    .AndroidLog.d.bind(null, "ViewRemoteDebugger"));
+
+XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
+  const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+  const { DebuggerServer } = require("devtools/server/main");
+  return DebuggerServer;
+});
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
+class GeckoViewRemoteDebugger extends GeckoViewModule {
+  init() {
+    this._isEnabled = false;
+    this._usbDebugger = new USBRemoteDebugger();
+  }
+
+  onSettingsUpdate() {
+    let enabled = this.settings.useRemoteDebugger;
+
+    if (enabled && !this._isEnabled) {
+      this.register();
+    } else if (!enabled) {
+      this.unregister();
+    }
+  }
+
+  register() {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors("navigator:geckoview");
+      DebuggerServer.registerModule(
+        "resource://gre/modules/dbg-browser-actors.js");
+      DebuggerServer.allowChromeProcess = true;
+    }
+    this._isEnabled = true;
+    this._usbDebugger.stop();
+
+    let windowId = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIDOMWindowUtils)
+                              .outerWindowID;
+    let portOrPath = this.settings.debuggerSocketDir +
+                     "/firefox-debugger-socket-" +
+                     windowId;
+    this._usbDebugger.start(portOrPath);
+  }
+
+  unregister() {
+    this._isEnabled = false;
+    this._usbDebugger.stop();
+  }
+}
+
+class USBRemoteDebugger {
+  start(aPortOrPath) {
+    try {
+      let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
+      let authenticator = new AuthenticatorType.Server();
+      authenticator.allowConnection = this.allowConnection.bind(this);
+      this._listener = DebuggerServer.createListener();
+      this._listener.portOrPath = aPortOrPath;
+      this._listener.authenticator = authenticator;
+      this._listener.open();
+      debug(`USB remote debugger - listening on ${aPortOrPath}`);
+    } catch (e) {
+      debug("Unable to start USB debugger server: " + e);
+    }
+  }
+
+  stop() {
+    if (!this._listener) {
+      return;
+    }
+
+    try {
+      this._listener.close();
+      this._listener = null;
+    } catch (e) {
+      debug("Unable to stop USB debugger server: " + e);
+    }
+  }
+
+  allowConnection(aSession) {
+    if (!this._listener) {
+      return DebuggerServer.AuthenticationResult.DENY;
+    }
+
+    if (aSession.server.port) {
+      return DebuggerServer.AuthenticationResult.DENY;
+    }
+    return DebuggerServer.AuthenticationResult.ALLOW;
+  }
+}
--- a/mobile/android/modules/geckoview/GeckoViewTab.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewTab.jsm
@@ -17,19 +17,20 @@ XPCOMUtils.defineLazyGetter(this, "dump"
 
 function debug(aMsg) {
   // dump(aMsg);
 }
 
 // Stub BrowserApp implementation for WebExtensions support.
 class GeckoViewTab extends GeckoViewModule {
   init() {
-    this.browser.tab = { id: 0 };
+    this.browser.tab = { id: 0, browser: this.browser };
 
-    this.window.BrowserApp = {
+    this.window.gBrowser = this.window.BrowserApp = {
+      selectedBrowser: this.browser,
       tabs: [this.browser.tab],
       selectedTab: this.browser.tab,
 
       getTabForId: function(aId) {
         return this.selectedTab;
       },
 
       getTabForBrowser: function(aBrowser) {
--- a/mobile/android/modules/geckoview/moz.build
+++ b/mobile/android/modules/geckoview/moz.build
@@ -6,14 +6,15 @@
 
 EXTRA_JS_MODULES += [
     'AndroidLog.jsm',
     'GeckoViewContent.jsm',
     'GeckoViewContentModule.jsm',
     'GeckoViewModule.jsm',
     'GeckoViewNavigation.jsm',
     'GeckoViewProgress.jsm',
+    'GeckoViewRemoteDebugger.jsm',
     'GeckoViewScroll.jsm',
     'GeckoViewSettings.jsm',
     'GeckoViewTab.jsm',
     'GeckoViewUtils.jsm',
     'Messaging.jsm',
 ]
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -875,16 +875,17 @@ pref("gfx.webrender.force-angle", true);
 
 pref("gfx.webrender.highlight-painted-layers", false);
 pref("gfx.webrender.layers-free", true);
 pref("gfx.webrender.blob-images", false);
 
 // WebRender debugging utilities.
 pref("gfx.webrender.debug.texture-cache", false);
 pref("gfx.webrender.debug.render-targets", false);
+pref("gfx.webrender.debug.alpha-primitives", false);
 pref("gfx.webrender.debug.profiler", false);
 
 // Whether webrender should be used as much as possible.
 pref("gfx.webrendest.enabled", false);
 
 pref("accessibility.browsewithcaret", false);
 pref("accessibility.warn_on_browsewithcaret", true);
 
@@ -5070,22 +5071,16 @@ pref("dom.vibrator.max_vibrate_ms", 1000
 pref("dom.vibrator.max_vibrate_list_len", 128);
 
 // Battery API
 pref("dom.battery.enabled", true);
 
 // Streams API
 pref("dom.streams.enabled", false);
 
-// Abort API
-pref("dom.abortController.enabled", true);
-
-// Fetch + Abort API
-pref("dom.abortController.fetch.enabled", true);
-
 // Push
 
 pref("dom.push.enabled", false);
 
 pref("dom.push.loglevel", "error");
 
 pref("dom.push.serverURL", "wss://push.services.mozilla.com/");
 pref("dom.push.userAgentID", "");
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -2321,19 +2321,19 @@ toolbar#nav-bar {
     def verifyTests(self, options):
         """
         Support --verify mode: Run test(s) many times in a variety of
         configurations/environments in an effort to find intermittent
         failures.
         """
 
         # Number of times to repeat test(s) when running with --repeat
-        VERIFY_REPEAT = 20
+        VERIFY_REPEAT = 10
         # Number of times to repeat test(s) when running test in
-        VERIFY_REPEAT_SINGLE_BROWSER = 10
+        VERIFY_REPEAT_SINGLE_BROWSER = 5
 
         def step1():
             stepOptions = copy.deepcopy(options)
             stepOptions.repeat = VERIFY_REPEAT
             stepOptions.keep_open = False
             stepOptions.runUntilFailure = True
             result = self.runTests(stepOptions)
             result = result or (-2 if self.countfail > 0 else 0)
@@ -2347,22 +2347,51 @@ toolbar#nav-bar {
             for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
                 result = self.runTests(stepOptions)
                 result = result or (-2 if self.countfail > 0 else 0)
                 self.message_logger.finish()
                 if result != 0:
                     break
             return result
 
+        def step3():
+            stepOptions = copy.deepcopy(options)
+            stepOptions.repeat = VERIFY_REPEAT
+            stepOptions.keep_open = False
+            stepOptions.environment.append("MOZ_CHAOSMODE=3")
+            result = self.runTests(stepOptions)
+            result = result or (-2 if self.countfail > 0 else 0)
+            self.message_logger.finish()
+            return result
+
+        def step4():
+            stepOptions = copy.deepcopy(options)
+            stepOptions.repeat = 0
+            stepOptions.keep_open = False
+            stepOptions.environment.append("MOZ_CHAOSMODE=3")
+            for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
+                result = self.runTests(stepOptions)
+                result = result or (-2 if self.countfail > 0 else 0)
+                self.message_logger.finish()
+                if result != 0:
+                    break
+            return result
+
         steps = [
             ("1. Run each test %d times in one browser." % VERIFY_REPEAT,
              step1),
             ("2. Run each test %d times in a new browser each time." %
              VERIFY_REPEAT_SINGLE_BROWSER,
              step2),
+            ("3. Run each test %d times in one browser, in chaos mode." %
+             VERIFY_REPEAT,
+             step3),
+            ("4. Run each test %d times in a new browser each time, "
+             "in chaos mode." % VERIFY_REPEAT_SINGLE_BROWSER,
+             step4),
         ]
 
         stepResults = {}
         for (descr, step) in steps:
             stepResults[descr] = "not run / incomplete"
 
         startTime = datetime.now()
         maxTime = timedelta(seconds=options.verify_max_time)
--- a/testing/talos/talos/cmdline.py
+++ b/testing/talos/talos/cmdline.py
@@ -96,18 +96,18 @@ def create_parser(mach_interface=False):
                  "many samples to take with the profiler")
     add_arg('--geckoProfile', action="store_true", dest="gecko_profile",
             help="Profile the run and output the results in $MOZ_UPLOAD_DIR.")
     add_arg('--geckoProfileInterval', dest='gecko_profile_interval', type=float,
             help="How frequently to take samples (ms)")
     add_arg('--geckoProfileEntries', dest="gecko_profile_entries", type=int,
             help="How many samples to take with the profiler")
     add_arg('--extension', dest='extensions', action='append',
-            default=['${talos}/talos-powers/talos-powers-signed.xpi',
-                     '${talos}/pageloader/pageloader-signed.xpi'],
+            default=['${talos}/talos-powers',
+                     '${talos}/pageloader'],
             help="Extension to install while running")
     add_arg('--fast', action='store_true',
             help="Run tp tests as tp_fast")
     add_arg('--symbolsPath', dest='symbols_path',
             help="Path to the symbols for the build we are testing")
     add_arg('--xperf_path',
             help="Path to windows performance tool xperf.exe")
     add_arg('--test_timeout', type=int, default=1200,
--- a/testing/talos/talos/config.py
+++ b/testing/talos/talos/config.py
@@ -189,17 +189,19 @@ DEFAULTS = dict(
         'lightweightThemes.selectedThemeID': "",
         'devtools.chrome.enabled': False,
         'devtools.debugger.remote-enabled': False,
         'devtools.theme': "light",
         'devtools.timeline.enabled': False,
         'identity.fxaccounts.migrateToDevEdition': False,
         'plugin.state.flash': 0,
         'media.libavcodec.allow-obsolete': True,
-        'extensions.legacy.enabled': True
+        'extensions.legacy.enabled': True,
+        'xpinstall.signatures.required': False,
+        'extensions.allow-non-mpc-extensions': True
     }
 )
 
 
 # keys to generated self.config that are global overrides to tests
 GLOBAL_OVERRIDES = (
     'cycles',
     'gecko_profile',
--- a/testing/talos/talos/ffsetup.py
+++ b/testing/talos/talos/ffsetup.py
@@ -87,20 +87,16 @@ class FFSetup(object):
             if type(value) is str:
                 value = utils.interpolate(value, webserver=webserver)
                 preferences[name] = value
 
         extensions = self.browser_config['extensions'][:]
         if self.test_config.get('extensions'):
             extensions.append(self.test_config['extensions'])
 
-        if self.browser_config['develop'] or \
-           'try' in str.lower(self.browser_config['branch_name']):
-            extensions = [os.path.dirname(i) for i in extensions]
-
         profile = Profile.clone(
             os.path.normpath(self.test_config['profile_path']),
             self.profile_dir,
             restore=False)
 
         profile.set_preferences(preferences)
 
         # installing addons
--- a/testing/talos/talos/run_tests.py
+++ b/testing/talos/talos/run_tests.py
@@ -112,22 +112,16 @@ def run_tests(config, browser_config):
         test['cleanup'] = utils.interpolate(test['cleanup'])
 
     # pass --no-remote to firefox launch, if --develop is specified
     # we do that to allow locally the user to have another running firefox
     # instance
     if browser_config['develop']:
         browser_config['extra_args'] = '--no-remote'
 
-    # with addon signing for production talos, we want to develop without it
-    if browser_config['develop'] or 'try' in str.lower(browser_config['branch_name']):
-        browser_config['preferences']['xpinstall.signatures.required'] = False
-
-    browser_config['preferences']['extensions.allow-non-mpc-extensions'] = True
-
     # if using firstNonBlankPaint, must turn on pref for it
     if test.get('fnbpaint', False):
         LOG.info("Using firstNonBlankPaint, so turning on pref for it")
         browser_config['preferences']['dom.performance.time_to_non_blank_paint.enabled'] = True
 
     # set defaults
     testdate = config.get('testdate', '')
 
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -161,17 +161,17 @@ class sessionrestore(TsBase):
     """
     A start up test measuring the time it takes to load a sessionstore.js file.
 
     1. Set up Firefox to restore from a given sessionstore.js file.
     2. Launch Firefox.
     3. Measure the delta between firstPaint and sessionRestored.
     """
     extensions = \
-        '${talos}/startup_test/sessionrestore/addon/sessionrestore-signed.xpi'
+        '${talos}/startup_test/sessionrestore/addon'
     cycles = 10
     timeout = 900
     gecko_profile_startup = True
     gecko_profile_entries = 10000000
     profile_path = '${talos}/startup_test/sessionrestore/profile'
     shutdown = False
     reinstall = ['sessionstore.jsonlz4', 'sessionstore.js', 'sessionCheckpoints.json']
     # Restore the session. We have to provide a URL, otherwise Talos
@@ -205,17 +205,17 @@ class sessionrestore_many_windows(sessio
     profile_path = '${talos}/startup_test/sessionrestore/profile-manywindows'
 
 
 @register_test()
 class tresize(TsBase):
     """
     This test does some resize thing.
     """
-    extensions = '${talos}/startup_test/tresize/addon/tresize-signed.xpi'
+    extensions = '${talos}/startup_test/tresize/addon'
     cycles = 20
     url = 'startup_test/tresize/addon/content/tresize-test.html'
     timeout = 150
     gecko_profile_interval = 2
     gecko_profile_entries = 1000000
     tpmozafterpaint = True
     filters = filter.ignore_first.prepare(5) + filter.median.prepare()
     unit = 'ms'
@@ -282,17 +282,17 @@ class tpaint(PageloaderTest):
 
 
 @register_test()
 class tabpaint(PageloaderTest):
     """
     Tests the amount of time it takes to open new tabs, triggered from
     both the parent process and the content process.
     """
-    extensions = '${talos}/tests/tabpaint/tabpaint-signed.xpi'
+    extensions = '${talos}/tests/tabpaint'
     tpmanifest = '${talos}/tests/tabpaint/tabpaint.manifest'
     tppagecycles = 20
     gecko_profile_entries = 1000000
     tploadnocache = True
     unit = 'ms'
     preferences = {
         # By default, Talos is configured to open links from
         # content in new windows. We're overriding them so that
@@ -304,17 +304,17 @@ class tabpaint(PageloaderTest):
     }
 
 
 @register_test()
 class tps(PageloaderTest):
     """
     Tests the amount of time it takes to switch between tabs
     """
-    extensions = '${talos}/tests/tabswitch/tabswitch-signed.xpi'
+    extensions = '${talos}/tests/tabswitch'
     tpmanifest = '${talos}/tests/tabswitch/tps.manifest'
     tppagecycles = 5
     gecko_profile_entries = 5000000
     tploadnocache = True
     preferences = {
         'addon.test.tabswitch.urlfile': os.path.join('${talos}',
                                                      'tests',
                                                      'tp5o.html'),
@@ -343,17 +343,17 @@ class tart(PageloaderTest):
       (favicon and long title).
     - Each animation produces 3 test results:
       - error: difference between the designated duration and the actual
         completion duration from the trigger.
       - half: average interval over the 2nd half of the animation.
       - all: average interval over all recorded intervals.
     """
     tpmanifest = '${talos}/tests/tart/tart.manifest'
-    extensions = '${talos}/tests/tart/addon/tart-signed.xpi'
+    extensions = '${talos}/tests/tart/addon'
     tpcycles = 1
     tppagecycles = 25
     tploadnocache = True
     tpmozafterpaint = False
     gecko_profile_interval = 10
     gecko_profile_entries = 1000000
     win_counters = w7_counters = linux_counters = mac_counters = None
     """
@@ -380,17 +380,17 @@ class cart(PageloaderTest):
     All comments for TART also apply here (e.g. for ASAP+OMTC, etc)
     Subtests are:
     1-customize-enter - from triggering customize mode until it's ready for
     the user
     2-customize-exit  - exiting customize
     3-customize-enter-css - only the CSS animation part of entering customize
     """
     tpmanifest = '${talos}/tests/tart/cart.manifest'
-    extensions = '${talos}/tests/tart/addon/tart-signed.xpi'
+    extensions = '${talos}/tests/tart/addon'
     tpcycles = 1
     tppagecycles = 25
     tploadnocache = True
     tpmozafterpaint = False
     gecko_profile_interval = 1
     gecko_profile_entries = 10000000
     win_counters = w7_counters = linux_counters = mac_counters = None
     """
@@ -406,17 +406,17 @@ class cart(PageloaderTest):
 @register_test()
 class damp(PageloaderTest):
     """
     Devtools At Maximum Performance
     Tests the speed of DevTools toolbox open, close, and page reload
     for each tool, across a very simple and very complicated page.
     """
     tpmanifest = '${talos}/tests/devtools/damp.manifest'
-    extensions = '${talos}/tests/devtools/addon/devtools-signed.xpi'
+    extensions = '${talos}/tests/devtools/addon'
     cycles = 5
     tpcycles = 1
     tppagecycles = 5
     tploadnocache = True
     tpmozafterpaint = False
     gecko_profile_interval = 10
     gecko_profile_entries = 1000000
     win_counters = w7_counters = linux_counters = mac_counters = None
--- a/testing/web-platform/mach_commands.py
+++ b/testing/web-platform/mach_commands.py
@@ -274,17 +274,17 @@ testing/web-platform/tests for tests tha
         if editor:
             if ref_path:
                 path = "%s %s" % (path, ref_path)
             proc = subprocess.Popen("%s %s" % (editor, path), shell=True)
 
         if proc:
             proc.wait()
 
-        context.commands.dispatch("wpt-manifest-update", context, {"check_clean": False, "rebuild": False})
+        context.commands.dispatch("wpt-manifest-update", context)
 
 
 class WPTManifestUpdater(MozbuildObject):
     def run_update(self, check_clean=False, rebuild=False, **kwargs):
         import manifestupdate
         from wptrunner import wptlogging
         logger = wptlogging.setup(kwargs, {"mach": sys.stdout})
         wpt_dir = os.path.abspath(os.path.join(self.topsrcdir, 'testing', 'web-platform'))
deleted file mode 100644
--- a/testing/web-platform/meta/dom/__dir__.ini
+++ /dev/null
@@ -1,1 +0,0 @@
-prefs: [dom.abortController.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/dom/abort/__dir__.ini
+++ /dev/null
@@ -1,1 +0,0 @@
-prefs: [dom.abortController.enabled:true]
--- a/testing/web-platform/meta/fetch/api/abort/__dir__.ini
+++ b/testing/web-platform/meta/fetch/api/abort/__dir__.ini
@@ -1,4 +1,2 @@
 prefs: [javascript.options.streams:true,
-        dom.abortController.enabled:true,
-        dom.abortController.fetch.enabled:true,
         dom.streams.enabled:true]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/browsers/windows/browsing-context-names/choose-_blank-003.html.ini
@@ -0,0 +1,4 @@
+[choose-_blank-003.html]
+  type: testharness
+  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1374133
+
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -1166,17 +1166,17 @@ class XPCShellTests(object):
     def runTests(self, options, testClass=XPCShellTestThread, mobileArgs=None):
         """
           Run xpcshell tests.
         """
 
         global gotSIGINT
 
         # Number of times to repeat test(s) in --verify mode
-        VERIFY_REPEAT = 20
+        VERIFY_REPEAT = 10
 
         if isinstance(options, Namespace):
             options = vars(options)
 
         # Try to guess modules directory.
         # This somewhat grotesque hack allows the buildbot machines to find the
         # modules directory without having to configure the buildbot hosts. This
         # code path should never be executed in local runs because the build system
@@ -1398,19 +1398,34 @@ class XPCShellTests(object):
                     self.testCount += 1
                     test = testClass(test_object, retry=False,
                                      mobileArgs=mobileArgs, **kwargs)
                     sequential_tests.append(test)
                 status = self.runTestList(tests_queue, sequential_tests,
                                           testClass, mobileArgs, **kwargs)
                 return status
 
+            def step2():
+                # Run tests sequentially, with MOZ_CHAOSMODE enabled.
+                sequential_tests = []
+                self.env["MOZ_CHAOSMODE"] = "3"
+                for i in xrange(VERIFY_REPEAT):
+                    self.testCount += 1
+                    test = testClass(test_object, retry=False,
+                                     mobileArgs=mobileArgs, **kwargs)
+                    sequential_tests.append(test)
+                status = self.runTestList(tests_queue, sequential_tests,
+                                          testClass, mobileArgs, **kwargs)
+                return status
+
             steps = [
                 ("1. Run each test %d times, sequentially." % VERIFY_REPEAT,
                  step1),
+                ("2. Run each test %d times, sequentially, in chaos mode." % VERIFY_REPEAT,
+                 step2),
             ]
             startTime = datetime.now()
             maxTime = timedelta(seconds=options['verifyMaxTime'])
             for test_object in self.alltests:
                 stepResults = {}
                 for (descr, step) in steps:
                     stepResults[descr] = "not run / incomplete"
                 finalResult = "PASSED"
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/docs/data/first-shutdown-ping.rst
@@ -0,0 +1,10 @@
+
+"first-shutdown" ping
+==================
+
+This ping is a duplicate of the main-ping sent on first shutdown. Enabling pingsender
+for first sessions will impact existing engagment metrics. The ``first-shutdown`` ping enables a
+more accurate view of users that churn after the first session. This ping exists as a
+stopgap until existing metrics are re-evaluated for use first session ``main-pings``.
+
+See :doc:`main-ping` for details about this payload.
deleted file mode 100644
--- a/toolkit/components/telemetry/docs/data/first-shutdown.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-"first-shutdown" ping
-==================
-
-This ping is a duplicate of the main-ping sent on first shutdown. Enabling pingsender
-for first sessions will impact existing engagment metrics. The ``first-shutdown`` ping enables a
-more accurate view of users that churn after the first session. This ping exists as a
-stopgap until existing metrics are re-evaluated for use first session ``main-pings``.
-
-See :doc:`main-ping` for details about this payload.
--- a/toolkit/components/telemetry/docs/data/index.rst
+++ b/toolkit/components/telemetry/docs/data/index.rst
@@ -9,11 +9,12 @@ Data documentation
 
    common-ping
    environment
    main-ping
    deletion-ping
    crash-ping
    backgroundhangmonitor-ping
    anonymous-ping
+   first-shutdown-ping
    *-ping
 
 The `mozilla-pipeline-schemas repository <https://github.com/mozilla-services/mozilla-pipeline-schemas/>`_ contains schemas for some of the pings.
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -40,17 +40,16 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMFileList.h"
 #include "nsIDOMFocusEvent.h"
 #include "nsIDOMFormData.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDOMHistory.h"
-#include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLButtonElement.h"
 #include "nsIDOMHTMLCanvasElement.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
@@ -316,17 +315,16 @@ const ComponentsInterfaceShimEntry kComp
   DEFINE_SHIM(Event),
   DEFINE_SHIM(EventTarget),
   DEFINE_SHIM(FileList),
   DEFINE_SHIM(FocusEvent),
   DEFINE_SHIM(FormData),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIFrameLoader, FrameLoader),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError),
   DEFINE_SHIM(History),
-  DEFINE_SHIM(HTMLAnchorElement),
   DEFINE_SHIM(HTMLAreaElement),
   DEFINE_SHIM(HTMLBaseElement),
   DEFINE_SHIM(HTMLButtonElement),
   DEFINE_SHIM(HTMLCanvasElement),
   DEFINE_SHIM(HTMLCollection),
   DEFINE_SHIM(HTMLDocument),
   DEFINE_SHIM(HTMLElement),
   DEFINE_SHIM(HTMLFormElement),