Merge autoland to mozilla-central. a=merge
authorOana Pop Rus <opoprus@mozilla.com>
Fri, 29 Mar 2019 23:51:13 +0200
changeset 466808 414f37afbe07fd8e5164daf8fa50b38cb64c83ec
parent 466707 579cc975268f03bcc335f099a25215b87836a4ef (current diff)
parent 466807 bd03a5a96bde1398d881c364c96cc06ec7d30de7 (diff)
child 466830 4526b65c502ed7838db645761c0468d6637c112b
push id35780
push useropoprus@mozilla.com
push dateFri, 29 Mar 2019 21:53:01 +0000
treeherdermozilla-central@414f37afbe07 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central. a=merge
browser/base/content/aboutNetError-new.xhtml
browser/themes/shared/aboutNetError-new.css
browser/themes/shared/incontent-icons/cert-error-new.svg
dom/indexedDB/IDBWrapperCache.cpp
dom/indexedDB/IDBWrapperCache.h
dom/media/webrtc/AllocationHandle.h
ipc/ipdl/test/ipdl/error/managedNoCtor.ipdl
ipc/ipdl/test/ipdl/error/managerNoCtor.ipdl
testing/raptor/raptor/playback/alternate-server-replay.py
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -17,16 +17,17 @@
 #include "xpcAccessibleDocument.h"
 
 #ifdef A11Y_LOG
 #  include "Logging.h"
 #endif
 
 #include "mozilla/Components.h"
 #include "mozilla/EventListenerManager.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Event.h"  // for Event
 #include "nsContentUtils.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIWebNavigation.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIWebProgress.h"
@@ -432,18 +433,20 @@ DocAccessible* DocManager::CreateDocOrRo
   }
 
   nsIWidget* widget = nsContentUtils::WidgetForDocument(aDocument);
   if (!widget || widget->WindowType() == eWindowType_invisible) {
     return nullptr;
   }
 
   // Ignore documents without presshell and not having root frame.
-  nsIPresShell* presShell = aDocument->GetShell();
-  if (!presShell || presShell->IsDestroying()) return nullptr;
+  PresShell* presShell = aDocument->GetPresShell();
+  if (!presShell || presShell->IsDestroying()) {
+    return nullptr;
+  }
 
   bool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);
 
   DocAccessible* parentDocAcc = nullptr;
   if (!isRootDoc) {
     // XXXaaronl: ideally we would traverse the presshell chain. Since there's
     // no easy way to do that, we cheat and use the document hierarchy.
     parentDocAcc = GetDocAccessible(aDocument->GetParentDocument());
--- a/accessible/base/DocManager.h
+++ b/accessible/base/DocManager.h
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11_DocManager_h_
 #define mozilla_a11_DocManager_h_
 
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Document.h"
 #include "nsIDOMEventListener.h"
 #include "nsRefPtrHashtable.h"
 #include "nsIWebProgressListener.h"
 #include "nsWeakReference.h"
 #include "nsIPresShell.h"
 #include "mozilla/StaticPtr.h"
 
@@ -178,16 +179,16 @@ class DocManager : public nsIWebProgress
 };
 
 /**
  * Return the existing document accessible for the document if any.
  * Note this returns the doc accessible for the primary pres shell if there is
  * more than one.
  */
 inline DocAccessible* GetExistingDocAccessible(const dom::Document* aDocument) {
-  nsIPresShell* ps = aDocument->GetShell();
-  return ps ? ps->GetDocAccessible() : nullptr;
+  PresShell* presShell = aDocument->GetPresShell();
+  return presShell ? presShell->GetDocAccessible() : nullptr;
 }
 
 }  // namespace a11y
 }  // namespace mozilla
 
 #endif  // mozilla_a11_DocManager_h_
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -17,16 +17,17 @@
 #include "nsIChannel.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsISelectionController.h"
 #include "nsTraceRefcnt.h"
 #include "nsIWebProgress.h"
 #include "prenv.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIURI.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/Selection.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -159,23 +160,23 @@ static void LogDocState(dom::Document* a
   dom::Element* rootEl = aDocumentNode->GetBodyElement();
   if (!rootEl) {
     rootEl = aDocumentNode->GetRootElement();
   }
   printf(", has %srole content", rootEl ? "" : "no ");
 }
 
 static void LogPresShell(dom::Document* aDocumentNode) {
-  nsIPresShell* ps = aDocumentNode->GetShell();
-  printf("presshell: %p", static_cast<void*>(ps));
+  PresShell* presShell = aDocumentNode->GetPresShell();
+  printf("presshell: %p", static_cast<void*>(presShell));
 
   nsIScrollableFrame* sf = nullptr;
-  if (ps) {
-    printf(", is %s destroying", (ps->IsDestroying() ? "" : "not"));
-    sf = ps->GetRootScrollFrameAsScrollable();
+  if (presShell) {
+    printf(", is %s destroying", (presShell->IsDestroying() ? "" : "not"));
+    sf = presShell->GetRootScrollFrameAsScrollable();
   }
   printf(", root scroll frame: %p", static_cast<void*>(sf));
 }
 
 static void LogDocLoadGroup(dom::Document* aDocumentNode) {
   nsCOMPtr<nsILoadGroup> loadGroup = aDocumentNode->GetDocumentLoadGroup();
   printf("load group: %p", static_cast<void*>(loadGroup));
 }
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -67,16 +67,17 @@
 #include "nsTreeUtils.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsXBLBinding.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/HTMLTableElement.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/Services.h"
 #include "nsDeckFrame.h"
 
 #ifdef MOZ_XUL
 #  include "XULAlertAccessible.h"
 #  include "XULComboboxAccessible.h"
 #  include "XULElementAccessibles.h"
 #  include "XULFormControlAccessible.h"
@@ -367,19 +368,19 @@ class PluginTimerCallBack final : public
  public:
   explicit PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Notify(nsITimer* aTimer) final {
     if (!mContent->IsInUncomposedDoc()) return NS_OK;
 
-    nsIPresShell* ps = mContent->OwnerDoc()->GetShell();
-    if (ps) {
-      DocAccessible* doc = ps->GetDocAccessible();
+    PresShell* presShell = mContent->OwnerDoc()->GetPresShell();
+    if (presShell) {
+      DocAccessible* doc = presShell->GetDocAccessible();
       if (doc) {
         // Make sure that if we created an accessible for the plugin that wasn't
         // a plugin accessible we remove it before creating the right
         // accessible.
         doc->RecreateAccessible(mContent);
         sPluginTimers->RemoveElement(aTimer);
         return NS_OK;
       }
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -9,26 +9,26 @@
 
 #include "nsIBaseWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "mozilla/dom/Document.h"
 #include "nsRange.h"
 #include "nsXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIObserverService.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsISelectionController.h"
 #include "nsISimpleEnumerator.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TouchEvents.h"
 #include "nsView.h"
 #include "nsGkAtoms.h"
 
 #include "nsComponentManagerUtils.h"
 
 #include "XULTreeElement.h"
 #include "nsTreeColumns.h"
@@ -65,18 +65,20 @@ void nsCoreUtils::DispatchClickEvent(XUL
                                      nsTreeColumn *aColumn,
                                      const nsAString &aPseudoElt) {
   RefPtr<dom::Element> tcElm = aTree->GetTreeBody();
   if (!tcElm) return;
 
   Document *document = tcElm->GetUncomposedDoc();
   if (!document) return;
 
-  nsCOMPtr<nsIPresShell> presShell = document->GetShell();
-  if (!presShell) return;
+  RefPtr<PresShell> presShell = document->GetPresShell();
+  if (!presShell) {
+    return;
+  }
 
   // Ensure row is visible.
   aTree->EnsureRowIsVisible(aRowIndex);
 
   // Calculate x and y coordinates.
   nsresult rv;
   nsIntRect rect =
       aTree->GetCoordsForCellItem(aRowIndex, aColumn, aPseudoElt, rv);
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -2,21 +2,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
 #include "mozilla/EventForwards.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Element.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIContent.h"
-#include "mozilla/dom/Document.h"  // for GetShell()
-#include "nsIPresShell.h"
+#include "mozilla/dom/Document.h"  // for GetPresShell()
 
 #include "nsPoint.h"
 #include "nsTArray.h"
 
 class nsRange;
 class nsTreeColumn;
 class nsIFrame;
 class nsIDocShell;
@@ -208,17 +208,17 @@ class nsCoreUtils {
    * Return true if the given document is an error page.
    */
   static bool IsErrorPage(Document *aDocument);
 
   /**
    * Return presShell for the document containing the given DOM node.
    */
   static nsIPresShell *GetPresShellFor(nsINode *aNode) {
-    return aNode->OwnerDoc()->GetShell();
+    return aNode->OwnerDoc()->GetPresShell();
   }
 
   /**
    * Get the ID for an element, in some types of XML this may not be the ID
    * attribute
    * @param aContent  Node to get the ID for
    * @param aID       Where to put ID string
    * @return          true if there is an ID set for this node
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -25,29 +25,29 @@
 #include "nsIDocShell.h"
 #include "mozilla/dom/Document.h"
 #include "nsPIDOMWindow.h"
 #include "nsIEditingSession.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsImageFrame.h"
 #include "nsIPersistentProperties2.h"
-#include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/HTMLEditor.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/MutationEventBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -461,18 +461,20 @@ nsIFrame* DocAccessible::GetFrame() cons
 nsRect DocAccessible::RelativeBounds(nsIFrame** aRelativeFrame) const {
   *aRelativeFrame = GetFrame();
 
   dom::Document* document = mDocumentNode;
   dom::Document* parentDoc = nullptr;
 
   nsRect bounds;
   while (document) {
-    nsIPresShell* presShell = document->GetShell();
-    if (!presShell) return nsRect();
+    mozilla::PresShell* presShell = document->GetPresShell();
+    if (!presShell) {
+      return nsRect();
+    }
 
     nsRect scrollPort;
     nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
     if (sf) {
       scrollPort = sf->GetScrollPortRect();
     } else {
       nsIFrame* rootFrame = presShell->GetRootFrame();
       if (!rootFrame) return nsRect();
--- a/browser/actors/NetErrorChild.jsm
+++ b/browser/actors/NetErrorChild.jsm
@@ -19,18 +19,16 @@ XPCOMUtils.defineLazyGlobalGetters(this,
 XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
 
 XPCOMUtils.defineLazyGetter(this, "gPipNSSBundle", function() {
   return Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
 });
 XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
   return Services.strings.createBundle("chrome://branding/locale/brand.properties");
 });
-XPCOMUtils.defineLazyPreferenceGetter(this, "newErrorPagesEnabled",
-  "browser.security.newcerterrorpage.enabled");
 XPCOMUtils.defineLazyPreferenceGetter(this, "mitmErrorPageEnabled",
   "browser.security.newcerterrorpage.mitm.enabled");
 XPCOMUtils.defineLazyPreferenceGetter(this, "mitmPrimingEnabled",
   "security.certerrors.mitm.priming.enabled");
 XPCOMUtils.defineLazyGetter(this, "gNSSErrorsBundle", function() {
   return Services.strings.createBundle("chrome://pipnss/locale/nsserrors.properties");
 });
 
@@ -123,40 +121,34 @@ class NetErrorChild extends ActorChild {
 
     let msg1 = gPipNSSBundle.formatStringFromName("certErrorIntro",
                                                   [hostString], 1);
     msg1 += "\n\n";
 
     if (input.data.certIsUntrusted) {
       switch (input.data.code) {
         case MOZILLA_PKIX_ERROR_MITM_DETECTED:
-          if (newErrorPagesEnabled && mitmErrorPageEnabled) {
+          if (mitmErrorPageEnabled) {
             let brandName = gBrandBundle.GetStringFromName("brandShortName");
             msg1 = gPipNSSBundle.GetStringFromName("certErrorMitM");
             msg1 += "\n\n";
             msg1 += gPipNSSBundle.formatStringFromName("certErrorMitM2", [brandName], 1);
             msg1 += "\n\n";
             msg1 += gPipNSSBundle.formatStringFromName("certErrorMitM3", [brandName], 1);
             msg1 += "\n";
             break;
           }
           // If the condition is false, fall through...
         case SEC_ERROR_UNKNOWN_ISSUER:
           let brandName = gBrandBundle.GetStringFromName("brandShortName");
-          if (newErrorPagesEnabled) {
-            msg1 = "";
-            msg1 += gPipNSSBundle.formatStringFromName("certErrorTrust_UnknownIssuer4", [hostString], 1);
-            msg1 += "\n\n";
-            msg1 += gPipNSSBundle.formatStringFromName("certErrorTrust_UnknownIssuer6", [brandName, hostString], 2);
-            msg1 += "\n\n";
-          } else {
-            msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer") + "\n";
-            msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer2") + "\n";
-            msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_UnknownIssuer3") + "\n";
-          }
+          msg1 = "";
+          msg1 += gPipNSSBundle.formatStringFromName("certErrorTrust_UnknownIssuer4", [hostString], 1);
+          msg1 += "\n\n";
+          msg1 += gPipNSSBundle.formatStringFromName("certErrorTrust_UnknownIssuer6", [brandName, hostString], 2);
+          msg1 += "\n\n";
           break;
         case SEC_ERROR_CA_CERT_INVALID:
           msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_CaInvalid") + "\n";
           break;
         case SEC_ERROR_UNTRUSTED_ISSUER:
           msg1 += gPipNSSBundle.GetStringFromName("certErrorTrust_Issuer") + "\n";
           break;
         case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
@@ -185,24 +177,20 @@ class NetErrorChild extends ActorChild {
       let numSubjectAltNames = subjectAltNames.length;
 
       subjectAltNames = subjectAltNames.filter(name => name.length > 0);
       numSubjectAltNames = subjectAltNames.length;
 
       let msgPrefix = "";
       if (numSubjectAltNames != 0) {
         if (numSubjectAltNames == 1) {
-          if (newErrorPagesEnabled) {
-            technicalInfo.textContent = "";
-            let brandName = gBrandBundle.GetStringFromName("brandShortName");
-            msgPrefix = gPipNSSBundle.formatStringFromName("certErrorMismatchSinglePrefix3", [brandName, hostString], 2) + " ";
-            msgPrefix += gPipNSSBundle.GetStringFromName("certErrorMismatchSinglePrefix");
-          } else {
-            msgPrefix = gPipNSSBundle.GetStringFromName("certErrorMismatchSinglePrefix");
-          }
+          technicalInfo.textContent = "";
+          let brandName = gBrandBundle.GetStringFromName("brandShortName");
+          msgPrefix = gPipNSSBundle.formatStringFromName("certErrorMismatchSinglePrefix3", [brandName, hostString], 2) + " ";
+          msgPrefix += gPipNSSBundle.GetStringFromName("certErrorMismatchSinglePrefix");
           // Let's check if we want to make this a link.
           let okHost = input.data.certSubjectAltNames;
           let href = "";
           let thisHost = doc.location.hostname;
           let proto = doc.location.protocol + "//";
           // If okHost is a wildcard domain ("*.example.com") let's
           // use "www" instead.  "*.example.com" isn't going to
           // get anyone anywhere useful. bug 432491
@@ -259,88 +247,57 @@ class NetErrorChild extends ActorChild {
             let fragment = BrowserUtils.getLocalizedFragment(doc,
                                                              msgPrefix,
                                                              input.data.certSubjectAltNames);
             technicalInfo.appendChild(fragment);
           }
           technicalInfo.append("\n");
         } else {
           let msg = "";
-          if (newErrorPagesEnabled) {
-            technicalInfo.textContent = "";
-            let brandName = gBrandBundle.GetStringFromName("brandShortName");
-            msg = gPipNSSBundle.formatStringFromName("certErrorMismatchMultiple3", [brandName, hostString], 2) + " ";
-          } else {
-            msg = gPipNSSBundle.GetStringFromName("certErrorMismatchMultiple") + "\n";
-          }
+          technicalInfo.textContent = "";
+          let brandName = gBrandBundle.GetStringFromName("brandShortName");
+          msg = gPipNSSBundle.formatStringFromName("certErrorMismatchMultiple3", [brandName, hostString], 2) + " ";
           for (let i = 0; i < numSubjectAltNames; i++) {
             msg += subjectAltNames[i];
             if (i != (numSubjectAltNames - 1)) {
               msg += ", ";
             }
           }
           technicalInfo.append(msg + "\n");
         }
       } else {
         let msg = "";
-        if (newErrorPagesEnabled) {
-          technicalInfo.textContent = "";
-          let brandName = gBrandBundle.GetStringFromName("brandShortName");
-          msg = gPipNSSBundle.formatStringFromName("certErrorMismatch3", [brandName, hostString], 2) + " ";
-        } else {
-          msg = gPipNSSBundle.formatStringFromName("certErrorMismatch",
-                                                     [hostString], 1);
-        }
+        technicalInfo.textContent = "";
+        let brandName = gBrandBundle.GetStringFromName("brandShortName");
+        msg = gPipNSSBundle.formatStringFromName("certErrorMismatch3", [brandName, hostString], 2) + " ";
         technicalInfo.append(msg + "\n");
       }
     }
 
     if (input.data.isNotValidAtThisTime) {
       let nowTime = new Date().getTime() * 1000;
-      let dateOptions = { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" };
-      let now = new Services.intl.DateTimeFormat(undefined, dateOptions).format(new Date());
       let msg = "";
       if (input.data.validity.notBefore) {
         if (nowTime > input.data.validity.notAfter) {
-          if (newErrorPagesEnabled) {
-            technicalInfo.textContent = "";
-            msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow2",
-                                                    [hostString], 1);
-            msg += "\n";
-          } else {
-            msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow",
-                                                      [input.data.validity.notAfterLocalTime, now], 2);
-            msg += "\n";
-          }
+          technicalInfo.textContent = "";
+          msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow2",
+                                                  [hostString], 1);
+          msg += "\n";
         } else {
-          // eslint-disable-next-line no-lonely-if
-          if (newErrorPagesEnabled) {
-            technicalInfo.textContent = "";
-            msg += gPipNSSBundle.formatStringFromName("certErrorNotYetValidNow2",
-                                                      [hostString], 1);
-            msg += "\n";
-          } else {
-            msg += gPipNSSBundle.formatStringFromName("certErrorNotYetValidNow",
-                                                      [input.data.validity.notBeforeLocalTime, now], 2);
-            msg += "\n";
-          }
+          technicalInfo.textContent = "";
+          msg += gPipNSSBundle.formatStringFromName("certErrorNotYetValidNow2",
+                                                    [hostString], 1);
+          msg += "\n";
          }
         } else {
-        // If something goes wrong, we assume the cert expired.
-        // eslint-disable-next-line no-lonely-if
-          if (newErrorPagesEnabled) {
-            technicalInfo.textContent = "";
-            msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow2",
-                                                      [hostString], 1);
-            msg += "\n";
-          } else {
-            msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow",
-                                                      ["", now], 2);
-            msg += "\n";
-          }
+          // If something goes wrong, we assume the cert expired.
+          technicalInfo.textContent = "";
+          msg += gPipNSSBundle.formatStringFromName("certErrorExpiredNow2",
+                                                    [hostString], 1);
+          msg += "\n";
       }
       technicalInfo.append(msg);
     }
     technicalInfo.append("\n");
 
     // Add link to certificate and error message.
     let linkPrefix = gPipNSSBundle.GetStringFromName("certErrorCodePrefix3");
     let detailLink = doc.createElement("a");
@@ -382,18 +339,17 @@ class NetErrorChild extends ActorChild {
           textContainer.style.marginTop = `${offset}px`;
         }
       }
     }
 
     // Check if the connection is being man-in-the-middled. When the parent
     // detects an intercepted connection, the page may be reloaded with a new
     // error code (MOZILLA_PKIX_ERROR_MITM_DETECTED).
-    if (newErrorPagesEnabled && mitmPrimingEnabled &&
-        msg.data.code == SEC_ERROR_UNKNOWN_ISSUER &&
+    if (mitmPrimingEnabled && msg.data.code == SEC_ERROR_UNKNOWN_ISSUER &&
         // Only do this check for top-level failures.
         doc.ownerGlobal.top === doc.ownerGlobal) {
       this.mm.sendAsyncMessage("Browser:PrimeMitm");
     }
 
     let div = doc.getElementById("certificateErrorText");
     div.textContent = msg.data.info;
     this._setTechDetails(msg, doc);
@@ -428,19 +384,16 @@ class NetErrorChild extends ActorChild {
     // Need to do this here (which is not exactly at load but a few ticks later),
     // because this is the first time we have access to the error code.
     this.recordLoadEvent(doc);
 
     switch (msg.data.code) {
       case SSL_ERROR_BAD_CERT_DOMAIN:
       case SEC_ERROR_OCSP_INVALID_SIGNING_CERT:
       case SEC_ERROR_UNKNOWN_ISSUER:
-        if (!newErrorPagesEnabled) {
-          break;
-        }
         if (es) {
           // eslint-disable-next-line no-unsanitized/property
           es.innerHTML = errWhatToDo.innerHTML;
         }
         if (est) {
           // eslint-disable-next-line no-unsanitized/property
           est.innerHTML = errWhatToDoTitle.innerHTML;
         }
@@ -463,17 +416,17 @@ class NetErrorChild extends ActorChild {
           gPipNSSBundle.GetStringFromName("certErrorSymantecDistrustAdministrator");
         descriptionContainer.append(adminDescription);
 
         learnMoreLink.href = baseURL + "symantec-warning";
 
         updateContainerPosition();
         break;
       case MOZILLA_PKIX_ERROR_MITM_DETECTED:
-        if (newErrorPagesEnabled && mitmErrorPageEnabled) {
+        if (mitmErrorPageEnabled) {
           let autoEnabledEnterpriseRoots =
             Services.prefs.getBoolPref("security.enterprise_roots.auto-enabled", false);
           if (mitmPrimingEnabled && autoEnabledEnterpriseRoots) {
             // If we automatically tried to import enterprise root certs but it didn't
             // fix the MITM, reset the pref.
             this.mm.sendAsyncMessage("Browser:ResetEnterpriseRootsPref");
           }
 
@@ -570,19 +523,17 @@ class NetErrorChild extends ActorChild {
             clockSkew = true;
 
             doc.getElementById("wrongSystemTimeWithoutReference_URL")
               .textContent = doc.location.hostname;
             doc.getElementById("wrongSystemTimeWithoutReference_systemDate")
               .textContent = formatter.format(systemDate);
           }
         }
-        if (!newErrorPagesEnabled) {
-          break;
-        }
+
         let systemDate = formatter.format(new Date());
         doc.getElementById("wrongSystemTime_systemDate1").textContent = systemDate;
         if (clockSkew) {
           doc.body.classList.add("illustrated", "clockSkewError");
           let clockErrTitle = doc.getElementById("et_clockSkewError");
           let clockErrDesc = doc.getElementById("ed_clockSkewError");
           // eslint-disable-next-line no-unsanitized/property
           doc.querySelector(".title-text").textContent = clockErrTitle.textContent;
@@ -635,28 +586,26 @@ class NetErrorChild extends ActorChild {
           }
           updateContainerPosition();
         }
         break;
     }
 
     // Add slightly more alarming UI unless there are indicators that
     // show that the error is harmless or can not be skipped anyway.
-    if (newErrorPagesEnabled) {
-      let {cssClass} = this.getParams(doc);
-      // Don't alarm users when they can't continue to the website anyway...
-      if (cssClass != "badStsCert" &&
-          // Errors in iframes can't be skipped either...
-          doc.ownerGlobal.parent == doc.ownerGlobal &&
-          // Also don't bother if it's just the user's clock being off...
-          !clockSkew &&
-          // Symantec distrust is likely harmless as well.
-          msg.data.code != MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED) {
-        doc.body.classList.add("caution");
-      }
+    let {cssClass} = this.getParams(doc);
+    // Don't alarm users when they can't continue to the website anyway...
+    if (cssClass != "badStsCert" &&
+        // Errors in iframes can't be skipped either...
+        doc.ownerGlobal.parent == doc.ownerGlobal &&
+        // Also don't bother if it's just the user's clock being off...
+        !clockSkew &&
+        // Symantec distrust is likely harmless as well.
+        msg.data.code != MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED) {
+      doc.body.classList.add("caution");
     }
   }
 
   handleEvent(aEvent) {
     // Documents have a null ownerDocument.
     let doc = aEvent.originalTarget.ownerDocument || aEvent.originalTarget;
 
     switch (aEvent.type) {
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -963,19 +963,16 @@ pref("app.feedback.baseURL", "https://in
 #endif
 
 // base URL for web-based marketing pages
 pref("app.productInfo.baseURL", "https://www.mozilla.org/firefox/features/");
 
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
-// Enable the new certificate error pages.
-pref("browser.security.newcerterrorpage.enabled", true);
-
 pref("browser.security.newcerterrorpage.mitm.enabled", true);
 pref("security.certerrors.recordEventTelemetry", true);
 pref("security.certerrors.permanentOverride", true);
 pref("security.certerrors.mitm.priming.enabled", true);
 pref("security.certerrors.mitm.priming.endpoint", "https://mitmdetection.services.mozilla.com/");
 pref("security.certerrors.mitm.auto_enable_enterprise_roots", false);
 
 // Whether to start the private browsing mode at application startup
--- a/browser/app/winlauncher/LauncherProcessWin.cpp
+++ b/browser/app/winlauncher/LauncherProcessWin.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/CmdLineAndEnvUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/DynamicallyLinkedFunctionPtr.h"
 #include "mozilla/glue/Debug.h"
 #include "mozilla/LauncherResult.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/SafeMode.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/WindowsConsole.h"
 #include "mozilla/WindowsVersion.h"
 #include "mozilla/WinHeaderOnlyUtils.h"
 #include "nsWindowsHelpers.h"
 
 #include <windows.h>
 #include <processthreadsapi.h>
 
 #include "DllBlocklistWin.h"
@@ -214,16 +215,18 @@ Maybe<int> LauncherMain(int& argc, wchar
       imgLoadPol.PreferSystem32Images = 1;
 
       DebugOnly<BOOL> setOk = pSetProcessMitigationPolicy(
           ProcessImageLoadPolicy, &imgLoadPol, sizeof(imgLoadPol));
       MOZ_ASSERT(setOk);
     }
   }
 
+  mozilla::UseParentConsole();
+
   if (!SetArgv0ToFullBinaryPath(argv)) {
     HandleLauncherError(LAUNCHER_ERROR_GENERIC());
     return Nothing();
   }
 
   LauncherFlags flags = ProcessCmdLine(argc, argv);
 
   nsAutoHandle mediumIlToken;
--- a/browser/app/winlauncher/moz.build
+++ b/browser/app/winlauncher/moz.build
@@ -26,13 +26,14 @@ OS_LIBS += [
 
 TEST_DIRS += [
     'test',
 ]
 
 if CONFIG['MOZ_LAUNCHER_PROCESS']:
     UNIFIED_SOURCES += [
         '/toolkit/xre/LauncherRegistryInfo.cpp',
+        '/widget/windows/WindowsConsole.cpp',
     ]
     for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
         DEFINES[var] = '"%s"' % CONFIG[var]
 
 DisableStlWrapping()
deleted file mode 100644
--- a/browser/base/content/aboutNetError-new.xhtml
+++ /dev/null
@@ -1,237 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!DOCTYPE html [
-  <!ENTITY % htmlDTD
-    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "DTD/xhtml1-strict.dtd">
-  %htmlDTD;
-  <!ENTITY % netErrorDTD
-    SYSTEM "chrome://browser/locale/netError.dtd">
-  %netErrorDTD;
-  <!ENTITY % globalDTD
-    SYSTEM "chrome://global/locale/global.dtd">
-  %globalDTD;
-]>
-
-<!-- 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/. -->
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
-    <title>&loadError.label;</title>
-    <link rel="stylesheet" href="chrome://browser/skin/aboutNetError-new.css" type="text/css" media="all" />
-    <!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
-         toolkit/components/places/src/nsFaviconService.h should be updated. -->
-    <link rel="icon" id="favicon" href="chrome://global/skin/icons/warning.svg"/>
-  </head>
-
-  <body data-new-error-pages-enabled="true" dir="&locale.dir;">
-    <!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
-    <div id="errorContainer">
-      <div id="errorPageTitlesContainer">
-        <span id="ept_nssBadCert">&certerror.pagetitle2;</span>
-        <span id="ept_nssBadCert_sts">&certerror.sts.pagetitle;</span>
-        <span id="ept_captivePortal">&captivePortal.title;</span>
-        <span id="ept_dnsNotFound">&dnsNotFound.pageTitle;</span>
-        <span id="ept_malformedURI">&malformedURI.pageTitle;</span>
-        <span id="ept_blockedByPolicy">&blockedByPolicy.title;</span>
-      </div>
-      <div id="errorTitlesContainer">
-        <h1 id="et_generic">&generic.title;</h1>
-        <h1 id="et_captivePortal">&captivePortal.title;</h1>
-        <h1 id="et_dnsNotFound">&dnsNotFound.title1;</h1>
-        <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
-        <h1 id="et_fileAccessDenied">&fileAccessDenied.title;</h1>
-        <h1 id="et_malformedURI">&malformedURI.title1;</h1>
-        <h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
-        <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
-        <h1 id="et_netTimeout">&netTimeout.title;</h1>
-        <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
-        <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
-        <h1 id="et_netReset">&netReset.title;</h1>
-        <h1 id="et_notCached">&notCached.title;</h1>
-        <h1 id="et_netOffline">&netOffline.title;</h1>
-        <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
-        <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
-        <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
-        <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
-        <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
-        <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
-        <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
-        <h1 id="et_nssBadCert">&certerror.longpagetitle2;</h1>
-        <h1 id="et_nssBadCert_sts">&certerror.sts.longpagetitle;</h1>
-        <h1 id="et_cspBlocked">&cspBlocked.title;</h1>
-        <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
-        <h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
-        <h1 id="et_sslv3Used">&sslv3Used.title;</h1>
-        <h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
-        <h1 id="et_blockedByPolicy">&blockedByPolicy.title;</h1>
-        <h1 id="et_mitm">&certerror.mitm.title;</h1>
-        <h1 id="et_clockSkewError">&clockSkewError.title;</h1>
-        <h1 id="et_networkProtocolError">&networkProtocolError.title;</h1>
-      </div>
-      <div id="errorDescriptionsContainer">
-        <div id="ed_generic">&generic.longDesc;</div>
-        <div id="ed_captivePortal">&captivePortal.longDesc2;</div>
-        <div id="ed_dnsNotFound">&dnsNotFound.longDesc1;</div>
-        <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
-        <div id="ed_fileAccessDenied">&fileAccessDenied.longDesc;</div>
-        <div id="ed_malformedURI"></div>
-        <div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
-        <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
-        <div id="ed_netTimeout">&netTimeout.longDesc;</div>
-        <div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
-        <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
-        <div id="ed_netReset">&netReset.longDesc;</div>
-        <div id="ed_notCached">&notCached.longDesc;</div>
-        <div id="ed_netOffline">&netOffline.longDesc2;</div>
-        <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
-        <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
-        <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
-        <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
-        <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
-        <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
-        <div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
-        <div id="ed_nssBadCert">&certerror.introPara2;</div>
-        <div id="ed_nssBadCert_sts">&certerror.sts.introPara;</div>
-        <div id="ed_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.introPara;</div>
-        <div id="ed_mitm">&certerror.mitm.longDesc;</div>
-        <div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
-        <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
-        <div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
-        <div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
-        <div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>
-        <div id="ed_blockedByPolicy"></div>
-        <div id="ed_clockSkewError">&clockSkewError.longDesc;</div>
-        <div id="ed_networkProtocolError">&networkProtocolError.longDesc;</div>
-      </div>
-      <div id="errorDescriptions2Container">
-          <div id="ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.secondPara2;</div>
-          <div id="ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE_sts">&certerror.expiredCert.sts.secondPara;</div>
-      </div>
-      <div id="whatCanYouDoAboutItTitleContainer">
-        <div id="edd_nssBadCert"><strong>&certerror.whatCanYouDoAboutItTitle;</strong></div>
-      </div>
-      <div id="whatCanYouDoAboutItContainer">
-        <div id="es_nssBadCert_SEC_ERROR_UNKNOWN_ISSUER">&certerror.unknownIssuer.whatCanYouDoAboutIt;</div>
-        <div id="es_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
-        <div id="es_nssBadCert_SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
-        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
-        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
-        <div id="es_nssBadCert_SSL_ERROR_BAD_CERT_DOMAIN">&certerror.badCertDomain.whatCanYouDoAboutIt;</div>
-        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_MITM_DETECTED">
-          <ul>
-            <li>&certerror.mitm.whatCanYouDoAboutIt1;</li>
-            <li>&certerror.mitm.whatCanYouDoAboutIt2;</li>
-            <li id="mitmWhatCanYouDoAboutIt3">&certerror.mitm.whatCanYouDoAboutIt3;</li>
-          </ul>
-        </div>
-      </div>
-      <!-- Stores an alternative text for when we don't want to add "Recommended" to the
-           return button. This is one of many l10n atrocities in this file and should be
-           removed when we finally switch to Fluent. -->
-      <span id="stsReturnButtonText">&returnToPreviousPage.label;</span>
-      <span id="stsMitmWhatCanYouDoAboutIt3">&certerror.mitm.sts.whatCanYouDoAboutIt3;</span>
-    </div>
-
-    <!-- PAGE CONTAINER (for styling purposes only) -->
-    <div id="errorPageContainer" class="container">
-      <div id="text-container">
-        <!-- Error Title -->
-        <div class="title">
-          <h1 class="title-text"/>
-        </div>
-
-        <!-- LONG CONTENT (the section most likely to require scrolling) -->
-        <div id="errorLongContent">
-
-          <!-- Short Description -->
-          <div id="errorShortDesc">
-            <p id="errorShortDescText" />
-          </div>
-
-          <div id="errorShortDesc2">
-              <p id="errorShortDescText2" />
-          </div>
-
-          <div id="errorWhatToDoTitle">
-              <p id="errorWhatToDoTitleText" />
-          </div>
-
-          <div id="errorWhatToDo">
-              <p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation1;</p>
-              <p id="errorWhatToDoText" />
-          </div>
-
-          <div id="errorWhatToDo2">
-              <p id="errorWhatToDoText2" />
-              <p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation1;</p>
-          </div>
-
-          <div id="wrongSystemTimePanel">
-            &certerror.wrongSystemTime2;
-          </div>
-
-          <div id="wrongSystemTimeWithoutReferencePanel">
-            &certerror.wrongSystemTimeWithoutReference;
-          </div>
-
-          <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
-          <div id="errorLongDesc" />
-
-          <div id="learnMoreContainer">
-            <p><a id="learnMoreLink" target="new" data-telemetry-id="learn_more_link">&errorReporting.learnMore;</a></p>
-          </div>
-        </div>
-
-        <!-- UI for option to report certificate errors to Mozilla. Removed on
-             init for other error types .-->
-        <div id="prefChangeContainer" class="button-container">
-          <p>&prefReset.longDesc;</p>
-          <button id="prefResetButton" class="primary">&prefReset.label;</button>
-        </div>
-
-        <div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
-          <button id="returnButton" class="primary" data-telemetry-id="return_button_top">&returnToPreviousPage1.label;</button>
-          <button id="openPortalLoginPageButton" class="primary">&openPortalLoginPage.label2;</button>
-          <button id="errorTryAgain" class="primary">&retry.label;</button>
-          <button id="advancedButton" data-telemetry-id="advanced_button">&advanced2.label;</button>
-        </div>
-      </div>
-
-      <div id="netErrorButtonContainer" class="button-container">
-        <button id="errorTryAgain" class="primary">&retry.label;</button>
-      </div>
-
-      <div id="advancedPanelContainer">
-        <div id="badCertAdvancedPanel" class="advanced-panel">
-          <p id="badCertTechnicalInfo"/>
-          <a id="viewCertificate" href="javascript:void(0)">&viewCertificate.label;</a>
-          <div id="advancedPanelButtonContainer" class="button-container">
-            <button id="advancedPanelReturnButton" class="primary" data-telemetry-id="return_button_adv">&returnToPreviousPage1.label;</button>
-            <button id="advancedPanelErrorTryAgain" class="primary">&retry.label;</button>
-            <div class="exceptionDialogButtonContainer">
-              <button id="exceptionDialogButton" data-telemetry-id="exception_button">&securityOverride.exceptionButton1Label;</button>
-            </div>
-          </div>
-        </div>
-
-        <div id="certificateErrorReporting">
-            <p class="toggle-container-with-text">
-                <input type="checkbox" id="automaticallyReportInFuture" role="checkbox" data-telemetry-id="auto_report_cb"/>
-                <label for="automaticallyReportInFuture">&errorReporting.automatic2;</label>
-            </p>
-        </div>
-
-        <div id="certificateErrorDebugInformation">
-          <button id="copyToClipboard" data-telemetry-id="clipboard_button_top">&certerror.copyToClipboard.label;</button>
-          <div id="certificateErrorText"/>
-          <button id="copyToClipboard" data-telemetry-id="clipboard_button_bot">&certerror.copyToClipboard.label;</button>
-        </div>
-      </div>
-    </div>
-  </body>
-  <script type="application/javascript" src="chrome://browser/content/aboutNetError.js"/>
-</html>
--- a/browser/base/content/aboutNetError.js
+++ b/browser/base/content/aboutNetError.js
@@ -10,17 +10,16 @@
 // document.location.href gets the current URI off the docshell,
 // which is the URL displayed in the location bar, i.e.
 // the URI that the user attempted to load.
 
 let searchParams = new URLSearchParams(document.documentURI.split("?")[1]);
 
 // Set to true on init if the error code is nssBadCert.
 let gIsCertError;
-let gNewErrorPagesEnabled;
 
 function getErrorCode() {
   return searchParams.get("e");
 }
 
 function getCSSClass() {
   return searchParams.get("s");
 }
@@ -124,26 +123,24 @@ function disallowCertOverridesIfNeeded()
   // host and the cert is bad (STS Spec section 7.3) or if the
   // certerror is in a frame (bug 633691).
   if (cssClass == "badStsCert" || window != top) {
     document.getElementById("exceptionDialogButton").setAttribute("hidden", "true");
   }
   if (cssClass == "badStsCert") {
     document.getElementById("badStsCertExplanation").removeAttribute("hidden");
 
-    if (gNewErrorPagesEnabled) {
-      let stsReturnButtonText = document.getElementById("stsReturnButtonText").textContent;
-      document.getElementById("returnButton").textContent = stsReturnButtonText;
-      document.getElementById("advancedPanelReturnButton").textContent = stsReturnButtonText;
+    let stsReturnButtonText = document.getElementById("stsReturnButtonText").textContent;
+    document.getElementById("returnButton").textContent = stsReturnButtonText;
+    document.getElementById("advancedPanelReturnButton").textContent = stsReturnButtonText;
 
-      let stsMitmWhatCanYouDoAboutIt3 =
-        document.getElementById("stsMitmWhatCanYouDoAboutIt3").innerHTML;
-      // eslint-disable-next-line no-unsanitized/property
-      document.getElementById("mitmWhatCanYouDoAboutIt3").innerHTML = stsMitmWhatCanYouDoAboutIt3;
-    }
+    let stsMitmWhatCanYouDoAboutIt3 =
+      document.getElementById("stsMitmWhatCanYouDoAboutIt3").innerHTML;
+    // eslint-disable-next-line no-unsanitized/property
+    document.getElementById("mitmWhatCanYouDoAboutIt3").innerHTML = stsMitmWhatCanYouDoAboutIt3;
   }
 }
 
 function initPage() {
   var err = getErrorCode();
   // List of error pages with an illustration.
   let illustratedErrors = [
     "malformedURI", "dnsNotFound", "connectionFailure", "netInterrupt",
@@ -152,30 +149,29 @@ function initPage() {
   if (illustratedErrors.includes(err)) {
     document.body.classList.add("illustrated", err);
   }
   if (err == "blockedByPolicy") {
     document.body.classList.add("blocked");
   }
 
   gIsCertError = (err == "nssBadCert");
-  gNewErrorPagesEnabled = !!document.body.dataset.newErrorPagesEnabled;
   // Only worry about captive portals if this is a cert error.
   let showCaptivePortalUI = isCaptive() && gIsCertError;
   if (showCaptivePortalUI) {
     err = "captivePortal";
   }
 
   let l10nErrId = err;
   let className = getCSSClass();
   if (className) {
     document.body.classList.add(className);
   }
 
-  if (gNewErrorPagesEnabled && gIsCertError && (window !== window.top || className == "badStsCert")) {
+  if (gIsCertError && (window !== window.top || className == "badStsCert")) {
     l10nErrId += "_sts";
   }
 
   let pageTitle = document.getElementById("ept_" + l10nErrId);
   if (pageTitle) {
     document.title = pageTitle.textContent;
   }
 
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -26,17 +26,18 @@
          toolkit/components/places/src/nsFaviconService.h should be updated. -->
     <link rel="icon" id="favicon" href="chrome://global/skin/icons/warning.svg"/>
   </head>
 
   <body dir="&locale.dir;">
     <!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
     <div id="errorContainer">
       <div id="errorPageTitlesContainer">
-        <span id="ept_nssBadCert">&certerror.pagetitle1;</span>
+        <span id="ept_nssBadCert">&certerror.pagetitle2;</span>
+        <span id="ept_nssBadCert_sts">&certerror.sts.pagetitle;</span>
         <span id="ept_captivePortal">&captivePortal.title;</span>
         <span id="ept_dnsNotFound">&dnsNotFound.pageTitle;</span>
         <span id="ept_malformedURI">&malformedURI.pageTitle;</span>
         <span id="ept_blockedByPolicy">&blockedByPolicy.title;</span>
       </div>
       <div id="errorTitlesContainer">
         <h1 id="et_generic">&generic.title;</h1>
         <h1 id="et_captivePortal">&captivePortal.title;</h1>
@@ -54,23 +55,26 @@
         <h1 id="et_netOffline">&netOffline.title;</h1>
         <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
         <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
         <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
         <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
         <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
         <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
         <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
-        <h1 id="et_nssBadCert">&certerror.longpagetitle1;</h1>
+        <h1 id="et_nssBadCert">&certerror.longpagetitle2;</h1>
+        <h1 id="et_nssBadCert_sts">&certerror.sts.longpagetitle;</h1>
         <h1 id="et_cspBlocked">&cspBlocked.title;</h1>
         <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
         <h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
         <h1 id="et_sslv3Used">&sslv3Used.title;</h1>
         <h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
         <h1 id="et_blockedByPolicy">&blockedByPolicy.title;</h1>
+        <h1 id="et_mitm">&certerror.mitm.title;</h1>
+        <h1 id="et_clockSkewError">&clockSkewError.title;</h1>
         <h1 id="et_networkProtocolError">&networkProtocolError.title;</h1>
       </div>
       <div id="errorDescriptionsContainer">
         <div id="ed_generic">&generic.longDesc;</div>
         <div id="ed_captivePortal">&captivePortal.longDesc2;</div>
         <div id="ed_dnsNotFound">&dnsNotFound.longDesc1;</div>
         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
         <div id="ed_fileAccessDenied">&fileAccessDenied.longDesc;</div>
@@ -85,25 +89,56 @@
         <div id="ed_netOffline">&netOffline.longDesc2;</div>
         <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
         <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
         <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
         <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
         <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
         <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
         <div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
-        <div id="ed_nssBadCert">&certerror.introPara;</div>
+        <div id="ed_nssBadCert">&certerror.introPara2;</div>
+        <div id="ed_nssBadCert_sts">&certerror.sts.introPara;</div>
+        <div id="ed_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.introPara;</div>
+        <div id="ed_mitm">&certerror.mitm.longDesc;</div>
         <div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
         <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
         <div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
         <div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
         <div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>
         <div id="ed_blockedByPolicy"></div>
+        <div id="ed_clockSkewError">&clockSkewError.longDesc;</div>
         <div id="ed_networkProtocolError">&networkProtocolError.longDesc;</div>
       </div>
+      <div id="errorDescriptions2Container">
+          <div id="ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.secondPara2;</div>
+          <div id="ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE_sts">&certerror.expiredCert.sts.secondPara;</div>
+      </div>
+      <div id="whatCanYouDoAboutItTitleContainer">
+        <div id="edd_nssBadCert"><strong>&certerror.whatCanYouDoAboutItTitle;</strong></div>
+      </div>
+      <div id="whatCanYouDoAboutItContainer">
+        <div id="es_nssBadCert_SEC_ERROR_UNKNOWN_ISSUER">&certerror.unknownIssuer.whatCanYouDoAboutIt;</div>
+        <div id="es_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
+        <div id="es_nssBadCert_SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
+        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
+        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE">&certerror.expiredCert.whatCanYouDoAboutIt2;</div>
+        <div id="es_nssBadCert_SSL_ERROR_BAD_CERT_DOMAIN">&certerror.badCertDomain.whatCanYouDoAboutIt;</div>
+        <div id="es_nssBadCert_MOZILLA_PKIX_ERROR_MITM_DETECTED">
+          <ul>
+            <li>&certerror.mitm.whatCanYouDoAboutIt1;</li>
+            <li>&certerror.mitm.whatCanYouDoAboutIt2;</li>
+            <li id="mitmWhatCanYouDoAboutIt3">&certerror.mitm.whatCanYouDoAboutIt3;</li>
+          </ul>
+        </div>
+      </div>
+      <!-- Stores an alternative text for when we don't want to add "Recommended" to the
+           return button. This is one of many l10n atrocities in this file and should be
+           removed when we finally switch to Fluent. -->
+      <span id="stsReturnButtonText">&returnToPreviousPage.label;</span>
+      <span id="stsMitmWhatCanYouDoAboutIt3">&certerror.mitm.sts.whatCanYouDoAboutIt3;</span>
     </div>
 
     <!-- PAGE CONTAINER (for styling purposes only) -->
     <div id="errorPageContainer" class="container">
       <div id="text-container">
         <!-- Error Title -->
         <div class="title">
           <h1 class="title-text"/>
@@ -116,68 +151,83 @@
           <div id="errorShortDesc">
             <p id="errorShortDescText" />
           </div>
 
           <div id="errorShortDesc2">
               <p id="errorShortDescText2" />
           </div>
 
-          <p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation;</p>
+          <div id="errorWhatToDoTitle">
+              <p id="errorWhatToDoTitleText" />
+          </div>
+
+          <div id="errorWhatToDo">
+              <p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation1;</p>
+              <p id="errorWhatToDoText" />
+          </div>
+
+          <div id="errorWhatToDo2">
+              <p id="errorWhatToDoText2" />
+              <p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation1;</p>
+          </div>
 
           <div id="wrongSystemTimePanel">
             &certerror.wrongSystemTime2;
           </div>
 
           <div id="wrongSystemTimeWithoutReferencePanel">
             &certerror.wrongSystemTimeWithoutReference;
           </div>
 
           <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
           <div id="errorLongDesc" />
 
           <div id="learnMoreContainer">
-            <p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new" data-telemetry-id="learn_more_link">&errorReporting.learnMore;</a></p>
+            <p><a id="learnMoreLink" target="new" data-telemetry-id="learn_more_link">&errorReporting.learnMore;</a></p>
           </div>
         </div>
 
         <!-- UI for option to report certificate errors to Mozilla. Removed on
              init for other error types .-->
-        <div id="certificateErrorReporting">
-          <p class="toggle-container-with-text">
-            <input type="checkbox" id="automaticallyReportInFuture" role="checkbox"  data-telemetry-id="auto_report_cb"/>
-            <label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic2;</label>
-          </p>
-        </div>
-
         <div id="prefChangeContainer" class="button-container">
           <p>&prefReset.longDesc;</p>
           <button id="prefResetButton" class="primary">&prefReset.label;</button>
         </div>
 
         <div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
-          <button id="returnButton" class="primary" data-telemetry-id="return_button_top">&returnToPreviousPage.label;</button>
+          <button id="returnButton" class="primary" data-telemetry-id="return_button_top">&returnToPreviousPage1.label;</button>
           <button id="openPortalLoginPageButton" class="primary">&openPortalLoginPage.label2;</button>
-          <button id="advancedButton" data-telemetry-id="advanced_button">&advanced.label;</button>
+          <button id="errorTryAgain" class="primary">&retry.label;</button>
+          <button id="advancedButton" data-telemetry-id="advanced_button">&advanced2.label;</button>
         </div>
       </div>
 
       <div id="netErrorButtonContainer" class="button-container">
         <button id="errorTryAgain" class="primary">&retry.label;</button>
       </div>
 
       <div id="advancedPanelContainer">
         <div id="badCertAdvancedPanel" class="advanced-panel">
           <p id="badCertTechnicalInfo"/>
+          <a id="viewCertificate" href="javascript:void(0)">&viewCertificate.label;</a>
           <div id="advancedPanelButtonContainer" class="button-container">
+            <button id="advancedPanelReturnButton" class="primary" data-telemetry-id="return_button_adv">&returnToPreviousPage1.label;</button>
             <button id="advancedPanelErrorTryAgain" class="primary">&retry.label;</button>
+            <div class="exceptionDialogButtonContainer">
+              <button id="exceptionDialogButton" data-telemetry-id="exception_button">&securityOverride.exceptionButton1Label;</button>
+            </div>
           </div>
-          <div class="exceptionDialogButtonContainer">
-            <button id="exceptionDialogButton" data-telemetry-id="exception_button">&securityOverride.exceptionButtonLabel;</button>
-          </div>
+        </div>
+
+        <div id="certificateErrorReporting">
+            <p class="toggle-container-with-text">
+                <input type="checkbox" id="automaticallyReportInFuture" role="checkbox" data-telemetry-id="auto_report_cb"/>
+                <label for="automaticallyReportInFuture">&errorReporting.automatic2;</label>
+            </p>
         </div>
 
         <div id="certificateErrorDebugInformation">
           <button id="copyToClipboard" data-telemetry-id="clipboard_button_top">&certerror.copyToClipboard.label;</button>
           <div id="certificateErrorText"/>
           <button id="copyToClipboard" data-telemetry-id="clipboard_button_bot">&certerror.copyToClipboard.label;</button>
         </div>
       </div>
--- a/browser/base/content/browser-contentblocking.js
+++ b/browser/base/content/browser-contentblocking.js
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var Fingerprinting = {
   PREF_ENABLED: "privacy.trackingprotection.fingerprinting.enabled",
+  reportBreakageLabel: "fingerprinting",
   telemetryIdentifier: "fp",
 
   strings: {
     get subViewBlocked() {
       delete this.subViewBlocked;
       return this.subViewBlocked =
         gNavigatorBundle.getString("contentBlocking.fingerprintersView.blocked.label");
     },
@@ -111,16 +112,17 @@ var Fingerprinting = {
     }
 
     return listItem;
   },
 };
 
 var Cryptomining = {
   PREF_ENABLED: "privacy.trackingprotection.cryptomining.enabled",
+  reportBreakageLabel: "cryptomining",
   telemetryIdentifier: "cm",
 
   strings: {
     get subViewBlocked() {
       delete this.subViewBlocked;
       return this.subViewBlocked =
         gNavigatorBundle.getString("contentBlocking.cryptominersView.blocked.label");
     },
@@ -979,16 +981,18 @@ var ContentBlocking = {
     body += `${TrackingProtection.PREF_ENABLED_GLOBALLY}: ${Services.prefs.getBoolPref(TrackingProtection.PREF_ENABLED_GLOBALLY)}\n`;
     body += `${TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS}: ${Services.prefs.getBoolPref(TrackingProtection.PREF_ENABLED_IN_PRIVATE_WINDOWS)}\n`;
     body += `urlclassifier.trackingTable: ${Services.prefs.getStringPref("urlclassifier.trackingTable")}\n`;
     body += `network.http.referer.defaultPolicy: ${Services.prefs.getIntPref("network.http.referer.defaultPolicy")}\n`;
     body += `network.http.referer.defaultPolicy.pbmode: ${Services.prefs.getIntPref("network.http.referer.defaultPolicy.pbmode")}\n`;
     body += `${ThirdPartyCookies.PREF_ENABLED}: ${Services.prefs.getIntPref(ThirdPartyCookies.PREF_ENABLED)}\n`;
     body += `network.cookie.lifetimePolicy: ${Services.prefs.getIntPref("network.cookie.lifetimePolicy")}\n`;
     body += `privacy.restrict3rdpartystorage.expiration: ${Services.prefs.getIntPref("privacy.restrict3rdpartystorage.expiration")}\n`;
+    body += `${Fingerprinting.PREF_ENABLED}: ${Services.prefs.getBoolPref(Fingerprinting.PREF_ENABLED)}\n`;
+    body += `${Cryptomining.PREF_ENABLED}: ${Services.prefs.getBoolPref(Cryptomining.PREF_ENABLED)}\n`;
 
     let comments = document.getElementById("identity-popup-breakageReportView-collection-comments");
     body += "\n**Comments**\n" + comments.value;
 
     formData.set("body", body);
 
     let activatedBlockers = [];
     for (let blocker of this.blockers) {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3175,62 +3175,38 @@ var BrowserOnClick = {
       case "viewCertificate":
         securityInfo = getSecurityInfo(securityInfoAsString);
         cert = securityInfo.serverCert;
         Services.ww.openWindow(window, "chrome://pippki/content/certViewer.xul",
                                "_blank", "centerscreen,chrome", cert);
         break;
       case "exceptionDialogButton":
         securityInfo = getSecurityInfo(securityInfoAsString);
-        let params = { exceptionAdded: false,
-                       securityInfo };
-        if (Services.prefs.getBoolPref("browser.security.newcerterrorpage.enabled", false)) {
-          let overrideService = Cc["@mozilla.org/security/certoverride;1"]
-                                  .getService(Ci.nsICertOverrideService);
-          let flags = 0;
-          if (securityInfo.isUntrusted) {
-            flags |= overrideService.ERROR_UNTRUSTED;
-          }
-          if (securityInfo.isDomainMismatch) {
-            flags |= overrideService.ERROR_MISMATCH;
-          }
-          if (securityInfo.isNotValidAtThisTime) {
-            flags |= overrideService.ERROR_TIME;
-          }
-          let uri = Services.uriFixup.createFixupURI(location, 0);
-          let permanentOverride =
-            Services.prefs.getBoolPref("security.certerrors.permanentOverride");
-          cert = securityInfo.serverCert;
-          overrideService.rememberValidityOverride(
-            uri.asciiHost, uri.port,
-            cert,
-            flags,
-            !permanentOverride);
-          browser.reload();
-          return;
+        let overrideService = Cc["@mozilla.org/security/certoverride;1"]
+                                .getService(Ci.nsICertOverrideService);
+        let flags = 0;
+        if (securityInfo.isUntrusted) {
+          flags |= overrideService.ERROR_UNTRUSTED;
+        }
+        if (securityInfo.isDomainMismatch) {
+          flags |= overrideService.ERROR_MISMATCH;
         }
-
-        try {
-          switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) {
-            case 2 : // Pre-fetch & pre-populate
-              params.prefetchCert = true;
-            case 1 : // Pre-populate
-              params.location = location;
-          }
-        } catch (e) {
-          Cu.reportError("Couldn't get ssl_override pref: " + e);
+        if (securityInfo.isNotValidAtThisTime) {
+          flags |= overrideService.ERROR_TIME;
         }
-
-        window.openDialog("chrome://pippki/content/exceptionDialog.xul",
-                          "", "chrome,centerscreen,modal", params);
-
-        // If the user added the exception cert, attempt to reload the page
-        if (params.exceptionAdded) {
-          browser.reload();
-        }
+        let uri = Services.uriFixup.createFixupURI(location, 0);
+        let permanentOverride =
+          Services.prefs.getBoolPref("security.certerrors.permanentOverride");
+        cert = securityInfo.serverCert;
+        overrideService.rememberValidityOverride(
+          uri.asciiHost, uri.port,
+          cert,
+          flags,
+          !permanentOverride);
+        browser.reload();
         break;
 
       case "returnButton":
         goBackFromErrorPage();
         break;
 
       case "advancedPanelReturnButton":
         goBackFromErrorPage();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -120,101 +120,83 @@
 # *must* go into the browser-sets.inc file so that they can be shared with other
 # top level windows in macWindow.inc.xul.
 #include browser-sets.inc
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
-      <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
+      <menuitem id="context_reloadTab" data-lazy-l10n-id="reload-tab"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_reloadSelectedTabs" label="&reloadTabs.label;" hidden="true"
-                accesskey="&reloadTabs.accesskey;"
+      <menuitem id="context_reloadSelectedTabs" data-lazy-l10n-id="reload-tabs" hidden="true"
                 oncommand="gBrowser.reloadMultiSelectedTabs();"/>
       <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/>
       <menuitem id="context_toggleMuteSelectedTabs" hidden="true"
                 oncommand="gBrowser.toggleMuteAudioOnMultiSelectedTabs(TabContextMenu.contextTab);"/>
-      <menuitem id="context_pinTab" label="&pinTab.label;"
-                accesskey="&pinTab.accesskey;"
+      <menuitem id="context_pinTab" data-lazy-l10n-id="pin-tab"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
-                accesskey="&unpinTab.accesskey;"
+      <menuitem id="context_unpinTab" data-lazy-l10n-id="unpin-tab" hidden="true"
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_pinSelectedTabs" label="&pinSelectedTabs.label;" hidden="true"
-                accesskey="&pinSelectedTabs.accesskey;"
+      <menuitem id="context_pinSelectedTabs" data-lazy-l10n-id="pin-selected-tabs" hidden="true"
                 oncommand="gBrowser.pinMultiSelectedTabs();"/>
-      <menuitem id="context_unpinSelectedTabs" label="&unpinSelectedTabs.label;" hidden="true"
-                accesskey="&unpinSelectedTabs.accesskey;"
+      <menuitem id="context_unpinSelectedTabs" data-lazy-l10n-id="unpin-selected-tabs" hidden="true"
                 oncommand="gBrowser.unpinMultiSelectedTabs();"/>
-      <menuitem id="context_duplicateTab" label="&duplicateTab.label;"
-                accesskey="&duplicateTab.accesskey;"
+      <menuitem id="context_duplicateTab" data-lazy-l10n-id="duplicate-tab"
                 oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');"/>
-      <menuitem id="context_duplicateTabs" label="&duplicateTabs.label;"
-                accesskey="&duplicateTabs.accesskey;"
+      <menuitem id="context_duplicateTabs" data-lazy-l10n-id="duplicate-tabs"
                 oncommand="TabContextMenu.duplicateSelectedTabs();"/>
       <menuseparator/>
-      <menuitem id="context_selectAllTabs" label="&selectAllTabs.label;" accesskey="&selectAllTabs.accesskey;"
+      <menuitem id="context_selectAllTabs" data-lazy-l10n-id="select-all-tabs"
                 oncommand="gBrowser.selectAllTabs();"/>
       <menuitem id="context_bookmarkSelectedTabs"
                 hidden="true"
-                label="&bookmarkSelectedTabs.label;"
-                accesskey="&bookmarkSelectedTabs.accesskey;"
+                data-lazy-l10n-id="bookmark-selected-tabs"
                 oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueSelectedPages);"/>
       <menuitem id="context_bookmarkTab"
-                label="&bookmarkTab.label;"
-                accesskey="&bookmarkTab.accesskey;"
+                data-lazy-l10n-id="bookmark-tab"
                 oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.getUniquePages([TabContextMenu.contextTab]));"/>
       <menu id="context_reopenInContainer"
-            label="&reopenInContainer.label;"
-            accesskey="&reopenInContainer.accesskey;"
+            data-lazy-l10n-id="reopen-in-container"
             hidden="true">
         <menupopup oncommand="TabContextMenu.reopenInContainer(event);"
                    onpopupshowing="TabContextMenu.createReopenInContainerMenu(event);"/>
       </menu>
-      <menu id="context_moveTabOptions"
-            multiselectcontextlabel="&moveSelectedTabOptions.label;"
-            multiselectcontextaccesskey="&moveSelectedTabOptions.accesskey;"
-            nonmultiselectcontextlabel="&moveTabOptions.label;"
-            nonmultiselectcontextaccesskey="&moveTabOptions.accesskey;">
+      <menu id="context_moveTabOptions">
         <menupopup id="moveTabOptionsMenu">
           <menuitem id="context_moveToStart"
-                    label="&moveToStart.label;"
-                    accesskey="&moveToStart.accesskey;"
+                    data-lazy-l10n-id="move-to-start"
                     tbattr="tabbrowser-multiple"
                     oncommand="gBrowser.moveTabsToStart(TabContextMenu.contextTab);"/>
           <menuitem id="context_moveToEnd"
-                    label="&moveToEnd.label;"
-                    accesskey="&moveToEnd.accesskey;"
+                    data-lazy-l10n-id="move-to-end"
                     tbattr="tabbrowser-multiple"
                     oncommand="gBrowser.moveTabsToEnd(TabContextMenu.contextTab);"/>
-          <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
-                    accesskey="&moveToNewWindow.accesskey;"
+          <menuitem id="context_openTabInWindow" data-lazy-l10n-id="move-to-new-window"
                     tbattr="tabbrowser-multiple"
                     oncommand="gBrowser.replaceTabsWithWindow(TabContextMenu.contextTab);"/>
         </menupopup>
       </menu>
       <menu id="context_sendTabToDevice"
             class="sync-ui-item">
         <menupopup id="context_sendTabToDevicePopupMenu"
                    onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle, TabContextMenu.contextTab.multiselected);"/>
       </menu>
       <menuseparator/>
-      <menuitem id="context_closeTabsToTheEnd" label="&closeTabsToTheEnd.label;" accesskey="&closeTabsToTheEnd.accesskey;"
+      <menuitem id="context_closeTabsToTheEnd" data-lazy-l10n-id="close-tabs-to-the-end"
                 oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
-      <menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
+      <menuitem id="context_closeOtherTabs" data-lazy-l10n-id="close-other-tabs"
                 oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
       <menuitem id="context_undoCloseTab"
-                label="&undoCloseTab.label;"
-                accesskey="&undoCloseTab.accesskey;"
+                data-lazy-l10n-id="undo-close-tab"
                 observes="History:UndoCloseTab"/>
-      <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
+      <menuitem id="context_closeTab" data-lazy-l10n-id="close-tab"
                 oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/>
-      <menuitem id="context_closeSelectedTabs" label="&closeTabs.label;"
-                hidden="true" accesskey="&closeTabs.accesskey;"
+      <menuitem id="context_closeSelectedTabs" data-lazy-l10n-id="close-tabs"
+                hidden="true"
                 oncommand="gBrowser.removeMultiSelectedTabs();"/>
     </menupopup>
 
     <!-- bug 415444/582485: event.stopPropagation is here for the cloned version
          of this menupopup -->
     <menupopup id="backForwardMenu"
                onpopupshowing="return FillHistoryMenu(event.target);"
                oncommand="gotoHistoryIndex(event); event.stopPropagation();"
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -1,16 +1,12 @@
 /* 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/. */
 
-.tabbrowser-arrowscrollbox {
-  -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox");
-}
-
 .tab-close-button[pinned],
 #tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
 .tab-icon-pending:not([pendingicon]),
 .tab-icon-pending[busy],
 .tab-icon-pending[pinned],
 .tab-icon-image:not([src]):not([pinned]):not([crashed])[selected],
 .tab-icon-image:not([src]):not([pinned]):not([crashed]):not([sharing]),
 .tab-icon-image[busy],
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -4740,16 +4740,29 @@ window._gBrowser = {
         return;
       }
 
       SitePermissions.set(event.detail.url, "autoplay-media",
                           SitePermissions.BLOCK,
                           SitePermissions.SCOPE_GLOBAL,
                           browser);
     });
+
+    let tabContextFTLInserter = () => {
+      MozXULElement.insertFTLIfNeeded("browser/tabContextMenu.ftl");
+      // Un-lazify the l10n-ids now that the FTL file has been inserted.
+      document.getElementById("tabContextMenu").querySelectorAll("[data-lazy-l10n-id]").forEach(el => {
+        el.setAttribute("data-l10n-id", el.getAttribute("data-lazy-l10n-id"));
+        el.removeAttribute("data-lazy-l10n-id");
+      });
+      this.tabContainer.removeEventListener("mouseover", tabContextFTLInserter);
+      this.tabContainer.removeEventListener("focus", tabContextFTLInserter, true);
+    };
+    this.tabContainer.addEventListener("mouseover", tabContextFTLInserter);
+    this.tabContainer.addEventListener("focus", tabContextFTLInserter, true);
   },
 
   setSuccessor(aTab, successorTab) {
     if (aTab.ownerGlobal != window) {
       throw new Error("Cannot set the successor of another window's tab");
     }
     if (successorTab == aTab) {
       successorTab = null;
@@ -5397,21 +5410,17 @@ var TabContextMenu = {
     contextUnpinTab.hidden = !this.contextTab.pinned || multiselectionContext;
     let contextPinSelectedTabs = document.getElementById("context_pinSelectedTabs");
     contextPinSelectedTabs.hidden = this.contextTab.pinned || !multiselectionContext;
     let contextUnpinSelectedTabs = document.getElementById("context_unpinSelectedTabs");
     contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext;
 
     let contextMoveTabOptions = document.getElementById("context_moveTabOptions");
     contextMoveTabOptions.disabled = gBrowser.allTabsSelected();
-    let moveTabOptionsStringPrefix = multiselectionContext ? "multiselectcontext" : "nonmultiselectcontext";
-    let moveTabOptionsLabel = contextMoveTabOptions.getAttribute(moveTabOptionsStringPrefix + "label");
-    let moveTabOptionsAccessKey = contextMoveTabOptions.getAttribute(moveTabOptionsStringPrefix + "accesskey");
-    contextMoveTabOptions.setAttribute("label", moveTabOptionsLabel);
-    contextMoveTabOptions.setAttribute("accesskey", moveTabOptionsAccessKey);
+    document.l10n.setAttributes(contextMoveTabOptions, multiselectionContext ? "move-tabs" : "move-tab");
     let selectedTabs = gBrowser.selectedTabs;
     let contextMoveTabToEnd = document.getElementById("context_moveToEnd");
     let allSelectedTabsAdjacent = selectedTabs.every((element, index, array) => {
       return array.length > index + 1 ? element._tPos + 1 == array[index + 1]._tPos : true;
     });
     let contextTabIsSelected = this.contextTab.multiselected;
     let visibleTabs = gBrowser.visibleTabs;
     let lastVisibleTab = visibleTabs[visibleTabs.length - 1];
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3,77 +3,16 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <bindings id="tabBrowserBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox">
-    <implementation>
-      <!-- Override scrollbox.xml method, since our scrollbox's children are
-           inherited from the binding parent -->
-      <method name="_getScrollableElements">
-        <body><![CDATA[
-          return Array.filter(document.getBindingParent(this).children,
-                              this._canScrollToElement, this);
-        ]]></body>
-      </method>
-      <method name="_canScrollToElement">
-        <parameter name="tab"/>
-        <body><![CDATA[
-          return !tab._pinnedUnscrollable && !tab.hidden;
-        ]]></body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="underflow" phase="capturing"><![CDATA[
-        // Ignore underflow events:
-        // - from nested scrollable elements
-        // - for vertical orientation
-        // - corresponding to an overflow event that we ignored
-        let tabs = document.getBindingParent(this);
-        if (event.originalTarget != this.scrollbox ||
-            event.detail == 0 ||
-            !tabs.hasAttribute("overflow")) {
-          return;
-        }
-
-        tabs.removeAttribute("overflow");
-
-        if (tabs._lastTabClosedByMouse) {
-          tabs._expandSpacerBy(this._scrollButtonDown.clientWidth);
-        }
-
-        for (let tab of Array.from(gBrowser._removingTabs)) {
-          gBrowser.removeTab(tab);
-        }
-
-        tabs._positionPinnedTabs();
-      ]]></handler>
-      <handler event="overflow"><![CDATA[
-        // Ignore overflow events:
-        // - from nested scrollable elements
-        // - for vertical orientation
-        if (event.originalTarget != this.scrollbox ||
-            event.detail == 0) {
-          return;
-        }
-
-        var tabs = document.getBindingParent(this);
-        tabs.setAttribute("overflow", "true");
-        tabs._positionPinnedTabs();
-        tabs._handleTabSelect(true);
-      ]]></handler>
-    </handlers>
-  </binding>
-
   <binding id="tabbrowser-tabs"
            extends="chrome://global/content/bindings/tabbox.xml#tabs">
     <content>
       <xul:hbox class="tab-drop-indicator-box">
         <xul:image class="tab-drop-indicator" anonid="tab-drop-indicator" collapsed="true"/>
       </xul:hbox>
       <xul:arrowscrollbox anonid="arrowscrollbox" orient="horizontal" flex="1"
                           style="min-width: 1px;"
@@ -136,16 +75,17 @@
             "browser.tabs.multiselect", null,
             (pref, prevValue, newValue) => this._multiselectEnabled = newValue);
           this._multiselectEnabled = this._multiselectEnabledPref;
 
           this._setPositionalAttributes();
 
           CustomizableUI.addListener(this);
           this._updateNewTabVisibility();
+          this._initializeArrowScrollbox();
 
           XPCOMUtils.defineLazyPreferenceGetter(this, "_closeTabByDblclick",
             "browser.tabs.closeTabByDblclick", false);
 
           if (gMultiProcessBrowser) {
             this.tabbox.tabpanels.setAttribute("async", "true");
           }
         ]]>
@@ -191,16 +131,68 @@
           this.setAttribute("aria-multiselectable", !!val);
           return val;
         </setter>
         <getter>
           return this.getAttribute("aria-multiselectable") == "true";
         </getter>
       </property>
 
+      <method name="_initializeArrowScrollbox">
+        <body><![CDATA[
+          let arrowScrollbox = this.arrowScrollbox;
+          arrowScrollbox.addEventListener("underflow", event => {
+            // Ignore underflow events:
+            // - from nested scrollable elements
+            // - for vertical orientation
+            // - corresponding to an overflow event that we ignored
+            if (event.originalTarget != arrowScrollbox.scrollbox ||
+                event.detail == 0 ||
+                !this.hasAttribute("overflow")) {
+              return;
+            }
+
+            this.removeAttribute("overflow");
+
+            if (this._lastTabClosedByMouse) {
+              this._expandSpacerBy(this._scrollButtonDown.clientWidth);
+            }
+
+            for (let tab of Array.from(gBrowser._removingTabs)) {
+              gBrowser.removeTab(tab);
+            }
+
+            this._positionPinnedTabs();
+          }, true);
+
+          arrowScrollbox.addEventListener("overflow", event => {
+            // Ignore overflow events:
+            // - from nested scrollable elements
+            // - for vertical orientation
+            if (event.originalTarget != arrowScrollbox.scrollbox ||
+                event.detail == 0) {
+              return;
+            }
+
+            this.setAttribute("overflow", "true");
+            this._positionPinnedTabs();
+            this._handleTabSelect(true);
+          });
+
+          // Override scrollbox.xml method, since our scrollbox's children are
+          // inherited from the scrollbox binding parent (this).
+          arrowScrollbox._getScrollableElements = () => {
+            return Array.filter(this.children, arrowScrollbox._canScrollToElement);
+          };
+          arrowScrollbox._canScrollToElement = tab => {
+            return !tab._pinnedUnscrollable && !tab.hidden;
+          };
+        ]]></body>
+      </method>
+
       <method name="observe">
         <parameter name="aSubject"/>
         <parameter name="aTopic"/>
         <parameter name="aData"/>
         <body><![CDATA[
           switch (aTopic) {
             case "nsPref:changed":
               // This is has to deal with changes in
--- a/browser/base/content/test/about/browser_aboutCertError.js
+++ b/browser/base/content/test/about/browser_aboutCertError.js
@@ -6,17 +6,16 @@
 // This is testing the aboutCertError page (Bug 1207107).
 
 const GOOD_PAGE = "https://example.com/";
 const GOOD_PAGE_2 = "https://example.org/";
 const BAD_CERT = "https://expired.example.com/";
 const UNKNOWN_ISSUER = "https://self-signed.example.com ";
 const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
 const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm");
-const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
 
 add_task(async function checkReturnToAboutHome() {
   info("Loading a bad cert page directly and making sure 'return to previous page' goes to about:home");
   for (let useFrame of [false, true]) {
     let tab = await openErrorPage(BAD_CERT, useFrame);
     let browser = tab.linkedBrowser;
 
     is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack");
@@ -254,17 +253,16 @@ add_task(async function checkUnknownIssu
     });
     ok(href.endsWith("security-error"), "security-error in the Learn More URL");
 
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
 });
 
 add_task(async function checkCautionClass() {
-  Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
   info("Checking that are potentially more dangerous get a 'caution' class");
   for (let useFrame of [false, true]) {
     let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame);
     let browser = tab.linkedBrowser;
 
     await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
       let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
       is(doc.body.classList.contains("caution"), !frame, `Cert error body has ${frame ? "no" : ""} caution class`);
@@ -277,21 +275,19 @@ add_task(async function checkCautionClas
 
     await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
       let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
       ok(!doc.body.classList.contains("caution"), "Cert error body has no caution class");
     });
 
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
-  Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
 });
 
 add_task(async function checkViewCertificate() {
-  Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
   info("Loading a cert error and checking that the certificate can be shown.");
   for (let useFrame of [false, true]) {
     let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame);
     let browser = tab.linkedBrowser;
 
     let dialogOpened = BrowserTestUtils.domWindowOpened();
 
     await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
@@ -305,17 +301,16 @@ add_task(async function checkViewCertifi
     is(win.document.documentURI, "chrome://pippki/content/certViewer.xul",
       "Opened the cert viewer dialog");
     is(win.document.getElementById("commonname").value, "self-signed.example.com",
       "Shows the correct certificate in the dialog");
     win.close();
 
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
-  Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
 });
 
 add_task(async function checkBadStsCertHeadline() {
   info("Loading a bad sts cert error page and checking that the correct headline is shown");
   for (let useFrame of [false, true]) {
     let tab = await openErrorPage(BAD_CERT, useFrame);
     let browser = tab.linkedBrowser;
 
--- a/browser/base/content/test/about/browser_aboutCertError_clockSkew.js
+++ b/browser/base/content/test/about/browser_aboutCertError_clockSkew.js
@@ -1,20 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS = "services.settings.clock_skew_seconds";
 const PREF_SERVICES_SETTINGS_LAST_FETCHED = "services.settings.last_update_seconds";
-const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
 
 add_task(async function checkWrongSystemTimeWarning() {
-  Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
-
   async function setUpPage() {
     let browser;
     let certErrorLoaded;
     await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
       gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "https://expired.example.com/");
       browser = gBrowser.selectedBrowser;
       certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
     }, false);
@@ -75,10 +72,9 @@ add_task(async function checkWrongSystem
   ok(message.text.includes("expired.example.com"), "URL found in error message");
   ok(message.systemDate.includes(localDateFmt), "Correct local date displayed");
   ok(message.learnMoreLink.includes("time-errors"), "time-errors in the Learn More URL");
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
   Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_LAST_FETCHED);
   Services.prefs.clearUserPref(PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS);
-  Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
 });
--- a/browser/base/content/test/about/browser_aboutCertError_exception.js
+++ b/browser/base/content/test/about/browser_aboutCertError_exception.js
@@ -1,20 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const BAD_CERT = "https://expired.example.com/";
 const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
-const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
 const PREF_PERMANENT_OVERRIDE = "security.certerrors.permanentOverride";
 
 add_task(async function checkExceptionDialogButton() {
-  Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
   info("Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception");
   let tab = await openErrorPage(BAD_CERT);
   let browser = tab.linkedBrowser;
   let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
   info("Clicking the exceptionDialogButton in advanced panel");
   await ContentTask.spawn(browser, null, async function() {
     let doc = content.document;
     let exceptionButton = doc.getElementById("exceptionDialogButton");
@@ -28,21 +26,19 @@ add_task(async function checkExceptionDi
     let doc = content.document;
     ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
   });
 
   let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
                               .getService(Ci.nsICertOverrideService);
   certOverrideService.clearValidityOverride("expired.example.com", -1);
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
-  Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
 });
 
 add_task(async function checkPermanentExceptionPref() {
-  Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
   info("Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref");
 
   for (let permanentOverride of [false, true]) {
     Services.prefs.setBoolPref(PREF_PERMANENT_OVERRIDE, permanentOverride);
 
     let tab = await openErrorPage(BAD_CERT);
     let browser = tab.linkedBrowser;
     let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
@@ -78,17 +74,16 @@ add_task(async function checkPermanentEx
     is(isTemporary.value, !permanentOverride,
       `Has stored a ${permanentOverride ? "permanent" : "temporary"} exception for the page.`);
 
     certOverrideService.clearValidityOverride("expired.example.com", -1);
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
 
   Services.prefs.clearUserPref(PREF_PERMANENT_OVERRIDE);
-  Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
 });
 
 add_task(async function checkBadStsCert() {
   info("Loading a badStsCert and making sure exception button doesn't show up");
 
   for (let useFrame of [false, true]) {
     let tab = await openErrorPage(BAD_STS_CERT, useFrame);
     let browser = tab.linkedBrowser;
@@ -100,28 +95,19 @@ add_task(async function checkBadStsCert(
     });
 
     let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
       let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
       let advancedButton = doc.getElementById("advancedButton");
       advancedButton.click();
       return doc.getElementById("badCertTechnicalInfo").textContent;
     });
-    if (Services.prefs.getBoolPref(PREF_NEW_CERT_ERRORS)) {
-      ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
-      ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
-      ok(message.includes("a certificate that is not valid for"), "Didn't find error message.");
-      ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
-
-      BrowserTestUtils.removeTab(gBrowser.selectedTab);
-      return;
-    }
     ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
     ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
-    ok(message.includes("uses an invalid security certificate"), "Didn't find error message.");
+    ok(message.includes("a certificate that is not valid for"), "Didn't find error message.");
     ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
 
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
 });
 
 add_task(async function checkhideAddExceptionButtonViaPref() {
   info("Loading a bad cert page and verifying the pref security.certerror.hideAddException");
--- a/browser/base/content/test/about/browser_aboutCertError_mitm.js
+++ b/browser/base/content/test/about/browser_aboutCertError_mitm.js
@@ -1,26 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
 const PREF_MITM_PRIMING = "security.certerrors.mitm.priming.enabled";
 const PREF_MITM_PRIMING_ENDPOINT = "security.certerrors.mitm.priming.endpoint";
 const PREF_MITM_CANARY_ISSUER = "security.pki.mitm_canary_issuer";
 const PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS = "security.certerrors.mitm.auto_enable_enterprise_roots";
 const PREF_ENTERPRISE_ROOTS = "security.enterprise_roots.enabled";
 
 const UNKNOWN_ISSUER = "https://untrusted.example.com";
 
 // Check that basic MitM priming works and the MitM error page is displayed successfully.
 add_task(async function checkMitmPriming() {
   await SpecialPowers.pushPrefEnv({"set": [
-    [PREF_NEW_CERT_ERRORS, true],
     [PREF_MITM_PRIMING, true],
     [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
   ]});
 
   let browser;
   let certErrorLoaded;
   await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
     gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
@@ -55,17 +53,16 @@ add_task(async function checkMitmPriming
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
   Services.prefs.clearUserPref(PREF_MITM_CANARY_ISSUER);
 });
 
 // Check that we set the enterprise roots pref correctly on MitM
 add_task(async function checkMitmAutoEnableEnterpriseRoots() {
   await SpecialPowers.pushPrefEnv({"set": [
-    [PREF_NEW_CERT_ERRORS, true],
     [PREF_MITM_PRIMING, true],
     [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
     [PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS, true],
   ]});
 
   let browser;
   let certErrorLoaded;
 
--- a/browser/base/content/test/about/browser_aboutCertError_telemetry.js
+++ b/browser/base/content/test/about/browser_aboutCertError_telemetry.js
@@ -48,21 +48,19 @@ add_task(async function checkTelemetryCl
       "learn_more_link",
       "auto_report_cb",
       "error_code_link",
       "clipboard_button_top",
       "clipboard_button_bot",
       "return_button_top",
     ];
 
-    if (Services.prefs.getBoolPref("browser.security.newcerterrorpage.enabled")) {
-      recordedObjects.push("return_button_adv");
-      if (!useFrame) {
-        recordedObjects.push("exception_button");
-      }
+    recordedObjects.push("return_button_adv");
+    if (!useFrame) {
+      recordedObjects.push("exception_button");
     }
 
     for (let object of recordedObjects) {
       let tab = await openErrorPage(BAD_CERT, useFrame);
       let browser = tab.linkedBrowser;
 
       let loadEvents = await TestUtils.waitForCondition(() => {
         let events = Services.telemetry.snapshotEvents(
--- a/browser/base/content/test/general/browser_typeAheadFind.js
+++ b/browser/base/content/test/general/browser_typeAheadFind.js
@@ -1,14 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function() {
   let testWindow = await BrowserTestUtils.openNewBrowserWindow();
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test.
+  testWindow.gBrowser.selectedTab.focus();
 
   BrowserTestUtils.loadURI(testWindow.gBrowser, "data:text/html,<h1>A Page</h1>");
   await BrowserTestUtils.browserLoaded(testWindow.gBrowser.selectedBrowser);
 
   await SimpleTest.promiseFocus(testWindow.gBrowser.selectedBrowser);
 
   ok(!testWindow.gFindBarInitialized, "find bar is not initialized");
 
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -455,67 +455,26 @@ function promiseOnBookmarkItemAdded(aExp
       }
     };
     info("Waiting for a bookmark to be added");
     PlacesUtils.observers.addListener(["bookmark-added"], listener);
   });
 }
 
 async function loadBadCertPage(url) {
-  const EXCEPTION_DIALOG_URI = "chrome://pippki/content/exceptionDialog.xul";
-  let exceptionDialogResolved = new Promise(function(resolve) {
-    // When the certificate exception dialog has opened, click the button to add
-    // an exception.
-    let certExceptionDialogObserver = {
-      observe(aSubject, aTopic, aData) {
-        if (aTopic == "cert-exception-ui-ready") {
-          Services.obs.removeObserver(this, "cert-exception-ui-ready");
-          let certExceptionDialog = getCertExceptionDialog(EXCEPTION_DIALOG_URI);
-          ok(certExceptionDialog, "found exception dialog");
-          executeSoon(function() {
-            certExceptionDialog.documentElement.getButton("extra1").click();
-            resolve();
-          });
-        }
-      },
-    };
-
-    Services.obs.addObserver(certExceptionDialogObserver,
-                             "cert-exception-ui-ready");
-  });
-
   let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
   await BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   await loaded;
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     content.document.getElementById("exceptionDialogButton").click();
   });
-  if (!Services.prefs.getBoolPref("browser.security.newcerterrorpage.enabled", false)) {
-    await exceptionDialogResolved;
-  }
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 }
 
-// Utility function to get a handle on the certificate exception dialog.
-// Modified from toolkit/components/passwordmgr/test/prompt_common.js
-function getCertExceptionDialog(aLocation) {
-  for (let {docShell} of Services.wm.getXULWindowEnumerator(null)) {
-    let containedDocShells = docShell.getDocShellEnumerator(
-                                      docShell.typeChrome,
-                                      docShell.ENUMERATE_FORWARDS);
-    for (let {domWindow} of containedDocShells) {
-      if (domWindow.location.href == aLocation) {
-        return domWindow.document;
-      }
-    }
-  }
-  return undefined;
-}
-
 /**
  * Waits for the message from content to update the Page Style menu.
  *
  * @param browser
  *        The <xul:browser> to wait for.
  * @return Promise
  */
 async function promiseStylesheetsUpdated(browser) {
--- a/browser/base/content/test/performance/browser_startup_images.js
+++ b/browser/base/content/test/performance/browser_startup_images.js
@@ -20,20 +20,16 @@
  *
  * Please don't add items to this list. Please remove items from this list.
  */
 const whitelist = [
   {
     file: "chrome://browser/skin/arrow-left.svg",
     platforms: ["linux", "win", "macosx"],
   },
-  {
-    file: "chrome://browser/skin/tabbrowser/tab-overflow-indicator.png",
-    platforms: ["linux", "win", "macosx"],
-  },
 
   {
     file: "chrome://browser/skin/places/toolbarDropMarker.png",
     platforms: ["linux", "win", "macosx"],
   },
 
   {
     file: "chrome://browser/skin/tabbrowser/tabDragIndicator.png",
--- a/browser/base/content/test/permissions/browser_temporary_permissions_navigation.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions_navigation.js
@@ -45,16 +45,19 @@ add_task(async function testTempPermissi
       scope: SitePermissions.SCOPE_PERSISTENT,
     });
 
     // Set the permission again.
     SitePermissions.set(uri, id, SitePermissions.BLOCK, SitePermissions.SCOPE_TEMPORARY, browser);
 
     // Open the tab context menu.
     let contextMenu = document.getElementById("tabContextMenu");
+    // The TabContextMenu initializes its strings only on a focus or mouseover event.
+    // Calls focus event on the TabContextMenu early in the test.
+    gBrowser.selectedTab.focus();
     let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
     EventUtils.synthesizeMouseAtCenter(gBrowser.selectedTab, {type: "contextmenu", button: 2});
     await popupShownPromise;
 
     let reloadMenuItem = document.getElementById("context_reloadTab");
 
     reloaded = BrowserTestUtils.browserLoaded(browser, false, uri.spec);
 
@@ -80,16 +83,19 @@ add_task(async function testTempPermissi
   await BrowserTestUtils.withNewTab(uri.spec, async function(browser) {
     SitePermissions.set(uri, id, SitePermissions.BLOCK, SitePermissions.SCOPE_TEMPORARY, browser);
 
     // Select all tabs before opening the context menu.
     gBrowser.selectAllTabs();
 
     // Open the tab context menu.
     let contextMenu = document.getElementById("tabContextMenu");
+    // The TabContextMenu initializes its strings only on a focus or mouseover event.
+    // Calls focus event on the TabContextMenu early in the test.
+    gBrowser.selectedTab.focus();
     let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
     EventUtils.synthesizeMouseAtCenter(gBrowser.selectedTab, {type: "contextmenu", button: 2});
     await popupShownPromise;
 
     let reloadMenuItem = document.getElementById("context_reloadSelectedTabs");
 
     let reloaded = Promise.all(gBrowser.visibleTabs.map(
       tab => BrowserTestUtils.browserLoaded(gBrowser.getBrowserForTab(tab))));
--- a/browser/base/content/test/sanitize/browser_sanitize-formhistory.js
+++ b/browser/base/content/test/sanitize/browser_sanitize-formhistory.js
@@ -1,15 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  *  License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(async function test() {
   // This test relies on the form history being empty to start with delete
   // all the items first.
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test.
+  gBrowser.selectedTab.focus();
   await new Promise((resolve, reject) => {
     FormHistory.update({ op: "remove" },
                        { handleError(error) {
                            reject(error);
                          },
                          handleCompletion(reason) {
                            if (!reason) {
                              resolve();
--- a/browser/base/content/test/siteIdentity/head.js
+++ b/browser/base/content/test/siteIdentity/head.js
@@ -251,60 +251,17 @@ async function assertMixedContentBlockin
     let hideEvent = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
     info("Hiding identity popup");
     gIdentityHandler._identityPopup.hidePopup();
     await hideEvent;
   }
 }
 
 async function loadBadCertPage(url) {
-  const EXCEPTION_DIALOG_URI = "chrome://pippki/content/exceptionDialog.xul";
-  let exceptionDialogResolved = new Promise(function(resolve) {
-    // When the certificate exception dialog has opened, click the button to add
-    // an exception.
-    let certExceptionDialogObserver = {
-      observe(aSubject, aTopic, aData) {
-        if (aTopic == "cert-exception-ui-ready") {
-          Services.obs.removeObserver(this, "cert-exception-ui-ready");
-          let certExceptionDialog = getCertExceptionDialog(EXCEPTION_DIALOG_URI);
-          ok(certExceptionDialog, "found exception dialog");
-          executeSoon(function() {
-            certExceptionDialog.documentElement.getButton("extra1").click();
-            resolve();
-          });
-        }
-      },
-    };
-
-    Services.obs.addObserver(certExceptionDialogObserver,
-                             "cert-exception-ui-ready");
-  });
-
   let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
   await BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
   await loaded;
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     content.document.getElementById("exceptionDialogButton").click();
   });
-  if (!Services.prefs.getBoolPref("browser.security.newcerterrorpage.enabled", false)) {
-    await exceptionDialogResolved;
-  }
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 }
-
-// Utility function to get a handle on the certificate exception dialog.
-// Modified from toolkit/components/passwordmgr/test/prompt_common.js
-function getCertExceptionDialog(aLocation) {
-  for (let win of Services.wm.getXULWindowEnumerator(null)) {
-    let windowDocShell = win.docShell;
-
-    let containedDocShells = windowDocShell.getDocShellEnumerator(
-                                      Ci.nsIDocShellTreeItem.typeChrome,
-                                      Ci.nsIDocShell.ENUMERATE_FORWARDS);
-    for (let {domWindow} of containedDocShells) {
-      if (domWindow.location.href == aLocation) {
-        return domWindow.document;
-      }
-    }
-  }
-  return undefined;
-}
--- a/browser/base/content/test/static/browser_misused_characters_in_strings.js
+++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js
@@ -5,20 +5,16 @@
  * detect newly occurring issues in shipping files. It is a list of objects
  * specifying conditions under which an error should be ignored.
  *
  * As each issue is found in the whitelist, it is removed from the list. At
  * the end of the test, there is an assertion that all items have been
  * removed from the whitelist, thus ensuring there are no stale entries. */
 let gWhitelist = [{
     file: "netError.dtd",
-    key: "certerror.introPara",
-    type: "single-quote",
-  }, {
-    file: "netError.dtd",
     key: "certerror.introPara2",
     type: "single-quote",
   }, {
     file: "netError.dtd",
     key: "certerror.sts.introPara",
     type: "single-quote",
   }, {
     file: "netError.dtd",
--- a/browser/base/content/test/static/browser_parsable_css.js
+++ b/browser/base/content/test/static/browser_parsable_css.js
@@ -71,16 +71,25 @@ if (!Services.prefs.getBoolPref("layout.
   // These are UA sheets which use non-content-exposed `display` values.
   whitelist.push({
     sourceName: /(skin\/shared\/Heartbeat|((?:res|gre-resources)\/(ua|html)))\.css$/i,
     errorMessage: /Error in parsing value for .*\bdisplay\b/i,
     isFromDevTools: false,
   });
 }
 
+if (!Services.prefs.getBoolPref("layout.css.line-height-moz-block-height.content.enabled")) {
+  // -moz-block-height is used in form controls but not exposed to the web.
+  whitelist.push({
+    sourceName: /(?:res|gre-resources)\/forms\.css$/i,
+    errorMessage: /Error in parsing value for \u2018line-height\u2019/iu,
+    isFromDevTools: false,
+  });
+}
+
 if (!Services.prefs.getBoolPref("full-screen-api.unprefix.enabled")) {
   whitelist.push({
     sourceName: /(?:res|gre-resources)\/(ua|html)\.css$/i,
     errorMessage: /Unknown pseudo-class .*\bfullscreen\b/i,
     isFromDevTools: false,
   }, {
     // PDFjs is futureproofing its pseudoselectors, and those rules are dropped.
     sourceName: /web\/viewer\.css$/i,
--- a/browser/base/content/test/sync/browser_contextmenu_sendtab.js
+++ b/browser/base/content/test/sync/browser_contextmenu_sendtab.js
@@ -14,16 +14,19 @@ const fxaDevices = [
 ];
 
 let [testTab] = gBrowser.visibleTabs;
 
 function updateTabContextMenu(tab = gBrowser.selectedTab) {
   let menu = document.getElementById("tabContextMenu");
   var evt = new Event("");
   tab.dispatchEvent(evt);
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test
+  gBrowser.selectedTab.focus();
   menu.openPopup(tab, "end_after", 0, 0, true, false, evt);
   is(window.TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
   menu.hidePopup();
 }
 
 add_task(async function setup() {
   await promiseSyncReady();
   // gSync.init() is called in a requestIdleCallback. Force its initialization.
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -2,33 +2,55 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/benignPage.html";
 const COOKIE_PAGE = "http://not-tracking.example.com/browser/browser/base/content/test/trackingUI/cookiePage.html";
 
+const CM_PREF = "privacy.trackingprotection.cryptomining.enabled";
+const FP_PREF = "privacy.trackingprotection.fingerprinting.enabled";
 const TP_PREF = "privacy.trackingprotection.enabled";
+
 const PREF_REPORT_BREAKAGE_ENABLED = "browser.contentblocking.reportBreakage.enabled";
 const PREF_REPORT_BREAKAGE_URL = "browser.contentblocking.reportBreakage.url";
 
 let {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
 let {CommonUtils} = ChromeUtils.import("resource://services-common/utils.js");
 let {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 
 add_task(async function setup() {
   await UrlClassifierTestUtils.addTestTrackers();
 
   let oldCanRecord = Services.telemetry.canRecordExtended;
   Services.telemetry.canRecordExtended = true;
 
   registerCleanupFunction(() => {
     Services.telemetry.canRecordExtended = oldCanRecord;
+
+    // Clear prefs that are touched in this test again for sanity.
+    Services.prefs.clearUserPref(TP_PREF);
+    Services.prefs.clearUserPref(FP_PREF);
+    Services.prefs.clearUserPref(CM_PREF);
+    Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_ENABLED);
+    Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
+
+    UrlClassifierTestUtils.cleanupTestTrackers();
   });
+
+  await SpecialPowers.pushPrefEnv({set: [
+    [ ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS ],
+    [ "privacy.trackingprotection.fingerprinting.annotate.enabled", true ],
+    [ "urlclassifier.features.fingerprinting.blacklistHosts", "fingerprinting.example.com" ],
+    [ "urlclassifier.features.fingerprinting.annotate.blacklistHosts", "fingerprinting.example.com" ],
+    [ "privacy.trackingprotection.cryptomining.enabled", true ],
+    [ "urlclassifier.features.cryptomining.blacklistHosts", "cryptomining.example.com" ],
+    [ "urlclassifier.features.cryptomining.annotate.blacklistHosts", "cryptomining.example.com" ],
+  ]});
 });
 
 add_task(async function testReportBreakageVisibility() {
   let scenarios = [
     {
       url: TRACKING_PAGE,
       prefs: {
         "privacy.trackingprotection.enabled": true,
@@ -129,108 +151,139 @@ add_task(async function testReportBreaka
 
     ok(true, "Main view was shown");
   });
 
   Services.prefs.clearUserPref(TP_PREF);
   Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_ENABLED);
 });
 
-add_task(async function testReportBreakage() {
+add_task(async function testTP() {
+  Services.prefs.setBoolPref(TP_PREF, true);
+  // Make sure that we correctly strip the query.
+  let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
+  await BrowserTestUtils.withNewTab(url, async function() {
+    await testReportBreakage(TRACKING_PAGE, "trackingprotection");
+  });
+
+  Services.prefs.clearUserPref(TP_PREF);
+});
+
+add_task(async function testFP() {
+  Services.prefs.setBoolPref(FP_PREF, true);
+  // Make sure that we correctly strip the query.
+  let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
+  await BrowserTestUtils.withNewTab(url, async function(browser) {
+    await ContentTask.spawn(browser, {}, function() {
+      content.postMessage("fingerprinting", "*");
+    });
+
+    // Without TP, we will have a cookie restrictions entry for trackertest.org.
+    await testReportBreakage(TRACKING_PAGE, "cookierestrictions,fingerprinting");
+  });
+
+  Services.prefs.clearUserPref(FP_PREF);
+});
+
+add_task(async function testCM() {
+  Services.prefs.setBoolPref(CM_PREF, true);
+  // Make sure that we correctly strip the query.
+  let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
+  await BrowserTestUtils.withNewTab(url, async function(browser) {
+    await ContentTask.spawn(browser, {}, function() {
+      content.postMessage("cryptomining", "*");
+    });
+
+    // Without TP, we will have a cookie restrictions entry for trackertest.org.
+    await testReportBreakage(TRACKING_PAGE, "cookierestrictions,cryptomining");
+  });
+
+  Services.prefs.clearUserPref(CM_PREF);
+});
+
+async function testReportBreakage(url, tags) {
   // Setup a mock server for receiving breakage reports.
   let server = new HttpServer();
   server.start(-1);
   let i = server.identity;
   let path = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort + "/";
 
-  Services.prefs.setBoolPref(TP_PREF, true);
   Services.prefs.setBoolPref(PREF_REPORT_BREAKAGE_ENABLED, true);
   Services.prefs.setStringPref(PREF_REPORT_BREAKAGE_URL, path);
 
-  // Make sure that we correctly strip the query.
-  let url = TRACKING_PAGE + "?a=b&1=abc&unicode=🦊";
-  await BrowserTestUtils.withNewTab(url, async function() {
-    await openIdentityPopup();
+  await openIdentityPopup();
 
-    let reportBreakageButton = document.getElementById("identity-popup-content-blocking-report-breakage");
-    ok(BrowserTestUtils.is_visible(reportBreakageButton), "report breakage button is visible");
-    let reportBreakageView = document.getElementById("identity-popup-breakageReportView");
-    let viewShown = BrowserTestUtils.waitForEvent(reportBreakageView, "ViewShown");
-    reportBreakageButton.click();
-    await viewShown;
+  let reportBreakageButton = document.getElementById("identity-popup-content-blocking-report-breakage");
+  await TestUtils.waitForCondition(() => BrowserTestUtils.is_visible(reportBreakageButton),
+    "report breakage button is visible");
+  let reportBreakageView = document.getElementById("identity-popup-breakageReportView");
+  let viewShown = BrowserTestUtils.waitForEvent(reportBreakageView, "ViewShown");
+  reportBreakageButton.click();
+  await viewShown;
 
-    let submitButton = document.getElementById("identity-popup-breakageReportView-submit");
-    let reportURL = document.getElementById("identity-popup-breakageReportView-collection-url").value;
+  let submitButton = document.getElementById("identity-popup-breakageReportView-submit");
+  let reportURL = document.getElementById("identity-popup-breakageReportView-collection-url").value;
 
-    is(reportURL, TRACKING_PAGE, "Shows the correct URL in the report UI.");
+  is(reportURL, url, "Shows the correct URL in the report UI.");
 
-    // Make sure that sending the report closes the identity popup.
-    let popuphidden = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
+  // Make sure that sending the report closes the identity popup.
+  let popuphidden = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
 
-    // Check that we're receiving a good report.
-    await new Promise(resolve => {
-      server.registerPathHandler("/", async (request, response) => {
-        is(request.method, "POST", "request was a post");
+  // Check that we're receiving a good report.
+  await new Promise(resolve => {
+    server.registerPathHandler("/", async (request, response) => {
+      is(request.method, "POST", "request was a post");
 
-        // Extract and "parse" the form data in the request body.
-        let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
-        let boundary = request.getHeader("Content-Type").match(/boundary=-+([^-]*)/i)[1];
-        let regex = new RegExp("-+" + boundary + "-*\\s+");
-        let sections = body.split(regex);
+      // Extract and "parse" the form data in the request body.
+      let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream);
+      let boundary = request.getHeader("Content-Type").match(/boundary=-+([^-]*)/i)[1];
+      let regex = new RegExp("-+" + boundary + "-*\\s+");
+      let sections = body.split(regex);
 
-        let prefs = [
-          "privacy.trackingprotection.enabled",
-          "privacy.trackingprotection.pbmode.enabled",
-          "urlclassifier.trackingTable",
-          "network.http.referer.defaultPolicy",
-          "network.http.referer.defaultPolicy.pbmode",
-          "network.cookie.cookieBehavior",
-          "network.cookie.lifetimePolicy",
-          "privacy.restrict3rdpartystorage.expiration",
-        ];
-        let prefsBody = "";
-
-        for (let pref of prefs) {
-          prefsBody += `${pref}: ${Preferences.get(pref)}\r\n`;
-        }
+      let prefs = [
+        "privacy.trackingprotection.enabled",
+        "privacy.trackingprotection.pbmode.enabled",
+        "urlclassifier.trackingTable",
+        "network.http.referer.defaultPolicy",
+        "network.http.referer.defaultPolicy.pbmode",
+        "network.cookie.cookieBehavior",
+        "network.cookie.lifetimePolicy",
+        "privacy.restrict3rdpartystorage.expiration",
+        "privacy.trackingprotection.fingerprinting.enabled",
+        "privacy.trackingprotection.cryptomining.enabled",
+      ];
+      let prefsBody = "";
 
-        Assert.deepEqual(sections, [
-          "",
-          "Content-Disposition: form-data; name=\"title\"\r\n\r\ntracking.example.org\r\n",
-          "Content-Disposition: form-data; name=\"body\"\r\n\r\n" +
-          `Full URL: ${reportURL + "?"}\r\n` +
-          `userAgent: ${navigator.userAgent}\r\n\r\n` +
-          "**Preferences**\r\n" +
-          `${prefsBody}\r\n` +
-          "**Comments**\r\n" +
-          "This is a comment\r\n",
-          "Content-Disposition: form-data; name=\"labels\"\r\n\r\n" +
-          "trackingprotection\r\n",
-          "",
-        ], "Should send the correct form data");
+      for (let pref of prefs) {
+        prefsBody += `${pref}: ${Preferences.get(pref)}\r\n`;
+      }
 
-        resolve();
-      });
+      Assert.deepEqual(sections, [
+        "",
+        "Content-Disposition: form-data; name=\"title\"\r\n\r\ntracking.example.org\r\n",
+        "Content-Disposition: form-data; name=\"body\"\r\n\r\n" +
+        `Full URL: ${reportURL + "?"}\r\n` +
+        `userAgent: ${navigator.userAgent}\r\n\r\n` +
+        "**Preferences**\r\n" +
+        `${prefsBody}\r\n` +
+        "**Comments**\r\n" +
+        "This is a comment\r\n",
+        "Content-Disposition: form-data; name=\"labels\"\r\n\r\n" +
+        `${tags}\r\n`,
+        "",
+      ], "Should send the correct form data");
 
-      let comments = document.getElementById("identity-popup-breakageReportView-collection-comments");
-      comments.value = "This is a comment";
-      submitButton.click();
+      resolve();
     });
 
-    await popuphidden;
+    let comments = document.getElementById("identity-popup-breakageReportView-collection-comments");
+    comments.value = "This is a comment";
+    submitButton.click();
   });
 
+  await popuphidden;
+
   // Stop the server.
   await new Promise(r => server.stop(r));
 
-  Services.prefs.clearUserPref(TP_PREF);
   Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_ENABLED);
   Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
-});
-
-add_task(async function cleanup() {
-  // Clear prefs that are touched in this test again for sanity.
-  Services.prefs.clearUserPref(TP_PREF);
-  Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_ENABLED);
-  Services.prefs.clearUserPref(PREF_REPORT_BREAKAGE_URL);
-
-  UrlClassifierTestUtils.cleanupTestTrackers();
-});
+}
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -16,17 +16,16 @@ browser.jar:
 
         content/browser/illustrations/error-connection-failure.svg (content/illustrations/error-connection-failure.svg)
         content/browser/illustrations/error-server-not-found.svg (content/illustrations/error-server-not-found.svg)
         content/browser/illustrations/error-malformed-url.svg (content/illustrations/error-malformed-url.svg)
         content/browser/illustrations/under-construction.svg (content/illustrations/under-construction.svg)
         content/browser/illustrations/blue-berror.svg (content/illustrations/blue-berror.svg)
         content/browser/aboutNetError.xhtml            (content/aboutNetError.xhtml)
         content/browser/aboutNetError.js               (content/aboutNetError.js)
-        content/browser/aboutNetError-new.xhtml        (content/aboutNetError-new.xhtml)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
         content/browser/aboutTabCrashed.css           (content/aboutTabCrashed.css)
         content/browser/aboutTabCrashed.js            (content/aboutTabCrashed.js)
         content/browser/aboutTabCrashed.xhtml         (content/aboutTabCrashed.xhtml)
 *       content/browser/browser.css                   (content/browser.css)
         content/browser/browser.js                    (content/browser.js)
 #ifdef MOZ_BROWSER_XHTML
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -17,17 +17,16 @@
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 namespace browser {
 
 NS_IMPL_ISUPPORTS(AboutRedirector, nsIAboutModule)
 
 bool AboutRedirector::sNewTabPageEnabled = false;
-bool AboutRedirector::sNewCertErrorPageEnabled = false;
 
 static const uint32_t ACTIVITY_STREAM_FLAGS =
     nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::ENABLE_INDEXED_DB |
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
     nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGED_CHILD |
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT;
 
 struct RedirEntry {
@@ -140,23 +139,16 @@ AboutRedirector::NewChannel(nsIURI* aURI
 
   static bool sNTPEnabledCacheInited = false;
   if (!sNTPEnabledCacheInited) {
     Preferences::AddBoolVarCache(&AboutRedirector::sNewTabPageEnabled,
                                  "browser.newtabpage.enabled");
     sNTPEnabledCacheInited = true;
   }
 
-  static bool sNCEPEnabledCacheInited = false;
-  if (!sNCEPEnabledCacheInited) {
-    Preferences::AddBoolVarCache(&AboutRedirector::sNewCertErrorPageEnabled,
-                                 "browser.security.newcerterrorpage.enabled");
-    sNCEPEnabledCacheInited = true;
-  }
-
   for (auto& redir : kRedirMap) {
     if (!strcmp(path.get(), redir.id)) {
       nsAutoCString url;
 
       // Let the aboutNewTabService decide where to redirect for about:home and
       // enabled about:newtab. Disabledx about:newtab page uses fallback.
       if (path.EqualsLiteral("home") ||
           (sNewTabPageEnabled && path.EqualsLiteral("newtab"))) {
@@ -170,20 +162,16 @@ AboutRedirector::NewChannel(nsIURI* aURI
       if (path.EqualsLiteral("welcome")) {
         nsCOMPtr<nsIAboutNewTabService> aboutNewTabService =
             do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv);
         NS_ENSURE_SUCCESS(rv, rv);
         rv = aboutNewTabService->GetWelcomeURL(url);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
-      if (sNewCertErrorPageEnabled && path.EqualsLiteral("certerror")) {
-        url.AssignLiteral("chrome://browser/content/aboutNetError-new.xhtml");
-      }
-
       // fall back to the specified url in the map
       if (url.IsEmpty()) {
         url.AssignASCII(redir.url);
       }
 
       nsCOMPtr<nsIChannel> tempChannel;
       nsCOMPtr<nsIURI> tempURI;
       rv = NS_NewURI(getter_AddRefs(tempURI), url);
--- a/browser/components/customizableui/test/browser_947914_button_find.js
+++ b/browser/components/customizableui/test/browser_947914_button_find.js
@@ -1,16 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 add_task(async function() {
   info("Check find button existence and functionality");
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test.
+  gBrowser.selectedTab.focus();
   CustomizableUI.addWidgetToArea("find-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   registerCleanupFunction(() => CustomizableUI.reset());
 
   await waitForOverflowButtonShown();
 
   await document.getElementById("nav-bar").overflowable.show();
   info("Menu panel was opened");
 
--- a/browser/components/customizableui/test/browser_947914_button_history.js
+++ b/browser/components/customizableui/test/browser_947914_button_history.js
@@ -3,16 +3,19 @@
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
 
 add_task(async function() {
   info("Check history button existence and functionality");
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test.
+  gBrowser.selectedTab.focus();
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PATH + "dummy_history_item.html");
   BrowserTestUtils.removeTab(tab);
 
   tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PATH); // will 404, but we don't care.
 
   CustomizableUI.addWidgetToArea("history-panelmenu", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   registerCleanupFunction(() => CustomizableUI.reset());
 
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -498,16 +498,19 @@ async function openActionContextMenu(ext
 }
 
 function closeActionContextMenu(itemToSelect, kind, win = window) {
   let menuID = kind == "page" ? "pageActionContextMenu" : "toolbar-context-menu";
   return closeChromeContextMenu(menuID, itemToSelect, win);
 }
 
 function openTabContextMenu(win = window) {
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu before opening.
+  gBrowser.selectedTab.focus();
   return openChromeContextMenu("tabContextMenu", ".tabbrowser-tab[selected]", win);
 }
 
 function closeTabContextMenu(itemToSelect, win = window) {
   return closeChromeContextMenu("tabContextMenu", itemToSelect, win);
 }
 
 function getPageActionPopup(extension, win = window) {
--- a/browser/components/shell/HeadlessShell.jsm
+++ b/browser/components/shell/HeadlessShell.jsm
@@ -36,18 +36,18 @@ function loadContentWindow(webNavigation
         // Ignore inner-frame events
         if (progress != webProgress) {
           return;
         }
         // Ignore events that don't change the document
         if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
           return;
         }
-        // Ignore the initial about:blank
-        if (uri.spec != location.spec) {
+        // Ignore the initial about:blank, unless about:blank is requested
+        if (location.spec == "about:blank" && uri.spec != "about:blank") {
           return;
         }
         let contentWindow = docShell.domWindow;
         progressListeners.delete(progressListener);
         webProgress.removeProgressListener(progressListener);
         contentWindow.addEventListener("load", (event) => {
           resolve(contentWindow);
         }, { once: true });
--- a/browser/components/shell/test/chrome.ini
+++ b/browser/components/shell/test/chrome.ini
@@ -1,5 +1,8 @@
 [DEFAULT]
-support-files = headless.html
+support-files =
+  headless.html
+  headless_redirect.html
+  headless_redirect.html^headers^
 
 [test_headless_screenshot.html]
 skip-if = toolkit == 'android'
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/browser/components/shell/test/headless_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Moved Temporarily
+Location: headless.html
\ No newline at end of file
--- a/browser/components/shell/test/test_headless_screenshot.html
+++ b/browser/components/shell/test/test_headless_screenshot.html
@@ -132,16 +132,19 @@ https://bugzilla.mozilla.org/show_bug.cg
     await testFileCreationPositive(["-url", "http://mochi.test:8888/chrome/browser/components/shell/test/headless.html", "-screenshot", "--window-size=800"], "screenshot.png");
 
     // Test other variations of the "window-size" argument.
     await testWindowSizePositive(800, 600);
     await testWindowSizePositive(1234);
     await testFileCreationNegative(["-url", "http://mochi.test:8888/chrome/browser/components/shell/test/headless.html", "-screenshot", "-window-size", "hello"], "screenshot.png");
     await testFileCreationNegative(["-url", "http://mochi.test:8888/chrome/browser/components/shell/test/headless.html", "-screenshot", "-window-size", "800,"], "screenshot.png");
 
+    // Test when the requested URL redirects
+    await testFileCreationPositive(["-url", "http://mochi.test:8888/chrome/browser/components/shell/test/headless_redirect.html", "-screenshot", screenshotPath], screenshotPath);
+
     SimpleTest.finish();
   })();
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1378010">Mozilla Bug 1378010</a>
 <p id="display"></p>
 <div id="content" style="display: none">
--- a/browser/components/urlbar/UrlbarController.jsm
+++ b/browser/components/urlbar/UrlbarController.jsm
@@ -110,26 +110,27 @@ class UrlbarController {
   /**
    * Cancels an in-progress query. Note, queries may continue running if they
    * can't be cancelled.
    *
    * @param {UrlbarUtils.CANCEL_REASON} [reason]
    *   The reason the query was cancelled.
    */
   cancelQuery(reason) {
-    if (!this._lastQueryContext) {
+    if (!this._lastQueryContext ||
+        this._lastQueryContext._cancelled) {
       return;
     }
 
     TelemetryStopwatch.cancel(TELEMETRY_1ST_RESULT, this._lastQueryContext);
     TelemetryStopwatch.cancel(TELEMETRY_6_FIRST_RESULTS, this._lastQueryContext);
 
     this.manager.cancelQuery(this._lastQueryContext);
+    this._lastQueryContext._cancelled = true;
     this._notify("onQueryCancelled", this._lastQueryContext);
-    delete this._lastQueryContext;
 
     if (reason == UrlbarUtils.CANCEL_REASON.BLUR &&
         ExtensionSearchHandler.hasActiveInputSession()) {
       ExtensionSearchHandler.handleInputCancelled();
     }
   }
 
   /**
--- a/browser/components/urlbar/UrlbarView.jsm
+++ b/browser/components/urlbar/UrlbarView.jsm
@@ -31,18 +31,18 @@ class UrlbarView {
     this.panel = input.panel;
     this.controller = input.controller;
     this.document = this.panel.ownerDocument;
     this.window = this.document.defaultView;
 
     this._mainContainer = this.panel.querySelector(".urlbarView-body-inner");
     this._rows = this.panel.querySelector("#urlbarView-results");
 
+    this._rows.addEventListener("mousedown", this);
     this._rows.addEventListener("mouseup", this);
-    this._rows.addEventListener("mousedown", this);
 
     // For the horizontal fade-out effect, set the overflow attribute on result
     // rows when they overflow.
     this._rows.addEventListener("overflow", this);
     this._rows.addEventListener("underflow", this);
 
     this.panel.addEventListener("popupshowing", this);
     this.panel.addEventListener("popupshown", this);
@@ -135,16 +135,19 @@ class UrlbarView {
    *   Set to true to select the previous item. By default the next item
    *   will be selected.
    */
   selectBy(amount, {reverse = false} = {}) {
     if (!this.isOpen) {
       throw new Error("UrlbarView: Cannot select an item if the view isn't open.");
     }
 
+    // Freeze results as the user is interacting with them.
+    this.controller.cancelQuery();
+
     let row = this._selected;
 
     if (!row) {
       this._selectItem(reverse ? this._rows.lastElementChild :
                                  this._rows.firstElementChild);
       return;
     }
 
@@ -408,17 +411,17 @@ class UrlbarView {
     content.appendChild(favicon);
     item._elements.set("favicon", favicon);
 
     let title = this._createElement("span");
     title.className = "urlbarView-title";
     content.appendChild(title);
     item._elements.set("title", title);
 
-    let tagsContainer = this._createElement("div");
+    let tagsContainer = this._createElement("span");
     tagsContainer.className = "urlbarView-tags";
     content.appendChild(tagsContainer);
     item._elements.set("tagsContainer", tagsContainer);
 
     let titleSeparator = this._createElement("span");
     titleSeparator.className = "urlbarView-title-separator";
     content.appendChild(titleSeparator);
 
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -144,15 +144,12 @@ browser/features/formautofill@mozilla.or
 browser/chrome/browser/res/payments/formautofill/editAddress.xhtml
 browser/features/formautofill@mozilla.org/chrome/content/editCreditCard.xhtml
 browser/chrome/browser/res/payments/formautofill/editCreditCard.xhtml
 browser/features/formautofill@mozilla.org/chrome/content/autofillEditForms.js
 browser/chrome/browser/res/payments/formautofill/autofillEditForms.js
 # Bug 1451050 - Remote settings empty dumps (will be populated with data eventually)
 browser/defaults/settings/pinning/pins.json
 browser/defaults/settings/main/example.json
-# Bug 1463748 - Fork and pref-off the new error pages
-browser/chrome/browser/content/browser/aboutNetError-new.xhtml
-browser/chrome/browser/content/browser/aboutNetError.xhtml
 #ifdef MOZ_EME_WIN32_ARTIFACT
 gmp-clearkey/0.1/manifest.json
 i686/gmp-clearkey/0.1/manifest.json
 #endif
--- a/browser/locales/all-locales
+++ b/browser/locales/all-locales
@@ -1,13 +1,12 @@
 ach
 af
 an
 ar
-as
 ast
 az
 be
 bg
 bn
 br
 bs
 ca
@@ -16,17 +15,16 @@ crh
 cs
 cy
 da
 de
 dsb
 el
 en-CA
 en-GB
-en-ZA
 eo
 es-AR
 es-CL
 es-ES
 es-MX
 et
 eu
 fa
@@ -57,28 +55,25 @@ kk
 km
 kn
 ko
 lij
 lo
 lt
 ltg
 lv
-mai
 mk
-ml
 mr
 ms
 my
 nb-NO
 ne-NP
 nl
 nn-NO
 oc
-or
 pa-IN
 pl
 pt-BR
 pt-PT
 rm
 ro
 ru
 si
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/browser/tabContextMenu.ftl
@@ -0,0 +1,70 @@
+# 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/.
+
+reload-tab =
+    .label = Reload Tab
+    .accesskey = R
+select-all-tabs =
+    .label = Select All Tabs
+    .accesskey = S
+duplicate-tab =
+    .label = Duplicate Tab
+    .accesskey = D
+duplicate-tabs =
+    .label = Duplicate Tabs
+    .accesskey = D
+close-tabs-to-the-end =
+    .label = Close Tabs to the Right
+    .accesskey = i
+close-other-tabs =
+    .label = Close Other Tabs
+    .accesskey = o
+reload-tabs =
+    .label = Reload Tabs
+    .accesskey = R
+pin-tab =
+    .label = Pin Tab
+    .accesskey = P
+unpin-tab =
+    .label = Unpin Tab
+    .accesskey = p
+pin-selected-tabs =
+    .label = Pin Tabs
+    .accesskey = P
+unpin-selected-tabs =
+    .label = Unpin Tabs
+    .accesskey = p
+bookmark-selected-tabs =
+    .label = Bookmark Tabs…
+    .accesskey = B
+bookmark-tab =
+    .label = Bookmark Tab
+    .accesskey = B
+reopen-in-container =
+    .label = Reopen in Container
+    .accesskey = e
+move-to-start =
+    .label = Move to Start
+    .accesskey = S
+move-to-end =
+    .label = Move to End
+    .accesskey = E
+move-to-new-window =
+    .label = Move to New Window
+    .accesskey = W
+undo-close-tab =
+    .label = Undo Close Tab
+    .accesskey = U
+close-tab =
+    .label = Close Tab
+    .accesskey = c
+close-tabs =
+    .label = Close Tabs
+    .accesskey = S
+move-tabs =
+    .label = Move Tabs
+    .accesskey = v
+move-tab =
+    .label = Move Tab
+    .accesskey = v
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -14,60 +14,16 @@
 <!-- LOCALIZATION NOTE (mainWindow.titlePrivateBrowsingSuffix): This will be appended to the window's title
                                                                 inside the private browsing mode -->
 <!ENTITY mainWindow.titlePrivateBrowsingSuffix "(Private Browsing)">
 
 <!ENTITY appmenu.tooltip                     "Open menu">
 <!ENTITY navbarOverflow.label                "More tools…">
 
 <!-- Tab context menu -->
-<!ENTITY  reloadTab.label                    "Reload Tab">
-<!ENTITY  reloadTab.accesskey                "R">
-<!ENTITY  selectAllTabs.label                "Select All Tabs">
-<!ENTITY  selectAllTabs.accesskey            "S">
-<!-- LOCALIZATION NOTE (duplicateTab.label): This is a command to duplicate
-a tab (i.e. it is a verb, not adjective). -->
-<!ENTITY  duplicateTab.label                 "Duplicate Tab">
-<!-- LOCALIZATION NOTE (duplicateTab.accesskey, duplicateTabs.accesskey):
-These items have the same accesskey but will never be visible at the same time. -->
-<!ENTITY  duplicateTab.accesskey             "D">
-<!-- LOCALIZATION NOTE (duplicateTabs.label): This is a command to duplicate
-a tab (i.e. it is a verb, not adjective). -->
-<!ENTITY  duplicateTabs.label                "Duplicate Tabs">
-<!-- LOCALIZATION NOTE (duplicateTab.accesskey, duplicateTabs.accesskey):
-These items have the same accesskey but will never be visible at the same time. -->
-<!ENTITY  duplicateTabs.accesskey            "D">
-<!-- LOCALIZATION NOTE (closeTabsToTheEnd.label): This should indicate the
-direction in which tabs are closed, i.e. locales that use RTL mode should say
-left instead of right. -->
-<!ENTITY  closeTabsToTheEnd.label            "Close Tabs to the Right">
-<!ENTITY  closeTabsToTheEnd.accesskey        "i">
-<!ENTITY  closeOtherTabs.label               "Close Other Tabs">
-<!ENTITY  closeOtherTabs.accesskey           "o">
-
-<!ENTITY  closeTabs.label                    "Close Tabs">
-<!ENTITY  closeTabs.accesskey                "S">
-<!ENTITY  pinSelectedTabs.label              "Pin Tabs">
-<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
-unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
-same accesskey but will never be visible at the same time. -->
-<!ENTITY  pinSelectedTabs.accesskey          "P">
-<!ENTITY  unpinSelectedTabs.label            "Unpin Tabs">
-<!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
-unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
-same accesskey but will never be visible at the same time. -->
-<!ENTITY  unpinSelectedTabs.accesskey        "p">
-<!-- LOCALIZATION NOTE(reloadTab.label, reloadTabs.label): have the same accesskey
-but will never be visible at the same time. -->
-<!ENTITY  reloadTabs.label                   "Reload Tabs">
-<!ENTITY  reloadTabs.accesskey               "R">
-<!ENTITY  bookmarkSelectedTabs.label         "Bookmark Tabs…">
-<!-- LOCALIZATION NOTE(bookmarkTab.accesskey, bookmarkSelectedTabs.accesskey):
-These items have the same accesskey but will never be visible at the same time. -->
-<!ENTITY  bookmarkSelectedTabs.accesskey     "B">
 
 <!-- LOCALIZATION NOTE (pinTab.label, unpinTab.label): "Pin" is being
 used as a metaphor for expressing the fact that these tabs are "pinned" to the
 left edge of the tabstrip. Really we just want the string to express the idea
 that this is a lightweight and reversible action that keeps your tab where you
 can reach it easily. -->
 <!ENTITY  pinTab.label                       "Pin Tab">
 <!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
@@ -78,38 +34,18 @@ same accesskey but will never be visible
 <!-- LOCALIZATION NOTE(pinTab.accesskey, pinSelectedTabs.accesskey,
 unpinTab.accesskey, unpinSelectedTabs.accesskey): These share the
 same accesskey but will never be visible at the same time. -->
 <!ENTITY  unpinTab.accesskey                 "p">
 <!ENTITY  sendPageToDevice.label             "Send Page to Device">
 <!ENTITY  sendPageToDevice.accesskey         "n">
 <!ENTITY  sendLinkToDevice.label             "Send Link to Device">
 <!ENTITY  sendLinkToDevice.accesskey         "n">
-<!-- LOCALIZATION NOTE (moveTabOptions.label and moveSelectedTabOptions.label):
-These two items have the same accesskey but will never be visible at the same time. -->
-<!ENTITY  moveTabOptions.label               "Move Tab">
-<!ENTITY  moveTabOptions.accesskey           "v">
-<!ENTITY  moveSelectedTabOptions.label       "Move Tabs">
-<!ENTITY  moveSelectedTabOptions.accesskey   "v">
-<!ENTITY  moveToStart.label                  "Move to Start">
-<!ENTITY  moveToStart.accesskey              "S">
-<!ENTITY  moveToEnd.label                    "Move to End">
-<!ENTITY  moveToEnd.accesskey                "E">
-<!ENTITY  moveToNewWindow.label              "Move to New Window">
-<!ENTITY  moveToNewWindow.accesskey          "W">
-<!ENTITY  reopenInContainer.label            "Reopen in Container">
-<!ENTITY  reopenInContainer.accesskey        "e">
-<!ENTITY  bookmarkTab.label                  "Bookmark Tab">
-<!-- LOCALIZATION NOTE(bookmarkTab.accesskey, bookmarkSelectedTabs.accesskey):
-These items have the same accesskey but will never be visible at the same time. -->
-<!ENTITY  bookmarkTab.accesskey              "B">
 <!ENTITY  undoCloseTab.label                 "Undo Close Tab">
 <!ENTITY  undoCloseTab.accesskey             "U">
-<!ENTITY  closeTab.label                     "Close Tab">
-<!ENTITY  closeTab.accesskey                 "c">
 <!ENTITY  hiddenTabs.label                   "Hidden Tabs">
 
 <!ENTITY  listAllTabs.label      "List all tabs">
 <!-- LOCALIZATION NOTE (allTabsMenu.searchTabs.label): "Search" is a verb, as
 in "Search through tabs". -->
 <!ENTITY  allTabsMenu.searchTabs.label       "Search Tabs">
 
 <!ENTITY tabCmd.label "New Tab">
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -4,17 +4,16 @@
 
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
 %brandDTD;
 
 <!ENTITY loadError.label "Problem loading page">
 <!ENTITY retry.label "Try Again">
 <!ENTITY returnToPreviousPage.label "Go Back">
 <!ENTITY returnToPreviousPage1.label "Go Back (Recommended)">
-<!ENTITY advanced.label "Advanced">
 <!ENTITY advanced2.label "Advanced…">
 <!ENTITY viewCertificate.label "View Certificate">
 
 <!-- Specific error messages -->
 
 <!ENTITY connectionFailure.title "Unable to connect">
 <!ENTITY connectionFailure.longDesc "&sharedLongDesc;">
 
@@ -143,23 +142,21 @@
 <!ENTITY nssFailure2.title "Secure Connection Failed">
 <!ENTITY nssFailure2.longDesc2 "
 <ul>
   <li>The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.</li>
   <li>Please contact the website owners to inform them of this problem.</li>
 </ul>
 ">
 
-<!ENTITY certerror.longpagetitle1 "Your connection is not secure">
 <!ENTITY certerror.longpagetitle2 "Warning: Potential Security Risk Ahead">
 <!ENTITY certerror.sts.longpagetitle  "Did Not Connect: Potential Security Issue">
-<!-- Localization note (certerror.introPara, certerror.introPara2) - The text content of the span tag
+<!-- Localization note (certerror.introPara2) - The text content of the span tag
 will be replaced at runtime with the name of the server to which the user
 was trying to connect. -->
-<!ENTITY certerror.introPara "The owner of <span class='hostname'/> has configured their website improperly.  To protect your information from being stolen, &brandShortName; has not connected to this website.">
 <!ENTITY certerror.introPara2 "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/>. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.">
 <!ENTITY certerror.sts.introPara "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/> because this website requires a secure connection.">
 
 <!ENTITY certerror.expiredCert.introPara "&brandShortName; detected an issue and did not continue to <span class='hostname'/>. The website is either misconfigured or your computer clock is set to the wrong time.">
 <!ENTITY certerror.expiredCert.secondPara2 "It’s likely the website’s certificate is expired, which prevents &brandShortName; from connecting securely. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.">
 <!ENTITY certerror.expiredCert.sts.secondPara "It’s likely the website’s certificate is expired, which prevents &brandShortName; from connecting securely.">
 
 <!ENTITY certerror.whatCanYouDoAboutItTitle "What can you do about it?">
@@ -190,18 +187,16 @@ was trying to connect. -->
 ">
 
 <!ENTITY cspBlocked.title "Blocked by Content Security Policy">
 <!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
 
 <!ENTITY corruptedContentErrorv2.title "Corrupted Content Error">
 <!ENTITY corruptedContentErrorv2.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
 
-
-<!ENTITY securityOverride.exceptionButtonLabel "Add Exception…">
 <!ENTITY securityOverride.exceptionButton1Label "Accept the Risk and Continue">
 
 <!ENTITY errorReporting.automatic2 "Report errors like this to help Mozilla identify and block malicious sites">
 <!ENTITY errorReporting.learnMore "Learn more…">
 
 <!ENTITY remoteXUL.title "Remote XUL">
 <!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
 
@@ -211,23 +206,18 @@ was trying to connect. -->
 <!ENTITY sslv3Used.longDesc2 "Advanced info: SSL_ERROR_UNSUPPORTED_VERSION">
 
 <!-- LOCALIZATION NOTE (certerror.wrongSystemTime2,
                         certerror.wrongSystemTimeWithoutReference) - The <span id='..' />
      tags will be injected with actual values, please leave them unchanged. -->
 <!ENTITY certerror.wrongSystemTime2 "<p> &brandShortName; did not connect to <span id='wrongSystemTime_URL'/> because your computer’s clock appears to show the wrong time and this is preventing a secure connection.</p> <p>Your computer is set to <span id='wrongSystemTime_systemDate'/>, when it should be <span id='wrongSystemTime_actualDate'/>. To fix this problem, change your date and time settings to match the correct time.</p>">
 <!ENTITY certerror.wrongSystemTimeWithoutReference "<p>&brandShortName; did not connect to <span id='wrongSystemTimeWithoutReference_URL'/> because your computer’s clock appears to show the wrong time and this is preventing a secure connection.</p> <p>Your computer is set to <span id='wrongSystemTimeWithoutReference_systemDate'/>. To fix this problem, change your date and time settings to match the correct time.</p>">
 
-<!ENTITY certerror.pagetitle1  "Insecure Connection">
 <!ENTITY certerror.pagetitle2  "Warning: Potential Security Risk Ahead">
 <!ENTITY certerror.sts.pagetitle  "Did Not Connect: Potential Security Issue">
-<!ENTITY certerror.whatShouldIDo.badStsCertExplanation "This site uses HTTP
-Strict Transport Security (HSTS) to specify that &brandShortName; may only connect
-to it securely. As a result, it is not possible to add an exception for this
-certificate.">
 <!ENTITY certerror.whatShouldIDo.badStsCertExplanation1 "<span class='hostname'></span> has a security policy called HTTP Strict Transport Security (HSTS), which means that &brandShortName; can only connect to it securely. You can’t add an exception to visit this site.">
 <!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
 
 <!ENTITY inadequateSecurityError.title "Your connection is not secure">
 <!-- LOCALIZATION NOTE (inadequateSecurityError.longDesc) - Do not translate
      "NS_ERROR_NET_INADEQUATE_SECURITY". -->
 <!ENTITY inadequateSecurityError.longDesc "<p><span class='hostname'></span> uses security technology that is outdated and vulnerable to attack. An attacker could easily reveal information which you thought to be safe. The website administrator will need to fix the server first before you can visit the site.</p><p>Error code: NS_ERROR_NET_INADEQUATE_SECURITY</p>">
 
--- a/browser/locales/l10n.toml
+++ b/browser/locales/l10n.toml
@@ -4,17 +4,16 @@
 
 basepath = "../.."
 
 locales = [
     "ach",
     "af",
     "an",
     "ar",
-    "as",
     "ast",
     "az",
     "be",
     "bg",
     "bn",
     "br",
     "bs",
     "ca",
@@ -23,17 +22,16 @@ locales = [
     "cs",
     "cy",
     "da",
     "de",
     "dsb",
     "el",
     "en-CA",
     "en-GB",
-    "en-ZA",
     "eo",
     "es-AR",
     "es-CL",
     "es-ES",
     "es-MX",
     "et",
     "eu",
     "fa",
@@ -64,28 +62,25 @@ locales = [
     "km",
     "kn",
     "ko",
     "lij",
     "lo",
     "lt",
     "ltg",
     "lv",
-    "mai",
     "mk",
-    "ml",
     "mr",
     "ms",
     "my",
     "nb-NO",
     "ne-NP",
     "nl",
     "nn-NO",
     "oc",
-    "or",
     "pa-IN",
     "pl",
     "pt-BR",
     "pt-PT",
     "rm",
     "ro",
     "ru",
     "si",
--- a/browser/locales/shipped-locales
+++ b/browser/locales/shipped-locales
@@ -1,13 +1,12 @@
 ach
 af
 an
 ar
-as
 ast
 az
 be
 bg
 bn
 br
 bs
 ca
@@ -16,17 +15,16 @@ cs
 cy
 da
 de
 dsb
 el
 en-CA
 en-GB
 en-US
-en-ZA
 eo
 es-AR
 es-CL
 es-ES
 es-MX
 et
 eu
 fa
@@ -55,28 +53,25 @@ ka
 kab
 kk
 km
 kn
 ko
 lij
 lt
 lv
-mai
 mk
-ml
 mr
 ms
 my
 nb-NO
 ne-NP
 nl
 nn-NO
 oc
-or
 pa-IN
 pl
 pt-BR
 pt-PT
 rm
 ro
 ru
 si
deleted file mode 100644
--- a/browser/themes/shared/aboutNetError-new.css
+++ /dev/null
@@ -1,290 +0,0 @@
-/* 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/. */
-
-@import url("chrome://browser/skin/error-pages.css");
-
-:root {
-  --exception-button-container-background: #F5F5F7;
-}
-
-body.certerror {
-  width: 100%;
-  justify-content: normal;
-}
-
-body.caution {
-  border-style: solid;
-  border-color: #ffe900;
-  border-width: 16px;
-}
-
-body.captiveportal .title {
-  background-image: url("wifi.svg");
-}
-
-body.certerror .title {
-  background-image: url("cert-error-new.svg");
-}
-
-body.blocked .title {
-  background-image: url("chrome://global/skin/icons/blocked.svg");
-}
-
-body.clockSkewError .title {
-  background-image: none;
-  background-repeat: no-repeat;
-}
-
-#errorContainer {
-  display: none;
-}
-
-/* Pressing the retry button will cause the cursor to flicker from a pointer to
- * not-allowed. Override the disabled cursor behaviour since we will never show
- * the button disabled as the initial state. */
-button:disabled {
-  cursor: pointer;
-}
-
-#errorWhatToDoTitle {
-  margin-top: 2em;
-}
-
-#prefChangeContainer {
-  display: none;
-}
-
-#learnMoreContainer {
-  display: none;
-}
-
-#certErrorAndCaptivePortalButtonContainer {
-  display: none;
-}
-
-#advancedPanelButtonContainer {
-  background-color: var(--exception-button-container-background);
-  display: flex;
-  justify-content: end;
-  padding: 5px;
-  margin-top: 2em;
-}
-
-body:not(.neterror) #certErrorAndCaptivePortalButtonContainer {
-  display: flex;
-}
-
-body:not(.neterror) #netErrorButtonContainer {
-  display: none;
-}
-
-#errorTryAgain {
-  margin-top: 1.2em;
-}
-
-#advancedButton {
-  display: none;
-}
-
-body.captiveportal #returnButton {
-  display: none;
-}
-
-body:not(.captiveportal) #openPortalLoginPageButton {
-  display: none;
-}
-
-body:not(.clockSkewError) #errorTryAgain {
-  display: none;
-}
-
-body:not(.clockSkewError) #advancedPanelErrorTryAgain {
-  display: none;
-}
-
-#openPortalLoginPageButton {
-  margin-inline-start: 0;
-}
-
-body:not(.neterror) #advancedButton {
-  display: block;
-}
-
-#certificateErrorReporting {
-  display: none;
-  padding-bottom: 10px;
-}
-
-#advancedPanelContainer {
-  width: 100%;
-  left: 0;
-}
-
-.advanced-panel {
-  /* Hidden until the link is clicked */
-  display: none;
-  background-color: white;
-  border: 1px lightgray solid;
-  margin: 48px auto;
-  min-width: var(--in-content-container-min-width);
-  max-width: var(--in-content-container-max-width);
-}
-
-#overrideWeakCryptoPanel {
-  display: none;
-  flex-direction: row;
-  flex-wrap: wrap;
-  justify-content: space-between;
-  align-content: space-between;
-  align-items: flex-start;
-  margin-top: 1em;
-}
-
-.mitm-name,
-#hostname {
-  font-weight: bold;
-}
-
-#automaticallyReportInFuture {
-  cursor: pointer;
-  /* Prevent the checkbox from looking super
-   * squeezed on small viewports */
-  flex-shrink: 0;
-}
-
-#errorCode:not([href]) {
-  color: var(--in-content-page-color);
-  cursor: text;
-  text-decoration: none;
-}
-
-#errorCode[href] {
-  white-space: nowrap;
-}
-
-#viewCertificate {
-  margin: 0 3em;
-}
-
-#badCertTechnicalInfo {
-  margin: 3em 3em 1em;
-  overflow: auto;
-  white-space: pre-wrap;
-}
-
-#certificateErrorReporting {
-  display: none;
-}
-
-#certificateErrorDebugInformation {
-  display: none;
-  background-color: var(--in-content-box-background-hover) !important;
-  border-top: 1px solid var(--in-content-border-color);
-  width: 100%;
-  padding: 1em 17.5%;
-  box-sizing: border-box;
-}
-
-#certificateErrorText {
-  font-family: monospace;
-  white-space: pre-wrap;
-  padding: 1em 0;
-  display: flex;
-  flex-wrap: wrap;
-}
-
-#cert_domain_link:not([href]) {
-  color: var(--in-content-page-color);
-  text-decoration: none;
-}
-
-.exceptionDialogButtonContainer {
-  background-color: var(--exception-button-container-background);
-  display: flex;
-  justify-content: end;
-}
-
-.exceptionDialogButtonContainer[hidden] {
-  display: none;
-}
-
-.connectionFailure #errorPageContainer,
-.netInterrupt #errorPageContainer,
-.netTimeout #errorPageContainer,
-.netReset #errorPageContainer,
-.netOffline #errorPageContainer {
-  background-image: url("chrome://browser/content/illustrations/error-connection-failure.svg");
-}
-
-.dnsNotFound #errorPageContainer {
-  background-image: url("chrome://browser/content/illustrations/error-server-not-found.svg");
-}
-
-.malformedURI #errorPageContainer {
-  background-image: url("chrome://browser/content/illustrations/error-malformed-url.svg");
-}
-
-.clockSkewError #errorPageContainer {
-  background-image: url("chrome://browser/content/illustrations/blue-berror.svg");
-  background-size: 18.5em;
-}
-
-.clockSkewError #returnButton {
-  display: none;
-}
-
-.clockSkewError #advancedButton {
-  display: none;
-}
-
-.clockSkewError #advancedPanelErrorTryAgain,
-.clockSkewError #errorTryAgain {
-  display: block;
-  margin-top: 0.3em;
-}
-
-.clockSkewError #exceptionDialogButton {
-  display: none;
-}
-
-.clockSkewError #advancedPanelReturnButton {
-  display: none;
-}
-
-.malformedURI #errorTryAgain {
-  display: none;
-}
-
-#wrongSystemTimePanel {
-  display: none;
-}
-
-#wrongSystemTimeWithoutReferencePanel {
-  display: none;
-}
-
-@media only screen and (max-width: 959px) {
-  #certificateErrorText {
-    /* The encoded certificate chain looks better when we're not
-     * wrapping words on big screens, but at some point we need
-     * to wrap to avoid overflowing */
-    word-wrap: anywhere;
-  }
-}
-
-@media only screen and (max-width: 480px) {
-  #badCertTechnicalInfo {
-    margin: 10px 10px 5px;
-  }
-
-  #viewCertificate {
-    margin: 0 10px;
-  }
-
-  #errorCode[href] {
-    /* Break the error code to avoid long codes overflowing the screen */
-    white-space: normal;
-    word-wrap: anywhere;
-  }
-}
--- a/browser/themes/shared/aboutNetError.css
+++ b/browser/themes/shared/aboutNetError.css
@@ -4,96 +4,124 @@
 
 @import url("chrome://browser/skin/error-pages.css");
 
 :root {
   --exception-button-container-background: #F5F5F7;
 }
 
 body.certerror {
+  width: 100%;
   justify-content: normal;
 }
 
+body.caution {
+  border-style: solid;
+  border-color: #ffe900;
+  border-width: 16px;
+}
+
 body.captiveportal .title {
   background-image: url("wifi.svg");
 }
 
 body.certerror .title {
   background-image: url("cert-error.svg");
 }
 
 body.blocked .title {
   background-image: url("chrome://global/skin/icons/blocked.svg");
 }
 
+body.clockSkewError .title {
+  background-image: none;
+  background-repeat: no-repeat;
+}
+
 #errorContainer {
   display: none;
 }
 
 /* Pressing the retry button will cause the cursor to flicker from a pointer to
  * not-allowed. Override the disabled cursor behaviour since we will never show
  * the button disabled as the initial state. */
 button:disabled {
   cursor: pointer;
 }
 
+#errorWhatToDoTitle {
+  margin-top: 2em;
+}
+
 #prefChangeContainer {
   display: none;
 }
 
 #learnMoreContainer {
   display: none;
 }
 
 #certErrorAndCaptivePortalButtonContainer {
   display: none;
 }
 
+#advancedPanelButtonContainer {
+  background-color: var(--exception-button-container-background);
+  display: flex;
+  justify-content: end;
+  padding: 5px;
+  margin-top: 2em;
+}
+
 body:not(.neterror) #certErrorAndCaptivePortalButtonContainer {
   display: flex;
 }
 
 body:not(.neterror) #netErrorButtonContainer {
   display: none;
 }
 
-#advancedPanelErrorTryAgain {
-  display: none;
-}
-
 #errorTryAgain {
   margin-top: 1.2em;
 }
 
 #advancedButton {
   display: none;
 }
 
 body.captiveportal #returnButton {
   display: none;
 }
 
 body:not(.captiveportal) #openPortalLoginPageButton {
   display: none;
 }
 
+body:not(.clockSkewError) #errorTryAgain {
+  display: none;
+}
+
+body:not(.clockSkewError) #advancedPanelErrorTryAgain {
+  display: none;
+}
+
 #openPortalLoginPageButton {
   margin-inline-start: 0;
 }
 
 body:not(.neterror) #advancedButton {
   display: block;
 }
 
 #certificateErrorReporting {
   display: none;
+  padding-bottom: 10px;
 }
 
 #advancedPanelContainer {
-  position: absolute;
   width: 100%;
   left: 0;
 }
 
 .advanced-panel {
   /* Hidden until the link is clicked */
   display: none;
   background-color: white;
@@ -108,49 +136,56 @@ body:not(.neterror) #advancedButton {
   flex-direction: row;
   flex-wrap: wrap;
   justify-content: space-between;
   align-content: space-between;
   align-items: flex-start;
   margin-top: 1em;
 }
 
-span#hostname {
+.mitm-name,
+#hostname {
   font-weight: bold;
 }
 
 #automaticallyReportInFuture {
   cursor: pointer;
+  /* Prevent the checkbox from looking super
+   * squeezed on small viewports */
+  flex-shrink: 0;
 }
 
 #errorCode:not([href]) {
   color: var(--in-content-page-color);
   cursor: text;
   text-decoration: none;
 }
 
 #errorCode[href] {
   white-space: nowrap;
 }
 
+#viewCertificate {
+  margin: 0 3em;
+}
+
 #badCertTechnicalInfo {
-  margin: 3em;
+  margin: 3em 3em 1em;
   overflow: auto;
   white-space: pre-wrap;
 }
 
 #certificateErrorReporting {
   display: none;
 }
 
 #certificateErrorDebugInformation {
   display: none;
   background-color: var(--in-content-box-background-hover) !important;
   border-top: 1px solid var(--in-content-border-color);
-  position: absolute;
   width: 100%;
   padding: 1em 17.5%;
   box-sizing: border-box;
 }
 
 #certificateErrorText {
   font-family: monospace;
   white-space: pre-wrap;
@@ -163,17 +198,16 @@ span#hostname {
   color: var(--in-content-page-color);
   text-decoration: none;
 }
 
 .exceptionDialogButtonContainer {
   background-color: var(--exception-button-container-background);
   display: flex;
   justify-content: end;
-  padding: 10px;
 }
 
 .exceptionDialogButtonContainer[hidden] {
   display: none;
 }
 
 .connectionFailure #errorPageContainer,
 .netInterrupt #errorPageContainer,
@@ -186,19 +220,71 @@ span#hostname {
 .dnsNotFound #errorPageContainer {
   background-image: url("chrome://browser/content/illustrations/error-server-not-found.svg");
 }
 
 .malformedURI #errorPageContainer {
   background-image: url("chrome://browser/content/illustrations/error-malformed-url.svg");
 }
 
+.clockSkewError #errorPageContainer {
+  background-image: url("chrome://browser/content/illustrations/blue-berror.svg");
+  background-size: 18.5em;
+}
+
+.clockSkewError #returnButton {
+  display: none;
+}
+
+.clockSkewError #advancedButton {
+  display: none;
+}
+
+.clockSkewError #advancedPanelErrorTryAgain,
+.clockSkewError #errorTryAgain {
+  display: block;
+  margin-top: 0.3em;
+}
+
+.clockSkewError #exceptionDialogButton {
+  display: none;
+}
+
+.clockSkewError #advancedPanelReturnButton {
+  display: none;
+}
+
 .malformedURI #errorTryAgain {
   display: none;
 }
 
 #wrongSystemTimePanel {
   display: none;
 }
 
 #wrongSystemTimeWithoutReferencePanel {
   display: none;
 }
+
+@media only screen and (max-width: 959px) {
+  #certificateErrorText {
+    /* The encoded certificate chain looks better when we're not
+     * wrapping words on big screens, but at some point we need
+     * to wrap to avoid overflowing */
+    word-wrap: anywhere;
+  }
+}
+
+@media only screen and (max-width: 480px) {
+  #badCertTechnicalInfo {
+    margin: 10px 10px 5px;
+  }
+
+  #viewCertificate {
+    margin: 0 10px;
+  }
+
+  #errorCode[href] {
+    /* Break the error code to avoid long codes overflowing the screen */
+    white-space: normal;
+    word-wrap: anywhere;
+  }
+}
--- a/browser/themes/shared/browser.inc.css
+++ b/browser/themes/shared/browser.inc.css
@@ -20,16 +20,22 @@
 }
 
 @media (min-resolution: 1.5dppx) {
   :root {
     --tabs-navbar-shadow-size: 0.5px;
   }
 }
 
+@media (min-resolution: 3dppx) {
+  :root {
+    --tabs-navbar-shadow-size: 0.33px;
+  }
+}
+
 /* Increase contrast of UI links on dark themes */
 
 :root[lwt-popup-brighttext] panel .text-link {
   color: @lwtPopupBrighttextLinkColor@;
 }
 
 /* Toolbar / content area border */
 
deleted file mode 100644
--- a/browser/themes/shared/incontent-icons/cert-error-new.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg height="96" viewBox="0 0 96 96" width="96" xmlns="http://www.w3.org/2000/svg">
-  <g fill="none" fill-rule="evenodd">
-    <path d="m54 87h-38.718c-4.1514504-.0042773-8.00579913-2.1539983-10.19089334-5.6838598-2.1850942-3.5298615-2.39050529-7.9383886-.54310666-11.6561402l29.718-59.46c2.0323569-4.06636891 6.1880314-6.63518463 10.734-6.63518463s8.7016431 2.56881572 10.734 6.63518463l19.0437959 38.0875919c-8.4035561 1.5187368-14.7777959 8.8711807-14.7777959 17.7124081v1.0104467c-3.547421 1.6851959-6 5.3009594-6 9.4895533z" fill="#ffe900" fill-rule="nonzero"/>
-    <path d="m39 27c0-3.3137085 2.6862915-6 6-6s6 2.6862915 6 6v24c0 3.3137085-2.6862915 6-6 6s-6-2.6862915-6-6zm6 49.5c-4.1421356 0-7.5-3.3578644-7.5-7.5s3.3578644-7.5 7.5-7.5 7.5 3.3578644 7.5 7.5-3.3578644 7.5-7.5 7.5z" fill="#3e2800"/>
-    <path d="m89.2954301 61.9390003c.4560585 1.2683141.7045699 2.6356354.7045699 4.0609997v6h1.5c2.4620372-.0002189 4.4671728 1.9781816 4.5 4.44v15c.0160526 1.203836-.4509571 2.3639032-1.296617 3.2208385-.8456598.8569353-1.99944 1.3392685-3.203383 1.3391615h-27c-2.4852814 0-4.5-2.0147186-4.5-4.5v-15c0-2.4852814 2.0147186-4.5 4.5-4.5h1.5v-6c0-6.627417 5.372583-12 12-12 2.9975478 0 5.7383932 1.0990736 7.8415359 2.9162204l-4.2654615 4.2654616c-.998662-.7424058-2.236069-1.181682-3.5760744-1.181682-3.3137085 0-6 2.6862915-6 6v6h12v-4.7655696z" fill="#b1b1b3" fill-rule="nonzero"/>
-  </g>
-</svg>
\ No newline at end of file
--- a/browser/themes/shared/incontent-icons/cert-error.svg
+++ b/browser/themes/shared/incontent-icons/cert-error.svg
@@ -1,41 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<svg version="1.1"
-     xmlns="http://www.w3.org/2000/svg"
-     width="45"
-     height="45"
-     viewBox="0 0 45 45">
-
-  <style>
-    .icon-default {
-      fill: #999;
-    }
-  </style>
-
-  <defs>
-    <rect id="shape-lock-clasp-outer" x="8" y="2" width="28" height="40" rx="14" ry="14" />
-    <rect id="shape-lock-clasp-inner" x="14" y="8" width="16" height="28" rx="8" ry="8" />
-    <rect id="shape-lock-base" x="4" y="18" width="36" height="24" rx="3" ry="3" />
-
-    <mask id="mask-clasp-cutout">
-      <rect width="48" height="48" fill="#000" />
-      <use href="#shape-lock-clasp-outer" fill="#fff" />
-      <use href="#shape-lock-clasp-inner" fill="#000" />
-      <line x1="4" y1="38" x2="41" y2="3" stroke="#000" stroke-width="5.5" />
-      <line x1="4" y1="46" x2="41" y2="11" stroke="#000" stroke-width="5.5" />
-      <rect x="4" y="18" width="36" height="26" rx="6" ry="6" />
-    </mask>
-
-    <mask id="mask-base-cutout">
-      <rect width="45" height="45" fill="#000" />
-      <use href="#shape-lock-base" fill="#fff" />
-      <line x1="2.5" y1="41.5" x2="41" y2="5" stroke="#000" stroke-width="8.5" />
-    </mask>
-  </defs>
-
-  <use href="#shape-lock-clasp-outer" mask="url(#mask-clasp-cutout)" fill="#999" />
-  <use href="#shape-lock-base" mask="url(#mask-base-cutout)" fill="#999" />
-
-  <line x1="2.5" y1="41.5" x2="41" y2="5" stroke="#d92d21" stroke-width="5.5" />
-
+<svg height="96" viewBox="0 0 96 96" width="96" xmlns="http://www.w3.org/2000/svg">
+  <g fill="none" fill-rule="evenodd">
+    <path d="m54 87h-38.718c-4.1514504-.0042773-8.00579913-2.1539983-10.19089334-5.6838598-2.1850942-3.5298615-2.39050529-7.9383886-.54310666-11.6561402l29.718-59.46c2.0323569-4.06636891 6.1880314-6.63518463 10.734-6.63518463s8.7016431 2.56881572 10.734 6.63518463l19.0437959 38.0875919c-8.4035561 1.5187368-14.7777959 8.8711807-14.7777959 17.7124081v1.0104467c-3.547421 1.6851959-6 5.3009594-6 9.4895533z" fill="#ffe900" fill-rule="nonzero"/>
+    <path d="m39 27c0-3.3137085 2.6862915-6 6-6s6 2.6862915 6 6v24c0 3.3137085-2.6862915 6-6 6s-6-2.6862915-6-6zm6 49.5c-4.1421356 0-7.5-3.3578644-7.5-7.5s3.3578644-7.5 7.5-7.5 7.5 3.3578644 7.5 7.5-3.3578644 7.5-7.5 7.5z" fill="#3e2800"/>
+    <path d="m89.2954301 61.9390003c.4560585 1.2683141.7045699 2.6356354.7045699 4.0609997v6h1.5c2.4620372-.0002189 4.4671728 1.9781816 4.5 4.44v15c.0160526 1.203836-.4509571 2.3639032-1.296617 3.2208385-.8456598.8569353-1.99944 1.3392685-3.203383 1.3391615h-27c-2.4852814 0-4.5-2.0147186-4.5-4.5v-15c0-2.4852814 2.0147186-4.5 4.5-4.5h1.5v-6c0-6.627417 5.372583-12 12-12 2.9975478 0 5.7383932 1.0990736 7.8415359 2.9162204l-4.2654615 4.2654616c-.998662-.7424058-2.236069-1.181682-3.5760744-1.181682-3.3137085 0-6 2.6862915-6 6v6h12v-4.7655696z" fill="#b1b1b3" fill-rule="nonzero"/>
+  </g>
 </svg>
\ No newline at end of file
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This is not a complete / proper jar manifest. It is included by the
 # actual theme-specific manifests, so that shared resources need only
 # be specified once. As a result, the source file paths are relative
 # to the location of the actual manifest.
 
   skin/classic/browser/aboutNetError.css                       (../shared/aboutNetError.css)
-  skin/classic/browser/aboutNetError-new.css                   (../shared/aboutNetError-new.css)
   skin/classic/browser/blockedSite.css                         (../shared/blockedSite.css)
   skin/classic/browser/error-pages.css                         (../shared/error-pages.css)
   skin/classic/browser/aboutRestartRequired.css                (../shared/aboutRestartRequired.css)
 * skin/classic/browser/aboutSessionRestore.css                 (../shared/aboutSessionRestore.css)
   skin/classic/browser/aboutLibrary.css                        (../shared/aboutLibrary.css)
   skin/classic/browser/aboutTabCrashed.css                     (../shared/aboutTabCrashed.css)
   skin/classic/browser/aboutWelcomeBack.css                    (../shared/aboutWelcomeBack.css)
   skin/classic/browser/setDesktopBackground.css                (../shared/setDesktopBackground.css)
@@ -237,17 +236,16 @@
 
   skin/classic/browser/translating-16.png                      (../shared/translation/translating-16.png)
   skin/classic/browser/translating-16@2x.png                   (../shared/translation/translating-16@2x.png)
   skin/classic/browser/translation-16.png                      (../shared/translation/translation-16.png)
   skin/classic/browser/translation-16@2x.png                   (../shared/translation/translation-16@2x.png)
   skin/classic/browser/update-badge.svg                        (../shared/update-badge.svg)
   skin/classic/browser/warning.svg                             (../shared/warning.svg)
   skin/classic/browser/cert-error.svg                          (../shared/incontent-icons/cert-error.svg)
-  skin/classic/browser/cert-error-new.svg                      (../shared/incontent-icons/cert-error-new.svg)
   skin/classic/browser/wifi.svg                                (../shared/incontent-icons/wifi.svg)
   skin/classic/browser/tab-crashed.svg                         (../shared/incontent-icons/tab-crashed.svg)
   skin/classic/browser/welcome-back.svg                        (../shared/incontent-icons/welcome-back.svg)
   skin/classic/browser/readerMode.svg                          (../shared/reader/readerMode.svg)
   skin/classic/browser/panic-panel/header.png                  (../shared/panic-panel/header.png)
   skin/classic/browser/panic-panel/header@2x.png               (../shared/panic-panel/header@2x.png)
   skin/classic/browser/panic-panel/icons.png                   (../shared/panic-panel/icons.png)
   skin/classic/browser/panic-panel/icons@2x.png                (../shared/panic-panel/icons@2x.png)
--- a/chrome/nsChromeRegistry.cpp
+++ b/chrome/nsChromeRegistry.cpp
@@ -16,33 +16,34 @@
 #include "nsQueryObject.h"
 
 #include "mozilla/dom/URL.h"
 #include "nsDOMWindowList.h"
 #include "nsIConsoleService.h"
 #include "mozilla/dom/Document.h"
 #include "nsIDOMWindow.h"
 #include "nsIObserverService.h"
-#include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsIWindowMediator.h"
 #include "nsIPrefService.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/Printf.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/dom/Location.h"
 #include "nsIURIMutator.h"
 
 #include "unicode/uloc.h"
 
 nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
 
 // DO NOT use namespace mozilla; it'll break due to a naming conflict between
 // mozilla::TextRange and a TextRange in OSX headers.
+using mozilla::PresShell;
 using mozilla::StyleSheet;
 using mozilla::dom::Document;
 using mozilla::dom::IsChromeURI;
 using mozilla::dom::Location;
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void nsChromeRegistry::LogMessage(const char* aMsg, ...) {
@@ -339,21 +340,21 @@ nsresult nsChromeRegistry::RefreshWindow
   }
 
   nsresult rv;
   // Get the document.
   RefPtr<Document> document = aWindow->GetDoc();
   if (!document) return NS_OK;
 
   // Deal with the agent sheets first.  Have to do all the style sets by hand.
-  nsCOMPtr<nsIPresShell> shell = document->GetShell();
-  if (shell) {
+  RefPtr<PresShell> presShell = document->GetPresShell();
+  if (presShell) {
     // Reload only the chrome URL agent style sheets.
     nsTArray<RefPtr<StyleSheet>> agentSheets;
-    rv = shell->GetAgentStyleSheets(agentSheets);
+    rv = presShell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsTArray<RefPtr<StyleSheet>> newAgentSheets;
     for (StyleSheet* sheet : agentSheets) {
       nsIURI* uri = sheet->GetSheetURI();
 
       if (IsChromeURI(uri)) {
         // Reload the sheet.
@@ -365,17 +366,17 @@ nsresult nsChromeRegistry::RefreshWindow
           return NS_OK;
         }
       } else {  // Just use the same sheet.
         rv = newAgentSheets.AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
         if (NS_FAILED(rv)) return rv;
       }
     }
 
-    rv = shell->SetAgentStyleSheets(newAgentSheets);
+    rv = presShell->SetAgentStyleSheets(newAgentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   size_t count = document->SheetCount();
 
   // Build an array of style sheets we need to reload.
   nsTArray<RefPtr<StyleSheet>> oldSheets(count);
   nsTArray<RefPtr<StyleSheet>> newSheets(count);
--- a/devtools/client/aboutdebugging-new/src/components/App.js
+++ b/devtools/client/aboutdebugging-new/src/components/App.js
@@ -125,17 +125,27 @@ class App extends PureComponent {
         path: "/runtime/:runtimeId",
         render: routeProps => this.renderRuntime(routeProps),
       }),
       // default route when there's no match which includes "/"
       // TODO: the url does not match "/" means invalid URL,
       // in this case maybe we'd like to do something else than a redirect.
       // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1509897
       Route({
-        render: () => Redirect({ to: "/setup"}),
+        render: routeProps => {
+          const { pathname } = routeProps.location;
+          // The old about:debugging supported the following routes:
+          // about:debugging#workers, about:debugging#addons and about:debugging#tabs.
+          // Such links can still be found in external documentation pages.
+          // We redirect to This Firefox rather than the Setup Page here.
+          if (pathname === "/workers" || pathname === "/addons" || pathname === "/tabs") {
+            return Redirect({ to: `/runtime/${RUNTIMES.THIS_FIREFOX}`});
+          }
+          return Redirect({ to: "/setup"});
+        },
       })
     );
   }
 
   render() {
     const {
       adbAddonStatus,
       dispatch,
--- a/devtools/client/aboutdebugging-new/src/components/connect/ConnectSteps.js
+++ b/devtools/client/aboutdebugging-new/src/components/connect/ConnectSteps.js
@@ -23,17 +23,17 @@ class ConnectSteps extends PureComponent
     };
   }
 
   render() {
     return dom.ul(
       {
         className: "connect-page__step-list",
       },
-      this.props.steps.map(step =>
+      ...this.props.steps.map(step =>
         Localized(
           {
             id: step.localizationId,
             a: step.url ? dom.a({
               href: step.url,
               target: "_blank",
             }) : null,
           },
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_routes.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_routes.js
@@ -86,8 +86,31 @@ add_task(async function() {
       document.title,
       "Debugging - Setup",
       "Checking title for 'setup' page"
   );
   is(document.location.hash, "#/setup", "Redirected to root");
 
   await removeTab(tab);
 });
+
+/**
+ * Test that routes from old about:debugging redirect to this Firefox.
+ */
+add_task(async function testOldAboutDebuggingRoutes() {
+  info("Check that routes from old about:debugging redirect to this Firefox");
+  const { document, tab } = await openAboutDebugging();
+
+  const routes = ["addons", "tabs", "workers"];
+  for (const route of routes) {
+    info("Move to setup page before testing the route");
+    document.location.hash = "#/setup";
+    await waitUntil(() => document.querySelector(".js-connect-page"));
+
+    info(`Check that navigating to ${route} redirects to This Firefox`);
+    document.location.hash = route;
+    await waitUntil(() => document.querySelector(".js-runtime-page"));
+    is(document.location.hash, "#/runtime/this-firefox",
+      `${route} was redirected to This Firefox`);
+  }
+
+  await removeTab(tab);
+});
--- a/devtools/client/aboutdebugging/test/head.js
+++ b/devtools/client/aboutdebugging/test/head.js
@@ -12,16 +12,19 @@ Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
   this);
 
 const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 const { Management } = ChromeUtils.import("resource://gre/modules/Extension.jsm", null);
 const { ExtensionTestCommon } = ChromeUtils.import("resource://testing-common/ExtensionTestCommon.jsm");
 
 async function openAboutDebugging(page, win) {
+  info("Turn off the new about:debugging for the test");
+  await pushPref("devtools.aboutdebugging.new-enabled", false);
+
   info("opening about:debugging");
   let url = "about:debugging";
   if (page) {
     url += "#" + page;
   }
 
   const tab = await addTab(url, { window: win });
   const browser = tab.linkedBrowser;
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -59,16 +59,18 @@ loader.lazyRequireGetter(this, "buildHar
 loader.lazyRequireGetter(this, "NetMonitorAPI",
   "devtools/client/netmonitor/src/api", true);
 loader.lazyRequireGetter(this, "sortPanelDefinitions",
   "devtools/client/framework/toolbox-tabs-order-manager", true);
 loader.lazyRequireGetter(this, "createEditContextMenu",
   "devtools/client/framework/toolbox-context-menu", true);
 loader.lazyRequireGetter(this, "remoteClientManager",
   "devtools/client/shared/remote-debugging/remote-client-manager.js", true);
+loader.lazyRequireGetter(this, "ResponsiveUIManager",
+  "devtools/client/responsive.html/manager", true);
 
 loader.lazyGetter(this, "domNodeConstants", () => {
   return require("devtools/shared/dom-node-constants");
 });
 
 loader.lazyGetter(this, "registerHarOverlay", () => {
   return require("devtools/client/netmonitor/src/har/toolbox-overlay").register;
 });
@@ -1338,33 +1340,54 @@ Toolbox.prototype = {
         this.inspector.nodePicker.cancel();
       }
       // Stop the console from toggling.
       event.stopImmediatePropagation();
     }
   },
 
   _onPickerStarting: async function() {
+    this.tellRDMAboutPickerState(true);
     this.pickerButton.isChecked = true;
     await this.selectTool("inspector", "inspect_dom");
     this.on("select", this.inspector.nodePicker.stop);
   },
 
   _onPickerStarted: async function() {
     this.doc.addEventListener("keypress", this._onPickerKeypress, true);
     this.telemetry.scalarAdd("devtools.inspector.element_picker_used", 1);
   },
 
   _onPickerStopped: function() {
+    this.tellRDMAboutPickerState(false);
     this.off("select", this.inspector.nodePicker.stop);
     this.doc.removeEventListener("keypress", this._onPickerKeypress, true);
     this.pickerButton.isChecked = false;
   },
 
   /**
+   * RDM sometimes simulates touch events. For this to work correctly at all times, it
+   * needs to know when the picker is active or not.
+   * This method communicates with the RDM Manager if it exists.
+   *
+   * @param {Boolean} state
+   */
+  tellRDMAboutPickerState: async function(state) {
+    const { tab } = this.target;
+
+    if (!ResponsiveUIManager.isActiveForTab(tab) ||
+        await !this.target.actorHasMethod("emulation", "setElementPickerState")) {
+      return;
+    }
+
+    const ui = ResponsiveUIManager.getResponsiveUIForTab(tab);
+    await ui.emulationFront.setElementPickerState(state);
+  },
+
+  /**
    * When the picker is canceled, make sure the toolbox
    * gets the focus.
    */
   _onPickerCanceled: function() {
     this.win.focus();
   },
 
   /**
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -338,17 +338,17 @@ pref("devtools.responsive.show-setting-t
 // Show the custom user agent input in Nightly builds.
 #if defined(NIGHTLY_BUILD)
 pref("devtools.responsive.showUserAgentInput", true);
 #else
 pref("devtools.responsive.showUserAgentInput", false);
 #endif
 
 // Enable new about:debugging.
-pref("devtools.aboutdebugging.new-enabled", false);
+pref("devtools.aboutdebugging.new-enabled", true);
 
 // Show tab debug targets for This Firefox (on by default for local builds).
 #ifdef MOZILLA_OFFICIAL
   pref("devtools.aboutdebugging.local-tab-debugging", false);
 #else
   pref("devtools.aboutdebugging.local-tab-debugging", true);
 #endif
 
--- a/devtools/client/shared/components/NotificationBox.js
+++ b/devtools/client/shared/components/NotificationBox.js
@@ -68,17 +68,17 @@ class NotificationBox extends Component 
                              - {String} label: The label to appear on the button.
                              - {String} accesskey: The accesskey attribute set on the
                                                    <button> element.
       */
       notifications: PropTypes.instanceOf(Map),
       // Message that should be shown when hovering over the close button
       closeButtonTooltip: PropTypes.string,
       // Wraps text when passed from console window as wrapping: true
-      wrapping: PropTypes.boolean,
+      wrapping: PropTypes.bool,
     };
   }
 
   static get defaultProps() {
     return {
       closeButtonTooltip: l10n.getStr("notificationBox.closeTooltip"),
     };
   }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_ctrl_a_select_all.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_ctrl_a_select_all.js
@@ -14,16 +14,19 @@ add_task(async function() {
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performTests();
 });
 
 async function performTests() {
+  // The TabContextMenu initializes its strings only on a focus or mouseover event.
+  // Calls focus event on the TabContextMenu early in the test.
+  gBrowser.selectedTab.focus();
   const hud = await openNewTabAndConsole(TEST_URI);
   const {jsterm} = hud;
 
   setInputValue(hud, "Ignore These Four Words");
 
   // Test select all with (cmd|control) + a.
   EventUtils.synthesizeKey("a", { accelKey: true });
 
--- a/devtools/server/actors/emulation.js
+++ b/devtools/server/actors/emulation.js
@@ -172,16 +172,40 @@ const EmulationActor = protocol.ActorCla
 
     return false;
   },
 
   /* Touch events override */
 
   _previousTouchEventsOverride: undefined,
 
+  /**
+   * Set the current element picker state.
+   *
+   * True means the element picker is currently active and we should not be emulating
+   * touch events.
+   * False means the element picker is not active and it is ok to emulate touch events.
+   *
+   * This actor method is meant to be called by the DevTools front-end. The reason for
+   * this is the following:
+   * RDM is the only current consumer of the touch simulator. RDM instantiates this actor
+   * on its own, whether or not the Toolbox is opened. That means it does so in its own
+   * Debugger Server instance.
+   * When the Toolbox is running, it uses a different DebuggerServer. Therefore, it is not
+   * possible for the touch simulator to know whether the picker is active or not. This
+   * state has to be sent by the client code of the Toolbox to this actor.
+   * If a future use case arises where we want to use the touch simulator from the Toolbox
+   * too, then we could add code in here to detect the picker mode as described in
+   * https://bugzilla.mozilla.org/show_bug.cgi?id=1409085#c3
+   * @param {Boolean} state
+   */
+  setElementPickerState(state) {
+    this.touchSimulator.setElementPickerState(state);
+  },
+
   setTouchEventsOverride(flag) {
     if (this.getTouchEventsOverride() == flag) {
       return false;
     }
     if (this._previousTouchEventsOverride === undefined) {
       this._previousTouchEventsOverride = this.getTouchEventsOverride();
     }
 
--- a/devtools/server/actors/emulation/touch-simulator.js
+++ b/devtools/server/actors/emulation/touch-simulator.js
@@ -68,17 +68,33 @@ TouchSimulator.prototype = {
       return;
     }
     this.events.forEach(evt => {
       this.simulatorTarget.removeEventListener(evt, this, true);
     });
     this.enabled = false;
   },
 
+  /**
+   * Set the current element picker state value.
+   * True means the element picker is currently active and we should not be emulating
+   * touch events.
+   * False means the element picker is not active and it is ok to emulate touch events.
+   * @param {Boolean} state
+   */
+  setElementPickerState(state) {
+    this._isPicking = state;
+  },
+
   handleEvent(evt) {
+    // Bail out if devtools is in pick mode in the same tab.
+    if (this._isPicking) {
+      return;
+    }
+
     // The gaia system window use an hybrid system even on the device which is
     // a mix of mouse/touch events. So let's not cancel *all* mouse events
     // if it is the current target.
     const content = this.getContent(evt.target);
     if (!content) {
       return;
     }
     const isSystemWindow = content.location.toString()
--- a/devtools/shared/specs/emulation.js
+++ b/devtools/shared/specs/emulation.js
@@ -118,12 +118,19 @@ const emulationSpec = generateActorSpec(
     },
 
     clearUserAgentOverride: {
       request: {},
       response: {
         valueChanged: RetVal("boolean"),
       },
     },
+
+    setElementPickerState: {
+      request: {
+        state: Arg(0, "boolean"),
+      },
+      response: {},
+    },
   },
 });
 
 exports.emulationSpec = emulationSpec;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -23,16 +23,17 @@
 #include "mozilla/Components.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Logging.h"
 #include "mozilla/MediaFeatureChange.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/ScrollTypes.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "mozilla/WidgetUtils.h"
@@ -7873,18 +7874,19 @@ nsresult nsDocShell::RestoreFromHistory(
   // Insert the new root view at the correct location in the view tree.
   if (container) {
     nsSubDocumentFrame* subDocFrame =
         do_QueryFrame(container->GetPrimaryFrame());
     rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
   } else {
     rootViewParent = nullptr;
   }
-  if (sibling && sibling->GetShell() && sibling->GetShell()->GetViewManager()) {
-    rootViewSibling = sibling->GetShell()->GetViewManager()->GetRootView();
+  if (sibling && sibling->GetPresShell() &&
+      sibling->GetPresShell()->GetViewManager()) {
+    rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
   } else {
     rootViewSibling = nullptr;
   }
   if (rootViewParent && newRootView &&
       newRootView->GetParent() != rootViewParent) {
     nsViewManager* parentVM = rootViewParent->GetViewManager();
     if (parentVM) {
       // InsertChild(parent, child, sib, true) inserts the child after
--- a/docshell/base/nsDocShellEditorData.cpp
+++ b/docshell/base/nsDocShellEditorData.cpp
@@ -53,33 +53,16 @@ nsresult nsDocShellEditorData::MakeEdita
   }
   return NS_OK;
 }
 
 bool nsDocShellEditorData::GetEditable() {
   return mMakeEditable || (mHTMLEditor != nullptr);
 }
 
-nsresult nsDocShellEditorData::CreateEditor() {
-  nsCOMPtr<nsIEditingSession> editingSession;
-  nsresult rv = GetEditingSession(getter_AddRefs(editingSession));
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> domWindow =
-      mDocShell ? mDocShell->GetWindow() : nullptr;
-  rv = editingSession->SetupEditorOnWindow(domWindow);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  return NS_OK;
-}
-
 nsresult nsDocShellEditorData::GetEditingSession(nsIEditingSession** aResult) {
   EnsureEditingSession();
 
   NS_ADDREF(*aResult = mEditingSession);
 
   return NS_OK;
 }
 
--- a/docshell/base/nsDocShellEditorData.h
+++ b/docshell/base/nsDocShellEditorData.h
@@ -19,17 +19,16 @@ class nsIEditingSession;
 
 class nsDocShellEditorData {
  public:
   explicit nsDocShellEditorData(nsIDocShell* aOwningDocShell);
   ~nsDocShellEditorData();
 
   nsresult MakeEditable(bool aWaitForUriLoad);
   bool GetEditable();
-  nsresult CreateEditor();
   nsresult GetEditingSession(nsIEditingSession** aResult);
   mozilla::HTMLEditor* GetHTMLEditor() const { return mHTMLEditor; }
   nsresult SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
   void TearDownEditor();
   nsresult DetachFromWindow();
   nsresult ReattachToWindow(nsIDocShell* aDocShell);
   bool WaitingForLoad() const { return mMakeEditable; }
 
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -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/. */
 
 #include "Animation.h"
 #include "AnimationUtils.h"
 #include "mozilla/dom/AnimationBinding.h"
 #include "mozilla/dom/AnimationPlaybackEvent.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/AnimationEventDispatcher.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Maybe.h"          // For Maybe
 #include "mozilla/TypeTraits.h"     // For std::forward<>
 #include "nsAnimationManager.h"     // For CSSAnimation
 #include "nsDOMMutationObserver.h"  // For nsAutoAnimationMutationBatch
--- a/dom/animation/AnimationUtils.h
+++ b/dom/animation/AnimationUtils.h
@@ -14,16 +14,17 @@
 #include "nsStringFwd.h"
 
 class nsIContent;
 class nsIFrame;
 struct JSContext;
 
 namespace mozilla {
 
+enum class PseudoStyleType : uint8_t;
 class ComputedTimingFunction;
 class EffectSet;
 
 namespace dom {
 class Document;
 }
 
 class AnimationUtils {
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -15,29 +15,30 @@
 #include "mozilla/AnimationUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/ComputedStyleInlines.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/FloatingPoint.h"  // For IsFinite
 #include "mozilla/LayerAnimationInfo.h"
 #include "mozilla/LookAndFeel.h"  // For LookAndFeel::GetInt
 #include "mozilla/KeyframeUtils.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TypeTraits.h"
 #include "Layers.h"              // For Layer
 #include "nsComputedDOMStyle.h"  // nsComputedDOMStyle::GetComputedStyle
 #include "nsContentUtils.h"
 #include "nsCSSPropertyIDSet.h"
 #include "nsCSSProps.h"             // For nsCSSProps::PropHasFlags
 #include "nsCSSPseudoElements.h"    // For PseudoStyleType
 #include "nsDOMMutationObserver.h"  // For nsAutoAnimationMutationBatch
 #include "nsIFrame.h"
-#include "nsIPresShell.h"
 #include "nsIScriptError.h"
+#include "nsPresContextInlines.h"
 #include "nsRefreshDriver.h"
 
 namespace mozilla {
 
 void AnimationProperty::SetPerformanceWarning(
     const AnimationPerformanceWarning& aWarning, const Element* aElement) {
   if (mPerformanceWarning && *mPerformanceWarning == aWarning) {
     return;
@@ -1201,17 +1202,17 @@ KeyframeEffect::OverflowRegionRefreshInt
 bool KeyframeEffect::CanThrottleIfNotVisible(nsIFrame& aFrame) const {
   // Unless we are newly in-effect, we can throttle the animation if the
   // animation is paint only and the target frame is out of view or the document
   // is in background tabs.
   if (!mInEffectOnLastAnimationTimingUpdate || !CanIgnoreIfNotVisible()) {
     return false;
   }
 
-  nsIPresShell* presShell = GetPresShell();
+  PresShell* presShell = GetPresShell();
   if (presShell && !presShell->IsActive()) {
     return true;
   }
 
   const bool isVisibilityHidden =
       !aFrame.IsVisibleOrMayHaveVisibleDescendants();
   if ((!isVisibilityHidden || HasVisibilityChange()) &&
       !aFrame.IsScrolledOutOfView()) {
@@ -1403,22 +1404,22 @@ nsIFrame* KeyframeEffect::GetPrimaryFram
 
 Document* KeyframeEffect::GetRenderedDocument() const {
   if (!mTarget) {
     return nullptr;
   }
   return mTarget->mElement->GetComposedDoc();
 }
 
-nsIPresShell* KeyframeEffect::GetPresShell() const {
+PresShell* KeyframeEffect::GetPresShell() const {
   Document* doc = GetRenderedDocument();
   if (!doc) {
     return nullptr;
   }
-  return doc->GetShell();
+  return doc->GetPresShell();
 }
 
 /* static */
 bool KeyframeEffect::IsGeometricProperty(const nsCSSPropertyID aProperty) {
   MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty),
              "Property should be a longhand property");
 
   switch (aProperty) {
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -29,27 +29,27 @@
 #include "mozilla/dom/AnimationEffect.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Element.h"
 
 struct JSContext;
 class JSObject;
 class nsIContent;
 class nsIFrame;
-class nsIPresShell;
 
 namespace mozilla {
 
 class AnimValuesStyleRule;
 enum class PseudoStyleType : uint8_t;
 class ErrorResult;
 struct AnimationRule;
 struct TimingParams;
 class EffectSet;
 class ComputedStyle;
+class PresShell;
 
 namespace dom {
 class ElementOrCSSPseudoElement;
 class GlobalObject;
 class OwningElementOrCSSPseudoElement;
 class UnrestrictedDoubleOrKeyframeAnimationOptions;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 enum class IterationCompositeOperation : uint8_t;
@@ -278,17 +278,17 @@ class KeyframeEffect : public AnimationE
       const nsIFrame* aFrame,
       AnimationPerformanceWarning::Type& aPerformanceWarning /* out */) const;
   bool HasGeometricProperties() const;
   bool AffectsGeometry() const override {
     return GetTarget() && HasGeometricProperties();
   }
 
   Document* GetRenderedDocument() const;
-  nsIPresShell* GetPresShell() const;
+  PresShell* GetPresShell() const;
 
   // Associates a warning with the animated property set on the specified frame
   // indicating why, for example, the property could not be animated on the
   // compositor. |aParams| and |aParamsLength| are optional parameters which
   // will be used to generate a localized message for devtools.
   void SetPerformanceWarning(const nsCSSPropertyIDSet& aPropertySet,
                              const AnimationPerformanceWarning& aWarning);
 
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -25,16 +25,17 @@
 #include "jsapi.h"             // For most JSAPI
 #include "js/ForOfIterator.h"  // For JS::ForOfIterator
 #include "nsClassHashtable.h"
 #include "nsContentUtils.h"  // For GetContextForContent
 #include "nsCSSPropertyIDSet.h"
 #include "nsCSSProps.h"
 #include "nsCSSPseudoElements.h"  // For PseudoStyleType
 #include "nsIScriptError.h"
+#include "nsPresContextInlines.h"
 #include "nsTArray.h"
 #include <algorithm>  // For std::stable_sort, std::min
 
 using mozilla::dom::Nullable;
 
 namespace mozilla {
 
 // ------------------------------------------------------------------
--- a/dom/animation/PendingAnimationTracker.cpp
+++ b/dom/animation/PendingAnimationTracker.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PendingAnimationTracker.h"
 
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/AnimationTimeline.h"
 #include "mozilla/dom/Nullable.h"
 #include "nsIFrame.h"
-#include "nsIPresShell.h"
 #include "nsTransitionManager.h"  // For CSSTransition
 
 using mozilla::dom::Nullable;
 
 namespace mozilla {
 
 NS_IMPL_CYCLE_COLLECTION(PendingAnimationTracker, mPlayPendingSet,
                          mPausePendingSet, mDocument)
@@ -168,17 +168,17 @@ void PendingAnimationTracker::MarkAnimat
   }
 }
 
 void PendingAnimationTracker::EnsurePaintIsScheduled() {
   if (!mDocument) {
     return;
   }
 
-  nsIPresShell* presShell = mDocument->GetShell();
+  PresShell* presShell = mDocument->GetPresShell();
   if (!presShell) {
     return;
   }
 
   nsIFrame* rootFrame = presShell->GetRootFrame();
   if (!rootFrame) {
     return;
   }
--- a/dom/base/AnonymousContent.cpp
+++ b/dom/base/AnonymousContent.cpp
@@ -1,20 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AnonymousContent.h"
+#include "mozilla/PresShell.h"
+#include "mozilla/dom/Document.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/AnonymousContentBinding.h"
 #include "nsComputedDOMStyle.h"
 #include "nsCycleCollectionParticipant.h"
-#include "mozilla/dom/Document.h"
 #include "nsIFrame.h"
 #include "nsStyledElement.h"
 #include "HTMLCanvasElement.h"
 
 namespace mozilla {
 namespace dom {
 
 // Ref counting and cycle collection
@@ -180,18 +181,17 @@ void AnonymousContent::GetComputedStyleP
     const nsAString& aElementId, const nsAString& aPropertyName,
     DOMString& aResult, ErrorResult& aRv) {
   Element* element = GetElementById(aElementId);
   if (!element) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
-  nsIPresShell* shell = element->OwnerDoc()->GetShell();
-  if (!shell) {
+  if (!element->OwnerDoc()->GetPresShell()) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
   RefPtr<nsComputedDOMStyle> cs =
       new nsComputedDOMStyle(element, NS_LITERAL_STRING(""),
                              element->OwnerDoc(), nsComputedDOMStyle::eAll);
   aRv = cs->GetPropertyValue(aPropertyName, aResult);
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -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/. */
 
 #include "DOMIntersectionObserver.h"
 #include "nsCSSPropertyID.h"
 #include "nsIFrame.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ServoBindings.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserverEntry)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
@@ -247,17 +248,17 @@ void DOMIntersectionObserver::Update(Doc
         rootRectRelativeToRootFrame = rootFrame->GetRectRelativeToSelf();
       }
       nsIFrame* containingBlock =
           nsLayoutUtils::GetContainingBlockForClientRect(rootFrame);
       rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
           rootFrame, rootRectRelativeToRootFrame, containingBlock);
     }
   } else {
-    nsCOMPtr<nsIPresShell> presShell = aDocument->GetShell();
+    RefPtr<PresShell> presShell = aDocument->GetPresShell();
     if (presShell) {
       rootFrame = presShell->GetRootScrollFrame();
       if (rootFrame) {
         nsPresContext* presContext = rootFrame->PresContext();
         while (!presContext->IsRootContentDocument()) {
           presContext = presContext->GetParentPresContext();
           if (!presContext) {
             break;
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -2246,35 +2246,35 @@ already_AddRefed<nsIPrincipal> Document:
 }
 
 void Document::RemoveDocStyleSheetsFromStyleSets() {
   // The stylesheets should forget us
   for (StyleSheet* sheet : Reversed(mStyleSheets)) {
     sheet->ClearAssociatedDocumentOrShadowRoot();
 
     if (sheet->IsApplicable()) {
-      nsCOMPtr<nsIPresShell> shell = GetShell();
-      if (shell) {
-        shell->StyleSet()->RemoveDocStyleSheet(sheet);
+      RefPtr<PresShell> presShell = GetPresShell();
+      if (presShell) {
+        presShell->StyleSet()->RemoveDocStyleSheet(sheet);
       }
     }
     // XXX Tell observers?
   }
 }
 
 void Document::RemoveStyleSheetsFromStyleSets(
     const nsTArray<RefPtr<StyleSheet>>& aSheets, SheetType aType) {
   // The stylesheets should forget us
   for (StyleSheet* sheet : Reversed(aSheets)) {
     sheet->ClearAssociatedDocumentOrShadowRoot();
 
     if (sheet->IsApplicable()) {
-      nsCOMPtr<nsIPresShell> shell = GetShell();
-      if (shell) {
-        shell->StyleSet()->RemoveStyleSheet(aType, sheet);
+      RefPtr<PresShell> presShell = GetPresShell();
+      if (presShell) {
+        presShell->StyleSet()->RemoveStyleSheet(aType, sheet);
       }
     }
     // XXX Tell observers?
   }
 }
 
 void Document::ResetStylesheetsToURI(nsIURI* aURI) {
   MOZ_ASSERT(aURI);
@@ -2318,20 +2318,20 @@ void Document::ResetStylesheetsToURI(nsI
     mAttrStyleSheet = new nsHTMLStyleSheet(this);
   }
 
   if (!mStyleAttrStyleSheet) {
     mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet();
   }
 
   // Now set up our style sets
-  if (nsIPresShell* shell = GetShell()) {
-    FillStyleSet(shell->StyleSet());
-    if (shell->StyleSet()->StyleSheetsHaveChanged()) {
-      shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    FillStyleSet(presShell->StyleSet());
+    if (presShell->StyleSet()->StyleSheetsHaveChanged()) {
+      presShell->ApplicableStylesChanged();
     }
   }
 }
 
 static void AppendSheetsToStyleSet(ServoStyleSet* aStyleSet,
                                    const nsTArray<RefPtr<StyleSheet>>& aSheets,
                                    SheetType aType) {
   for (StyleSheet* sheet : Reversed(aSheets)) {
@@ -3625,65 +3625,67 @@ static inline void AssertNoStaleServoDat
           AssertNoStaleServoDataIn(*child);
         }
       }
     }
   }
 #endif
 }
 
-already_AddRefed<nsIPresShell> Document::CreateShell(
+already_AddRefed<PresShell> Document::CreatePresShell(
     nsPresContext* aContext, nsViewManager* aViewManager,
     UniquePtr<ServoStyleSet> aStyleSet) {
   NS_ASSERTION(!mPresShell, "We have a presshell already!");
 
   NS_ENSURE_FALSE(GetBFCacheEntry(), nullptr);
 
   FillStyleSet(aStyleSet.get());
   AssertNoStaleServoDataIn(*this);
 
-  RefPtr<PresShell> shell = new PresShell;
+  RefPtr<PresShell> presShell = new PresShell;
   // Note: we don't hold a ref to the shell (it holds a ref to us)
-  mPresShell = shell;
-  shell->Init(this, aContext, aViewManager, std::move(aStyleSet));
+  mPresShell = presShell;
+  presShell->Init(this, aContext, aViewManager, std::move(aStyleSet));
 
   // Make sure to never paint if we belong to an invisible DocShell.
   nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
-  if (docShell && docShell->IsInvisible()) shell->SetNeverPainting(true);
+  if (docShell && docShell->IsInvisible()) {
+    presShell->SetNeverPainting(true);
+  }
 
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug,
-          ("DOCUMENT %p with PressShell %p and DocShell %p", this, shell.get(),
-           docShell.get()));
+          ("DOCUMENT %p with PressShell %p and DocShell %p", this,
+           presShell.get(), docShell.get()));
 
   mExternalResourceMap.ShowViewers();
 
   UpdateFrameRequestCallbackSchedulingState();
 
   // Now that we have a shell, we might have @font-face rules (the presence of a
   // shell may change which rules apply to us). We don't need to do anything
   // like EnsureStyleFlush or such, there's nothing to update yet and when stuff
   // is ready to update we'll flush the font set.
   MarkUserFontSetDirty();
 
-  return shell.forget();
+  return presShell.forget();
 }
 
 void Document::UpdateFrameRequestCallbackSchedulingState(
-    nsIPresShell* aOldShell) {
+    PresShell* aOldPresShell) {
   // If the condition for shouldBeScheduled changes to depend on some other
   // variable, add UpdateFrameRequestCallbackSchedulingState() calls to the
   // places where that variable can change.
   bool shouldBeScheduled = mPresShell && IsEventHandlingEnabled() &&
                            !mFrameRequestCallbacks.IsEmpty();
   if (shouldBeScheduled == mFrameRequestCallbacksScheduled) {
     // nothing to do
     return;
   }
 
-  nsIPresShell* presShell = aOldShell ? aOldShell : mPresShell;
+  PresShell* presShell = aOldPresShell ? aOldPresShell : mPresShell;
   MOZ_RELEASE_ASSERT(presShell);
 
   nsRefreshDriver* rd = presShell->GetPresContext()->RefreshDriver();
   if (shouldBeScheduled) {
     rd->ScheduleFrameRequestCallbacks(this);
   } else {
     rd->RevokeFrameRequestCallbacks(this);
   }
@@ -3733,36 +3735,36 @@ bool Document::ShouldThrottleFrameReques
     // platforms and is unlikely to be human-perceivable on non-APZ platforms.
     return true;
   }
 
   // We got painted during the last paint, so run at full speed.
   return false;
 }
 
-void Document::DeleteShell() {
+void Document::DeletePresShell() {
   mExternalResourceMap.HideViewers();
   if (nsPresContext* presContext = mPresShell->GetPresContext()) {
     presContext->RefreshDriver()->CancelPendingFullscreenEvents(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
   // no longer intend to paint.
   ImageTracker()->RequestDiscardAll();
 
   // Now that we no longer have a shell, we need to forget about any FontFace
   // objects for @font-face rules that came from the style set. There's no need
   // to call EnsureStyleFlush either, the shell is going away anyway, so there's
   // no point on it.
   MarkUserFontSetDirty();
 
-  nsIPresShell* oldShell = mPresShell;
+  PresShell* oldPresShell = mPresShell;
   mPresShell = nullptr;
-  UpdateFrameRequestCallbackSchedulingState(oldShell);
+  UpdateFrameRequestCallbackSchedulingState(oldPresShell);
   mStyleSetFilled = false;
 
   ClearStaleServoData();
   AssertNoStaleServoDataIn(*this);
 }
 
 void Document::SetBFCacheEntry(nsIBFCacheEntry* aEntry) {
   MOZ_ASSERT(IsBFCachingAllowed() || !aEntry, "You should have checked!");
@@ -3947,19 +3949,19 @@ void Document::RemoveChildNode(nsIConten
   mCachedRootElement = nullptr;
   nsINode::RemoveChildNode(aKid, aNotify);
   MOZ_ASSERT(mCachedRootElement != aKid,
              "Stale pointer in mCachedRootElement, after we tried to clear it "
              "(maybe somebody called GetRootElement() too early?)");
 }
 
 void Document::AddStyleSheetToStyleSets(StyleSheet* aSheet) {
-  if (nsIPresShell* shell = GetShell()) {
-    shell->StyleSet()->AddDocStyleSheet(aSheet, this);
-    shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->StyleSet()->AddDocStyleSheet(aSheet, this);
+    presShell->ApplicableStylesChanged();
   }
 }
 
 #define DO_STYLESHEET_NOTIFICATION(className, type, memberName, argName) \
   do {                                                                   \
     className##Init init;                                                \
     init.mBubbles = true;                                                \
     init.mCancelable = true;                                             \
@@ -3987,19 +3989,19 @@ void Document::NotifyStyleSheetRemoved(S
                                        bool aDocumentSheet) {
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent, "StyleSheetRemoved",
                                mDocumentSheet, aDocumentSheet);
   }
 }
 
 void Document::RemoveStyleSheetFromStyleSets(StyleSheet* aSheet) {
-  if (nsIPresShell* shell = GetShell()) {
-    shell->StyleSet()->RemoveDocStyleSheet(aSheet);
-    shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->StyleSet()->RemoveDocStyleSheet(aSheet);
+    presShell->ApplicableStylesChanged();
   }
 }
 
 void Document::RemoveStyleSheet(StyleSheet* aSheet) {
   MOZ_ASSERT(aSheet);
   RefPtr<StyleSheet> sheet = DocumentOrShadowRoot::RemoveSheet(*aSheet);
 
   if (!sheet) {
@@ -4169,20 +4171,20 @@ nsresult Document::LoadAdditionalStyleSh
 nsresult Document::AddAdditionalStyleSheet(additionalSheetType aType,
                                            StyleSheet* aSheet) {
   if (mAdditionalSheets[aType].Contains(aSheet)) return NS_ERROR_INVALID_ARG;
 
   if (!aSheet->IsApplicable()) return NS_ERROR_INVALID_ARG;
 
   mAdditionalSheets[aType].AppendElement(aSheet);
 
-  if (nsIPresShell* shell = GetShell()) {
+  if (PresShell* presShell = GetPresShell()) {
     SheetType type = ConvertAdditionalSheetType(aType);
-    shell->StyleSet()->AppendStyleSheet(type, aSheet);
-    shell->ApplicableStylesChanged();
+    presShell->StyleSet()->AppendStyleSheet(type, aSheet);
+    presShell->ApplicableStylesChanged();
   }
 
   // Passing false, so documet.styleSheets.length will not be affected by
   // these additional sheets.
   NotifyStyleSheetAdded(aSheet, false);
   return NS_OK;
 }
 
@@ -4194,20 +4196,20 @@ void Document::RemoveAdditionalStyleShee
 
   int32_t i = FindSheet(mAdditionalSheets[aType], aSheetURI);
   if (i >= 0) {
     RefPtr<StyleSheet> sheetRef = sheets[i];
     sheets.RemoveElementAt(i);
 
     if (!mIsGoingAway) {
       MOZ_ASSERT(sheetRef->IsApplicable());
-      if (nsIPresShell* shell = GetShell()) {
+      if (PresShell* presShell = GetPresShell()) {
         SheetType type = ConvertAdditionalSheetType(aType);
-        shell->StyleSet()->RemoveStyleSheet(type, sheetRef);
-        shell->ApplicableStylesChanged();
+        presShell->StyleSet()->RemoveStyleSheet(type, sheetRef);
+        presShell->ApplicableStylesChanged();
       }
     }
 
     // Passing false, so documet.styleSheets.length will not be affected by
     // these additional sheets.
     NotifyStyleSheetRemoved(sheetRef, false);
     sheetRef->ClearAssociatedDocumentOrShadowRoot();
   }
@@ -4936,18 +4938,18 @@ void Document::UnblockDOMContentLoaded()
   if (--mBlockDOMContentLoaded != 0 || mDidFireDOMContentLoaded) {
     return;
   }
 
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug,
           ("DOCUMENT %p UnblockDOMContentLoaded", this));
 
   mDidFireDOMContentLoaded = true;
-  if (nsIPresShell* shell = GetShell()) {
-    shell->GetRefreshDriver()->NotifyDOMContentLoaded();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->GetRefreshDriver()->NotifyDOMContentLoaded();
   }
 
   MOZ_ASSERT(mReadyState == READYSTATE_INTERACTIVE);
   if (!mSynchronousDOMContentLoaded) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIRunnable> ev =
         NewRunnableMethod("Document::DispatchContentLoadedEvents", this,
                           &Document::DispatchContentLoadedEvents);
@@ -4966,138 +4968,139 @@ void Document::ContentStateChanged(nsICo
 }
 
 void Document::DocumentStatesChanged(EventStates aStateMask) {
   UpdateDocumentStates(aStateMask);
   NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentStatesChanged, (this, aStateMask));
 }
 
 void Document::StyleRuleChanged(StyleSheet* aSheet, css::Rule* aStyleRule) {
-  if (nsIPresShell* shell = GetShell()) {
-    shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->ApplicableStylesChanged();
   }
 
   if (!StyleSheetChangeEventsEnabled()) {
     return;
   }
 
   DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent, "StyleRuleChanged", mRule,
                              aStyleRule);
 }
 
 void Document::StyleRuleAdded(StyleSheet* aSheet, css::Rule* aStyleRule) {
-  if (nsIPresShell* shell = GetShell()) {
-    shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->ApplicableStylesChanged();
   }
 
   if (!StyleSheetChangeEventsEnabled()) {
     return;
   }
 
   DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent, "StyleRuleAdded", mRule,
                              aStyleRule);
 }
 
 void Document::StyleRuleRemoved(StyleSheet* aSheet, css::Rule* aStyleRule) {
-  if (nsIPresShell* shell = GetShell()) {
-    shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->ApplicableStylesChanged();
   }
 
   if (!StyleSheetChangeEventsEnabled()) {
     return;
   }
 
   DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent, "StyleRuleRemoved", mRule,
                              aStyleRule);
 }
 
 #undef DO_STYLESHEET_NOTIFICATION
 
-static Element* GetCustomContentContainer(nsIPresShell* aShell) {
-  if (!aShell || !aShell->GetCanvasFrame()) {
+static Element* GetCustomContentContainer(PresShell* aPresShell) {
+  if (!aPresShell || !aPresShell->GetCanvasFrame()) {
     return nullptr;
   }
 
-  return aShell->GetCanvasFrame()->GetCustomContentContainer();
+  return aPresShell->GetCanvasFrame()->GetCustomContentContainer();
 }
 
 static void InsertAnonContentIntoCanvas(AnonymousContent& aAnonContent,
-                                        nsIPresShell* aShell) {
-  Element* container = GetCustomContentContainer(aShell);
+                                        PresShell* aPresShell) {
+  Element* container = GetCustomContentContainer(aPresShell);
   if (!container) {
     return;
   }
 
   nsresult rv = container->AppendChildTo(&aAnonContent.ContentNode(), true);
   if (NS_FAILED(rv)) {
     return;
   }
 
-  aShell->GetCanvasFrame()->ShowCustomContentContainer();
+  aPresShell->GetCanvasFrame()->ShowCustomContentContainer();
 }
 
 already_AddRefed<AnonymousContent> Document::InsertAnonymousContent(
     Element& aElement, ErrorResult& aRv) {
   nsAutoScriptBlocker scriptBlocker;
 
   // Clone the node to avoid returning a direct reference.
   nsCOMPtr<nsINode> clone = aElement.CloneNode(true, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   auto anonContent =
       MakeRefPtr<AnonymousContent>(clone.forget().downcast<Element>());
   mAnonymousContents.AppendElement(anonContent);
 
-  InsertAnonContentIntoCanvas(*anonContent, GetShell());
+  InsertAnonContentIntoCanvas(*anonContent, GetPresShell());
 
   return anonContent.forget();
 }
 
 static void RemoveAnonContentFromCanvas(AnonymousContent& aAnonContent,
-                                        nsIPresShell* aShell) {
-  RefPtr<Element> container = GetCustomContentContainer(aShell);
+                                        PresShell* aPresShell) {
+  RefPtr<Element> container = GetCustomContentContainer(aPresShell);
   if (!container) {
     return;
   }
   container->RemoveChild(aAnonContent.ContentNode(), IgnoreErrors());
 }
 
 void Document::RemoveAnonymousContent(AnonymousContent& aContent,
                                       ErrorResult& aRv) {
   nsAutoScriptBlocker scriptBlocker;
 
   auto index = mAnonymousContents.IndexOf(&aContent);
   if (index == mAnonymousContents.NoIndex) {
     return;
   }
 
   mAnonymousContents.RemoveElementAt(index);
-  RemoveAnonContentFromCanvas(aContent, GetShell());
-
-  if (mAnonymousContents.IsEmpty() && GetCustomContentContainer(GetShell())) {
-    GetShell()->GetCanvasFrame()->HideCustomContentContainer();
+  RemoveAnonContentFromCanvas(aContent, GetPresShell());
+
+  if (mAnonymousContents.IsEmpty() &&
+      GetCustomContentContainer(GetPresShell())) {
+    GetPresShell()->GetCanvasFrame()->HideCustomContentContainer();
   }
 }
 
 Element* Document::GetAnonRootIfInAnonymousContentContainer(
     nsINode* aNode) const {
   if (!aNode->IsInNativeAnonymousSubtree()) {
     return nullptr;
   }
 
-  nsIPresShell* shell = GetShell();
-  if (!shell || !shell->GetCanvasFrame()) {
+  PresShell* presShell = GetPresShell();
+  if (!presShell || !presShell->GetCanvasFrame()) {
     return nullptr;
   }
 
   nsAutoScriptBlocker scriptBlocker;
   nsCOMPtr<Element> customContainer =
-      shell->GetCanvasFrame()->GetCustomContentContainer();
+      presShell->GetCanvasFrame()->GetCustomContentContainer();
   if (!customContainer) {
     return nullptr;
   }
 
   // An arbitrary number of elements can be inserted as children of the custom
   // container frame.  We want the one that was added that contains aNode, so
   // we need to keep track of the last child separately using |child| here.
   nsINode* child = aNode;
@@ -5521,19 +5524,19 @@ void Document::EnableStyleSheetsForSetIn
     sheet->GetTitle(title);
     if (!title.IsEmpty()) {
       sheet->SetEnabled(title.Equals(aSheetSet));
     }
   }
   if (aUpdateCSSLoader) {
     CSSLoader()->DocumentStyleSheetSetChanged();
   }
-  if (nsIPresShell* shell = GetShell()) {
-    if (shell->StyleSet()->StyleSheetsHaveChanged()) {
-      shell->ApplicableStylesChanged();
+  if (PresShell* presShell = GetPresShell()) {
+    if (presShell->StyleSet()->StyleSheetsHaveChanged()) {
+      presShell->ApplicableStylesChanged();
     }
   }
 }
 
 void Document::GetCharacterSet(nsAString& aCharacterSet) const {
   nsAutoCString charset;
   GetDocumentCharacterSet()->Name(charset);
   CopyASCIItoUTF16(charset, aCharacterSet);
@@ -5886,20 +5889,20 @@ void Document::NotifyPossibleTitleChange
 
 void Document::DoNotifyPossibleTitleChange() {
   mPendingTitleChangeEvent.Forget();
   mHaveFiredTitleChange = true;
 
   nsAutoString title;
   GetTitle(title);
 
-  nsCOMPtr<nsIPresShell> shell = GetShell();
-  if (shell) {
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (presShell) {
     nsCOMPtr<nsISupports> container =
-        shell->GetPresContext()->GetContainerWeak();
+        presShell->GetPresContext()->GetContainerWeak();
     if (container) {
       nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
       if (docShellWin) {
         docShellWin->SetTitle(title);
       }
     }
   }
 
@@ -7109,18 +7112,18 @@ void Document::FlushPendingNotifications
   if (mParentDocument && IsSafeToFlush()) {
     mozilla::ChangesToFlush parentFlush = aFlush;
     if (flushType >= FlushType::Style) {
       parentFlush.mFlushType = std::max(FlushType::Layout, flushType);
     }
     mParentDocument->FlushPendingNotifications(parentFlush);
   }
 
-  if (nsIPresShell* shell = GetShell()) {
-    shell->FlushPendingNotifications(aFlush);
+  if (RefPtr<PresShell> presShell = GetPresShell()) {
+    presShell->FlushPendingNotifications(aFlush);
   }
 }
 
 static bool Copy(Document* aDocument, void* aData) {
   auto* resources = static_cast<nsTArray<nsCOMPtr<Document>>*>(aData);
   resources->AppendElement(aDocument);
   return true;
 }
@@ -7310,20 +7313,21 @@ already_AddRefed<Element> Document::Crea
 
   nsCOMPtr<Element> element;
   nsresult rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
                               NOT_FROM_PARSER, aIs);
   return NS_SUCCEEDED(rv) ? element.forget() : nullptr;
 }
 
 bool Document::IsSafeToFlush() const {
-  nsIPresShell* shell = GetShell();
-  if (!shell) return true;
-
-  return shell->IsSafeToFlush();
+  PresShell* presShell = GetPresShell();
+  if (!presShell) {
+    return true;
+  }
+  return presShell->IsSafeToFlush();
 }
 
 void Document::Sanitize() {
   // Sanitize the document by resetting all (current and former) 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.
@@ -8298,22 +8302,22 @@ static void FireOrClearDelayedEvents(nsT
   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
     // closed before this event ran.
     if (!aDocuments[i]->EventHandlingSuppressed()) {
       fm->FireDelayedEvents(aDocuments[i]);
-      nsCOMPtr<nsIPresShell> shell = aDocuments[i]->GetShell();
-      if (shell) {
+      RefPtr<PresShell> presShell = aDocuments[i]->GetPresShell();
+      if (presShell) {
         // Only fire events for active documents.
         bool fire = aFireEvents && aDocuments[i]->GetInnerWindow() &&
                     aDocuments[i]->GetInnerWindow()->IsCurrentInnerWindow();
-        shell->FireOrClearDelayedEvents(fire);
+        presShell->FireOrClearDelayedEvents(fire);
       }
     }
   }
 }
 
 void Document::PreloadPictureClosed() {
   MOZ_ASSERT(mPreloadPictureDepth > 0);
   mPreloadPictureDepth--;
@@ -8785,63 +8789,64 @@ void Document::SetScrollToRef(nsIURI* aD
     ++start;  // Skip over the '#'
 
     mScrollToRef = Substring(start, end);
   }
 }
 
 void Document::ScrollToRef() {
   if (mScrolledToRefAlready) {
-    nsCOMPtr<nsIPresShell> shell = GetShell();
-    if (shell) {
-      shell->ScrollToAnchor();
+    RefPtr<PresShell> presShell = GetPresShell();
+    if (presShell) {
+      presShell->ScrollToAnchor();
     }
     return;
   }
 
   if (mScrollToRef.IsEmpty()) {
     return;
   }
 
-  nsCOMPtr<nsIPresShell> shell = GetShell();
-  if (shell) {
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (presShell) {
     nsresult rv = NS_ERROR_FAILURE;
     // We assume that the bytes are in UTF-8, as it says in the spec:
     // http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
     NS_ConvertUTF8toUTF16 ref(mScrollToRef);
     // Check an empty string which might be caused by the UTF-8 conversion
     if (!ref.IsEmpty()) {
       // Note that GoToAnchor will handle flushing layout as needed.
-      rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
+      rv = presShell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
     } else {
       rv = NS_ERROR_FAILURE;
     }
 
     if (NS_FAILED(rv)) {
       nsAutoCString buff;
       const bool unescaped =
           NS_UnescapeURL(mScrollToRef.BeginReading(), mScrollToRef.Length(),
                          /*aFlags =*/0, buff);
 
       // This attempt is only necessary if characters were unescaped.
       if (unescaped) {
         NS_ConvertUTF8toUTF16 utf16Str(buff);
         if (!utf16Str.IsEmpty()) {
-          rv = shell->GoToAnchor(utf16Str, mChangeScrollPosWhenScrollingToRef);
+          rv = presShell->GoToAnchor(utf16Str,
+                                     mChangeScrollPosWhenScrollingToRef);
         }
       }
 
       // If UTF-8 URI failed then try to assume the string as a
       // document's charset.
       if (NS_FAILED(rv)) {
         const Encoding* encoding = GetDocumentCharacterSet();
         rv = encoding->DecodeWithoutBOMHandling(unescaped ? buff : mScrollToRef,
                                                 ref);
         if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
-          rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
+          rv = presShell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
         }
       }
     }
     if (NS_SUCCEEDED(rv)) {
       mScrolledToRefAlready = true;
     }
   }
 }
@@ -9166,18 +9171,18 @@ void Document::GetPlugins(nsTArray<nsIOb
 }
 
 void Document::ScheduleSVGUseElementShadowTreeUpdate(
     SVGUseElement& aUseElement) {
   MOZ_ASSERT(aUseElement.IsInComposedDoc());
 
   mSVGUseElementsNeedingShadowTreeUpdate.PutEntry(&aUseElement);
 
-  if (nsIPresShell* shell = GetShell()) {
-    shell->EnsureStyleFlush();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->EnsureStyleFlush();
   }
 }
 
 void Document::DoUpdateSVGUseElementShadowTrees() {
   MOZ_ASSERT(!mSVGUseElementsNeedingShadowTreeUpdate.IsEmpty());
   nsTArray<RefPtr<SVGUseElement>> useElementsToUpdate;
 
   do {
@@ -9253,39 +9258,39 @@ already_AddRefed<nsDOMCaretPosition> Doc
   using FrameForPointOption = nsLayoutUtils::FrameForPointOption;
 
   nscoord x = nsPresContext::CSSPixelsToAppUnits(aX);
   nscoord y = nsPresContext::CSSPixelsToAppUnits(aY);
   nsPoint pt(x, y);
 
   FlushPendingNotifications(FlushType::Layout);
 
-  nsIPresShell* ps = GetShell();
-  if (!ps) {
+  PresShell* presShell = GetPresShell();
+  if (!presShell) {
     return nullptr;
   }
 
-  nsIFrame* rootFrame = ps->GetRootFrame();
+  nsIFrame* rootFrame = presShell->GetRootFrame();
 
   // XUL docs, unlike HTML, have no frame tree until everything's done loading
   if (!rootFrame) {
     return nullptr;
   }
 
   nsIFrame* ptFrame = nsLayoutUtils::GetFrameForPoint(
       rootFrame, pt,
       {FrameForPointOption::IgnorePaintSuppression,
        FrameForPointOption::IgnoreCrossDoc});
   if (!ptFrame) {
     return nullptr;
   }
 
   // We require frame-relative coordinates for GetContentOffsetsFromPoint.
   nsPoint aOffset;
-  nsCOMPtr<nsIWidget> widget = nsContentUtils::GetWidget(ps, &aOffset);
+  nsCOMPtr<nsIWidget> widget = nsContentUtils::GetWidget(presShell, &aOffset);
   LayoutDeviceIntPoint refPoint = nsContentUtils::ToWidgetPoint(
       CSSPoint(aX, aY), aOffset, GetPresContext());
   nsPoint adjustedPoint =
       nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, refPoint, ptFrame);
 
   nsFrame::ContentOffsets offsets =
       ptFrame->GetContentOffsetsFromPoint(adjustedPoint);
 
@@ -10217,20 +10222,20 @@ void Document::CleanupFullscreenState() 
     if (nsCOMPtr<Element> element = do_QueryReferent(weakPtr)) {
       ClearFullscreenStateOnElement(element);
     }
   }
   mFullscreenStack.Clear();
   mFullscreenRoot = nullptr;
 
   // Restore the zoom level that was in place prior to entering fullscreen.
-  if (nsIPresShell* shell = GetShell()) {
-    if (shell->GetMobileViewportManager()) {
-      shell->SetResolutionAndScaleTo(mSavedResolution,
-                                     nsIPresShell::ChangeOrigin::eMainThread);
+  if (PresShell* presShell = GetPresShell()) {
+    if (presShell->GetMobileViewportManager()) {
+      presShell->SetResolutionAndScaleTo(
+          mSavedResolution, nsIPresShell::ChangeOrigin::eMainThread);
     }
   }
 
   UpdateViewportScrollbarOverrideForFullscreen(this);
 }
 
 bool Document::FullscreenStackPush(Element* aElement) {
   NS_ASSERTION(aElement, "Must pass non-null to FullscreenStackPush()");
@@ -10611,23 +10616,24 @@ bool Document::ApplyFullscreen(UniquePtr
     child->SetFullscreenRoot(fullScreenRootDoc);
 
     // When entering fullscreen, reset the RCD's resolution to the intrinsic
     // resolution, otherwise the fullscreen content could be sized larger than
     // the screen (since fullscreen is implemented using position:fixed and
     // fixed elements are sized to the layout viewport).
     // This also ensures that things like video controls aren't zoomed in
     // when in fullscreen mode.
-    if (nsIPresShell* shell = child->GetShell()) {
+    if (PresShell* presShell = child->GetPresShell()) {
       if (RefPtr<MobileViewportManager> manager =
-              shell->GetMobileViewportManager()) {
+              presShell->GetMobileViewportManager()) {
         // Save the previous resolution so it can be restored.
-        child->mSavedResolution = shell->GetResolution();
-        shell->SetResolutionAndScaleTo(manager->ComputeIntrinsicResolution(),
-                                       nsIPresShell::ChangeOrigin::eMainThread);
+        child->mSavedResolution = presShell->GetResolution();
+        presShell->SetResolutionAndScaleTo(
+            manager->ComputeIntrinsicResolution(),
+            nsIPresShell::ChangeOrigin::eMainThread);
       }
     }
 
     NS_ASSERTION(child->GetFullscreenRoot() == fullScreenRootDoc,
                  "Fullscreen root should be set!");
     if (child == fullScreenRootDoc) {
       break;
     }
@@ -10887,41 +10893,41 @@ bool Document::SetPointerLock(Element* a
 #ifdef DEBUG
   if (!aElement) {
     nsCOMPtr<Document> pointerLockedDoc =
         do_QueryReferent(EventStateManager::sPointerLockedDoc);
     MOZ_ASSERT(pointerLockedDoc == this);
   }
 #endif
 
-  nsIPresShell* shell = GetShell();
-  if (!shell) {
+  PresShell* presShell = GetPresShell();
+  if (!presShell) {
     NS_WARNING("SetPointerLock(): No PresShell");
     if (!aElement) {
       // If we are unlocking pointer lock, but for some reason the doc
       // has already detached from the presshell, just ask the event
       // state manager to release the pointer.
       EventStateManager::SetPointerLock(nullptr, nullptr);
       return true;
     }
     return false;
   }
-  nsPresContext* presContext = shell->GetPresContext();
+  nsPresContext* presContext = presShell->GetPresContext();
   if (!presContext) {
     NS_WARNING("SetPointerLock(): Unable to get PresContext");
     return false;
   }
 
   nsCOMPtr<nsIWidget> widget;
-  nsIFrame* rootFrame = shell->GetRootFrame();
+  nsIFrame* rootFrame = presShell->GetRootFrame();
   if (!NS_WARN_IF(!rootFrame)) {
     widget = rootFrame->GetNearestWidget();
     NS_WARNING_ASSERTION(widget,
                          "SetPointerLock(): Unable to find widget in "
-                         "shell->GetRootFrame()->GetNearestWidget();");
+                         "presShell->GetRootFrame()->GetNearestWidget();");
     if (aElement && !widget) {
       return false;
     }
   }
 
   // Hide the cursor and set pointer lock for future mouse events
   RefPtr<EventStateManager> esm = presContext->EventStateManager();
   esm->SetCursor(aCursorStyle, nullptr, Nothing(), widget, true);
@@ -11691,18 +11697,18 @@ void Document::FlushUserFontSet() {
   if (!mFontFaceSetDirty) {
     return;
   }
 
   mFontFaceSetDirty = false;
 
   if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
     nsTArray<nsFontFaceRuleContainer> rules;
-    nsIPresShell* shell = GetShell();
-    if (shell && !shell->StyleSet()->AppendFontFaceRules(rules)) {
+    PresShell* presShell = GetPresShell();
+    if (presShell && !presShell->StyleSet()->AppendFontFaceRules(rules)) {
       return;
     }
 
     if (!mFontFaceSet && !rules.IsEmpty()) {
       nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
       mFontFaceSet = new FontFaceSet(window, this);
     }
 
@@ -11710,31 +11716,31 @@ void Document::FlushUserFontSet() {
     if (mFontFaceSet) {
       changed = mFontFaceSet->UpdateRules(rules);
     }
 
     // We need to enqueue a style change reflow (for later) to
     // reflect that we're modifying @font-face rules.  (However,
     // without a reflow, nothing will happen to start any downloads
     // that are needed.)
-    if (changed && shell) {
-      if (nsPresContext* presContext = shell->GetPresContext()) {
+    if (changed && presShell) {
+      if (nsPresContext* presContext = presShell->GetPresContext()) {
         presContext->UserFontSetUpdated();
       }
     }
   }
 }
 
 void Document::MarkUserFontSetDirty() {
   if (mFontFaceSetDirty) {
     return;
   }
   mFontFaceSetDirty = true;
-  if (nsIPresShell* shell = GetShell()) {
-    shell->EnsureStyleFlush();
+  if (PresShell* presShell = GetPresShell()) {
+    presShell->EnsureStyleFlush();
   }
 }
 
 FontFaceSet* Document::Fonts() {
   if (!mFontFaceSet) {
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
     mFontFaceSet = new FontFaceSet(window, this);
     FlushUserFontSet();
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef mozilla_dom_Document_h___
 #define mozilla_dom_Document_h___
 
+#include "mozilla/EventStates.h"  // for EventStates
 #include "mozilla/FlushType.h"  // for enum
 #include "mozilla/Pair.h"       // for Pair
 #include "nsAutoPtr.h"          // for member
 #include "nsCOMArray.h"         // for member
 #include "nsCompatibility.h"    // for member
 #include "nsCOMPtr.h"           // for member
 #include "nsICookieSettings.h"
 #include "nsGkAtoms.h"  // for static class members
@@ -18,17 +19,16 @@
 #include "nsIApplicationCacheContainer.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #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 "nsIRadioGroupContainer.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptGlobalObject.h"  // for member (in nsCOMPtr)
 #include "nsIServiceManager.h"
 #include "nsIURI.h"  // for use in inline functions
 #include "nsIUUIDGenerator.h"
@@ -133,16 +133,17 @@ class AbstractThread;
 class CSSStyleSheet;
 class Encoding;
 class ErrorResult;
 class EventStates;
 class EventListenerManager;
 class FullscreenExit;
 class FullscreenRequest;
 class PendingAnimationTracker;
+class PresShell;
 class ServoStyleSet;
 class SMILAnimationController;
 enum class StyleCursorKind : uint8_t;
 template <typename>
 class OwningNonNull;
 struct URLExtraData;
 
 namespace css {
@@ -465,18 +466,18 @@ class Document : public nsINode,
                                                                    nsINode)
 
 #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_;                                                   \
+    if (PresShell* presShell = GetObservingPresShell()) {                     \
+      presShell->func_ params_;                                               \
     }                                                                         \
   } while (0)
 
   // nsIApplicationCacheContainer
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
   // nsIRadioGroupContainer
   NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
@@ -1238,37 +1239,31 @@ class Document : public nsINode,
 
   /**
    * 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.
    */
-  already_AddRefed<nsIPresShell> CreateShell(
+  already_AddRefed<PresShell> CreatePresShell(
       nsPresContext* aContext, nsViewManager* aViewManager,
       UniquePtr<ServoStyleSet> aStyleSet);
-  void DeleteShell();
-
-  nsIPresShell* GetShell() const {
+  void DeletePresShell();
+
+  PresShell* GetPresShell() const {
     return GetBFCacheEntry() ? nullptr : mPresShell;
   }
 
-  nsIPresShell* GetObservingShell() const {
-    return mPresShell && mPresShell->IsObservingDocument() ? mPresShell
-                                                           : nullptr;
-  }
+  inline PresShell* GetObservingPresShell() const;
 
   // Return whether the presshell for this document is safe to flush.
   bool IsSafeToFlush() const;
 
-  nsPresContext* GetPresContext() const {
-    nsIPresShell* shell = GetShell();
-    return shell ? shell->GetPresContext() : nullptr;
-  }
+  inline nsPresContext* GetPresContext() const;
 
   bool HasShellOrBFCacheEntry() const { return mPresShell || mBFCacheEntry; }
 
   // Instead using this method, what you probably want is
   // RemoveFromBFCacheSync() as we do in MessagePort and BroadcastChannel.
   void DisallowBFCaching() {
     NS_ASSERTION(!mBFCacheEntry, "We're already in the bfcache!");
     mBFCacheDisallowed = true;
@@ -2513,17 +2508,17 @@ class Document : public nsINode,
    */
   Document* GetDisplayDocument() const { return mDisplayDocument; }
 
   /**
    * Set the display document for this document.  aDisplayDocument must not be
    * null.
    */
   void SetDisplayDocument(Document* aDisplayDocument) {
-    MOZ_ASSERT(!GetShell() && !GetContainer() && !GetWindow(),
+    MOZ_ASSERT(!GetPresShell() && !GetContainer() && !GetWindow(),
                "Shouldn't set mDisplayDocument on documents that already "
                "have a presentation or a docshell or a window");
     MOZ_ASSERT(aDisplayDocument, "Must not be null");
     MOZ_ASSERT(aDisplayDocument != this, "Should be different document");
     MOZ_ASSERT(!aDisplayDocument->GetDisplayDocument(),
                "Display documents should not nest");
     mDisplayDocument = aDisplayDocument;
     mHasDisplayDocument = !!aDisplayDocument;
@@ -3852,17 +3847,17 @@ class Document : public nsINode,
   nsCString GetContentTypeInternal() const { return mContentType; }
 
   // Update our frame request callback scheduling state, if needed.  This will
   // schedule or unschedule them, if necessary, and update
   // mFrameRequestCallbacksScheduled.  aOldShell should only be passed when
   // mPresShell is becoming null; in that case it will be used to get hold of
   // the relevant refresh driver.
   void UpdateFrameRequestCallbackSchedulingState(
-      nsIPresShell* aOldShell = nullptr);
+      PresShell* aOldPresShell = nullptr);
 
   // Helper for GetScrollingElement/IsScrollingElement.
   bool IsPotentiallyScrollable(HTMLBodyElement* aBody);
 
   // Return the same type parent docuement if exists, or return null.
   Document* GetSameTypeParentDocument();
 
   void MaybeAllowStorageForOpenerAfterUserInteraction();
@@ -4332,17 +4327,17 @@ class Document : public nsINode,
   // if this document is part of a multipart document,
   // the ID can be used to distinguish it from the other parts.
   uint32_t mPartID;
 
   // Cycle collector generation in which we're certain that this document
   // won't be collected
   uint32_t mMarkedCCGeneration;
 
-  nsIPresShell* mPresShell;
+  PresShell* mPresShell;
 
   nsCOMArray<nsINode> mSubtreeModifiedTargets;
   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.
--- a/dom/base/DocumentInlines.h
+++ b/dom/base/DocumentInlines.h
@@ -1,24 +1,36 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef mozilla_dom_DocumentInlines_h
 #define mozilla_dom_DocumentInlines_h
 
+#include "mozilla/dom/Document.h"
+
+#include "mozilla/dom/HTMLBodyElement.h"
 #include "nsContentUtils.h"
-#include "mozilla/dom/Document.h"
-#include "mozilla/dom/HTMLBodyElement.h"
+#include "nsIPresShell.h"
+#include "nsPresContext.h"
 #include "nsStyleSheetService.h"
 
 namespace mozilla {
 namespace dom {
 
+inline PresShell* Document::GetObservingPresShell() const {
+  return mPresShell && mPresShell->IsObservingDocument() ? mPresShell : nullptr;
+}
+
+inline nsPresContext* Document::GetPresContext() const {
+  PresShell* presShell = GetPresShell();
+  return presShell ? presShell->GetPresContext() : nullptr;
+}
+
 inline HTMLBodyElement* Document::GetBodyElement() {
   return static_cast<HTMLBodyElement*>(GetHtmlChildElement(nsGkAtoms::body));
 }
 
 template <typename T>
 size_t Document::FindDocStyleSheetInsertionPoint(const nsTArray<T>& aDocSheets,
                                                  const StyleSheet& aSheet) {
   nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
--- a/dom/base/DocumentOrShadowRoot.cpp
+++ b/dom/base/DocumentOrShadowRoot.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DocumentOrShadowRoot.h"
 #include "mozilla/EventStateManager.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/StyleSheetList.h"
 #include "nsFocusManager.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
 #include "nsLayoutUtils.h"
@@ -239,22 +240,22 @@ static void QueryNodesFromRect(DocumentO
   nsCOMPtr<Document> doc = aRoot.AsNode().OwnerDoc();
 
   // Make sure the layout information we get is up-to-date, and
   // ensure we get a root frame (for everything but XUL)
   if (aShouldFlushLayout == FlushLayout::Yes) {
     doc->FlushPendingNotifications(FlushType::Layout);
   }
 
-  nsIPresShell* ps = doc->GetShell();
-  if (!ps) {
+  PresShell* presShell = doc->GetPresShell();
+  if (!presShell) {
     return;
   }
 
-  nsIFrame* rootFrame = ps->GetRootFrame();
+  nsIFrame* rootFrame = presShell->GetRootFrame();
   // XUL docs, unlike HTML, have no frame tree until everything's done loading
   if (!rootFrame) {
     return;  // return null to premature XUL callers as a reminder to wait
   }
 
   aOptions += FrameForPointOption::IgnorePaintSuppression;
   aOptions += FrameForPointOption::IgnoreCrossDoc;
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -29,17 +29,16 @@
 #include "mozilla/dom/DocumentTimeline.h"
 #include "nsFlexContainerFrame.h"
 #include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsStyleConsts.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsDOMCID.h"
 #include "nsIServiceManager.h"
 #include "nsDOMCSSAttrDeclaration.h"
 #include "nsNameSpaceManager.h"
@@ -63,16 +62,17 @@
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FullscreenChange.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/RestyleManager.h"
 #include "mozilla/ScrollTypes.h"
 #include "mozilla/SizeOfState.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/TextEvents.h"
 #include "nsNodeUtils.h"
 #include "mozilla/dom/DirectionalityUtils.h"
 #include "mozilla/dom/Document.h"
@@ -443,17 +443,17 @@ Element::StyleStateLocks Element::Locked
     return *locks;
   }
   return StyleStateLocks();
 }
 
 void Element::NotifyStyleStateChange(EventStates aStates) {
   Document* doc = GetComposedDoc();
   if (doc) {
-    nsIPresShell* presShell = doc->GetShell();
+    RefPtr<PresShell> presShell = doc->GetPresShell();
     if (presShell) {
       nsAutoScriptBlocker scriptBlocker;
       presShell->ContentStateChanged(doc, this, aStates);
     }
   }
 }
 
 void Element::LockStyleStates(EventStates aStates, bool aEnabled) {
@@ -522,17 +522,17 @@ static bool IsLikelyCustomElement(const 
 }
 
 static bool MayNeedToLoadXBLBinding(const Document& aDocument,
                                     const Element& aElement) {
   // If we have a frame, the frame has already loaded the binding.
   // Otherwise, don't do anything else here unless we're dealing with
   // XUL or an HTML element that may have a plugin-related overlay
   // (i.e. object or embed).
-  if (!aDocument.GetShell() || aElement.GetPrimaryFrame()) {
+  if (!aDocument.GetPresShell() || aElement.GetPrimaryFrame()) {
     return false;
   }
 
   if (auto* xulElem = nsXULElement::FromNode(aElement)) {
     return !IsLikelyCustomElement(*xulElem);
   }
 
   return aElement.IsAnyOfHTMLElements(nsGkAtoms::object, nsGkAtoms::embed);
@@ -693,18 +693,18 @@ nsIScrollableFrame* Element::GetScrollFr
   // Now reget *aStyledFrame if the caller asked for it, because that frame
   // flush can kill it.
   if (aFrame) {
     *aFrame = GetPrimaryFrame(FlushType::None);
   }
 
   if (isScrollingElement) {
     // Our scroll info should map to the root scrollable frame if there is one.
-    if (nsIPresShell* shell = doc->GetShell()) {
-      return shell->GetRootScrollFrameAsScrollable();
+    if (PresShell* presShell = doc->GetPresShell()) {
+      return presShell->GetRootScrollFrameAsScrollable();
     }
   }
 
   return nullptr;
 }
 
 void Element::ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject) {
   if (aObject.IsScrollIntoViewOptions()) {
@@ -726,17 +726,17 @@ void Element::ScrollIntoView(const Boole
 
 void Element::ScrollIntoView(const ScrollIntoViewOptions& aOptions) {
   Document* document = GetComposedDoc();
   if (!document) {
     return;
   }
 
   // Get the presentation shell
-  nsCOMPtr<nsIPresShell> presShell = document->GetShell();
+  RefPtr<PresShell> presShell = document->GetPresShell();
   if (!presShell) {
     return;
   }
 
   int16_t vpercent = nsIPresShell::SCROLL_CENTER;
   switch (aOptions.mBlock) {
     case ScrollLogicalPosition::Start:
       vpercent = nsIPresShell::SCROLL_TOP;
@@ -985,17 +985,17 @@ nsRect Element::GetClientAreaRect() {
       LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0;
   bool rootContentDocument =
       presContext && presContext->IsRootContentDocument();
   if (overlayScrollbars && rootContentDocument &&
       doc->IsScrollingElement(this)) {
     // We will always have a pres shell if we have a pres context, and we will
     // only get here if we have a pres context from the root content document
     // check
-    nsIPresShell* presShell = doc->GetShell();
+    PresShell* presShell = doc->GetPresShell();
 
     // Ensure up to date dimensions, but don't reflow
     RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
     if (viewManager) {
       viewManager->FlushDelayedResize(false);
     }
     return nsRect(nsPoint(), presContext->GetVisibleArea().Size());
   }
@@ -1193,18 +1193,18 @@ already_AddRefed<ShadowRoot> Element::At
   nsAutoScriptBlocker scriptBlocker;
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo =
       mNodeInfo->NodeInfoManager()->GetNodeInfo(
           nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None,
           DOCUMENT_FRAGMENT_NODE);
 
   if (Document* doc = GetComposedDoc()) {
-    if (nsIPresShell* shell = doc->GetShell()) {
-      shell->DestroyFramesForAndRestyle(this);
+    if (PresShell* presShell = doc->GetPresShell()) {
+      presShell->DestroyFramesForAndRestyle(this);
     }
   }
   MOZ_ASSERT(!GetPrimaryFrame());
 
   /**
    * 4. Let shadow be a new shadow root whose node document is
    *    context object's node document, host is context object,
    *    and mode is init's mode.
@@ -1314,18 +1314,18 @@ void Element::UnattachShadow() {
   ShadowRoot* shadowRoot = GetShadowRoot();
   if (!shadowRoot) {
     return;
   }
 
   nsAutoScriptBlocker scriptBlocker;
 
   if (Document* doc = GetComposedDoc()) {
-    if (nsIPresShell* shell = doc->GetShell()) {
-      shell->DestroyFramesForAndRestyle(this);
+    if (PresShell* presShell = doc->GetPresShell()) {
+      presShell->DestroyFramesForAndRestyle(this);
     }
   }
   MOZ_ASSERT(!GetPrimaryFrame());
 
   shadowRoot->Unattach();
   SetShadowRoot(nullptr);
 
   // Beware shadowRoot could be dead after this call.
@@ -2036,18 +2036,18 @@ nsresult Element::SetSMILOverrideStyleDe
   Element::nsExtendedDOMSlots* slots = ExtendedDOMSlots();
 
   slots->mSMILOverrideStyleDeclaration = aDeclaration;
 
   // Only need to request a restyle if we're in a document.  (We might not
   // be in a document, if we're clearing animation effects on a target node
   // that's been detached since the previous animation sample.)
   if (Document* doc = GetComposedDoc()) {
-    if (nsIPresShell* shell = doc->GetShell()) {
-      shell->RestyleForAnimation(this, StyleRestyleHint_RESTYLE_SMIL);
+    if (PresShell* presShell = doc->GetPresShell()) {
+      presShell->RestyleForAnimation(this, StyleRestyleHint_RESTYLE_SMIL);
     }
   }
 
   return NS_OK;
 }
 
 bool Element::IsLabelable() const { return false; }
 
@@ -4285,18 +4285,18 @@ static void NoteDirtyElement(Element* aE
     // order to avoid work here, because since the style system keeps style data
     // in, e.g., subtrees under a leaf frame, missing restyles and such in there
     // has observable behavior via getComputedStyle, for example.
     if (Servo_Element_IsDisplayNone(parent->AsElement())) {
       return;
     }
   }
 
-  if (nsIPresShell* shell = doc->GetShell()) {
-    shell->EnsureStyleFlush();
+  if (PresShell* presShell = doc->GetPresShell()) {
+    presShell->EnsureStyleFlush();
   }
 
   MOZ_ASSERT(parent->IsElement() || parent == doc);
 
   // The bit checks below rely on this to arrive to useful conclusions about the
   // shape of the tree.
   AssertNoBitsPropagatedFrom(existingRoot);
 
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -26,16 +26,18 @@
 #include "nsNodeUtils.h"
 #include "nsPresContext.h"
 #include "Units.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FlushType.h"
+#include "mozilla/PresShell.h"
+#include "mozilla/PseudoStyleType.h"
 #include "mozilla/RustCell.h"
 #include "mozilla/SMILAttr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/DirectionalityUtils.h"
 #include "mozilla/dom/FragmentOrElement.h"
 #include "mozilla/dom/DOMRect.h"
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -1371,26 +1371,20 @@ void EventSourceImpl::DispatchAllMessage
   }
 
   nsresult rv = mEventSource->CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
   AutoJSAPI jsapi;
-  if (mIsMainThread) {
-    if (NS_WARN_IF(!jsapi.Init(mEventSource->GetOwner()))) {
-      return;
-    }
-  } else {
-    MOZ_ASSERT(mWorkerRef);
-    if (NS_WARN_IF(!jsapi.Init(mWorkerRef->Private()->GlobalScope()))) {
-      return;
-    }
+  if (NS_WARN_IF(!jsapi.Init(mEventSource->GetOwnerGlobal()))) {
+    return;
   }
+
   JSContext* cx = jsapi.cx();
 
   while (mMessagesToDispatch.GetSize() > 0) {
     UniquePtr<Message> message(
         static_cast<Message*>(mMessagesToDispatch.PopFront()));
     // Now we can turn our string into a jsval
     JS::Rooted<JS::Value> jsData(cx);
     {
@@ -1778,23 +1772,24 @@ NS_IMETHODIMP
 EventSourceImpl::CheckListenerChain() {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
   return NS_OK;
 }
 ////////////////////////////////////////////////////////////////////////////////
 // EventSource
 ////////////////////////////////////////////////////////////////////////////////
 
-EventSource::EventSource(nsPIDOMWindowInner* aOwnerWindow,
+EventSource::EventSource(nsIGlobalObject* aGlobal,
                          nsICookieSettings* aCookieSettings,
                          bool aWithCredentials)
-    : DOMEventTargetHelper(aOwnerWindow),
+    : DOMEventTargetHelper(aGlobal),
       mWithCredentials(aWithCredentials),
       mIsMainThread(true),
       mKeepingAlive(false) {
+  MOZ_ASSERT(aGlobal);
   MOZ_ASSERT(aCookieSettings);
   mImpl = new EventSourceImpl(this, aCookieSettings);
 }
 
 EventSource::~EventSource() {}
 
 nsresult EventSource::CreateAndDispatchSimpleEvent(const nsAString& aName) {
   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
@@ -1805,39 +1800,41 @@ nsresult EventSource::CreateAndDispatchS
   DispatchEvent(*event, rv);
   return rv.StealNSResult();
 }
 
 /* static */
 already_AddRefed<EventSource> EventSource::Constructor(
     const GlobalObject& aGlobal, const nsAString& aURL,
     const EventSourceInit& aEventSourceInitDict, ErrorResult& aRv) {
-  nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
-      do_QueryInterface(aGlobal.GetAsSupports());
-
-  MOZ_ASSERT(!NS_IsMainThread() || ownerWindow);
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+  if (NS_WARN_IF(!global)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   nsCOMPtr<nsICookieSettings> cookieSettings;
+  nsCOMPtr<nsPIDOMWindowInner> ownerWindow = do_QueryInterface(global);
   if (ownerWindow) {
     Document* doc = ownerWindow->GetExtantDoc();
     if (NS_WARN_IF(!doc)) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     cookieSettings = doc->CookieSettings();
   } else {
     // Worker side.
     WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(workerPrivate);
     cookieSettings = workerPrivate->CookieSettings();
   }
 
   RefPtr<EventSource> eventSource = new EventSource(
-      ownerWindow, cookieSettings, aEventSourceInitDict.mWithCredentials);
+      global, cookieSettings, aEventSourceInitDict.mWithCredentials);
   RefPtr<EventSourceImpl> eventSourceImp = eventSource->mImpl;
 
   if (NS_IsMainThread()) {
     // Get principal from document and init EventSourceImpl
     nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
         do_QueryInterface(aGlobal.GetAsSupports());
     if (!scriptPrincipal) {
       aRv.Throw(NS_ERROR_FAILURE);
--- a/dom/base/EventSource.h
+++ b/dom/base/EventSource.h
@@ -19,17 +19,17 @@
 #include "nsIObserver.h"
 #include "nsIStreamListener.h"
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsITimer.h"
 #include "nsIHttpChannel.h"
 #include "nsDeque.h"
 
-class nsPIDOMWindowInner;
+class nsIGlobalObject;
 class nsICookieSettings;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
@@ -76,18 +76,18 @@ class EventSource final : public DOMEven
 
   IMPL_EVENT_HANDLER(open)
   IMPL_EVENT_HANDLER(message)
   IMPL_EVENT_HANDLER(error)
 
   void Close();
 
  private:
-  EventSource(nsPIDOMWindowInner* aOwnerWindow,
-              nsICookieSettings* aCookieSettings, bool aWithCredentials);
+  EventSource(nsIGlobalObject* aGlobal, nsICookieSettings* aCookieSettings,
+              bool aWithCredentials);
   virtual ~EventSource();
   // prevent bad usage
   EventSource(const EventSource& x) = delete;
   EventSource& operator=(const EventSource& x) = delete;
 
   void AssertIsOnTargetThread() const {
     MOZ_ASSERT(NS_IsMainThread() == mIsMainThread);
   }
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -17,16 +17,17 @@
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/DeclarationBlock.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/HTMLEditor.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/RestyleManager.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/URLExtraData.h"
 #include "mozilla/dom/Attr.h"
 #include "nsDOMAttributeMap.h"
 #include "nsAtom.h"
 #include "mozilla/dom/NodeInfo.h"
@@ -38,17 +39,16 @@
 #include "nsIDocumentEncoder.h"
 #include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIFrame.h"
 #include "nsIAnonymousContentCreator.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsStyleConsts.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsDOMCID.h"
 #include "nsIServiceManager.h"
 #include "nsDOMCSSAttrDeclaration.h"
 #include "nsNameSpaceManager.h"
@@ -1575,17 +1575,17 @@ static bool ShouldClearPurple(nsIContent
   return aContent->HasProperties();
 }
 
 // If aNode is not optimizable, but is an element
 // with a frame in a document which has currently active presshell,
 // we can act as if it was optimizable. When the primary frame dies, aNode
 // will end up to the purple buffer because of the refcount change.
 bool NodeHasActiveFrame(Document* aCurrentDoc, nsINode* aNode) {
-  return aCurrentDoc->GetShell() && aNode->IsElement() &&
+  return aCurrentDoc->GetPresShell() && aNode->IsElement() &&
          aNode->AsElement()->GetPrimaryFrame();
 }
 
 bool OwnedByBindingManager(Document* aCurrentDoc, nsINode* aNode) {
   return aNode->IsElement() && aNode->AsElement()->GetXBLBinding();
 }
 
 // CanSkip checks if aNode is known-live, and if it is, returns true. If aNode
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -14,30 +14,31 @@
 #include "nsIURIFixup.h"
 #include "nsIURL.h"
 #include "nsIURIMutator.h"
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "nsCOMPtr.h"
 #include "nsEscape.h"
 #include "nsIDOMWindow.h"
-#include "mozilla/dom/Document.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsError.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Components.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/Unused.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/LocationBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "ReferrerInfo.h"
 
 namespace mozilla {
 namespace dom {
 
 Location::Location(nsPIDOMWindowInner* aWindow, nsIDocShell* aDocShell)
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -3,16 +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/. */
 
 #include "PostMessageEvent.h"
 
 #include "MessageEvent.h"
 #include "mozilla/dom/BlobBinding.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileList.h"
 #include "mozilla/dom/FileListBinding.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
--- a/dom/base/ResponsiveImageSelector.cpp
+++ b/dom/base/ResponsiveImageSelector.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ResponsiveImageSelector.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ServoStyleSetInlines.h"
 #include "mozilla/TextUtils.h"
 #include "nsIURI.h"
 #include "mozilla/dom/Document.h"
 #include "nsContentUtils.h"
 #include "nsPresContext.h"
 
 #include "nsCSSProps.h"
@@ -396,17 +397,17 @@ int ResponsiveImageSelector::GetSelected
   SelectImage();
 
   return mSelectedCandidateIndex;
 }
 
 bool ResponsiveImageSelector::ComputeFinalWidthForCurrentViewport(
     double* aWidth) {
   dom::Document* doc = Document();
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   nsPresContext* pctx = presShell ? presShell->GetPresContext() : nullptr;
 
   if (!pctx) {
     return false;
   }
   nscoord effectiveWidth =
       presShell->StyleSet()->EvaluateSourceSizeList(mServoSourceSizeList.get());
 
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -12,16 +12,17 @@
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsWindowSizes.h"
 #include "nsXBLPrototypeBinding.h"
 #include "mozilla/dom/DirectionalityUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IdentifierMapEntry.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ServoStyleRuleMap.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/dom/StyleSheetList.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -180,22 +181,22 @@ void ShadowRoot::Unattach() {
 
 void ShadowRoot::InvalidateStyleAndLayoutOnSubtree(Element* aElement) {
   MOZ_ASSERT(aElement);
   Document* doc = GetComposedDoc();
   if (!doc) {
     return;
   }
 
-  nsIPresShell* shell = doc->GetShell();
-  if (!shell) {
+  PresShell* presShell = doc->GetPresShell();
+  if (!presShell) {
     return;
   }
 
-  shell->DestroyFramesForAndRestyle(aElement);
+  presShell->DestroyFramesForAndRestyle(aElement);
 }
 
 void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) {
   MOZ_ASSERT(aSlot);
 
   // Note that if name attribute missing, the slot is a default slot.
   nsAutoString name;
   aSlot->GetName(name);
@@ -344,18 +345,18 @@ void ShadowRoot::RuleChanged(StyleSheet&
 }
 
 void ShadowRoot::ApplicableRulesChanged() {
   Document* doc = GetComposedDoc();
   if (!doc) {
     return;
   }
 
-  if (nsIPresShell* shell = doc->GetShell()) {
-    shell->RecordShadowStyleChange(*this);
+  if (PresShell* presShell = doc->GetPresShell()) {
+    presShell->RecordShadowStyleChange(*this);
   }
 }
 
 void ShadowRoot::InsertSheetAt(size_t aIndex, StyleSheet& aSheet) {
   DocumentOrShadowRoot::InsertSheetAt(aIndex, aSheet);
   if (aSheet.IsApplicable()) {
     InsertSheetIntoAuthorData(aIndex, aSheet);
   }
@@ -529,18 +530,18 @@ void ShadowRoot::MaybeReassignElement(El
   SlotAssignment assignment = SlotAssignmentFor(aElement);
 
   if (assignment.mSlot == oldSlot) {
     // Nothing to do here.
     return;
   }
 
   if (Document* doc = GetComposedDoc()) {
-    if (nsIPresShell* shell = doc->GetShell()) {
-      shell->SlotAssignmentWillChange(*aElement, oldSlot, assignment.mSlot);
+    if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
+      presShell->SlotAssignmentWillChange(*aElement, oldSlot, assignment.mSlot);
     }
   }
 
   if (oldSlot) {
     oldSlot->RemoveAssignedNode(aElement);
     oldSlot->EnqueueSlotChangeEvent();
   }
 
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -6,30 +6,30 @@
 
 /*
  * Base class for the XML and HTML content sinks, which construct a
  * DOM based on information from the parser.
  */
 
 #include "nsContentSink.h"
 #include "mozilla/Components.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/SRILogHelper.h"
 #include "nsStyleLinkElement.h"
 #include "nsIDocShell.h"
 #include "nsILoadContext.h"
 #include "nsIPrefetchService.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsIProtocolHandler.h"
 #include "nsIHttpChannel.h"
 #include "nsIContent.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsViewManager.h"
 #include "nsAtom.h"
 #include "nsGkAtoms.h"
 #include "nsGlobalWindowInner.h"
 #include "nsNetCID.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIApplicationCache.h"
@@ -94,17 +94,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 nsContentSink::nsContentSink()
     : mBackoffCount(0),
       mLastNotificationTime(0),
-      mBeganUpdate(0),
       mLayoutStarted(0),
       mDynamicLowerValue(0),
       mParsing(0),
       mDroppedTimer(0),
       mDeferredLayoutStart(0),
       mDeferredFlushTags(0),
       mIsDocumentObserver(0),
       mRunsToCompletion(0),
@@ -1186,47 +1185,43 @@ void nsContentSink::StartLayout(bool aIg
   // sure to flush tags instead of just calling UpdateChildCounts() after we
   // loop over the shells.
   FlushTags();
 
   mLayoutStarted = true;
   mLastNotificationTime = PR_Now();
 
   mDocument->SetMayStartLayout(true);
-  nsCOMPtr<nsIPresShell> shell = mDocument->GetShell();
+  RefPtr<PresShell> presShell = mDocument->GetPresShell();
   // Make sure we don't call Initialize() for a shell that has
   // already called it. This can happen when the layout frame for
   // an iframe is constructed *between* the Embed() call for the
   // docshell in the iframe, and the content sink's call to OpenBody().
   // (Bug 153815)
-  if (shell && !shell->DidInitialize()) {
-    nsresult rv = shell->Initialize();
+  if (presShell && !presShell->DidInitialize()) {
+    nsresult rv = presShell->Initialize();
     if (NS_FAILED(rv)) {
       return;
     }
   }
 
   // If the document we are loading has a reference or it is a
   // frameset document, disable the scroll bars on the views.
 
   mDocument->SetScrollToRef(mDocument->GetDocumentURI());
 }
 
 void nsContentSink::NotifyAppend(nsIContent* aContainer, uint32_t aStartIndex) {
-  if (aContainer->GetUncomposedDoc() != mDocument) {
-    // aContainer is not actually in our document anymore.... Just bail out of
-    // here; notifying on our document for this append would be wrong.
-    return;
-  }
-
   mInNotification++;
 
   {
     // Scope so we call EndUpdate before we decrease mInNotification
-    MOZ_AUTO_DOC_UPDATE(mDocument, !mBeganUpdate);
+    //
+    // Note that aContainer->OwnerDoc() may not be mDocument.
+    MOZ_AUTO_DOC_UPDATE(aContainer->OwnerDoc(), true);
     nsNodeUtils::ContentAppended(
         aContainer, aContainer->GetChildAt_Deprecated(aStartIndex));
     mLastNotificationTime = PR_Now();
   }
 
   mInNotification--;
 }
 
@@ -1345,30 +1340,30 @@ nsresult nsContentSink::WillResumeImpl()
 }
 
 nsresult nsContentSink::DidProcessATokenImpl() {
   if (mRunsToCompletion || !mParser) {
     return NS_OK;
   }
 
   // Get the current user event time
-  nsIPresShell* shell = mDocument->GetShell();
-  if (!shell) {
+  PresShell* presShell = mDocument->GetPresShell();
+  if (!presShell) {
     // If there's no pres shell in the document, return early since
     // we're not laying anything out here.
     return NS_OK;
   }
 
   // Increase before comparing to gEventProbeRate
   ++mDeflectedCount;
 
   // Check if there's a pending event
   if (sPendingEventMode != 0 && !mHasPendingEvent &&
       (mDeflectedCount % sEventProbeRate) == 0) {
-    nsViewManager* vm = shell->GetViewManager();
+    nsViewManager* vm = presShell->GetViewManager();
     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
     nsCOMPtr<nsIWidget> widget;
     vm->GetRootWidget(getter_AddRefs(widget));
     mHasPendingEvent = widget && widget->HasPendingInputEvent();
   }
 
   if (mHasPendingEvent && sPendingEventMode == 2) {
     return NS_ERROR_HTMLPARSER_INTERRUPTED;
@@ -1492,25 +1487,25 @@ bool nsContentSink::IsScriptExecutingImp
   return !!mScriptLoader->GetCurrentScript();
 }
 
 nsresult nsContentSink::WillParseImpl(void) {
   if (mRunsToCompletion || !mDocument) {
     return NS_OK;
   }
 
-  nsIPresShell* shell = mDocument->GetShell();
-  if (!shell) {
+  PresShell* presShell = mDocument->GetPresShell();
+  if (!presShell) {
     return NS_OK;
   }
 
   uint32_t currentTime = PR_IntervalToMicroseconds(PR_IntervalNow());
 
   if (sEnablePerfMode == 0) {
-    nsViewManager* vm = shell->GetViewManager();
+    nsViewManager* vm = presShell->GetViewManager();
     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
     uint32_t lastEventTime;
     vm->GetLastUserEventTime(lastEventTime);
 
     bool newDynLower =
         mDocument->IsInBackgroundWindow() ||
         ((currentTime - mBeginLoadTime) > uint32_t(sInitialPerfTime) &&
          (currentTime - lastEventTime) < uint32_t(sInteractiveTime));
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -283,18 +283,16 @@ class nsContentSink : public nsICSSLoade
 
   // Time of last notification
   // Note: mLastNotificationTime is only valid once mLayoutStarted is true.
   PRTime mLastNotificationTime;
 
   // Timer used for notification
   nsCOMPtr<nsITimer> mNotificationTimer;
 
-  // Have we already called BeginUpdate for this set of content changes?
-  uint8_t mBeganUpdate : 1;
   uint8_t mLayoutStarted : 1;
   uint8_t mDynamicLowerValue : 1;
   uint8_t mParsing : 1;
   uint8_t mDroppedTimer : 1;
   // If true, we deferred starting layout until sheets load
   uint8_t mDeferredLayoutStart : 1;
   // If true, we deferred notifications until sheets load
   uint8_t mDeferredFlushTags : 1;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -45,16 +45,17 @@
 #include "mozilla/Components.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/MessageBroadcaster.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/dom/Event.h"
@@ -85,16 +86,17 @@
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/Likely.h"
 #include "mozilla/ManualNAC.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/TextEvents.h"
 #include "nsArrayUtils.h"
 #include "nsAString.h"
@@ -3191,35 +3193,31 @@ void nsContentUtils::SplitExpatName(cons
     nameStart = aExpatName;
     nameEnd = pos;
     *aPrefix = nullptr;
   }
   *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
 }
 
 // static
-nsIPresShell* nsContentUtils::GetPresShellForContent(
-    const nsIContent* aContent) {
+PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
   Document* doc = aContent->GetComposedDoc();
   if (!doc) {
     return nullptr;
   }
-
-  return doc->GetShell();
+  return doc->GetPresShell();
 }
 
 // static
 nsPresContext* nsContentUtils::GetContextForContent(
     const nsIContent* aContent) {
-  nsIPresShell* presShell = GetPresShellForContent(aContent);
-
+  PresShell* presShell = GetPresShellForContent(aContent);
   if (!presShell) {
     return nullptr;
   }
-
   return presShell->GetPresContext();
 }
 
 // static
 bool nsContentUtils::CanLoadImage(nsIURI* aURI, nsINode* aNode,
                                   Document* aLoadingDocument,
                                   nsIPrincipal* aLoadingPrincipal) {
   MOZ_ASSERT(aURI, "Must have a URI");
@@ -4178,17 +4176,17 @@ nsresult nsContentUtils::DispatchInputEv
     }
   } else {
     Document* document = aEventTargetElement->OwnerDoc();
     if (NS_WARN_IF(!document)) {
       return NS_ERROR_FAILURE;
     }
     // If we're running xpcshell tests, we fail to get presShell here.
     // Even in such case, we need to dispatch "input" event without widget.
-    nsIPresShell* presShell = document->GetShell();
+    PresShell* presShell = document->GetPresShell();
     if (presShell) {
       nsPresContext* presContext = presShell->GetPresContext();
       if (NS_WARN_IF(!presContext)) {
         return NS_ERROR_FAILURE;
       }
       widget = presContext->GetRootWidget();
       if (NS_WARN_IF(!widget)) {
         return NS_ERROR_FAILURE;
@@ -6292,19 +6290,19 @@ void nsContentUtils::PopulateStringFromS
 
 nsIPresShell* nsContentUtils::FindPresShellForDocument(const Document* aDoc) {
   const Document* doc = aDoc;
   Document* displayDoc = doc->GetDisplayDocument();
   if (displayDoc) {
     doc = displayDoc;
   }
 
-  nsIPresShell* shell = doc->GetShell();
-  if (shell) {
-    return shell;
+  PresShell* presShell = doc->GetPresShell();
+  if (presShell) {
+    return presShell;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
   while (docShellTreeItem) {
     // We may be in a display:none subdocument, or we may not have a presshell
     // created yet.
     // Walk the docshell tree to find the nearest container that has a
     // presshell, and return that.
@@ -9827,17 +9825,17 @@ bool nsContentUtils::AttemptLargeAllocat
 /* static */
 void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
     Document* aDocument, nsTArray<nsIContent*>& aElements) {
   MOZ_ASSERT(aDocument);
 #ifdef DEBUG
   size_t oldLength = aElements.Length();
 #endif
 
-  if (nsIPresShell* presShell = aDocument->GetShell()) {
+  if (PresShell* presShell = aDocument->GetPresShell()) {
     if (nsIFrame* scrollFrame = presShell->GetRootScrollFrame()) {
       nsIAnonymousContentCreator* creator = do_QueryFrame(scrollFrame);
       MOZ_ASSERT(
           creator,
           "scroll frame should always implement nsIAnonymousContentCreator");
       creator->AppendAnonymousContentTo(aElements, 0);
     }
 
@@ -10504,19 +10502,19 @@ bool nsContentUtils::StringifyJSON(JSCon
 bool nsContentUtils::
     HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
         Document* aDocument) {
   if (!aDocument || aDocument->IsLoadedAsData()) {
     return false;
   }
 
   Document* topLevel = aDocument->GetTopLevelContentDocument();
-  return topLevel && topLevel->GetShell() &&
-         topLevel->GetShell()->GetPresContext() &&
-         !topLevel->GetShell()->GetPresContext()->HadContentfulPaint() &&
+  return topLevel && topLevel->GetPresShell() &&
+         topLevel->GetPresShell()->GetPresContext() &&
+         !topLevel->GetPresShell()->GetPresContext()->HadContentfulPaint() &&
          nsThreadManager::MainThreadHasPendingHighPriorityEvents();
 }
 
 /* static */
 bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
   MOZ_ASSERT(aPrefName);
 
   nsAutoCString blackList;
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -122,16 +122,17 @@ class nsRefPtrHashtable;
 template <class T>
 class nsReadingIterator;
 
 namespace mozilla {
 class Dispatcher;
 class ErrorResult;
 class EventListenerManager;
 class HTMLEditor;
+class PresShell;
 class TextEditor;
 
 namespace dom {
 class ContentFrameMessageManager;
 struct CustomElementDefinition;
 class DataTransfer;
 class DocumentFragment;
 class Element;
@@ -822,17 +823,17 @@ class nsContentUtils {
 
   /**
    * Method that gets the pres shell for the node.
    *
    * @param aContent The content node.
    * @return the pres shell, or nullptr if the content is not in a document
    *         (if GetComposedDoc returns nullptr)
    */
-  static nsIPresShell* GetPresShellForContent(const nsIContent* aContent);
+  static mozilla::PresShell* GetPresShellForContent(const nsIContent* aContent);
 
   /**
    * Method to do security and content policy checks on the image URI
    *
    * @param aURI uri of the image to be loaded
    * @param aNode, the context the image is loaded in (eg an element)
    * @param aLoadingDocument the document we belong to
    * @param aLoadingPrincipal the principal doing the load
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -13,17 +13,16 @@
 #include "nsIClipboard.h"
 #include "nsIFormControl.h"
 #include "nsWidgetsCID.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsRange.h"
 #include "imgIContainer.h"
 #include "imgIRequest.h"
-#include "nsIPresShell.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/DataTransfer.h"
 
 #include "nsIDocShell.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIClipboardHelper.h"
 #include "nsISelectionController.h"
 
@@ -51,16 +50,17 @@
 #  include "nsReadableUtils.h"
 #  include "nsXULAppAPI.h"
 #endif
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/IntegerRange.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
@@ -583,18 +583,20 @@ static nsresult AppendImagePromise(nsITr
   return aTransferable->AddDataFlavor(kFilePromiseMime);
 }
 #endif  // XP_WIN
 
 nsIContent* nsCopySupport::GetSelectionForCopy(Document* aDocument,
                                                Selection** aSelection) {
   *aSelection = nullptr;
 
-  nsIPresShell* presShell = aDocument->GetShell();
-  if (!presShell) return nullptr;
+  PresShell* presShell = aDocument->GetPresShell();
+  if (!presShell) {
+    return nullptr;
+  }
 
   nsCOMPtr<nsIContent> focusedContent;
   nsCOMPtr<nsISelectionController> selectionController =
       presShell->GetSelectionControllerForFocusedContent(
           getter_AddRefs(focusedContent));
   if (!selectionController) {
     return nullptr;
   }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -14,16 +14,17 @@
 #include "nsQueryContentEventResult.h"
 #include "nsGlobalWindow.h"
 #include "nsFocusManager.h"
 #include "nsFrameManager.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/BlobBinding.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsFrame.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "ClientLayerManager.h"
@@ -39,25 +40,25 @@
 #include "nsCharsetSource.h"
 #include "nsJSEnvironment.h"
 #include "nsJSUtils.h"
 
 #include "mozilla/ChaosMode.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TextEventDispatcher.h"
 #include "mozilla/TouchEvents.h"
 
 #include "nsViewManager.h"
 
 #include "nsLayoutUtils.h"
 #include "nsComputedDOMStyle.h"
-#include "nsIPresShell.h"
 #include "nsCSSProps.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/DOMRect.h"
 #include <algorithm>
@@ -1034,17 +1035,17 @@ nsIWidget* nsDOMWindowUtils::GetWidget(n
 
   return nullptr;
 }
 
 nsIWidget* nsDOMWindowUtils::GetWidgetForElement(Element* aElement) {
   if (!aElement) return GetWidget();
 
   Document* doc = aElement->GetUncomposedDoc();
-  nsIPresShell* presShell = doc ? doc->GetShell() : nullptr;
+  PresShell* presShell = doc ? doc->GetPresShell() : nullptr;
 
   if (presShell) {
     nsIFrame* frame = aElement->GetPrimaryFrame();
     if (!frame) {
       frame = presShell->GetRootFrame();
     }
     if (frame) return frame->GetNearestWidget();
   }
@@ -1370,17 +1371,17 @@ static nsresult getScrollXYAppUnits(cons
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(aWindow);
   nsCOMPtr<Document> doc = window ? window->GetExtantDoc() : nullptr;
   NS_ENSURE_STATE(doc);
 
   if (aFlushLayout) {
     doc->FlushPendingNotifications(FlushType::Layout);
   }
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   if (presShell) {
     nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
     if (sf) {
       aScrollPos = sf->GetScrollPosition();
     }
   }
   return NS_OK;
 }
@@ -1456,17 +1457,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetVisualViewportOffsetRelativeToLayoutViewport(
     float* aOffsetX, float* aOffsetY) {
   *aOffsetX = 0;
   *aOffsetY = 0;
 
   nsCOMPtr<Document> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
 
   nsPoint offset = presShell->GetVisualViewportOffsetRelativeToLayoutViewport();
   *aOffsetX = nsPresContext::AppUnitsToFloatCSSPixels(offset.x);
   *aOffsetY = nsPresContext::AppUnitsToFloatCSSPixels(offset.y);
 
   return NS_OK;
 }
@@ -1475,17 +1476,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetVisualViewportOffset(int32_t* aOffsetX,
                                           int32_t* aOffsetY) {
   *aOffsetX = 0;
   *aOffsetY = 0;
 
   nsCOMPtr<Document> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
 
   nsPoint offset = presShell->GetVisualViewportOffset();
   *aOffsetX = nsPresContext::AppUnitsToIntCSSPixels(offset.x);
   *aOffsetY = nsPresContext::AppUnitsToIntCSSPixels(offset.y);
 
   return NS_OK;
 }
@@ -1498,17 +1499,17 @@ nsDOMWindowUtils::GetScrollbarSize(bool 
 
   nsCOMPtr<Document> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   if (aFlushLayout) {
     doc->FlushPendingNotifications(FlushType::Layout);
   }
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
 
   nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();
   NS_ENSURE_TRUE(scrollFrame, NS_OK);
 
   nsMargin sizes = scrollFrame->GetActualScrollbarSizes();
   *aWidth = nsPresContext::AppUnitsToIntCSSPixels(sizes.LeftRight());
   *aHeight = nsPresContext::AppUnitsToIntCSSPixels(sizes.TopBottom());
@@ -1540,17 +1541,17 @@ nsDOMWindowUtils::GetBoundsWithoutFlushi
 
 NS_IMETHODIMP
 nsDOMWindowUtils::NeedsFlush(int32_t aFlushType, bool* aResult) {
   MOZ_ASSERT(aResult);
 
   nsCOMPtr<Document> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   NS_ENSURE_STATE(presShell);
 
   FlushType flushType;
   switch (aFlushType) {
     case FLUSH_STYLE:
       flushType = FlushType::Style;
       break;
 
@@ -1582,17 +1583,17 @@ nsDOMWindowUtils::FlushLayoutWithoutThro
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetRootBounds(DOMRect** aResult) {
   Document* doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   nsRect bounds(0, 0, 0, 0);
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   if (presShell) {
     nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
     if (sf) {
       bounds = sf->GetScrollRange();
       bounds.SetWidth(bounds.Width() + sf->GetScrollPortRect().Width());
       bounds.SetHeight(bounds.Height() + sf->GetScrollPortRect().Height());
     } else if (presShell->GetRootFrame()) {
       bounds = presShell->GetRootFrame()->GetRect();
@@ -1692,23 +1693,24 @@ nsDOMWindowUtils::DispatchDOMEventViaPre
   nsCOMPtr<nsIContent> content = do_QueryInterface(aTarget);
   NS_ENSURE_STATE(content);
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   if (content->OwnerDoc()->GetWindow() != window) {
     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
   }
   nsCOMPtr<Document> targetDoc = content->GetUncomposedDoc();
   NS_ENSURE_STATE(targetDoc);
-  RefPtr<nsIPresShell> targetShell = targetDoc->GetShell();
-  NS_ENSURE_STATE(targetShell);
+  RefPtr<PresShell> targetPresShell = targetDoc->GetPresShell();
+  NS_ENSURE_STATE(targetPresShell);
 
   targetDoc->FlushPendingNotifications(FlushType::Layout);
 
   nsEventStatus status = nsEventStatus_eIgnore;
-  targetShell->HandleEventWithTarget(internalEvent, nullptr, content, &status);
+  targetPresShell->HandleEventWithTarget(internalEvent, nullptr, content,
+                                         &status);
   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 static void InitEvent(WidgetGUIEvent& aEvent,
                       LayoutDeviceIntPoint* aPt = nullptr) {
   if (aPt) {
     aEvent.mRefPoint = *aPt;
@@ -4026,17 +4028,17 @@ nsDOMWindowUtils::GetDirectionFromText(c
       return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::EnsureDirtyRootFrame() {
   Document* doc = GetDocument();
-  nsIPresShell* presShell = doc ? doc->GetShell() : nullptr;
+  PresShell* presShell = doc ? doc->GetPresShell() : nullptr;
 
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
 
   nsIFrame* frame = presShell->GetRootFrame();
   if (!frame) {
     return NS_ERROR_FAILURE;
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -16,17 +16,16 @@
 #include "ContentParent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIFormControl.h"
 #include "nsLayoutUtils.h"
-#include "nsIPresShell.h"
 #include "nsFrameTraversal.h"
 #include "nsIWebNavigation.h"
 #include "nsCaret.h"
 #include "nsIBaseWindow.h"
 #include "nsIXULWindow.h"
 #include "nsViewManager.h"
 #include "nsFrameSelection.h"
 #include "mozilla/dom/Document.h"
@@ -55,16 +54,17 @@
 #include "mozilla/dom/Text.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/Services.h"
 #include "mozilla/Unused.h"
 #include <algorithm>
 
 #ifdef MOZ_XUL
 #  include "nsIDOMXULMenuListElement.h"
 #endif
 
@@ -1477,27 +1477,29 @@ Element* nsFocusManager::CheckIfFocusabl
     return nullptr;
   }
 
   // Make sure that our frames are up to date while ensuring the presshell is
   // also initialized in case we come from a script calling focus() early.
   mEventHandlingNeedsFlush = false;
   doc->FlushPendingNotifications(FlushType::EnsurePresShellInitAndFrames);
 
-  nsIPresShell* shell = doc->GetShell();
-  if (!shell) return nullptr;
+  PresShell* presShell = doc->GetPresShell();
+  if (!presShell) {
+    return nullptr;
+  }
 
   // the root content can always be focused,
   // except in userfocusignored context.
   if (aElement == doc->GetRootElement()) {
     return nsContentUtils::IsUserFocusIgnored(aElement) ? nullptr : aElement;
   }
 
   // cannot focus content in print preview mode. Only the root can be focused.
-  nsPresContext* presContext = shell->GetPresContext();
+  nsPresContext* presContext = presShell->GetPresContext();
   if (presContext &&
       presContext->Type() == nsPresContext::eContext_PrintPreview) {
     LOGCONTENT("Cannot focus %s while in print preview", aElement)
     return nullptr;
   }
 
   nsIFrame* frame = aElement->GetPrimaryFrame();
   if (!frame) {
@@ -2524,17 +2526,17 @@ nsresult nsFocusManager::DetermineElemen
     } else {
       return NS_OK;
     }
   }
 
   Element* rootContent = doc->GetRootElement();
   NS_ENSURE_TRUE(rootContent, NS_OK);
 
-  nsIPresShell* presShell = doc->GetShell();
+  PresShell* presShell = doc->GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_OK);
 
   if (aType == MOVEFOCUS_FIRST) {
     if (!aStartContent) startContent = rootContent;
     return GetNextTabbableContent(presShell, startContent, nullptr,
                                   startContent, true, 1, false, false,
                                   aNextContent);
   }
@@ -2771,17 +2773,17 @@ nsresult nsFocusManager::DetermineElemen
     // parent document and presshell. If there is no enclosing frame element,
     // then this is a top-level, embedded or remote window.
     startContent = piWindow->GetFrameElementInternal();
     if (startContent) {
       doc = startContent->GetComposedDoc();
       NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
       rootContent = doc->GetRootElement();
-      presShell = doc->GetShell();
+      presShell = doc->GetPresShell();
 
       // We can focus the root element now that we have moved to another
       // document.
       mayFocusRoot = true;
 
       nsIFrame* frame = startContent->GetPrimaryFrame();
       if (!frame) {
         return NS_OK;
@@ -3621,21 +3623,22 @@ bool nsFocusManager::TryToMoveFocusToSub
         *aResultContent = GetRootForFocus(subframe, subdoc, false, true);
         if (*aResultContent) {
           NS_ADDREF(*aResultContent);
           return true;
         }
       }
     }
     Element* rootElement = subdoc->GetRootElement();
-    nsIPresShell* subShell = subdoc->GetShell();
-    if (rootElement && subShell) {
+    PresShell* subPresShell = subdoc->GetPresShell();
+    if (rootElement && subPresShell) {
       nsresult rv = GetNextTabbableContent(
-          subShell, rootElement, aOriginalStartContent, rootElement, aForward,
-          (aForward ? 1 : 0), false, aForDocumentNavigation, aResultContent);
+          subPresShell, rootElement, aOriginalStartContent, rootElement,
+          aForward, (aForward ? 1 : 0), false, aForDocumentNavigation,
+          aResultContent);
       NS_ENSURE_SUCCESS(rv, false);
       if (*aResultContent) {
         return true;
       }
     }
   }
   return false;
 }
@@ -3768,17 +3771,17 @@ nsresult nsFocusManager::FocusFirst(Elem
       }
     }
 
     nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
     if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
       // If the found content is in a chrome shell, navigate forward one
       // tabbable item so that the first item is focused. Note that we
       // always go forward and not back here.
-      nsIPresShell* presShell = doc->GetShell();
+      PresShell* presShell = doc->GetPresShell();
       if (presShell) {
         return GetNextTabbableContent(presShell, aRootElement, nullptr,
                                       aRootElement, true, 1, false, false,
                                       aNextContent);
       }
     }
   }
 
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -11,17 +11,16 @@
 
 #include "base/basictypes.h"
 
 #include "prenv.h"
 
 #include "nsDocShell.h"
 #include "nsIDOMMozBrowserFrame.h"
 #include "nsIDOMWindow.h"
-#include "nsIPresShell.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "mozilla/dom/Document.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
@@ -81,16 +80,17 @@
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
 #include "mozilla/dom/MozFrameLoaderOwnerBinding.h"
 #include "mozilla/gfx/CrossProcessPaint.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrame.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ServoCSSParser.h"
 #include "mozilla/ServoStyleSet.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "nsSandboxFlags.h"
@@ -1000,19 +1000,19 @@ nsresult nsFrameLoader::SwapWithOtherRem
 
   Document* ourDoc = ourContent->GetComposedDoc();
   Document* otherDoc = otherContent->GetComposedDoc();
   if (!ourDoc || !otherDoc) {
     // Again, how odd, given that we had docshells
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  nsIPresShell* ourShell = ourDoc->GetShell();
-  nsIPresShell* otherShell = otherDoc->GetShell();
-  if (!ourShell || !otherShell) {
+  PresShell* ourPresShell = ourDoc->GetPresShell();
+  PresShell* otherPresShell = otherDoc->GetPresShell();
+  if (!ourPresShell || !otherPresShell) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // FIXME: Consider supporting FrameLoader swapping for remote sub frames.
   if (mBrowserBridgeChild) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
@@ -1148,18 +1148,18 @@ nsresult nsFrameLoader::SwapWithOtherRem
   // to ourselves to make sure we don't die while we overwrite our reference to
   // ourself.
   RefPtr<nsFrameLoader> kungFuDeathGrip(this);
   aThisOwner->SetFrameLoader(aOther);
   aOtherOwner->SetFrameLoader(kungFuDeathGrip);
 
   ourFrameFrame->EndSwapDocShells(otherFrame);
 
-  ourShell->BackingScaleFactorChanged();
-  otherShell->BackingScaleFactorChanged();
+  ourPresShell->BackingScaleFactorChanged();
+  otherPresShell->BackingScaleFactorChanged();
 
   // Initialize browser API if needed now that owner content has changed.
   InitializeBrowserAPI();
   aOther->InitializeBrowserAPI();
 
   mInSwap = aOther->mInSwap = false;
 
   // Send an updated tab context since owner content type may have changed.
@@ -1412,19 +1412,19 @@ nsresult nsFrameLoader::SwapWithOtherLoa
   if (!ourDoc || !otherDoc) {
     // Again, how odd, given that we had docshells
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   NS_ASSERTION(ourDoc == ourParentDocument, "Unexpected parent document");
   NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document");
 
-  nsIPresShell* ourShell = ourDoc->GetShell();
-  nsIPresShell* otherShell = otherDoc->GetShell();
-  if (!ourShell || !otherShell) {
+  PresShell* ourPresShell = ourDoc->GetPresShell();
+  PresShell* otherPresShell = otherDoc->GetPresShell();
+  if (!ourPresShell || !otherPresShell) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   if (ourDocshell->GetIsIsolatedMozBrowserElement() !=
       otherDocshell->GetIsIsolatedMozBrowserElement()) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
@@ -1571,18 +1571,18 @@ nsresult nsFrameLoader::SwapWithOtherLoa
 
   ourFrameFrame->EndSwapDocShells(otherFrame);
 
   // If the content being swapped came from windows on two screens with
   // incompatible backing resolution (e.g. dragging a tab between windows on
   // hi-dpi and low-dpi screens), it will have style data that is based on
   // the wrong appUnitsPerDevPixel value. So we tell the PresShells that their
   // backing scale factor may have changed. (Bug 822266)
-  ourShell->BackingScaleFactorChanged();
-  otherShell->BackingScaleFactorChanged();
+  ourPresShell->BackingScaleFactorChanged();
+  otherPresShell->BackingScaleFactorChanged();
 
   // Initialize browser API if needed now that owner content has changed
   InitializeBrowserAPI();
   aOther->InitializeBrowserAPI();
 
   return NS_OK;
 }
 
@@ -3092,17 +3092,17 @@ already_AddRefed<mozilla::dom::Promise> 
     return nullptr;
   }
 
   RefPtr<Document> document = GetOwnerContent()->GetOwnerDocument();
   if (NS_WARN_IF(!document)) {
     aRv = NS_ERROR_FAILURE;
     return nullptr;
   }
-  nsIPresShell* presShell = document->GetShell();
+  PresShell* presShell = document->GetPresShell();
   if (NS_WARN_IF(!presShell)) {
     aRv = NS_ERROR_FAILURE;
     return nullptr;
   }
 
   nscolor color;
   css::Loader* loader = document->CSSLoader();
   ServoStyleSet* set = presShell->StyleSet();
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -13,16 +13,17 @@
 // Local Includes
 #include "Navigator.h"
 #include "nsContentSecurityManager.h"
 #include "nsScreen.h"
 #include "nsHistory.h"
 #include "nsDOMNavigationTiming.h"
 #include "nsIDOMStorageManager.h"
 #include "mozilla/dom/ContentFrameMessageManager.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/DOMJSProxyHandler.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/LocalStorage.h"
 #include "mozilla/dom/LocalStorageCommon.h"
 #include "mozilla/dom/LSObject.h"
 #include "mozilla/dom/PartitionedLocalStorage.h"
 #include "mozilla/dom/Storage.h"
@@ -90,16 +91,17 @@
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Debug.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "mozilla/ScrollTypes.h"
 #include "mozilla/ThrottledEventQueue.h"
 #include "AudioChannelService.h"
 #include "nsAboutProtocolUtils.h"
 #include "nsCharTraits.h"  // NS_IS_HIGH/LOW_SURROGATE
 #include "PostMessageEvent.h"
 #include "mozilla/dom/DocGroup.h"
@@ -117,17 +119,16 @@
 #include "nsIContent.h"
 #include "nsIDocShell.h"
 #include "mozilla/dom/Document.h"
 #include "Crypto.h"
 #include "nsDOMString.h"
 #include "nsIEmbeddingSiteWindow.h"
 #include "nsThreadUtils.h"
 #include "nsILoadContext.h"
-#include "nsIPresShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsISelectionController.h"
 #include "nsIPrompt.h"
 #include "nsIPromptService.h"
 #include "nsIPromptFactory.h"
 #include "nsIAddonPolicyService.h"
@@ -1130,34 +1131,34 @@ void nsGlobalWindowInner::FreeInnerObjec
     mDocumentURI = mDoc->GetDocumentURI();
     mDocBaseURI = mDoc->GetDocBaseURI();
 
     while (mDoc->EventHandlingSuppressed()) {
       mDoc->UnsuppressEventHandlingAndFireEvents(false);
     }
 
     if (mObservingDidRefresh) {
-      nsIPresShell* shell = mDoc->GetShell();
-      if (shell) {
-        Unused << shell->RemovePostRefreshObserver(this);
+      PresShell* presShell = mDoc->GetPresShell();
+      if (presShell) {
+        Unused << presShell->RemovePostRefreshObserver(this);
       }
     }
   }
 
   // Remove our reference to the document and the document principal.
   mFocusedElement = nullptr;
 
   if (mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())
         ->Disconnect();
     mApplicationCache = nullptr;
   }
 
   if (mIndexedDB) {
-    mIndexedDB->DisconnectFromWindow(this);
+    mIndexedDB->DisconnectFromGlobal(this);
     mIndexedDB = nullptr;
   }
 
   UnlinkHostObjectURIs();
 
   NotifyWindowIDDestroyed("inner-window-destroyed");
 
   CleanupCachedXBLHandlers();
@@ -1443,17 +1444,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
   if (tmp->mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())
         ->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
   }
   if (tmp->mIndexedDB) {
-    tmp->mIndexedDB->DisconnectFromWindow(tmp);
+    tmp->mIndexedDB->DisconnectFromGlobal(tmp);
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
 
@@ -6252,18 +6253,18 @@ already_AddRefed<Promise> nsGlobalWindow
     return nullptr;
   }
 
   if (!mDoc) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsIPresShell* shell = mDoc->GetShell();
-  if (!shell) {
+  PresShell* presShell = mDoc->GetPresShell();
+  if (!presShell) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   // We need to associate the lifetime of the Promise to the lifetime
   // of the caller's global. That way, if the window we're observing
   // refresh driver ticks on goes away before our observer is fired,
   // we can still resolve the Promise.
@@ -6276,23 +6277,23 @@ already_AddRefed<Promise> nsGlobalWindow
   RefPtr<Promise> resultPromise = Promise::Create(global, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
       new PromiseDocumentFlushedResolver(resultPromise, aCallback));
 
-  if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
+  if (!presShell->NeedStyleFlush() && !presShell->NeedLayoutFlush()) {
     flushResolver->Call();
     return resultPromise.forget();
   }
 
   if (!mObservingDidRefresh) {
-    bool success = shell->AddPostRefreshObserver(this);
+    bool success = presShell->AddPostRefreshObserver(this);
     if (!success) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
     mObservingDidRefresh = true;
   }
 
   mDocumentFlushedResolvers.AppendElement(std::move(flushResolver));
@@ -6329,19 +6330,19 @@ void nsGlobalWindowInner::CallOrCancelDo
     if (!mDocumentFlushedResolvers.Length()) {
       break;
     }
 
     // If there are new items, the observer is not added for them when calling
     // PromiseDocumentFlushed.  Add here and leave.
     // FIXME: Handle this case inside PromiseDocumentFlushed (bug 1442824).
     if (mDoc) {
-      nsIPresShell* shell = mDoc->GetShell();
-      if (shell) {
-        (void)shell->AddPostRefreshObserver(this);
+      PresShell* presShell = mDoc->GetPresShell();
+      if (presShell) {
+        Unused << presShell->AddPostRefreshObserver(this);
         break;
       }
     }
 
     // If we fail adding observer, keep looping to resolve or reject all
     // promises.  This case happens while destroying window.
     // This violates the constraint that the promiseDocumentFlushed callback
     // only ever run when no flush needed, but it's necessary to resolve
@@ -6360,29 +6361,29 @@ void nsGlobalWindowInner::CancelDocument
 void nsGlobalWindowInner::DidRefresh() {
   auto rejectionGuard = MakeScopeExit([&] {
     CancelDocumentFlushedResolvers();
     mObservingDidRefresh = false;
   });
 
   MOZ_ASSERT(mDoc);
 
-  nsIPresShell* shell = mDoc->GetShell();
-  MOZ_ASSERT(shell);
-
-  if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
+  PresShell* presShell = mDoc->GetPresShell();
+  MOZ_ASSERT(presShell);
+
+  if (presShell->NeedStyleFlush() || presShell->NeedLayoutFlush()) {
     // By the time our observer fired, something has already invalidated
     // style or layout - or perhaps we're still in the middle of a flush that
     // was interrupted. In either case, we'll wait until the next refresh driver
     // tick instead and try again.
     rejectionGuard.release();
     return;
   }
 
-  bool success = shell->RemovePostRefreshObserver(this);
+  bool success = presShell->RemovePostRefreshObserver(this);
   if (!success) {
     return;
   }
 
   rejectionGuard.release();
 
   CallDocumentFlushedResolvers();
   mObservingDidRefresh = false;
@@ -6791,25 +6792,38 @@ Worklet* nsGlobalWindowInner::GetPaintWo
     mPaintWorklet = PaintWorkletImpl::CreateWorklet(this, principal);
   }
 
   return mPaintWorklet;
 }
 
 void nsGlobalWindowInner::GetRegionalPrefsLocales(
     nsTArray<nsString>& aLocales) {
+  MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance());
+
   AutoTArray<nsCString, 10> rpLocales;
   mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(
       rpLocales);
 
   for (const auto& loc : rpLocales) {
     aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
   }
 }
 
+void nsGlobalWindowInner::GetWebExposedLocales(nsTArray<nsString>& aLocales) {
+  MOZ_ASSERT(mozilla::intl::LocaleService::GetInstance());
+
+  AutoTArray<nsCString, 10> rpLocales;
+  mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(rpLocales);
+
+  for (const auto& loc : rpLocales) {
+    aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
+  }
+}
+
 IntlUtils* nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError) {
   if (!mIntlUtils) {
     mIntlUtils = new IntlUtils(this);
   }
 
   return mIntlUtils;
 }
 
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -628,16 +628,18 @@ class nsGlobalWindowInner final : public
                   mozilla::ErrorResult& aRv);
   already_AddRefed<mozilla::dom::External> GetExternal(
       mozilla::ErrorResult& aRv);
 
   mozilla::dom::Worklet* GetPaintWorklet(mozilla::ErrorResult& aRv);
 
   void GetRegionalPrefsLocales(nsTArray<nsString>& aLocales);
 
+  void GetWebExposedLocales(nsTArray<nsString>& aLocales);
+
   mozilla::dom::IntlUtils* GetIntlUtils(mozilla::ErrorResult& aRv);
 
   void StoreSharedWorker(mozilla::dom::SharedWorker* aSharedWorker);
 
   void ForgetSharedWorker(mozilla::dom::SharedWorker* aSharedWorker);
 
  public:
   void Alert(nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
--- a/dom/base/nsHistory.cpp
+++ b/dom/base/nsHistory.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHistory.h"
 
 #include "jsapi.h"
 #include "nsCOMPtr.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIDocShell.h"
 #include "nsIWebNavigation.h"
 #include "nsIURI.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsReadableUtils.h"
 #include "nsContentUtils.h"
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -51,16 +51,17 @@
 #include "js/Wrapper.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MainThreadIdlePeriod.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -84,17 +85,16 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/CycleCollectedJSContext.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "GeckoProfiler.h"
 #include "mozilla/IdleTaskRunner.h"
 #include "nsIDocShell.h"
-#include "nsIPresShell.h"
 #include "nsViewManager.h"
 #include "mozilla/EventStateManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 const size_t gStackSize = 8192;
 
@@ -1938,17 +1938,17 @@ void nsJSContext::MaybeRunNextCollectorS
 
   Document* rootDocument = root->GetDocument();
   if (!rootDocument ||
       rootDocument->GetReadyStateEnum() != Document::READYSTATE_COMPLETE ||
       rootDocument->IsInBackgroundWindow()) {
     return;
   }
 
-  nsIPresShell* presShell = rootDocument->GetShell();
+  PresShell* presShell = rootDocument->GetPresShell();
   if (!presShell) {
     return;
   }
 
   nsViewManager* vm = presShell->GetViewManager();
   if (!vm) {
     return;
   }
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -6,16 +6,17 @@
 
 #include "nsNodeUtils.h"
 #include "nsContentUtils.h"
 #include "nsCSSPseudoElements.h"
 #include "nsINode.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/Element.h"
 #include "nsIMutationObserver.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsIXPConnect.h"
 #include "PLDHashTable.h"
 #include "nsCOMArray.h"
 #include "nsPIDOMWindow.h"
 #ifdef MOZ_XUL
@@ -25,16 +26,17 @@
 #include "nsGenericHTMLElement.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/KeyframeEffect.h"
+#include "mozilla/PresShell.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsObjectLoadingContent.h"
 #include "nsDOMMutationObserver.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 
@@ -61,18 +63,18 @@ enum class IsRemoveNotification {
   bool needsEnterLeave = doc->MayHaveDOMMutationObservers();                  \
   if (needsEnterLeave) {                                                      \
     nsDOMMutationObserver::EnterMutationHandling();                           \
   }                                                                           \
   nsINode* node = content_;                                                   \
   COMPOSED_DOC_DECL                                                           \
   NS_ASSERTION(node->OwnerDoc() == doc, "Bogus document");                    \
   if (remove_ == IsRemoveNotification::Yes && node->GetComposedDoc()) {       \
-    if (nsIPresShell* shell = doc->GetObservingShell()) {                     \
-      shell->func_ params_;                                                   \
+    if (PresShell* presShell = doc->GetObservingPresShell()) {                \
+      presShell->func_ params_;                                               \
     }                                                                         \
   }                                                                           \
   doc->BindingManager()->func_ params_;                                       \
   nsINode* last;                                                              \
   do {                                                                        \
     nsINode::nsSlots* slots = node->GetExistingSlots();                       \
     if (slots && !slots->mMutationObservers.IsEmpty()) {                      \
       NS_OBSERVER_AUTO_ARRAY_NOTIFY_OBSERVERS(                                \
@@ -87,18 +89,18 @@ enum class IsRemoveNotification {
   } while (node);                                                             \
   /* Whitelist NativeAnonymousChildListChange removal notifications from      \
    * the assertion since it runs from UnbindFromTree, and thus we don't       \
    * reach the document, but doesn't matter. */                               \
   MOZ_ASSERT((last == doc) == wasInComposedDoc ||                             \
              (remove_ == IsRemoveNotification::Yes &&                         \
               !strcmp(#func_, "NativeAnonymousChildListChange")));            \
   if (remove_ == IsRemoveNotification::No && last == doc) {                   \
-    if (nsIPresShell* shell = doc->GetObservingShell()) {                     \
-      shell->func_ params_;                                                   \
+    if (PresShell* presShell = doc->GetObservingPresShell()) {                \
+      presShell->func_ params_;                                               \
     }                                                                         \
   }                                                                           \
   if (needsEnterLeave) {                                                      \
     nsDOMMutationObserver::LeaveMutationHandling();                           \
   }                                                                           \
   PR_END_MACRO
 
 #define IMPL_ANIMATION_NOTIFICATION(func_, content_, params_) \
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -21,17 +21,16 @@
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObjectFrame.h"
 #include "nsIOService.h"
 #include "nsIPermissionManager.h"
 #include "nsPluginHost.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsJSNPRuntime.h"
 #include "nsINestedURI.h"
-#include "nsIPresShell.h"
 #include "nsScriptSecurityManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIStreamConverterService.h"
 #include "nsIURILoader.h"
 #include "nsIURL.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebNavigationInfo.h"
 #include "nsIScriptChannel.h"
@@ -87,16 +86,17 @@
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/widget/IMEData.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/LoadInfo.h"
+#include "mozilla/PresShell.h"
 #include "nsChannelClassifier.h"
 #include "nsFocusManager.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #  ifdef CreateEvent
 #    undef CreateEvent
 #  endif
@@ -2480,19 +2480,19 @@ void nsObjectLoadingContent::NotifyState
       thisEl->NotifyUAWidgetTeardown();
     } else if (!hadProblemState && hasProblemState) {
       thisEl->AttachAndSetUAShadowRoot();
       thisEl->NotifyUAWidgetSetupOrChange();
     }
   } else if (aOldType != mType) {
     // If our state changed, then we already recreated frames
     // Otherwise, need to do that here
-    nsCOMPtr<nsIPresShell> shell = doc->GetShell();
-    if (shell) {
-      shell->PostRecreateFramesFor(thisEl);
+    RefPtr<PresShell> presShell = doc->GetPresShell();
+    if (presShell) {
+      presShell->PostRecreateFramesFor(thisEl);
     }
   }
 
   if (aSync) {
     MOZ_ASSERT(InActiveDocument(thisEl), "Something is confused");
     // Make sure that frames are actually constructed immediately.
     doc->FlushPendingNotifications(FlushType::Frames);
   }
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -25,16 +25,17 @@
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/RangeBinding.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Text.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Likely.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsStyleStruct.h"
 #include "nsStyleStructInlines.h"
 #include "nsComputedDOMStyle.h"
 #include "mozilla/dom/InspectorFontFace.h"
@@ -63,18 +64,18 @@ static void InvalidateAllFrames(nsINode*
     case nsINode::TEXT_NODE:
     case nsINode::ELEMENT_NODE: {
       nsIContent* content = static_cast<nsIContent*>(aNode);
       frame = content->GetPrimaryFrame();
       break;
     }
     case nsINode::DOCUMENT_NODE: {
       Document* doc = static_cast<Document*>(aNode);
-      nsIPresShell* shell = doc ? doc->GetShell() : nullptr;
-      frame = shell ? shell->GetRootFrame() : nullptr;
+      PresShell* presShell = doc ? doc->GetPresShell() : nullptr;
+      frame = presShell ? presShell->GetRootFrame() : nullptr;
       break;
     }
   }
   for (nsIFrame* f = frame; f; f = f->GetNextContinuation()) {
     f->InvalidateFrameSubtree();
   }
 }
 
@@ -2723,18 +2724,18 @@ static void ExtractRectFromOffset(nsIFra
       aR->SetWidth(aR->XMost() - point.x);
       aR->x = point.x;
     }
   }
 }
 
 static nsTextFrame* GetTextFrameForContent(nsIContent* aContent,
                                            bool aFlushLayout) {
-  Document* doc = aContent->OwnerDoc();
-  nsIPresShell* presShell = doc->GetShell();
+  RefPtr<Document> doc = aContent->OwnerDoc();
+  PresShell* presShell = doc->GetPresShell();
   if (!presShell) {
     return nullptr;
   }
 
   // Try to un-suppress whitespace if needed, but only if we'll be able to flush
   // to immediately see the results of the un-suppression. If we can't flush
   // here, then calling EnsureFrameForTextNodeIsCreatedAfterFlush would be
   // pointless anyway.
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -193,47 +193,54 @@ class TeardownRunnableOnWorker final : p
   bool PreRun(WorkerPrivate* aWorkerPrivate) override { return true; }
 
   void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                bool aRunResult) override {}
 };
 
 }  // namespace
 
-BroadcastChannel::BroadcastChannel(nsPIDOMWindowInner* aWindow,
+BroadcastChannel::BroadcastChannel(nsIGlobalObject* aGlobal,
                                    const nsAString& aChannel)
-    : DOMEventTargetHelper(aWindow), mChannel(aChannel), mState(StateActive) {
-  // Window can be null in workers
-
+    : DOMEventTargetHelper(aGlobal), mChannel(aChannel), mState(StateActive) {
+  MOZ_ASSERT(aGlobal);
   KeepAliveIfHasListenersFor(NS_LITERAL_STRING("message"));
 }
 
 BroadcastChannel::~BroadcastChannel() {
   Shutdown();
   MOZ_ASSERT(!mWorkerRef);
 }
 
 JSObject* BroadcastChannel::WrapObject(JSContext* aCx,
                                        JS::Handle<JSObject*> aGivenProto) {
   return BroadcastChannel_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */
 already_AddRefed<BroadcastChannel> BroadcastChannel::Constructor(
     const GlobalObject& aGlobal, const nsAString& aChannel, ErrorResult& aRv) {
-  nsCOMPtr<nsPIDOMWindowInner> window =
-      do_QueryInterface(aGlobal.GetAsSupports());
-  // Window is null in workers.
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+  if (NS_WARN_IF(!global)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
-  RefPtr<BroadcastChannel> bc = new BroadcastChannel(window, aChannel);
+  RefPtr<BroadcastChannel> bc = new BroadcastChannel(global, aChannel);
 
   nsAutoCString origin;
   PrincipalInfo principalInfo;
 
   if (NS_IsMainThread()) {
+    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
+    if (NS_WARN_IF(!window)) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+
     nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();
 
     if (!incumbent) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     nsIPrincipal* principal = incumbent->PrincipalOrNull();
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -8,17 +8,17 @@
 #define mozilla_dom_BroadcastChannel_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "mozilla/RefPtr.h"
 
-class nsPIDOMWindowInner;
+class nsIGlobalObject;
 
 namespace mozilla {
 
 namespace ipc {
 class PrincipalInfo;
 }  // namespace ipc
 
 namespace dom {
@@ -52,17 +52,17 @@ class BroadcastChannel final : public DO
   void Close();
 
   IMPL_EVENT_HANDLER(message)
   IMPL_EVENT_HANDLER(messageerror)
 
   void Shutdown();
 
  private:
-  BroadcastChannel(nsPIDOMWindowInner* aWindow, const nsAString& aChannel);
+  BroadcastChannel(nsIGlobalObject* aGlobal, const nsAString& aChannel);
 
   ~BroadcastChannel();
 
   void RemoveDocFromBFCache();
 
   void DisconnectFromOwner() override;
 
   RefPtr<BroadcastChannelChild> mActor;
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -11,16 +11,17 @@
 // That messes up our call to EventDispatcher::CreateEvent below.
 
 #ifdef CreateEvent
 #  undef CreateEvent
 #endif
 
 #include "BrowserElementParent.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/WindowProxyHolder.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsVariant.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/CustomEvent.h"
 
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -15,16 +15,17 @@
 #include "gfxTextRun.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BasicRenderingContext2D.h"
 #include "mozilla/dom/CanvasGradient.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasPattern.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/UniquePtr.h"
 #include "gfx2DGlue.h"
 #include "imgIEncoder.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/EnumeratedArray.h"
 #include "FilterSupport.h"
 #include "SVGObserverUtils.h"
 #include "Layers.h"
@@ -387,17 +388,17 @@ class CanvasRenderingContext2D final : p
   virtual int32_t GetHeight() override { return GetSize().height; }
 
   // nsICanvasRenderingContextInternal
   /**
    * Gets the pres shell from either the canvas element or the doc shell
    */
   nsIPresShell* GetPresShell() final {
     if (mCanvasElement) {
-      return mCanvasElement->OwnerDoc()->GetShell();
+      return mCanvasElement->OwnerDoc()->GetPresShell();
     }
     if (mDocShell) {
       return mDocShell->GetPresShell();
     }
     return nullptr;
   }
   NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override;
   NS_IMETHOD InitializeWithDrawTarget(
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -8,16 +8,17 @@
 
 #include "mozilla/gfx/2D.h"
 #include "nsISupports.h"
 #include "nsIInputStream.h"
 #include "nsIDocShell.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/OffscreenCanvas.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/NotNull.h"
 
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID       \
   {                                                  \
     0xb84f2fed, 0x9d4b, 0x430b, {                    \
       0xbd, 0xfb, 0x85, 0x57, 0x8a, 0xc2, 0xb4, 0x4b \
@@ -53,17 +54,17 @@ class nsICanvasRenderingContextInternal 
   void SetCanvasElement(mozilla::dom::HTMLCanvasElement* parentCanvas) {
     RemovePostRefreshObserver();
     mCanvasElement = parentCanvas;
     AddPostRefreshObserverIfNecessary();
   }
 
   virtual nsIPresShell* GetPresShell() {
     if (mCanvasElement) {
-      return mCanvasElement->OwnerDoc()->GetShell();
+      return mCanvasElement->OwnerDoc()->GetPresShell();
     }
     return nullptr;
   }
 
   void RemovePostRefreshObserver() {
     if (mRefreshDriver) {
       mRefreshDriver->RemovePostRefreshObserver(this);
       mRefreshDriver = nullptr;
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -3,30 +3,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContentEventHandler.h"
 
 #include "mozilla/ContentIterator.h"
 #include "mozilla/IMEStateManager.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLUnknownElement.h"
 #include "mozilla/dom/Selection.h"
 #include "nsCaret.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsCopySupport.h"
 #include "nsElementTable.h"
 #include "nsFocusManager.h"
 #include "nsFontMetrics.h"
 #include "nsFrameSelection.h"
-#include "nsIPresShell.h"
 #include "nsIFrame.h"
 #include "nsIObjectFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsQueryObject.h"
 #include "nsRange.h"
 #include "nsTextFragment.h"
 #include "nsTextFrame.h"
@@ -282,17 +282,17 @@ nsresult ContentEventHandler::InitRootCo
   // See bug 537041 comment 5, the range could have removed node.
   if (NS_WARN_IF(startNode->GetComposedDoc() != mDocument)) {
     return NS_ERROR_FAILURE;
   }
 
   NS_ASSERTION(startNode->GetComposedDoc() == endNode->GetComposedDoc(),
                "firstNormalSelectionRange crosses the document boundary");
 
-  mRootContent = startNode->GetSelectionRootContent(mDocument->GetShell());
+  mRootContent = startNode->GetSelectionRootContent(mDocument->GetPresShell());
   if (NS_WARN_IF(!mRootContent)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult ContentEventHandler::InitCommon(SelectionType aSelectionType,
@@ -304,18 +304,18 @@ nsresult ContentEventHandler::InitCommon
   mSelection = nullptr;
   mRootContent = nullptr;
   mFirstSelectedRawRange.Clear();
 
   nsresult rv = InitBasic(aRequireFlush);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISelectionController> selectionController;
-  if (nsIPresShell* shell = mDocument->GetShell()) {
-    selectionController = shell->GetSelectionControllerForFocusedContent();
+  if (PresShell* presShell = mDocument->GetPresShell()) {
+    selectionController = presShell->GetSelectionControllerForFocusedContent();
   }
   if (NS_WARN_IF(!selectionController)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   mSelection =
       selectionController->GetSelection(ToRawSelectionType(aSelectionType));
   if (NS_WARN_IF(!mSelection)) {
@@ -960,18 +960,18 @@ nsresult ContentEventHandler::ExpandToCl
   // boundaries. It's false, but no problem now, maybe.
   if (!aContent->IsText() || *aXPOffset == 0 ||
       *aXPOffset == aContent->TextLength()) {
     return NS_OK;
   }
 
   NS_ASSERTION(*aXPOffset <= aContent->TextLength(), "offset is out of range.");
 
-  MOZ_DIAGNOSTIC_ASSERT(mDocument->GetShell());
-  RefPtr<nsFrameSelection> fs = mDocument->GetShell()->FrameSelection();
+  MOZ_DIAGNOSTIC_ASSERT(mDocument->GetPresShell());
+  RefPtr<nsFrameSelection> fs = mDocument->GetPresShell()->FrameSelection();
   int32_t offsetInFrame;
   CaretAssociationHint hint =
       aForward ? CARET_ASSOCIATE_BEFORE : CARET_ASSOCIATE_AFTER;
   nsIFrame* frame = fs->GetFrameForNodeOffset(aContent, int32_t(*aXPOffset),
                                               hint, &offsetInFrame);
   if (frame) {
     int32_t startOffset, endOffset;
     nsresult rv = frame->GetOffsets(startOffset, endOffset);
@@ -2506,19 +2506,19 @@ nsresult ContentEventHandler::OnQueryCha
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   aEvent->mReply.mOffset = aEvent->mReply.mTentativeCaretOffset =
       WidgetQueryContentEvent::NOT_FOUND;
 
-  nsIPresShell* shell = mDocument->GetShell();
-  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
-  nsIFrame* rootFrame = shell->GetRootFrame();
+  PresShell* presShell = mDocument->GetPresShell();
+  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+  nsIFrame* rootFrame = presShell->GetRootFrame();
   NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
   nsIWidget* rootWidget = rootFrame->GetNearestWidget();
   NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
 
   // The root frame's widget might be different, e.g., the event was fired on
   // a popup but the rootFrame is the document root.
   if (rootWidget != aEvent->mWidget) {
     MOZ_ASSERT(aEvent->mWidget, "The event must have the widget");
@@ -2618,19 +2618,19 @@ nsresult ContentEventHandler::OnQueryDOM
     return rv;
   }
 
   aEvent->mSucceeded = false;
   aEvent->mReply.mWidgetIsHit = false;
 
   NS_ENSURE_TRUE(aEvent->mWidget, NS_ERROR_FAILURE);
 
-  nsIPresShell* shell = mDocument->GetShell();
-  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
-  nsIFrame* docFrame = shell->GetRootFrame();
+  PresShell* presShell = mDocument->GetPresShell();
+  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+  nsIFrame* docFrame = presShell->GetRootFrame();
   NS_ENSURE_TRUE(docFrame, NS_ERROR_FAILURE);
 
   LayoutDeviceIntPoint eventLoc =
       aEvent->mRefPoint + aEvent->mWidget->WidgetToScreenOffset();
   CSSIntRect docFrameRect = docFrame->GetScreenRect();
   CSSIntPoint eventLocCSS(
       docFrame->PresContext()->DevPixelsToIntCSSPixels(eventLoc.x) -
           docFrameRect.x,
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -2,39 +2,40 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AccessCheck.h"
 #include "base/basictypes.h"
 #include "ipc/IPCMessageUtils.h"
-#include "mozilla/dom/Event.h"
-#include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/ShadowRoot.h"
 #include "nsContentUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDeviceContext.h"
 #include "nsError.h"
 #include "nsGlobalWindow.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
-#include "mozilla/dom/Document.h"
 #include "nsIPresShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsJSEnvironment.h"
 #include "nsLayoutUtils.h"
 #include "nsPIWindowRoot.h"
 #include "nsRFPService.h"
 
 namespace mozilla {
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/HalSensor.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/LoadedScript.h"
 #include "mozilla/dom/PopupBlocker.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -440,19 +441,19 @@ void EventListenerManager::ProcessApzAwa
     if (nsCOMPtr<DOMEventTargetHelper> helper = do_QueryInterface(mTarget)) {
       if (nsPIDOMWindowInner* window = helper->GetOwner()) {
         doc = window->GetExtantDoc();
       }
     }
   }
 
   if (doc && gfxPlatform::AsyncPanZoomEnabled()) {
-    nsIPresShell* ps = doc->GetShell();
-    if (ps) {
-      nsIFrame* f = ps->GetRootFrame();
+    PresShell* presShell = doc->GetPresShell();
+    if (presShell) {
+      nsIFrame* f = presShell->GetRootFrame();
       if (f) {
         f->SchedulePaint();
       }
     }
   }
 }
 
 bool EventListenerManager::IsDeviceType(EventMessage aEventMessage) {
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -850,19 +850,19 @@ void EventStateManager::NotifyTargetUser
   MOZ_ASSERT(aEvent->mMessage == eKeyDown || aEvent->mMessage == eMouseDown ||
              aEvent->mMessage == ePointerDown || aEvent->mMessage == eTouchEnd);
   doc->NotifyUserGestureActivation();
 }
 
 already_AddRefed<EventStateManager> EventStateManager::ESMFromContentOrThis(
     nsIContent* aContent) {
   if (aContent) {
-    nsIPresShell* shell = aContent->OwnerDoc()->GetShell();
-    if (shell) {
-      nsPresContext* prescontext = shell->GetPresContext();
+    PresShell* presShell = aContent->OwnerDoc()->GetPresShell();
+    if (presShell) {
+      nsPresContext* prescontext = presShell->GetPresContext();
       if (prescontext) {
         RefPtr<EventStateManager> esm = prescontext->EventStateManager();
         if (esm) {
           return esm.forget();
         }
       }
     }
   }
@@ -4297,19 +4297,19 @@ void EventStateManager::NotifyMouseOver(
 
   // Check to see if we're a subdocument and if so update the parent
   // document's ESM state to indicate that the mouse is over the
   // content associated with our subdocument.
   EnsureDocument(mPresContext);
   if (Document* parentDoc = mDocument->GetParentDocument()) {
     if (nsCOMPtr<nsIContent> docContent =
             parentDoc->FindContentForSubDocument(mDocument)) {
-      if (nsIPresShell* parentShell = parentDoc->GetShell()) {
+      if (PresShell* parentPresShell = parentDoc->GetPresShell()) {
         RefPtr<EventStateManager> parentESM =
-            parentShell->GetPresContext()->EventStateManager();
+            parentPresShell->GetPresContext()->EventStateManager();
         parentESM->NotifyMouseOver(aMouseEvent, docContent);
       }
     }
   }
   // Firing the DOM event in the parent document could cause all kinds
   // of havoc.  Reverify and take care.
   if (wrapper->mLastOverElement == aContent) return;
 
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/IMEStateManager.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EditorBase.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/MouseEventBinding.h"
 #include "mozilla/dom/TabParent.h"
 
 #include "HTMLInputElement.h"
@@ -27,17 +28,16 @@
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Document.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsINode.h"
 #include "nsIObserverService.h"
-#include "nsIPresShell.h"
 #include "nsISupports.h"
 #include "nsPresContext.h"
 
 namespace mozilla {
 
 using namespace dom;
 using namespace widget;
 
@@ -917,21 +917,21 @@ void IMEStateManager::UpdateIMEState(con
 
   if (sIsGettingNewIMEState) {
     MOZ_LOG(sISMLog, LogLevel::Debug,
             ("  UpdateIMEState(), "
              "does nothing because of called while getting new IME state"));
     return;
   }
 
-  nsCOMPtr<nsIPresShell> presShell;
+  RefPtr<PresShell> presShell;
   if (!aEditorBase) {
     MOZ_ASSERT(aContent, "we must have content");
     Document* doc = aContent->OwnerDoc();
-    presShell = doc->GetShell();
+    presShell = doc->GetPresShell();
   } else {
     presShell = aEditorBase->GetPresShell();
   }
 
   if (NS_WARN_IF(!presShell)) {
     MOZ_LOG(sISMLog, LogLevel::Error,
             ("  UpdateIMEState(), FAILED due to "
              "editor doesn't have PresShell"));
--- a/dom/events/PointerEventHandler.cpp
+++ b/dom/events/PointerEventHandler.cpp
@@ -622,18 +622,18 @@ bool PointerEventHandler::GetPointerPrim
   return false;
 }
 
 /* static */
 void PointerEventHandler::DispatchGotOrLostPointerCaptureEvent(
     bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent,
     nsIContent* aCaptureTarget) {
   Document* targetDoc = aCaptureTarget->OwnerDoc();
-  nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
-  if (NS_WARN_IF(!shell)) {
+  RefPtr<PresShell> presShell = targetDoc->GetPresShell();
+  if (NS_WARN_IF(!presShell)) {
     return;
   }
 
   if (!aIsGotCapture && !aCaptureTarget->IsInComposedDoc()) {
     // If the capturing element was removed from the DOM tree, fire
     // ePointerLostCapture at the document.
     PointerEventInit init;
     init.mPointerId = aPointerEvent->pointerId;
@@ -649,17 +649,17 @@ void PointerEventHandler::DispatchGotOrL
   }
   nsEventStatus status = nsEventStatus_eIgnore;
   WidgetPointerEvent localEvent(
       aPointerEvent->IsTrusted(),
       aIsGotCapture ? ePointerGotCapture : ePointerLostCapture,
       aPointerEvent->mWidget);
 
   localEvent.AssignPointerEventData(*aPointerEvent, true);
-  DebugOnly<nsresult> rv = shell->HandleEventWithTarget(
+  DebugOnly<nsresult> rv = presShell->HandleEventWithTarget(
       &localEvent, aCaptureTarget->GetPrimaryFrame(), aCaptureTarget, &status);
 
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "DispatchGotOrLostPointerCaptureEvent failed");
 }
 
 /* static */
 void PointerEventHandler::MaybeCacheSpoofedPointerID(uint16_t aInputSource,
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -1043,17 +1043,17 @@ FetchDriver::OnStartRequest(nsIRequest* 
 
   // Resolves fetch() promise which may trigger code running in a worker.  Make
   // sure the Response is fully initialized before calling this.
   mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect);
   if (NS_WARN_IF(!mResponse)) {
     // Fail to generate a paddingInfo for opaque response.
     MOZ_DIAGNOSTIC_ASSERT(mResponse->Type() == ResponseType::Opaque);
     FailWithNetworkError(NS_ERROR_UNEXPECTED);
-    return rv;
+    return NS_ERROR_UNEXPECTED;
   }
 
   // From "Main Fetch" step 19: SRI-part1.
   if (ShouldCheckSRI(mRequest, mResponse) && mSRIMetadata.IsEmpty()) {
     nsIConsoleReportCollector* reporter = nullptr;
     if (mObserver) {
       reporter = mObserver->GetReporter();
     }
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/InternalResponse.cpp
@@ -6,16 +6,17 @@
 
 #include "InternalResponse.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/cache/CacheTypes.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
+#include "mozilla/RandomNum.h"
 #include "nsIRandomGenerator.h"
 #include "nsIURI.h"
 #include "nsStreamUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
@@ -117,24 +118,34 @@ nsresult InternalResponse::GeneratePaddi
   MOZ_DIAGNOSTIC_ASSERT(mPaddingSize == UNKNOWN_PADDING_SIZE);
 
   // Utilize random generator to generator a random number
   nsresult rv;
   uint32_t randomNumber = 0;
   nsCOMPtr<nsIRandomGenerator> randomGenerator =
       do_GetService("@mozilla.org/security/random-generator;1", &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    Maybe<uint64_t> maybeRandomNum = RandomUint64();
+    if (maybeRandomNum.isSome()) {
+      mPaddingInfo.emplace(uint32_t(maybeRandomNum.value() % kMaxRandomNumber));
+      return NS_OK;
+    }
     return rv;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(randomGenerator);
 
   uint8_t* buffer;
   rv = randomGenerator->GenerateRandomBytes(sizeof(randomNumber), &buffer);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    Maybe<uint64_t> maybeRandomNum = RandomUint64();
+    if (maybeRandomNum.isSome()) {
+      mPaddingInfo.emplace(uint32_t(maybeRandomNum.value() % kMaxRandomNumber));
+      return NS_OK;
+    }
     return rv;
   }
 
   memcpy(&randomNumber, buffer, sizeof(randomNumber));
   free(buffer);
 
   mPaddingInfo.emplace(randomNumber % kMaxRandomNumber);
 
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/dom/HTMLLinkElement.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLLinkElementBinding.h"
 #include "nsContentUtils.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsDOMTokenList.h"
 #include "nsIContentInlines.h"
 #include "mozilla/dom/Document.h"
 #include "nsINode.h"
@@ -112,28 +113,33 @@ bool HTMLLinkElement::HasDeferredDNSPref
 nsresult HTMLLinkElement::BindToTree(Document* aDocument, nsIContent* aParent,
                                      nsIContent* aBindingParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv =
       nsGenericHTMLElement::BindToTree(aDocument, aParent, aBindingParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  bool isLocalizationLink =
+      aDocument && this->AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel,
+                                     nsGkAtoms::localization, eIgnoreCase);
+
   if (Document* doc = GetComposedDoc()) {
-    doc->RegisterPendingLinkUpdate(this);
+    if (!isLocalizationLink || !doc->NodePrincipal()->IsSystemPrincipal()) {
+      doc->RegisterPendingLinkUpdate(this);
+    }
     TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
   }
 
   void (HTMLLinkElement::*update)() =
       &HTMLLinkElement::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(
       NewRunnableMethod("dom::HTMLLinkElement::BindToTree", this, update));
 
-  if (aDocument && this->AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel,
-                                     nsGkAtoms::localization, eIgnoreCase)) {
+  if (isLocalizationLink) {
     aDocument->LocalizationLinkAdded(this);
   }
 
   CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
 
   return rv;
 }
 
--- a/dom/html/HTMLMenuElement.cpp
+++ b/dom/html/HTMLMenuElement.cpp
@@ -3,16 +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/. */
 
 #include "mozilla/dom/HTMLMenuElement.h"
 
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLMenuElementBinding.h"
 #include "mozilla/dom/HTMLMenuItemElement.h"
 #include "nsIMenuBuilder.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
 
 #define HTMLMENUBUILDER_CONTRACTID "@mozilla.org/content/html-menu-builder;1"
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/HTMLSourceElementBinding.h"
 
+#include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/ResponsiveImageSelector.h"
 #include "mozilla/dom/MediaList.h"
 #include "mozilla/dom/MediaSource.h"
 
 #include "nsGkAtoms.h"
 
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -7,31 +7,31 @@
 #include "ImageDocument.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/ComputedStyle.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ImageDocumentBinding.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/MouseEvent.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/StaticPrefs.h"
 #include "nsRect.h"
 #include "nsIImageLoadingContent.h"
 #include "nsGenericHTMLElement.h"
 #include "nsDocShell.h"
 #include "DocumentInlines.h"
 #include "nsDOMTokenList.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrame.h"
 #include "nsGkAtoms.h"
 #include "imgIRequest.h"
 #include "imgILoader.h"
 #include "imgIContainer.h"
 #include "imgINotificationObserver.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIChannel.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsError.h"
 #include "nsURILoader.h"
 #include "nsIDocShell.h"
@@ -397,22 +397,22 @@ ImageDocument::DOMRestoreImageTo(int32_t
 }
 
 void ImageDocument::ScrollImageTo(int32_t aX, int32_t aY, bool restoreImage) {
   if (restoreImage) {
     RestoreImage();
     FlushPendingNotifications(FlushType::Layout);
   }
 
-  nsCOMPtr<nsIPresShell> shell = GetShell();
-  if (!shell) {
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (!presShell) {
     return;
   }
 
-  nsIScrollableFrame* sf = shell->GetRootScrollFrameAsScrollable();
+  nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
   if (!sf) {
     return;
   }
 
   float ratio = GetRatio();
   // Don't try to scroll image if the document is not visible (mVisibleWidth or
   // mVisibleHeight is zero).
   if (ratio <= 0.0) {
@@ -830,19 +830,19 @@ float ImageDocument::GetZoomLevel() {
     }
   }
   return zoomLevel;
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
 float ImageDocument::GetResolution() {
   float resolution = mOriginalResolution;
-  nsCOMPtr<nsIPresShell> shell = GetShell();
-  if (shell) {
-    resolution = shell->GetResolution();
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (presShell) {
+    resolution = presShell->GetResolution();
   }
   return resolution;
 }
 #endif
 
 }  // namespace dom
 }  // namespace mozilla
 
--- a/dom/html/MediaDocument.cpp
+++ b/dom/html/MediaDocument.cpp
@@ -3,27 +3,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaDocument.h"
 #include "nsGkAtoms.h"
 #include "nsRect.h"
 #include "nsPresContext.h"
-#include "nsIPresShell.h"
 #include "nsIScrollable.h"
 #include "nsViewManager.h"
 #include "nsITextToSubURI.h"
 #include "nsIURL.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsCharsetSource.h"  // kCharsetFrom* macro definition
 #include "nsNodeInfoManager.h"
 #include "nsContentUtils.h"
 #include "nsDocElementCreatedNotificationRunner.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/Services.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIMultiPartChannel.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace dom {
@@ -237,21 +237,21 @@ nsresult MediaDocument::CreateSyntheticD
 
   root->AppendChildTo(body, false);
 
   return NS_OK;
 }
 
 nsresult MediaDocument::StartLayout() {
   mMayStartLayout = true;
-  nsCOMPtr<nsIPresShell> shell = GetShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   // Don't mess with the presshell if someone has already handled
   // its initial reflow.
-  if (shell && !shell->DidInitialize()) {
-    nsresult rv = shell->Initialize();
+  if (presShell && !presShell->DidInitialize()) {
+    nsresult rv = presShell->Initialize();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 void MediaDocument::GetFileName(nsAString& aResult, nsIChannel* aChannel) {
   aResult.Truncate();
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -2,26 +2,26 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaDocument.h"
 #include "nsIPluginDocument.h"
 #include "nsGkAtoms.h"
-#include "nsIPresShell.h"
 #include "nsIObjectFrame.h"
 #include "nsNPAPIPluginInstance.h"
 #include "DocumentInlines.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIPropertyBag2.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/PresShell.h"
 #include "nsObjectLoadingContent.h"
 #include "GeckoProfiler.h"
 
 namespace mozilla {
 namespace dom {
 
 class PluginDocument final : public MediaDocument, public nsIPluginDocument {
  public:
@@ -177,17 +177,17 @@ nsresult PluginDocument::StartDocumentLo
   mStreamListener = new PluginStreamListener(this);
   NS_ASSERTION(aDocListener, "null aDocListener");
   NS_ADDREF(*aDocListener = mStreamListener);
 
   return rv;
 }
 
 nsresult PluginDocument::CreateSyntheticPluginDocument() {
-  NS_ASSERTION(!GetShell() || !GetShell()->DidInitialize(),
+  NS_ASSERTION(!GetPresShell() || !GetPresShell()->DidInitialize(),
                "Creating synthetic plugin document content too late");
 
   // make our generic document
   nsresult rv = MediaDocument::CreateSyntheticDocument();
   NS_ENSURE_SUCCESS(rv, rv);
   // then attach our plugin
 
   Element* body = GetBodyElement();
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -452,25 +452,23 @@ nsresult SinkContext::GrowStack() {
  * Flush all elements that have been seen so far such that
  * they are visible in the tree. Specifically, make sure
  * that they are all added to their respective parents.
  * Also, do notification at the top for all content that
  * has been newly added so that the frame tree is complete.
  */
 nsresult SinkContext::FlushTags() {
   mSink->mDeferredFlushTags = false;
-  bool oldBeganUpdate = mSink->mBeganUpdate;
   uint32_t oldUpdates = mSink->mUpdatesInNotification;
 
   ++(mSink->mInNotification);
   mSink->mUpdatesInNotification = 0;
   {
     // Scope so we call EndUpdate before we decrease mInNotification
     mozAutoDocUpdate updateBatch(mSink->mDocument, true);
-    mSink->mBeganUpdate = true;
 
     // Start from the base of the stack (growing downward) and do
     // a notification from the node that is closest to the root of
     // tree for any content that has been added.
 
     // Note that we can start at stackPos == 0 here, because it's the caller's
     // responsibility to handle flushing interactions between contexts (see
     // HTMLContentSink::BeginContext).
@@ -510,17 +508,16 @@ nsresult SinkContext::FlushTags() {
   }
   --(mSink->mInNotification);
 
   if (mSink->mUpdatesInNotification > 1) {
     UpdateChildCounts();
   }
 
   mSink->mUpdatesInNotification = oldUpdates;
-  mSink->mBeganUpdate = oldBeganUpdate;
 
   return NS_OK;
 }
 
 /**
  * NOTE!! Forked into nsXMLContentSink. Please keep in sync.
  */
 void SinkContext::UpdateChildCounts() {
@@ -865,27 +862,23 @@ void HTMLContentSink::CloseHeadContext()
     uint32_t n = mContextStack.Length() - 1;
     mCurrentContext = mContextStack.ElementAt(n);
     mContextStack.RemoveElementAt(n);
   }
 }
 
 void HTMLContentSink::NotifyInsert(nsIContent* aContent,
                                    nsIContent* aChildContent) {
-  if (aContent && aContent->GetUncomposedDoc() != mDocument) {
-    // aContent is not actually in our document anymore.... Just bail out of
-    // here; notifying on our document for this insert would be wrong.
-    return;
-  }
-
   mInNotification++;
 
   {
     // Scope so we call EndUpdate before we decrease mInNotification
-    MOZ_AUTO_DOC_UPDATE(mDocument, !mBeganUpdate);
+    // Note that aContent->OwnerDoc() may be different to mDocument already.
+    MOZ_AUTO_DOC_UPDATE(aContent ? aContent->OwnerDoc() : mDocument.get(),
+                        true);
     nsNodeUtils::ContentInserted(NODE_FROM(aContent, mDocument), aChildContent);
     mLastNotificationTime = PR_Now();
   }
 
   mInNotification--;
 }
 
 void HTMLContentSink::NotifyRootInsertion() {
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -3,16 +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/. */
 
 #include "nsHTMLDocument.h"
 
 #include "nsIContentPolicy.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/HTMLAllCollection.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
 #include "nsCOMPtr.h"
 #include "nsGlobalWindow.h"
 #include "nsString.h"
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
@@ -1427,17 +1428,17 @@ void nsHTMLDocument::Close(ErrorResult& 
   // one line of code here!
   // XXXbz as far as I can tell this may not be needed anymore; all
   // the testcases in bug 57636 pass without this line...  Leaving
   // it be for now, though.  In any case, there's no reason to do
   // this if we have no presshell, since in that case none of the
   // above about reusing frames applies.
   //
   // XXXhsivonen keeping this around for bug 577508 / 253951 still :-(
-  if (GetShell()) {
+  if (GetPresShell()) {
     FlushPendingNotifications(FlushType::Layout);
   }
 }
 
 void nsHTMLDocument::WriteCommon(const Sequence<nsString>& aText,
                                  bool aNewlineTerminate,
                                  mozilla::ErrorResult& rv) {
   // Fast path the common case
@@ -1868,18 +1869,20 @@ static void NotifyEditableStateChange(ns
   }
 }
 
 void nsHTMLDocument::TearingDownEditor() {
   if (IsEditingOn()) {
     EditingState oldState = mEditingState;
     mEditingState = eTearingDown;
 
-    nsCOMPtr<nsIPresShell> presShell = GetShell();
-    if (!presShell) return;
+    RefPtr<PresShell> presShell = GetPresShell();
+    if (!presShell) {
+      return;
+    }
 
     nsTArray<RefPtr<StyleSheet>> agentSheets;
     presShell->GetAgentStyleSheets(agentSheets);
 
     auto cache = nsLayoutStylesheetCache::Singleton();
 
     agentSheets.RemoveElement(cache->ContentEditableSheet());
     if (oldState == eDesignMode)
@@ -2013,17 +2016,17 @@ nsresult nsHTMLDocument::EditingStateCha
   bool spellRecheckAll = false;
   bool putOffToRemoveScriptBlockerUntilModifyingEditingState = false;
   htmlEditor = nullptr;
 
   {
     EditingState oldState = mEditingState;
     nsAutoEditingState push(this, eSettingUp);
 
-    nsCOMPtr<nsIPresShell> presShell = GetShell();
+    RefPtr<PresShell> presShell = GetPresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
     // Before making this window editable, we need to modify UA style sheet
     // because new style may change whether focused element will be focusable
     // or not.
     nsTArray<RefPtr<StyleSheet>> agentSheets;
     rv = presShell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -2195,17 +2198,17 @@ void nsHTMLDocument::MaybeDispatchCheckK
   checkEvent.mFlags.mOnlySystemGroupDispatch = true;
   // Post the event rather than dispatching it synchronously because we need
   // a call of SetKeyPressEventModel() before first key input.  Therefore, we
   // can avoid paying unnecessary runtime cost for most web apps.
   (new AsyncEventDispatcher(this, checkEvent))->PostDOMEvent();
 }
 
 void nsHTMLDocument::SetKeyPressEventModel(uint16_t aKeyPressEventModel) {
-  nsIPresShell* presShell = GetShell();
+  PresShell* presShell = GetPresShell();
   if (!presShell) {
     return;
   }
   presShell->SetKeyPressEventModel(aKeyPressEventModel);
 }
 
 void nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
                                    nsIPrincipal& aSubjectPrincipal,
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsTextEditorState.h"
 #include "mozilla/TextInputListener.h"
 
 #include "nsCOMPtr.h"
-#include "nsIPresShell.h"
 #include "nsView.h"
 #include "nsCaret.h"
 #include "nsLayoutCID.h"
 #include "nsITextControlFrame.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsTextControlFrame.h"
 #include "nsIControllers.h"
 #include "nsITransactionManager.h"
@@ -30,16 +29,17 @@
 #include "mozilla/dom/Selection.h"
 #include "mozilla/TextEditRules.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsIController.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLTextAreaElement.h"
 #include "mozilla/dom/Text.h"
 #include "nsNumberControlFrame.h"
 #include "nsFrameSelection.h"
@@ -794,17 +794,17 @@ void TextInputListener::OnSelectionChang
   bool collapsed = aSelection.IsCollapsed();
   if (!collapsed && (aReason & (nsISelectionListener::MOUSEUP_REASON |
                                 nsISelectionListener::KEYPRESS_REASON |
                                 nsISelectionListener::SELECTALL_REASON))) {
     nsIContent* content = mFrame->GetContent();
     if (content) {
       nsCOMPtr<Document> doc = content->GetComposedDoc();
       if (doc) {
-        nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
+        RefPtr<PresShell> presShell = doc->GetPresShell();
         if (presShell) {
           nsEventStatus status = nsEventStatus_eIgnore;
           WidgetEvent event(true, eFormSelect);
 
           presShell->HandleEventWithTarget(&event, mFrame, content, &status);
         }
       }
     }
@@ -1340,18 +1340,20 @@ nsresult nsTextEditorState::PrepareEdito
     // for its content manipulations, and it causes it to fail some security
     // checks deep inside when initializing. So we explictly make it clear that
     // we're native code.
     // Note that any script that's directly trying to access our value
     // has to be going through some scriptable object to do that and that
     // already does the relevant security checks.
     AutoNoJSAPI nojsapi;
 
-    rv = newTextEditor->Init(*doc, GetRootNode(), mSelCon, editorFlags,
-                             defaultValue);
+    RefPtr<Element> rootElement = GetRootNode();
+    RefPtr<nsTextInputSelectionImpl> selectionController = mSelCon;
+    rv = newTextEditor->Init(*doc, rootElement, selectionController,
+                             editorFlags, defaultValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Initialize the controller for the editor
 
   if (!SuppressEventHandlers(presContext)) {
     nsCOMPtr<nsIControllers> controllers;
     nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -517,17 +517,18 @@ void DeserializeStructuredCloneFiles(
         case StructuredCloneFile::eBlob: {
           MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TIPCBlob);
 
           const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
 
           RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(ipcBlob);
           MOZ_ASSERT(blobImpl);
 
-          RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
+          RefPtr<Blob> blob =
+              Blob::Create(aDatabase->GetOwnerGlobal(), blobImpl);
 
           StructuredCloneFile* file = aFiles.AppendElement();
           MOZ_ASSERT(file);
 
           file->mType = StructuredCloneFile::eBlob;
           file->mBlob.swap(blob);
 
           break;
@@ -605,17 +606,18 @@ void DeserializeStructuredCloneFiles(
 
           MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TIPCBlob);
 
           const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
 
           RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(ipcBlob);
           MOZ_ASSERT(blobImpl);
 
-          RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
+          RefPtr<Blob> blob =
+              Blob::Create(aDatabase->GetOwnerGlobal(), blobImpl);
 
           StructuredCloneFile* file = aFiles.AppendElement();
           MOZ_ASSERT(file);
 
           file->mType = StructuredCloneFile::eWasmBytecode;
           file->mBlob.swap(blob);
 
           break;
@@ -1220,17 +1222,18 @@ already_AddRefed<File> ConvertActorToFil
   RefPtr<BlobImpl> blobImpl = actor->SetPendingInfoAndDeleteActor(
       mutableFile->Name(), mutableFile->Type(), size.value(),
       lastModified.value());
   MOZ_ASSERT(blobImpl);
 
   RefPtr<BlobImpl> blobImplSnapshot =
       new BlobImplSnapshot(blobImpl, static_cast<IDBFileHandle*>(aFileHandle));
 
-  RefPtr<File> file = File::Create(mutableFile->GetOwner(), blobImplSnapshot);
+  RefPtr<File> file =
+      File::Create(mutableFile->GetOwnerGlobal(), blobImplSnapshot);
   return file.forget();
 }
 
 void DispatchFileHandleErrorEvent(IDBFileRequest* aFileRequest,
                                   nsresult aErrorCode,
                                   IDBFileHandle* aFileHandle) {
   MOZ_ASSERT(aFileRequest);
   aFileRequest->AssertIsOnOwningThread();
@@ -1672,17 +1675,18 @@ mozilla::ipc::IPCResult BackgroundFactor
   nsresult rv;
   nsCOMPtr<nsIPrincipal> principal =
       mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   if (XRE_IsParentProcess()) {
-    nsCOMPtr<nsPIDOMWindowInner> window = mFactory->GetParentObject();
+    nsCOMPtr<nsIGlobalObject> global = mFactory->GetParentObject();
+    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
     MOZ_ASSERT(window);
 
     nsCOMPtr<Element> ownerElement =
         do_QueryInterface(window->GetChromeEventHandler());
     if (NS_WARN_IF(!ownerElement)) {
       // If this fails, the page was navigated. Fail the permission check by
       // forcing an immediate retry.
       if (!SendPermissionRetry()) {
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -29,17 +29,16 @@ using namespace indexedDB;
 
 IDBCursor::IDBCursor(Type aType, BackgroundCursorChild* aBackgroundActor,
                      const Key& aKey)
     : mBackgroundActor(aBackgroundActor),
       mRequest(aBackgroundActor->GetRequest()),
       mSourceObjectStore(aBackgroundActor->GetObjectStore()),
       mSourceIndex(aBackgroundActor->GetIndex()),
       mTransaction(mRequest->GetTransaction()),
-      mScriptOwner(mTransaction->Database()->GetScriptOwner()),
       mCachedKey(JS::UndefinedValue()),
       mCachedPrimaryKey(JS::UndefinedValue()),
       mCachedValue(JS::UndefinedValue()),
       mKey(aKey),
       mType(aType),
       mDirection(aBackgroundActor->GetDirection()),
       mHaveCachedKey(false),
       mHaveCachedPrimaryKey(false),
@@ -50,22 +49,16 @@ IDBCursor::IDBCursor(Type aType, Backgro
   MOZ_ASSERT(aBackgroundActor);
   aBackgroundActor->AssertIsOnOwningThread();
   MOZ_ASSERT(mRequest);
   MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
                 mSourceObjectStore);
   MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, mSourceIndex);
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(!aKey.IsUnset());
-  MOZ_ASSERT(mScriptOwner);
-
-  if (mScriptOwner) {
-    mozilla::HoldJSObjects(this);
-    mRooted = true;
-  }
 }
 
 bool IDBCursor::IsLocaleAware() const {
   return mSourceIndex && !mSourceIndex->Locale().IsEmpty();
 }
 
 IDBCursor::~IDBCursor() {
   AssertIsOnOwningThread();
@@ -185,17 +178,16 @@ void IDBCursor::DropJSObjects() {
   AssertIsOnOwningThread();
 
   Reset();
 
   if (!mRooted) {
     return;
   }
 
-  mScriptOwner = nullptr;
   mRooted = false;
 
   mozilla::DropJSObjects(this);
 }
 
 bool IDBCursor::IsSourceDeleted() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mTransaction);
@@ -229,17 +221,17 @@ void IDBCursor::Reset() {
 
   mHaveCachedKey = false;
   mHaveCachedPrimaryKey = false;
   mHaveCachedValue = false;
   mHaveValue = false;
   mContinueCalled = false;
 }
 
-nsPIDOMWindowInner* IDBCursor::GetParentObject() const {
+nsIGlobalObject* IDBCursor::GetParentObject() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mTransaction);
 
   return mTransaction->GetParentObject();
 }
 
 IDBCursorDirection IDBCursor::GetDirection() const {
   AssertIsOnOwningThread();
@@ -868,17 +860,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
   MOZ_ASSERT_IF(!tmp->mHaveCachedKey, tmp->mCachedKey.isUndefined());
   MOZ_ASSERT_IF(!tmp->mHaveCachedPrimaryKey,
                 tmp->mCachedPrimaryKey.isUndefined());
   MOZ_ASSERT_IF(!tmp->mHaveCachedValue, tmp->mCachedValue.isUndefined());
 
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptOwner)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedKey)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedPrimaryKey)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedValue)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
   // Don't unlink mRequest, mSourceObjectStore, or mSourceIndex!
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -10,17 +10,17 @@
 #include "IndexedDatabase.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/IDBCursorBinding.h"
 #include "mozilla/dom/indexedDB/Key.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 
-class nsPIDOMWindowInner;
+class nsIGlobalObject;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 class IDBIndex;
@@ -60,18 +60,16 @@ class IDBCursor final : public nsISuppor
 
   RefPtr<IDBRequest> mRequest;
   RefPtr<IDBObjectStore> mSourceObjectStore;
   RefPtr<IDBIndex> mSourceIndex;
 
   // mSourceObjectStore or mSourceIndex will hold this alive.
   IDBTransaction* mTransaction;
 
-  JS::Heap<JSObject*> mScriptOwner;
-
   // These are cycle-collected!
   JS::Heap<JS::Value> mCachedKey;
   JS::Heap<JS::Value> mCachedPrimaryKey;
   JS::Heap<JS::Value> mCachedValue;
 
   Key mKey;
   Key mSortKey;
   Key mPrimaryKey;
@@ -109,17 +107,17 @@ class IDBCursor final : public nsISuppor
   void AssertIsOnOwningThread() const
 #ifdef DEBUG
       ;
 #else
   {
   }
 #endif
 
-  nsPIDOMWindowInner* GetParentObject() const;
+  nsIGlobalObject* GetParentObject() const;
 
   void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
 
   IDBCursorDirection GetDirection() const;
 
   void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
               ErrorResult& aRv);
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -145,17 +145,17 @@ class IDBDatabase::Observer final : publ
     MOZ_ASSERT(!mWeakDatabase);
   }
 
   NS_DECL_NSIOBSERVER
 };
 
 IDBDatabase::IDBDatabase(IDBOpenDBRequest* aRequest, IDBFactory* aFactory,
                          BackgroundDatabaseChild* aActor, DatabaseSpec* aSpec)
-    : IDBWrapperCache(aRequest),
+    : DOMEventTargetHelper(aRequest),
       mFactory(aFactory),
       mSpec(aSpec),
       mBackgroundActor(aActor),
       mFileHandleDisabled(aRequest->IsFileHandleDisabled()),
       mClosed(false),
       mInvalidated(false),
       mQuotaExceeded(false),
       mIncreasedActiveDatabaseCount(false) {
@@ -179,20 +179,20 @@ already_AddRefed<IDBDatabase> IDBDatabas
   MOZ_ASSERT(aRequest);
   MOZ_ASSERT(aFactory);
   aFactory->AssertIsOnOwningThread();
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(aSpec);
 
   RefPtr<IDBDatabase> db = new IDBDatabase(aRequest, aFactory, aActor, aSpec);
 
-  db->SetScriptOwner(aRequest->GetScriptOwner());
-
   if (NS_IsMainThread()) {
-    if (nsPIDOMWindowInner* window = aFactory->GetParentObject()) {
+    nsCOMPtr<nsPIDOMWindowInner> window =
+        do_QueryInterface(aFactory->GetParentObject());
+    if (window) {
       uint64_t windowId = window->WindowID();
 
       RefPtr<Observer> observer = new Observer(db, windowId);
 
       nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
       MOZ_ASSERT(obsSvc);
 
       // This topic must be successfully registered.
@@ -313,20 +313,16 @@ void IDBDatabase::RefreshSpec(bool aMayD
   for (auto iter = mTransactions.Iter(); !iter.Done(); iter.Next()) {
     RefPtr<IDBTransaction> transaction = iter.Get()->GetKey();
     MOZ_ASSERT(transaction);
     transaction->AssertIsOnOwningThread();
     transaction->RefreshSpec(aMayDelete);
   }
 }
 
-nsPIDOMWindowInner* IDBDatabase::GetParentObject() const {
-  return mFactory->GetParentObject();
-}
-
 const nsString& IDBDatabase::Name() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mSpec);
 
   return mSpec->metadata().name();
 }
 
 uint64_t IDBDatabase::Version() const {
@@ -1055,42 +1051,44 @@ void IDBDatabase::LogWarning(const char*
   MOZ_ASSERT(aMessageName);
 
   ScriptErrorHelper::DumpLocalizedMessage(
       nsDependentCString(aMessageName), aFilename, aLineNumber, aColumnNumber,
       nsIScriptError::warningFlag, mFactory->IsChrome(),
       mFactory->InnerWindowID());
 }
 
-NS_IMPL_ADDREF_INHERITED(IDBDatabase, IDBWrapperCache)
-NS_IMPL_RELEASE_INHERITED(IDBDatabase, IDBWrapperCache)
+NS_IMPL_ADDREF_INHERITED(IDBDatabase, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(IDBDatabase, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBDatabase)
-NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase,
+                                                  DOMEventTargetHelper)
   tmp->AssertIsOnOwningThread();
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase,
+                                                DOMEventTargetHelper)
   tmp->AssertIsOnOwningThread();
 
   // Don't unlink mFactory!
 
   // We've been unlinked, at the very least we should be able to prevent further
   // transactions from starting and unblock any other SetVersion callers.
   tmp->CloseInternal();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 void IDBDatabase::DisconnectFromOwner() {
   InvalidateInternal();
-  IDBWrapperCache::DisconnectFromOwner();
+  DOMEventTargetHelper::DisconnectFromOwner();
 }
 
 void IDBDatabase::LastRelease() {
   AssertIsOnOwningThread();
 
   CloseInternal();
 
   if (mBackgroundActor) {
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -5,26 +5,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_idbdatabase_h__
 #define mozilla_dom_idbdatabase_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/IDBTransactionBinding.h"
 #include "mozilla/dom/StorageTypeBinding.h"
-#include "mozilla/dom/IDBWrapperCache.h"
 #include "mozilla/dom/quota/PersistenceType.h"
+#include "mozilla/DOMEventTargetHelper.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 
 class nsIEventTarget;
-class nsPIDOMWindowInner;
+class nsIGlobalObject;
 
 namespace mozilla {
 
 class ErrorResult;
 class EventChainPostVisitor;
 
 namespace dom {
 
@@ -42,17 +42,17 @@ class Optional;
 class StringOrStringSequence;
 
 namespace indexedDB {
 class BackgroundDatabaseChild;
 class DatabaseSpec;
 class PBackgroundIDBDatabaseFileChild;
 }  // namespace indexedDB
 
-class IDBDatabase final : public IDBWrapperCache {
+class IDBDatabase final : public DOMEventTargetHelper {
   typedef mozilla::dom::indexedDB::DatabaseSpec DatabaseSpec;
   typedef mozilla::dom::StorageType StorageType;
   typedef mozilla::dom::quota::PersistenceType PersistenceType;
 
   class Observer;
   friend class Observer;
 
   friend class IDBObjectStore;
@@ -173,18 +173,16 @@ class IDBDatabase final : public IDBWrap
   nsresult GetQuotaInfo(nsACString& aOrigin, PersistenceType* aPersistenceType);
 
   bool IsFileHandleDisabled() const { return mFileHandleDisabled; }
 
   void NoteLiveMutableFile(IDBMutableFile* aMutableFile);
 
   void NoteFinishedMutableFile(IDBMutableFile* aMutableFile);
 
-  nsPIDOMWindowInner* GetParentObject() const;
-
   already_AddRefed<DOMStringList> ObjectStoreNames() const;
 
   already_AddRefed<IDBObjectStore> CreateObjectStore(
       const nsAString& aName,
       const IDBObjectStoreParameters& aOptionalParameters, ErrorResult& aRv);
 
   void DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
 
@@ -223,17 +221,17 @@ class IDBDatabase final : public IDBWrap
     MaybeDecreaseActiveDatabaseCount();
 
     mBackgroundActor = nullptr;
   }
 
   const DatabaseSpec* Spec() const { return mSpec; }
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, DOMEventTargetHelper)
 
   // DOMEventTargetHelper
   void DisconnectFromOwner() override;
 
   virtual void LastRelease() override;
 
   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
 
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -65,32 +65,28 @@ struct IDBFactory::PendingRequestInfo {
                      const FactoryRequestParams& aParams)
       : mRequest(aRequest), mParams(aParams) {
     MOZ_ASSERT(aRequest);
     MOZ_ASSERT(aParams.type() != FactoryRequestParams::T__None);
   }
 };
 
 IDBFactory::IDBFactory()
-    : mOwningObject(nullptr),
-      mBackgroundActor(nullptr),
+    : mBackgroundActor(nullptr),
       mInnerWindowID(0),
       mActiveTransactionCount(0),
       mActiveDatabaseCount(0),
       mBackgroundActorFailed(false),
       mPrivateBrowsingMode(false) {
   AssertIsOnOwningThread();
 }
 
 IDBFactory::~IDBFactory() {
   MOZ_ASSERT_IF(mBackgroundActorFailed, !mBackgroundActor);
 
-  mOwningObject = nullptr;
-  mozilla::DropJSObjects(this);
-
   if (mBackgroundActor) {
     mBackgroundActor->SendDeleteMeInternal();
     MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
   }
 }
 
 // static
 nsresult IDBFactory::CreateForWindow(nsPIDOMWindowInner* aWindow,
@@ -138,136 +134,141 @@ nsresult IDBFactory::CreateForWindow(nsP
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
 
   RefPtr<IDBFactory> factory = new IDBFactory();
   factory->mPrincipalInfo = std::move(principalInfo);
-  factory->mWindow = aWindow;
+
+  factory->mGlobal = do_QueryInterface(aWindow);
+  MOZ_ASSERT(factory->mGlobal);
+
   factory->mTabChild = TabChild::GetFrom(aWindow);
   factory->mEventTarget =
       nsGlobalWindowInner::Cast(aWindow)->EventTargetFor(TaskCategory::Other);
   factory->mInnerWindowID = aWindow->WindowID();
   factory->mPrivateBrowsingMode =
       loadContext && loadContext->UsePrivateBrowsing();
 
   factory.forget(aFactory);
   return NS_OK;
 }
 
 // static
-nsresult IDBFactory::CreateForMainThreadJS(JSContext* aCx,
-                                           JS::Handle<JSObject*> aOwningObject,
+nsresult IDBFactory::CreateForMainThreadJS(nsIGlobalObject* aGlobal,
                                            IDBFactory** aFactory) {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aGlobal);
+
+  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aGlobal);
+  if (NS_WARN_IF(!sop)) {
+    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+  }
 
   nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo());
-  nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aOwningObject);
+  nsIPrincipal* principal = sop->GetPrincipal();
   MOZ_ASSERT(principal);
   bool isSystem;
   if (!AllowedForPrincipal(principal, &isSystem)) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   nsresult rv = PrincipalToPrincipalInfo(principal, principalInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (NS_WARN_IF(!QuotaManager::IsPrincipalInfoValid(*principalInfo))) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  rv = CreateForMainThreadJSInternal(aCx, aOwningObject, principalInfo,
-                                     aFactory);
+  rv = CreateForMainThreadJSInternal(aGlobal, principalInfo, aFactory);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   MOZ_ASSERT(!principalInfo);
 
   return NS_OK;
 }
 
 // static
-nsresult IDBFactory::CreateForWorker(JSContext* aCx,
-                                     JS::Handle<JSObject*> aOwningObject,
+nsresult IDBFactory::CreateForWorker(nsIGlobalObject* aGlobal,
                                      const PrincipalInfo& aPrincipalInfo,
                                      uint64_t aInnerWindowID,
                                      IDBFactory** aFactory) {
   MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aGlobal);
   MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None);
 
   nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo(aPrincipalInfo));
 
-  nsresult rv = CreateForJSInternal(aCx, aOwningObject, principalInfo,
-                                    aInnerWindowID, aFactory);
+  nsresult rv =
+      CreateInternal(aGlobal, principalInfo, aInnerWindowID, aFactory);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   MOZ_ASSERT(!principalInfo);
 
   return NS_OK;
 }
 
 // static
 nsresult IDBFactory::CreateForMainThreadJSInternal(
-    JSContext* aCx, JS::Handle<JSObject*> aOwningObject,
-    nsAutoPtr<PrincipalInfo>& aPrincipalInfo, IDBFactory** aFactory) {
+    nsIGlobalObject* aGlobal, nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
+    IDBFactory** aFactory) {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aGlobal);
   MOZ_ASSERT(aPrincipalInfo);
 
   if (aPrincipalInfo->type() != PrincipalInfo::TSystemPrincipalInfo &&
       NS_WARN_IF(!Preferences::GetBool(kPrefIndexedDBEnabled, false))) {
     *aFactory = nullptr;
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
   if (NS_WARN_IF(!mgr)) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  nsresult rv = CreateForJSInternal(aCx, aOwningObject, aPrincipalInfo,
-                                    /* aInnerWindowID */ 0, aFactory);
+  nsresult rv =
+      CreateInternal(aGlobal, aPrincipalInfo, /* aInnerWindowID */ 0, aFactory);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 // static
-nsresult IDBFactory::CreateForJSInternal(
-    JSContext* aCx, JS::Handle<JSObject*> aOwningObject,
-    nsAutoPtr<PrincipalInfo>& aPrincipalInfo, uint64_t aInnerWindowID,
-    IDBFactory** aFactory) {
-  MOZ_ASSERT(aCx);
-  MOZ_ASSERT(aOwningObject);
+nsresult IDBFactory::CreateInternal(nsIGlobalObject* aGlobal,
+                                    nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
+                                    uint64_t aInnerWindowID,
+                                    IDBFactory** aFactory) {
+  MOZ_ASSERT(aGlobal);
   MOZ_ASSERT(aPrincipalInfo);
   MOZ_ASSERT(aPrincipalInfo->type() != PrincipalInfo::T__None);
   MOZ_ASSERT(aFactory);
-  MOZ_ASSERT(JS_IsGlobalObject(aOwningObject));
 
   if (aPrincipalInfo->type() != PrincipalInfo::TContentPrincipalInfo &&
       aPrincipalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) {
     NS_WARNING("IndexedDB not allowed for this principal!");
     aPrincipalInfo = nullptr;
     *aFactory = nullptr;
     return NS_OK;
   }
 
   RefPtr<IDBFactory> factory = new IDBFactory();
   factory->mPrincipalInfo = aPrincipalInfo.forget();
-  factory->mOwningObject = aOwningObject;
-  mozilla::HoldJSObjects(factory.get());
+  factory->mGlobal = aGlobal;
   factory->mEventTarget = GetCurrentThreadEventTarget();
   factory->mInnerWindowID = aInnerWindowID;
 
   factory.forget(aFactory);
   return NS_OK;
 }
 
 // static
@@ -372,28 +373,31 @@ bool IDBFactory::AllowedForPrincipal(nsI
   return true;
 }
 
 void IDBFactory::UpdateActiveTransactionCount(int32_t aDelta) {
   AssertIsOnOwningThread();
   MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 || (mActiveTransactionCount + aDelta) <
                                           mActiveTransactionCount);
   mActiveTransactionCount += aDelta;
-  if (mWindow) {
-    mWindow->UpdateActiveIndexedDBTransactionCount(aDelta);
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal);
+  if (window) {
+    window->UpdateActiveIndexedDBTransactionCount(aDelta);
   }
 }
 
 void IDBFactory::UpdateActiveDatabaseCount(int32_t aDelta) {
   AssertIsOnOwningThread();
   MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 ||
                         (mActiveDatabaseCount + aDelta) < mActiveDatabaseCount);
   mActiveDatabaseCount += aDelta;
-  if (mWindow) {
-    mWindow->UpdateActiveIndexedDBDatabaseCount(aDelta);
+
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal);
+  if (window) {
+    window->UpdateActiveIndexedDBDatabaseCount(aDelta);
   }
 }
 
 bool IDBFactory::IsChrome() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mPrincipalInfo);
 
   return mPrincipalInfo->type() == PrincipalInfo::TSystemPrincipalInfo;
@@ -416,18 +420,19 @@ already_AddRefed<IDBOpenDBRequest> IDBFa
                       Optional<uint64_t>(aVersion), Optional<StorageType>(),
                       /* aDeleting */ false, aCallerType, aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest> IDBFactory::Open(
     JSContext* aCx, const nsAString& aName, const IDBOpenDBOptions& aOptions,
     CallerType aCallerType, ErrorResult& aRv) {
   if (!IsChrome() && aOptions.mStorage.WasPassed()) {
-    if (mWindow && mWindow->GetExtantDoc()) {
-      mWindow->GetExtantDoc()->WarnOnceAbout(
+    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal);
+    if (window && window->GetExtantDoc()) {
+      window->GetExtantDoc()->WarnOnceAbout(
           Document::eIDBOpenDBOptions_StorageType);
     } else if (!NS_IsMainThread()) {
       // The method below reports on the main thread too, so we need to make
       // sure we're on a worker. Workers don't have a WarnOnceAbout mechanism,
       // so this will be reported every time.
       WorkerPrivate::ReportErrorToConsole("IDBOpenDBOptions_StorageType");
     }
 
@@ -558,18 +563,17 @@ already_AddRefed<IDBOpenDBRequest> IDBFa
                       /* aDeleting */ true, aGuarantee, aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(
     JSContext* aCx, nsIPrincipal* aPrincipal, const nsAString& aName,
     const Optional<uint64_t>& aVersion,
     const Optional<StorageType>& aStorageType, bool aDeleting,
     CallerType aCallerType, ErrorResult& aRv) {
-  MOZ_ASSERT(mWindow || mOwningObject);
-  MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode);
+  MOZ_ASSERT(mGlobal);
 
   CommonFactoryRequestParams commonParams;
 
   PrincipalInfo& principalInfo = commonParams.principalInfo();
 
   if (aPrincipal) {
     if (!NS_IsMainThread()) {
       MOZ_CRASH(
@@ -719,34 +723,22 @@ already_AddRefed<IDBOpenDBRequest> IDBFa
       }
       MOZ_ASSERT(threadLocal);
       MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal);
 
       threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
     }
   }
 
-  RefPtr<IDBOpenDBRequest> request;
-
-  if (mWindow) {
-    JS::Rooted<JSObject*> scriptOwner(
-        aCx, nsGlobalWindowInner::Cast(mWindow.get())->FastGetGlobalJSObject());
-    MOZ_ASSERT(scriptOwner);
-
-    request =
-        IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner);
-  } else {
-    JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject);
-
-    request = IDBOpenDBRequest::CreateForJS(aCx, this, scriptOwner);
-    if (!request) {
-      MOZ_ASSERT(!NS_IsMainThread());
-      aRv.ThrowUncatchableException();
-      return nullptr;
-    }
+  RefPtr<IDBOpenDBRequest> request =
+      IDBOpenDBRequest::Create(aCx, this, mGlobal);
+  if (!request) {
+    MOZ_ASSERT(!NS_IsMainThread());
+    aRv.ThrowUncatchableException();
+    return nullptr;
   }
 
   MOZ_ASSERT(request);
 
   if (aDeleting) {
     IDB_LOG_MARK(
         "IndexedDB %s: Child  Request[%llu]: "
         "indexedDB.deleteDatabase(\"%s\")",
@@ -812,51 +804,49 @@ nsresult IDBFactory::InitiateRequest(IDB
   }
 
   MOZ_ASSERT(actor->GetActorEventTarget(),
              "The event target shall be inherited from its manager actor.");
 
   return NS_OK;
 }
 
-void IDBFactory::DisconnectFromWindow(nsPIDOMWindowInner* aOldWindow) {
-  MOZ_DIAGNOSTIC_ASSERT(aOldWindow);
-  // If CC unlinks us first, then mWindow might be nullptr
-  MOZ_DIAGNOSTIC_ASSERT(!mWindow || mWindow == aOldWindow);
+void IDBFactory::DisconnectFromGlobal(nsIGlobalObject* aOldGlobal) {
+  MOZ_DIAGNOSTIC_ASSERT(aOldGlobal);
+  // If CC unlinks us first, then mGlobal might be nullptr
+  MOZ_DIAGNOSTIC_ASSERT(!mGlobal || mGlobal == aOldGlobal);
 
-  mWindow = nullptr;
+  mGlobal = nullptr;
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBFactory)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-  tmp->mOwningObject = nullptr;
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBFactory)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOwningObject)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 JSObject* IDBFactory::WrapObject(JSContext* aCx,
                                  JS::Handle<JSObject*> aGivenProto) {
   return IDBFactory_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 }  // namespace dom
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -13,16 +13,17 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 
+class nsIGlobalObject;
 class nsIEventTarget;
 class nsIPrincipal;
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 
 class ErrorResult;
 
@@ -53,20 +54,17 @@ class IDBFactory final : public nsISuppo
   typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
 
   class BackgroundCreateCallback;
   struct PendingRequestInfo;
 
   nsAutoPtr<PrincipalInfo> mPrincipalInfo;
 
-  // If this factory lives on a window then mWindow must be non-null. Otherwise
-  // mOwningObject must be non-null.
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-  JS::Heap<JSObject*> mOwningObject;
+  nsCOMPtr<nsIGlobalObject> mGlobal;
 
   // This will only be set if the factory belongs to a window in a child
   // process.
   RefPtr<TabChild> mTabChild;
 
   indexedDB::BackgroundFactoryChild* mBackgroundActor;
 
   // It is either set to a DocGroup-specific EventTarget if created by
@@ -79,22 +77,20 @@ class IDBFactory final : public nsISuppo
 
   bool mBackgroundActorFailed;
   bool mPrivateBrowsingMode;
 
  public:
   static nsresult CreateForWindow(nsPIDOMWindowInner* aWindow,
                                   IDBFactory** aFactory);
 
-  static nsresult CreateForMainThreadJS(JSContext* aCx,
-                                        JS::Handle<JSObject*> aOwningObject,
+  static nsresult CreateForMainThreadJS(nsIGlobalObject* aGlobal,
                                         IDBFactory** aFactory);
 
-  static nsresult CreateForWorker(JSContext* aCx,
-                                  JS::Handle<JSObject*> aOwningObject,
+  static nsresult CreateForWorker(nsIGlobalObject* aGlobal,
                                   const PrincipalInfo& aPrincipalInfo,
                                   uint64_t aInnerWindowID,
                                   IDBFactory** aFactory);
 
   static bool AllowedForWindow(nsPIDOMWindowInner* aWindow);
 
   static bool AllowedForPrincipal(nsIPrincipal* aPrincipal,
                                   bool* aIsSystemPrincipal = nullptr);
@@ -122,17 +118,17 @@ class IDBFactory final : public nsISuppo
   // Increase/Decrease the number of active databases and IDBOpenRequests for
   // the decision making of preemption and throttling.
   // Note: A non-closed database or a pending IDBOpenRequest could block
   // IDB operations in other window.
   void UpdateActiveDatabaseCount(int32_t aDelta);
 
   void IncrementParentLoggingRequestSerialNumber();
 
-  nsPIDOMWindowInner* GetParentObject() const { return mWindow; }
+  nsIGlobalObject* GetParentObject() const { return mGlobal; }
 
   TabChild* GetTabChild() const { return mTabChild; }
 
   PrincipalInfo* GetPrincipalInfo() const {
     AssertIsOnOwningThread();
 
     return mPrincipalInfo;
   }
@@ -173,38 +169,37 @@ class IDBFactory final : public nsISuppo
       const IDBOpenDBOptions& aOptions, SystemCallerGuarantee,
       ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest> DeleteForPrincipal(
       JSContext* aCx, nsIPrincipal* aPrincipal, const nsAString& aName,
       const IDBOpenDBOptions& aOptions, SystemCallerGuarantee,
       ErrorResult& aRv);
 
-  void DisconnectFromWindow(nsPIDOMWindowInner* aOldWindow);
+  void DisconnectFromGlobal(nsIGlobalObject* aOldGlobal);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
 
   // nsWrapperCache
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
  private:
   IDBFactory();
   ~IDBFactory();
 
   static nsresult CreateForMainThreadJSInternal(
-      JSContext* aCx, JS::Handle<JSObject*> aOwningObject,
-      nsAutoPtr<PrincipalInfo>& aPrincipalInfo, IDBFactory** aFactory);
+      nsIGlobalObject* aGlobal, nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
+      IDBFactory** aFactory);
 
-  static nsresult CreateForJSInternal(JSContext* aCx,
-                                      JS::Handle<JSObject*> aOwningObject,
-                                      nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
-                                      uint64_t aInnerWindowID,
-                                      IDBFactory** aFactory);
+  static nsresult CreateInternal(nsIGlobalObject* aGlobal,
+                                 nsAutoPtr<PrincipalInfo>& aPrincipalInfo,
+                                 uint64_t aInnerWindowID,
+                                 IDBFactory** aFactory);
 
   static nsresult AllowedForWindowInternal(nsPIDOMWindowInner* aWindow,
                                            nsIPrincipal** aPrincipal);
 
   already_AddRefed<IDBOpenDBRequest> OpenInternal(
       JSContext* aCx, nsIPrincipal* aPrincipal, const nsAString& aName,
       const Optional<uint64_t>& aVersion,
       const Optional<StorageType>& aStorageType, bool aDeleting,
--- a/dom/indexedDB/IDBFileHandle.h
+++ b/dom/indexedDB/IDBFileHandle.h
@@ -11,18 +11,16 @@
 #include "js/TypeDecls.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/FileModeBinding.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIRunnable.h"
 #include "nsWeakReference.h"
 
-class nsPIDOMWindowInner;
-
 namespace mozilla {
 namespace dom {
 
 class Blob;
 class FileRequestData;
 class FileRequestParams;
 struct IDBFileMetadataParameters;
 class IDBFileRequest;
@@ -107,21 +105,16 @@ class IDBFileHandle final : public DOMEv
   bool IsAborted() const {
     AssertIsOnOwningThread();
     return mAborted;
   }
 
   void Abort();
 
   // WebIDL
-  nsPIDOMWindowInner* GetParentObject() const {
-    AssertIsOnOwningThread();
-    return GetOwner();
-  }
-
   IDBMutableFile* GetMutableFile() const {
     AssertIsOnOwningThread();
     return mMutableFile;
   }
 
   IDBMutableFile* GetFileHandle() const {
     AssertIsOnOwningThread();
     return GetMutableFile();
--- a/dom/indexedDB/IDBFileRequest.cpp
+++ b/dom/indexedDB/IDBFileRequest.cpp
@@ -21,17 +21,17 @@
 
 namespace mozilla {
 namespace dom {
 
 using namespace mozilla::dom::indexedDB;
 
 IDBFileRequest::IDBFileRequest(IDBFileHandle* aFileHandle,
                                bool aWrapAsDOMRequest)
-    : DOMRequest(aFileHandle->GetOwner()),
+    : DOMRequest(aFileHandle->GetOwnerGlobal()),
       mFileHandle(aFileHandle),
       mWrapAsDOMRequest(aWrapAsDOMRequest),
       mHasEncoding(false) {
   MOZ_ASSERT(aFileHandle);
   aFileHandle->AssertIsOnOwningThread();
 }
 
 IDBFileRequest::~IDBFileRequest() { AssertIsOnOwningThread(); }
@@ -67,17 +67,17 @@ void IDBFileRequest::FireProgressEvent(u
   DispatchTrustedEvent(event);
 }
 
 void IDBFileRequest::SetResultCallback(ResultCallback* aCallback) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aCallback);
 
   AutoJSAPI autoJS;
-  if (NS_WARN_IF(!autoJS.Init(GetOwner()))) {
+  if (NS_WARN_IF(!autoJS.Init(GetOwnerGlobal()))) {
     FireError(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     return;
   }
 
   JSContext* cx = autoJS.cx();
 
   JS::Rooted<JS::Value> result(cx);
   nsresult rv = aCallback->GetResult(cx, &result);
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -233,17 +233,17 @@ const nsCString& IDBIndex::Locale() cons
 
 bool IDBIndex::IsAutoLocale() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mMetadata);
 
   return mMetadata->autoLocale();
 }
 
-nsPIDOMWindowInner* IDBIndex::GetParentObject() const {
+nsIGlobalObject* IDBIndex::GetParentObject() const {
   AssertIsOnOwningThread();
 
   return mObjectStore->GetParentObject();
 }
 
 void IDBIndex::GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                           ErrorResult& aRv) {
   AssertIsOnOwningThread();
--- a/dom/indexedDB/IDBIndex.h
+++ b/dom/indexedDB/IDBIndex.h
@@ -11,17 +11,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/IDBCursorBinding.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsTArrayForwardDeclare.h"
 #include "nsWrapperCache.h"
 
-class nsPIDOMWindowInner;
+class nsIGlobalObject;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 class IDBObjectStore;
@@ -78,17 +78,17 @@ class IDBIndex final : public nsISupport
 
   bool IsAutoLocale() const;
 
   IDBObjectStore* ObjectStore() const {
     AssertIsOnOwningThread();
     return mObjectStore;
   }
 
-  nsPIDOMWindowInner* GetParentObject() const;
+  nsIGlobalObject* GetParentObject() const;
 
   void GetName(nsString& aName) const { aName = Name(); }
 
   void SetName(const nsAString& aName, ErrorResult& aRv);
 
   void GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                   ErrorResult& aRv);
 
--- a/dom/indexedDB/IDBMutableFile.h
+++ b/dom/indexedDB/IDBMutableFile.h
@@ -12,18 +12,16 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/FileModeBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsHashKeys.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 
-class nsPIDOMWindowInner;
-
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 class DOMRequest;
 class File;
@@ -100,18 +98,16 @@ class IDBMutableFile final : public DOME
 
   void RegisterFileHandle(IDBFileHandle* aFileHandle);
 
   void UnregisterFileHandle(IDBFileHandle* aFileHandle);
 
   void AbortFileHandles();
 
   // WebIDL
-  nsPIDOMWindowInner* GetParentObject() const { return GetOwner(); }
-
   void GetName(nsString& aName) const { aName = mName; }
 
   void GetType(nsString& aType) const { aType = mType; }
 
   IDBDatabase* Database() const;
 
   already_AddRefed<IDBFileHandle> Open(FileMode aMode, ErrorResult& aError);
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1864,17 +1864,17 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTING_AD