Merge mozilla-central to autoland. a=merge CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Tue, 13 Mar 2018 01:16:04 +0200
changeset 766796 a29e28df0a142521b8520ce645bfb4c5339b7367
parent 766795 f505a9fa69d180fd8562404c402330b12fa85d86 (current diff)
parent 766552 0ac3698a74a7b1a742682b8e704f1f418df827ed (diff)
child 766797 1187ae9020bef4e101696883feb3b41ffb8724db
push id102399
push userbmo:mratcliffe@mozilla.com
push dateTue, 13 Mar 2018 10:12:19 +0000
reviewersmerge
milestone61.0a1
Merge mozilla-central to autoland. a=merge CLOSED TREE
browser/base/content/tabbrowser.js
devtools/client/aboutdebugging/modules/worker.js
devtools/client/aboutdebugging/test/browser_addons_debug_bootstrapped.js
devtools/client/aboutdebugging/test/browser_addons_debug_webextension.js
devtools/client/aboutdebugging/test/browser_addons_debug_webextension_inspector.js
devtools/client/aboutdebugging/test/browser_addons_debug_webextension_nobg.js
devtools/client/aboutdebugging/test/browser_addons_debug_webextension_popup.js
devtools/client/aboutdebugging/test/browser_service_workers_push.js
devtools/client/aboutdebugging/test/browser_service_workers_push_service.js
devtools/client/aboutdebugging/test/browser_service_workers_timeout.js
devtools/client/aboutdebugging/test/head.js
devtools/client/dom/dom-panel.js
devtools/client/framework/devtools.js
devtools/client/framework/toolbox-highlighter-utils.js
devtools/client/framework/toolbox-options.js
devtools/client/framework/toolbox.js
devtools/client/inspector/boxmodel/components/BoxModelApp.js
devtools/client/inspector/boxmodel/test/browser_boxmodel_guides.js
devtools/client/inspector/boxmodel/test/head.js
devtools/client/inspector/computed/computed.js
devtools/client/inspector/test/shared-head.js
devtools/client/jsonview/test/browser_jsonview_content_type.js
devtools/client/jsonview/test/browser_jsonview_save_json.js
devtools/client/memory/actions/allocations.js
devtools/client/memory/actions/census-display.js
devtools/client/memory/actions/diffing.js
devtools/client/memory/actions/io.js
devtools/client/memory/actions/label-display.js
devtools/client/memory/actions/refresh.js
devtools/client/memory/actions/snapshot.js
devtools/client/memory/actions/task-cache.js
devtools/client/memory/actions/tree-map-display.js
devtools/client/memory/actions/view.js
devtools/client/memory/test/browser/browser_memory_tree_map-01.js
devtools/client/memory/test/browser/head.js
devtools/client/memory/test/chrome/head.js
devtools/client/memory/test/unit/head.js
devtools/client/memory/test/unit/test_action-clear-snapshots_05.js
devtools/client/netmonitor/test/browser_net_view-source-debugger.js
devtools/client/performance/components/jit-optimizations.js
devtools/client/performance/modules/widgets/graphs.js
devtools/client/performance/panel.js
devtools/client/performance/performance-controller.js
devtools/client/performance/performance-view.js
devtools/client/performance/test/helpers/profiler-mm-utils.js
devtools/client/performance/test/helpers/tab-utils.js
devtools/client/performance/test/helpers/wait-utils.js
devtools/client/performance/views/details-abstract-subview.js
devtools/client/performance/views/details-js-flamegraph.js
devtools/client/performance/views/details-memory-flamegraph.js
devtools/client/performance/views/details.js
devtools/client/performance/views/overview.js
devtools/client/performance/views/recordings.js
devtools/client/performance/views/toolbar.js
devtools/client/shared/components/VirtualizedTree.js
devtools/client/shared/components/test/mochitest/test_stack-trace.html
devtools/client/shared/developer-toolbar.js
devtools/client/shared/test/browser_css_color.js
devtools/client/shared/test/browser_filter-editor-08.js
devtools/client/shared/test/browser_filter-editor-09.js
devtools/client/shared/test/browser_filter-editor-10.js
devtools/client/shared/test/browser_inplace-editor-01.js
devtools/client/shared/test/browser_inplace-editor-02.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_css_variable.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
devtools/client/shared/test/browser_key_shortcuts.js
devtools/client/shared/test/browser_outputparser.js
devtools/client/shared/test/browser_poller.js
devtools/client/shared/test/browser_tableWidget_keyboard_interaction.js
devtools/client/shared/test/browser_tableWidget_mouse_interaction.js
devtools/client/shared/test/browser_telemetry_button_paintflashing.js
devtools/client/shared/test/browser_telemetry_button_responsive.js
devtools/client/shared/test/browser_telemetry_button_scratchpad.js
devtools/client/shared/test/browser_telemetry_sidebar.js
devtools/client/shared/test/browser_templater_basic.js
devtools/client/shared/test/browser_toolbar_tooltip.js
devtools/client/shared/test/frame-script-utils.js
devtools/client/shared/test/head.js
devtools/client/shared/test/shared-head.js
devtools/client/shared/test/test-actor-registry.js
devtools/client/shared/test/test-actor.js
devtools/client/shared/widgets/ColorWidget.js
devtools/client/shared/widgets/FlameGraph.js
devtools/client/shared/widgets/Graphs.js
devtools/client/shared/widgets/LineGraphWidget.js
devtools/client/shared/widgets/tooltip/HTMLTooltip.js
devtools/client/shared/widgets/tooltip/TooltipToggle.js
devtools/client/sourceeditor/test/browser_editor_find_again.js
devtools/client/storage/test/browser_storage_dynamic_updates_localStorage.js
devtools/client/storage/test/browser_storage_dynamic_updates_sessionStorage.js
devtools/client/storage/test/browser_storage_overflow.js
devtools/client/storage/test/head.js
devtools/client/styleeditor/StyleEditorUI.jsm
devtools/client/styleeditor/StyleSheetEditor.jsm
devtools/client/styleeditor/styleeditor-panel.js
devtools/client/styleeditor/test/browser_styleeditor_bug_740541_iframes.js
devtools/client/styleeditor/test/browser_styleeditor_bug_851132_middle_click.js
devtools/client/styleeditor/test/browser_styleeditor_filesave.js
devtools/client/styleeditor/test/browser_styleeditor_highlight-selector.js
devtools/client/styleeditor/test/browser_styleeditor_import.js
devtools/client/styleeditor/test/browser_styleeditor_inline_friendly_names.js
devtools/client/styleeditor/test/browser_styleeditor_new.js
devtools/client/styleeditor/test/browser_styleeditor_opentab.js
devtools/client/styleeditor/test/browser_styleeditor_private_perwindowpb.js
devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
devtools/client/styleeditor/test/browser_styleeditor_sv_keynav.js
devtools/client/styleeditor/test/browser_styleeditor_syncIntoRuleView.js
devtools/client/styleeditor/test/head.js
devtools/client/webconsole/console-output.js
devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/head.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_console_table.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_init.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_loglimit.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_message_categories.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_object_inspector_while_debugging_and_inspecting.js
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_optimized_out_vars.js
devtools/server/actors/accessibility.js
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsarrayinlines.h
js/src/jsbool.cpp
js/src/jsbool.h
js/src/jsboolinlines.h
toolkit/modules/debug.js
--- a/.hgtags
+++ b/.hgtags
@@ -135,8 +135,9 @@ 6583496f169cd8a13c531ed16e98e8bf313eda8e
 f9605772a0c9098ed1bcaa98089b2c944ed69e9b FIREFOX_BETA_55_BASE
 320642944e42a889db13c6c55b404e32319d4de6 FIREFOX_BETA_56_BASE
 8e818b5e9b6bef0fc1a5c527ecf30b0d56a02f14 FIREFOX_BETA_57_BASE
 f7e9777221a34f9f23c2e4933307eb38b621b679 FIREFOX_NIGHTLY_57_END
 40a14ca1cf04499f398e4cb8ba359b39eae4e216 FIREFOX_BETA_58_BASE
 1f91961bb79ad06fd4caef9e5dfd546afd5bf42c FIREFOX_NIGHTLY_58_END
 5faab9e619901b1513fd4ca137747231be550def FIREFOX_NIGHTLY_59_END
 e33efdb3e1517d521deb949de3fcd6d9946ea440 FIREFOX_BETA_60_BASE
+fdd1a0082c71673239fc2f3a6a93de889c07a1be FIREFOX_NIGHTLY_60_END
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1443983: Removing addoncompat.manifest requires clobber.
+Merge day clobber
\ No newline at end of file
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -33,18 +33,16 @@
 
            Explore -> ExploreEnd       (v)
 ******************************************************************************/
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GestureSettings", "GestureTracker"]; // jshint ignore:line
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
 ChromeUtils.defineModuleGetter(this, "Utils", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Logger", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "setTimeout", // jshint ignore:line
   "resource://gre/modules/Timer.jsm");
 ChromeUtils.defineModuleGetter(this, "clearTimeout", // jshint ignore:line
   "resource://gre/modules/Timer.jsm");
--- a/accessible/jsat/OutputGenerator.jsm
+++ b/accessible/jsat/OutputGenerator.jsm
@@ -10,17 +10,16 @@ const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_VALUE = 0x04;
 const NAME_FROM_SUBTREE_RULE = 0x10;
 const IGNORE_EXPLICIT_NAME = 0x20;
 
 const OUTPUT_DESC_FIRST = 0;
 const OUTPUT_DESC_LAST = 1;
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "Utils", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "PrefCache", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Logger", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Roles", // jshint ignore:line
   "resource://gre/modules/accessibility/Constants.jsm");
--- a/accessible/jsat/PointerAdapter.jsm
+++ b/accessible/jsat/PointerAdapter.jsm
@@ -3,18 +3,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* exported PointerRelay, PointerAdapter */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["PointerRelay", "PointerAdapter"]; // jshint ignore:line
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
 ChromeUtils.defineModuleGetter(this, "Utils", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Logger", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "GestureSettings", // jshint ignore:line
   "resource://gre/modules/accessibility/Gestures.jsm");
 ChromeUtils.defineModuleGetter(this, "GestureTracker", // jshint ignore:line
   "resource://gre/modules/accessibility/Gestures.jsm");
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -1,17 +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/. */
 
 /* exported Presentation */
 
 "use strict";
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Logger", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "PivotContext", // jshint ignore:line
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "UtteranceGenerator", // jshint ignore:line
   "resource://gre/modules/accessibility/OutputGenerator.jsm");
 ChromeUtils.defineModuleGetter(this, "BrailleGenerator", // jshint ignore:line
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -1,15 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env mozilla/frame-script */
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "Logger",
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "Presentation",
   "resource://gre/modules/accessibility/Presentation.jsm");
 ChromeUtils.defineModuleGetter(this, "Utils",
   "resource://gre/modules/accessibility/Utils.jsm");
 ChromeUtils.defineModuleGetter(this, "EventManager",
   "resource://gre/modules/accessibility/EventManager.jsm");
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -2674,17 +2674,17 @@ window._gBrowser = {
 
     aTab.style.maxWidth = ""; // ensure that fade-out transition happens
     aTab.removeAttribute("fadein");
     aTab.removeAttribute("bursting");
 
     setTimeout(function(tab, tabbrowser) {
       if (tab.parentNode &&
           window.getComputedStyle(tab).maxWidth == "0.1px") {
-        NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
+        console.assert(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
         tabbrowser._endRemoveTab(tab);
       }
     }, 3000, aTab, this);
   },
 
   _hasBeforeUnload(aTab) {
     let browser = aTab.linkedBrowser;
     return browser.isRemoteBrowser && browser.frameLoader &&
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -23,17 +23,16 @@ const blacklist = {
     "TelemetryStartup.js",
   ]),
   modules: new Set([
     "resource:///modules/ContentWebRTC.jsm",
     "resource://gre/modules/InlineSpellChecker.jsm",
     "resource://gre/modules/InlineSpellCheckerContent.jsm",
     "resource://gre/modules/Promise.jsm",
     "resource://gre/modules/Task.jsm",
-    "resource://gre/modules/debug.js",
     "resource://gre/modules/osfile.jsm",
   ]),
   services: new Set([
     "@mozilla.org/base/telemetry-startup;1",
     "@mozilla.org/push/Service;1",
   ])
 };
 
--- a/browser/components/downloads/DownloadsTaskbar.jsm
+++ b/browser/components/downloads/DownloadsTaskbar.jsm
@@ -35,16 +35,22 @@ XPCOMUtils.defineLazyGetter(this, "gWinT
 });
 
 XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function() {
   return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
          Cc["@mozilla.org/widget/macdocksupport;1"]
            .getService(Ci.nsITaskbarProgress);
 });
 
+XPCOMUtils.defineLazyGetter(this, "gGtkTaskbarProgress", function() {
+  return ("@mozilla.org/widget/taskbarprogress/gtk;1" in Cc) &&
+         Cc["@mozilla.org/widget/taskbarprogress/gtk;1"]
+           .getService(Ci.nsIGtkTaskbarProgress);
+});
+
 // DownloadsTaskbar
 
 /**
  * Handles the download progress indicator in the taskbar.
  */
 var DownloadsTaskbar = {
   /**
    * Underlying DownloadSummary providing the aggregate download information, or
@@ -84,16 +90,20 @@ var DownloadsTaskbar = {
         Services.obs.addObserver(() => {
           this._taskbarProgress = null;
           gMacTaskbarProgress = null;
         }, "quit-application-granted");
       } else if (gWinTaskbar) {
         // On Windows, the indicator is currently hidden because we have no
         // previous browser window, thus we should attach the indicator now.
         this._attachIndicator(aBrowserWindow);
+      } else if (gGtkTaskbarProgress) {
+        this._taskbarProgress = gGtkTaskbarProgress;
+
+        this._attachGtkTaskbarProgress(aBrowserWindow);
       } else {
         // The taskbar indicator is not available on this platform.
         return;
       }
     }
 
     // Ensure that the DownloadSummary object will be created asynchronously.
     if (!this._summary) {
@@ -138,16 +148,45 @@ var DownloadsTaskbar = {
         // The last browser window has been closed.  We remove the reference to
         // the taskbar progress object so that the indicator will be registered
         // again on the next browser window that is opened.
         this._taskbarProgress = null;
       }
     });
   },
 
+  /**
+   * In gtk3, the window itself implements the progress interface.
+   */
+  _attachGtkTaskbarProgress(aWindow) {
+    // Set the current window.
+    this._taskbarProgress.setPrimaryWindow(aWindow);
+
+    // If the DownloadSummary object has already been created, we should update
+    // the state of the new indicator, otherwise it will be updated as soon as
+    // the DownloadSummary view is registered.
+    if (this._summary) {
+      this.onSummaryChanged();
+    }
+
+    aWindow.addEventListener("unload", () => {
+      // Locate another browser window, excluding the one being closed.
+      let browserWindow = RecentWindow.getMostRecentBrowserWindow();
+      if (browserWindow) {
+        // Move the progress indicator to the other browser window.
+        this._attachGtkTaskbarProgress(browserWindow);
+      } else {
+        // The last browser window has been closed.  We remove the reference to
+        // the taskbar progress object so that the indicator will be registered
+        // again on the next browser window that is opened.
+        this._taskbarProgress = null;
+      }
+    });
+  },
+
   // DownloadSummary view
 
   onSummaryChanged() {
     // If the last browser window has been closed, we have no indicator any more.
     if (!this._taskbarProgress) {
       return;
     }
 
--- a/browser/components/feeds/FeedConverter.js
+++ b/browser/components/feeds/FeedConverter.js
@@ -1,15 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/debug.js");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 function LOG(str) {
   dump("*** " + str + "\n");
 }
 
 const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
 const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
@@ -386,42 +385,46 @@ FeedResultService.prototype = {
       break;
     }
   },
 
   /**
    * See nsIFeedResultService.idl
    */
   addFeedResult(feedResult) {
-    NS_ASSERT(feedResult.uri != null, "null URI!");
-    NS_ASSERT(feedResult.uri != null, "null feedResult!");
+    if (feedResult.uri == null)
+      throw new Error("null URI!");
+    if (feedResult.uri == null)
+      throw new Error("null feedResult!");
     let spec = feedResult.uri.spec;
     if (!this._results[spec])
       this._results[spec] = [];
     this._results[spec].push(feedResult);
   },
 
   /**
    * See nsIFeedResultService.idl
    */
   getFeedResult(uri) {
-    NS_ASSERT(uri != null, "null URI!");
+    if (uri == null)
+      throw new Error("null URI!");
     let resultList = this._results[uri.spec];
     for (let result of resultList) {
       if (result.uri == uri)
         return result;
     }
     return null;
   },
 
   /**
    * See nsIFeedResultService.idl
    */
   removeFeedResult(uri) {
-    NS_ASSERT(uri != null, "null URI!");
+    if (uri == null)
+      throw new Error("null URI!");
     let resultList = this._results[uri.spec];
     if (!resultList)
       return;
     let deletions = 0;
     for (let i = 0; i < resultList.length; ++i) {
       if (resultList[i].uri == uri) {
         delete resultList[i];
         ++deletions;
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -127,17 +127,18 @@ var BookmarkPropertiesPanel = {
   _getDialogTitle: function BPP__getDialogTitle() {
     if (this._action == ACTION_ADD) {
       if (this._itemType == BOOKMARK_ITEM)
         return this._strings.getString("dialogTitleAddBookmark");
       if (this._itemType == LIVEMARK_CONTAINER)
         return this._strings.getString("dialogTitleAddLivemark");
 
       // add folder
-      NS_ASSERT(this._itemType == BOOKMARK_FOLDER, "Unknown item type");
+      if (this._itemType != BOOKMARK_FOLDER)
+        throw new Error("Unknown item type");
       if (this._URIs.length)
         return this._strings.getString("dialogTitleAddMulti");
 
       return this._strings.getString("dialogTitleAddFolder");
     }
     if (this._action == ACTION_EDIT) {
       return this._strings.getFormattedString("dialogTitleEdit", [this._title]);
     }
@@ -147,17 +148,18 @@ var BookmarkPropertiesPanel = {
   /**
    * Determines the initial data for the item edited or added by this dialog
    */
   async _determineItemInfo() {
     let dialogInfo = window.arguments[0];
     this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT;
     this._hiddenRows = dialogInfo.hiddenRows ? dialogInfo.hiddenRows : [];
     if (this._action == ACTION_ADD) {
-      NS_ASSERT("type" in dialogInfo, "missing type property for add action");
+      if (!("type" in dialogInfo))
+        throw new Error("missing type property for add action");
 
       if ("title" in dialogInfo)
         this._title = dialogInfo.title;
 
       if ("defaultInsertionPoint" in dialogInfo) {
         this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint;
       } else {
         this._defaultInsertionPoint =
@@ -166,18 +168,18 @@ var BookmarkPropertiesPanel = {
             parentGuid: PlacesUtils.bookmarks.menuGuid
           });
       }
 
       switch (dialogInfo.type) {
         case "bookmark":
           this._itemType = BOOKMARK_ITEM;
           if ("uri" in dialogInfo) {
-            NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI,
-                      "uri property should be a uri object");
+            if (!(dialogInfo.uri instanceof Ci.nsIURI))
+              throw new Error("uri property should be a uri object");
             this._uri = dialogInfo.uri;
             if (typeof(this._title) != "string") {
               this._title = await PlacesUtils.history.fetch(this._uri) ||
                             this._uri.spec;
             }
           } else {
             this._uri = Services.io.newURI("about:blank");
             this._title = this._strings.getString("newBookmarkDefault");
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -656,25 +656,16 @@ PlacesController.prototype = {
 
     PlacesUIUtils.showBookmarkDialog({ action: "edit",
                                        node,
                                        hiddenRows: [ "folderPicker" ]
                                      }, window.top);
   },
 
   /**
-   * This method can be run on a URI parameter to ensure that it didn't
-   * receive a string instead of an nsIURI object.
-   */
-  _assertURINotString: function PC__assertURINotString(value) {
-    NS_ASSERT((typeof(value) == "object") && !(value instanceof String),
-           "This method should be passed a URI as a nsIURI object, not as a string.");
-  },
-
-  /**
    * Reloads the selected livemark if any.
    */
   reloadSelectedLivemark: function PC_reloadSelectedLivemark() {
     var selectedNode = this._view.selectedNode;
     if (selectedNode) {
       let itemId = selectedNode.itemId;
       PlacesUtils.livemarks.getLivemark({ id: itemId })
         .then(aLivemark => {
@@ -796,17 +787,18 @@ PlacesController.prototype = {
    *          An array of nodes to remove. Should all be adjacent.
    * @param   [out] transactions
    *          An array of transactions.
    * @param   [optional] removedFolders
    *          An array of folder nodes that have already been removed.
    * @return {Integer} The total number of items affected.
    */
   async _removeRange(range, transactions, removedFolders) {
-    NS_ASSERT(transactions instanceof Array, "Must pass a transactions array");
+    if (!(transactions instanceof Array))
+      throw new Error("Must pass a transactions array");
     if (!removedFolders)
       removedFolders = [];
 
     let bmGuidsToRemove = [];
     let totalItems = 0;
 
     for (var i = 0; i < range.length; ++i) {
       var node = range[i];
@@ -864,22 +856,17 @@ PlacesController.prototype = {
       }
     }
     if (bmGuidsToRemove.length) {
       transactions.push(PlacesTransactions.Remove({ guids: bmGuidsToRemove }));
     }
     return totalItems;
   },
 
-  /**
-   * Removes the set of selected ranges from bookmarks.
-   * @param   txnName
-   *          See |remove|.
-   */
-  async _removeRowsFromBookmarks(txnName) {
+  async _removeRowsFromBookmarks() {
     let ranges = this._view.removableSelectionRanges;
     let transactions = [];
     let removedFolders = [];
     let totalItems = 0;
 
     for (let range of ranges) {
       totalItems += await this._removeRange(range, transactions, removedFolders);
     }
@@ -924,53 +911,48 @@ PlacesController.prototype = {
     if (PlacesUtils.nodeIsHost(aContainerNode)) {
       // Site container.
       PlacesUtils.history.removePagesFromHost(aContainerNode.title, true);
     } else if (PlacesUtils.nodeIsDay(aContainerNode)) {
       // Day container.
       let query = aContainerNode.getQueries()[0];
       let beginTime = query.beginTime;
       let endTime = query.endTime;
-      NS_ASSERT(query && beginTime && endTime,
-                "A valid date container query should exist!");
+      if (!query || !beginTime || !endTime)
+        throw new Error("A valid date container query should exist!");
       // We want to exclude beginTime from the removal because
       // removePagesByTimeframe includes both extremes, while date containers
       // exclude the lower extreme.  So, if we would not exclude it, we would
       // end up removing more history than requested.
       PlacesUtils.history.removePagesByTimeframe(beginTime + 1, endTime);
     }
   },
 
   /**
    * Removes the selection
-   * @param   aTxnName
-   *          A name for the transaction if this is being performed
-   *          as part of another operation.
    */
-  async remove(aTxnName) {
+  async remove() {
     if (!this._hasRemovableSelection())
       return;
 
-    NS_ASSERT(aTxnName !== undefined, "Must supply Transaction Name");
-
     var root = this._view.result.root;
 
     if (PlacesUtils.nodeIsFolder(root)) {
-      await this._removeRowsFromBookmarks(aTxnName);
+      await this._removeRowsFromBookmarks();
     } else if (PlacesUtils.nodeIsQuery(root)) {
       var queryType = PlacesUtils.asQuery(root).queryOptions.queryType;
       if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS) {
-        await this._removeRowsFromBookmarks(aTxnName);
+        await this._removeRowsFromBookmarks();
       } else if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
         this._removeRowsFromHistory();
       } else {
-        NS_ASSERT(false, "implement support for QUERY_TYPE_UNIFIED");
+        throw new Error("implement support for QUERY_TYPE_UNIFIED");
       }
     } else
-      NS_ASSERT(false, "unexpected root");
+      throw new Error("unexpected root");
   },
 
   /**
    * Fills a DataTransfer object with the content of the selection that can be
    * dropped elsewhere.
    * @param   aEvent
    *          The dragstart event.
    */
@@ -1256,17 +1238,18 @@ PlacesController.prototype = {
   },
 
   /**
    * Checks if we can insert into a container.
    * @param   container
    *          The container were we are want to drop
    */
   disallowInsertion(container) {
-    NS_ASSERT(container, "empty container");
+    if (!container)
+      throw new Error("empty container");
     // Allow dropping into Tag containers and editable folders.
     return !PlacesUtils.nodeIsTagQuery(container) &&
            (!PlacesUtils.nodeIsFolder(container) ||
             PlacesUIUtils.isFolderReadOnly(container, this._view));
   },
 
   /**
    * Determines if a node can be moved.
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -997,31 +997,31 @@ var ViewMenu = {
    *          item only.
    *          Must be contained by popup. Can be null (in which case all
    *          items until the end of the popup will be removed). Ignored
    *          if startID is null.
    * @returns The element for the caller to insert new items before,
    *          null if the caller should just append to the popup.
    */
   _clean: function VM__clean(popup, startID, endID) {
-    if (endID)
-      NS_ASSERT(startID, "meaningless to have valid endID and null startID");
+    if (endID && !startID)
+      throw new Error("meaningless to have valid endID and null startID");
     if (startID) {
       var startElement = document.getElementById(startID);
-      NS_ASSERT(startElement.parentNode ==
-                popup, "startElement is not in popup");
-      NS_ASSERT(startElement,
-                "startID does not correspond to an existing element");
+      if (startElement.parentNode != popup)
+        throw new Error("startElement is not in popup");
+      if (!startElement)
+        throw new Error("startID does not correspond to an existing element");
       var endElement = null;
       if (endID) {
         endElement = document.getElementById(endID);
-        NS_ASSERT(endElement.parentNode == popup,
-                  "endElement is not in popup");
-        NS_ASSERT(endElement,
-                  "endID does not correspond to an existing element");
+        if (endElement.parentNode != popup)
+          throw new Error("endElement is not in popup");
+        if (!endElement)
+          throw new Error("endID does not correspond to an existing element");
       }
       while (startElement.nextSibling != endElement)
         popup.removeChild(startElement.nextSibling);
       return endElement;
     }
     while (popup.hasChildNodes()) {
       popup.firstChild.remove();
     }
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -204,17 +204,17 @@
 
             if (!wasOpen)
               container.containerOpen = false;
 
             return null;
           }
 
           var container = this.result.root;
-          NS_ASSERT(container, "No result, cannot select place URI!");
+          console.assert(container, "No result, cannot select place URI!");
           if (!container)
             return;
 
           var child = findNode(container, []);
           if (child)
             this.selectNode(child);
           else {
             // If the specified child could not be located, clear the selection
@@ -474,17 +474,17 @@
       <method name="_getInsertionPoint">
         <parameter name="index"/>
         <parameter name="orientation"/>
         <body><![CDATA[
           var result = this.result;
           var resultview = this.view;
           var container = result.root;
           var dropNearNode = null;
-          NS_ASSERT(container, "null container");
+          console.assert(container, "null container");
           // When there's no selection, assume the container is the container
           // the view is populated from (i.e. the result's itemId).
           if (index != -1) {
             var lastSelected = resultview.nodeForTreeIndex(index);
             if (resultview.isContainer(index) && orientation == Ci.nsITreeView.DROP_ON) {
               // If the last selected item is an open container, append _into_
               // it, rather than insert adjacent to it.
               container = lastSelected;
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -646,17 +646,17 @@ PlacesTreeView.prototype = {
       case Ci.nsINavHistoryQueryOptions.SORT_BY_TAGS_DESCENDING:
         return [this.COLUMN_TYPE_TAGS, true];
     }
     return [this.COLUMN_TYPE_UNKNOWN, false];
   },
 
   // nsINavHistoryResultObserver
   nodeInserted: function PTV_nodeInserted(aParentNode, aNode, aNewIndex) {
-    NS_ASSERT(this._result, "Got a notification but have no result!");
+    console.assert(this._result, "Got a notification but have no result!");
     if (!this._tree || !this._result)
       return;
 
     // Bail out for hidden separators.
     if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
       return;
 
     let parentRow;
@@ -720,17 +720,17 @@ PlacesTreeView.prototype = {
    * removed but the node it is collapsed with is not being removed (this then
    * just swap out the removee with its collapsing partner). The only time
    * when we really remove things is when deleting URIs, which will apply to
    * all collapsees. This function is called sometimes when resorting items.
    * However, we won't do this when sorted by date because dates will never
    * change for visits, and date sorting is the only time things are collapsed.
    */
   nodeRemoved: function PTV_nodeRemoved(aParentNode, aNode, aOldIndex) {
-    NS_ASSERT(this._result, "Got a notification but have no result!");
+    console.assert(this._result, "Got a notification but have no result!");
     if (!this._tree || !this._result)
       return;
 
     // XXX bug 517701: We don't know what to do when the root node is removed.
     if (aNode == this._rootNode)
       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
 
     // Bail out for hidden separators.
@@ -775,17 +775,17 @@ PlacesTreeView.prototype = {
     // Restore selection.
     let rowToSelect = Math.min(oldRow, this._rows.length - 1);
     if (rowToSelect != -1)
       this.selection.rangedSelect(rowToSelect, rowToSelect, true);
   },
 
   nodeMoved:
   function PTV_nodeMoved(aNode, aOldParent, aOldIndex, aNewParent, aNewIndex) {
-    NS_ASSERT(this._result, "Got a notification but have no result!");
+    console.assert(this._result, "Got a notification but have no result!");
     if (!this._tree || !this._result)
       return;
 
     // Bail out for hidden separators.
     if (PlacesUtils.nodeIsSeparator(aNode) && this.isSorted())
       return;
 
     // Note that at this point the node has already been moved by the backend,
@@ -824,17 +824,17 @@ PlacesTreeView.prototype = {
     if (nodesToReselect.length > 0) {
       this._restoreSelection(nodesToReselect, aNewParent);
       this.selection.selectEventsSuppressed = false;
     }
   },
 
   _invalidateCellValue: function PTV__invalidateCellValue(aNode,
                                                           aColumnType) {
-    NS_ASSERT(this._result, "Got a notification but have no result!");
+    console.assert(this._result, "Got a notification but have no result!");
     if (!this._tree || !this._result)
       return;
 
     // Nothing to do for the root node.
     if (aNode == this._rootNode)
       return;
 
     let row = this._getRowForNode(aNode);
@@ -971,17 +971,17 @@ PlacesTreeView.prototype = {
               aLivemark.unregisterForUpdates(aNode);
             }
           }, () => undefined);
       }
     }
   },
 
   invalidateContainer: function PTV_invalidateContainer(aContainer) {
-    NS_ASSERT(this._result, "Need to have a result to update");
+    console.assert(this._result, "Need to have a result to update");
     if (!this._tree)
       return;
 
     // If we are currently editing, don't invalidate the container until we
     // finish.
     if (this._tree.element.getAttribute("editing")) {
       if (!this._editingObservers) {
         this._editingObservers = new Map();
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -78,16 +78,17 @@ run-if = nightly_build
 [browser_privacypane_5.js]
 [browser_privacypane_8.js]
 [browser_sanitizeOnShutdown_prefLocked.js]
 [browser_searchShowSuggestionsFirst.js]
 [browser_searchsuggestions.js]
 [browser_security-1.js]
 [browser_security-2.js]
 [browser_siteData.js]
+skip-if = (os == 'linux' && debug) # Bug 1439332
 [browser_siteData2.js]
 [browser_siteData3.js]
 [browser_spotlight.js]
 [browser_site_login_exceptions.js]
 [browser_permissions_dialog.js]
 [browser_subdialogs.js]
 support-files =
   subdialog.xul
--- a/browser/components/preferences/selectBookmark.js
+++ b/browser/components/preferences/selectBookmark.js
@@ -53,18 +53,18 @@ var SelectBookmarkDialog = {
   },
 
   /**
    * User accepts their selection. Set all the selected URLs or the contents
    * of the selected folder as the list of homepages.
    */
   accept: function SBD_accept() {
     var bookmarks = document.getElementById("bookmarks");
-    NS_ASSERT(bookmarks.hasSelection,
-              "Should not be able to accept dialog if there is no selected URL!");
+    if (!bookmarks.hasSelection)
+      throw new Error("Should not be able to accept dialog if there is no selected URL!");
     var urls = [];
     var names = [];
     var selectedNode = bookmarks.selectedNode;
     if (PlacesUtils.nodeIsFolder(selectedNode)) {
       var contents = PlacesUtils.getFolderContents(selectedNode.itemId).root;
       var cc = contents.childCount;
       for (var i = 0; i < cc; ++i) {
         var node = contents.getChild(i);
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-60.0a1
+61.0a1
--- a/browser/config/version_display.txt
+++ b/browser/config/version_display.txt
@@ -1,1 +1,1 @@
-60.0a1
+61.0a1
--- a/browser/extensions/formautofill/test/browser/browser.ini
+++ b/browser/extensions/formautofill/test/browser/browser.ini
@@ -7,16 +7,17 @@ support-files =
   ../fixtures/autocomplete_simple_basic.html
   ../fixtures/autocomplete_creditcard_basic.html
 
 [browser_autocomplete_footer.js]
 [browser_autocomplete_marked_back_forward.js]
 [browser_autocomplete_marked_detached_tab.js]
 [browser_check_installed.js]
 [browser_creditCard_doorhanger.js]
+skip-if (os == "linux") || (os == "mac" && debug) || (os == "win") # bug 1425884
 [browser_creditCard_fill_master_password.js]
 [browser_dropdown_layout.js]
 [browser_editAddressDialog.js]
 [browser_editCreditCardDialog.js]
 [browser_first_time_use_doorhanger.js]
 [browser_insecure_form.js]
 [browser_manageAddressesDialog.js]
 [browser_manageCreditCardsDialog.js]
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -1406,43 +1406,41 @@ set_config('DEVELOPER_OPTIONS', develope
 js_option(env='RUSTC_OPT_LEVEL',
           nargs=1,
           help='Rust compiler optimization level (-C opt-level=%s)')
 
 # --enable-release kicks in full optimizations.
 imply_option('RUSTC_OPT_LEVEL', '2', when='--enable-release')
 
 
-@depends('RUSTC_OPT_LEVEL', debug_rust, '--enable-debug-symbols',
-         moz_optimize)
-def rust_compiler_flags(opt_level_option, debug_rust, debug_symbols,
-                        moz_optimize):
-    optimize = moz_optimize.optimize
+@depends('RUSTC_OPT_LEVEL', moz_optimize)
+def rustc_opt_level(opt_level_option, moz_optimize):
+    if opt_level_option:
+        return opt_level_option[0]
+    else:
+        return '1' if moz_optimize.optimize else '0'
 
+
+@depends(rustc_opt_level, debug_rust, '--enable-debug-symbols')
+def rust_compiler_flags(opt_level, debug_rust, debug_symbols):
     # Cargo currently supports only two interesting profiles for building:
     # development and release. Those map (roughly) to --enable-debug and
     # --disable-debug in Gecko, respectively.
     #
     # But we'd also like to support an additional axis of control for
     # optimization level. Since Cargo only supports 2 profiles, we're in
     # a bit of a bind.
     #
     # Code here derives various compiler options given other configure options.
     # The options defined here effectively override defaults specified in
     # Cargo.toml files.
 
-    opt_level = None
     debug_assertions = None
     debug_info = None
 
-    if opt_level_option:
-        opt_level = opt_level_option[0]
-    else:
-        opt_level = '1' if optimize else '0'
-
     # opt-level=0 implies -C debug-assertions, which may not be desired
     # unless Rust debugging is enabled.
     if opt_level == '0' and not debug_rust:
         debug_assertions = False
 
     if debug_symbols:
         debug_info = '2'
 
@@ -1460,16 +1458,49 @@ def rust_compiler_flags(opt_level_option
     for opt in opts:
         flags.extend(['-C', opt])
 
     return flags
 
 
 set_config('MOZ_RUST_DEFAULT_FLAGS', rust_compiler_flags)
 
+# Rust incremental compilation
+# ==============================================================
+
+
+@depends(rustc_opt_level, debug_rust, 'MOZ_AUTOMATION')
+def cargo_incremental(opt_level, debug_rust, automation):
+    """Return a value for the CARGO_INCREMENTAL environment variable."""
+
+    # We never want to use incremental compilation in automation.  sccache
+    # handles our automation use case much better than incremental compilation
+    # would.
+    if automation:
+        return '0'
+
+    # Incremental compilation is automatically turned on for debug builds, so
+    # we don't need to do anything special here.
+    if debug_rust:
+        return
+
+    # --enable-release automatically sets -O2 for Rust code, and people can
+    # set RUSTC_OPT_LEVEL to 2 or even 3 if they want to profile Rust code.
+    # Let's assume that if Rust code is using -O2 or higher, we shouldn't
+    # be using incremental compilation, because we'd be imposing a
+    # significant runtime cost.
+    if opt_level not in ('0', '1'):
+        return
+
+    # We're clear to use incremental compilation!
+    return '1'
+
+
+set_config('CARGO_INCREMENTAL', cargo_incremental)
+
 # Linker detection
 # ==============================================================
 
 
 @depends(target)
 def is_linker_option_enabled(target):
     if target.kernel not in ('Darwin', 'WINNT', 'SunOS'):
         return True
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by build/moz.configure/init.configure.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-60.0a1
+61.0a1
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -859,20 +859,18 @@ endif
 cargo_rustc_flags = $(CARGO_RUSTCFLAGS)
 ifndef DEVELOPER_OPTIONS
 ifndef MOZ_DEBUG_RUST
 # Enable link-time optimization for release builds.
 cargo_rustc_flags += -C lto
 endif
 endif
 
-# Disable incremental Rust compilation in automation builds, where
-# the lack of environmental continuity makes it unhelpful.
-ifdef MOZ_AUTOMATION
-cargo_incremental := CARGO_INCREMENTAL=0
+ifdef CARGO_INCREMENTAL
+cargo_incremental := CARGO_INCREMENTAL=$(CARGO_INCREMENTAL)
 endif
 
 rustflags_override = RUSTFLAGS='$(MOZ_RUST_DEFAULT_FLAGS) $(RUSTFLAGS)'
 
 ifdef MOZ_MSVCBITS
 # If we are building a MozillaBuild shell, we want to clear out the
 # vcvars.bat environment variables for cargo builds. This is because
 # a 32-bit MozillaBuild shell on a 64-bit machine will try to use
--- a/devtools/server/actors/accessibility.js
+++ b/devtools/server/actors/accessibility.js
@@ -820,21 +820,29 @@ const AccessibleWalkerActor = ActorClass
    *
    * @param  {Object} event
    *         Correspoinding content event.
    * @return {null|Object}
    *         Accessible object, if available, that corresponds to a DOM node.
    */
   async _findAndAttachAccessible(event) {
     let target = event.originalTarget || event.target;
-    let rawAccessible = this.a11yService.getAccessibleFor(target);
+    let rawAccessible;
+    // Find a first accessible object in the target's ancestry, including
+    // target. Note: not all DOM nodes have corresponding accessible objects
+    // (for example, a <DIV> element that is used as a container for other
+    // things) thus we need to find one that does.
+    while (!rawAccessible && target) {
+      rawAccessible = this.a11yService.getAccessibleFor(target);
+      target = target.parentNode;
+    }
     // If raw accessible object is defunct or detached, no need to cache it and
     // its ancestry.
     if (!rawAccessible || isDefunct(rawAccessible) || rawAccessible.indexInParent < 0) {
-      return {};
+      return null;
     }
 
     const doc = await this.getDocument();
     let accessible = this.addRef(rawAccessible);
     // There is a chance that ancestry lookup can fail if the accessible is in
     // the detached subtree. At that point the root accessible object would be
     // defunct and accessing it via parent property will throw.
     try {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -352,17 +352,17 @@ public:
 
   PrincipalFlashClassifier();
 
   // Fire async classification based on the given principal.
   void AsyncClassify(nsIPrincipal* aPrincipal);
 
   // Would block if the result hasn't come out.
   mozilla::dom::FlashClassification ClassifyMaybeSync(nsIPrincipal* aPrincipal,
-                                           bool aIsThirdParty);
+                                                      bool aIsThirdParty);
 
 private:
  ~PrincipalFlashClassifier() = default;
 
   void Reset();
   bool EnsureUriClassifier();
   mozilla::dom::FlashClassification CheckIfClassifyNeeded(nsIPrincipal* aPrincipal);
   mozilla::dom::FlashClassification Resolve(bool aIsThirdParty);
@@ -815,17 +815,17 @@ nsOnloadBlocker::SetLoadFlags(nsLoadFlag
 nsExternalResourceMap::nsExternalResourceMap()
   : mHaveShutDown(false)
 {
 }
 
 nsIDocument*
 nsExternalResourceMap::RequestResource(nsIURI* aURI,
                                        nsINode* aRequestingNode,
-                                       nsDocument* aDisplayDocument,
+                                       nsIDocument* aDisplayDocument,
                                        ExternalResourceLoad** aPendingLoad)
 {
   // If we ever start allowing non-same-origin loads here, we might need to do
   // something interesting with aRequestingPrincipal even for the hashtable
   // gets.
   NS_PRECONDITION(aURI, "Must have a URI");
   NS_PRECONDITION(aRequestingNode, "Must have a node");
   *aPendingLoad = nullptr;
@@ -1418,16 +1418,19 @@ nsIDocument::nsIDocument()
     mBlockAllMixedContentPreloads(false),
     mUpgradeInsecureRequests(false),
     mUpgradeInsecurePreloads(false),
     mCharacterSet(WINDOWS_1252_ENCODING),
     mCharacterSetSource(0),
     mParentDocument(nullptr),
     mCachedRootElement(nullptr),
     mNodeInfoManager(nullptr),
+#ifdef DEBUG
+    mStyledLinksCleared(false),
+#endif
     mBidiEnabled(false),
     mMathMLEnabled(false),
     mIsInitialDocumentInWindow(false),
     mIgnoreDocGroupMismatches(false),
     mLoadedAsData(false),
     mLoadedAsInteractiveData(false),
     mMayStartLayout(true),
     mHaveFiredTitleChange(false),
@@ -1481,17 +1484,29 @@ nsIDocument::nsIDocument()
     mIsSVGGlyphsDocument(false),
     mAllowUnsafeHTML(false),
     mInDestructor(false),
     mIsGoingAway(false),
     mInXBLUpdate(false),
     mNeedsReleaseAfterStackRefCntRelease(false),
     mStyleSetFilled(false),
     mSSApplicableStateNotificationPending(false),
+    mMayHaveTitleElement(false),
+    mDOMLoadingSet(false),
+    mDOMInteractiveSet(false),
+    mDOMCompleteSet(false),
+    mAutoFocusFired(false),
+    mScrolledToRefAlready(false),
+    mChangeScrollPosWhenScrollingToRef(false),
+    mHasWarnedAboutBoxObjects(false),
+    mDelayFrameLoaderInitialization(false),
+    mSynchronousDOMContentLoaded(false),
+    mMaybeServiceWorkerControlled(false),
     mIsScopedStyleEnabled(eScopedStyle_Unknown),
+    mPendingFullscreenRequests(0),
     mCompatMode(eCompatibility_FullStandards),
     mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
     mStyleBackendType(StyleBackendType::None),
 #ifdef MOZILLA_INTERNAL_API
     mVisibilityState(dom::VisibilityState::Hidden),
 #else
     mDummy(0),
 #endif
@@ -1499,84 +1514,69 @@ nsIDocument::nsIDocument()
     mDefaultElementType(0),
     mAllowXULXBL(eTriUnset),
     mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
     mSandboxFlags(0),
     mPartID(0),
     mMarkedCCGeneration(0),
     mPresShell(nullptr),
     mSubtreeModifiedDepth(0),
+    mPreloadPictureDepth(0),
     mEventsSuppressed(0),
     mIgnoreDestructiveWritesCounter(0),
     mFrameRequestCallbackCounter(0),
     mStaticCloneCount(0),
     mWindow(nullptr),
     mBFCacheEntry(nullptr),
     mInSyncOperationCount(0),
     mBlockDOMContentLoaded(0),
     mUseCounters(0),
     mChildDocumentUseCounters(0),
     mNotifiedPageForUseCounter(0),
     mIncCounters(),
     mUserHasInteracted(false),
     mUserHasActivatedInteraction(false),
     mStackRefCnt(0),
     mUpdateNestLevel(0),
+    mViewportType(Unknown),
+    mSubDocuments(nullptr),
+    mHeaderData(nullptr),
+    mFlashClassification(FlashClassification::Unclassified),
+    mBoxObjectTable(nullptr),
+    mCurrentOrientationAngle(0),
+    mCurrentOrientationType(OrientationType::Portrait_primary),
     mServoRestyleRootDirtyBits(0),
     mThrowOnDynamicMarkupInsertionCounter(0),
     mIgnoreOpensDuringUnloadCounter(0)
 {
   SetIsInDocument();
   for (auto& cnt : mIncCounters) {
     cnt = 0;
   }
 }
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
-  , mSubDocuments(nullptr)
-  , mFlashClassification(FlashClassification::Unclassified)
-  , mHeaderData(nullptr)
-  , mMayHaveTitleElement(false)
-  , mHasWarnedAboutBoxObjects(false)
-  , mDelayFrameLoaderInitialization(false)
-  , mSynchronousDOMContentLoaded(false)
   , mParserAborted(false)
-  , mCurrentOrientationAngle(0)
-  , mCurrentOrientationType(OrientationType::Portrait_primary)
   , mReportedUseCounters(false)
-  , mPendingFullscreenRequests(0)
   , mXMLDeclarationBits(0)
-  , mBoxObjectTable(nullptr)
   , mOnloadBlockCount(0)
   , mAsyncOnloadBlockCount(0)
-#ifdef DEBUG
-  , mStyledLinksCleared(false)
-#endif
-  , mPreloadPictureDepth(0)
-  , mScrolledToRefAlready(0)
-  , mChangeScrollPosWhenScrollingToRef(0)
-  , mViewportType(Unknown)
   , mValidWidth(false)
   , mValidHeight(false)
   , mAutoSize(false)
   , mAllowZoom(false)
   , mAllowDoubleTapZoom(false)
   , mValidScaleFloat(false)
   , mValidMaxScale(false)
   , mScaleStrEmpty(false)
   , mWidthStrEmpty(false)
-  , mMaybeServiceWorkerControlled(false)
 #ifdef DEBUG
   , mWillReparent(false)
 #endif
-  , mDOMLoadingSet(false)
-  , mDOMInteractiveSet(false)
-  , mDOMCompleteSet(false)
-  , mAutoFocusFired(false)
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
 
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
 
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
 
@@ -2862,32 +2862,32 @@ nsDocument::SendToConsole(nsCOMArray<nsI
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                     NS_ConvertUTF16toUTF8(category),
                                     this, nsContentUtils::eSECURITY_PROPERTIES,
                                     NS_ConvertUTF16toUTF8(messageTag).get());
   }
 }
 
 void
-nsDocument::ApplySettingsFromCSP(bool aSpeculative)
+nsIDocument::ApplySettingsFromCSP(bool aSpeculative)
 {
   nsresult rv = NS_OK;
   if (!aSpeculative) {
     // 1) apply settings from regular CSP
     nsCOMPtr<nsIContentSecurityPolicy> csp;
     rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
     NS_ENSURE_SUCCESS_VOID(rv);
     if (csp) {
       // Set up any Referrer Policy specified by CSP
       bool hasReferrerPolicy = false;
       uint32_t referrerPolicy = mozilla::net::RP_Unset;
       rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
       NS_ENSURE_SUCCESS_VOID(rv);
       if (hasReferrerPolicy) {
-        mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
+        mReferrerPolicy = static_cast<enum ReferrerPolicy>(referrerPolicy);
         mReferrerPolicySet = true;
       }
 
       // Set up 'block-all-mixed-content' if not already inherited
       // from the parent context or set by any other CSP.
       if (!mBlockAllMixedContent) {
         rv = csp->GetBlockAllMixedContent(&mBlockAllMixedContent);
         NS_ENSURE_SUCCESS_VOID(rv);
@@ -2934,17 +2934,17 @@ nsDocument::InitCSP(nsIChannel* aChannel
     MOZ_LOG(gCspPRLog, LogLevel::Debug,
            ("CSP is disabled, skipping CSP init for document %p", this));
     return NS_OK;
   }
 
   // In case this channel was instrument to discard the CSP, then
   // there is nothing for us to do here.
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
-  if (loadInfo->GetAllowDocumentToBeAgnosticToCSP()) {
+  if (loadInfo && loadInfo->GetAllowDocumentToBeAgnosticToCSP()) {
     return NS_OK;
   }
 
   nsAutoCString tCspHeaderValue, tCspROHeaderValue;
 
   nsCOMPtr<nsIHttpChannel> httpChannel;
   nsresult rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -3077,17 +3077,17 @@ nsDocument::StopDocumentLoad()
 {
   if (mParser) {
     mParserAborted = true;
     mParser->Terminate();
   }
 }
 
 void
-nsDocument::SetDocumentURI(nsIURI* aURI)
+nsIDocument::SetDocumentURI(nsIURI* aURI)
 {
   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
   mDocumentURI = NS_TryToMakeImmutable(aURI);
   nsIURI* newBase = GetDocBaseURI();
 
   bool equalBases = false;
   // Changing just the ref of a URI does not change how relative URIs would
   // resolve wrt to it, so we can treat the bases as equal as long as they're
@@ -3106,28 +3106,16 @@ nsDocument::SetDocumentURI(nsIURI* aURI)
 
   // If changing the document's URI changed the base URI of the document, we
   // need to refresh the hrefs of all the links on the page.
   if (!equalBases) {
     RefreshLinkHrefs();
   }
 }
 
-void
-nsDocument::SetChromeXHRDocURI(nsIURI* aURI)
-{
-  mChromeXHRDocURI = aURI;
-}
-
-void
-nsDocument::SetChromeXHRDocBaseURI(nsIURI* aURI)
-{
-  mChromeXHRDocBaseURI = aURI;
-}
-
 static void
 GetFormattedTimeString(PRTime aTime, nsAString& aFormattedTimeString)
 {
   PRExplodedTime prtime;
   PR_ExplodeTime(aTime, PR_LocalTimeParameters, &prtime);
   // "MM/DD/YYYY hh:mm:ss"
   char formatedTime[24];
   if (SprintfLiteral(formatedTime, "%02d/%02d/%04d %02d:%02d:%02d",
@@ -3146,103 +3134,109 @@ nsIDocument::GetLastModified(nsAString& 
 {
   if (!mLastModified.IsEmpty()) {
     aLastModified.Assign(mLastModified);
   } else {
     GetFormattedTimeString(PR_Now(), aLastModified);
   }
 }
 
-void
-nsDocument::AddToNameTable(Element *aElement, nsAtom* aName)
+static void
+IncrementExpandoGeneration(nsIDocument& aDoc)
+{
+  ++static_cast<nsDocument&>(aDoc).mExpandoAndGeneration.generation;
+}
+
+void
+nsIDocument::AddToNameTable(Element* aElement, nsAtom* aName)
 {
   MOZ_ASSERT(nsGenericHTMLElement::ShouldExposeNameAsHTMLDocumentProperty(aElement),
              "Only put elements that need to be exposed as document['name'] in "
              "the named table.");
 
   nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aName);
 
   // Null for out-of-memory
   if (entry) {
     if (!entry->HasNameElement() &&
         !entry->HasIdElementExposedAsHTMLDocumentProperty()) {
-      ++mExpandoAndGeneration.generation;
+      IncrementExpandoGeneration(*this);
     }
     entry->AddNameElement(this, aElement);
   }
 }
 
 void
-nsDocument::RemoveFromNameTable(Element *aElement, nsAtom* aName)
+nsIDocument::RemoveFromNameTable(Element* aElement, nsAtom* aName)
 {
   // Speed up document teardown
   if (mIdentifierMap.Count() == 0)
     return;
 
   nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aName);
   if (!entry) // Could be false if the element was anonymous, hence never added
     return;
 
   entry->RemoveNameElement(aElement);
   if (!entry->HasNameElement() &&
       !entry->HasIdElementExposedAsHTMLDocumentProperty()) {
-    ++mExpandoAndGeneration.generation;
-  }
-}
-
-void
-nsDocument::AddToIdTable(Element *aElement, nsAtom* aId)
+    IncrementExpandoGeneration(*this);
+  }
+}
+
+void
+nsIDocument::AddToIdTable(Element* aElement, nsAtom* aId)
 {
   nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aId);
 
   if (entry) { /* True except on OOM */
     if (nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(aElement) &&
         !entry->HasNameElement() &&
         !entry->HasIdElementExposedAsHTMLDocumentProperty()) {
-      ++mExpandoAndGeneration.generation;
+      IncrementExpandoGeneration(*this);
     }
     entry->AddIdElement(aElement);
   }
 }
 
 void
-nsDocument::RemoveFromIdTable(Element *aElement, nsAtom* aId)
+nsIDocument::RemoveFromIdTable(Element* aElement, nsAtom* aId)
 {
   NS_ASSERTION(aId, "huhwhatnow?");
 
   // Speed up document teardown
   if (mIdentifierMap.Count() == 0) {
     return;
   }
 
   nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId);
   if (!entry) // Can be null for XML elements with changing ids.
     return;
 
   entry->RemoveIdElement(aElement);
   if (nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(aElement) &&
       !entry->HasNameElement() &&
       !entry->HasIdElementExposedAsHTMLDocumentProperty()) {
-    ++mExpandoAndGeneration.generation;
+    IncrementExpandoGeneration(*this);
   }
   if (entry->IsEmpty()) {
     mIdentifierMap.RemoveEntry(entry);
   }
 }
 
 nsIPrincipal*
 nsDocument::GetPrincipal()
 {
   return NodePrincipal();
 }
 
 extern bool sDisablePrefetchHTTPSPref;
 
 void
-nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
+nsIDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
 {
   if (aNewPrincipal && mAllowDNSPrefetch && sDisablePrefetchHTTPSPref) {
     nsCOMPtr<nsIURI> uri;
     aNewPrincipal->GetURI(getter_AddRefs(uri));
     bool isHTTPS;
     if (!uri || NS_FAILED(uri->SchemeIs("https", &isHTTPS)) ||
         isHTTPS) {
       mAllowDNSPrefetch = false;
@@ -3355,17 +3349,17 @@ nsIDocument::GetContentType(nsAString& a
 
 void
 nsDocument::SetContentType(const nsAString& aContentType)
 {
   SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
 }
 
 bool
-nsDocument::GetAllowPlugins()
+nsIDocument::GetAllowPlugins()
 {
   // First, we ask our docshell if it allows plugins.
   nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
 
   if (docShell) {
     bool allowPlugins = false;
     docShell->GetAllowPlugins(&allowPlugins);
     if (!allowPlugins) {
@@ -3467,27 +3461,27 @@ nsDocument::IsWebAnimationsEnabled(Calle
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return aCallerType == dom::CallerType::System ||
          nsContentUtils::AnimationsAPICoreEnabled();
 }
 
 DocumentTimeline*
-nsDocument::Timeline()
+nsIDocument::Timeline()
 {
   if (!mDocumentTimeline) {
     mDocumentTimeline = new DocumentTimeline(this, TimeDuration(0));
   }
 
   return mDocumentTimeline;
 }
 
 void
-nsDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
+nsIDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
 {
   // Hold a strong ref for the root element since Element::GetAnimations() calls
   // FlushPendingNotifications() which may destroy the element.
   RefPtr<Element> root = GetRootElement();
   if (!root) {
     return;
   }
   AnimationFilter filter;
@@ -3598,22 +3592,22 @@ nsIDocument::GetActiveElement()
 Element*
 nsIDocument::GetCurrentScript()
 {
   nsCOMPtr<Element> el(do_QueryInterface(ScriptLoader()->GetCurrentScript()));
   return el;
 }
 
 nsresult
-nsDocument::NodesFromRectHelper(float aX, float aY,
-                                float aTopSize, float aRightSize,
-                                float aBottomSize, float aLeftSize,
-                                bool aIgnoreRootScrollFrame,
-                                bool aFlushLayout,
-                                nsIDOMNodeList** aReturn)
+nsIDocument::NodesFromRectHelper(float aX, float aY,
+                                 float aTopSize, float aRightSize,
+                                 float aBottomSize, float aLeftSize,
+                                 bool aIgnoreRootScrollFrame,
+                                 bool aFlushLayout,
+                                 nsIDOMNodeList** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
 
   nsSimpleContentList* elements = new nsSimpleContentList(this);
   NS_ADDREF(elements);
   *aReturn = elements;
 
   // Following the same behavior of elementFromPoint,
@@ -3687,17 +3681,17 @@ nsIDocument::GetBaseURI(bool aTryUseXHRD
   } else {
     uri = GetDocBaseURI();
   }
 
   return uri.forget();
 }
 
 void
-nsDocument::SetBaseURI(nsIURI* aURI)
+nsIDocument::SetBaseURI(nsIURI* aURI)
 {
   if (!aURI && !mDocumentBaseURI) {
     return;
   }
 
   // Don't do anything if the URI wasn't actually changed.
   if (aURI && mDocumentBaseURI) {
     bool equalBases = false;
@@ -3732,22 +3726,16 @@ nsIDocument::DefaultStyleAttrURLData()
   return mCachedURLData;
 #else
   MOZ_CRASH("Should not be called for non-stylo build");
   return nullptr;
 #endif
 }
 
 void
-nsDocument::GetBaseTarget(nsAString &aBaseTarget)
-{
-  aBaseTarget = mBaseTarget;
-}
-
-void
 nsDocument::SetDocumentCharacterSet(NotNull<const Encoding*> aEncoding)
 {
   if (mCharacterSet != aEncoding) {
     mCharacterSet = aEncoding;
 
     if (nsPresContext* context = GetPresContext()) {
       context->DispatchCharSetChange(aEncoding);
     }
@@ -3756,32 +3744,32 @@ nsDocument::SetDocumentCharacterSet(NotN
 
 void
 nsIDocument::GetSandboxFlagsAsString(nsAString& aFlags)
 {
   nsContentUtils::SandboxFlagsToString(mSandboxFlags, aFlags);
 }
 
 void
-nsDocument::GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const
+nsIDocument::GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const
 {
   aData.Truncate();
   const nsDocHeaderData* data = mHeaderData;
   while (data) {
     if (data->mField == aHeaderField) {
       aData = data->mData;
 
       break;
     }
     data = data->mNext;
   }
 }
 
 void
-nsDocument::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData)
+nsIDocument::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData)
 {
   if (!aHeaderField) {
     NS_ERROR("null headerField");
     return;
   }
 
   if (!mHeaderData) {
     if (!aData.IsEmpty()) { // don't bother storing empty string
@@ -3862,29 +3850,29 @@ nsDocument::SetHeaderData(nsAtom* aHeade
       aHeaderField == nsGkAtoms::viewport_height ||
       aHeaderField == nsGkAtoms::viewport_width ||
       aHeaderField ==  nsGkAtoms::viewport_user_scalable) {
     mViewportType = Unknown;
   }
 
   // Referrer policy spec says to ignore any empty referrer policies.
   if (aHeaderField == nsGkAtoms::referrer && !aData.IsEmpty()) {
-     ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData);
+     enum ReferrerPolicy policy = mozilla::net::ReferrerPolicyFromString(aData);
     // If policy is not the empty string, then set element's node document's
     // referrer policy to policy
     if (policy != mozilla::net::RP_Unset) {
       // Referrer policy spec (section 6.1) says that we always use the newest
       // referrer policy we find
       mReferrerPolicy = policy;
       mReferrerPolicySet = true;
     }
   }
 
   if (aHeaderField == nsGkAtoms::headerReferrerPolicy && !aData.IsEmpty()) {
-     ReferrerPolicy policy = nsContentUtils::GetReferrerPolicyFromHeader(aData);
+     enum ReferrerPolicy policy = nsContentUtils::GetReferrerPolicyFromHeader(aData);
     if (policy != mozilla::net::RP_Unset) {
       mReferrerPolicy = policy;
       mReferrerPolicySet = true;
     }
   }
 
 }
 void
@@ -3922,18 +3910,19 @@ AssertNoStaleServoDataIn(const nsINode& 
         AssertNoStaleServoDataIn(*shadow);
       }
     }
   }
 #endif
 }
 
 already_AddRefed<nsIPresShell>
-nsDocument::CreateShell(nsPresContext* aContext, nsViewManager* aViewManager,
-                        StyleSetHandle aStyleSet)
+nsIDocument::CreateShell(nsPresContext* aContext,
+                         nsViewManager* aViewManager,
+                         StyleSetHandle aStyleSet)
 {
   NS_ASSERTION(!mPresShell, "We have a presshell already!");
 
   NS_ENSURE_FALSE(GetBFCacheEntry(), nullptr);
 
   FillStyleSet(aStyleSet);
   AssertNoStaleServoDataIn(static_cast<nsINode&>(*this));
 
@@ -4036,17 +4025,17 @@ nsIDocument::ShouldThrottleFrameRequests
     return true;
   }
 
   // We got painted during the last paint, so run at full speed.
   return false;
 }
 
 void
-nsDocument::DeleteShell()
+nsIDocument::DeleteShell()
 {
   mExternalResourceMap.HideViewers();
   if (nsPresContext* presContext = mPresShell->GetPresContext()) {
     presContext->RefreshDriver()->CancelPendingEvents(this);
   }
 
   // When our shell goes away, request that all our images be immediately
   // discarded, so we don't carry around decoded image data for a document we
@@ -4090,30 +4079,18 @@ SubDocInitEntry(PLDHashEntryHdr *entry, 
               (static_cast<const SubDocMapEntry *>(entry));
 
   e->mKey = const_cast<Element*>(static_cast<const Element*>(key));
   NS_ADDREF(e->mKey);
 
   e->mSubDocument = nullptr;
 }
 
-bool
-nsDocument::AllowPaymentRequest() const
-{
-  return mAllowPaymentRequest;
-}
-
-void
-nsDocument::SetAllowPaymentRequest(bool aAllowPaymentRequest)
-{
-  mAllowPaymentRequest = aAllowPaymentRequest;
-}
-
 nsresult
-nsDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
+nsIDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_UNEXPECTED);
 
   if (!aSubDoc) {
     // aSubDoc is nullptr, remove the mapping
 
     if (mSubDocuments) {
       nsIDocument* subDoc = GetSubDocumentFor(aElement);
@@ -4176,32 +4153,32 @@ nsDocument::SetSubDocumentFor(Element* a
 
     aSubDoc->SetParentDocument(this);
   }
 
   return NS_OK;
 }
 
 nsIDocument*
-nsDocument::GetSubDocumentFor(nsIContent *aContent) const
+nsIDocument::GetSubDocumentFor(nsIContent *aContent) const
 {
   if (mSubDocuments && aContent->IsElement()) {
     auto entry = static_cast<SubDocMapEntry*>
                             (mSubDocuments->Search(aContent->AsElement()));
 
     if (entry) {
       return entry->mSubDocument;
     }
   }
 
   return nullptr;
 }
 
 Element*
-nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
+nsIDocument::FindContentForSubDocument(nsIDocument *aDocument) const
 {
   NS_ENSURE_TRUE(aDocument, nullptr);
 
   if (!mSubDocuments) {
     return nullptr;
   }
 
   for (auto iter = mSubDocuments->Iter(); !iter.Done(); iter.Next()) {
@@ -4209,103 +4186,87 @@ nsDocument::FindContentForSubDocument(ns
     if (entry->mSubDocument == aDocument) {
       return entry->mKey;
     }
   }
   return nullptr;
 }
 
 bool
-nsDocument::IsNodeOfType(uint32_t aFlags) const
-{
-    return !(aFlags & ~eDOCUMENT);
+nsIDocument::IsNodeOfType(uint32_t aFlags) const
+{
+  return !(aFlags & ~eDOCUMENT);
 }
 
 Element*
 nsIDocument::GetRootElement() const
 {
   return (mCachedRootElement && mCachedRootElement->GetParentNode() == this) ?
          mCachedRootElement : GetRootElementInternal();
 }
 
 nsIContent*
 nsIDocument::GetUnfocusedKeyEventTarget()
 {
   return GetRootElement();
 }
 
 Element*
-nsDocument::GetRootElementInternal() const
+nsIDocument::GetRootElementInternal() const
 {
   // We invoke GetRootElement() immediately before the servo traversal, so we
   // should always have a cache hit from Servo.
   MOZ_ASSERT(NS_IsMainThread());
 
   // Loop backwards because any non-elements, such as doctypes and PIs
   // are likely to appear before the root element.
   uint32_t i;
   for (i = mChildren.ChildCount(); i > 0; --i) {
     nsIContent* child = mChildren.ChildAt(i - 1);
     if (child->IsElement()) {
-      const_cast<nsDocument*>(this)->mCachedRootElement = child->AsElement();
+      const_cast<nsIDocument*>(this)->mCachedRootElement = child->AsElement();
       return child->AsElement();
     }
   }
 
-  const_cast<nsDocument*>(this)->mCachedRootElement = nullptr;
+  const_cast<nsIDocument*>(this)->mCachedRootElement = nullptr;
   return nullptr;
 }
 
-nsIContent *
-nsDocument::GetChildAt_Deprecated(uint32_t aIndex) const
-{
-  return mChildren.GetSafeChildAt(aIndex);
-}
-
-int32_t
-nsDocument::ComputeIndexOf(const nsINode* aPossibleChild) const
-{
-  return mChildren.IndexOfChild(aPossibleChild);
-}
-
-uint32_t
-nsDocument::GetChildCount() const
-{
-  return mChildren.ChildCount();
-}
-
 nsresult
-nsDocument::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
-                            bool aNotify)
+nsIDocument::InsertChildBefore(nsIContent* aKid,
+                               nsIContent* aBeforeThis,
+                               bool aNotify)
 {
   if (aKid->IsElement() && GetRootElement()) {
     NS_WARNING("Inserting root element when we already have one");
     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
   }
 
   int32_t index = aBeforeThis ? ComputeIndexOf(aBeforeThis) : GetChildCount();
   MOZ_ASSERT(index >= 0);
 
   return doInsertChildAt(aKid, index, aNotify, mChildren);
 }
 
 nsresult
-nsDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
-                                     bool aNotify)
+nsIDocument::InsertChildAt_Deprecated(nsIContent* aKid,
+                                      uint32_t aIndex,
+                                      bool aNotify)
 {
   if (aKid->IsElement() && GetRootElement()) {
     NS_WARNING("Inserting root element when we already have one");
     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
   }
 
   return doInsertChildAt(aKid, aIndex, aNotify, mChildren);
 }
 
 void
-nsDocument::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
+nsIDocument::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
 {
   nsCOMPtr<nsIContent> oldKid = GetChildAt_Deprecated(aIndex);
   if (!oldKid) {
     return;
   }
 
   if (oldKid->IsElement()) {
     // Destroy the link map up front before we mess with the child list.
@@ -4322,17 +4283,17 @@ nsDocument::RemoveChildAt_Deprecated(uin
   mCachedRootElement = nullptr;
   doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
   MOZ_ASSERT(mCachedRootElement != oldKid,
              "Stale pointer in mCachedRootElement, after we tried to clear it "
              "(maybe somebody called GetRootElement() too early?)");
 }
 
 void
-nsDocument::RemoveChildNode(nsIContent* aKid, bool aNotify)
+nsIDocument::RemoveChildNode(nsIContent* aKid, bool aNotify)
 {
   if (aKid->IsElement()) {
     // Destroy the link map up front before we mess with the child list.
     DestroyElementMaps();
   }
 
   // Preemptively clear mCachedRootElement, since we may be about to remove it
   // from our child list, and we don't want to return this maybe-obsolete value
@@ -4722,24 +4683,24 @@ nsIDocument::RemoveAdditionalStyleSheet(
     NotifyStyleSheetRemoved(sheetRef, false);
     EndUpdate(UPDATE_STYLE);
 
     sheetRef->ClearAssociatedDocument();
   }
 }
 
 nsIGlobalObject*
-nsDocument::GetScopeObject() const
+nsIDocument::GetScopeObject() const
 {
   nsCOMPtr<nsIGlobalObject> scope(do_QueryReferent(mScopeObject));
   return scope;
 }
 
 void
-nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
+nsIDocument::SetScopeObject(nsIGlobalObject* aGlobal)
 {
   mScopeObject = do_GetWeakReference(aGlobal);
   if (aGlobal) {
     mHasHadScriptHandlingObject = true;
 
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
     if (window) {
       // We want to get the tabgroup unconditionally, such that we can make
@@ -4771,17 +4732,17 @@ CheckIfContainsEMEContent(nsISupports* a
     bool* contains = static_cast<bool*>(aContainsEME);
     if (mediaElem->GetMediaKeys()) {
       *contains = true;
     }
   }
 }
 
 bool
-nsDocument::ContainsEMEContent()
+nsIDocument::ContainsEMEContent()
 {
   bool containsEME = false;
   EnumerateActivityObservers(CheckIfContainsEMEContent,
                              static_cast<void*>(&containsEME));
   return containsEME;
 }
 
 static void
@@ -4793,17 +4754,17 @@ CheckIfContainsMSEContent(nsISupports* a
     RefPtr<MediaSource> ms = mediaElem->GetMozMediaSourceObject();
     if (ms) {
       *contains = true;
     }
   }
 }
 
 bool
-nsDocument::ContainsMSEContent()
+nsIDocument::ContainsMSEContent()
 {
   bool containsMSE = false;
   EnumerateActivityObservers(CheckIfContainsMSEContent,
                              static_cast<void*>(&containsMSE));
   return containsMSE;
 }
 
 static void
@@ -4996,17 +4957,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
   }
 
   // Set our visibility state, but do not fire the event.  This is correct
   // because either we're coming out of bfcache (in which case IsVisible() will
   // still test false at this point and no state change will happen) or we're
   // doing the initial document load and don't want to fire the event for this
   // change.
   dom::VisibilityState oldState = mVisibilityState;
-  mVisibilityState = GetVisibilityState();
+  mVisibilityState = ComputeVisibilityState();
   // When the visibility is changed, notify it to observers.
   // Some observers need the notification, for example HTMLMediaElement uses
   // it to update internal media resource allocation.
   // When video is loaded via VideoDocument, HTMLMediaElement and MediaDecoder
   // creation are already done before nsDocument::SetScriptGlobalObject() call.
   // MediaDecoder decides whether starting decoding is decided based on
   // document's visibility. When the MediaDecoder is created,
   // nsDocument::SetScriptGlobalObject() is not yet called and document is
@@ -5034,17 +4995,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
       return;
     }
 
     mMaybeServiceWorkerControlled = true;
   }
 }
 
 nsIScriptGlobalObject*
-nsDocument::GetScriptHandlingObjectInternal() const
+nsIDocument::GetScriptHandlingObjectInternal() const
 {
   MOZ_ASSERT(!mScriptGlobalObject,
              "Do not call this when mScriptGlobalObject is set!");
   if (mHasHadDefaultView) {
     return nullptr;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
@@ -5055,29 +5016,29 @@ nsDocument::GetScriptHandlingObjectInter
     if (!outer || outer->GetCurrentInnerWindow() != win) {
       NS_WARNING("Wrong inner/outer window combination!");
       return nullptr;
     }
   }
   return scriptHandlingObject;
 }
 void
-nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
+nsIDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
 {
   NS_ASSERTION(!mScriptGlobalObject ||
                mScriptGlobalObject == aScriptObject,
                "Wrong script object!");
   if (aScriptObject) {
     SetScopeObject(aScriptObject);
     mHasHadDefaultView = false;
   }
 }
 
 nsPIDOMWindowOuter*
-nsDocument::GetWindowInternal() const
+nsIDocument::GetWindowInternal() const
 {
   MOZ_ASSERT(!mWindow, "This should not be called when mWindow is not null!");
   // Let's use mScriptGlobalObject. Even if the document is already removed from
   // the docshell, the outer window might be still obtainable from the it.
   nsCOMPtr<nsPIDOMWindowOuter> win;
   if (mRemovedFromDocShell) {
     // The docshell returns the outer window we are done.
     nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocumentContainer);
@@ -5089,24 +5050,18 @@ nsDocument::GetWindowInternal() const
       // mScriptGlobalObject is always the inner window, let's get the outer.
       win = inner->GetOuterWindow();
     }
   }
 
   return win;
 }
 
-ScriptLoader*
-nsDocument::ScriptLoader()
-{
-  return mScriptLoader;
-}
-
 bool
-nsDocument::InternalAllowXULXBL()
+nsIDocument::InternalAllowXULXBL()
 {
   if (nsContentUtils::AllowXULXBLForPrincipal(NodePrincipal())) {
     mAllowXULXBL = eTriTrue;
     return true;
   }
 
   mAllowXULXBL = eTriFalse;
   return false;
@@ -5211,86 +5166,86 @@ nsDocument::BeginLoad()
   if (mScriptLoader) {
     mScriptLoader->BeginDeferringScripts();
   }
 
   NS_DOCUMENT_NOTIFY_OBSERVERS(BeginLoad, (this));
 }
 
 void
-nsDocument::ReportEmptyGetElementByIdArg()
+nsIDocument::ReportEmptyGetElementByIdArg()
 {
   nsContentUtils::ReportEmptyGetElementByIdArg(this);
 }
 
 Element*
-nsDocument::AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
+nsIDocument::AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
                                 void* aData, bool aForImage)
 {
   nsDependentAtomString id(aID);
 
   if (!CheckGetElementByIdArg(id))
     return nullptr;
 
   nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aID);
   NS_ENSURE_TRUE(entry, nullptr);
 
   entry->AddContentChangeCallback(aObserver, aData, aForImage);
   return aForImage ? entry->GetImageIdElement() : entry->GetIdElement();
 }
 
 void
-nsDocument::RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
+nsIDocument::RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
                                    void* aData, bool aForImage)
 {
   nsDependentAtomString id(aID);
 
   if (!CheckGetElementByIdArg(id))
     return;
 
   nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aID);
   if (!entry) {
     return;
   }
 
   entry->RemoveContentChangeCallback(aObserver, aData, aForImage);
 }
 
 void
-nsDocument::MozSetImageElement(const nsAString& aImageElementId,
+nsIDocument::MozSetImageElement(const nsAString& aImageElementId,
                                Element* aElement)
 {
   if (aImageElementId.IsEmpty())
     return;
 
   // Hold a script blocker while calling SetImageElement since that can call
   // out to id-observers
   nsAutoScriptBlocker scriptBlocker;
 
-  nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aImageElementId);
+  nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aImageElementId);
   if (entry) {
     entry->SetImageElement(aElement);
     if (entry->IsEmpty()) {
       mIdentifierMap.RemoveEntry(entry);
     }
   }
 }
 
 Element*
-nsDocument::LookupImageElement(const nsAString& aId)
+nsIDocument::LookupImageElement(const nsAString& aId)
 {
   if (aId.IsEmpty())
     return nullptr;
 
-  nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aId);
+  nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId);
   return entry ? entry->GetImageIdElement() : nullptr;
 }
 
 void
-nsDocument::DispatchContentLoadedEvents()
+nsIDocument::DispatchContentLoadedEvents()
 {
   // If you add early returns from this method, make sure you're
   // calling UnblockOnload properly.
 
   // Unpin references to preloaded images
   mPreloadingImages.Clear();
 
   // DOM manipulation after content loaded should not care if the element
@@ -5299,28 +5254,28 @@ nsDocument::DispatchContentLoadedEvents(
 
   if (mTiming) {
     mTiming->NotifyDOMContentLoadedStart(nsIDocument::GetDocumentURI());
   }
 
   // Dispatch observer notification to notify observers document is interactive.
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
-    nsIPrincipal *principal = GetPrincipal();
-    os->NotifyObservers(static_cast<nsIDocument*>(this),
+    nsIPrincipal* principal = NodePrincipal();
+    os->NotifyObservers(this,
                         nsContentUtils::IsSystemPrincipal(principal) ?
                           "chrome-document-interactive" :
                           "content-document-interactive",
                         nullptr);
   }
 
   // Fire a DOM event notifying listeners that this document has been
   // loaded (excluding images and other loads initiated by this
   // document).
-  nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
+  nsContentUtils::DispatchTrustedEvent(this, this,
                                        NS_LITERAL_STRING("DOMContentLoaded"),
                                        true, false);
 
   if (MayStartLayout()) {
     MaybeResolveReadyForIdle();
   }
 
   RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
@@ -5389,17 +5344,17 @@ nsDocument::DispatchContentLoadedEvents(
       parent = parent->GetParentDocument();
     } while (parent);
   }
 
   // If the document has a manifest attribute, fire a MozApplicationManifest
   // event.
   Element* root = GetRootElement();
   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::manifest)) {
-    nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
+    nsContentUtils::DispatchChromeEvent(this, this,
                                         NS_LITERAL_STRING("MozApplicationManifest"),
                                         true, true);
   }
 
   if (mMaybeServiceWorkerControlled) {
     using mozilla::dom::ServiceWorkerManager;
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (swm) {
@@ -5443,34 +5398,34 @@ nsDocument::EndLoad()
     return;
   }
   mDidCallBeginLoad = false;
 
   UnblockDOMContentLoaded();
 }
 
 void
-nsDocument::UnblockDOMContentLoaded()
+nsIDocument::UnblockDOMContentLoaded()
 {
   MOZ_ASSERT(mBlockDOMContentLoaded);
   if (--mBlockDOMContentLoaded != 0 || mDidFireDOMContentLoaded) {
     return;
   }
 
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p UnblockDOMContentLoaded", this));
 
   mDidFireDOMContentLoaded = true;
 
   MOZ_ASSERT(mReadyState == READYSTATE_INTERACTIVE);
   if (!mSynchronousDOMContentLoaded) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIRunnable> ev =
-      NewRunnableMethod("nsDocument::DispatchContentLoadedEvents",
+      NewRunnableMethod("nsIDocument::DispatchContentLoadedEvents",
                         this,
-                        &nsDocument::DispatchContentLoadedEvents);
+                        &nsIDocument::DispatchContentLoadedEvents);
     Dispatch(TaskCategory::Other, ev.forget());
   } else {
     DispatchContentLoadedEvents();
   }
 }
 
 void
 nsIDocument::ContentStateChanged(nsIContent* aContent, EventStates aStateMask)
@@ -5685,17 +5640,17 @@ nsIDocument::GetDoctype() const
     if (child->NodeType() == DOCUMENT_TYPE_NODE) {
       return static_cast<DocumentType*>(child);
     }
   }
   return nullptr;
 }
 
 DOMImplementation*
-nsDocument::GetImplementation(ErrorResult& rv)
+nsIDocument::GetImplementation(ErrorResult& rv)
 {
   if (!mDOMImplementation) {
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), "about:blank");
     if (!uri) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
@@ -5735,19 +5690,19 @@ GetPseudoElementType(const nsString& aSt
     return CSSPseudoElementType::NotPseudo;
   }
   RefPtr<nsAtom> pseudo = NS_Atomize(Substring(aString, 1));
   return nsCSSPseudoElements::GetPseudoType(pseudo,
       nsCSSProps::EnabledState::eInUASheets);
 }
 
 already_AddRefed<Element>
-nsDocument::CreateElement(const nsAString& aTagName,
-                          const ElementCreationOptionsOrString& aOptions,
-                          ErrorResult& rv)
+nsIDocument::CreateElement(const nsAString& aTagName,
+                           const ElementCreationOptionsOrString& aOptions,
+                           ErrorResult& rv)
 {
   rv = nsContentUtils::CheckQName(aTagName, false);
   if (rv.Failed()) {
     return nullptr;
   }
 
   bool needsLowercase = IsHTMLDocument() && !IsLowercaseASCII(aTagName);
   nsAutoString lcTagName;
@@ -5789,20 +5744,20 @@ nsDocument::CreateElement(const nsAStrin
   if (is) {
     elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
   }
 
   return elem.forget();
 }
 
 already_AddRefed<Element>
-nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
-                            const nsAString& aQualifiedName,
-                            const ElementCreationOptionsOrString& aOptions,
-                            ErrorResult& rv)
+nsIDocument::CreateElementNS(const nsAString& aNamespaceURI,
+                             const nsAString& aQualifiedName,
+                             const ElementCreationOptionsOrString& aOptions,
+                             ErrorResult& rv)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                             aQualifiedName,
                                             mNodeInfoManager,
                                             ELEMENT_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
@@ -6194,19 +6149,19 @@ GetElementByAttribute(Element* aElement,
     if (matchedElement)
       return matchedElement;
   }
 
   return nullptr;
 }
 
 Element*
-nsDocument::GetAnonymousElementByAttribute(nsIContent* aElement,
-                                           nsAtom* aAttrName,
-                                           const nsAString& aAttrValue) const
+nsIDocument::GetAnonymousElementByAttribute(nsIContent* aElement,
+                                            nsAtom* aAttrName,
+                                            const nsAString& aAttrValue) const
 {
   nsINodeList* nodeList = BindingManager()->GetAnonymousNodesFor(aElement);
   if (!nodeList)
     return nullptr;
 
   uint32_t length = 0;
   nodeList->GetLength(&length);
 
@@ -6357,17 +6312,17 @@ nsIDocument::SetBody(nsGenericHTMLElemen
   if (currentBody) {
     root->ReplaceChild(*newBody, *currentBody, rv);
   } else {
     root->AppendChild(*newBody, rv);
   }
 }
 
 Element*
-nsDocument::GetTitleElement()
+nsIDocument::GetTitleElement()
 {
   // mMayHaveTitleElement will have been set to true if any HTML or SVG
   // <title> element has been bound to this document. So if it's false,
   // we know there is nothing to do here. This avoids us having to search
   // the whole DOM if someone calls document.title on a large document
   // without a title.
   if (!mMayHaveTitleElement)
     return nullptr;
@@ -6394,17 +6349,17 @@ nsDocument::GetTitleElement()
                                                  /* aLiveList = */ false);
 
   nsIContent* first = list->Item(0, false);
 
   return first ? first->AsElement() : nullptr;
 }
 
 void
-nsDocument::GetTitle(nsAString& aTitle)
+nsIDocument::GetTitle(nsAString& aTitle)
 {
   aTitle.Truncate();
 
   Element* rootElement = GetRootElement();
   if (!rootElement) {
     return;
   }
 
@@ -6423,17 +6378,17 @@ nsDocument::GetTitle(nsAString& aTitle)
     nsContentUtils::GetNodeTextContent(title, false, tmp);
   }
 
   tmp.CompressWhitespace();
   aTitle = tmp;
 }
 
 void
-nsDocument::SetTitle(const nsAString& aTitle, ErrorResult& aRv)
+nsIDocument::SetTitle(const nsAString& aTitle, ErrorResult& aRv)
 {
   Element* rootElement = GetRootElement();
   if (!rootElement) {
     return;
   }
 
 #ifdef MOZ_XUL
   if (rootElement->IsXULElement()) {
@@ -6481,43 +6436,43 @@ nsDocument::SetTitle(const nsAString& aT
   } else {
     return;
   }
 
   aRv = nsContentUtils::SetNodeTextContent(title, aTitle, false);
 }
 
 void
-nsDocument::NotifyPossibleTitleChange(bool aBoundTitleElement)
+nsIDocument::NotifyPossibleTitleChange(bool aBoundTitleElement)
 {
   NS_ASSERTION(!mInUnlinkOrDeletion || !aBoundTitleElement,
                "Setting a title while unlinking or destroying the element?");
   if (mInUnlinkOrDeletion) {
     return;
   }
 
   if (aBoundTitleElement) {
     mMayHaveTitleElement = true;
   }
   if (mPendingTitleChangeEvent.IsPending())
     return;
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
-  RefPtr<nsRunnableMethod<nsDocument, void, false>> event =
-    NewNonOwningRunnableMethod("nsDocument::DoNotifyPossibleTitleChange",
+  RefPtr<nsRunnableMethod<nsIDocument, void, false>> event =
+    NewNonOwningRunnableMethod("nsIDocument::DoNotifyPossibleTitleChange",
                                this,
-                               &nsDocument::DoNotifyPossibleTitleChange);
+                               &nsIDocument::DoNotifyPossibleTitleChange);
   nsresult rv = Dispatch(TaskCategory::Other, do_AddRef(event));
   if (NS_SUCCEEDED(rv)) {
     mPendingTitleChangeEvent = Move(event);
   }
 }
 
 void
-nsDocument::DoNotifyPossibleTitleChange()
+nsIDocument::DoNotifyPossibleTitleChange()
 {
   mPendingTitleChangeEvent.Forget();
   mHaveFiredTitleChange = true;
 
   nsAutoString title;
   GetTitle(title);
 
   nsCOMPtr<nsIPresShell> shell = GetShell();
@@ -6534,17 +6489,17 @@ nsDocument::DoNotifyPossibleTitleChange(
 
   // Fire a DOM event for the title change.
   nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
                                       NS_LITERAL_STRING("DOMTitleChanged"),
                                       true, true);
 }
 
 already_AddRefed<BoxObject>
-nsDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv)
+nsIDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv)
 {
   if (!aElement) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsIDocument* doc = aElement->OwnerDoc();
   if (doc != this) {
@@ -6603,17 +6558,17 @@ nsDocument::GetBoxObjectFor(Element* aEl
 
   boxObject->Init(aElement);
   entry.OrInsert([&boxObject]() { return boxObject; });
 
   return boxObject.forget();
 }
 
 void
-nsDocument::ClearBoxObjectFor(nsIContent* aContent)
+nsIDocument::ClearBoxObjectFor(nsIContent* aContent)
 {
   if (mBoxObjectTable) {
     if (auto entry = mBoxObjectTable->Lookup(aContent)) {
       nsPIBoxObject* boxObject = entry.Data();
       boxObject->Clear();
       entry.Remove();
     }
   }
@@ -6627,17 +6582,17 @@ nsIDocument::MatchMedia(const nsAString&
     new MediaQueryList(this, aMediaQueryList, aCallerType);
 
   mDOMMediaQueryLists.insertBack(result);
 
   return result.forget();
 }
 
 void
-nsDocument::FlushSkinBindings()
+nsIDocument::FlushSkinBindings()
 {
   BindingManager()->FlushSkinBindings();
 }
 
 void
 nsIDocument::SetMayStartLayout(bool aMayStartLayout)
 {
   mMayStartLayout = aMayStartLayout;
@@ -6646,78 +6601,78 @@ nsIDocument::SetMayStartLayout(bool aMay
     if (state >= READYSTATE_INTERACTIVE) {
       // DOMContentLoaded has fired already.
       MaybeResolveReadyForIdle();
     }
   }
 }
 
 nsresult
-nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
+nsIDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
 {
   mInitializableFrameLoaders.RemoveElement(aLoader);
   // Don't even try to initialize.
   if (mInDestructor) {
     NS_WARNING("Trying to initialize a frame loader while"
                "document is being deleted");
     return NS_ERROR_FAILURE;
   }
 
   mInitializableFrameLoaders.AppendElement(aLoader);
   if (!mFrameLoaderRunner) {
     mFrameLoaderRunner =
-      NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+      NewRunnableMethod("nsIDocument::MaybeInitializeFinalizeFrameLoaders",
                         this,
-                        &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+                        &nsIDocument::MaybeInitializeFinalizeFrameLoaders);
     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
   }
   return NS_OK;
 }
 
 nsresult
-nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer)
+nsIDocument::FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer)
 {
   mInitializableFrameLoaders.RemoveElement(aLoader);
   if (mInDestructor) {
     return NS_ERROR_FAILURE;
   }
 
   mFrameLoaderFinalizers.AppendElement(aFinalizer);
   if (!mFrameLoaderRunner) {
     mFrameLoaderRunner =
-      NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+      NewRunnableMethod("nsIDocument::MaybeInitializeFinalizeFrameLoaders",
                         this,
-                        &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+                        &nsIDocument::MaybeInitializeFinalizeFrameLoaders);
     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
   }
   return NS_OK;
 }
 
 void
-nsDocument::MaybeInitializeFinalizeFrameLoaders()
+nsIDocument::MaybeInitializeFinalizeFrameLoaders()
 {
   if (mDelayFrameLoaderInitialization || mUpdateNestLevel != 0) {
     // This method will be recalled when mUpdateNestLevel drops to 0,
     // or when !mDelayFrameLoaderInitialization.
     mFrameLoaderRunner = nullptr;
     return;
   }
 
   // We're not in an update, but it is not safe to run scripts, so
   // postpone frameloader initialization and finalization.
   if (!nsContentUtils::IsSafeToRunScript()) {
     if (!mInDestructor && !mFrameLoaderRunner &&
         (mInitializableFrameLoaders.Length() ||
          mFrameLoaderFinalizers.Length())) {
       mFrameLoaderRunner =
-        NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+        NewRunnableMethod("nsIDocument::MaybeInitializeFinalizeFrameLoaders",
                           this,
-                          &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+                          &nsIDocument::MaybeInitializeFinalizeFrameLoaders);
       nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
     }
     return;
   }
   mFrameLoaderRunner = nullptr;
 
   // Don't use a temporary array for mInitializableFrameLoaders, because
   // loading a frame may cause some other frameloader to be removed from the
@@ -6735,52 +6690,52 @@ nsDocument::MaybeInitializeFinalizeFrame
     mFrameLoaderFinalizers.SwapElements(finalizers);
     for (uint32_t i = 0; i < length; ++i) {
       finalizers[i]->Run();
     }
   }
 }
 
 void
-nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
+nsIDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
 {
   uint32_t length = mInitializableFrameLoaders.Length();
   for (uint32_t i = 0; i < length; ++i) {
     if (mInitializableFrameLoaders[i]->GetExistingDocShell() == aShell) {
       mInitializableFrameLoaders.RemoveElementAt(i);
       return;
     }
   }
 }
 
 nsIDocument*
-nsDocument::RequestExternalResource(nsIURI* aURI,
-                                    nsINode* aRequestingNode,
-                                    ExternalResourceLoad** aPendingLoad)
+nsIDocument::RequestExternalResource(nsIURI* aURI,
+                                     nsINode* aRequestingNode,
+                                     ExternalResourceLoad** aPendingLoad)
 {
   NS_PRECONDITION(aURI, "Must have a URI");
   NS_PRECONDITION(aRequestingNode, "Must have a node");
   if (mDisplayDocument) {
     return mDisplayDocument->RequestExternalResource(aURI,
                                                      aRequestingNode,
                                                      aPendingLoad);
   }
 
   return mExternalResourceMap.RequestResource(aURI, aRequestingNode,
                                               this, aPendingLoad);
 }
 
 void
-nsDocument::EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData)
+nsIDocument::EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData)
 {
   mExternalResourceMap.EnumerateResources(aCallback, aData);
 }
 
 nsSMILAnimationController*
-nsDocument::GetAnimationController()
+nsIDocument::GetAnimationController()
 {
   // We create the animation controller lazily because most documents won't want
   // one and only SVG documents and the like will call this
   if (mAnimationController)
     return mAnimationController;
   // Refuse to create an Animation Controller for data documents.
   if (mLoadedAsData || mLoadedAsInteractiveData)
     return nullptr;
@@ -6801,17 +6756,17 @@ nsDocument::GetAnimationController()
   if (!mIsShowing && !mIsBeingUsedAsImage) {
     mAnimationController->OnPageHide();
   }
 
   return mAnimationController;
 }
 
 PendingAnimationTracker*
-nsDocument::GetOrCreatePendingAnimationTracker()
+nsIDocument::GetOrCreatePendingAnimationTracker()
 {
   if (!mPendingAnimationTracker) {
     mPendingAnimationTracker = new PendingAnimationTracker(this);
   }
 
   return mPendingAnimationTracker;
 }
 
@@ -7650,17 +7605,17 @@ Copy(nsIDocument* aDocument, void* aData
 {
   nsTArray<nsCOMPtr<nsIDocument> >* resources =
     static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
   resources->AppendElement(aDocument);
   return true;
 }
 
 void
-nsDocument::FlushExternalResources(FlushType aType)
+nsIDocument::FlushExternalResources(FlushType aType)
 {
   NS_ASSERTION(aType >= FlushType::Style,
     "should only need to flush for style or higher in external resources");
   if (GetDisplayDocument()) {
     return;
   }
   nsTArray<nsCOMPtr<nsIDocument> > resources;
   EnumerateExternalResources(Copy, &resources);
@@ -7721,17 +7676,17 @@ nsDocument::GetXMLDeclaration(nsAString&
       aStandalone.AssignLiteral("yes");
     } else {
       aStandalone.AssignLiteral("no");
     }
   }
 }
 
 bool
-nsDocument::IsScriptEnabled()
+nsIDocument::IsScriptEnabled()
 {
   // If this document is sandboxed without 'allow-scripts'
   // script is not enabled
   if (HasScriptsBlockedBySandbox()) {
     return false;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> globalObject = do_QueryInterface(GetInnerWindow());
@@ -7991,17 +7946,17 @@ nsDocument::CreateElem(const nsAString& 
   nsAutoString qName;
   if (aPrefix) {
     aPrefix->ToString(qName);
     qName.Append(':');
   }
   qName.Append(aName);
 
   // Note: "a:b:c" is a valid name in non-namespaces XML, and
-  // nsDocument::CreateElement can call us with such a name and no prefix,
+  // nsIDocument::CreateElement can call us with such a name and no prefix,
   // which would cause an error if we just used true here.
   bool nsAware = aPrefix != nullptr || aNamespaceID != GetDefaultNamespaceID();
   NS_ASSERTION(NS_SUCCEEDED(nsContentUtils::CheckQName(qName, nsAware)),
                "Don't pass invalid prefixes to nsDocument::CreateElem, "
                "check caller.");
 #endif
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
@@ -8021,17 +7976,17 @@ nsIDocument::IsSafeToFlush() const
   nsIPresShell* shell = GetShell();
   if (!shell)
     return true;
 
   return shell->IsSafeToFlush();
 }
 
 void
-nsDocument::Sanitize()
+nsIDocument::Sanitize()
 {
   // Sanitize the document by resetting all password fields and any form
   // fields with autocomplete=off to their default values.  We do this now,
   // instead of when the presentation is restored, to offer some protection
   // in case there is ever an exploit that allows a cached document to be
   // accessed from a different document.
 
   // First locate all input elements, regardless of whether they are
@@ -8078,17 +8033,17 @@ nsDocument::Sanitize()
 
     form->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete, value);
     if (value.LowerCaseEqualsLiteral("off"))
       form->Reset();
   }
 }
 
 void
-nsDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
+nsIDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
 {
   if (!mSubDocuments) {
     return;
   }
 
   // PLDHashTable::Iterator can't handle modifications while iterating so we
   // copy all entries to an array first before calling any callbacks.
   AutoTArray<nsCOMPtr<nsIDocument>, 8> subdocs;
@@ -8102,17 +8057,17 @@ nsDocument::EnumerateSubDocuments(nsSubD
   for (auto subdoc : subdocs) {
     if (!aCallback(subdoc, aData)) {
       break;
     }
   }
 }
 
 void
-nsDocument::CollectDescendantDocuments(
+nsIDocument::CollectDescendantDocuments(
   nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
   nsDocTestFunc aCallback) const
 {
   if (!mSubDocuments) {
     return;
   }
 
   for (auto iter = mSubDocuments->Iter(); !iter.Done(); iter.Next()) {
@@ -8127,17 +8082,17 @@ nsDocument::CollectDescendantDocuments(
   }
 }
 
 #ifdef DEBUG_bryner
 #define DEBUG_PAGE_CACHE
 #endif
 
 bool
-nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
+nsIDocument::CanSavePresentation(nsIRequest *aNewRequest)
 {
   if (EventHandlingSuppressed()) {
     return false;
   }
 
   // Do not allow suspended windows to be placed in the
   // bfcache.  This method is also used to verify a document
   // coming out of the bfcache is ok to restore, though.  So
@@ -8289,17 +8244,17 @@ nsDocument::RemovedFromDocShell()
 
   uint32_t i, count = mChildren.ChildCount();
   for (i = 0; i < count; ++i) {
     mChildren.ChildAt(i)->SaveSubtreeState();
   }
 }
 
 already_AddRefed<nsILayoutHistoryState>
-nsDocument::GetLayoutHistoryState() const
+nsIDocument::GetLayoutHistoryState() const
 {
   nsCOMPtr<nsILayoutHistoryState> state;
   if (!mScriptGlobalObject) {
     state = mLayoutHistoryState;
   } else {
     nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
     if (docShell) {
       docShell->GetLayoutHistoryState(getter_AddRefs(state));
@@ -8497,19 +8452,19 @@ nsIDocument::GetContentInThisDocument(ns
     // the containing document.
     f = f->PresContext()->GetPresShell()->GetRootFrame();
   }
 
   return nullptr;
 }
 
 void
-nsDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
-                                   const nsAString& aType,
-                                   bool aPersisted)
+nsIDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
+                                    const nsAString& aType,
+                                    bool aPersisted)
 {
   if (!aDispatchTarget) {
     return;
   }
 
   PageTransitionEventInit init;
   init.mBubbles = true;
   init.mCancelable = true;
@@ -8531,18 +8486,17 @@ static bool
 NotifyPageShow(nsIDocument* aDocument, void* aData)
 {
   const bool* aPersistedPtr = static_cast<const bool*>(aData);
   aDocument->OnPageShow(*aPersistedPtr, nullptr);
   return true;
 }
 
 void
-nsDocument::OnPageShow(bool aPersisted,
-                       EventTarget* aDispatchStartTarget)
+nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget)
 {
   mVisible = true;
 
   EnumerateActivityObservers(NotifyActivityChanged, nullptr);
   EnumerateExternalResources(NotifyPageShow, &aPersisted);
 
   Element* root = GetRootElement();
   if (aPersisted && root) {
@@ -8573,18 +8527,18 @@ nsDocument::OnPageShow(bool aPersisted,
   }
 
   UpdateVisibilityState();
 
   if (!mIsBeingUsedAsImage) {
     // Dispatch observer notification to notify observers page is shown.
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
-      nsIPrincipal *principal = GetPrincipal();
-      os->NotifyObservers(static_cast<nsIDocument*>(this),
+      nsIPrincipal* principal = NodePrincipal();
+      os->NotifyObservers(this,
                           nsContentUtils::IsSystemPrincipal(principal) ?
                             "chrome-page-shown" :
                             "content-page-shown",
                           nullptr);
     }
 
     nsCOMPtr<EventTarget> target = aDispatchStartTarget;
     if (!target) {
@@ -8623,26 +8577,25 @@ DispatchFullScreenChange(nsIDocument* aT
   DispatchCustomEventWithFlush(
     aTarget, NS_LITERAL_STRING("fullscreenchange"),
     /* Bubbles */ true, /* OnlyChrome */ false);
 }
 
 static void ClearPendingFullscreenRequests(nsIDocument* aDoc);
 
 void
-nsDocument::OnPageHide(bool aPersisted,
-                       EventTarget* aDispatchStartTarget)
+nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
 {
   // Send out notifications that our <link> elements are detached,
   // but only if this is not a full unload.
   Element* root = GetRootElement();
   if (aPersisted && root) {
     RefPtr<nsContentList> links = NS_GetContentList(root,
-                                                      kNameSpaceID_XHTML,
-                                                      NS_LITERAL_STRING("link"));
+                                                    kNameSpaceID_XHTML,
+                                                    NS_LITERAL_STRING("link"));
 
     uint32_t linkCount = links->Length(true);
     for (uint32_t i = 0; i < linkCount; ++i) {
       static_cast<HTMLLinkElement*>(links->Item(i, false))->LinkRemoved();
     }
   }
 
   // See nsIDocument
@@ -8664,18 +8617,18 @@ nsDocument::OnPageHide(bool aPersisted,
   }
 
   ExitPointerLock();
 
   if (!mIsBeingUsedAsImage) {
     // Dispatch observer notification to notify observers page is hidden.
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
-      nsIPrincipal* principal = GetPrincipal();
-      os->NotifyObservers(static_cast<nsIDocument*>(this),
+      nsIPrincipal* principal = NodePrincipal();
+      os->NotifyObservers(this,
                           nsContentUtils::IsSystemPrincipal(principal) ?
                             "chrome-page-hidden" :
                             "content-page-hidden",
                           nullptr);
     }
 
     // Now send out a PageHide event.
     nsCOMPtr<EventTarget> target = aDispatchStartTarget;
@@ -8720,34 +8673,34 @@ nsDocument::OnPageHide(bool aPersisted,
 
     // If anyone was listening to this document's state, advertizing the state
     // change would be the least of the politeness.
     DispatchFullScreenChange(this);
   }
 }
 
 void
-nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
+nsIDocument::WillDispatchMutationEvent(nsINode* aTarget)
 {
   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
                mSubtreeModifiedTargets.Count() == 0,
                "mSubtreeModifiedTargets not cleared after dispatching?");
   ++mSubtreeModifiedDepth;
   if (aTarget) {
     // MayDispatchMutationEvent is often called just before this method,
     // so it has already appended the node to mSubtreeModifiedTargets.
     int32_t count = mSubtreeModifiedTargets.Count();
     if (!count || mSubtreeModifiedTargets[count - 1] != aTarget) {
       mSubtreeModifiedTargets.AppendObject(aTarget);
     }
   }
 }
 
 void
-nsDocument::MutationEventDispatched(nsINode* aTarget)
+nsIDocument::MutationEventDispatched(nsINode* aTarget)
 {
   --mSubtreeModifiedDepth;
   if (mSubtreeModifiedDepth == 0) {
     int32_t count = mSubtreeModifiedTargets.Count();
     if (!count) {
       return;
     }
 
@@ -8788,52 +8741,28 @@ nsDocument::MutationEventDispatched(nsIN
       InternalMutationEvent mutation(true, eLegacySubtreeModified);
       (new AsyncEventDispatcher(realTargets[k], mutation))->
         RunDOMEventWhenSafe();
     }
   }
 }
 
 void
-nsDocument::AddStyleRelevantLink(Link* aLink)
-{
-  NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
-#ifdef DEBUG
-  nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
-  NS_ASSERTION(!entry, "Document already knows about this Link!");
-  mStyledLinksCleared = false;
-#endif
-  (void)mStyledLinks.PutEntry(aLink);
-}
-
-void
-nsDocument::ForgetLink(Link* aLink)
-{
-  NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
-#ifdef DEBUG
-  nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
-  NS_ASSERTION(entry || mStyledLinksCleared,
-               "Document knows nothing about this Link!");
-#endif
-  mStyledLinks.RemoveEntry(aLink);
-}
-
-void
-nsDocument::DestroyElementMaps()
+nsIDocument::DestroyElementMaps()
 {
 #ifdef DEBUG
   mStyledLinksCleared = true;
 #endif
   mStyledLinks.Clear();
   mIdentifierMap.Clear();
-  ++mExpandoAndGeneration.generation;
-}
-
-void
-nsDocument::RefreshLinkHrefs()
+  IncrementExpandoGeneration(*this);
+}
+
+void
+nsIDocument::RefreshLinkHrefs()
 {
   // Get a list of all links we know about.  We will reset them, which will
   // remove them from the document, so we need a copy of what is in the
   // hashtable.
   LinkArray linksToNotify(mStyledLinks.Count());
   for (auto iter = mStyledLinks.ConstIter(); !iter.Done(); iter.Next()) {
     linksToNotify.AppendElement(iter.Get()->GetKey());
   }
@@ -8928,17 +8857,17 @@ nsDocument::CloneDocHelper(nsDocument* c
   // Preallocate attributes and child arrays
   rv = clone->mChildren.EnsureCapacityToClone(mChildren, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 void
-nsDocument::SetReadyStateInternal(ReadyState rs)
+nsIDocument::SetReadyStateInternal(ReadyState rs)
 {
   mReadyState = rs;
   if (rs == READYSTATE_UNINITIALIZED) {
     // Transition back to uninitialized happens only to keep assertions happy
     // right before readyState transitions to something else. Make this
     // transition undetectable by Web content.
     return;
   }
@@ -8993,29 +8922,29 @@ static bool
 SuppressEventHandlingInDocument(nsIDocument* aDocument, void* aData)
 {
   aDocument->SuppressEventHandling(*static_cast<uint32_t*>(aData));
 
   return true;
 }
 
 void
-nsDocument::SuppressEventHandling(uint32_t aIncrease)
+nsIDocument::SuppressEventHandling(uint32_t aIncrease)
 {
   mEventsSuppressed += aIncrease;
   UpdateFrameRequestCallbackSchedulingState();
   for (uint32_t i = 0; i < aIncrease; ++i) {
     ScriptLoader()->AddExecuteBlocker();
   }
 
   EnumerateSubDocuments(SuppressEventHandlingInDocument, &aIncrease);
 }
 
 static void
-FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
+FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument>>& aDocuments,
                          bool aFireEvents)
 {
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (!fm)
     return;
 
   for (uint32_t i = 0; i < aDocuments.Length(); ++i) {
     // NB: Don't bother trying to fire delayed events on documents that were
@@ -9030,37 +8959,30 @@ FireOrClearDelayedEvents(nsTArray<nsCOMP
                     aDocuments[i]->GetInnerWindow()->IsCurrentInnerWindow();
         shell->FireOrClearDelayedEvents(fire);
       }
     }
   }
 }
 
 void
-nsDocument::PreloadPictureOpened()
-{
-  mPreloadPictureDepth++;
-}
-
-void
-nsDocument::PreloadPictureClosed()
-{
+nsIDocument::PreloadPictureClosed()
+{
+  MOZ_ASSERT(mPreloadPictureDepth > 0);
   mPreloadPictureDepth--;
   if (mPreloadPictureDepth == 0) {
     mPreloadPictureFoundSource.SetIsVoid(true);
-  } else {
-    MOZ_ASSERT(mPreloadPictureDepth >= 0);
-  }
-}
-
-void
-nsDocument::PreloadPictureImageSource(const nsAString& aSrcsetAttr,
-                                      const nsAString& aSizesAttr,
-                                      const nsAString& aTypeAttr,
-                                      const nsAString& aMediaAttr)
+  }
+}
+
+void
+nsIDocument::PreloadPictureImageSource(const nsAString& aSrcsetAttr,
+                                       const nsAString& aSizesAttr,
+                                       const nsAString& aTypeAttr,
+                                       const nsAString& aMediaAttr)
 {
   // Nested pictures are not valid syntax, so while we'll eventually load them,
   // it's not worth tracking sources mixed between nesting levels to preload
   // them effectively.
   if (mPreloadPictureDepth == 1 && mPreloadPictureFoundSource.IsVoid()) {
     // <picture> selects the first matching source, so if this returns a URI we
     // needn't consider new sources until a new <picture> is encountered.
     bool found =
@@ -9071,21 +8993,21 @@ nsDocument::PreloadPictureImageSource(co
     if (found && mPreloadPictureFoundSource.IsVoid()) {
       // Found an empty source, which counts
       mPreloadPictureFoundSource.SetIsVoid(false);
     }
   }
 }
 
 already_AddRefed<nsIURI>
-nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
-                                const nsAString& aSrcAttr,
-                                const nsAString& aSrcsetAttr,
-                                const nsAString& aSizesAttr,
-                                bool *aIsImgSet)
+nsIDocument::ResolvePreloadImage(nsIURI *aBaseURI,
+                                 const nsAString& aSrcAttr,
+                                 const nsAString& aSrcsetAttr,
+                                 const nsAString& aSizesAttr,
+                                 bool *aIsImgSet)
 {
   nsString sourceURL;
   bool isImgSet;
   if (mPreloadPictureDepth == 1 && !mPreloadPictureFoundSource.IsVoid()) {
     // We're in a <picture> element and found a URI from a source previous to
     // this image, use it.
     sourceURL = mPreloadPictureFoundSource;
     isImgSet = true;
@@ -9117,23 +9039,25 @@ nsDocument::ResolvePreloadImage(nsIURI *
 
   // We don't clear mPreloadPictureFoundSource because subsequent <img> tags in
   // this this <picture> share the same <sources> (though this is not valid per
   // spec)
   return uri.forget();
 }
 
 void
-nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
-                              ReferrerPolicy aReferrerPolicy, bool aIsImgSet)
+nsIDocument::MaybePreLoadImage(nsIURI* uri,
+                               const nsAString &aCrossOriginAttr,
+                               enum ReferrerPolicy aReferrerPolicy,
+                               bool aIsImgSet)
 {
   // Early exit if the img is already present in the img-cache
   // which indicates that the "real" load has already started and
   // that we shouldn't preload it.
-  if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this))) {
+  if (nsContentUtils::IsImageInCache(uri, this)) {
     return;
   }
 
   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL |
                           nsContentUtils::CORSModeToLoadImageFlags(
                             Element::StringToCORSMode(aCrossOriginAttr));
 
   nsContentPolicyType policyType =
@@ -9160,17 +9084,17 @@ nsDocument::MaybePreLoadImage(nsIURI* ur
   // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
   // unlink
   if (NS_SUCCEEDED(rv)) {
     mPreloadingImages.Put(uri, request.forget());
   }
 }
 
 void
-nsDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode)
+nsIDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode)
 {
   NS_MutateURI mutator(aOrigURI);
   if (NS_FAILED(mutator.GetStatus())) {
       return;
   }
 
   // The URI created here is used in 2 contexts. One is nsISpeculativeConnect
   // which ignores the path and uses only the origin. The other is for the
@@ -9206,17 +9130,17 @@ nsDocument::MaybePreconnect(nsIURI* aOri
   if (aCORSMode == CORS_ANONYMOUS) {
     speculator->SpeculativeAnonymousConnect2(uri, NodePrincipal(), nullptr);
   } else {
     speculator->SpeculativeConnect2(uri, NodePrincipal(), nullptr);
   }
 }
 
 void
-nsDocument::ForgetImagePreload(nsIURI* aURI)
+nsIDocument::ForgetImagePreload(nsIURI* aURI)
 {
   // Checking count is faster than hashing the URI in the common
   // case of empty table.
   if (mPreloadingImages.Count() != 0) {
     nsCOMPtr<imgIRequest> req;
     mPreloadingImages.Remove(aURI, getter_AddRefs(req));
     if (req) {
       // Make sure to cancel the request so imagelib knows it's gone.
@@ -9308,59 +9232,57 @@ public:
 
   NS_IMETHOD Run() override
   {
     FireOrClearDelayedEvents(mDocuments, true);
     return NS_OK;
   }
 
 private:
-  nsTArray<nsCOMPtr<nsIDocument> > mDocuments;
+  nsTArray<nsCOMPtr<nsIDocument>> mDocuments;
 };
 
 static bool
-GetAndUnsuppressSubDocuments(nsIDocument* aDocument,
-                             void* aData)
+GetAndUnsuppressSubDocuments(nsIDocument* aDocument, void* aData)
 {
   if (aDocument->EventHandlingSuppressed() > 0) {
-    static_cast<nsDocument*>(aDocument)->DecreaseEventSuppression();
+    aDocument->DecreaseEventSuppression();
     aDocument->ScriptLoader()->RemoveExecuteBlocker();
   }
 
-  nsTArray<nsCOMPtr<nsIDocument> >* docs =
-    static_cast<nsTArray<nsCOMPtr<nsIDocument> >* >(aData);
+  auto* docs = static_cast<nsTArray<nsCOMPtr<nsIDocument>>*>(aData);
 
   docs->AppendElement(aDocument);
   aDocument->EnumerateSubDocuments(GetAndUnsuppressSubDocuments, aData);
   return true;
 }
 
 void
-nsDocument::UnsuppressEventHandlingAndFireEvents(bool aFireEvents)
+nsIDocument::UnsuppressEventHandlingAndFireEvents(bool aFireEvents)
 {
   nsTArray<nsCOMPtr<nsIDocument>> documents;
   GetAndUnsuppressSubDocuments(this, &documents);
 
   if (aFireEvents) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIRunnable> ded = new nsDelayedEventDispatcher(documents);
     Dispatch(TaskCategory::Other, ded.forget());
   } else {
     FireOrClearDelayedEvents(documents, false);
   }
 }
 
 nsISupports*
-nsDocument::GetCurrentContentSink()
+nsIDocument::GetCurrentContentSink()
 {
   return mParser ? mParser->GetContentSink() : nullptr;
 }
 
 nsIDocument*
-nsDocument::GetTemplateContentsOwner()
+nsIDocument::GetTemplateContentsOwner()
 {
   if (!mTemplateContentsOwner) {
     bool hasHadScriptObject = true;
     nsIScriptGlobalObject* scriptObject =
       GetScriptHandlingObject(hasHadScriptObject);
 
     nsCOMPtr<nsIDOMDocument> domDocument;
     nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
@@ -9450,17 +9372,17 @@ public:
     return rv.StealNSResult();
   }
 private:
   nsCOMPtr<Element> mElement;
   nsCOMPtr<nsPIDOMWindowOuter> mTopWindow;
 };
 
 void
-nsDocument::SetAutoFocusElement(Element* aAutoFocusElement)
+nsIDocument::SetAutoFocusElement(Element* aAutoFocusElement)
 {
   if (mAutoFocusFired) {
     // Too late.
     return;
   }
 
   if (mAutoFocusElement) {
     // The spec disallows multiple autofocus elements, so we consider only the
@@ -9468,17 +9390,17 @@ nsDocument::SetAutoFocusElement(Element*
     return;
   }
 
   mAutoFocusElement = do_GetWeakReference(aAutoFocusElement);
   TriggerAutoFocus();
 }
 
 void
-nsDocument::TriggerAutoFocus()
+nsIDocument::TriggerAutoFocus()
 {
   if (mAutoFocusFired) {
     return;
   }
 
   if (!mPresShell || !mPresShell->DidInitialize()) {
     // Delay autofocus until frames are constructed so that we don't thrash
     // style and layout calculations.
@@ -9505,17 +9427,17 @@ nsDocument::TriggerAutoFocus()
     nsCOMPtr<nsIRunnable> event =
       new nsAutoFocusEvent(autoFocusElement.forget(), topWindow.forget());
     nsresult rv = NS_DispatchToCurrentThread(event.forget());
     NS_ENSURE_SUCCESS_VOID(rv);
   }
 }
 
 void
-nsDocument::SetScrollToRef(nsIURI *aDocumentURI)
+nsIDocument::SetScrollToRef(nsIURI* aDocumentURI)
 {
   if (!aDocumentURI) {
     return;
   }
 
   nsAutoCString ref;
 
   // Since all URI's that pass through here aren't URL's we can't
@@ -9537,17 +9459,17 @@ nsDocument::SetScrollToRef(nsIURI *aDocu
   if (FindCharInReadable('#', start, end)) {
     ++start; // Skip over the '#'
 
     mScrollToRef = Substring(start, end);
   }
 }
 
 void
-nsDocument::ScrollToRef()
+nsIDocument::ScrollToRef()
 {
   if (mScrolledToRefAlready) {
     nsCOMPtr<nsIPresShell> shell = GetShell();
     if (shell) {
       shell->ScrollToAnchor();
     }
     return;
   }
@@ -9597,28 +9519,16 @@ nsDocument::ScrollToRef()
     }
     if (NS_SUCCEEDED(rv)) {
       mScrolledToRefAlready = true;
     }
   }
 }
 
 void
-nsDocument::ResetScrolledToRefAlready()
-{
-  mScrolledToRefAlready = false;
-}
-
-void
-nsDocument::SetChangeScrollPosWhenScrollingToRef(bool aValue)
-{
-  mChangeScrollPosWhenScrollingToRef = aValue;
-}
-
-void
 nsIDocument::RegisterActivityObserver(nsISupports* aSupports)
 {
   if (!mActivityObservers) {
     mActivityObservers = new nsTHashtable<nsPtrHashKey<nsISupports> >();
   }
   mActivityObservers->PutEntry(aSupports);
 }
 
@@ -9811,17 +9721,17 @@ nsIDocument::CancelFrameRequestCallback(
 {
   // mFrameRequestCallbacks is stored sorted by handle
   if (mFrameRequestCallbacks.RemoveElementSorted(aHandle)) {
     UpdateFrameRequestCallbackSchedulingState();
   }
 }
 
 nsresult
-nsDocument::GetStateObject(nsIVariant** aState)
+nsIDocument::GetStateObject(nsIVariant** aState)
 {
   // Get the document's current state object. This is the object backing both
   // history.state and popStateEvent.state.
   //
   // mStateObjectContainer may be null; this just means that there's no
   // current state object.
 
   if (!mStateObjectCached && mStateObjectContainer) {
@@ -9832,38 +9742,30 @@ nsDocument::GetStateObject(nsIVariant** 
     NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
     JSAutoCompartment ac(cx, global);
 
     mStateObjectContainer->
       DeserializeToVariant(cx, getter_AddRefs(mStateObjectCached));
   }
 
   NS_IF_ADDREF(*aState = mStateObjectCached);
-
   return NS_OK;
 }
 
-nsDOMNavigationTiming*
-nsDocument::GetNavigationTiming() const
-{
-  return mTiming;
-}
-
-nsresult
-nsDocument::SetNavigationTiming(nsDOMNavigationTiming* aTiming)
+void
+nsIDocument::SetNavigationTiming(nsDOMNavigationTiming* aTiming)
 {
   mTiming = aTiming;
   if (!mLoadingTimeStamp.IsNull() && mTiming) {
-    mTiming->SetDOMLoadingTimeStamp(nsIDocument::GetDocumentURI(), mLoadingTimeStamp);
-  }
-  return NS_OK;
+    mTiming->SetDOMLoadingTimeStamp(GetDocumentURI(), mLoadingTimeStamp);
+  }
 }
 
 Element*
-nsDocument::FindImageMap(const nsAString& aUseMapValue)
+nsIDocument::FindImageMap(const nsAString& aUseMapValue)
 {
   if (aUseMapValue.IsEmpty()) {
     return nullptr;
   }
 
   nsAString::const_iterator start, end;
   aUseMapValue.BeginReading(start);
   aUseMapValue.EndReading(end);
@@ -9988,79 +9890,43 @@ mozilla::dom::ImageTracker*
 nsIDocument::ImageTracker()
 {
   if (!mImageTracker) {
     mImageTracker = new mozilla::dom::ImageTracker;
   }
   return mImageTracker;
 }
 
-nsresult
-nsDocument::AddPlugin(nsIObjectLoadingContent* aPlugin)
-{
-  MOZ_ASSERT(aPlugin);
-  if (!mPlugins.PutEntry(aPlugin)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_OK;
-}
-
-void
-nsDocument::RemovePlugin(nsIObjectLoadingContent* aPlugin)
-{
-  MOZ_ASSERT(aPlugin);
-  mPlugins.RemoveEntry(aPlugin);
-}
-
 static bool
 AllSubDocumentPluginEnum(nsIDocument* aDocument, void* userArg)
 {
   nsTArray<nsIObjectLoadingContent*>* plugins =
-    reinterpret_cast< nsTArray<nsIObjectLoadingContent*>* >(userArg);
+    reinterpret_cast<nsTArray<nsIObjectLoadingContent*>*>(userArg);
   MOZ_ASSERT(plugins);
   aDocument->GetPlugins(*plugins);
   return true;
 }
 
 void
-nsDocument::GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins)
+nsIDocument::GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins)
 {
   aPlugins.SetCapacity(aPlugins.Length() + mPlugins.Count());
   for (auto iter = mPlugins.ConstIter(); !iter.Done(); iter.Next()) {
     aPlugins.AppendElement(iter.Get()->GetKey());
   }
   EnumerateSubDocuments(AllSubDocumentPluginEnum, &aPlugins);
 }
 
-nsresult
-nsDocument::AddResponsiveContent(nsIContent* aContent)
-{
-  MOZ_ASSERT(aContent);
-  MOZ_ASSERT(aContent->IsHTMLElement(nsGkAtoms::img));
-  mResponsiveContent.PutEntry(aContent);
-  return NS_OK;
-}
-
-void
-nsDocument::RemoveResponsiveContent(nsIContent* aContent)
-{
-  MOZ_ASSERT(aContent);
-  mResponsiveContent.RemoveEntry(aContent);
-}
-
-void
-nsDocument::NotifyMediaFeatureValuesChanged()
+void
+nsIDocument::NotifyMediaFeatureValuesChanged()
 {
   for (auto iter = mResponsiveContent.ConstIter(); !iter.Done();
        iter.Next()) {
-    nsCOMPtr<nsIContent> content = iter.Get()->GetKey();
-    if (content->IsHTMLElement(nsGkAtoms::img)) {
-      auto* imageElement = static_cast<HTMLImageElement*>(content.get());
-      imageElement->MediaFeatureValuesChanged();
-    }
+    RefPtr<HTMLImageElement> imageElement = iter.Get()->GetKey();
+    imageElement->MediaFeatureValuesChanged();
   }
 }
 
 already_AddRefed<Touch>
 nsIDocument::CreateTouch(nsGlobalWindowInner* aView,
                          EventTarget* aTarget,
                          int32_t aIdentifier,
                          int32_t aPageX, int32_t aPageY,
@@ -10569,24 +10435,24 @@ FullscreenRoots::IsEmpty()
 {
   return !sInstance;
 }
 
 } // end namespace mozilla.
 using mozilla::FullscreenRoots;
 
 nsIDocument*
-nsDocument::GetFullscreenRoot()
+nsIDocument::GetFullscreenRoot()
 {
   nsCOMPtr<nsIDocument> root = do_QueryReferent(mFullscreenRoot);
   return root;
 }
 
 void
-nsDocument::SetFullscreenRoot(nsIDocument* aRoot)
+nsIDocument::SetFullscreenRoot(nsIDocument* aRoot)
 {
   mFullscreenRoot = do_GetWeakReference(aRoot);
 }
 
 void
 nsIDocument::ExitFullscreen()
 {
   RestorePreviousFullScreenState();
@@ -10656,33 +10522,33 @@ static uint32_t
 CountFullscreenSubDocuments(nsIDocument* aDoc)
 {
   uint32_t count = 0;
   aDoc->EnumerateSubDocuments(CountFullscreenSubDocuments, &count);
   return count;
 }
 
 bool
-nsDocument::IsFullscreenLeaf()
+nsIDocument::IsFullscreenLeaf()
 {
   // A fullscreen leaf document is fullscreen, and has no fullscreen
   // subdocuments.
   if (!FullScreenStackTop()) {
     return false;
   }
   return CountFullscreenSubDocuments(this) == 0;
 }
 
 static bool
 ResetFullScreen(nsIDocument* aDocument, void* aData)
 {
   if (aDocument->FullScreenStackTop()) {
     NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
         "Should have at most 1 fullscreen subdocument.");
-    static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
+    aDocument->CleanupFullscreenState();
     NS_ASSERTION(!aDocument->FullScreenStackTop(),
                  "Should reset full-screen");
     auto changed = reinterpret_cast<nsCOMArray<nsIDocument>*>(aData);
     changed->AppendElement(aDocument);
     aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
   }
   return true;
 }
@@ -10797,56 +10663,55 @@ GetFullscreenLeaf(nsIDocument* aDoc)
   if (!root->FullScreenStackTop()) {
     return nullptr;
   }
   GetFullscreenLeaf(root, &leaf);
   return leaf;
 }
 
 void
-nsDocument::RestorePreviousFullScreenState()
+nsIDocument::RestorePreviousFullScreenState()
 {
   NS_ASSERTION(!FullScreenStackTop() || !FullscreenRoots::IsEmpty(),
     "Should have at least 1 fullscreen root when fullscreen!");
 
   if (!FullScreenStackTop() || !GetWindow() || FullscreenRoots::IsEmpty()) {
     return;
   }
 
   nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
-  AutoTArray<nsDocument*, 8> exitDocs;
+  AutoTArray<nsIDocument*, 8> exitDocs;
 
   nsIDocument* doc = fullScreenDoc;
   // Collect all subdocuments.
   for (; doc != this; doc = doc->GetParentDocument()) {
-    exitDocs.AppendElement(static_cast<nsDocument*>(doc));
+    exitDocs.AppendElement(doc);
   }
   MOZ_ASSERT(doc == this, "Must have reached this doc");
   // Collect all ancestor documents which we are going to change.
   for (; doc; doc = doc->GetParentDocument()) {
-    nsDocument* theDoc = static_cast<nsDocument*>(doc);
-    MOZ_ASSERT(!theDoc->mFullScreenStack.IsEmpty(),
+    MOZ_ASSERT(!doc->mFullScreenStack.IsEmpty(),
                "Ancestor of fullscreen document must also be in fullscreen");
     if (doc != this) {
-      Element* top = theDoc->FullScreenStackTop();
+      Element* top = doc->FullScreenStackTop();
       if (top->IsHTMLElement(nsGkAtoms::iframe)) {
         if (static_cast<HTMLIFrameElement*>(top)->FullscreenFlag()) {
           // If this is an iframe, and it explicitly requested
           // fullscreen, don't rollback it automatically.
           break;
         }
       }
     }
-    exitDocs.AppendElement(theDoc);
-    if (theDoc->mFullScreenStack.Length() > 1) {
+    exitDocs.AppendElement(doc);
+    if (doc->mFullScreenStack.Length() > 1) {
       break;
     }
   }
 
-  nsDocument* lastDoc = exitDocs.LastElement();
+  nsIDocument* lastDoc = exitDocs.LastElement();
   if (!lastDoc->GetParentDocument() &&
       lastDoc->mFullScreenStack.Length() == 1) {
     // If we are fully exiting fullscreen, don't touch anything here,
     // just wait for the window to get out from fullscreen first.
     AskWindowToExitFullscreen(this);
     return;
   }
 
@@ -10863,17 +10728,17 @@ nsDocument::RestorePreviousFullScreenSta
   if (lastDoc->mFullScreenStack.Length() > 1) {
     lastDoc->FullScreenStackPop();
     newFullscreenDoc = lastDoc;
   } else {
     lastDoc->CleanupFullscreenState();
     newFullscreenDoc = lastDoc->GetParentDocument();
   }
   // Dispatch the fullscreenchange event to all document listed.
-  for (nsDocument* d : exitDocs) {
+  for (nsIDocument* d : exitDocs) {
     DispatchFullScreenChange(d);
   }
 
   MOZ_ASSERT(newFullscreenDoc, "If we were going to exit from fullscreen on "
              "all documents in this doctree, we should've asked the window to "
              "exit first instead of reaching here.");
   if (fullScreenDoc != newFullscreenDoc &&
       !nsContentUtils::HaveEqualPrincipals(fullScreenDoc, newFullscreenDoc)) {
@@ -10901,17 +10766,17 @@ public:
     mRequest->GetDocument()->RequestFullScreen(Move(mRequest));
     return NS_OK;
   }
 
   UniquePtr<FullscreenRequest> mRequest;
 };
 
 void
-nsDocument::AsyncRequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
+nsIDocument::AsyncRequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
 {
   if (!aRequest->GetElement()) {
     MOZ_ASSERT_UNREACHABLE(
       "Must pass non-null element to nsDocument::AsyncRequestFullScreen");
     return;
   }
 
   // Request full-screen asynchronously.
@@ -10950,17 +10815,17 @@ ClearFullscreenStateOnElement(Element* a
   EventStateManager::SetFullScreenState(aElement, false);
   // Reset iframe fullscreen flag.
   if (aElement->IsHTMLElement(nsGkAtoms::iframe)) {
     static_cast<HTMLIFrameElement*>(aElement)->SetFullscreenFlag(false);
   }
 }
 
 void
-nsDocument::CleanupFullscreenState()
+nsIDocument::CleanupFullscreenState()
 {
   // Iterate the fullscreen stack and clear the fullscreen states.
   // Since we also need to clear the fullscreen-ancestor state, and
   // currently fullscreen elements can only be placed in hierarchy
   // order in the stack, reversely iterating the stack could be more
   // efficient. NOTE that fullscreen-ancestor state would be removed
   // in bug 1199529, and the elements may not in hierarchy order
   // after bug 1195213.
@@ -10970,32 +10835,32 @@ nsDocument::CleanupFullscreenState()
     }
   }
   mFullScreenStack.Clear();
   mFullscreenRoot = nullptr;
   UpdateViewportScrollbarOverrideForFullscreen(this);
 }
 
 bool
-nsDocument::FullScreenStackPush(Element* aElement)
+nsIDocument::FullScreenStackPush(Element* aElement)
 {
   NS_ASSERTION(aElement, "Must pass non-null to FullScreenStackPush()");
   Element* top = FullScreenStackTop();
   if (top == aElement || !aElement) {
     return false;
   }
   EventStateManager::SetFullScreenState(aElement, true);
   mFullScreenStack.AppendElement(do_GetWeakReference(aElement));
   NS_ASSERTION(FullScreenStackTop() == aElement, "Should match");
   UpdateViewportScrollbarOverrideForFullscreen(this);
   return true;
 }
 
 void
-nsDocument::FullScreenStackPop()
+nsIDocument::FullScreenStackPop()
 {
   if (mFullScreenStack.IsEmpty()) {
     return;
   }
 
   ClearFullscreenStateOnElement(FullScreenStackTop());
 
   // Remove top element. Note the remaining top element in the stack
@@ -11019,31 +10884,31 @@ nsDocument::FullScreenStackPop()
       break;
     }
   }
 
   UpdateViewportScrollbarOverrideForFullscreen(this);
 }
 
 Element*
-nsDocument::FullScreenStackTop()
+nsIDocument::FullScreenStackTop()
 {
   if (mFullScreenStack.IsEmpty()) {
     return nullptr;
   }
   uint32_t last = mFullScreenStack.Length() - 1;
   nsCOMPtr<Element> element(do_QueryReferent(mFullScreenStack[last]));
   NS_ASSERTION(element, "Should have full-screen element!");
   NS_ASSERTION(element->IsInComposedDoc(), "Full-screen element should be in doc");
   NS_ASSERTION(element->OwnerDoc() == this, "Full-screen element should be in this doc");
   return element;
 }
 
-/* virtual */ nsTArray<Element*>
-nsDocument::GetFullscreenStack() const
+nsTArray<Element*>
+nsIDocument::GetFullscreenStack() const
 {
   nsTArray<Element*> elements;
   for (const nsWeakPtr& ptr : mFullScreenStack) {
     if (nsCOMPtr<Element> elem = do_QueryReferent(ptr)) {
       MOZ_ASSERT(elem->State().HasState(NS_EVENT_STATE_FULL_SCREEN));
       elements.AppendElement(elem);
     }
   }
@@ -11084,31 +10949,31 @@ IsInActiveTab(nsIDocument* aDoc)
   fm->GetActiveWindow(getter_AddRefs(activeWindow));
   if (!activeWindow) {
     return false;
   }
 
   return activeWindow == rootWin;
 }
 
-nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
+nsresult nsIDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
 {
   // Ensure the frame element is the fullscreen element in this document.
   // If the frame element is already the fullscreen element in this document,
   // this has no effect.
   nsCOMPtr<nsIContent> content(do_QueryInterface(aFrameElement));
   auto request = MakeUnique<FullscreenRequest>(content->AsElement());
   request->mIsCallerChrome = false;
   request->mShouldNotifyNewOrigin = false;
   RequestFullScreen(Move(request));
 
   return NS_OK;
 }
 
-nsresult nsDocument::RemoteFrameFullscreenReverted()
+nsresult nsIDocument::RemoteFrameFullscreenReverted()
 {
   RestorePreviousFullScreenState();
   return NS_OK;
 }
 
 /* static */ bool
 nsIDocument::IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject)
 {
@@ -11147,18 +11012,18 @@ GetFullscreenError(nsIDocument* aDoc, bo
   nsCOMPtr<nsIDocShell> docShell(aDoc->GetDocShell());
   if (!docShell || !docShell->GetFullscreenAllowed()) {
     return "FullscreenDeniedContainerNotAllowed";
   }
   return nullptr;
 }
 
 bool
-nsDocument::FullscreenElementReadyCheck(Element* aElement,
-                                        bool aWasCallerChrome)
+nsIDocument::FullscreenElementReadyCheck(Element* aElement,
+                                         bool aWasCallerChrome)
 {
   NS_ASSERTION(aElement,
     "Must pass non-null element to nsDocument::RequestFullScreen");
   if (!aElement || aElement == FullScreenStackTop()) {
     return false;
   }
   if (!aElement->IsInComposedDoc()) {
     DispatchFullscreenError("FullscreenDeniedNotInDocument");
@@ -11366,17 +11231,17 @@ ShouldApplyFullscreenDirectly(nsIDocumen
     // if it is already in fullscreen. If we do not apply the state but
     // instead add it to the queue and wait for the window as normal,
     // we would get stuck.
     return true;
   }
 }
 
 void
-nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
+nsIDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
 {
   nsCOMPtr<nsPIDOMWindowOuter> rootWin = GetRootWindow(this);
   if (!rootWin) {
     return;
   }
 
   if (ShouldApplyFullscreenDirectly(this, rootWin)) {
     ApplyFullscreen(*aRequest);
@@ -11434,17 +11299,17 @@ ClearPendingFullscreenRequests(nsIDocume
   PendingFullscreenRequestList::Iterator iter(
     aDoc, PendingFullscreenRequestList::eInclusiveDescendants);
   while (!iter.AtEnd()) {
     iter.DeleteAndNext();
   }
 }
 
 bool
-nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
+nsIDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
 {
   Element* elem = aRequest.GetElement();
   if (!FullscreenElementReadyCheck(elem, aRequest.mIsCallerChrome)) {
     return false;
   }
 
   // Stash a reference to any existing fullscreen doc, we'll use this later
   // to detect if the origin which is fullscreen has changed.
@@ -11535,49 +11400,23 @@ nsDocument::ApplyFullscreen(const Fullsc
   // document, as required by the spec.
   for (uint32_t i = 0; i < changed.Length(); ++i) {
     DispatchFullScreenChange(changed[changed.Length() - i - 1]);
   }
   return true;
 }
 
 bool
-nsDocument::FullscreenEnabled(CallerType aCallerType)
+nsIDocument::FullscreenEnabled(CallerType aCallerType)
 {
   return !GetFullscreenError(this, aCallerType == CallerType::System);
 }
 
-uint16_t
-nsDocument::CurrentOrientationAngle() const
-{
-  return mCurrentOrientationAngle;
-}
-
-OrientationType
-nsDocument::CurrentOrientationType() const
-{
-  return mCurrentOrientationType;
-}
-
-void
-nsDocument::SetCurrentOrientation(mozilla::dom::OrientationType aType,
-                                  uint16_t aAngle)
-{
-  mCurrentOrientationType = aType;
-  mCurrentOrientationAngle = aAngle;
-}
-
-Promise*
-nsDocument::GetOrientationPendingPromise() const
-{
-  return mOrientationPendingPromise;
-}
-
-void
-nsDocument::SetOrientationPendingPromise(Promise* aPromise)
+void
+nsIDocument::SetOrientationPendingPromise(Promise* aPromise)
 {
   mOrientationPendingPromise = aPromise;
 }
 
 static void
 DispatchPointerLockChange(nsIDocument* aTarget)
 {
   if (!aTarget) {
@@ -11759,17 +11598,17 @@ PointerLockRequest::Run()
   ChangePointerLockedElement(e, d, nullptr);
   nsContentUtils::DispatchEventOnlyToChrome(
     doc, ToSupports(e), NS_LITERAL_STRING("MozDOMPointerLock:Entered"),
     /* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
   return NS_OK;
 }
 
 void
-nsDocument::RequestPointerLock(Element* aElement, CallerType aCallerType)
+nsIDocument::RequestPointerLock(Element* aElement, CallerType aCallerType)
 {
   NS_ASSERTION(aElement,
     "Must pass non-null element to nsDocument::RequestPointerLock");
 
   nsCOMPtr<Element> pointerLockedElement =
     do_QueryReferent(EventStateManager::sPointerLockedElement);
   if (aElement == pointerLockedElement) {
     DispatchPointerLockChange(this);
@@ -11784,17 +11623,17 @@ nsDocument::RequestPointerLock(Element* 
   bool userInputOrSystemCaller = EventStateManager::IsHandlingUserInput() ||
                                  aCallerType == CallerType::System;
   nsCOMPtr<nsIRunnable> request =
     new PointerLockRequest(aElement, userInputOrSystemCaller);
   Dispatch(TaskCategory::Other, request.forget());
 }
 
 bool
-nsDocument::SetPointerLock(Element* aElement, int aCursorStyle)
+nsIDocument::SetPointerLock(Element* aElement, int aCursorStyle)
 {
   MOZ_ASSERT(!aElement || aElement->OwnerDoc() == this,
              "We should be either unlocking pointer (aElement is nullptr), "
              "or locking pointer to an element in this document");
 #ifdef DEBUG
   if (!aElement) {
     nsCOMPtr<nsIDocument> pointerLockedDoc =
       do_QueryReferent(EventStateManager::sPointerLockedDoc);
@@ -11872,63 +11711,63 @@ nsDocument::UnlockPointer(nsIDocument* a
 
 void
 nsIDocument::UnlockPointer(nsIDocument* aDoc)
 {
   nsDocument::UnlockPointer(aDoc);
 }
 
 void
-nsDocument::UpdateVisibilityState()
+nsIDocument::UpdateVisibilityState()
 {
   dom::VisibilityState oldState = mVisibilityState;
-  mVisibilityState = GetVisibilityState();
+  mVisibilityState = ComputeVisibilityState();
   if (oldState != mVisibilityState) {
     nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
                                          NS_LITERAL_STRING("visibilitychange"),
                                          /* bubbles = */ true,
                                          /* cancelable = */ false);
     EnumerateActivityObservers(NotifyActivityChanged, nullptr);
   }
 
   if (mVisibilityState == dom::VisibilityState::Visible) {
     MaybeActiveMediaComponents();
   }
 }
 
 VisibilityState
-nsDocument::GetVisibilityState() const
+nsIDocument::ComputeVisibilityState() const
 {
   // We have to check a few pieces of information here:
   // 1)  Are we in bfcache (!IsVisible())?  If so, nothing else matters.
   // 2)  Do we have an outer window?  If not, we're hidden.  Note that we don't
   //     want to use GetWindow here because it does weird groveling for windows
   //     in some cases.
   // 3)  Is our outer window background?  If so, we're hidden.
   // Otherwise, we're visible.
   if (!IsVisible() || !mWindow || !mWindow->GetOuterWindow() ||
       mWindow->GetOuterWindow()->IsBackground()) {
     return dom::VisibilityState::Hidden;
   }
 
   return dom::VisibilityState::Visible;
 }
 
-/* virtual */ void
-nsDocument::PostVisibilityUpdateEvent()
+void
+nsIDocument::PostVisibilityUpdateEvent()
 {
   nsCOMPtr<nsIRunnable> event =
-    NewRunnableMethod("nsDocument::UpdateVisibilityState",
+    NewRunnableMethod("nsIDocument::UpdateVisibilityState",
                       this,
-                      &nsDocument::UpdateVisibilityState);
+                      &nsIDocument::UpdateVisibilityState);
   Dispatch(TaskCategory::Other, event.forget());
 }
 
 void
-nsDocument::MaybeActiveMediaComponents()
+nsIDocument::MaybeActiveMediaComponents()
 {
   if (!mWindow) {
     return;
   }
 
   GetWindow()->MaybeActiveMediaComponents();
 }
 
@@ -12414,71 +12253,57 @@ nsDocument::ReportUseCounters(UseCounter
 
   if (IsContentDocument() || IsResourceDoc()) {
     uint16_t num = mIncCounters[eIncCounter_ScriptTag];
     Telemetry::Accumulate(Telemetry::DOM_SCRIPT_EVAL_PER_DOCUMENT, num);
   }
 }
 
 void
-nsDocument::AddIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
-             "Intersection observer already in the list");
-  mIntersectionObservers.PutEntry(aObserver);
-}
-
-void
-nsDocument::RemoveIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  mIntersectionObservers.RemoveEntry(aObserver);
-}
-
-void
-nsDocument::UpdateIntersectionObservations()
+nsIDocument::UpdateIntersectionObservations()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
   }
 
   DOMHighResTimeStamp time = 0;
   if (nsPIDOMWindowInner* window = GetInnerWindow()) {
     Performance* perf = window->GetPerformance();
     if (perf) {
       time = perf->Now();
     }
   }
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
-      observers.AppendElement(observer);
+    observers.AppendElement(observer);
   }
   for (const auto& observer : observers) {
     if (observer) {
       observer->Update(this, time);
     }
   }
 }
 
 void
-nsDocument::ScheduleIntersectionObserverNotification()
+nsIDocument::ScheduleIntersectionObserverNotification()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
   }
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIRunnable> notification =
     NewRunnableMethod("nsDocument::NotifyIntersectionObservers",
                       this,
                       &nsDocument::NotifyIntersectionObservers);
   Dispatch(TaskCategory::Other, notification.forget());
 }
 
 void
-nsDocument::NotifyIntersectionObservers()
+nsIDocument::NotifyIntersectionObservers()
 {
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
     observers.AppendElement(observer);
   }
   for (const auto& observer : observers) {
     if (observer) {
@@ -12490,17 +12315,17 @@ nsDocument::NotifyIntersectionObservers(
 static bool
 NotifyLayerManagerRecreatedCallback(nsIDocument* aDocument, void* aData)
 {
   aDocument->NotifyLayerManagerRecreated();
   return true;
 }
 
 void
-nsDocument::NotifyLayerManagerRecreated()
+nsIDocument::NotifyLayerManagerRecreated()
 {
   EnumerateActivityObservers(NotifyActivityChanged, nullptr);
   EnumerateSubDocuments(NotifyLayerManagerRecreatedCallback, nullptr);
 }
 
 XPathEvaluator*
 nsIDocument::XPathEvaluator()
 {
@@ -12863,20 +12688,20 @@ nsIDocument::GetSameTypeParentDocument()
  * the classification lists. We perform AsyncInitFlashClassification on
  * StartDocumentLoad() and the result may not be initialized when this function
  * gets called. In that case, We can only unfortunately have a blocking wait.
  *
  * For more information, see
  * toolkit/components/url-classifier/flash-block-lists.rst
  */
 FlashClassification
-nsDocument::PrincipalFlashClassification()
+nsIDocument::PrincipalFlashClassification()
 {
   MOZ_ASSERT(mPrincipalFlashClassifier);
-  return mPrincipalFlashClassifier->ClassifyMaybeSync(GetPrincipal(),
+  return mPrincipalFlashClassifier->ClassifyMaybeSync(NodePrincipal(),
                                                       IsThirdParty());
 }
 
 /**
  * Helper function for |nsDocument::PrincipalFlashClassification|
  *
  * Adds a table name string to a table list (a comma separated string). The
  * table will not be added if the name is an empty string.
@@ -13267,17 +13092,17 @@ PrincipalFlashClassifier::AsyncClassifyI
       return FlashClassification::Denied;
     }
   }
 
   return FlashClassification::Unclassified;
 }
 
 FlashClassification
-nsDocument::ComputeFlashClassification()
+nsIDocument::ComputeFlashClassification()
 {
   nsCOMPtr<nsIDocShellTreeItem> current = this->GetDocShell();
   if (!current) {
     return FlashClassification::Denied;
   }
   nsCOMPtr<nsIDocShellTreeItem> parent;
   DebugOnly<nsresult> rv = current->GetSameTypeParent(getter_AddRefs(parent));
   MOZ_ASSERT(NS_SUCCEEDED(rv),
@@ -13316,17 +13141,17 @@ nsDocument::ComputeFlashClassification()
  * Retrieves the classification of plugins in this document. This is dependent
  * on the classification of this document and all parent documents.
  * This function is infallible - It must return some classification that
  * callers can act on.
  *
  * This function will NOT return FlashClassification::Unclassified
  */
 FlashClassification
-nsDocument::DocumentFlashClassification()
+nsIDocument::DocumentFlashClassification()
 {
   if (mFlashClassification == FlashClassification::Unclassified) {
     FlashClassification result = ComputeFlashClassification();
     mFlashClassification = result;
     MOZ_ASSERT(result != FlashClassification::Unclassified,
       "nsDocument::GetPluginClassification should never return Unclassified");
   }
 
@@ -13344,17 +13169,17 @@ nsDocument::DocumentFlashClassification(
  *  - The document has a different scheme (http/https) than its parent document
  *  - The document's domain and subdomain do not match those of its parent
  *    document.
  *
  * If there is an error in determining whether the document is Third-Party,
  * it will be assumed to be Third-Party for security reasons.
  */
 bool
-nsDocument::IsThirdParty()
+nsIDocument::IsThirdParty()
 {
   if (mIsThirdParty.isSome()) {
     return mIsThirdParty.value();
   }
 
   nsCOMPtr<nsIDocShellTreeItem> docshell = this->GetDocShell();
   if (!docshell) {
     mIsThirdParty.emplace(true);
@@ -13379,17 +13204,17 @@ nsDocument::IsThirdParty()
     return mIsThirdParty.value();
   }
 
   if (parentDocument->IsThirdParty()) {
     mIsThirdParty.emplace(true);
     return mIsThirdParty.value();
   }
 
-  nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
+  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(parentDocument,
                                                              &rv);
   if (NS_WARN_IF(NS_FAILED(rv) || !sop)) {
     // Failure
     mIsThirdParty.emplace(true);
     return mIsThirdParty.value();
   }
   nsCOMPtr<nsIPrincipal> parentPrincipal = sop->GetPrincipal();
@@ -13445,17 +13270,17 @@ nsIDocument::GetSelection(ErrorResult& a
   if (!window->IsCurrentInnerWindow()) {
     return nullptr;
   }
 
   return nsGlobalWindowInner::Cast(window)->GetSelection(aRv);
 }
 
 void
-nsDocument::RecordNavigationTiming(ReadyState aReadyState)
+nsIDocument::RecordNavigationTiming(ReadyState aReadyState)
 {
   if (!XRE_IsContentProcess()) {
     return;
   }
   if (!IsTopLevelContentDocument()) {
     return;
   }
   // If we dont have the timing yet (mostly because the doc is still loading),
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -8,16 +8,17 @@
  * Base class for all our document implementations.
  */
 
 #ifndef nsDocument_h___
 #define nsDocument_h___
 
 #include "nsIDocument.h"
 
+#include "jsfriendapi.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCRT.h"
 #include "nsWeakReference.h"
 #include "nsWeakPtr.h"
 #include "nsTArray.h"
 #include "nsIdentifierMapEntry.h"
 #include "nsIDOMDocument.h"
@@ -25,52 +26,41 @@
 #include "nsIScriptGlobalObject.h"
 #include "nsIContent.h"
 #include "nsIPrincipal.h"
 #include "nsIParser.h"
 #include "nsBindingManager.h"
 #include "nsRefPtrHashtable.h"
 #include "nsJSThingHashtable.h"
 #include "nsIScriptObjectPrincipal.h"
-#include "nsIURI.h"
 #include "nsIRadioGroupContainer.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIRequest.h"
 #include "nsILoadGroup.h"
 #include "nsTObserverArray.h"
 #include "nsStubMutationObserver.h"
 #include "nsIChannel.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsContentList.h"
 #include "nsGkAtoms.h"
-#include "nsIApplicationCache.h"
-#include "nsIApplicationCacheContainer.h"
 #include "mozilla/StyleSetHandle.h"
 #include "PLDHashTable.h"
-#include "nsAttrAndChildArray.h"
 #include "nsDOMAttributeMap.h"
-#include "nsIContentViewer.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsILoadContext.h"
-#include "nsIProgressEventSink.h"
-#include "nsISecurityEventSink.h"
-#include "nsIChannelEventSink.h"
 #include "imgIRequest.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "mozilla/dom/BoxObject.h"
 #include "mozilla/dom/DOMImplementation.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/StyleSheetList.h"
 #include "nsDataHashtable.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Attributes.h"
-#include "jsfriendapi.h"
 #include "mozilla/LinkedList.h"
 #include "CustomElementRegistry.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/Maybe.h"
 #include "nsIURIClassifier.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
@@ -102,21 +92,21 @@ class Performance;
 
 struct FullscreenRequest : public LinkedListElement<FullscreenRequest>
 {
   explicit FullscreenRequest(Element* aElement);
   FullscreenRequest(const FullscreenRequest&) = delete;
   ~FullscreenRequest();
 
   Element* GetElement() const { return mElement; }
-  nsDocument* GetDocument() const { return mDocument; }
+  nsIDocument* GetDocument() const { return mDocument; }
 
 private:
   RefPtr<Element> mElement;
-  RefPtr<nsDocument> mDocument;
+  RefPtr<nsIDocument> mDocument;
 
 public:
   // This value should be true if the fullscreen request is
   // originated from chrome code.
   bool mIsCallerChrome = false;
   // This value denotes whether we should trigger a NewOrigin event if
   // requesting fullscreen in its document causes the origin which is
   // fullscreen to change. We may want *not* to trigger that event if
@@ -124,205 +114,28 @@ public:
   // request in a subdocument in different process, whereupon the caller
   // need to send some notification itself with the real origin.
   bool mShouldNotifyNewOrigin = true;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-class nsDocHeaderData
-{
-public:
-  nsDocHeaderData(nsAtom* aField, const nsAString& aData)
-    : mField(aField), mData(aData), mNext(nullptr)
-  {
-  }
-
-  ~nsDocHeaderData(void)
-  {
-    delete mNext;
-  }
-
-  RefPtr<nsAtom> mField;
-  nsString          mData;
-  nsDocHeaderData*  mNext;
-};
-
 class nsOnloadBlocker final : public nsIRequest
 {
 public:
   nsOnloadBlocker() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUEST
 
 private:
   ~nsOnloadBlocker() {}
 };
 
-class nsExternalResourceMap
-{
-public:
-  typedef nsIDocument::ExternalResourceLoad ExternalResourceLoad;
-  nsExternalResourceMap();
-
-  /**
-   * Request an external resource document.  This does exactly what
-   * nsIDocument::RequestExternalResource is documented to do.
-   */
-  nsIDocument* RequestResource(nsIURI* aURI,
-                               nsINode* aRequestingNode,
-                               nsDocument* aDisplayDocument,
-                               ExternalResourceLoad** aPendingLoad);
-
-  /**
-   * Enumerate the resource documents.  See
-   * nsIDocument::EnumerateExternalResources.
-   */
-  void EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback, void* aData);
-
-  /**
-   * Traverse ourselves for cycle-collection
-   */
-  void Traverse(nsCycleCollectionTraversalCallback* aCallback) const;
-
-  /**
-   * Shut ourselves down (used for cycle-collection unlink), as well
-   * as for document destruction.
-   */
-  void Shutdown()
-  {
-    mPendingLoads.Clear();
-    mMap.Clear();
-    mHaveShutDown = true;
-  }
-
-  bool HaveShutDown() const
-  {
-    return mHaveShutDown;
-  }
-
-  // Needs to be public so we can traverse them sanely
-  struct ExternalResource
-  {
-    ~ExternalResource();
-    nsCOMPtr<nsIDocument> mDocument;
-    nsCOMPtr<nsIContentViewer> mViewer;
-    nsCOMPtr<nsILoadGroup> mLoadGroup;
-  };
-
-  // Hide all our viewers
-  void HideViewers();
-
-  // Show all our viewers
-  void ShowViewers();
-
-protected:
-  class PendingLoad : public ExternalResourceLoad,
-                      public nsIStreamListener
-  {
-    ~PendingLoad() {}
-
-  public:
-    explicit PendingLoad(nsDocument* aDisplayDocument) :
-      mDisplayDocument(aDisplayDocument)
-    {}
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSISTREAMLISTENER
-    NS_DECL_NSIREQUESTOBSERVER
-
-    /**
-     * Start aURI loading.  This will perform the necessary security checks and
-     * so forth.
-     */
-    nsresult StartLoad(nsIURI* aURI, nsINode* aRequestingNode);
-
-    /**
-     * Set up an nsIContentViewer based on aRequest.  This is guaranteed to
-     * put null in *aViewer and *aLoadGroup on all failures.
-     */
-    nsresult SetupViewer(nsIRequest* aRequest, nsIContentViewer** aViewer,
-                         nsILoadGroup** aLoadGroup);
-
-  private:
-    RefPtr<nsDocument> mDisplayDocument;
-    nsCOMPtr<nsIStreamListener> mTargetListener;
-    nsCOMPtr<nsIURI> mURI;
-  };
-  friend class PendingLoad;
-
-  class LoadgroupCallbacks final : public nsIInterfaceRequestor
-  {
-    ~LoadgroupCallbacks() {}
-  public:
-    explicit LoadgroupCallbacks(nsIInterfaceRequestor* aOtherCallbacks)
-      : mCallbacks(aOtherCallbacks)
-    {}
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIINTERFACEREQUESTOR
-  private:
-    // The only reason it's safe to hold a strong ref here without leaking is
-    // that the notificationCallbacks on a loadgroup aren't the docshell itself
-    // but a shim that holds a weak reference to the docshell.
-    nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
-
-    // Use shims for interfaces that docshell implements directly so that we
-    // don't hand out references to the docshell.  The shims should all allow
-    // getInterface back on us, but other than that each one should only
-    // implement one interface.
-
-    // XXXbz I wish we could just derive the _allcaps thing from _i
-#define DECL_SHIM(_i, _allcaps)                                              \
-    class _i##Shim final : public nsIInterfaceRequestor,                     \
-                           public _i                                         \
-    {                                                                        \
-      ~_i##Shim() {}                                                         \
-    public:                                                                  \
-      _i##Shim(nsIInterfaceRequestor* aIfreq, _i* aRealPtr)                  \
-        : mIfReq(aIfreq), mRealPtr(aRealPtr)                                 \
-      {                                                                      \
-        NS_ASSERTION(mIfReq, "Expected non-null here");                      \
-        NS_ASSERTION(mRealPtr, "Expected non-null here");                    \
-      }                                                                      \
-      NS_DECL_ISUPPORTS                                                      \
-      NS_FORWARD_NSIINTERFACEREQUESTOR(mIfReq->)                             \
-      NS_FORWARD_##_allcaps(mRealPtr->)                                      \
-    private:                                                                 \
-      nsCOMPtr<nsIInterfaceRequestor> mIfReq;                                \
-      nsCOMPtr<_i> mRealPtr;                                                 \
-    };
-
-    DECL_SHIM(nsILoadContext, NSILOADCONTEXT)
-    DECL_SHIM(nsIProgressEventSink, NSIPROGRESSEVENTSINK)
-    DECL_SHIM(nsIChannelEventSink, NSICHANNELEVENTSINK)
-    DECL_SHIM(nsISecurityEventSink, NSISECURITYEVENTSINK)
-    DECL_SHIM(nsIApplicationCacheContainer, NSIAPPLICATIONCACHECONTAINER)
-#undef DECL_SHIM
-  };
-
-  /**
-   * Add an ExternalResource for aURI.  aViewer and aLoadGroup might be null
-   * when this is called if the URI didn't result in an XML document.  This
-   * function makes sure to remove the pending load for aURI, if any, from our
-   * hashtable, and to notify its observers, if any.
-   */
-  nsresult AddExternalResource(nsIURI* aURI, nsIContentViewer* aViewer,
-                               nsILoadGroup* aLoadGroup,
-                               nsIDocument* aDisplayDocument);
-
-  nsClassHashtable<nsURIHashKey, ExternalResource> mMap;
-  nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads;
-  bool mHaveShutDown;
-};
-
-// For classifying a flash document based on its principal.
-class PrincipalFlashClassifier;
-
 // Base class for our document implementations.
 class nsDocument : public nsIDocument,
                    public nsIDOMDocument,
                    public nsSupportsWeakReference,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer,
                    public nsIApplicationCacheContainer,
                    public nsStubMutationObserver
@@ -351,161 +164,52 @@ public:
                                      nsILoadGroup* aLoadGroup,
                                      nsISupports* aContainer,
                                      nsIStreamListener **aDocListener,
                                      bool aReset = true,
                                      nsIContentSink* aContentSink = nullptr) override = 0;
 
   virtual void StopDocumentLoad() override;
 
-  virtual void NotifyPossibleTitleChange(bool aBoundTitleElement) override;
-
-  virtual void SetDocumentURI(nsIURI* aURI) override;
-
-  virtual void SetChromeXHRDocURI(nsIURI* aURI) override;
-
-  virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) override;
-
-  virtual void ApplySettingsFromCSP(bool aSpeculative) override;
-
-  /**
-   * Set the principal responsible for this document.
-   */
-  virtual void SetPrincipal(nsIPrincipal *aPrincipal) override;
-
   /**
    * Set the Content-Type of this document.
    */
   virtual void SetContentType(const nsAString& aContentType) override;
 
-  virtual void SetBaseURI(nsIURI* aURI) override;
-
-  /**
-   * Get/Set the base target of a link in a document.
-   */
-  virtual void GetBaseTarget(nsAString &aBaseTarget) override;
-
   /**
    * Set the document's character encoding. This will
    * trigger a startDocumentLoad if necessary to answer the question.
    */
   virtual void
     SetDocumentCharacterSet(NotNull<const Encoding*> aEncoding) override;
 
-  virtual Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
-                                       void* aData, bool aForImage) override;
-  virtual void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
-                                      void* aData, bool aForImage) override;
-
-  /**
-   * Access HTTP header data (this may also get set from other sources, like
-   * HTML META tags).
-   */
-  virtual void GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const override;
-  virtual void SetHeaderData(nsAtom* aheaderField,
-                             const nsAString& aData) override;
-
-  /**
-   * Create a new presentation shell that will use aContext for
-   * its presentation context (presentation contexts <b>must not</b> be
-   * shared among multiple presentation shells).
-   */
-  already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
-                                             nsViewManager* aViewManager,
-                                             mozilla::StyleSetHandle aStyleSet)
-    final;
-  virtual void DeleteShell() override;
-
-  virtual bool GetAllowPlugins() override;
-
   static bool CallerIsTrustedAboutPage(JSContext* aCx, JSObject* aObject);
   static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType);
-  virtual mozilla::dom::DocumentTimeline* Timeline() override;
-  virtual void GetAnimations(
-      nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
-  mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() override
-  {
-    return mTimelines;
-  }
-
-  virtual nsresult SetSubDocumentFor(Element* aContent,
-                                     nsIDocument* aSubDoc) override;
-  virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const override;
-  virtual Element* FindContentForSubDocument(nsIDocument *aDocument) const override;
-  virtual Element* GetRootElementInternal() const override;
-
-  virtual nsIChannel* GetChannel() const override {
-    return mChannel;
-  }
 
   virtual nsIChannel* GetFailedChannel() const override {
     return mFailedChannel;
   }
   virtual void SetFailedChannel(nsIChannel* aChannel) override {
     mFailedChannel = aChannel;
   }
 
   virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) override;
 
-  virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject) override;
-
-  virtual nsIGlobalObject* GetScopeObject() const override;
-  void SetScopeObject(nsIGlobalObject* aGlobal) override;
-  /**
-   * Get the script loader for this document
-   */
-  virtual mozilla::dom::ScriptLoader* ScriptLoader() override;
-
-  /**
-   * Add/Remove an element to the document's id and name hashes
-   */
-  virtual void AddToIdTable(Element* aElement, nsAtom* aId) override;
-  virtual void RemoveFromIdTable(Element* aElement, nsAtom* aId) override;
-  virtual void AddToNameTable(Element* aElement, nsAtom* aName) override;
-  virtual void RemoveFromNameTable(Element* aElement, nsAtom* aName) override;
-
   virtual void EndUpdate(nsUpdateType aUpdateType) override;
   virtual void BeginLoad() override;
   virtual void EndLoad() override;
 
-  virtual void SetReadyStateInternal(ReadyState rs) override;
-
-  virtual void FlushExternalResources(mozilla::FlushType aType) override;
   virtual void SetXMLDeclaration(const char16_t *aVersion,
                                  const char16_t *aEncoding,
                                  const int32_t aStandalone) override;
   virtual void GetXMLDeclaration(nsAString& aVersion,
                                  nsAString& aEncoding,
                                  nsAString& Standalone) override;
-  virtual bool IsScriptEnabled() override;
-
-  virtual void OnPageShow(bool aPersisted, mozilla::dom::EventTarget* aDispatchStartTarget) override;
-  virtual void OnPageHide(bool aPersisted, mozilla::dom::EventTarget* aDispatchStartTarget) override;
-
-  virtual void WillDispatchMutationEvent(nsINode* aTarget) override;
-  virtual void MutationEventDispatched(nsINode* aTarget) override;
-
-  // nsINode
-  virtual bool IsNodeOfType(uint32_t aFlags) const override;
-  virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
-  virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
-  virtual uint32_t GetChildCount() const override;
-  virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
-                                     bool aNotify) override;
-  virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
-                                            bool aNotify) override;
-  virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
-  virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
-                         bool aPreallocateChildren) const override
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
 
   // nsIRadioGroupContainer
   NS_IMETHOD WalkRadioGroup(const nsAString& aName,
                             nsIRadioVisitor* aVisitor,
                             bool aFlushContent) override;
   virtual void
     SetCurrentRadioButton(const nsAString& aName,
                           mozilla::dom::HTMLInputElement* aRadio) override;
@@ -541,30 +245,16 @@ public:
     // Flush use counters for the document and for its external resource
     // documents. (Should only be necessary for tests, where we need
     // flushing to happen synchronously and deterministically.)
     eIncludeExternalResources,
   };
 
   void ReportUseCounters(UseCounterReportKind aKind = UseCounterReportKind::eDefault);
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void UpdateIntersectionObservations() override;
-  virtual void ScheduleIntersectionObserverNotification() override;
-  virtual void NotifyIntersectionObservers() override;
-  virtual bool HasIntersectionObservers() const override
-  {
-    return !mIntersectionObservers.IsEmpty();
-  }
-
-  virtual void NotifyLayerManagerRecreated() override;
-
   bool IsSynthesized();
 
   // Check whether shadow DOM is enabled for the global of aObject.
   static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject);
   // Check whether shadow DOM is enabled for the document this node belongs to.
   static bool IsShadowDOMEnabled(const nsINode* aNode);
 private:
   void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
@@ -594,194 +284,39 @@ public:
 
   virtual nsresult Init();
 
   virtual already_AddRefed<Element> CreateElem(const nsAString& aName,
                                                nsAtom* aPrefix,
                                                int32_t aNamespaceID,
                                                const nsAString* aIs = nullptr) override;
 
-  virtual void Sanitize() override;
 
-  virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
-                                                 void *aData) override;
-  virtual void CollectDescendantDocuments(
-    nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
-    nsDocTestFunc aCallback) const override;
-
-  virtual bool CanSavePresentation(nsIRequest *aNewRequest) override;
   virtual void Destroy() override;
   virtual void RemovedFromDocShell() override;
-  virtual already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const override;
 
   virtual void BlockOnload() override;
   virtual void UnblockOnload(bool aFireSync) override;
 
-  virtual void AddStyleRelevantLink(mozilla::dom::Link* aLink) override;
-  virtual void ForgetLink(mozilla::dom::Link* aLink) override;
-
-  virtual void ClearBoxObjectFor(nsIContent* aContent) override;
-
-  virtual already_AddRefed<mozilla::dom::BoxObject>
-  GetBoxObjectFor(mozilla::dom::Element* aElement,
-                  mozilla::ErrorResult& aRv) override;
-
-  virtual Element*
-    GetAnonymousElementByAttribute(nsIContent* aElement,
-                                   nsAtom* aAttrName,
-                                   const nsAString& aAttrValue) const override;
-
-  virtual nsresult NodesFromRectHelper(float aX, float aY,
-                                                   float aTopSize, float aRightSize,
-                                                   float aBottomSize, float aLeftSize,
-                                                   bool aIgnoreRootScrollFrame,
-                                                   bool aFlushLayout,
-                                                   nsIDOMNodeList** aReturn) override;
-
-  virtual void FlushSkinBindings() override;
-
-  virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) override;
-  virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer) override;
-  virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) override;
-  virtual nsIDocument*
-    RequestExternalResource(nsIURI* aURI,
-                            nsINode* aRequestingNode,
-                            ExternalResourceLoad** aPendingLoad) override;
-  virtual void
-    EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData) override;
-
-  // Returns our (lazily-initialized) animation controller.
-  // If HasAnimationController is true, this is guaranteed to return non-null.
-  nsSMILAnimationController* GetAnimationController() override;
-
-  virtual mozilla::PendingAnimationTracker*
-  GetPendingAnimationTracker() final
-  {
-    return mPendingAnimationTracker;
-  }
-
-  virtual mozilla::PendingAnimationTracker*
-  GetOrCreatePendingAnimationTracker() override;
-
-  virtual void SuppressEventHandling(uint32_t aIncrease) override;
-
-  virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) override;
-
-  void DecreaseEventSuppression() {
-    MOZ_ASSERT(mEventsSuppressed);
-    --mEventsSuppressed;
-    UpdateFrameRequestCallbackSchedulingState();
-  }
-
-  virtual nsIDocument* GetTemplateContentsOwner() override;
-
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
                                                                    nsIDocument)
 
-  void DoNotifyPossibleTitleChange();
-
-  nsExternalResourceMap& ExternalResourceMap()
-  {
-    return mExternalResourceMap;
-  }
-
   void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
   void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData)
   {
     mLoadedAsInteractiveData = aLoadedAsInteractiveData;
   }
 
   nsresult CloneDocHelper(nsDocument* clone, bool aPreallocateChildren) const;
 
-  void MaybeInitializeFinalizeFrameLoaders();
-
   void MaybeEndOutermostXBLUpdate();
 
-  virtual void PreloadPictureOpened() override;
-  virtual void PreloadPictureClosed() override;
-
-  virtual void
-    PreloadPictureImageSource(const nsAString& aSrcsetAttr,
-                              const nsAString& aSizesAttr,
-                              const nsAString& aTypeAttr,
-                              const nsAString& aMediaAttr) override;
-
-  virtual already_AddRefed<nsIURI>
-    ResolvePreloadImage(nsIURI *aBaseURI,
-                        const nsAString& aSrcAttr,
-                        const nsAString& aSrcsetAttr,
-                        const nsAString& aSizesAttr,
-                        bool *aIsImgSet) override;
-
-  virtual void MaybePreLoadImage(nsIURI* uri,
-                                 const nsAString &aCrossOriginAttr,
-                                 ReferrerPolicy aReferrerPolicy,
-                                 bool aIsImgSet) override;
-
-  virtual void ForgetImagePreload(nsIURI* aURI) override;
-
-  virtual void MaybePreconnect(nsIURI* uri,
-                               mozilla::CORSMode aCORSMode) override;
-
-  virtual nsISupports* GetCurrentContentSink() override;
-
   // Only BlockOnload should call this!
   void AsyncBlockOnload();
 
-  virtual void SetAutoFocusElement(Element* aAutoFocusElement) override;
-  virtual void TriggerAutoFocus() override;
-
-  virtual void SetScrollToRef(nsIURI *aDocumentURI) override;
-  virtual void ScrollToRef() override;
-  virtual void ResetScrolledToRefAlready() override;
-  virtual void SetChangeScrollPosWhenScrollingToRef(bool aValue) override;
-
-  virtual Element* LookupImageElement(const nsAString& aElementId) override;
-  virtual void MozSetImageElement(const nsAString& aImageElementId,
-                                  Element* aElement) override;
-
-  // AddPlugin adds a plugin-related element to mPlugins when the element is
-  // added to the tree.
-  virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) override;
-  // RemovePlugin removes a plugin-related element to mPlugins when the
-  // element is removed from the tree.
-  virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) override;
-  // GetPlugins returns the plugin-related elements from
-  // the frame and any subframes.
-  virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins) override;
-
-  // Adds an element to mResponsiveContent when the element is
-  // added to the tree.
-  virtual nsresult AddResponsiveContent(nsIContent* aContent) override;
-  // Removes an element from mResponsiveContent when the element is
-  // removed from the tree.
-  virtual void RemoveResponsiveContent(nsIContent* aContent) override;
-  // Notifies any responsive content added by AddResponsiveContent upon media
-  // features values changing.
-  virtual void NotifyMediaFeatureValuesChanged() override;
-
-  virtual nsresult GetStateObject(nsIVariant** aResult) override;
-
-  virtual nsDOMNavigationTiming* GetNavigationTiming() const override;
-  virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) override;
-
-  virtual Element* FindImageMap(const nsAString& aNormalizedMapName) override;
-
-  virtual nsTArray<Element*> GetFullscreenStack() const override;
-  virtual void AsyncRequestFullScreen(
-    mozilla::UniquePtr<FullscreenRequest>&& aRequest) override;
-  virtual void RestorePreviousFullScreenState() override;
-  virtual bool IsFullscreenLeaf() override;
-  virtual nsresult
-    RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
-
-  virtual nsresult RemoteFrameFullscreenReverted() override;
-  virtual nsIDocument* GetFullscreenRoot() override;
-  virtual void SetFullscreenRoot(nsIDocument* aRoot) override;
-
   // Returns the size of the mBlockedTrackingNodes array. (nsIDocument.h)
   //
   // This array contains nodes that have been blocked to prevent
   // user tracking. They most likely have had their nsIChannel
   // canceled by the URL classifier (Safebrowsing).
   //
   // A script can subsequently use GetBlockedTrackingNodes()
   // to get a list of references to these nodes.
@@ -798,162 +333,36 @@ public:
   // Returns strong references to mBlockedTrackingNodes. (nsIDocument.h)
   //
   // This array contains nodes that have been blocked to prevent
   // user tracking. They most likely have had their nsIChannel
   // canceled by the URL classifier (Safebrowsing).
   //
   already_AddRefed<nsSimpleContentList> BlockedTrackingNodes() const;
 
-  // Do the "fullscreen element ready check" from the fullscreen spec.
-  // It returns true if the given element is allowed to go into fullscreen.
-  bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);
-
-  // This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
-  // to move this document into full-screen mode if allowed.
-  void RequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&& aRequest);
-
-  // Removes all elements from the full-screen stack, removing full-scren
-  // styles from the top element in the stack.
-  void CleanupFullscreenState();
-
-  // Pushes aElement onto the full-screen stack, and removes full-screen styles
-  // from the former full-screen stack top, and its ancestors, and applies the
-  // styles to aElement. aElement becomes the new "full-screen element".
-  bool FullScreenStackPush(Element* aElement);
-
-  // Remove the top element from the full-screen stack. Removes the full-screen
-  // styles from the former top element, and applies them to the new top
-  // element, if there is one.
-  void FullScreenStackPop();
-
-  // Returns the top element from the full-screen stack.
-  Element* FullScreenStackTop() override;
-
-  // DOM-exposed fullscreen API
-  bool FullscreenEnabled(mozilla::dom::CallerType aCallerType) override;
-
-  virtual bool AllowPaymentRequest() const override;
-  virtual void SetAllowPaymentRequest(bool aIsAllowPaymentRequest) override;
-
-  void RequestPointerLock(Element* aElement,
-                          mozilla::dom::CallerType aCallerType) override;
-  bool SetPointerLock(Element* aElement, int aCursorStyle);
   static void UnlockPointer(nsIDocument* aDoc = nullptr);
 
-  void SetCurrentOrientation(mozilla::dom::OrientationType aType,
-                             uint16_t aAngle) override;
-  uint16_t CurrentOrientationAngle() const override;
-  mozilla::dom::OrientationType CurrentOrientationType() const override;
-  void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) override;
-  mozilla::dom::Promise* GetOrientationPendingPromise() const override;
-
-  // This method may fire a DOM event; if it does so it will happen
-  // synchronously.
-  void UpdateVisibilityState();
-  // Posts an event to call UpdateVisibilityState
-  virtual void PostVisibilityUpdateEvent() override;
-
-  // Since we wouldn't automatically play media from non-visited page, we need
-  // to notify window when the page was first visited.
-  void MaybeActiveMediaComponents();
-
   virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const override;
   // DocAddSizeOfIncludingThis is inherited from nsIDocument.
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
-  // WebIDL bits
-  virtual mozilla::dom::DOMImplementation*
-    GetImplementation(mozilla::ErrorResult& rv) override;
-
-  virtual already_AddRefed<Element> CreateElement(const nsAString& aTagName,
-                                                  const mozilla::dom::ElementCreationOptionsOrString& aOptions,
-                                                  ErrorResult& rv) override;
-  virtual already_AddRefed<Element> CreateElementNS(const nsAString& aNamespaceURI,
-                                                    const nsAString& aQualifiedName,
-                                                    const mozilla::dom::ElementCreationOptionsOrString& aOptions,
-                                                    mozilla::ErrorResult& rv) override;
-
-  virtual void UnblockDOMContentLoaded() override;
-
 protected:
   friend class nsNodeUtils;
 
-  /**
-   * Check that aId is not empty and log a message to the console
-   * service if it is.
-   * @returns true if aId looks correct, false otherwise.
-   */
-  inline bool CheckGetElementByIdArg(const nsAString& aId)
-  {
-    if (aId.IsEmpty()) {
-      ReportEmptyGetElementByIdArg();
-      return false;
-    }
-    return true;
-  }
-
-  void ReportEmptyGetElementByIdArg();
-
-  void DispatchContentLoadedEvents();
-
   void RetrieveRelevantHeaders(nsIChannel *aChannel);
 
   void TryChannelCharset(nsIChannel *aChannel,
                          int32_t& aCharsetSource,
                          NotNull<const Encoding*>& aEncoding,
                          nsHtml5TreeOpExecutor* aExecutor);
 
-  // Call this before the document does something that will unbind all content.
-  // That will stop us from doing a lot of work as each element is removed.
-  void DestroyElementMaps();
-
-  // Refreshes the hrefs of all the links in the document.
-  void RefreshLinkHrefs();
-
   nsIContent* GetFirstBaseNodeWithHref();
   nsresult SetFirstBaseNodeWithHref(nsIContent *node);
 
-  /**
-   * Returns the title element of the document as defined by the HTML
-   * specification, or null if there isn't one.  For documents whose root
-   * element is an <svg:svg>, this is the first <svg:title> element that's a
-   * child of the root.  For other documents, it's the first HTML title element
-   * in the document.
-   */
-  Element* GetTitleElement();
-
-public:
-  // Get our title
-  virtual void GetTitle(nsAString& aTitle) override;
-  // Set our title
-  virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) override;
-
-  js::ExpandoAndGeneration mExpandoAndGeneration;
-
-  bool ContainsEMEContent();
-
-  bool ContainsMSEContent();
-
-protected:
-
-  void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
-                              const nsAString& aType,
-                              bool aPersisted);
-
-  virtual nsPIDOMWindowOuter* GetWindowInternal() const override;
-  virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const override;
-  virtual bool InternalAllowXULXBL() override;
-
-  void UpdateScreenOrientation();
-
-  virtual mozilla::dom::FlashClassification DocumentFlashClassification() override;
-  virtual bool IsThirdParty() override;
-
 #define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) do {                     \
     NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
                                              func_, params_);                 \
     /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \
        looks bogus. */                                                        \
     if (nsIPresShell* shell = GetObservingShell()) {                          \
       shell->func_ params_;                                                   \
     }                                                                         \
@@ -963,240 +372,89 @@ protected:
   void VerifyRootContentState();
 #endif
 
   explicit nsDocument(const char* aContentType);
   virtual ~nsDocument();
 
   void EnsureOnloadBlocker();
 
-  // Apply the fullscreen state to the document, and trigger related
-  // events. It returns false if the fullscreen element ready check
-  // fails and nothing gets changed.
-  bool ApplyFullscreen(const FullscreenRequest& aRequest);
-
-  // Retrieves the classification of the Flash plugins in the document based on
-  // the classification lists.
-  mozilla::dom::FlashClassification PrincipalFlashClassification();
-
-  // Attempts to determine the Flash classification of this page based on the
-  // the classification lists and the classification of parent documents.
-  mozilla::dom::FlashClassification ComputeFlashClassification();
-
-  PLDHashTable *mSubDocuments;
-
-  // Array of owning references to all children
-  nsAttrAndChildArray mChildren;
-
-  // Array of intersection observers
-  nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
-    mIntersectionObservers;
+public:
+  // FIXME(emilio): This needs to be here instead of in nsIDocument because Rust
+  // can't represent alignas(8) values on 32-bit architectures, which would
+  // cause nsIDocument's layout to be wrong in the Rust side.
+  //
+  // This can be fixed after updating to rust 1.25 and updating bindgen to
+  // include https://github.com/rust-lang-nursery/rust-bindgen/pull/1271.
+  js::ExpandoAndGeneration mExpandoAndGeneration;
 
-  // Tracker for animations that are waiting to start.
-  // nullptr until GetOrCreatePendingAnimationTracker is called.
-  RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
-
-  // Weak reference to the scope object (aka the script global object)
-  // that, unlike mScriptGlobalObject, is never unset once set. This
-  // is a weak reference to avoid leaks due to circular references.
-  nsWeakPtr mScopeObject;
-
-  // Stack of full-screen elements. When we request full-screen we push the
-  // full-screen element onto this stack, and when we cancel full-screen we
-  // pop one off this stack, restoring the previous full-screen state
-  nsTArray<nsWeakPtr> mFullScreenStack;
-
-  // The root of the doc tree in which this document is in. This is only
-  // non-null when this document is in fullscreen mode.
-  nsWeakPtr mFullscreenRoot;
-
-  RefPtr<PrincipalFlashClassifier> mPrincipalFlashClassifier;
-  mozilla::dom::FlashClassification mFlashClassification;
-  // Do not use this value directly. Call the |IsThirdParty()| method, which
-  // caches its result here.
-  mozilla::Maybe<bool> mIsThirdParty;
-
-public:
   RefPtr<mozilla::EventListenerManager> mListenerManager;
-  RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
-  nsDocHeaderData* mHeaderData;
 
   nsClassHashtable<nsStringHashKey, nsRadioGroupStruct> mRadioGroups;
 
-  // Recorded time of change to 'loading' state.
-  mozilla::TimeStamp mLoadingTimeStamp;
-
-  // True if this document has ever had an HTML or SVG <title> element
-  // bound to it
-  bool mMayHaveTitleElement:1;
-
-  bool mHasWarnedAboutBoxObjects:1;
-
-  bool mDelayFrameLoaderInitialization:1;
-
-  bool mSynchronousDOMContentLoaded:1;
-
   // Parser aborted. True if the parser of this document was forcibly
   // terminated instead of letting it finish at its own pace.
   bool mParserAborted:1;
 
   friend class nsCallRequestFullScreen;
 
-  // ScreenOrientation "pending promise" as described by
-  // http://www.w3.org/TR/screen-orientation/
-  RefPtr<mozilla::dom::Promise> mOrientationPendingPromise;
-
-  uint16_t mCurrentOrientationAngle;
-  mozilla::dom::OrientationType mCurrentOrientationType;
-
   // Whether we have reported use counters for this document with Telemetry yet.
   // Normally this is only done at document destruction time, but for image
   // documents (SVG documents) that are not guaranteed to be destroyed, we
   // report use counters when the image cache no longer has any imgRequestProxys
   // pointing to them.  We track whether we ever reported use counters so
   // that we only report them once for the document.
   bool mReportedUseCounters:1;
 
-  uint8_t mPendingFullscreenRequests;
-
   uint8_t mXMLDeclarationBits;
 
-  nsRefPtrHashtable<nsPtrHashKey<nsIContent>, mozilla::dom::BoxObject>* mBoxObjectTable;
-
-  // A document "without a browsing context" that owns the content of
-  // HTMLTemplateElement.
-  nsCOMPtr<nsIDocument> mTemplateContentsOwner;
-
   // The application cache that this document is associated with, if
   // any.  This can change during the lifetime of the document.
   nsCOMPtr<nsIApplicationCache> mApplicationCache;
 
   nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
-
-  RefPtr<nsDOMNavigationTiming> mTiming;
 private:
   friend class nsUnblockOnloadEvent;
-  // Recomputes the visibility state but doesn't set the new value.
-  mozilla::dom::VisibilityState GetVisibilityState() const;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   nsresult InitCSP(nsIChannel* aChannel);
 
   void ClearAllBoxObjects();
 
   // Returns true if the scheme for the url for this document is "about"
   bool IsAboutPage() const;
 
   // These are not implemented and not supported.
   nsDocument(const nsDocument& aOther);
   nsDocument& operator=(const nsDocument& aOther);
 
-  // The layout history state that should be used by nodes in this
-  // document.  We only actually store a pointer to it when:
-  // 1)  We have no script global object.
-  // 2)  We haven't had Destroy() called on us yet.
-  nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
-
   // Currently active onload blockers
   uint32_t mOnloadBlockCount;
   // Onload blockers which haven't been activated yet
   uint32_t mAsyncOnloadBlockCount;
   nsCOMPtr<nsIRequest> mOnloadBlocker;
 
-  // A hashtable of styled links keyed by address pointer.
-  nsTHashtable<nsPtrHashKey<mozilla::dom::Link> > mStyledLinks;
-#ifdef DEBUG
-  // Indicates whether mStyledLinks was cleared or not.  This is used to track
-  // state so we can provide useful assertions to consumers of ForgetLink and
-  // AddStyleRelevantLink.
-  bool mStyledLinksCleared;
-#endif
-
-  // A set of responsive images keyed by address pointer.
-  nsTHashtable< nsPtrHashKey<nsIContent> > mResponsiveContent;
-
-  nsTArray<RefPtr<nsFrameLoader> > mInitializableFrameLoaders;
-  nsTArray<nsCOMPtr<nsIRunnable> > mFrameLoaderFinalizers;
-  RefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
-
   nsCOMPtr<nsIRunnable> mMaybeEndOutermostXBLUpdateRunner;
 
-  nsRevocableEventPtr<nsRunnableMethod<nsDocument, void, false> >
-    mPendingTitleChangeEvent;
-
-  nsExternalResourceMap mExternalResourceMap;
-
-  // All images in process of being preloaded.  This is a hashtable so
-  // we can remove them as the real image loads start; that way we
-  // make sure to not keep the image load going when no one cares
-  // about it anymore.
-  nsRefPtrHashtable<nsURIHashKey, imgIRequest> mPreloadingImages;
-
-  // A list of preconnects initiated by the preloader. This prevents
-  // the same uri from being used more than once, and allows the dom
-  // builder to not repeat the work of the preloader.
-  nsDataHashtable< nsURIHashKey, bool> mPreloadedPreconnects;
-
-  // Current depth of picture elements from parser
-  int32_t mPreloadPictureDepth;
-
-  // Set if we've found a URL for the current picture
-  nsString mPreloadPictureFoundSource;
-
-  RefPtr<mozilla::dom::DOMImplementation> mDOMImplementation;
-
-  RefPtr<nsContentList> mImageMaps;
-
-  nsWeakPtr mAutoFocusElement;
-
-  nsCString mScrollToRef;
-  uint8_t mScrolledToRefAlready : 1;
-  uint8_t mChangeScrollPosWhenScrollingToRef : 1;
-
-  // Tracking for plugins in the document.
-  nsTHashtable< nsPtrHashKey<nsIObjectLoadingContent> > mPlugins;
-
-  RefPtr<mozilla::dom::DocumentTimeline> mDocumentTimeline;
-  mozilla::LinkedList<mozilla::dom::DocumentTimeline> mTimelines;
-
-  enum ViewportType {
-    DisplayWidthHeight,
-    Specified,
-    Unknown
-  };
-
-  ViewportType mViewportType;
-
   // These member variables cache information about the viewport so we don't have to
   // recalculate it each time.
   bool mValidWidth, mValidHeight;
   mozilla::LayoutDeviceToScreenScale mScaleMinFloat;
   mozilla::LayoutDeviceToScreenScale mScaleMaxFloat;
   mozilla::LayoutDeviceToScreenScale mScaleFloat;
   mozilla::CSSToLayoutDeviceScale mPixelRatio;
   bool mAutoSize, mAllowZoom, mAllowDoubleTapZoom, mValidScaleFloat, mValidMaxScale, mScaleStrEmpty, mWidthStrEmpty;
   mozilla::CSSSize mViewportSize;
 
-  // Set to true when the document is possibly controlled by the ServiceWorker.
-  // Used to prevent multiple requests to ServiceWorkerManager.
-  bool mMaybeServiceWorkerControlled;
-
 #ifdef DEBUG
 public:
   bool mWillReparent;
 #endif
-
-private:
-  void RecordNavigationTiming(ReadyState aReadyState);
-  bool mDOMLoadingSet : 1;
-  bool mDOMInteractiveSet : 1;
-  bool mDOMCompleteSet : 1;
-  bool mAutoFocusFired : 1;
 };
 
 class nsDocumentOnStack
 {
 public:
   explicit nsDocumentOnStack(nsIDocument* aDoc) : mDoc(aDoc)
   {
     mDoc->IncreaseStackRefCnt();
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2,34 +2,44 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsIDocument_h___
 #define nsIDocument_h___
 
 #include "mozilla/FlushType.h"           // for enum
+#include "nsAttrAndChildArray.h"
 #include "nsAutoPtr.h"                   // for member
 #include "nsCOMArray.h"                  // for member
 #include "nsCompatibility.h"             // for member
 #include "nsCOMPtr.h"                    // for member
 #include "nsGkAtoms.h"                   // for static class members
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheContainer.h"
+#include "nsIContentViewer.h"
 #include "nsIDocumentObserver.h"         // for typedef (nsUpdateType)
+#include "nsIInterfaceRequestor.h"
+#include "nsILoadContext.h"
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIParser.h"
 #include "nsIPresShell.h"
+#include "nsIChannelEventSink.h"
+#include "nsIProgressEventSink.h"
+#include "nsISecurityEventSink.h"
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
 #include "nsIServiceManager.h"
 #include "nsIURI.h"                      // for use in inline functions
 #include "nsIUUIDGenerator.h"
 #include "nsPIDOMWindow.h"               // for use in inline functions
 #include "nsPropertyTable.h"             // for member
 #include "nsStringFwd.h"
 #include "nsTHashtable.h"                // for member
+#include "nsURIHashKey.h"
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "nsWeakReference.h"
 #include "mozilla/UseCounter.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsContentListDeclarations.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
@@ -151,16 +161,17 @@ class Element;
 struct ElementCreationOptions;
 class Event;
 class EventTarget;
 class FontFaceSet;
 class FrameRequestCallback;
 struct FullscreenRequest;
 class ImageTracker;
 class HTMLBodyElement;
+class HTMLImageElement;
 struct LifecycleCallbackArgs;
 class Link;
 class Location;
 class MediaQueryList;
 class GlobalObject;
 class NodeFilter;
 class NodeIterator;
 enum class OrientationType : uint8_t;
@@ -208,31 +219,239 @@ enum DocumentFlavor {
 #define NS_DOCUMENT_STATE_RTL_LOCALE              NS_DEFINE_EVENT_STATE_MACRO(0)
 // Window activation status
 #define NS_DOCUMENT_STATE_WINDOW_INACTIVE         NS_DEFINE_EVENT_STATE_MACRO(1)
 
 // Some function forward-declarations
 class nsContentList;
 class nsDocumentOnStack;
 
+class nsDocHeaderData
+{
+public:
+  nsDocHeaderData(nsAtom* aField, const nsAString& aData)
+    : mField(aField), mData(aData), mNext(nullptr)
+  {
+  }
+
+  ~nsDocHeaderData(void)
+  {
+    delete mNext;
+  }
+
+  RefPtr<nsAtom> mField;
+  nsString mData;
+  nsDocHeaderData* mNext;
+};
+
+class nsExternalResourceMap
+{
+  typedef bool (*nsSubDocEnumFunc)(nsIDocument *aDocument, void *aData);
+
+public:
+  /**
+   * A class that represents an external resource load that has begun but
+   * doesn't have a document yet.  Observers can be registered on this object,
+   * and will be notified after the document is created.  Observers registered
+   * after the document has been created will NOT be notified.  When observers
+   * are notified, the subject will be the newly-created document, the topic
+   * will be "external-resource-document-created", and the data will be null.
+   * If document creation fails for some reason, observers will still be
+   * notified, with a null document pointer.
+   */
+  class ExternalResourceLoad : public nsISupports
+  {
+  public:
+    virtual ~ExternalResourceLoad() {}
+
+    void AddObserver(nsIObserver* aObserver)
+    {
+      MOZ_ASSERT(aObserver, "Must have observer");
+      mObservers.AppendElement(aObserver);
+    }
+
+    const nsTArray<nsCOMPtr<nsIObserver>> & Observers()
+    {
+      return mObservers;
+    }
+  protected:
+    AutoTArray<nsCOMPtr<nsIObserver>, 8> mObservers;
+  };
+
+  nsExternalResourceMap();
+
+  /**
+   * Request an external resource document.  This does exactly what
+   * nsIDocument::RequestExternalResource is documented to do.
+   */
+  nsIDocument* RequestResource(nsIURI* aURI,
+                               nsINode* aRequestingNode,
+                               nsIDocument* aDisplayDocument,
+                               ExternalResourceLoad** aPendingLoad);
+
+  /**
+   * Enumerate the resource documents.  See
+   * nsIDocument::EnumerateExternalResources.
+   */
+  void EnumerateResources(nsSubDocEnumFunc aCallback, void* aData);
+
+  /**
+   * Traverse ourselves for cycle-collection
+   */
+  void Traverse(nsCycleCollectionTraversalCallback* aCallback) const;
+
+  /**
+   * Shut ourselves down (used for cycle-collection unlink), as well
+   * as for document destruction.
+   */
+  void Shutdown()
+  {
+    mPendingLoads.Clear();
+    mMap.Clear();
+    mHaveShutDown = true;
+  }
+
+  bool HaveShutDown() const
+  {
+    return mHaveShutDown;
+  }
+
+  // Needs to be public so we can traverse them sanely
+  struct ExternalResource
+  {
+    ~ExternalResource();
+    nsCOMPtr<nsIDocument> mDocument;
+    nsCOMPtr<nsIContentViewer> mViewer;
+    nsCOMPtr<nsILoadGroup> mLoadGroup;
+  };
+
+  // Hide all our viewers
+  void HideViewers();
+
+  // Show all our viewers
+  void ShowViewers();
+
+protected:
+  class PendingLoad : public ExternalResourceLoad,
+                      public nsIStreamListener
+  {
+    ~PendingLoad() {}
+
+  public:
+    explicit PendingLoad(nsIDocument* aDisplayDocument) :
+      mDisplayDocument(aDisplayDocument)
+    {}
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSISTREAMLISTENER
+    NS_DECL_NSIREQUESTOBSERVER
+
+    /**
+     * Start aURI loading.  This will perform the necessary security checks and
+     * so forth.
+     */
+    nsresult StartLoad(nsIURI* aURI, nsINode* aRequestingNode);
+
+    /**
+     * Set up an nsIContentViewer based on aRequest.  This is guaranteed to
+     * put null in *aViewer and *aLoadGroup on all failures.
+     */
+    nsresult SetupViewer(nsIRequest* aRequest, nsIContentViewer** aViewer,
+                         nsILoadGroup** aLoadGroup);
+
+  private:
+    nsCOMPtr<nsIDocument> mDisplayDocument;
+    nsCOMPtr<nsIStreamListener> mTargetListener;
+    nsCOMPtr<nsIURI> mURI;
+  };
+  friend class PendingLoad;
+
+  class LoadgroupCallbacks final : public nsIInterfaceRequestor
+  {
+    ~LoadgroupCallbacks() {}
+  public:
+    explicit LoadgroupCallbacks(nsIInterfaceRequestor* aOtherCallbacks)
+      : mCallbacks(aOtherCallbacks)
+    {}
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIINTERFACEREQUESTOR
+  private:
+    // The only reason it's safe to hold a strong ref here without leaking is
+    // that the notificationCallbacks on a loadgroup aren't the docshell itself
+    // but a shim that holds a weak reference to the docshell.
+    nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
+
+    // Use shims for interfaces that docshell implements directly so that we
+    // don't hand out references to the docshell.  The shims should all allow
+    // getInterface back on us, but other than that each one should only
+    // implement one interface.
+
+    // XXXbz I wish we could just derive the _allcaps thing from _i
+#define DECL_SHIM(_i, _allcaps)                                              \
+    class _i##Shim final : public nsIInterfaceRequestor,                     \
+                           public _i                                         \
+    {                                                                        \
+      ~_i##Shim() {}                                                         \
+    public:                                                                  \
+      _i##Shim(nsIInterfaceRequestor* aIfreq, _i* aRealPtr)                  \
+        : mIfReq(aIfreq), mRealPtr(aRealPtr)                                 \
+      {                                                                      \
+        NS_ASSERTION(mIfReq, "Expected non-null here");                      \
+        NS_ASSERTION(mRealPtr, "Expected non-null here");                    \
+      }                                                                      \
+      NS_DECL_ISUPPORTS                                                      \
+      NS_FORWARD_NSIINTERFACEREQUESTOR(mIfReq->)                             \
+      NS_FORWARD_##_allcaps(mRealPtr->)                                      \
+    private:                                                                 \
+      nsCOMPtr<nsIInterfaceRequestor> mIfReq;                                \
+      nsCOMPtr<_i> mRealPtr;                                                 \
+    };
+
+    DECL_SHIM(nsILoadContext, NSILOADCONTEXT)
+    DECL_SHIM(nsIProgressEventSink, NSIPROGRESSEVENTSINK)
+    DECL_SHIM(nsIChannelEventSink, NSICHANNELEVENTSINK)
+    DECL_SHIM(nsISecurityEventSink, NSISECURITYEVENTSINK)
+    DECL_SHIM(nsIApplicationCacheContainer, NSIAPPLICATIONCACHECONTAINER)
+#undef DECL_SHIM
+  };
+
+  /**
+   * Add an ExternalResource for aURI.  aViewer and aLoadGroup might be null
+   * when this is called if the URI didn't result in an XML document.  This
+   * function makes sure to remove the pending load for aURI, if any, from our
+   * hashtable, and to notify its observers, if any.
+   */
+  nsresult AddExternalResource(nsIURI* aURI, nsIContentViewer* aViewer,
+                               nsILoadGroup* aLoadGroup,
+                               nsIDocument* aDisplayDocument);
+
+  nsClassHashtable<nsURIHashKey, ExternalResource> mMap;
+  nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads;
+  bool mHaveShutDown;
+};
+
 //----------------------------------------------------------------------
 
+// For classifying a flash document based on its principal.
+class PrincipalFlashClassifier;
+
 // Document interface.  This is implemented by all document objects in
 // Gecko.
 class nsIDocument : public nsINode,
                     public mozilla::dom::DocumentOrShadowRoot,
                     public mozilla::dom::DispatcherTrait
 {
   typedef mozilla::dom::GlobalObject GlobalObject;
 
 protected:
   using Encoding = mozilla::Encoding;
   template <typename T> using NotNull = mozilla::NotNull<T>;
 
 public:
+  typedef nsExternalResourceMap::ExternalResourceLoad ExternalResourceLoad;
   typedef mozilla::net::ReferrerPolicy ReferrerPolicyEnum;
   typedef mozilla::dom::Element Element;
   typedef mozilla::dom::FullscreenRequest FullscreenRequest;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
 
 #ifdef MOZILLA_INTERNAL_API
   nsIDocument();
@@ -308,23 +527,53 @@ public:
   virtual void StopDocumentLoad() = 0;
 
   virtual void SetSuppressParserErrorElement(bool aSuppress) {}
   virtual bool SuppressParserErrorElement() { return false; }
 
   virtual void SetSuppressParserErrorConsoleMessages(bool aSuppress) {}
   virtual bool SuppressParserErrorConsoleMessages() { return false; }
 
+  // nsINode
+  bool IsNodeOfType(uint32_t aFlags) const final;
+  nsIContent* GetChildAt_Deprecated(uint32_t aIndex) const final
+  {
+    return mChildren.GetSafeChildAt(aIndex);
+  }
+
+  int32_t ComputeIndexOf(const nsINode* aPossibleChild) const final
+  {
+    return mChildren.IndexOfChild(aPossibleChild);
+  }
+
+  uint32_t GetChildCount() const final
+  {
+    return mChildren.ChildCount();
+  }
+
+  nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
+                             bool aNotify) override;
+  nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
+                                    bool aNotify) override;
+  void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) final;
+  void RemoveChildNode(nsIContent* aKid, bool aNotify) final;
+  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo,
+                 nsINode **aResult,
+                 bool aPreallocateChildren) const override
+  {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
   /**
    * Signal that the document title may have changed
    * (see nsDocument::GetTitle).
    * @param aBoundTitleElement true if an HTML or SVG <title> element
    * has just been bound to the document.
    */
-  virtual void NotifyPossibleTitleChange(bool aBoundTitleElement) = 0;
+  void NotifyPossibleTitleChange(bool aBoundTitleElement);
 
   /**
    * Return the URI for the document. May return null.
    *
    * The value returned corresponds to the "document's address" in
    * HTML5.  As such, it may change over the lifetime of the document, for
    * instance as a result of the user navigating to a fragment identifier on
    * the page, or as a result to a call to pushState() or replaceState().
@@ -351,34 +600,40 @@ public:
   {
     return mOriginalURI;
   }
 
   /**
    * Set the URI for the document.  This also sets the document's original URI,
    * if it's null.
    */
-  virtual void SetDocumentURI(nsIURI* aURI) = 0;
+  void SetDocumentURI(nsIURI* aURI);
 
   /**
    * Set the URI for the document loaded via XHR, when accessed from
    * chrome privileged script.
    */
-  virtual void SetChromeXHRDocURI(nsIURI* aURI) = 0;
+  void SetChromeXHRDocURI(nsIURI* aURI)
+  {
+    mChromeXHRDocURI = aURI;
+  }
 
   /**
    * Set the base URI for the document loaded via XHR, when accessed from
    * chrome privileged script.
    */
-  virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) = 0;
+  void SetChromeXHRDocBaseURI(nsIURI* aURI)
+  {
+    mChromeXHRDocBaseURI = aURI;
+  }
 
   /**
    * Set referrer policy and upgrade-insecure-requests flags
    */
-  virtual void ApplySettingsFromCSP(bool aSpeculative) = 0;
+  void ApplySettingsFromCSP(bool aSpeculative);
 
   already_AddRefed<nsIParser> CreatorParserOrNull()
   {
     nsCOMPtr<nsIParser> parser = mParser;
     return parser.forget();
   }
 
   /**
@@ -429,17 +684,17 @@ public:
   void SetReferrer(const nsACString& aReferrer) {
     mReferrer = aReferrer;
   }
 
   /**
    * Set the principal responsible for this document.  Chances are,
    * you do not want to be using this.
    */
-  virtual void SetPrincipal(nsIPrincipal *aPrincipal) = 0;
+  void SetPrincipal(nsIPrincipal* aPrincipal);
 
   /**
    * Get the list of ancestor principals for a document.  This is the same as
    * the ancestor list for the document's docshell the last time SetContainer()
    * was called with a non-null argument. See the documentation for the
    * corresponding getter in docshell for how this list is determined.  We store
    * a copy of the list, because we may lose the ability to reach our docshell
    * before people stop asking us for this information.
@@ -490,33 +745,38 @@ public:
    */
   nsIURI* GetDocBaseURI() const
   {
     if (mDocumentBaseURI) {
       return mDocumentBaseURI;
     }
     return GetFallbackBaseURI();
   }
-  virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
-
-  virtual void SetBaseURI(nsIURI* aURI) = 0;
+
+  already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const final;
+
+  void SetBaseURI(nsIURI* aURI);
 
   /**
    * Return the URL data which style system needs for resolving url value.
    * This method attempts to use the cached object in mCachedURLData, but
    * if the base URI, document URI, or principal has changed since last
    * call to this function, or the function is called the first time for
    * the document, a new one is created.
    */
   mozilla::URLExtraData* DefaultStyleAttrURLData();
 
   /**
    * Get/Set the base target of a link in a document.
    */
-  virtual void GetBaseTarget(nsAString &aBaseTarget) = 0;
+  void GetBaseTarget(nsAString& aBaseTarget) const
+  {
+    aBaseTarget = mBaseTarget;
+  }
+
   void SetBaseTarget(const nsString& aBaseTarget) {
     mBaseTarget = aBaseTarget;
   }
 
   /**
    * Return a standard name for the document's character set.
    */
   NotNull<const Encoding*> GetDocumentCharacterSet() const
@@ -558,24 +818,40 @@ public:
    * in the future. If aForImage is true, mozSetImageElement can override
    * what content is associated with the ID. In that case the IDTargetObserver
    * will be notified at those times when the result of LookupImageElement
    * changes.
    * At most one (aObserver, aData, aForImage) triple can be
    * registered for each ID.
    * @return the content currently associated with the ID.
    */
-  virtual Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
-                                       void* aData, bool aForImage) = 0;
+  Element* AddIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
+                               void* aData, bool aForImage);
   /**
    * Remove the (aObserver, aData, aForImage) triple for a specific ID, if
    * registered.
    */
-  virtual void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
-                                      void* aData, bool aForImage) = 0;
+  void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver,
+                              void* aData, bool aForImage);
+
+  /**
+   * Check that aId is not empty and log a message to the console
+   * service if it is.
+   * @returns true if aId looks correct, false otherwise.
+   */
+  inline bool CheckGetElementByIdArg(const nsAString& aId)
+  {
+    if (aId.IsEmpty()) {
+      ReportEmptyGetElementByIdArg();
+      return false;
+    }
+    return true;
+  }
+
+  void ReportEmptyGetElementByIdArg();
 
   /**
    * Get the Content-Type of this document.
    */
   void GetContentType(nsAString& aContentType);
 
   /**
    * Set the Content-Type of this document.
@@ -888,31 +1164,30 @@ public:
   {
     mEncodingMenuDisabled = true;
   }
 
   /**
    * Access HTTP header data (this may also get set from other
    * sources, like HTML META tags).
    */
-  virtual void GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const = 0;
-  virtual void SetHeaderData(nsAtom* aheaderField, const nsAString& aData) = 0;
+  void GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const;
+  void SetHeaderData(nsAtom* aheaderField, const nsAString& aData);
 
   /**
    * Create a new presentation shell that will use aContext for its
    * presentation context (presentation contexts <b>must not</b> be
    * shared among multiple presentation shells). The caller of this
    * method is responsible for calling BeginObservingDocument() on the
    * presshell if the presshell should observe document mutations.
    */
-  virtual already_AddRefed<nsIPresShell> CreateShell(
-      nsPresContext* aContext,
-      nsViewManager* aViewManager,
-      mozilla::StyleSetHandle aStyleSet) = 0;
-  virtual void DeleteShell() = 0;
+  already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
+                                             nsViewManager* aViewManager,
+                                             mozilla::StyleSetHandle aStyleSet);
+  void DeleteShell();
 
   nsIPresShell* GetShell() const
   {
     return GetBFCacheEntry() ? nullptr : mPresShell;
   }
 
   nsIPresShell* GetObservingShell() const
   {
@@ -979,33 +1254,32 @@ public:
     if (aParent) {
       mIgnoreDocGroupMismatches = aParent->mIgnoreDocGroupMismatches;
     }
   }
 
   /**
    * Are plugins allowed in this document ?
    */
-  virtual bool GetAllowPlugins () = 0;
+  bool GetAllowPlugins();
 
   /**
    * Set the sub document for aContent to aSubDoc.
    */
-  virtual nsresult SetSubDocumentFor(Element* aContent,
-                                     nsIDocument* aSubDoc) = 0;
+  nsresult SetSubDocumentFor(Element* aContent, nsIDocument* aSubDoc);
 
   /**
    * Get the sub document for aContent
    */
-  virtual nsIDocument *GetSubDocumentFor(nsIContent *aContent) const = 0;
+  nsIDocument* GetSubDocumentFor(nsIContent* aContent) const;
 
   /**
    * Find the content node for which aDocument is a sub document.
    */
-  virtual Element* FindContentForSubDocument(nsIDocument* aDocument) const = 0;
+  Element* FindContentForSubDocument(nsIDocument* aDocument) const;
 
   /**
    * Return the doctype for this document.
    */
   mozilla::dom::DocumentType* GetDoctype() const;
 
   /**
    * Return the root element for this document.
@@ -1097,17 +1371,17 @@ public:
     if (!mPageUnloadingEventTimeStamp ||
         parentTimeStamp < mPageUnloadingEventTimeStamp) {
       return parentTimeStamp;
     }
 
     return mPageUnloadingEventTimeStamp;
   }
 
-  virtual void NotifyLayerManagerRecreated() = 0;
+  void NotifyLayerManagerRecreated();
 
   /**
    * Add an SVG element to the list of elements that need
    * their mapped attributes resolved to a Servo declaration block.
    *
    * These are weak pointers, please manually unschedule them when an element
    * is removed.
    */
@@ -1126,17 +1400,28 @@ public:
   // Resolve all SVG pres attrs scheduled in ScheduleSVGForPresAttrEvaluation
   void ResolveScheduledSVGPresAttrs();
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
 protected:
-  virtual Element *GetRootElementInternal() const = 0;
+  void DispatchContentLoadedEvents();
+
+  void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
+                              const nsAString& aType,
+                              bool aPersisted);
+
+  // Call this before the document does something that will unbind all content.
+  // That will stop us from doing a lot of work as each element is removed.
+  void DestroyElementMaps();
+
+  Element* GetRootElementInternal() const;
+  void DoNotifyPossibleTitleChange();
 
   void SetPageUnloadingEventTimeStamp()
   {
     MOZ_ASSERT(!mPageUnloadingEventTimeStamp);
     mPageUnloadingEventTimeStamp = mozilla::TimeStamp::NowLoRes();
   }
 
   void CleanUnloadEventsTimeStamp()
@@ -1450,17 +1735,20 @@ public:
     return mStyleImageLoader;
   }
 
   /**
    * Get the channel that was passed to StartDocumentLoad or Reset for this
    * document.  Note that this may be null in some cases (eg if
    * StartDocumentLoad or Reset were never called)
    */
-  virtual nsIChannel* GetChannel() const = 0;
+  nsIChannel* GetChannel() const
+  {
+    return mChannel;
+  }
 
   /**
    * Get this document's attribute stylesheet.  May return null if
    * there isn't one.
    */
   nsHTMLStyleSheet* GetAttributeStyleSheet() const {
     return mAttrStyleSheet;
   }
@@ -1486,27 +1774,27 @@ public:
    */
   nsIScriptGlobalObject*
     GetScriptHandlingObject(bool& aHasHadScriptHandlingObject) const
   {
     aHasHadScriptHandlingObject = mHasHadScriptHandlingObject;
     return mScriptGlobalObject ? mScriptGlobalObject.get() :
                                  GetScriptHandlingObjectInternal();
   }
-  virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject) = 0;
+  void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject);
 
   /**
    * Get the object that is used as the scope for all of the content
    * wrappers whose owner document is this document. Unlike the script global
    * object, this will only return null when the global object for this
    * document is truly gone. Use this object when you're trying to find a
    * content wrapper in XPConnect.
    */
-  virtual nsIGlobalObject* GetScopeObject() const = 0;
-  virtual void SetScopeObject(nsIGlobalObject* aGlobal) = 0;
+  nsIGlobalObject* GetScopeObject() const;
+  void SetScopeObject(nsIGlobalObject* aGlobal);
 
   /**
    * Return the window containing the document (the outer window).
    */
   nsPIDOMWindowOuter *GetWindow() const
   {
     return mWindow ? mWindow->GetOuterWindow() : GetWindowInternal();
   }
@@ -1545,90 +1833,113 @@ public:
     return window ? window->WindowID() : 0;
   }
 
   bool IsTopLevelWindowInactive() const;
 
   /**
    * Get the script loader for this document
    */
-  virtual mozilla::dom::ScriptLoader* ScriptLoader() = 0;
+  mozilla::dom::ScriptLoader* ScriptLoader()
+  {
+    return mScriptLoader;
+  }
 
   /**
    * Add/Remove an element to the document's id and name hashes
    */
-  virtual void AddToIdTable(Element* aElement, nsAtom* aId) = 0;
-  virtual void RemoveFromIdTable(Element* aElement, nsAtom* aId) = 0;
-  virtual void AddToNameTable(Element* aElement, nsAtom* aName) = 0;
-  virtual void RemoveFromNameTable(Element* aElement, nsAtom* aName) = 0;
+  void AddToIdTable(Element* aElement, nsAtom* aId);
+  void RemoveFromIdTable(Element* aElement, nsAtom* aId);
+  void AddToNameTable(Element* aElement, nsAtom* aName);
+  void RemoveFromNameTable(Element* aElement, nsAtom* aName);
 
   /**
    * Returns all elements in the fullscreen stack in the insertion order.
    */
-  virtual nsTArray<Element*> GetFullscreenStack() const = 0;
+  nsTArray<Element*> GetFullscreenStack() const;
 
   /**
    * Asynchronously requests that the document make aElement the fullscreen
    * element, and move into fullscreen mode. The current fullscreen element
    * (if any) is pushed onto the fullscreen element stack, and it can be
    * returned to fullscreen status by calling RestorePreviousFullScreenState().
    *
    * Note that requesting fullscreen in a document also makes the element which
    * contains this document in this document's parent document fullscreen. i.e.
    * the <iframe> or <browser> that contains this document is also mode
    * fullscreen. This happens recursively in all ancestor documents.
    */
-  virtual void AsyncRequestFullScreen(
-    mozilla::UniquePtr<FullscreenRequest>&& aRequest) = 0;
+  void AsyncRequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&&);
+
+  // Do the "fullscreen element ready check" from the fullscreen spec.
+  // It returns true if the given element is allowed to go into fullscreen.
+  bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);
+
+  // This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
+  // to move this document into full-screen mode if allowed.
+  void RequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&& aRequest);
+
+  // Removes all elements from the full-screen stack, removing full-scren
+  // styles from the top element in the stack.
+  void CleanupFullscreenState();
+
+  // Pushes aElement onto the full-screen stack, and removes full-screen styles
+  // from the former full-screen stack top, and its ancestors, and applies the
+  // styles to aElement. aElement becomes the new "full-screen element".
+  bool FullScreenStackPush(Element* aElement);
+
+  // Remove the top element from the full-screen stack. Removes the full-screen
+  // styles from the former top element, and applies them to the new top
+  // element, if there is one.
+  void FullScreenStackPop();
 
   /**
    * Called when a frame in a child process has entered fullscreen or when a
    * fullscreen frame in a child process changes to another origin.
    * aFrameElement is the frame element which contains the child-process
    * fullscreen document.
    */
-  virtual nsresult
-    RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) = 0;
+  nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement);
 
   /**
    * Called when a frame in a remote child document has rolled back fullscreen
    * so that all its fullscreen element stacks are empty; we must continue the
    * rollback in this parent process' doc tree branch which is fullscreen.
    * Note that only one branch of the document tree can have its documents in
    * fullscreen state at one time. We're in inconsistent state if a
    * fullscreen document has a parent and that parent isn't fullscreen. We
    * preserve this property across process boundaries.
    */
-   virtual nsresult RemoteFrameFullscreenReverted() = 0;
+   nsresult RemoteFrameFullscreenReverted();
 
   /**
    * Restores the previous full-screen element to full-screen status. If there
    * is no former full-screen element, this exits full-screen, moving the
    * top-level browser window out of full-screen mode.
    */
-  virtual void RestorePreviousFullScreenState() = 0;
+  void RestorePreviousFullScreenState();
 
   /**
    * Returns true if this document is a fullscreen leaf document, i.e. it
    * is in fullscreen mode and has no fullscreen children.
    */
-  virtual bool IsFullscreenLeaf() = 0;
+  bool IsFullscreenLeaf();
 
   /**
    * Returns the document which is at the root of this document's branch
    * in the in-process document tree. Returns nullptr if the document isn't
    * fullscreen.
    */
-  virtual nsIDocument* GetFullscreenRoot() = 0;
+  nsIDocument* GetFullscreenRoot();
 
   /**
    * Sets the fullscreen root to aRoot. This stores a weak reference to aRoot
    * in this document.
    */
-  virtual void SetFullscreenRoot(nsIDocument* aRoot) = 0;
+  void SetFullscreenRoot(nsIDocument* aRoot);
 
   /**
    * Synchronously cleans up the fullscreen state on the given document.
    *
    * Calling this without performing fullscreen transition could lead
    * to undesired effect (the transition happens after document state
    * flips), hence it should only be called either by nsGlobalWindow
    * when we have performed the transition, or when it is necessary to
@@ -1658,29 +1969,43 @@ public:
   static bool HandlePendingFullscreenRequests(nsIDocument* aDocument);
 
   /**
    * Dispatch fullscreenerror event and report the failure message to
    * the console.
    */
   void DispatchFullscreenError(const char* aMessage);
 
-  virtual void RequestPointerLock(Element* aElement,
-                                  mozilla::dom::CallerType aCallerType) = 0;
+  void RequestPointerLock(Element* aElement, mozilla::dom::CallerType);
+  bool SetPointerLock(Element* aElement, int aCursorStyle);
 
   static void UnlockPointer(nsIDocument* aDoc = nullptr);
 
   // ScreenOrientation related APIs
 
-  virtual void SetCurrentOrientation(mozilla::dom::OrientationType aType,
-                                     uint16_t aAngle) = 0;
-  virtual uint16_t CurrentOrientationAngle() const = 0;
-  virtual mozilla::dom::OrientationType CurrentOrientationType() const = 0;
-  virtual void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) = 0;
-  virtual mozilla::dom::Promise* GetOrientationPendingPromise() const = 0;
+  void SetCurrentOrientation(mozilla::dom::OrientationType aType,
+                             uint16_t aAngle)
+  {
+    mCurrentOrientationType = aType;
+    mCurrentOrientationAngle = aAngle;
+  }
+
+  uint16_t CurrentOrientationAngle() const
+  {
+    return mCurrentOrientationAngle;
+  }
+  mozilla::dom::OrientationType CurrentOrientationType() const
+  {
+    return mCurrentOrientationType;
+  }
+  void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise);
+  mozilla::dom::Promise* GetOrientationPendingPromise() const
+  {
+    return mOrientationPendingPromise;
+  }
 
   //----------------------------------------------------------------------
 
   // Document notification API's
 
   /**
    * Add a new observer of document change notifications. Whenever
    * content is changed, appended, inserted or removed the observers are
@@ -1701,17 +2026,17 @@ public:
   // To make this easy and painless, use the mozAutoDocUpdate helper class.
   void BeginUpdate(nsUpdateType aUpdateType);
   virtual void EndUpdate(nsUpdateType aUpdateType) = 0;
 
   virtual void BeginLoad() = 0;
   virtual void EndLoad() = 0;
 
   enum ReadyState { READYSTATE_UNINITIALIZED = 0, READYSTATE_LOADING = 1, READYSTATE_INTERACTIVE = 3, READYSTATE_COMPLETE = 4};
-  virtual void SetReadyStateInternal(ReadyState rs) = 0;
+  void SetReadyStateInternal(ReadyState rs);
   ReadyState GetReadyStateEnum()
   {
     return mReadyState;
   }
 
   // notify that a content node changed state.  This must happen under
   // a scriptblocker but NOT within a begin/end update.
   void ContentStateChanged(
@@ -1746,17 +2071,17 @@ public:
   void FlushPendingNotifications(mozilla::ChangesToFlush aFlush);
 
   /**
    * Calls FlushPendingNotifications on any external resources this document
    * has. If this document has no external resources or is an external resource
    * itself this does nothing. This should only be called with
    * aType >= FlushType::Style.
    */
-  virtual void FlushExternalResources(mozilla::FlushType aType) = 0;
+  void FlushExternalResources(mozilla::FlushType aType);
 
   nsBindingManager* BindingManager() const
   {
     return mNodeInfoManager->GetBindingManager();
   }
 
   /**
    * Only to be used inside Gecko, you can't really do anything with the
@@ -1846,17 +2171,17 @@ public:
   {
     return IsLoadedAsData() || IsLoadedAsInteractiveData();
   }
   bool LoadsFullXULStyleSheetUpFront()
   {
     return IsXULDocument() || AllowXULXBL();
   }
 
-  virtual bool IsScriptEnabled() = 0;
+  bool IsScriptEnabled();
 
   bool IsTopLevelContentDocument() const { return mIsTopLevelContentDocument; }
   void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument)
   {
     mIsTopLevelContentDocument = aIsTopLevelContentDocument;
     // When a document is set as TopLevelContentDocument, it must be
     // allowpaymentrequest. We handle the false case while a document is appended
     // in SetSubDocumentFor
@@ -1937,35 +2262,34 @@ public:
   uint32_t GetPartID() const {
     return mPartID;
   }
 
   /**
    * Sanitize the document by resetting all input elements and forms that have
    * autocomplete=off to their default values.
    */
-  virtual void Sanitize() = 0;
+  void Sanitize();
 
   /**
    * Enumerate all subdocuments.
    * The enumerator callback should return true to continue enumerating, or
    * false to stop.  This will never get passed a null aDocument.
    */
   typedef bool (*nsSubDocEnumFunc)(nsIDocument *aDocument, void *aData);
-  virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
-                                     void *aData) = 0;
+  void EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData);
 
   /**
    * Collect all the descendant documents for which |aCalback| returns true.
    * The callback function must not mutate any state for the given document.
    */
   typedef bool (*nsDocTestFunc)(const nsIDocument* aDocument);
-  virtual void CollectDescendantDocuments(
+  void CollectDescendantDocuments(
     nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
-    nsDocTestFunc aCallback) const = 0;
+    nsDocTestFunc aCallback) const;
 
   /**
    * Check whether it is safe to cache the presentation of this document
    * and all of its subdocuments. This method checks the following conditions
    * recursively:
    *  - Some document types, such as plugin documents, cannot be safely cached.
    *  - If there are any pending requests, we don't allow the presentation
    *    to be cached.  Ideally these requests would be suspended and resumed,
@@ -1974,17 +2298,17 @@ public:
    *    for correctness, but this likely puts the document into a state where
    *    it would not function correctly if restored.
    *
    * |aNewRequest| should be the request for a new document which will
    * replace this document in the docshell.  The new document's request
    * will be ignored when checking for active requests.  If there is no
    * request associated with the new document, this parameter may be null.
    */
-  virtual bool CanSavePresentation(nsIRequest *aNewRequest) = 0;
+  virtual bool CanSavePresentation(nsIRequest* aNewRequest);
 
   /**
    * Notify the document that its associated ContentViewer is being destroyed.
    * This releases circular references so that the document can go away.
    * Destroy() is only called on documents that have a content viewer.
    */
   virtual void Destroy() = 0;
 
@@ -1996,17 +2320,17 @@ public:
    */
   virtual void RemovedFromDocShell() = 0;
 
   /**
    * Get the layout history state that should be used to save and restore state
    * for nodes in this document.  This may return null; if that happens state
    * saving and restoration is not possible.
    */
-  virtual already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const = 0;
+  already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const;
 
   /**
    * Methods that can be used to prevent onload firing while an event that
    * should block onload is posted.  onload is guaranteed to not fire until
    * either all calls to BlockOnload() have been matched by calls to
    * UnblockOnload() or the load has been stopped altogether (by the user
    * pressing the Stop button, say).
    */
@@ -2019,78 +2343,99 @@ public:
    */
   virtual void UnblockOnload(bool aFireSync) = 0;
 
   void BlockDOMContentLoaded()
   {
     ++mBlockDOMContentLoaded;
   }
 
-  virtual void UnblockDOMContentLoaded() = 0;
+  void UnblockDOMContentLoaded();
 
   /**
    * Notification that the page has been shown, for documents which are loaded
    * into a DOM window.  This corresponds to the completion of document load,
    * or to the page's presentation being restored into an existing DOM window.
    * This notification fires applicable DOM events to the content window.  See
    * PageTransitionEvent.webidl for a description of the |aPersisted|
    * parameter. If aDispatchStartTarget is null, the pageshow event is
    * dispatched on the ScriptGlobalObject for this document, otherwise it's
    * dispatched on aDispatchStartTarget.
    * Note: if aDispatchStartTarget isn't null, the showing state of the
    * document won't be altered.
    */
   virtual void OnPageShow(bool aPersisted,
-                          mozilla::dom::EventTarget* aDispatchStartTarget) = 0;
+                          mozilla::dom::EventTarget* aDispatchStartTarget);
 
   /**
    * Notification that the page has been hidden, for documents which are loaded
    * into a DOM window.  This corresponds to the unloading of the document, or
    * to the document's presentation being saved but removed from an existing
    * DOM window.  This notification fires applicable DOM events to the content
    * window.  See PageTransitionEvent.webidl for a description of the
    * |aPersisted| parameter. If aDispatchStartTarget is null, the pagehide
    * event is dispatched on the ScriptGlobalObject for this document,
    * otherwise it's dispatched on aDispatchStartTarget.
    * Note: if aDispatchStartTarget isn't null, the showing state of the
    * document won't be altered.
    */
-  virtual void OnPageHide(bool aPersisted,
-                          mozilla::dom::EventTarget* aDispatchStartTarget) = 0;
+  void OnPageHide(bool aPersisted,
+                  mozilla::dom::EventTarget* aDispatchStartTarget);
 
   /*
    * We record the set of links in the document that are relevant to
    * style.
    */
   /**
    * Notification that an element is a link that is relevant to style.
    */
-  virtual void AddStyleRelevantLink(mozilla::dom::Link* aLink) = 0;
+  void AddStyleRelevantLink(mozilla::dom::Link* aLink)
+  {
+    NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
+#ifdef DEBUG
+    nsPtrHashKey<mozilla::dom::Link>* entry = mStyledLinks.GetEntry(aLink);
+    NS_ASSERTION(!entry, "Document already knows about this Link!");
+    mStyledLinksCleared = false;
+#endif
+    mStyledLinks.PutEntry(aLink);
+  }
+
   /**
    * Notification that an element is a link and its URI might have been
    * changed or the element removed. If the element is still a link relevant
    * to style, then someone must ensure that AddStyleRelevantLink is
    * (eventually) called on it again.
    */
-  virtual void ForgetLink(mozilla::dom::Link* aLink) = 0;
+  void ForgetLink(mozilla::dom::Link* aLink)
+  {
+    NS_ASSERTION(aLink, "Passing in a null link.  Expect crashes RSN!");
+#ifdef DEBUG
+    nsPtrHashKey<mozilla::dom::Link>* entry = mStyledLinks.GetEntry(aLink);
+    NS_ASSERTION(entry || mStyledLinksCleared,
+                 "Document knows nothing about this Link!");
+#endif
+    mStyledLinks.RemoveEntry(aLink);
+  }
+
+  // Refreshes the hrefs of all the links in the document.
+  void RefreshLinkHrefs();
 
   /**
    * Resets and removes a box object from the document's box object cache
    *
    * @param aElement canonical nsIContent pointer of the box object's element
    */
-  virtual void ClearBoxObjectFor(nsIContent *aContent) = 0;
+  void ClearBoxObjectFor(nsIContent* aContent);
 
   /**
    * Get the box object for an element. This is not exposed through a
    * scriptable interface except for XUL documents.
    */
-  virtual already_AddRefed<mozilla::dom::BoxObject>
-    GetBoxObjectFor(mozilla::dom::Element* aElement,
-                    mozilla::ErrorResult& aRv) = 0;
+  already_AddRefed<mozilla::dom::BoxObject>
+    GetBoxObjectFor(mozilla::dom::Element* aElement, mozilla::ErrorResult& aRv);
 
   /**
    * Support for window.matchMedia()
    */
 
   already_AddRefed<mozilla::dom::MediaQueryList>
     MatchMedia(const nsAString& aMediaQueryList,
                mozilla::dom::CallerType aCallerType);
@@ -2105,36 +2450,36 @@ public:
   nsCompatibility GetCompatibilityMode() const {
     return mCompatMode;
   }
 
   /**
    * Check whether we've ever fired a DOMTitleChanged event for this
    * document.
    */
-  bool HaveFiredDOMTitleChange() const {
+  bool HaveFiredDOMTitleChange() const
+  {
     return mHaveFiredTitleChange;
   }
 
-  virtual Element*
-    GetAnonymousElementByAttribute(nsIContent* aElement,
-                                   nsAtom* aAttrName,
-                                   const nsAString& aAttrValue) const = 0;
-
-  virtual nsresult NodesFromRectHelper(float aX, float aY,
-                                       float aTopSize, float aRightSize,
-                                       float aBottomSize, float aLeftSize,
-                                       bool aIgnoreRootScrollFrame,
-                                       bool aFlushLayout,
-                                       nsIDOMNodeList** aReturn) = 0;
+  Element* GetAnonymousElementByAttribute(nsIContent* aElement,
+                                          nsAtom* aAttrName,
+                                          const nsAString& aAttrValue) const;
+
+  nsresult NodesFromRectHelper(float aX, float aY,
+                               float aTopSize, float aRightSize,
+                               float aBottomSize, float aLeftSize,
+                               bool aIgnoreRootScrollFrame,
+                               bool aFlushLayout,
+                               nsIDOMNodeList** aReturn);
 
   /**
    * See FlushSkinBindings on nsBindingManager
    */
-  virtual void FlushSkinBindings() = 0;
+  void FlushSkinBindings();
 
   /**
    * To batch DOMSubtreeModified, document needs to be informed when
    * a mutation event might be dispatched, even if the event isn't actually
    * created because there are no listeners for it.
    *
    * @param aTarget is the target for the mutation event.
    */
@@ -2207,22 +2552,22 @@ public:
 
   virtual void SetMayStartLayout(bool aMayStartLayout);
 
   already_AddRefed<nsIDocumentEncoder> GetCachedEncoder();
 
   void SetCachedEncoder(already_AddRefed<nsIDocumentEncoder> aEncoder);
 
   // In case of failure, the document really can't initialize the frame loader.
-  virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) = 0;
+  nsresult InitializeFrameLoader(nsFrameLoader* aLoader);
   // In case of failure, the caller must handle the error, for example by
   // finalizing frame loader asynchronously.
-  virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer) = 0;
+  nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer);
   // Removes the frame loader of aShell from the initialization list.
-  virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
+  void TryCancelFrameLoaderInitialization(nsIDocShell* aShell);
 
   /**
    * Check whether this document is a root document that is not an
    * external resource.
    */
   bool IsRootDisplayDocument() const
   {
     return !mParentDocument && !mDisplayDocument;
@@ -2277,67 +2622,43 @@ public:
     MOZ_ASSERT(aDisplayDocument != this, "Should be different document");
     MOZ_ASSERT(!aDisplayDocument->GetDisplayDocument(),
                "Display documents should not nest");
     mDisplayDocument = aDisplayDocument;
     mHasDisplayDocument = !!aDisplayDocument;
   }
 
   /**
-   * A class that represents an external resource load that has begun but
-   * doesn't have a document yet.  Observers can be registered on this object,
-   * and will be notified after the document is created.  Observers registered
-   * after the document has been created will NOT be notified.  When observers
-   * are notified, the subject will be the newly-created document, the topic
-   * will be "external-resource-document-created", and the data will be null.
-   * If document creation fails for some reason, observers will still be
-   * notified, with a null document pointer.
-   */
-  class ExternalResourceLoad : public nsISupports
-  {
-  public:
-    virtual ~ExternalResourceLoad() {}
-
-    void AddObserver(nsIObserver* aObserver) {
-      MOZ_ASSERT(aObserver, "Must have observer");
-      mObservers.AppendElement(aObserver);
-    }
-
-    const nsTArray< nsCOMPtr<nsIObserver> > & Observers() {
-      return mObservers;
-    }
-  protected:
-    AutoTArray< nsCOMPtr<nsIObserver>, 8 > mObservers;
-  };
-
-  /**
    * Request an external resource document for aURI.  This will return the
    * resource document if available.  If one is not available yet, it will
    * start loading as needed, and the pending load object will be returned in
    * aPendingLoad so that the caller can register an observer to wait for the
    * load.  If this function returns null and doesn't return a pending load,
    * that means that there is no resource document for this URI and won't be
    * one in the future.
    *
    * @param aURI the URI to get
    * @param aRequestingNode the node making the request
    * @param aPendingLoad the pending load for this request, if any
    */
-  virtual nsIDocument*
-    RequestExternalResource(nsIURI* aURI,
-                            nsINode* aRequestingNode,
-                            ExternalResourceLoad** aPendingLoad) = 0;
+  nsIDocument* RequestExternalResource(nsIURI* aURI,
+                                       nsINode* aRequestingNode,
+                                       ExternalResourceLoad** aPendingLoad);
 
   /**
    * Enumerate the external resource documents associated with this document.
    * The enumerator callback should return true to continue enumerating, or
    * false to stop.  This callback will never get passed a null aDocument.
    */
-  virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
-                                          void* aData) = 0;
+  void EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData);
+
+  nsExternalResourceMap& ExternalResourceMap()
+  {
+    return mExternalResourceMap;
+  }
 
   /**
    * Return whether the document is currently showing (in the sense of
    * OnPageShow() having been called already and OnPageHide() not having been
    * called yet.
    */
   bool IsShowing() const { return mIsShowing; }
   /**
@@ -2399,49 +2720,60 @@ public:
   // Indicates whether mAnimationController has been (lazily) initialized.
   // If this returns true, we're promising that GetAnimationController()
   // will have a non-null return value.
   bool HasAnimationController()  { return !!mAnimationController; }
 
   // Getter for this document's SMIL Animation Controller. Performs lazy
   // initialization, if this document supports animation and if
   // mAnimationController isn't yet initialized.
-  virtual nsSMILAnimationController* GetAnimationController() = 0;
+  //
+  // If HasAnimationController is true, this is guaranteed to return non-null.
+  nsSMILAnimationController* GetAnimationController();
 
   // Gets the tracker for animations that are waiting to start.
   // Returns nullptr if there is no pending animation tracker for this document
   // which will be the case if there have never been any CSS animations or
   // transitions on elements in the document.
-  virtual mozilla::PendingAnimationTracker* GetPendingAnimationTracker() = 0;
+  mozilla::PendingAnimationTracker* GetPendingAnimationTracker()
+  {
+    return mPendingAnimationTracker;
+  }
 
   // Gets the tracker for animations that are waiting to start and
   // creates it if it doesn't already exist. As a result, the return value
   // will never be nullptr.
-  virtual mozilla::PendingAnimationTracker*
-  GetOrCreatePendingAnimationTracker() = 0;
+  mozilla::PendingAnimationTracker* GetOrCreatePendingAnimationTracker();
 
   /**
    * Prevents user initiated events from being dispatched to the document and
    * subdocuments.
    */
-  virtual void SuppressEventHandling(uint32_t aIncrease = 1) = 0;
+  void SuppressEventHandling(uint32_t aIncrease = 1);
 
   /**
    * Unsuppress event handling.
    * @param aFireEvents If true, delayed events (focus/blur) will be fired
    *                    asynchronously.
    */
-  virtual void UnsuppressEventHandlingAndFireEvents(bool aFireEvents) = 0;
+  void UnsuppressEventHandlingAndFireEvents(bool aFireEvents);
 
   uint32_t EventHandlingSuppressed() const { return mEventsSuppressed; }
 
   bool IsEventHandlingEnabled() {
     return !EventHandlingSuppressed() && mScriptGlobalObject;
   }
 
+  void DecreaseEventSuppression()
+  {
+    MOZ_ASSERT(mEventsSuppressed);
+    --mEventsSuppressed;
+    UpdateFrameRequestCallbackSchedulingState();
+  }
+
   /**
    * Increment https://html.spec.whatwg.org/#ignore-destructive-writes-counter
    */
   void IncrementIgnoreDestructiveWritesCounter() { ++mIgnoreDestructiveWritesCounter; }
 
   /**
    * Decrement https://html.spec.whatwg.org/#ignore-destructive-writes-counter
    */
@@ -2462,17 +2794,17 @@ public:
   void ForceEnableXULXBL() {
     mAllowXULXBL = eTriTrue;
   }
 
   /**
    * Returns the template content owner document that owns the content of
    * HTMLTemplateElement.
    */
-  virtual nsIDocument* GetTemplateContentsOwner() = 0;
+  nsIDocument* GetTemplateContentsOwner();
 
   /**
    * Returns true if this document is a static clone of a normal document.
    *
    * We create static clones for print preview and printing (possibly other
    * things in future).
    *
    * Note that static documents are also "loaded as data" (if this method
@@ -2517,58 +2849,61 @@ public:
    * expected to be marked void.
    *
    * NOTE that the parser does not attempt to track the current picture nesting
    * level or whether the given <source> tag is within a picture -- it is only
    * guaranteed to order these calls properly with respect to
    * ResolvePreLoadImage.
    */
 
-  virtual void PreloadPictureOpened() = 0;
-
-  virtual void PreloadPictureClosed() = 0;
-
-  virtual void PreloadPictureImageSource(const nsAString& aSrcsetAttr,
-                                         const nsAString& aSizesAttr,
-                                         const nsAString& aTypeAttr,
-                                         const nsAString& aMediaAttr) = 0;
+  void PreloadPictureOpened()
+  {
+    mPreloadPictureDepth++;
+  }
+
+  void PreloadPictureClosed();
+
+  void PreloadPictureImageSource(const nsAString& aSrcsetAttr,
+                                 const nsAString& aSizesAttr,
+                                 const nsAString& aTypeAttr,
+                                 const nsAString& aMediaAttr);
 
   /**
    * Called by the parser to resolve an image for preloading. The parser will
    * call the PreloadPicture* functions to inform us of possible <picture>
    * nesting and possible sources, which are used to inform URL selection
    * responsive <picture> or <img srcset> images.  Unset attributes are expected
    * to be marked void.
    * If this image is for <picture> or <img srcset>, aIsImgSet will be set to
    * true, false otherwise.
    */
-  virtual already_AddRefed<nsIURI>
-    ResolvePreloadImage(nsIURI *aBaseURI,
-                        const nsAString& aSrcAttr,
-                        const nsAString& aSrcsetAttr,
-                        const nsAString& aSizesAttr,
-                        bool *aIsImgSet) = 0;
+  already_AddRefed<nsIURI>
+  ResolvePreloadImage(nsIURI *aBaseURI,
+                      const nsAString& aSrcAttr,
+                      const nsAString& aSrcsetAttr,
+                      const nsAString& aSizesAttr,
+                      bool *aIsImgSet);
   /**
    * Called by nsParser to preload images. Can be removed and code moved
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.  aCrossOriginAttr should
    * be a void string if the attr is not present.
    * aIsImgSet is the value got from calling ResolvePreloadImage, it is true
    * when this image is for loading <picture> or <img srcset> images.
    */
-  virtual void MaybePreLoadImage(nsIURI* uri,
-                                 const nsAString& aCrossOriginAttr,
-                                 ReferrerPolicyEnum aReferrerPolicy,
-                                 bool aIsImgSet) = 0;
+  void MaybePreLoadImage(nsIURI* uri,
+                         const nsAString& aCrossOriginAttr,
+                         ReferrerPolicyEnum aReferrerPolicy,
+                         bool aIsImgSet);
 
   /**
    * Called by images to forget an image preload when they start doing
    * the real load.
    */
-  virtual void ForgetImagePreload(nsIURI* aURI) = 0;
+  void ForgetImagePreload(nsIURI* aURI);
 
   /**
    * Called by nsParser to preload style sheets.  Can also be merged into the
    * parser if and when the parser is merged with libgklayout.  aCrossOriginAttr
    * should be a void string if the attr is not present.
    */
   void PreloadStyle(nsIURI* aURI,
                     const mozilla::Encoding* aEncoding,
@@ -2594,17 +2929,17 @@ public:
    * so once can know whether a document is expected to be rendered left-to-right
    * or right-to-left.
    */
   virtual bool IsDocumentRightToLeft() { return false; }
 
   /**
    * Called by Parser for link rel=preconnect
    */
-  virtual void MaybePreconnect(nsIURI* uri, mozilla::CORSMode aCORSMode) = 0;
+  void MaybePreconnect(nsIURI* uri, mozilla::CORSMode aCORSMode);
 
   enum DocumentTheme {
     Doc_Theme_Uninitialized, // not determined yet
     Doc_Theme_None,
     Doc_Theme_Neutral,
     Doc_Theme_Dark,
     Doc_Theme_Bright
   };
@@ -2629,45 +2964,54 @@ public:
    * Document state bits have the form NS_DOCUMENT_STATE_* and are declared in
    * nsIDocument.h.
    */
   mozilla::EventStates GetDocumentState() const
   {
     return mDocumentState;
   }
 
-  virtual nsISupports* GetCurrentContentSink() = 0;
-
-  virtual void SetAutoFocusElement(Element* aAutoFocusElement) = 0;
-  virtual void TriggerAutoFocus() = 0;
-
-  virtual void SetScrollToRef(nsIURI *aDocumentURI) = 0;
-  virtual void ScrollToRef() = 0;
-  virtual void ResetScrolledToRefAlready() = 0;
-  virtual void SetChangeScrollPosWhenScrollingToRef(bool aValue) = 0;
+  nsISupports* GetCurrentContentSink();
+
+  void SetAutoFocusElement(Element* aAutoFocusElement);
+  void TriggerAutoFocus();
+
+  void SetScrollToRef(nsIURI* aDocumentURI);
+  void ScrollToRef();
+  void ResetScrolledToRefAlready()
+  {
+    mScrolledToRefAlready = false;
+  }
+
+  void SetChangeScrollPosWhenScrollingToRef(bool aValue)
+  {
+    mChangeScrollPosWhenScrollingToRef = aValue;
+  }
 
   using mozilla::dom::DocumentOrShadowRoot::GetElementById;
   using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
   using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS;
   using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName;
 
   /**
    * Lookup an image element using its associated ID, which is usually provided
    * by |-moz-element()|. Similar to GetElementById, with the difference that
    * elements set using mozSetImageElement have higher priority.
    * @param aId the ID associated the element we want to lookup
    * @return the element associated with |aId|
    */
-  virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
-
-  virtual mozilla::dom::DocumentTimeline* Timeline() = 0;
-  virtual mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() = 0;
-
-  virtual void GetAnimations(
-      nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) = 0;
+  Element* LookupImageElement(const nsAString& aElementId);
+
+  mozilla::dom::DocumentTimeline* Timeline();
+  mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines()
+  {
+    return mTimelines;
+  }
+
+  void GetAnimations(nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations);
 
   mozilla::dom::SVGSVGElement* GetSVGRootElement() const;
 
   nsresult ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
                                         int32_t *aHandle);
   void CancelFrameRequestCallback(int32_t aHandle);
 
   typedef nsTArray<RefPtr<mozilla::dom::FrameRequestCallback>> FrameRequestCallbackList;
@@ -2684,31 +3028,66 @@ public:
    */
   bool ShouldThrottleFrameRequests();
 
   // This returns true when the document tree is being teared down.
   bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
 
   mozilla::dom::ImageTracker* ImageTracker();
 
-  virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) = 0;
-  virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) = 0;
-  virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins) = 0;
-
-  virtual nsresult AddResponsiveContent(nsIContent* aContent) = 0;
-  virtual void RemoveResponsiveContent(nsIContent* aContent) = 0;
-  virtual void NotifyMediaFeatureValuesChanged() = 0;
-
-  virtual nsresult GetStateObject(nsIVariant** aResult) = 0;
-
-  virtual nsDOMNavigationTiming* GetNavigationTiming() const = 0;
-
-  virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
-
-  virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
+  // AddPlugin adds a plugin-related element to mPlugins when the element is
+  // added to the tree.
+  void AddPlugin(nsIObjectLoadingContent* aPlugin)
+  {
+    MOZ_ASSERT(aPlugin);
+    mPlugins.PutEntry(aPlugin);
+  }
+
+  // RemovePlugin removes a plugin-related element to mPlugins when the
+  // element is removed from the tree.
+  void RemovePlugin(nsIObjectLoadingContent* aPlugin)
+  {
+    MOZ_ASSERT(aPlugin);
+    mPlugins.RemoveEntry(aPlugin);
+  }
+
+  // GetPlugins returns the plugin-related elements from
+  // the frame and any subframes.
+  void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins);
+
+  // Adds an element to mResponsiveContent when the element is
+  // added to the tree.
+  void AddResponsiveContent(mozilla::dom::HTMLImageElement* aContent)
+  {
+    MOZ_ASSERT(aContent);
+    mResponsiveContent.PutEntry(aContent);
+  }
+
+  // Removes an element from mResponsiveContent when the element is
+  // removed from the tree.
+  void RemoveResponsiveContent(mozilla::dom::HTMLImageElement* aContent)
+  {
+    MOZ_ASSERT(aContent);
+    mResponsiveContent.RemoveEntry(aContent);
+  }
+
+  // Notifies any responsive content added by AddResponsiveContent upon media
+  // features values changing.
+  void NotifyMediaFeatureValuesChanged();
+
+  nsresult GetStateObject(nsIVariant** aResult);
+
+  nsDOMNavigationTiming* GetNavigationTiming() const
+  {
+    return mTiming;
+  }
+
+  void SetNavigationTiming(nsDOMNavigationTiming* aTiming);
+
+  Element* FindImageMap(const nsAString& aNormalizedMapName);
 
   // Add aLink to the set of links that need their status resolved.
   void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
 
   // Update state on links in mLinksToUpdate.  This function must be called
   // prior to selector matching that needs to differentiate between :link and
   // :visited.  In particular, it does _not_ need to be called before doing any
   // selector matching that uses TreeMatchContext::eNeverMatchVisited.  The only
@@ -2743,17 +3122,18 @@ public:
   };
 #undef DOCUMENT_WARNING
   bool HasWarnedAbout(DocumentWarnings aWarning) const;
   void WarnOnceAbout(DocumentWarnings aWarning,
                      bool asError = false,
                      const char16_t **aParams = nullptr,
                      uint32_t aParamsLength = 0) const;
 
-  virtual void PostVisibilityUpdateEvent() = 0;
+  // Posts an event to call UpdateVisibilityState
+  void PostVisibilityUpdateEvent();
 
   bool IsSyntheticDocument() const { return mIsSyntheticDocument; }
 
   // Note: nsIDocument is a sub-class of nsINode, which has a
   // SizeOfExcludingThis function.  However, because nsIDocument objects can
   // only appear at the top of the DOM tree, we have a specialized measurement
   // function which returns multiple sizes.
   virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const;
@@ -2810,18 +3190,17 @@ public:
   // WebIDL API
   nsIGlobalObject* GetParentObject() const
   {
     return GetScopeObject();
   }
   static already_AddRefed<nsIDocument>
     Constructor(const GlobalObject& aGlobal,
                 mozilla::ErrorResult& rv);
-  virtual mozilla::dom::DOMImplementation*
-    GetImplementation(mozilla::ErrorResult& rv) = 0;
+  mozilla::dom::DOMImplementation* GetImplementation(mozilla::ErrorResult& rv);
   MOZ_MUST_USE nsresult GetURL(nsString& retval) const;
   MOZ_MUST_USE nsresult GetDocumentURI(nsString& retval) const;
   // Return the URI for the document.
   // The returned value may differ if the document is loaded via XHR, and
   // when accessed from chrome privileged script and
   // from content privileged script for compatibility.
   void GetDocumentURIFromJS(nsString& aDocumentURI,
                             mozilla::dom::CallerType aCallerType,
@@ -2839,25 +3218,25 @@ public:
     eConnected,
     eDisconnected,
     eAdopted,
     eAttributeChanged
   };
 
   nsIDocument* GetTopLevelContentDocument();
 
-  virtual already_AddRefed<Element>
-    CreateElement(const nsAString& aTagName,
+  already_AddRefed<Element>
+  CreateElement(const nsAString& aTagName,
+                const mozilla::dom::ElementCreationOptionsOrString& aOptions,
+                mozilla::ErrorResult& rv);
+  already_AddRefed<Element>
+  CreateElementNS(const nsAString& aNamespaceURI,
+                  const nsAString& aQualifiedName,
                   const mozilla::dom::ElementCreationOptionsOrString& aOptions,
-                  mozilla::ErrorResult& rv) = 0;
-  virtual already_AddRefed<Element>
-    CreateElementNS(const nsAString& aNamespaceURI,
-                    const nsAString& aQualifiedName,
-                    const mozilla::dom::ElementCreationOptionsOrString& aOptions,
-                    mozilla::ErrorResult& rv) = 0;
+                  mozilla::ErrorResult& rv);
   already_AddRefed<mozilla::dom::DocumentFragment>
     CreateDocumentFragment() const;
   already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData) const;
   already_AddRefed<nsTextNode> CreateEmptyTextNode() const;
   already_AddRefed<mozilla::dom::Comment>
     CreateComment(const nsAString& aData) const;
   already_AddRefed<mozilla::dom::ProcessingInstruction>
     CreateProcessingInstruction(const nsAString& target, const nsAString& data,
@@ -2892,18 +3271,18 @@ public:
   already_AddRefed<mozilla::dom::Location> GetLocation() const;
   void GetReferrer(nsAString& aReferrer) const;
   void GetLastModified(nsAString& aLastModified) const;
   void GetReadyState(nsAString& aReadyState) const;
 
   already_AddRefed<mozilla::dom::AboutCapabilities> GetAboutCapabilities(
     ErrorResult& aRv);
 
-  virtual void GetTitle(nsAString& aTitle) = 0;
-  virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) = 0;
+  void GetTitle(nsAString& aTitle);
+  void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv);
   void GetDir(nsAString& aDirection) const;
   void SetDir(const nsAString& aDirection);
   already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName)
   {
     return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
                                                                       MatchNameAttribute,
                                                                       nullptr,
                                                                       UseExistingNameString,
@@ -2919,22 +3298,21 @@ public:
   void SetLastFocusTime(const mozilla::TimeStamp& aFocusTime);
   // Event handlers are all on nsINode already
   bool MozSyntheticDocument() const
   {
     return IsSyntheticDocument();
   }
   Element* GetCurrentScript();
   void ReleaseCapture() const;
-  virtual void MozSetImageElement(const nsAString& aImageElementId,
-                                  Element* aElement) = 0;
+  void MozSetImageElement(const nsAString& aImageElementId, Element* aElement);
   nsIURI* GetDocumentURIObject() const;
   // Not const because all the full-screen goop is not const
-  virtual bool FullscreenEnabled(mozilla::dom::CallerType aCallerType) = 0;
-  virtual Element* FullScreenStackTop() = 0;
+  bool FullscreenEnabled(mozilla::dom::CallerType aCallerType);
+  Element* FullScreenStackTop();
   bool Fullscreen()
   {
     return !!GetFullscreenElement();
   }
   void ExitFullscreen();
   void ExitPointerLock()
   {
     UnlockPointer(this);
@@ -3110,46 +3488,57 @@ public:
   void ReportHasScrollLinkedEffect();
   bool HasScrollLinkedEffect() const
   {
     return mHasScrollLinkedEffect;
   }
 
   mozilla::dom::DocGroup* GetDocGroup() const;
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-
-  virtual void UpdateIntersectionObservations() = 0;
-  virtual void ScheduleIntersectionObserverNotification() = 0;
-  virtual void NotifyIntersectionObservers() = 0;
-  virtual bool HasIntersectionObservers() const = 0;
+  void AddIntersectionObserver(mozilla::dom::DOMIntersectionObserver* aObserver)
+  {
+    MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
+               "Intersection observer already in the list");
+    mIntersectionObservers.PutEntry(aObserver);
+  }
+
+  void RemoveIntersectionObserver(mozilla::dom::DOMIntersectionObserver* aObserver)
+  {
+    mIntersectionObservers.RemoveEntry(aObserver);
+  }
+
+  bool HasIntersectionObservers() const
+  {
+    return !mIntersectionObservers.IsEmpty();
+  }
+
+  void UpdateIntersectionObservations();
+  void ScheduleIntersectionObserverNotification();
+  void NotifyIntersectionObservers();
 
   // Dispatch a runnable related to the document.
-  virtual nsresult Dispatch(mozilla::TaskCategory aCategory,
-                            already_AddRefed<nsIRunnable>&& aRunnable) override;
+  nsresult Dispatch(mozilla::TaskCategory aCategory,
+                    already_AddRefed<nsIRunnable>&& aRunnable) final;
 
   virtual nsISerialEventTarget*
   EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
   virtual mozilla::AbstractThread*
   AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
 
   // The URLs passed to these functions should match what
   // JS::DescribeScriptedCaller() returns, since these APIs are used to
   // determine whether some code is being called from a tracking script.
   void NoteScriptTrackingStatus(const nsACString& aURL, bool isTracking);
   bool IsScriptTracking(const nsACString& aURL) const;
 
   // For more information on Flash classification, see
   // toolkit/components/url-classifier/flash-block-lists.rst
-  virtual mozilla::dom::FlashClassification DocumentFlashClassification() = 0;
-  virtual bool IsThirdParty() = 0;
+  mozilla::dom::FlashClassification DocumentFlashClassification();
+  bool IsThirdParty();
 
   bool IsScopedStyleEnabled();
 
   nsINode* GetServoRestyleRoot() const
   {
     return mServoRestyleRoot;
   }
 
@@ -3196,18 +3585,25 @@ public:
   }
 
   void DecrementIgnoreOpensDuringUnloadCounter()
   {
     MOZ_ASSERT(mIgnoreOpensDuringUnloadCounter);
     --mIgnoreOpensDuringUnloadCounter;
   }
 
-  virtual bool AllowPaymentRequest() const = 0;
-  virtual void SetAllowPaymentRequest(bool aAllowPaymentRequest) = 0;
+  bool AllowPaymentRequest() const
+  {
+    return mAllowPaymentRequest;
+  }
+
+  void SetAllowPaymentRequest(bool aAllowPaymentRequest)
+  {
+    mAllowPaymentRequest = aAllowPaymentRequest;
+  }
 
   bool IsShadowDOMEnabled() const
   {
     return mIsShadowDOMEnabled;
   }
 
   bool ModuleScriptsEnabled();
 
@@ -3217,16 +3613,57 @@ public:
    * anonymous. Otherwise, when aFrame is in a subdocument, we use the frame
    * element containing the subdocument containing aFrame, and/or find the
    * nearest non-anonymous ancestor in this document.
    * Returns null if there is no such element.
    */
   nsIContent* GetContentInThisDocument(nsIFrame* aFrame) const;
 
 protected:
+
+  bool ContainsEMEContent();
+  bool ContainsMSEContent();
+
+  void MaybeInitializeFinalizeFrameLoaders();
+
+  /**
+   * Returns the title element of the document as defined by the HTML
+   * specification, or null if there isn't one.  For documents whose root
+   * element is an <svg:svg>, this is the first <svg:title> element that's a
+   * child of the root.  For other documents, it's the first HTML title element
+   * in the document.
+   */
+  Element* GetTitleElement();
+
+  // Retrieves the classification of the Flash plugins in the document based on
+  // the classification lists.
+  mozilla::dom::FlashClassification PrincipalFlashClassification();
+
+  // Attempts to determine the Flash classification of this page based on the
+  // the classification lists and the classification of parent documents.
+  mozilla::dom::FlashClassification ComputeFlashClassification();
+
+  void RecordNavigationTiming(ReadyState aReadyState);
+
+  // This method may fire a DOM event; if it does so it will happen
+  // synchronously.
+  void UpdateVisibilityState();
+
+  // Recomputes the visibility state but doesn't set the new value.
+  mozilla::dom::VisibilityState ComputeVisibilityState() const;
+
+  // Since we wouldn't automatically play media from non-visited page, we need
+  // to notify window when the page was first visited.
+  void MaybeActiveMediaComponents();
+
+  // Apply the fullscreen state to the document, and trigger related
+  // events. It returns false if the fullscreen element ready check
+  // fails and nothing gets changed.
+  bool ApplyFullscreen(const FullscreenRequest& aRequest);
+
   bool GetUseCounter(mozilla::UseCounter aUseCounter)
   {
     return mUseCounters[aUseCounter];
   }
 
   void SetChildDocumentUseCounter(mozilla::UseCounter aUseCounter)
   {
     if (!mChildDocumentUseCounters[aUseCounter]) {
@@ -3285,31 +3722,31 @@ protected:
       NS_RELEASE_THIS();
     }
   }
 
   ~nsIDocument();
   nsPropertyTable* GetExtraPropertyTable(uint16_t aCategory);
 
   // Never ever call this. Only call GetWindow!
-  virtual nsPIDOMWindowOuter* GetWindowInternal() const = 0;
+  nsPIDOMWindowOuter* GetWindowInternal() const;
 
   // Never ever call this. Only call GetScriptHandlingObject!
-  virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const = 0;
+  nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const;
 
   // Never ever call this. Only call AllowXULXBL!
-  virtual bool InternalAllowXULXBL() = 0;
+  bool InternalAllowXULXBL();
 
   /**
    * These methods should be called before and after dispatching
    * a mutation event.
    * To make this easy and painless, use the mozAutoSubtreeModified helper class.
    */
-  virtual void WillDispatchMutationEvent(nsINode* aTarget) = 0;
-  virtual void MutationEventDispatched(nsINode* aTarget) = 0;
+  void WillDispatchMutationEvent(nsINode* aTarget);
+  void MutationEventDispatched(nsINode* aTarget);
   friend class mozAutoSubtreeModified;
 
   virtual Element* GetNameSpaceElement() override
   {
     return GetRootElement();
   }
 
   void SetContentTypeInternal(const nsACString& aType);
@@ -3399,16 +3836,25 @@ protected:
   // The set of all object, embed, video/audio elements or
   // nsIObjectLoadingContent or nsIDocumentActivity for which this is the owner
   // document. (They might not be in the document.)
   //
   // These are non-owning pointers, the elements are responsible for removing
   // themselves when they go away.
   nsAutoPtr<nsTHashtable<nsPtrHashKey<nsISupports> > > mActivityObservers;
 
+  // A hashtable of styled links keyed by address pointer.
+  nsTHashtable<nsPtrHashKey<mozilla::dom::Link>> mStyledLinks;
+#ifdef DEBUG
+  // Indicates whether mStyledLinks was cleared or not.  This is used to track
+  // state so we can provide useful assertions to consumers of ForgetLink and
+  // AddStyleRelevantLink.
+  bool mStyledLinksCleared;
+#endif
+
   // The array of all links that need their status resolved.  Links must add themselves
   // to this set by calling RegisterPendingLinkUpdate when added to a document.
   static const size_t kSegmentSize = 128;
 
   typedef mozilla::SegmentedVector<nsCOMPtr<mozilla::dom::Link>,
                                    kSegmentSize,
                                    InfallibleAllocPolicy>
     LinksToUpdateList;
@@ -3632,20 +4078,44 @@ protected:
   // Whether we have filled our pres shell's style set with the document's
   // additional sheets and sheets from the nsStyleSheetService.
   bool mStyleSetFilled: 1;
 
   // Keeps track of whether we have a pending
   // 'style-sheet-applicable-state-changed' notification.
   bool mSSApplicableStateNotificationPending: 1;
 
+  // True if this document has ever had an HTML or SVG <title> element
+  // bound to it
+  bool mMayHaveTitleElement: 1;
+
+  bool mDOMLoadingSet: 1;
+  bool mDOMInteractiveSet: 1;
+  bool mDOMCompleteSet: 1;
+  bool mAutoFocusFired: 1;
+
+  bool mScrolledToRefAlready : 1;
+  bool mChangeScrollPosWhenScrollingToRef : 1;
+
+  bool mHasWarnedAboutBoxObjects: 1;
+
+  bool mDelayFrameLoaderInitialization: 1;
+
+  bool mSynchronousDOMContentLoaded: 1;
+
+  // Set to true when the document is possibly controlled by the ServiceWorker.
+  // Used to prevent multiple requests to ServiceWorkerManager.
+  bool mMaybeServiceWorkerControlled: 1;
+
   // Whether <style scoped> support is enabled in this document.
   enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
   unsigned int mIsScopedStyleEnabled : 2;
 
+  uint8_t mPendingFullscreenRequests;
+
   // Compatibility mode
   nsCompatibility mCompatMode;
 
   // Our readyState
   ReadyState mReadyState;
 
   // Whether this document has (or will have, once we have a pres shell) a
   // Gecko- or Servo-backed style system.
@@ -3720,17 +4190,34 @@ protected:
 
   // Cycle collector generation in which we're certain that this document
   // won't be collected
   uint32_t mMarkedCCGeneration;
 
   nsIPresShell* mPresShell;
 
   nsCOMArray<nsINode> mSubtreeModifiedTargets;
-  uint32_t            mSubtreeModifiedDepth;
+  uint32_t mSubtreeModifiedDepth;
+
+  // All images in process of being preloaded.  This is a hashtable so
+  // we can remove them as the real image loads start; that way we
+  // make sure to not keep the image load going when no one cares
+  // about it anymore.
+  nsRefPtrHashtable<nsURIHashKey, imgIRequest> mPreloadingImages;
+
+  // A list of preconnects initiated by the preloader. This prevents
+  // the same uri from being used more than once, and allows the dom
+  // builder to not repeat the work of the preloader.
+  nsDataHashtable<nsURIHashKey, bool> mPreloadedPreconnects;
+
+  // Current depth of picture elements from parser
+  uint32_t mPreloadPictureDepth;
+
+  // Set if we've found a URL for the current picture
+  nsString mPreloadPictureFoundSource;
 
   // If we're an external resource document, this will be non-null and will
   // point to our "display document": the one that all resource lookups should
   // go to.
   nsCOMPtr<nsIDocument> mDisplayDocument;
 
   uint32_t mEventsSuppressed;
 
@@ -3834,16 +4321,112 @@ protected:
   // Weak reference to our sink for in case we no longer have a parser.  This
   // will allow us to flush out any pending stuff from the sink even if
   // EndLoad() has already happened.
   nsWeakPtr mWeakSink;
 
   // Our update nesting level
   uint32_t mUpdateNestLevel;
 
+  enum ViewportType {
+    DisplayWidthHeight,
+    Specified,
+    Unknown
+  };
+
+  ViewportType mViewportType;
+
+  PLDHashTable* mSubDocuments;
+
+  nsDocHeaderData* mHeaderData;
+
+  RefPtr<PrincipalFlashClassifier> mPrincipalFlashClassifier;
+  mozilla::dom::FlashClassification mFlashClassification;
+  // Do not use this value directly. Call the |IsThirdParty()| method, which
+  // caches its result here.
+  mozilla::Maybe<bool> mIsThirdParty;
+
+  nsRevocableEventPtr<nsRunnableMethod<nsIDocument, void, false>>
+    mPendingTitleChangeEvent;
+
+  RefPtr<nsDOMNavigationTiming> mTiming;
+
+  // Recorded time of change to 'loading' state.
+  mozilla::TimeStamp mLoadingTimeStamp;
+
+  nsWeakPtr mAutoFocusElement;
+
+  nsCString mScrollToRef;
+
+  // Weak reference to the scope object (aka the script global object)
+  // that, unlike mScriptGlobalObject, is never unset once set. This
+  // is a weak reference to avoid leaks due to circular references.
+  nsWeakPtr mScopeObject;
+
+  // Array of intersection observers
+  nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
+    mIntersectionObservers;
+
+  // Stack of full-screen elements. When we request full-screen we push the
+  // full-screen element onto this stack, and when we cancel full-screen we
+  // pop one off this stack, restoring the previous full-screen state
+  nsTArray<nsWeakPtr> mFullScreenStack;
+
+  // The root of the doc tree in which this document is in. This is only
+  // non-null when this document is in fullscreen mode.
+  nsWeakPtr mFullscreenRoot;
+
+  RefPtr<mozilla::dom::DOMImplementation> mDOMImplementation;
+
+  RefPtr<nsContentList> mImageMaps;
+
+  // A set of responsive images keyed by address pointer.
+  nsTHashtable<nsPtrHashKey<mozilla::dom::HTMLImageElement>> mResponsiveContent;
+
+  // Tracking for plugins in the document.
+  nsTHashtable<nsPtrHashKey<nsIObjectLoadingContent>> mPlugins;
+
+  // Array of owning references to all children
+  nsAttrAndChildArray mChildren;
+
+  RefPtr<mozilla::dom::DocumentTimeline> mDocumentTimeline;
+  mozilla::LinkedList<mozilla::dom::DocumentTimeline> mTimelines;
+
+  RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
+
+  nsRefPtrHashtable<nsPtrHashKey<nsIContent>, mozilla::dom::BoxObject>*
+    mBoxObjectTable;
+
+  // Tracker for animations that are waiting to start.
+  // nullptr until GetOrCreatePendingAnimationTracker is called.
+  RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
+
+  // A document "without a browsing context" that owns the content of
+  // HTMLTemplateElement.
+  nsCOMPtr<nsIDocument> mTemplateContentsOwner;
+
+  nsExternalResourceMap mExternalResourceMap;
+
+  // ScreenOrientation "pending promise" as described by
+  // http://www.w3.org/TR/screen-orientation/
+  RefPtr<mozilla::dom::Promise> mOrientationPendingPromise;
+
+  uint16_t mCurrentOrientationAngle;
+  mozilla::dom::OrientationType mCurrentOrientationType;
+
+  nsTArray<RefPtr<nsFrameLoader>> mInitializableFrameLoaders;
+  nsTArray<nsCOMPtr<nsIRunnable>> mFrameLoaderFinalizers;
+  RefPtr<nsRunnableMethod<nsIDocument>> mFrameLoaderRunner;
+
+  // The layout history state that should be used by nodes in this
+  // document.  We only actually store a pointer to it when:
+  // 1)  We have no script global object.
+  // 2)  We haven't had Destroy() called on us yet.
+  nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
+
   nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets;
   nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
 
   // Member to store out last-selected stylesheet set.
   nsString mLastStyleSheetSet;
   RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
 
   // We lazily calculate declaration blocks for SVG elements with mapped
--- a/dom/base/nsNodeInfoManager.h
+++ b/dom/base/nsNodeInfoManager.h
@@ -130,17 +130,17 @@ public:
     return mMathMLEnabled == eTriTrue
              ? true
              : mMathMLEnabled == eTriFalse ? false : InternalMathMLEnabled();
   }
 
   void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
 
 protected:
-  friend class nsDocument;
+  friend class nsIDocument;
   friend class nsXULPrototypeDocument;
   friend nsresult NS_NewDOMDocumentType(nsIDOMDocumentType** ,
                                         nsNodeInfoManager *,
                                         nsAtom *,
                                         const nsAString& ,
                                         const nsAString& ,
                                         const nsAString& );
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -605,17 +605,17 @@ nsObjectLoadingContent::BindToTree(nsIDo
                                    nsIContent* aParent,
                                    nsIContent* aBindingParent,
                                    bool aCompileEventHandlers)
 {
   nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
                                     aCompileEventHandlers);
 
   if (aDocument) {
-    return aDocument->AddPlugin(this);
+    aDocument->AddPlugin(this);
   }
   return NS_OK;
 }
 
 void
 nsObjectLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
--- a/dom/browser-element/mochitest/chrome.ini
+++ b/dom/browser-element/mochitest/chrome.ini
@@ -31,17 +31,16 @@ support-files =
   file_illegal_web_manifest.html
 
 [test_browserElement_inproc_BackForward.html]
 [test_browserElement_inproc_BadScreenshot.html]
 [test_browserElement_inproc_DocumentFirstPaint.html]
 [test_browserElement_inproc_DOMRequestError.html]
 [test_browserElement_inproc_ExecuteScript.html]
 [test_browserElement_inproc_Find.html]
-fail-if = (os == 'win' && ccov) # Bug 1423667
 [test_browserElement_inproc_GetContentDimensions.html]
 [test_browserElement_inproc_GetScreenshot.html]
 [test_browserElement_inproc_GetScreenshotDppx.html]
 [test_browserElement_inproc_getWebManifest.html]
 [test_browserElement_inproc_NextPaint.html]
 [test_browserElement_inproc_PurgeHistory.html]
 [test_browserElement_inproc_ReloadPostRequest.html]
 disabled = no modal prompt on POST reload for chrome window
--- a/dom/credentialmanagement/tests/browser/browser_active_document.js
+++ b/dom/credentialmanagement/tests/browser/browser_active_document.js
@@ -80,16 +80,19 @@ add_task(async function test_background_
   await BrowserTestUtils.removeTab(tab_fg);
 });
 
 add_task(async function test_background_window() {
   // Open a tab, then a new window.
   let tab_bg = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
   let win = await BrowserTestUtils.openNewBrowserWindow();
 
+  // Wait until the new window is really focused.
+  await new Promise(resolve => SimpleTest.waitForFocus(resolve, win));
+
   // Requests from selected tabs not in the active window must fail.
   await promiseMakeCredential(tab_bg)
     .then(arrivingHereIsBad)
     .catch(expectNotAllowedError);
 
   // Requests from selected tabs not in the active window must fail.
   await promiseGetAssertion(tab_bg)
     .then(arrivingHereIsBad)
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -141,17 +141,17 @@ PluginDocument::SetScriptGlobalObject(ns
     BecomeInteractive();
   } else {
     mStreamListener = nullptr;
   }
 }
 
 
 bool
-PluginDocument::CanSavePresentation(nsIRequest *aNewRequest)
+PluginDocument::CanSavePresentation(nsIRequest* aNewRequest)
 {
   // Full-page plugins cannot be cached, currently, because we don't have
   // the stream listener data to feed to the plugin instance.
   return false;
 }
 
 
 nsresult
--- a/dom/media/webaudio/AudioNode.cpp
+++ b/dom/media/webaudio/AudioNode.cpp
@@ -86,17 +86,20 @@ AudioNode::Initialize(const AudioNodeOpt
   if (aOptions.mChannelCountMode.WasPassed()) {
     SetChannelCountModeValue(aOptions.mChannelCountMode.Value(), aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
   }
 
   if (aOptions.mChannelInterpretation.WasPassed()) {
-    SetChannelInterpretationValue(aOptions.mChannelInterpretation.Value());
+    SetChannelInterpretationValue(aOptions.mChannelInterpretation.Value(), aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
+    }
   }
 }
 
 size_t
 AudioNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   // Not owned:
   // - mContext
--- a/dom/media/webaudio/AudioNode.h
+++ b/dom/media/webaudio/AudioNode.h
@@ -147,17 +147,17 @@ public:
   {
     mChannelCountMode = aMode;
     SendChannelMixingParametersToStream();
   }
   ChannelInterpretation ChannelInterpretationValue() const
   {
     return mChannelInterpretation;
   }
-  void SetChannelInterpretationValue(ChannelInterpretation aMode)
+  virtual void SetChannelInterpretationValue(ChannelInterpretation aMode, ErrorResult& aRv)
   {
     mChannelInterpretation = aMode;
     SendChannelMixingParametersToStream();
   }
 
   struct InputNode final
   {
     ~InputNode()
--- a/dom/media/webaudio/ChannelSplitterNode.h
+++ b/dom/media/webaudio/ChannelSplitterNode.h
@@ -26,16 +26,29 @@ public:
 
   static already_AddRefed<ChannelSplitterNode>
   Constructor(const GlobalObject& aGlobal, AudioContext& aAudioContext,
               const ChannelSplitterOptions& aOptions, ErrorResult& aRv)
   {
     return Create(aAudioContext, aOptions, aRv);
   }
 
+  void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override
+  {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+  }
+  void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) override
+  {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+  }
+  void SetChannelInterpretationValue(ChannelInterpretation aMode, ErrorResult& aRv) override
+  {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+  }
+
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   uint16_t NumberOfOutputs() const override { return mOutputCount; }
 
   const char* NodeType() const override
   {
     return "ChannelSplitterNode";
   }
--- a/dom/webidl/AudioNode.webidl
+++ b/dom/webidl/AudioNode.webidl
@@ -53,16 +53,17 @@ interface AudioNode : EventTarget {
     readonly attribute unsigned long numberOfInputs;
     readonly attribute unsigned long numberOfOutputs;
 
     // Channel up-mixing and down-mixing rules for all inputs.
     [SetterThrows]
     attribute unsigned long channelCount;
     [SetterThrows]
     attribute ChannelCountMode channelCountMode;
+    [SetterThrows]
     attribute ChannelInterpretation channelInterpretation;
 
 };
 
 // Mozilla extension
 partial interface AudioNode {
   [ChromeOnly]
   readonly attribute unsigned long id;
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -68,19 +68,23 @@ enum class TextureFlags : uint32_t {
   COMPONENT_ALPHA    = 1 << 11,
   // The texture is being allocated for a compositor that no longer exists.
   // This flag is only used in the parent process.
   INVALID_COMPOSITOR = 1 << 12,
   // The texture was created by converting from YCBCR to RGB
   RGB_FROM_YCBCR     = 1 << 13,
   // The texture is used for snapshot.
   SNAPSHOT           = 1 << 14,
+  // Enable a non blocking read lock.
+  NON_BLOCKING_READ_LOCK = 1 << 15,
+  // Enable a blocking read lock.
+  BLOCKING_READ_LOCK = 1 << 16,
 
   // OR union of all valid bits
-  ALL_BITS           = (1 << 15) - 1,
+  ALL_BITS           = (1 << 17) - 1,
   // the default flags
   DEFAULT = NO_FLAGS
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextureFlags)
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
--- a/gfx/layers/PersistentBufferProvider.cpp
+++ b/gfx/layers/PersistentBufferProvider.cpp
@@ -101,17 +101,17 @@ PersistentBufferProviderShared::Create(g
 {
   if (!aKnowsCompositor || !aKnowsCompositor->GetTextureForwarder()->IPCOpen()) {
     return nullptr;
   }
 
   RefPtr<TextureClient> texture = TextureClient::CreateForDrawing(
     aKnowsCompositor, aFormat, aSize,
     BackendSelector::Canvas,
-    TextureFlags::DEFAULT,
+    TextureFlags::DEFAULT | TextureFlags::NON_BLOCKING_READ_LOCK,
     TextureAllocationFlags::ALLOC_DEFAULT
   );
 
   if (!texture) {
     return nullptr;
   }
 
   RefPtr<PersistentBufferProviderShared> provider =
@@ -185,17 +185,17 @@ PersistentBufferProviderShared::SetKnows
 
     // Get rid of everything else
     Destroy();
 
     if (prevTexture) {
       RefPtr<TextureClient> newTexture = TextureClient::CreateForDrawing(
         aKnowsCompositor, mFormat, mSize,
         BackendSelector::Canvas,
-        TextureFlags::DEFAULT,
+        TextureFlags::DEFAULT | TextureFlags::NON_BLOCKING_READ_LOCK,
         TextureAllocationFlags::ALLOC_DEFAULT
       );
 
       MOZ_ASSERT(newTexture);
       if (!newTexture) {
         return false;
       }
 
@@ -317,17 +317,17 @@ PersistentBufferProviderShared::BorrowDr
         // Give up now. The caller can fall-back to a non-shared buffer provider.
         return nullptr;
       }
     }
 
     RefPtr<TextureClient> newTexture = TextureClient::CreateForDrawing(
       mKnowsCompositor, mFormat, mSize,
       BackendSelector::Canvas,
-      TextureFlags::DEFAULT,
+      TextureFlags::DEFAULT | TextureFlags::NON_BLOCKING_READ_LOCK,
       TextureAllocationFlags::ALLOC_DEFAULT
     );
 
     MOZ_ASSERT(newTexture);
     if (newTexture) {
       if (mTextures.append(newTexture)) {
         tex = newTexture;
         mBack = Some<uint32_t>(mTextures.length() - 1);
@@ -378,19 +378,17 @@ PersistentBufferProviderShared::ReturnDr
 }
 
 TextureClient*
 PersistentBufferProviderShared::GetTextureClient()
 {
   // Can't access the front buffer while drawing.
   MOZ_ASSERT(!mDrawTarget);
   TextureClient* texture = GetTexture(mFront);
-  if (texture) {
-    texture->EnableReadLock();
-  } else {
+  if (!texture) {
     gfxCriticalNote << "PersistentBufferProviderShared: front buffer unavailable";
   }
   return texture;
 }
 
 already_AddRefed<gfx::SourceSurface>
 PersistentBufferProviderShared::BorrowSnapshot()
 {
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -106,23 +106,23 @@ CanvasClient2D::Update(gfx::IntSize aSiz
     gfxContentType contentType =
       aCanvasRenderer->IsOpaque() ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA;
     gfx::SurfaceFormat surfaceFormat
       = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
     TextureFlags flags = TextureFlags::DEFAULT;
     if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
       flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
     }
+    flags |= TextureFlags::NON_BLOCKING_READ_LOCK;
 
     mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aCanvasRenderer);
     if (!mBackBuffer) {
       NS_WARNING("Failed to allocate the TextureClient");
       return;
     }
-    mBackBuffer->EnableReadLock();
     MOZ_ASSERT(mBackBuffer->CanExposeDrawTarget());
 
     bufferCreated = true;
   }
 
   bool updated = false;
   {
     TextureClientAutoLock autoLock(mBackBuffer, OpenMode::OPEN_WRITE_ONLY);
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -745,24 +745,23 @@ ContentClientRemoteBuffer::CreateBufferI
 {
   TextureAllocationFlags textureAllocFlags
                          = (aFlags & TextureFlags::COMPONENT_ALPHA) ?
                             TextureAllocationFlags::ALLOC_CLEAR_BUFFER_BLACK :
                             TextureAllocationFlags::ALLOC_CLEAR_BUFFER;
 
   RefPtr<TextureClient> textureClient = CreateTextureClientForDrawing(
     aFormat, aRect.Size(), BackendSelector::Content,
-    aFlags | ExtraTextureFlags(),
+    aFlags | ExtraTextureFlags() | TextureFlags::BLOCKING_READ_LOCK,
     textureAllocFlags
   );
 
   if (!textureClient || !AddTextureClient(textureClient)) {
     return nullptr;
   }
-  textureClient->EnableBlockingReadLock();
 
   RefPtr<TextureClient> textureClientOnWhite;
   if (aFlags & TextureFlags::COMPONENT_ALPHA) {
     textureClientOnWhite = textureClient->CreateSimilar(
       mForwarder->GetCompositorBackendType(),
       aFlags | ExtraTextureFlags(),
       TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE
     );
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -92,17 +92,17 @@ ClientSingleTiledLayerBuffer::GetSurface
 }
 
 already_AddRefed<TextureClient>
 ClientSingleTiledLayerBuffer::GetTextureClient()
 {
   MOZ_ASSERT(mFormat != gfx::SurfaceFormat::UNKNOWN);
   return mCompositableClient.CreateTextureClientForDrawing(
     gfx::ImageFormatToSurfaceFormat(mFormat), mSize, BackendSelector::Content,
-    TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD);
+    TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD | TextureFlags::NON_BLOCKING_READ_LOCK);
 }
 
 void
 ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
                                           const nsIntRegion& aPaintRegion,
                                           const nsIntRegion& aDirtyRegion,
                                           LayerManager::DrawPaintedLayerCallback aCallback,
                                           void* aCallbackData,
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -592,33 +592,30 @@ void
 TextureClient::EnableReadLock()
 {
   if (!mReadLock) {
     mReadLock = NonBlockingTextureReadLock::Create(mAllocator);
   }
 }
 
 bool
-TextureClient::SerializeReadLock(ReadLockDescriptor& aDescriptor)
+TextureClient::OnForwardedToHost()
 {
   if (mData) {
     mData->OnForwardedToHost();
   }
 
   if (mReadLock && mUpdated) {
     // Take a read lock on behalf of the TextureHost. The latter will unlock
     // after the shared data is available again for drawing.
     mReadLock->ReadLock();
     mUpdated = false;
-    if (mReadLock->Serialize(aDescriptor, GetAllocator()->GetParentPid())) {
-      return true;
-    }
+    return true;
   }
 
-  aDescriptor = null_t();
   return false;
 }
 
 TextureClient::~TextureClient()
 {
   // TextureClients should be kept alive while there are references on the
   // paint thread.
   MOZ_ASSERT(mPaintThreadRefs == 0);
@@ -923,18 +920,24 @@ TextureClient::InitIPDLActor(Compositabl
   mExternalImageId = aForwarder->GetTextureForwarder()->GetNextExternalImageId();
 
   nsIEventTarget* target = nullptr;
   // Get the layers id if the forwarder is a ShadowLayerForwarder.
   if (ShadowLayerForwarder* forwarder = aForwarder->AsLayerForwarder()) {
     target = forwarder->GetEventTarget();
   }
 
+  ReadLockDescriptor readLockDescriptor = null_t();
+  if (mReadLock) {
+    mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
+  }
+
   PTextureChild* actor = aForwarder->GetTextureForwarder()->CreateTexture(
     desc,
+    readLockDescriptor,
     aForwarder->GetCompositorBackendType(),
     GetFlags(),
     mSerial,
     mExternalImageId,
     target);
 
   if (!actor) {
     gfxCriticalNote << static_cast<int32_t>(desc.type()) << ", "
@@ -985,18 +988,24 @@ TextureClient::InitIPDLActor(KnowsCompos
   SurfaceDescriptor desc;
   if (!ToSurfaceDescriptor(desc)) {
     return false;
   }
 
   // Try external image id allocation.
   mExternalImageId = aForwarder->GetTextureForwarder()->GetNextExternalImageId();
 
+  ReadLockDescriptor readLockDescriptor = null_t();
+  if (mReadLock) {
+    mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
+  }
+
   PTextureChild* actor = fwd->CreateTexture(
     desc,
+    readLockDescriptor,
     aForwarder->GetCompositorBackendType(),
     GetFlags(),
     mSerial,
     mExternalImageId);
   if (!actor) {
     gfxCriticalNote << static_cast<int32_t>(desc.type()) << ", "
                     << static_cast<int32_t>(aForwarder->GetCompositorBackendType()) << ", "
                     << static_cast<uint32_t>(GetFlags())
@@ -1345,16 +1354,24 @@ TextureClient::TextureClient(TextureData
   , mFwdTransactionId(0)
   , mSerial(++sSerialCounter)
 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
   , mPoolTracker(nullptr)
 #endif
 {
   mData->FillInfo(mInfo);
   mFlags |= mData->GetTextureFlags();
+
+  if (mFlags & TextureFlags::NON_BLOCKING_READ_LOCK) {
+    MOZ_ASSERT(!(mFlags & TextureFlags::BLOCKING_READ_LOCK));
+    EnableReadLock();
+  } else if (mFlags & TextureFlags::BLOCKING_READ_LOCK) {
+    MOZ_ASSERT(!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK));
+    EnableBlockingReadLock();
+  }
 }
 
 bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
                                         const gfx::IntRect* aRect,
                                         const gfx::IntPoint* aPoint)
 {
   MOZ_ASSERT(IsLocked());
   MOZ_ASSERT(aTarget->IsLocked());
@@ -1508,19 +1525,21 @@ public:
   bool mAllocSuccess;
 };
 
 class CrossProcessSemaphoreReadLock : public TextureReadLock
 {
 public:
   CrossProcessSemaphoreReadLock()
     : mSemaphore(CrossProcessSemaphore::Create("TextureReadLock", 1))
+    , mShared(false)
   {}
   explicit CrossProcessSemaphoreReadLock(CrossProcessSemaphoreHandle aHandle)
     : mSemaphore(CrossProcessSemaphore::Create(aHandle))
+    , mShared(false)
   {}
 
   virtual bool ReadLock() override
   {
     if (!IsValid()) {
       return false;
     }
     return mSemaphore->Wait();
@@ -1542,16 +1561,17 @@ public:
   }
   virtual bool IsValid() const override { return !!mSemaphore; }
 
   virtual bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
 
   virtual LockType GetType() override { return TYPE_CROSS_PROCESS_SEMAPHORE; }
 
   UniquePtr<CrossProcessSemaphore> mSemaphore;
+  bool mShared;
 };
 
 // static
 already_AddRefed<TextureReadLock>
 TextureReadLock::Deserialize(const ReadLockDescriptor& aDescriptor, ISurfaceAllocator* aAllocator)
 {
   switch (aDescriptor.type()) {
     case ReadLockDescriptor::TShmemSection: {
@@ -1723,21 +1743,23 @@ ShmemTextureReadLock::GetReadCount() {
   }
   ShmReadLockInfo* info = GetShmReadLockInfoPtr();
   return info->readCount;
 }
 
 bool
 CrossProcessSemaphoreReadLock::Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther)
 {
-  if (IsValid()) {
+  if (!mShared && IsValid()) {
     aOutput = ReadLockDescriptor(CrossProcessSemaphoreDescriptor(mSemaphore->ShareToProcess(aOther)));
+    mSemaphore->CloseHandle();
+    mShared = true;
     return true;
   } else {
-    return false;
+    return mShared;
   }
 }
 
 void
 TextureClient::EnableBlockingReadLock()
 {
   if (!mReadLock) {
     mReadLock = new CrossProcessSemaphoreReadLock();
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -630,27 +630,24 @@ public:
   void SetLastFwdTransactionId(uint64_t aTransactionId)
   {
     MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
     mFwdTransactionId = aTransactionId;
   }
 
   uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
 
-  void EnableReadLock();
-  void EnableBlockingReadLock();
-
   TextureReadLock* GetReadLock() { return mReadLock; }
 
   bool IsReadLocked() const;
 
   bool TryReadLock();
   void ReadUnlock();
 
-  bool SerializeReadLock(ReadLockDescriptor& aDescriptor);
+  bool OnForwardedToHost();
 
   // Mark that the TextureClient will be used by the paint thread, and should not
   // free its underlying texture data. This must only be called from the main
   // thread.
   void AddPaintThreadRef();
 
   // Mark that the TextureClient is no longer in use by the PaintThread. This
   // must only be called from the PaintThread.
@@ -678,16 +675,19 @@ private:
   CreateForRawBufferAccess(LayersIPCChannel* aAllocator,
                            gfx::SurfaceFormat aFormat,
                            gfx::IntSize aSize,
                            gfx::BackendType aMoz2dBackend,
                            LayersBackend aLayersBackend,
                            TextureFlags aTextureFlags,
                            TextureAllocationFlags flags = ALLOC_DEFAULT);
 
+  void EnableReadLock();
+  void EnableBlockingReadLock();
+
   /**
    * Called once, during the destruction of the Texture, on the thread in which
    * texture's reference count reaches 0 (could be any thread).
    *
    * Here goes the shut-down code that uses virtual methods.
    * Must only be called by Release().
    */
   void Finalize() {}
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -637,18 +637,16 @@ CreateBackBufferTexture(TextureClient* a
 
   RefPtr<TextureClient> texture = aAllocator->GetTextureClient();
 
   if (!texture) {
     gfxCriticalError() << "[Tiling:Client] Failed to allocate a TextureClient";
     return nullptr;
   }
 
-  texture->EnableReadLock();
-
   if (!aCompositable.AddTextureClient(texture)) {
     gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient";
     return nullptr;
   }
 
   return texture.forget();
 }
 
@@ -749,28 +747,27 @@ TileClient::GetTileDescriptor()
 {
   if (IsPlaceholderTile()) {
     mWasPlaceholder = true;
     return PlaceholderTileDescriptor();
   }
   bool wasPlaceholder = mWasPlaceholder;
   mWasPlaceholder = false;
 
-  ReadLockDescriptor lock;
-  mFrontBuffer->SerializeReadLock(lock);
+  bool readLocked = mFrontBuffer->OnForwardedToHost();
+  bool readLockedOnWhite = false;
 
-  ReadLockDescriptor lockOnWhite = null_t();
   if (mFrontBufferOnWhite) {
-    mFrontBufferOnWhite->SerializeReadLock(lockOnWhite);
+    readLockedOnWhite = mFrontBufferOnWhite->OnForwardedToHost();
   }
 
   return TexturedTileDescriptor(nullptr, mFrontBuffer->GetIPDLActor(),
                                 mFrontBufferOnWhite ? MaybeTexture(mFrontBufferOnWhite->GetIPDLActor()) : MaybeTexture(null_t()),
                                 mUpdateRect,
-                                lock, lockOnWhite,
+                                readLocked, readLockedOnWhite,
                                 wasPlaceholder);
 }
 
 void
 ClientMultiTiledLayerBuffer::DiscardBuffers()
 {
   for (TileClient& tile : mRetainedTiles) {
     tile.DiscardBuffers();
@@ -1114,17 +1111,17 @@ ClientMultiTiledLayerBuffer::ValidateTil
 
   SurfaceMode mode;
   gfxContentType content = GetContentType(&mode);
 
   if (!aTile.mAllocator) {
     aTile.SetTextureAllocator(mManager->GetCompositorBridgeChild()->GetTexturePool(
       mManager->AsShadowForwarder(),
       gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content),
-      TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD));
+      TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD | TextureFlags::NON_BLOCKING_READ_LOCK));
     MOZ_ASSERT(aTile.mAllocator);
   }
 
   nsIntRegion offsetScaledDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
   offsetScaledDirtyRegion.ScaleRoundOut(mResolution, mResolution);
 
   std::vector<CapturedTiledPaintState::Copy> asyncPaintCopies;
   std::vector<RefPtr<TextureClient>> asyncPaintClients;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -69,16 +69,17 @@ namespace layers {
 class TextureParent : public ParentActor<PTextureParent>
 {
 public:
   explicit TextureParent(HostIPCAllocator* aAllocator, uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId);
 
   ~TextureParent();
 
   bool Init(const SurfaceDescriptor& aSharedData,
+            const ReadLockDescriptor& aReadLock,
             const LayersBackend& aLayersBackend,
             const TextureFlags& aFlags);
 
   void NotifyNotUsed(uint64_t aTransactionId);
 
   virtual mozilla::ipc::IPCResult RecvRecycleTexture(const TextureFlags& aTextureFlags) override;
 
   TextureHost* GetTextureHost() { return mTextureHost; }
@@ -106,23 +107,24 @@ WrapWithWebRenderTextureHost(ISurfaceAll
   }
   return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 PTextureParent*
 TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
                              const SurfaceDescriptor& aSharedData,
+                             const ReadLockDescriptor& aReadLock,
                              LayersBackend aLayersBackend,
                              TextureFlags aFlags,
                              uint64_t aSerial,
                              const wr::MaybeExternalImageId& aExternalImageId)
 {
   TextureParent* actor = new TextureParent(aAllocator, aSerial, aExternalImageId);
-  if (!actor->Init(aSharedData, aLayersBackend, aFlags)) {
+  if (!actor->Init(aSharedData, aReadLock, aLayersBackend, aFlags)) {
     actor->ActorDestroy(ipc::IProtocol::ActorDestroyReason::FailedConstructor);
     delete actor;
     return nullptr;
   }
   return actor;
 }
 
 // static
@@ -188,16 +190,17 @@ already_AddRefed<TextureHost> CreateText
 // implemented in TextureD3D11.cpp
 already_AddRefed<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
                                                      ISurfaceAllocator* aDeallocator,
                                                      LayersBackend aBackend,
                                                      TextureFlags aFlags);
 
 already_AddRefed<TextureHost>
 TextureHost::Create(const SurfaceDescriptor& aDesc,
+                    const ReadLockDescriptor& aReadLock,
                     ISurfaceAllocator* aDeallocator,
                     LayersBackend aBackend,
                     TextureFlags aFlags,
                     wr::MaybeExternalImageId& aExternalImageId)
 {
   RefPtr<TextureHost> result;
 
   switch (aDesc.type()) {
@@ -247,16 +250,20 @@ TextureHost::Create(const SurfaceDescrip
       MOZ_CRASH("GFX: Unsupported Surface type host");
   }
 
   if (result && WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
     MOZ_ASSERT(aExternalImageId.isSome());
     result = new WebRenderTextureHost(aDesc, aFlags, result, aExternalImageId.ref());
   }
 
+  if (result) {
+    result->DeserializeReadLock(aReadLock, aDeallocator);
+  }
+
   return result.forget();
 }
 
 already_AddRefed<TextureHost>
 CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
                                     ISurfaceAllocator* aDeallocator,
                                     LayersBackend aBackend,
                                     TextureFlags aFlags)
@@ -350,16 +357,17 @@ CreateBackendIndependentTextureHost(cons
 }
 
 TextureHost::TextureHost(TextureFlags aFlags)
     : AtomicRefCountedWithFinalize("TextureHost")
     , mActor(nullptr)
     , mFlags(aFlags)
     , mCompositableCount(0)
     , mFwdTransactionId(0)
+    , mReadLocked(false)
 {
 }
 
 TextureHost::~TextureHost()
 {
   // If we still have a ReadLock, unlock it. At this point we don't care about
   // the texture client being written into on the other side since it should be
   // destroyed by now. But we will hit assertions if we don't ReadUnlock before
@@ -373,17 +381,17 @@ void TextureHost::Finalize()
     DeallocateSharedData();
     DeallocateDeviceData();
   }
 }
 
 void
 TextureHost::UnbindTextureSource()
 {
-  if (mReadLock) {
+  if (mReadLocked) {
     // This TextureHost is not used anymore. Since most compositor backends are
     // working asynchronously under the hood a compositor could still be using
     // this texture, so it is generally best to wait until the end of the next
     // composition before calling ReadUnlock. We ask the compositor to take care
     // of that for us.
     if (mProvider) {
       mProvider->UnlockAfterComposition(this);
     } else {
@@ -669,45 +677,41 @@ BufferTextureHost::PushDisplayItems(wr::
                                   aFilter);
   }
 }
 
 void
 TextureHost::DeserializeReadLock(const ReadLockDescriptor& aDesc,
                                  ISurfaceAllocator* aAllocator)
 {
-  RefPtr<TextureReadLock> lock = TextureReadLock::Deserialize(aDesc, aAllocator);
-  if (!lock) {
+  if (mReadLock) {
     return;
   }
 
-  // If mReadLock is not null it means we haven't unlocked it yet and the content
-  // side should not have been able to write into this texture and send a new lock!
-  MOZ_ASSERT(!mReadLock);
-  mReadLock = lock.forget();
+  mReadLock = TextureReadLock::Deserialize(aDesc, aAllocator);
 }
 
 void
-TextureHost::SetReadLock(TextureReadLock* aReadLock)
+TextureHost::SetReadLocked()
 {
-  if (!aReadLock) {
+  if (!mReadLock) {
     return;
   }
-  // If mReadLock is not null it means we haven't unlocked it yet and the content
-  // side should not have been able to write into this texture and send a new lock!
-  MOZ_ASSERT(!mReadLock);
-  mReadLock = aReadLock;
+  // If mReadLocked is true it means we haven't read unlocked yet and the content
+  // side should not have been able to write into this texture and read lock again!
+  MOZ_ASSERT(!mReadLocked);
+  mReadLocked = true;
 }
 
 void
 TextureHost::ReadUnlock()
 {
-  if (mReadLock) {
+  if (mReadLock && mReadLocked) {
     mReadLock->ReadUnlock();
-    mReadLock = nullptr;
+    mReadLocked = false;
   }
 }
 
 bool
 BufferTextureHost::EnsureWrappingTextureSource()
 {
   MOZ_ASSERT(!mHasIntermediateBuffer);
 
@@ -1243,20 +1247,22 @@ TextureParent::NotifyNotUsed(uint64_t aT
   if (!mTextureHost) {
     return;
   }
   mSurfaceAllocator->NotifyNotUsed(this, aTransactionId);
 }
 
 bool
 TextureParent::Init(const SurfaceDescriptor& aSharedData,
+                    const ReadLockDescriptor& aReadLock,
                     const LayersBackend& aBackend,
                     const TextureFlags& aFlags)
 {
   mTextureHost = TextureHost::Create(aSharedData,
+                                     aReadLock,
                                      mSurfaceAllocator,
                                      aBackend,
                                      aFlags,
                                      mExternalImageId);
   if (mTextureHost) {
     mTextureHost->mActor = this;
   }
 
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -396,16 +396,17 @@ protected:
   virtual ~TextureHost();
 
 public:
   /**
    * Factory method.
    */
   static already_AddRefed<TextureHost> Create(
     const SurfaceDescriptor& aDesc,
+    const ReadLockDescriptor& aReadLock,
     ISurfaceAllocator* aDeallocator,
     LayersBackend aBackend,
     TextureFlags aFlags,
     wr::MaybeExternalImageId& aExternalImageId);
 
   /**
    * Lock the texture host for compositing.
    */
@@ -543,16 +544,17 @@ public:
    *
    * TextureParent< is an implementation detail of TextureHost that is not
    * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
    * are for use with the managing IPDL protocols only (so that they can
    * implement AllocPTextureParent and DeallocPTextureParent).
    */
   static PTextureParent* CreateIPDLActor(HostIPCAllocator* aAllocator,
                                          const SurfaceDescriptor& aSharedData,
+                                         const ReadLockDescriptor& aDescriptor,
                                          LayersBackend aLayersBackend,
                                          TextureFlags aFlags,
                                          uint64_t aSerial,
                                          const wr::MaybeExternalImageId& aExternalImageId);
   static bool DestroyIPDLActor(PTextureParent* actor);
 
   /**
    * Destroy the TextureChild/Parent pair.
@@ -607,17 +609,17 @@ public:
   }
 
   int NumCompositableRefs() const { return mCompositableCount; }
 
   void SetLastFwdTransactionId(uint64_t aTransactionId);
 
   void DeserializeReadLock(const ReadLockDescriptor& aDesc,
                            ISurfaceAllocator* aAllocator);
-  void SetReadLock(TextureReadLock* aReadLock);
+  void SetReadLocked();
 
   TextureReadLock* GetReadLock() { return mReadLock; }
 
   virtual BufferTextureHost* AsBufferTextureHost() { return nullptr; }
   virtual MacIOSurfaceTextureHostOGL* AsMacIOSurfaceTextureHost() { return nullptr; }
   virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; }
 
   // Create the corresponding RenderTextureHost type of this texture, and
@@ -676,16 +678,17 @@ protected:
   void CallNotifyNotUsed();
 
   PTextureParent* mActor;
   RefPtr<TextureSourceProvider> mProvider;
   RefPtr<TextureReadLock> mReadLock;
   TextureFlags mFlags;
   int mCompositableCount;
   uint64_t mFwdTransactionId;
+  bool mReadLocked;
 
   friend class Compositor;
   friend class TextureParent;
   friend class TiledLayerBufferComposite;
   friend class TextureSourceProvider;
 };
 
 /**
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -316,25 +316,27 @@ TiledLayerBufferComposite::UseTiles(cons
         "Unrecognised tile descriptor type");
       continue;
     }
 
     const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
 
     tile.mTextureHost = TextureHost::AsTextureHost(texturedDesc.textureParent());
     tile.mTextureHost->SetTextureSourceProvider(aLayerManager->GetCompositor());
-    tile.mTextureHost->DeserializeReadLock(texturedDesc.sharedLock(), aAllocator);
+    if (texturedDesc.readLocked()) {
+      tile.mTextureHost->SetReadLocked();
+    }
 
     if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
       tile.mTextureHostOnWhite = TextureHost::AsTextureHost(
         texturedDesc.textureOnWhite().get_PTextureParent()
       );
-      tile.mTextureHostOnWhite->DeserializeReadLock(
-        texturedDesc.sharedLockOnWhite(), aAllocator
-      );
+      if (texturedDesc.readLockedOnWhite()) {
+        tile.mTextureHostOnWhite->SetReadLocked();
+      }
     }
 
     tile.mTilePosition = newTiles.TilePosition(i);
 
     // If this same tile texture existed in the old tile set then this will move the texture
     // source into our new tile.
     oldRetainedTiles.RecycleTextureSourceForTile(tile);
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -156,17 +156,19 @@ CompositableParentManager::ReceiveCompos
         CompositableHost::TimedTexture* t = textures.AppendElement();
         t->mTexture =
             TextureHost::AsTextureHost(timedTexture.textureParent());
         MOZ_ASSERT(t->mTexture);
         t->mTimeStamp = timedTexture.timeStamp();
         t->mPictureRect = timedTexture.picture();
         t->mFrameID = timedTexture.frameID();
         t->mProducerID = timedTexture.producerID();
-        t->mTexture->SetReadLock(FindReadLock(timedTexture.sharedLock()));
+        if (timedTexture.readLocked()) {
+          t->mTexture->SetReadLocked();
+        }
       }
       if (textures.Length() > 0) {
         compositable->UseTextureHost(textures);
 
         for (auto& timedTexture : op.textures()) {
           RefPtr<TextureHost> texture = TextureHost::AsTextureHost(timedTexture.textureParent());
           if (texture) {
             texture->SetLastFwdTransactionId(mFwdTransactionId);
@@ -181,18 +183,22 @@ CompositableParentManager::ReceiveCompos
         ScheduleComposition(compositable);
       }
       break;
     }
     case CompositableOperationDetail::TOpUseComponentAlphaTextures: {
       const OpUseComponentAlphaTextures& op = aEdit.detail().get_OpUseComponentAlphaTextures();
       RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
       RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
-      texOnBlack->SetReadLock(FindReadLock(op.sharedLockBlack()));
-      texOnWhite->SetReadLock(FindReadLock(op.sharedLockWhite()));
+      if (op.readLockedBlack()) {
+        texOnBlack->SetReadLocked();
+      }
+      if (op.readLockedWhite()) {
+        texOnWhite->SetReadLocked();
+      }
 
       MOZ_ASSERT(texOnBlack && texOnWhite);
       compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
 
       if (texOnBlack) {
         texOnBlack->SetLastFwdTransactionId(mFwdTransactionId);
         // Make sure that each texture was handled by the compositable
         // because the recycling logic depends on it.
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -847,16 +847,17 @@ CompositorBridgeChild::SendAllPluginsCap
   if (!mCanSend) {
     return false;
   }
   return PCompositorBridgeChild::SendAllPluginsCaptured();
 }
 
 PTextureChild*
 CompositorBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
+                                          const ReadLockDescriptor&,
                                           const LayersBackend&,
                                           const TextureFlags&,
                                           const uint64_t&,
                                           const uint64_t& aSerial,
                                           const wr::MaybeExternalImageId& aExternalImageId)
 {
   return TextureClient::CreateIPDLActor();
 }
@@ -999,32 +1000,33 @@ CompositorBridgeChild::GetTileLockAlloca
   if (!mSectionAllocator) {
     mSectionAllocator = new FixedSizeSmallShmemSectionAllocator(this);
   }
   return mSectionAllocator;
 }
 
 PTextureChild*
 CompositorBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
+                                     const ReadLockDescriptor& aReadLock,
                                      LayersBackend aLayersBackend,
                                      TextureFlags aFlags,
                                      uint64_t aSerial,
                                      wr::MaybeExternalImageId& aExternalImageId,
                                      nsIEventTarget* aTarget)
 {
   PTextureChild* textureChild = AllocPTextureChild(
-    aSharedData, aLayersBackend, aFlags, 0 /* FIXME */, aSerial, aExternalImageId);
+    aSharedData, aReadLock, aLayersBackend, aFlags, 0 /* FIXME */, aSerial, aExternalImageId);
 
   // Do the DOM labeling.
   if (aTarget) {
     SetEventTargetForActor(textureChild, aTarget);
   }
 
   return SendPTextureConstructor(
-    textureChild, aSharedData, aLayersBackend, aFlags, 0 /* FIXME? */, aSerial, aExternalImageId);
+    textureChild, aSharedData, aReadLock, aLayersBackend, aFlags, 0 /* FIXME? */, aSerial, aExternalImageId);
 }
 
 bool
 CompositorBridgeChild::AllocUnsafeShmem(size_t aSize,
                                    ipc::SharedMemory::SharedMemoryType aType,
                                    ipc::Shmem* aShmem)
 {
   ShmemAllocated(this);
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -99,27 +99,29 @@ public:
 
   virtual mozilla::ipc::IPCResult
   RecvCaptureAllPlugins(const uintptr_t& aParentWidget) override;
 
   virtual mozilla::ipc::IPCResult
   RecvHideAllPlugins(const uintptr_t& aParentWidget) override;
 
   virtual PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
+                                            const ReadLockDescriptor& aReadLock,
                                             const LayersBackend& aLayersBackend,
                                             const TextureFlags& aFlags,
                                             const uint64_t& aId,
                                             const uint64_t& aSerial,
                                             const wr::MaybeExternalImageId& aExternalImageId) override;
 
   virtual bool DeallocPTextureChild(PTextureChild* actor) override;
 
   virtual mozilla::ipc::IPCResult
   RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
   virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
+                                       const ReadLockDescriptor& aReadLock,
                                        LayersBackend aLayersBackend,
                                        TextureFlags aFlags,
                                        uint64_t aSerial,
                                        wr::MaybeExternalImageId& aExternalImageId,
                                        nsIEventTarget* aTarget) override;
 
   /**
    * Request that the parent tell us when graphics are ready on GPU.
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -2221,23 +2221,24 @@ CompositorBridgeParent::GetGeckoContentC
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   CompositorBridgeParent::LayerTreeState* state =
       GetStateForRoot(aContentLayersId, lock);
   return state ? state->mController.get() : nullptr;
 }
 
 PTextureParent*
 CompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                            const ReadLockDescriptor& aReadLock,
                                             const LayersBackend& aLayersBackend,
                                             const TextureFlags& aFlags,
                                             const uint64_t& aId,
                                             const uint64_t& aSerial,
                                             const wr::MaybeExternalImageId& aExternalImageId)
 {
-  return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
+  return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
 }
 
 bool
 CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor)
 {
   return TextureHost::DestroyIPDLActor(actor);
 }
 
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -263,16 +263,17 @@ public:
   void GetAPZTestData(const uint64_t& aLayersId,
                       APZTestData* aOutData) override;
   void SetConfirmedTargetAPZC(const uint64_t& aLayersId,
                               const uint64_t& aInputBlockId,
                               const nsTArray<ScrollableLayerGuid>& aTargets) override;
   AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) override { return mCompositionManager; }
 
   PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                      const ReadLockDescriptor& aReadLock,
                                       const LayersBackend& aLayersBackend,
                                       const TextureFlags& aFlags,
                                       const uint64_t& aId,
                                       const uint64_t& aSerial,
                                       const wr::MaybeExternalImageId& aExternalImageId) override;
   bool DeallocPTextureParent(PTextureParent* actor) override;
 
   bool IsSameProcess() const override;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -566,16 +566,17 @@ CrossProcessCompositorBridgeParent::Defe
 
 CrossProcessCompositorBridgeParent::~CrossProcessCompositorBridgeParent()
 {
   MOZ_ASSERT(XRE_GetIOMessageLoop());
 }
 
 PTextureParent*
 CrossProcessCompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                                        const ReadLockDescriptor& aReadLock,
                                                         const LayersBackend& aLayersBackend,
                                                         const TextureFlags& aFlags,
                                                         const uint64_t& aId,
                                                         const uint64_t& aSerial,
                                                         const wr::MaybeExternalImageId& aExternalImageId)
 {
   CompositorBridgeParent::LayerTreeState* state = nullptr;
 
@@ -597,17 +598,17 @@ CrossProcessCompositorBridgeParent::Allo
     // return null because this will mess up deserialization later and we'll
     // kill the content process. Instead, we signal that the underlying
     // TextureHost should not attempt to access the compositor.
     flags |= TextureFlags::INVALID_COMPOSITOR;
   } else if (actualBackend != LayersBackend::LAYERS_NONE && aLayersBackend != actualBackend) {
     gfxDevCrash(gfx::LogReason::PAllocTextureBackendMismatch) << "Texture backend is wrong";
   }
 
-  return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
+  return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
 }
 
 bool
 CrossProcessCompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor)
 {
   return TextureHost::DestroyIPDLActor(actor);
 }
 
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
@@ -117,16 +117,17 @@ public:
   void DidCompositeLocked(uint64_t aId,
                                   TimeStamp& aCompositeStart,
                                   TimeStamp& aCompositeEnd);
   void DidComposite(uint64_t aId,
                     TimeStamp& aCompositeStart,
                     TimeStamp& aCompositeEnd) override;
 
   PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                      const ReadLockDescriptor& aReadLock,
                                       const LayersBackend& aLayersBackend,
                                       const TextureFlags& aFlags,
                                       const uint64_t& aId,
                                       const uint64_t& aSerial,
                                       const wr::MaybeExternalImageId& aExternalImageId) override;
 
   bool DeallocPTextureParent(PTextureParent* actor) override;
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -136,26 +136,21 @@ ImageBridgeChild::UseTextures(Compositab
   for (auto& t : aTextures) {
     MOZ_ASSERT(t.mTextureClient);
     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
 
     if (!t.mTextureClient->IsSharedWithCompositor()) {
       return;
     }
 
-    ReadLockDescriptor readLock;
-    ReadLockHandle readLockHandle;
-    if (t.mTextureClient->SerializeReadLock(readLock)) {
-      readLockHandle = mTxn->AddReadLock(readLock);
-    }
-
+    bool readLocked = t.mTextureClient->OnForwardedToHost();
     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
-                                        readLockHandle,
                                         t.mTimeStamp, t.mPictureRect,
-                                        t.mFrameID, t.mProducerID));
+                                        t.mFrameID, t.mProducerID,
+                                        readLocked));
 
     // Wait end of usage on host side if TextureFlags::RECYCLE is set
     HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
   mTxn->AddNoSwapEdit(CompositableOperation(aCompositable->GetIPCHandle(),
                                             OpUseTexture(textures)));
 }
 
@@ -960,16 +955,17 @@ ImageBridgeChild::DeallocShmem(ipc::Shme
   GetMessageLoop()->PostTask(runnable.forget());
 
   task.Wait();
   return result;
 }
 
 PTextureChild*
 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
+                                     const ReadLockDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial,
                                      const wr::MaybeExternalImageId& aExternalImageId)
 {
   MOZ_ASSERT(CanSend());
   return TextureClient::CreateIPDLActor();
 }
@@ -1030,24 +1026,25 @@ ImageBridgeChild::RecvDidComposite(Infal
       listener->NotifyComposite(n);
     }
   }
   return IPC_OK();
 }
 
 PTextureChild*
 ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
+                                const ReadLockDescriptor& aReadLock,
                                 LayersBackend aLayersBackend,
                                 TextureFlags aFlags,
                                 uint64_t aSerial,
                                 wr::MaybeExternalImageId& aExternalImageId,
                                 nsIEventTarget* aTarget)
 {
   MOZ_ASSERT(CanSend());
-  return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
+  return SendPTextureConstructor(aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
 }
 
 static bool
 IBCAddOpDestroy(CompositableTransaction* aTxn, const OpDestroy& op)
 {
   if (aTxn->Finished()) {
     return false;
   }
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -168,16 +168,17 @@ public:
    * Can be called from any thread.
    */
   virtual MessageLoop * GetMessageLoop() const override;
 
   virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
 
   virtual PTextureChild*
   AllocPTextureChild(const SurfaceDescriptor& aSharedData,
+                     const ReadLockDescriptor& aReadLock,
                      const LayersBackend& aLayersBackend,
                      const TextureFlags& aFlags,
                      const uint64_t& aSerial,
                      const wr::MaybeExternalImageId& aExternalImageId) override;
 
   virtual bool
   DeallocPTextureChild(PTextureChild* actor) override;
 
@@ -326,16 +327,17 @@ public:
    * Can be used from any thread.
    * If used outside the ImageBridgeChild thread, it will proxy a synchronous
    * call on the ImageBridgeChild thread.
    */
   virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
 
   virtual PTextureChild* CreateTexture(
     const SurfaceDescriptor& aSharedData,
+    const ReadLockDescriptor& aReadLock,
     LayersBackend aLayersBackend,
     TextureFlags aFlags,
     uint64_t aSerial,
     wr::MaybeExternalImageId& aExternalImageId,
     nsIEventTarget* aTarget = nullptr) override;
 
   virtual bool IsSameProcess() const override;
 
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -315,22 +315,23 @@ mozilla::ipc::IPCResult
 ImageBridgeParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
 {
   ReleaseCompositable(aHandle);
   return IPC_OK();
 }
 
 PTextureParent*
 ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                       const ReadLockDescriptor& aReadLock,
                                        const LayersBackend& aLayersBackend,
                                        const TextureFlags& aFlags,
                                        const uint64_t& aSerial,
                                        const wr::MaybeExternalImageId& aExternalImageId)
 {
-  return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
+  return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
 }
 
 bool
 ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor)
 {
   return TextureHost::DestroyIPDLActor(actor);
 }
 
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -77,16 +77,17 @@ public:
 
   // PImageBridge
   virtual mozilla::ipc::IPCResult RecvImageBridgeThreadId(const PlatformThreadId& aThreadId) override;
   virtual mozilla::ipc::IPCResult RecvInitReadLocks(ReadLockArray&& aReadLocks) override;
   virtual mozilla::ipc::IPCResult RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
                                           const uint64_t& aFwdTransactionId) override;
 
   virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                              const ReadLockDescriptor& aReadLock,
                                               const LayersBackend& aLayersBackend,
                                               const TextureFlags& aFlags,
                                               const uint64_t& aSerial,
                                               const wr::MaybeExternalImageId& aExternalImageId) override;
   virtual bool DeallocPTextureParent(PTextureParent* actor) override;
 
   virtual mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                                       const TextureInfo& aInfo,
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -388,18 +388,18 @@ union MaybeTexture {
   PTexture;
   null_t;
 };
 
 struct TexturedTileDescriptor {
   PTexture texture;
   MaybeTexture textureOnWhite;
   IntRect updateRect;
-  ReadLockDescriptor sharedLock;
-  ReadLockDescriptor sharedLockOnWhite;
+  bool readLocked;
+  bool readLockedOnWhite;
   bool wasPlaceholder;
 };
 
 struct PlaceholderTileDescriptor {
 };
 
 union TileDescriptor {
   TexturedTileDescriptor;
@@ -434,21 +434,21 @@ struct OpPaintTextureRegion {
  * Tells the CompositableHost to remove the corresponding TextureHost
  */
 struct OpRemoveTexture {
   PTexture texture;
 };
 
 struct TimedTexture {
   PTexture texture;
-  ReadLockHandle sharedLock;
   TimeStamp timeStamp;
   IntRect picture;
   uint32_t frameID;
   uint32_t producerID;
+  bool readLocked;
 };
 
 /**
  * Tells the compositor-side which textures to use (for example, as front buffer
  * if there are several textures for double buffering).
  * This provides a list of textures with timestamps, ordered by timestamp.
  * The newest texture whose timestamp is <= the current time is rendered
  * (where null is considered less than every other timestamp). If there is no
@@ -458,18 +458,18 @@ struct TimedTexture {
  */
 struct OpUseTexture {
   TimedTexture[] textures;
 };
 
 struct OpUseComponentAlphaTextures {
   PTexture textureOnBlack;
   PTexture textureOnWhite;
-  ReadLockHandle sharedLockBlack;
-  ReadLockHandle sharedLockWhite;
+  bool readLockedBlack;
+  bool readLockedWhite;
 };
 
 union MaybeRegion {
   nsIntRegion;
   null_t;
 };
 
 struct OpNotifyNotUsed {
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -241,17 +241,17 @@ parent:
   // We visualize this information in the APZ minimap.
   async NotifyApproximatelyVisibleRegion(ScrollableLayerGuid guid, CSSIntRegion region);
 
   /**
    * Sent when the child has finished CaptureAllPlugins.
    */
   async AllPluginsCaptured();
 
-  async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t id, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
+  async PTexture(SurfaceDescriptor aSharedData, ReadLockDescriptor aReadLock, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t id, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
 
   sync SyncWithCompositor();
 
   // The pipelineId is the same as the layersId
   sync PWebRenderBridge(PipelineId pipelineId, LayoutDeviceIntSize aSize)
     returns (TextureFactoryIdentifier textureFactoryIdentifier, IdNamespace idNamespace);
 
   sync CheckContentOnlyTDR(uint32_t sequenceNum)
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -52,17 +52,17 @@ parent:
   // in a state in which it can't send asynchronous messages
   // so as to not race with the channel getting closed.
   // In the child side, the Closing the channel does not happen right after WillClose,
   // it is scheduled in the ImageBridgeChild's message queue in order to ensure
   // that all of the messages from the parent side have been received and processed
   // before sending closing the channel.
   sync WillClose();
 
-  async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
+  async PTexture(SurfaceDescriptor aSharedData, ReadLockDescriptor aReadLock, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t aSerial, MaybeExternalImageId aExternalImageId);
   async PMediaSystemResourceManager();
 
   sync NewCompositable(CompositableHandle aHandle, TextureInfo aInfo, LayersBackend aBackend);
   async ReleaseCompositable(CompositableHandle aHandle);
 };
 
 
 } // namespace
--- a/gfx/layers/ipc/PVideoBridge.ipdl
+++ b/gfx/layers/ipc/PVideoBridge.ipdl
@@ -19,15 +19,15 @@ namespace layers {
  * The PVideoBridge protocol is used to share textures from the video decoders
  * to the compositor.
  */
 sync protocol PVideoBridge
 {
   manages PTexture;
 
 parent:
-  async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend,
+  async PTexture(SurfaceDescriptor aSharedData, ReadLockDescriptor aReadLock, LayersBackend aBackend,
                  TextureFlags aTextureFlags, uint64_t aSerial);
 };
 
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -488,25 +488,21 @@ ShadowLayerForwarder::UseTextures(Compos
   }
 
   AutoTArray<TimedTexture,4> textures;
 
   for (auto& t : aTextures) {
     MOZ_ASSERT(t.mTextureClient);
     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
     MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
-    ReadLockDescriptor readLock;
-    ReadLockHandle readLockHandle;
-    if (t.mTextureClient->SerializeReadLock(readLock)) {
-      readLockHandle = mTxn->AddReadLock(readLock);
-    }
+    bool readLocked = t.mTextureClient->OnForwardedToHost();
     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
-                                        readLockHandle,
                                         t.mTimeStamp, t.mPictureRect,
-                                        t.mFrameID, t.mProducerID));
+                                        t.mFrameID, t.mProducerID,
+                                        readLocked));
     mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
   mTxn->AddEdit(CompositableOperation(aCompositable->GetIPCHandle(),
                                       OpUseTexture(textures)));
 }
 
 void
 ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositable,
@@ -523,37 +519,29 @@ ShadowLayerForwarder::UseComponentAlphaT
   MOZ_ASSERT(aTextureOnBlack);
   MOZ_ASSERT(aCompositable->GetIPCHandle());
   MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
   MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
   MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
   MOZ_RELEASE_ASSERT(aTextureOnWhite->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
   MOZ_RELEASE_ASSERT(aTextureOnBlack->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
 
-  ReadLockDescriptor readLockB;
-  ReadLockHandle readLockHandleB;
-  ReadLockDescriptor readLockW;
-  ReadLockHandle readLockHandleW;
-  if (aTextureOnBlack->SerializeReadLock(readLockB)) {
-    readLockHandleB = mTxn->AddReadLock(readLockB);
-  }
-  if (aTextureOnWhite->SerializeReadLock(readLockW)) {
-    readLockHandleW = mTxn->AddReadLock(readLockW);
-  }
+  bool readLockedB = aTextureOnBlack->OnForwardedToHost();
+  bool readLockedW = aTextureOnWhite->OnForwardedToHost();
 
   mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
   mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
 
   mTxn->AddEdit(
     CompositableOperation(
       aCompositable->GetIPCHandle(),
       OpUseComponentAlphaTextures(
         nullptr, aTextureOnBlack->GetIPDLActor(),
         nullptr, aTextureOnWhite->GetIPDLActor(),
-        readLockHandleB, readLockHandleW)
+        readLockedB, readLockedW)
       )
     );
 }
 
 static bool
 AddOpDestroy(Transaction* aTxn, const OpDestroy& op)
 {
   if (!aTxn->Opened()) {
--- a/gfx/layers/ipc/TextureForwarder.h
+++ b/gfx/layers/ipc/TextureForwarder.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_LAYERS_TEXTUREFORWARDER
 #define MOZILLA_LAYERS_TEXTUREFORWARDER
 
 #include <stdint.h>                     // for int32_t, uint64_t
 #include "gfxTypes.h"
+#include "mozilla/layers/LayersMessages.h"  // for Edit, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "mozilla/layers/KnowsCompositor.h"
 
 namespace mozilla {
 namespace ipc {
 class IShmemAllocator;
 }
@@ -64,16 +65,17 @@ protected:
  */
 class TextureForwarder : public LayersIPCChannel {
 public:
   /**
    * Create a TextureChild/Parent pair as as well as the TextureHost on the parent side.
    */
   virtual PTextureChild* CreateTexture(
     const SurfaceDescriptor& aSharedData,
+    const ReadLockDescriptor& aReadLock,
     LayersBackend aLayersBackend,
     TextureFlags aFlags,
     uint64_t aSerial,
     wr::MaybeExternalImageId& aExternalImageId,
     nsIEventTarget* aTarget = nullptr) = 0;
 };
 
 } // namespace layers
--- a/gfx/layers/ipc/VideoBridgeChild.cpp
+++ b/gfx/layers/ipc/VideoBridgeChild.cpp
@@ -73,16 +73,17 @@ VideoBridgeChild::AllocShmem(size_t aSiz
 bool
 VideoBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
   return PVideoBridgeChild::DeallocShmem(aShmem);
 }
 
 PTextureChild*
 VideoBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
+                                     const ReadLockDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial)
 {
   MOZ_ASSERT(CanSend());
   return TextureClient::CreateIPDLActor();
 }
 
@@ -101,24 +102,25 @@ VideoBridgeChild::ActorDestroy(ActorDest
 void
 VideoBridgeChild::DeallocPVideoBridgeChild()
 {
   mIPDLSelfRef = nullptr;
 }
 
 PTextureChild*
 VideoBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
+                                const ReadLockDescriptor& aReadLock,
                                 LayersBackend aLayersBackend,
                                 TextureFlags aFlags,
                                 uint64_t aSerial,
                                 wr::MaybeExternalImageId& aExternalImageId,
                                 nsIEventTarget* aTarget)
 {
   MOZ_ASSERT(CanSend());
-  return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
+  return SendPTextureConstructor(aSharedData, aReadLock, aLayersBackend, aFlags, aSerial);
 }
 
 bool VideoBridgeChild::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
 } // namespace layers
--- a/gfx/layers/ipc/VideoBridgeChild.h
+++ b/gfx/layers/ipc/VideoBridgeChild.h
@@ -22,16 +22,17 @@ public:
 
   static void Startup();
   static void Shutdown();
 
   static VideoBridgeChild* GetSingleton();
 
   // PVideoBridgeChild
   PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
+                                    const ReadLockDescriptor& aReadLock,
                                     const LayersBackend& aLayersBackend,
                                     const TextureFlags& aFlags,
                                     const uint64_t& aSerial) override;
   bool DeallocPTextureChild(PTextureChild* actor) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeallocPVideoBridgeChild() override;
 
@@ -42,16 +43,17 @@ public:
                         mozilla::ipc::Shmem* aShmem) override;
   bool AllocShmem(size_t aSize,
                   mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                   mozilla::ipc::Shmem* aShmem) override;
   bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
 
   // TextureForwarder
   PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
+                               const ReadLockDescriptor& aReadLock,
                                LayersBackend aLayersBackend,
                                TextureFlags aFlags,
                                uint64_t aSerial,
                                wr::MaybeExternalImageId& aExternalImageId,
                                nsIEventTarget* aTarget = nullptr) override;
 
   // ClientIPCAllocator
   base::ProcessId GetParentPid() const override { return OtherPid(); }
--- a/gfx/layers/ipc/VideoBridgeParent.cpp
+++ b/gfx/layers/ipc/VideoBridgeParent.cpp
@@ -52,22 +52,23 @@ void
 VideoBridgeParent::DeallocPVideoBridgeParent()
 {
   mCompositorThreadRef = nullptr;
   mSelfRef = nullptr;
 }
 
 PTextureParent*
 VideoBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                       const ReadLockDescriptor& aReadLock,
                                        const LayersBackend& aLayersBackend,
                                        const TextureFlags& aFlags,
                                        const uint64_t& aSerial)
 {
   PTextureParent* parent =
-    TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial, Nothing());
+    TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, Nothing());
   mTextureMap[aSerial] = parent;
   return parent;
 }
 
 bool
 VideoBridgeParent::DeallocPTextureParent(PTextureParent* actor)
 {
   mTextureMap.erase(TextureHost::GetTextureSerial(actor));
--- a/gfx/layers/ipc/VideoBridgeParent.h
+++ b/gfx/layers/ipc/VideoBridgeParent.h
@@ -24,16 +24,17 @@ public:
   ~VideoBridgeParent();
 
   static VideoBridgeParent* GetSingleton();
   TextureHost* LookupTexture(uint64_t aSerial);
 
   // PVideoBridgeParent
   void ActorDestroy(ActorDestroyReason aWhy) override;
   PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
+                                      const ReadLockDescriptor& aReadLock,
                                       const LayersBackend& aLayersBackend,
                                       const TextureFlags& aFlags,
                                       const uint64_t& aSerial) override;
   bool DeallocPTextureParent(PTextureParent* actor) override;
 
   // HostIPCAllocator
   base::ProcessId GetChildProcessId() override
   {
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -56,17 +56,17 @@ CompositingRenderTargetOGL::BindRenderTa
         mGL->RenewSurface(mCompositor->GetWidget());
         result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
       }
       if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
         nsAutoCString msg;
         msg.AppendPrintf("Framebuffer not complete -- CheckFramebufferStatus returned 0x%x, "
                          "GLContext=%p, IsOffscreen()=%d, mFBO=%d, aFBOTextureTarget=0x%x, "
                          "aRect.width=%d, aRect.height=%d",
-                         result, mGL, mGL->IsOffscreen(), mFBO, mInitParams.mFBOTextureTarget,
+                         result, mGL.get(), mGL->IsOffscreen(), mFBO, mInitParams.mFBOTextureTarget,
                          mInitParams.mSize.width, mInitParams.mSize.height);
         NS_WARNING(msg.get());
       }
     }
 
     needsClear = mClearOnBind;
   }
 
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -180,17 +180,17 @@ private:
 
   InitParams mInitParams;
   /**
    * There is temporary a cycle between the compositor and the render target,
    * each having a strong ref to the other. The compositor's reference to
    * the target is always cleared at the end of a frame.
    */
   RefPtr<CompositorOGL> mCompositor;
-  GLContext* mGL;
+  RefPtr<GLContext> mGL;
   GLuint mTextureHandle;
   GLuint mFBO;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_SURFACEOGL_H */
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -534,29 +534,22 @@ WebRenderBridgeChild::UseTextures(Compos
   }
 
   AutoTArray<TimedTexture,4> textures;
 
   for (auto& t : aTextures) {
     MOZ_ASSERT(t.mTextureClient);
     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
     MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() == GetIPCChannel());
-    ReadLockDescriptor readLock;
-    ReadLockHandle readLockHandle;
-    if (t.mTextureClient->SerializeReadLock(readLock)) {
-      readLockHandle = ReadLockHandle(++mReadLockSequenceNumber);
-      if (mReadLocks.LastElement().Length() >= GetMaxFileDescriptorsPerMessage()) {
-        mReadLocks.AppendElement();
-      }
-      mReadLocks.LastElement().AppendElement(ReadLockInit(readLock, readLockHandle));
-    }
+    bool readLocked = t.mTextureClient->OnForwardedToHost();
+
     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
-                                        readLockHandle,
                                         t.mTimeStamp, t.mPictureRect,
-                                        t.mFrameID, t.mProducerID));
+                                        t.mFrameID, t.mProducerID,
+                                        readLocked));
     GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
   AddWebRenderParentCommand(CompositableOperation(aCompositable->GetIPCHandle(),
                                             OpUseTexture(textures)));
 }
 
 void
 WebRenderBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
--- a/gfx/tests/gtest/TextureHelper.h
+++ b/gfx/tests/gtest/TextureHelper.h
@@ -144,19 +144,20 @@ CreateTextureHostWithBackend(TextureClie
                              LayersBackend& aLayersBackend)
 {
   if (!aClient) {
     return nullptr;
   }
 
   // client serialization
   SurfaceDescriptor descriptor;
+  ReadLockDescriptor readLock = null_t();
   RefPtr<TextureHost> textureHost;
 
   aClient->ToSurfaceDescriptor(descriptor);
 
   wr::MaybeExternalImageId id = Nothing();
-  return TextureHost::Create(descriptor, aDeallocator, aLayersBackend,
+  return TextureHost::Create(descriptor, readLock, aDeallocator, aLayersBackend,
                              aClient->GetFlags(), id);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/ipc/glue/CrossProcessSemaphore.h
+++ b/ipc/glue/CrossProcessSemaphore.h
@@ -73,16 +73,18 @@ public:
    * ShareToProcess
    * This function is called to generate a serializable structure that can
    * be sent to the specified process and opened on the other side.
    *
    * @returns A handle that can be shared to another process
    */
   CrossProcessSemaphoreHandle ShareToProcess(base::ProcessId aTargetPid);
 
+  void CloseHandle();
+
 private:
   friend struct IPC::ParamTraits<CrossProcessSemaphore>;
 
   CrossProcessSemaphore();
   CrossProcessSemaphore(const CrossProcessSemaphore&);
   CrossProcessSemaphore &operator=(const CrossProcessSemaphore&);
 
 #if defined(OS_WIN)
--- a/ipc/glue/CrossProcessSemaphore_posix.cpp
+++ b/ipc/glue/CrossProcessSemaphore_posix.cpp
@@ -71,16 +71,18 @@ CrossProcessSemaphore::Create(CrossProce
   if (!sharedBuffer->SetHandle(aHandle, ipc::SharedMemory::RightsReadWrite)) {
     return nullptr;
   }
 
   if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
     return nullptr;
   }
 
+  sharedBuffer->CloseHandle();
+
   SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->memory());
 
   if (!data) {
     return nullptr;
   }
 
   int32_t oldCount = data->mRefCount++;
   if (oldCount == 0) {
@@ -157,9 +159,15 @@ CrossProcessSemaphore::ShareToProcess(ba
 
   if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aTargetPid, &result)) {
     MOZ_CRASH();
   }
 
   return result;
 }
 
+void
+CrossProcessSemaphore::CloseHandle()
+{
+  mSharedBuffer->CloseHandle();
+}
+
 } // namespace mozilla
--- a/ipc/glue/CrossProcessSemaphore_unimplemented.cpp
+++ b/ipc/glue/CrossProcessSemaphore_unimplemented.cpp
@@ -49,9 +49,15 @@ CrossProcessSemaphore::Signal()
 
 CrossProcessSemaphoreHandle
 CrossProcessSemaphore::ShareToProcess(base::ProcessId aTargetPid)
 {
   MOZ_CRASH("Cross-process semaphores not allowed on this platform - woah! We should've aborted by now!");
   return 0;
 }
 
+void
+CrossProcessSemaphore::CloseHandle()
+{
+  MOZ_CRASH("Cross-process semaphores not allowed on this platform - woah! We should've aborted by now!");
 }
+
+}
--- a/ipc/glue/CrossProcessSemaphore_windows.cpp
+++ b/ipc/glue/CrossProcessSemaphore_windows.cpp
@@ -80,9 +80,14 @@ CrossProcessSemaphore::ShareToProcess(ba
 
   if (!succeeded) {
     return nullptr;
   }
 
   return newHandle;
 }
 
+void
+CrossProcessSemaphore::CloseHandle()
+{
 }
+
+}
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -669,18 +669,19 @@ MessageChannel::CanSend() const
     MonitorAutoLock lock(*mMonitor);
     return Connected();
 }
 
 void
 MessageChannel::WillDestroyCurrentMessageLoop()
 {
 #if defined(DEBUG)
-    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProtocolName"),
-                                       nsDependentCString(mName));
+    CrashReporter::AnnotateCrashReport(
+        NS_LITERAL_CSTRING("IPCFatalErrorProtocol"),
+        nsDependentCString(mName));
     MOZ_CRASH("MessageLoop destroyed before MessageChannel that's bound to it");
 #endif
 
     // Clear mWorkerThread to avoid posting to it in the future.
     MonitorAutoLock lock(*mMonitor);
     mWorkerLoop = nullptr;
 }
 
@@ -694,18 +695,19 @@ MessageChannel::Clear()
     // through this channel after it's Clear()'ed can cause this process to
     // crash.
     //
     // In practice, mListener owns the channel, so the channel gets deleted
     // before mListener.  But just to be safe, mListener is a weak pointer.
 
 #if !defined(ANDROID)
     if (!Unsound_IsClosed()) {
-        CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProtocolName"),
-                                           nsDependentCString(mName));
+        CrashReporter::AnnotateCrashReport(
+            NS_LITERAL_CSTRING("IPCFatalErrorProtocol"),
+            nsDependentCString(mName));
         switch (mChannelState) {
             case ChannelOpening:
                 MOZ_CRASH("MessageChannel destroyed without being closed " \
                           "(mChannelState == ChannelOpening).");
                 break;
             case ChannelConnected:
                 MOZ_CRASH("MessageChannel destroyed without being closed " \
                           "(mChannelState == ChannelConnected).");
rename from js/src/jsarrayinlines.h
rename to js/src/builtin/Array-inl.h
--- a/js/src/jsarrayinlines.h
+++ b/js/src/builtin/Array-inl.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 vm_jsarrayinlines_h
-#define vm_jsarrayinlines_h
+#ifndef builtin_Array_inl_h
+#define builtin_Array_inl_h
 
-#include "jsarray.h"
+#include "builtin/Array.h"
 
 #include "vm/ArgumentsObject.h"
 #include "vm/JSObject.h"
 
 #include "vm/ArgumentsObject-inl.h"
 #include "vm/UnboxedObject-inl.h"
 
 namespace js {
@@ -31,9 +31,9 @@ GetElement(JSContext* cx, HandleObject o
             return true;
     }
 
     return GetElement(cx, obj, obj, index, vp);
 }
 
 } // namespace js
 
-#endif // vm_jsarrayinlines_h
+#endif // builtin_Array_inl_h
rename from js/src/jsarray.cpp
rename to js/src/builtin/Array.cpp
--- a/js/src/jsarray.cpp
+++ b/js/src/builtin/Array.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "jsarrayinlines.h"
+#include "builtin/Array-inl.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/MathAlgorithms.h"
 
 #include <algorithm>
 
rename from js/src/jsarray.h
rename to js/src/builtin/Array.h
--- a/js/src/jsarray.h
+++ b/js/src/builtin/Array.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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/. */
 
 /* JS Array interface. */
 
-#ifndef jsarray_h
-#define jsarray_h
+#ifndef builtin_Array_h
+#define builtin_Array_h
 
 #include "jspubtd.h"
 
 #include "vm/ArrayObject.h"
 #include "vm/JSObject.h"
 
 namespace js {
 /* 2^32-2, inclusive */
@@ -275,9 +275,9 @@ class MOZ_NON_TEMPORARY_CLASS ArraySpeci
     void purge() {
         if (state_ == State::Initialized)
             reset();
     }
 };
 
 } /* namespace js */
 
-#endif /* jsarray_h */
+#endif /* builtin_Array_h */
rename from js/src/jsboolinlines.h
rename to js/src/builtin/Boolean-inl.h
--- a/js/src/jsboolinlines.h
+++ b/js/src/builtin/Boolean-inl.h
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 jsboolinlines_h
-#define jsboolinlines_h
+#ifndef builtin_Boolean_inl_h
+#define builtin_Boolean_inl_h
 
-#include "jsbool.h"
+#include "builtin/Boolean.h"
 
 #include "vm/BooleanObject.h"
 #include "vm/JSContext.h"
 #include "vm/WrapperObject.h"
 
 namespace js {
 
 inline bool
@@ -22,9 +22,9 @@ EmulatesUndefined(JSObject* obj)
     // here as it doesn't escape.
     AutoUnsafeCallWithABI unsafe;
     JSObject* actual = MOZ_LIKELY(!obj->is<WrapperObject>()) ? obj : UncheckedUnwrapWithoutExpose(obj);
     return actual->getClass()->emulatesUndefined();
 }
 
 } /* namespace js */
 
-#endif /* jsboolinlines_h */
+#endif /* builtin_Boolean_inl_h */
rename from js/src/jsbool.cpp
rename to js/src/builtin/Boolean.cpp
--- a/js/src/jsbool.cpp
+++ b/js/src/builtin/Boolean.cpp
@@ -3,17 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * JS boolean implementation.
  */
 
-#include "jsboolinlines.h"
+#include "builtin/Boolean-inl.h"
 
 #include "jsapi.h"
 #include "jstypes.h"
 
 #include "jit/InlinableNatives.h"