Merge autoland to mozilla-central. a=merge
authorOana Pop Rus <opoprus@mozilla.com>
Fri, 15 Mar 2019 18:31:40 +0200
changeset 522072 79995994a23fe694827bbbc3ec3f7b7819c8c6f2
parent 522067 5edbe9b1b82220b07ff446bd4a3b9ff2f7dda508 (current diff)
parent 522032 6343f4a4d75eca45559003206bce65c8c3c14f3e (diff)
child 522073 8ae5bb51b14199227e03a37b0bdd3b35f1f4d01e
push id10871
push usercbrindusan@mozilla.com
push dateMon, 18 Mar 2019 15:49:32 +0000
treeherdermozilla-beta@018abdd16060 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.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
--- a/browser/components/extensions/test/browser/browser_ext_search.js
+++ b/browser/components/extensions/test/browser/browser_ext_search.js
@@ -34,17 +34,17 @@ add_task(async function test_search() {
     browser.test.sendMessage("engines", engines);
 
     // Search with no tabId
     browser.search.search({query: SEARCH_TERM + "1", engine: "Search Test"});
     let result = await awaitSearchResult();
     browser.test.sendMessage("searchLoaded", result.url);
 
     // Search with tabId
-    let tab = await browser.tabs.create({});
+    let tab = await browser.tabs.create({url: "about:blank"});
     browser.search.search({query: SEARCH_TERM + "2", engine: "Search Test",
                            tabId: tab.id});
     result = await awaitSearchResult();
     browser.test.assertEq(result.tabId, tab.id, "Page loaded in right tab");
     browser.test.sendMessage("searchLoaded", result.url);
   }
 
   let extension = ExtensionTestUtils.loadExtension({
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -143,17 +143,17 @@ function PreviewController(win, tab) {
   this.win = win;
   this.tab = tab;
   this.linkedBrowser = tab.linkedBrowser;
   this.preview = this.win.createTabPreview(this);
 
   this.tab.addEventListener("TabAttrModified", this);
 
   XPCOMUtils.defineLazyGetter(this, "canvasPreview", function() {
-    let canvas = PageThumbs.createCanvas();
+    let canvas = PageThumbs.createCanvas(this.win);
     canvas.mozOpaque = true;
     return canvas;
   });
 }
 
 PreviewController.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsITaskbarPreviewController]),
 
@@ -265,17 +265,17 @@ PreviewController.prototype = {
    */
   requestPreview(aTaskbarCallback) {
     // Grab a high res content preview
     this.resetCanvasPreview();
     this.updateCanvasPreview(true, (aPreviewCanvas) => {
       let winWidth = this.win.width;
       let winHeight = this.win.height;
 
-      let composite = PageThumbs.createCanvas();
+      let composite = PageThumbs.createCanvas(this.win);
 
       // Use transparency, Aero glass is drawn black without it.
       composite.mozOpaque = false;
 
       let ctx = composite.getContext("2d");
       let scale = this.screenPixelsPerCSSPixel / this.zoom;
 
       composite.width = winWidth * scale;
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -57,16 +57,17 @@
 #include "nsIResProtocolHandler.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Components.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/NullPrincipal.h"
 #include <stdint.h>
+#include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsILoadInfo.h"
@@ -284,36 +285,17 @@ static void InheritAndSetCSPOnPrincipalI
 
   // if the principalToInherit had a CSP, add it to the before
   // created NullPrincipal (unless it already has one)
   MOZ_ASSERT(aPrincipal->GetIsNullPrincipal(),
              "inheriting the CSP only valid for NullPrincipal");
   nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP;
   aPrincipal->GetCsp(getter_AddRefs(nullPrincipalCSP));
   if (nullPrincipalCSP) {
-#ifdef DEBUG
-    {
-      uint32_t nullPrincipalCSPCount = 0;
-      nullPrincipalCSP->GetPolicyCount(&nullPrincipalCSPCount);
-
-      uint32_t originalCSPCount = 0;
-      originalCSP->GetPolicyCount(&originalCSPCount);
-
-      MOZ_ASSERT(nullPrincipalCSPCount == originalCSPCount,
-                 "There should be no other CSP here.");
-
-      nsAutoString nullPrincipalCSPStr, originalCSPStr;
-      for (uint32_t i = 0; i < originalCSPCount; ++i) {
-        originalCSP->GetPolicyString(i, originalCSPStr);
-        nullPrincipalCSP->GetPolicyString(i, nullPrincipalCSPStr);
-        MOZ_ASSERT(originalCSPStr.Equals(nullPrincipalCSPStr),
-                   "There should be no other CSP string here.");
-      }
-    }
-#endif
+    MOZ_ASSERT(nsCSPContext::Equals(originalCSP, nullPrincipalCSP));
     // CSPs are equal, no need to set it again.
     return;
   }
 
   // After 965637 all that magical CSP inheritance goes away. For now,
   // we have to create a clone of the current CSP and have to manually
   // set it on the Principal.
   uint32_t count = 0;
--- a/devtools/client/webconsole/webconsole-ui.js
+++ b/devtools/client/webconsole/webconsole-ui.js
@@ -283,18 +283,18 @@ class WebConsoleUI {
 
       shortcuts.on(l10n.getStr("webconsole.close.key"),
                    this.window.top.close.bind(this.window.top));
 
       ZoomKeys.register(this.window);
       shortcuts.on("CmdOrCtrl+Alt+R", quickRestart);
     } else if (Services.prefs.getBoolPref(PREF_SIDEBAR_ENABLED)) {
       shortcuts.on("Esc", event => {
-        if (!this.jsterm.autocompletePopup || !this.jsterm.autocompletePopup.isOpen) {
-          this.wrapper.dispatchSidebarClose();
+        this.wrapper.dispatchSidebarClose();
+        if (this.jsterm) {
           this.jsterm.focus();
         }
       });
     }
   }
 
   /**
    * Handler for page location changes.
@@ -333,17 +333,21 @@ class WebConsoleUI {
   }
 
   /**
    * Sets the focus to JavaScript input field when the web console tab is
    * selected or when there is a split console present.
    * @private
    */
   _onPanelSelected() {
-    this.jsterm.focus();
+    // We can only focus when we have the jsterm reference. This is fine because if the
+    // jsterm is not mounted yet, it will be focused in JSTerm's componentDidMount.
+    if (this.jsterm) {
+      this.jsterm.focus();
+    }
   }
 
   _onChangeSplitConsoleState() {
     this.wrapper.dispatchSplitConsoleCloseButtonToggle();
   }
 
   /**
    * Handler for the tabNavigated notification.
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -54,16 +54,17 @@
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ServiceWorkerInterceptController.h"
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/dom/SessionStorageManager.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/ChildSHistory.h"
+#include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
 
 #include "mozilla/net/ReferrerPolicy.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "ReferrerInfo.h"
 
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
@@ -9907,44 +9908,19 @@ nsresult nsDocShell::DoURILoad(nsDocShel
   }
 
   // Navigational requests that are same origin need to be upgraded in case
   // upgrade-insecure-requests is present. Please note that in that case
   // the triggeringPrincipal is holding the CSP that potentially
   // holds upgrade-insecure-requests.
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   aLoadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
-
 #ifdef DEBUG
-  {
-    // After Bug 965637 we move the CSP from the Principal into the Client,
-    // hence we need an explicit CSP argument passed to docshell. Let's make
-    // sure the explicit CSP is the same as the CSP on the Principal.
-    uint32_t principalCSPCount = 0;
-    if (csp) {
-      csp->GetPolicyCount(&principalCSPCount);
-    }
-
-    nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
-    uint32_t argCSPCount = 0;
-    if (argsCSP) {
-      argsCSP->GetPolicyCount(&argCSPCount);
-    }
-
-    MOZ_ASSERT(principalCSPCount == argCSPCount,
-               "Different PolicyCount for CSP as arg and Principal");
-
-    nsAutoString principalPolicyStr, argPolicyStr;
-    for (uint32_t i = 0; i < principalCSPCount; ++i) {
-      csp->GetPolicyString(i, principalPolicyStr);
-      argsCSP->GetPolicyString(i, argPolicyStr);
-      MOZ_ASSERT(principalPolicyStr.Equals(argPolicyStr),
-                 "Different PolicyStr for CSP as arg and Principal");
-    }
-  }
+  nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
+  MOZ_ASSERT(nsCSPContext::Equals(csp, argsCSP));
 #endif
 
   if (csp) {
     bool upgradeInsecureRequests = false;
     csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
     if (upgradeInsecureRequests) {
       // only upgrade if the navigation is same origin
       nsCOMPtr<nsIPrincipal> resultPrincipal;
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -368,16 +368,20 @@ nsresult WebMDemuxer::ReadMetadata() {
                             mInfo.mVideo.mCrypto.mKeyId);
       }
     } else if (type == NESTEGG_TRACK_AUDIO && !mHasAudio) {
       nestegg_audio_params params;
       r = nestegg_track_audio_params(context, track, &params);
       if (r == -1) {
         return NS_ERROR_FAILURE;
       }
+      if (params.rate > AudioInfo::MAX_RATE ||
+          params.channels > AudioConfig::ChannelLayout::MAX_CHANNELS) {
+        return NS_ERROR_DOM_MEDIA_METADATA_ERR;
+      }
 
       mAudioTrack = track;
       mHasAudio = true;
       mAudioCodec = nestegg_track_codec_id(context, track);
       if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
         mInfo.mAudio.mMimeType = "audio/vorbis";
       } else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
         mInfo.mAudio.mMimeType = "audio/opus";
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -248,16 +248,50 @@ nsCSPContext::nsCSPContext()
 
 nsCSPContext::~nsCSPContext() {
   CSPCONTEXTLOG(("nsCSPContext::~nsCSPContext"));
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     delete mPolicies[i];
   }
 }
 
+/* static */
+bool nsCSPContext::Equals(nsIContentSecurityPolicy* aCSP,
+                          nsIContentSecurityPolicy* aOtherCSP) {
+  if (aCSP == aOtherCSP) {
+    // fast path for pointer equality
+    return true;
+  }
+
+  uint32_t policyCount = 0;
+  if (aCSP) {
+    aCSP->GetPolicyCount(&policyCount);
+  }
+
+  uint32_t otherPolicyCount = 0;
+  if (aOtherCSP) {
+    aOtherCSP->GetPolicyCount(&otherPolicyCount);
+  }
+
+  if (policyCount != otherPolicyCount) {
+    return false;
+  }
+
+  nsAutoString policyStr, otherPolicyStr;
+  for (uint32_t i = 0; i < policyCount; ++i) {
+    aCSP->GetPolicyString(i, policyStr);
+    aOtherCSP->GetPolicyString(i, otherPolicyStr);
+    if (!policyStr.Equals(otherPolicyStr)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 nsresult nsCSPContext::InitFromOther(nsCSPContext* aOtherContext,
                                      Document* aDoc, nsIPrincipal* aPrincipal) {
   NS_ENSURE_ARG(aOtherContext);
 
   nsresult rv = SetRequestContext(aDoc, aPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (auto policy : aOtherContext->mPolicies) {
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -49,16 +49,19 @@ class nsCSPContext : public nsIContentSe
   NS_DECL_NSISERIALIZABLE
 
  protected:
   virtual ~nsCSPContext();
 
  public:
   nsCSPContext();
 
+  static bool Equals(nsIContentSecurityPolicy* aCSP,
+                     nsIContentSecurityPolicy* aOtherCSP);
+
   nsresult InitFromOther(nsCSPContext* otherContext,
                          mozilla::dom::Document* aDoc,
                          nsIPrincipal* aPrincipal);
 
   void SetIPCPolicies(
       const nsTArray<mozilla::ipc::ContentSecurityPolicy>& policies);
 
   /**
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -6,16 +6,17 @@
 
 #include <string.h>  // for nullptr, strcmp
 
 #include "imgIContainer.h"                    // for imgIContainer, etc
 #include "mozilla/ComposerCommandsUpdater.h"  // for ComposerCommandsUpdater
 #include "mozilla/FlushType.h"                // for FlushType::Frames
 #include "mozilla/HTMLEditor.h"               // for HTMLEditor
 #include "mozilla/mozalloc.h"                 // for operator new
+#include "mozilla/PresShell.h"                // for PresShell
 #include "nsAString.h"
 #include "nsComponentManagerUtils.h"  // for do_CreateInstance
 #include "nsContentUtils.h"
 #include "nsDebug.h"  // for NS_ENSURE_SUCCESS, etc
 #include "nsEditingSession.h"
 #include "nsError.h"               // for NS_ERROR_FAILURE, NS_OK, etc
 #include "nsIChannel.h"            // for nsIChannel
 #include "nsICommandManager.h"     // for nsICommandManager
@@ -28,17 +29,16 @@
 #include "nsIDOMWindow.h"          // for nsIDOMWindow
 #include "nsIDocShell.h"           // for nsIDocShell
 #include "mozilla/dom/Document.h"  // for Document
 #include "nsIDocumentStateListener.h"
 #include "nsIEditor.h"                   // for nsIEditor
 #include "nsIHTMLDocument.h"             // for nsIHTMLDocument, etc
 #include "nsIInterfaceRequestorUtils.h"  // for do_GetInterface
 #include "nsIPlaintextEditor.h"          // for nsIPlaintextEditor, etc
-#include "nsIPresShell.h"                // for nsIPresShell
 #include "nsIRefreshURI.h"               // for nsIRefreshURI
 #include "nsIRequest.h"                  // for nsIRequest
 #include "nsITimer.h"                    // for nsITimer, etc
 #include "nsITransactionManager.h"       // for nsITransactionManager
 #include "nsIWeakReference.h"            // for nsISupportsWeakReference, etc
 #include "nsIWebNavigation.h"            // for nsIWebNavigation
 #include "nsIWebProgress.h"              // for nsIWebProgress, etc
 #include "nsLiteralString.h"             // for NS_LITERAL_STRING
@@ -361,18 +361,21 @@ nsEditingSession::SetupEditorOnWindow(mo
     mComposerCommandsUpdater->NotifyDocumentCreated();
     return NS_ERROR_FAILURE;
   }
 
   // Create editor and do other things
   //  only if we haven't found some error above,
   nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
-  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+  RefPtr<PresShell> presShell =
+      static_cast<PresShell*>(docShell->GetPresShell());
+  if (NS_WARN_IF(!presShell)) {
+    return NS_ERROR_FAILURE;
+  }
 
   if (!mInteractive) {
     // Disable animation of images in this document:
     nsPresContext* presContext = presShell->GetPresContext();
     NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
     mImageAnimationMode = presContext->ImageAnimationMode();
     presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
@@ -1198,18 +1201,21 @@ void nsEditingSession::RemoveWebProgress
 
 void nsEditingSession::RestoreAnimationMode(nsPIDOMWindowOuter* aWindow) {
   if (mInteractive) {
     return;
   }
 
   nsCOMPtr<nsIDocShell> docShell = aWindow ? aWindow->GetDocShell() : nullptr;
   NS_ENSURE_TRUE_VOID(docShell);
-  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
-  NS_ENSURE_TRUE_VOID(presShell);
+  RefPtr<PresShell> presShell =
+      static_cast<PresShell*>(docShell->GetPresShell());
+  if (NS_WARN_IF(!presShell)) {
+    return;
+  }
   nsPresContext* presContext = presShell->GetPresContext();
   NS_ENSURE_TRUE_VOID(presContext);
 
   presContext->SetImageAnimationMode(mImageAnimationMode);
 }
 
 nsresult nsEditingSession::DetachFromWindow(mozIDOMWindowProxy* aWindow) {
   NS_ENSURE_TRUE(mDoneSetup, NS_OK);
@@ -1286,18 +1292,21 @@ nsresult nsEditingSession::ReattachToWin
   // Get editor
   RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorForWindow(aWindow);
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   if (!mInteractive) {
     // Disable animation of images in this document:
-    nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
-    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+    RefPtr<PresShell> presShell =
+        static_cast<PresShell*>(docShell->GetPresShell());
+    if (NS_WARN_IF(!presShell)) {
+      return NS_ERROR_FAILURE;
+    }
     nsPresContext* presContext = presShell->GetPresContext();
     NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
     mImageAnimationMode = presContext->ImageAnimationMode();
     presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
   }
 
   // The third controller takes an nsIEditor as the context
--- a/editor/libeditor/CompositionTransaction.cpp
+++ b/editor/libeditor/CompositionTransaction.cpp
@@ -8,18 +8,18 @@
 #include "mozilla/EditorBase.h"       // mEditorBase
 #include "mozilla/SelectionState.h"   // RangeUpdater
 #include "mozilla/TextComposition.h"  // TextComposition
 #include "mozilla/dom/Selection.h"    // local var
 #include "mozilla/dom/Text.h"         // mTextNode
 #include "nsAString.h"                // params
 #include "nsDebug.h"                  // for NS_ASSERTION, etc
 #include "nsError.h"                  // for NS_SUCCEEDED, NS_FAILED, etc
-#include "nsIPresShell.h"             // nsISelectionController constants
 #include "nsRange.h"                  // local var
+#include "nsISelectionController.h"   // for nsISelectionController constants
 #include "nsQueryObject.h"            // for do_QueryObject
 
 namespace mozilla {
 
 using namespace dom;
 
 // static
 already_AddRefed<CompositionTransaction> CompositionTransaction::Create(
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -36,16 +36,17 @@
 #include "mozilla/EditTransactionBase.h"    // for EditTransactionBase
 #include "mozilla/FlushType.h"              // for FlushType::Frames
 #include "mozilla/IMEContentObserver.h"     // for IMEContentObserver
 #include "mozilla/IMEStateManager.h"        // for IMEStateManager
 #include "mozilla/mozalloc.h"               // for operator new, etc.
 #include "mozilla/mozInlineSpellChecker.h"  // for mozInlineSpellChecker
 #include "mozilla/mozSpellChecker.h"        // for mozSpellChecker
 #include "mozilla/Preferences.h"            // for Preferences
+#include "mozilla/PresShell.h"              // for PresShell
 #include "mozilla/RangeBoundary.h"      // for RawRangeBoundary, RangeBoundary
 #include "mozilla/dom/Selection.h"      // for Selection, etc.
 #include "mozilla/Services.h"           // for GetObserverService
 #include "mozilla/ServoCSSParser.h"     // for ServoCSSParser
 #include "mozilla/TextComposition.h"    // for TextComposition
 #include "mozilla/TextInputListener.h"  // for TextInputListener
 #include "mozilla/TextServicesDocument.h"  // for TextServicesDocument
 #include "mozilla/TextEvents.h"
@@ -82,17 +83,16 @@
 #include "nsIEditorObserver.h"         // for nsIEditorObserver
 #include "nsIEditorSpellCheck.h"       // for nsIEditorSpellCheck
 #include "nsIFrame.h"                  // for nsIFrame
 #include "nsIHTMLDocument.h"           // for nsIHTMLDocument
 #include "nsIInlineSpellChecker.h"     // for nsIInlineSpellChecker, etc.
 #include "nsNameSpaceManager.h"        // for kNameSpaceID_None, etc.
 #include "nsINode.h"                   // for nsINode, etc.
 #include "nsIPlaintextEditor.h"        // for nsIPlaintextEditor, etc.
-#include "nsIPresShell.h"              // for nsIPresShell
 #include "nsISelectionController.h"    // for nsISelectionController, etc.
 #include "nsISelectionDisplay.h"       // for nsISelectionDisplay, etc.
 #include "nsISupportsBase.h"           // for nsISupports
 #include "nsISupportsUtils.h"          // for NS_ADDREF, NS_IF_ADDREF
 #include "nsITransferable.h"           // for nsITransferable
 #include "nsITransaction.h"            // for nsITransaction
 #include "nsITransactionManager.h"
 #include "nsIWeakReference.h"  // for nsISupportsWeakReference
@@ -256,18 +256,17 @@ nsresult EditorBase::Init(Document& aDoc
   // HTML editors currently don't have their own selection controller,
   // so they'll pass null as aSelCon, and we'll get the selection controller
   // off of the presshell.
   nsCOMPtr<nsISelectionController> selectionController;
   if (aSelectionController) {
     mSelectionController = aSelectionController;
     selectionController = aSelectionController;
   } else {
-    nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-    selectionController = do_QueryInterface(presShell);
+    selectionController = GetPresShell();
   }
   MOZ_ASSERT(selectionController,
              "Selection controller should be available at this point");
 
   if (mEditActionData) {
     // During edit action, selection is cached. But this selection is invalid
     // now since selection controller is updated, so we have to update this
     // cache.
@@ -445,17 +444,17 @@ bool EditorBase::GetDesiredSpellCheckSta
   if (!spellcheckLevel) {
     return false;  // Spellchecking forced off globally
   }
 
   if (!CanEnableSpellCheck()) {
     return false;
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  PresShell* presShell = GetPresShell();
   if (presShell) {
     nsPresContext* context = presShell->GetPresContext();
     if (context && !context->IsDynamic()) {
       return false;
     }
   }
 
   // Check DOM state
@@ -637,21 +636,21 @@ EditorBase::GetIsDocumentEditable(bool* 
 
 NS_IMETHODIMP
 EditorBase::GetDocument(Document** aDoc) {
   NS_IF_ADDREF(*aDoc = mDocument);
   return *aDoc ? NS_OK : NS_ERROR_NOT_INITIALIZED;
 }
 
 already_AddRefed<nsIWidget> EditorBase::GetWidget() {
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
-  NS_ENSURE_TRUE(ps, nullptr);
-  nsPresContext* pc = ps->GetPresContext();
-  NS_ENSURE_TRUE(pc, nullptr);
-  nsCOMPtr<nsIWidget> widget = pc->GetRootWidget();
+  nsPresContext* presContext = GetPresContext();
+  if (NS_WARN_IF(!presContext)) {
+    return nullptr;
+  }
+  nsCOMPtr<nsIWidget> widget = presContext->GetRootWidget();
   NS_ENSURE_TRUE(widget.get(), nullptr);
   return widget.forget();
 }
 
 NS_IMETHODIMP
 EditorBase::GetContentsMIMEType(char** aContentsMIMEType) {
   NS_ENSURE_ARG_POINTER(aContentsMIMEType);
   *aContentsMIMEType = ToNewCString(mContentMIMEType);
@@ -2945,19 +2944,19 @@ void EditorBase::DoSplitNode(const Edito
     }
   }
 
   // XXX Why do we ignore an error while moving nodes from the right node to
   //     the left node?
   aError.SuppressException();
 
   // Handle selection
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
-  if (ps) {
-    ps->FlushPendingNotifications(FlushType::Frames);
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (presShell) {
+    presShell->FlushPendingNotifications(FlushType::Frames);
   }
   NS_WARNING_ASSERTION(!Destroyed(),
                        "The editor is destroyed during splitting a node");
 
   bool allowedTransactionsToChangeSelection =
       AllowsTransactionsToChangeSelection();
 
   RefPtr<Selection> previousSelection;
@@ -4374,29 +4373,24 @@ nsresult EditorBase::InitializeSelection
   if (NS_WARN_IF(!targetNode)) {
     return NS_ERROR_INVALID_ARG;
   }
   nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
   if (!selectionRootContent) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-  if (NS_WARN_IF(!presShell)) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
   nsCOMPtr<nsISelectionController> selectionController =
       GetSelectionController();
   if (NS_WARN_IF(!selectionController)) {
     return NS_ERROR_FAILURE;
   }
 
   // Init the caret
-  RefPtr<nsCaret> caret = presShell->GetCaret();
+  RefPtr<nsCaret> caret = GetCaret();
   if (NS_WARN_IF(!caret)) {
     return NS_ERROR_FAILURE;
   }
   caret->SetSelection(SelectionRefPtr());
   selectionController->SetCaretReadOnly(IsReadonly());
   selectionController->SetCaretEnabled(true);
   // NOTE(emilio): It's important for this call to be after
   // SetCaretEnabled(true), since that would override mIgnoreUserModify to true.
@@ -4477,22 +4471,21 @@ nsresult EditorBase::FinalizeSelection()
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   SelectionRefPtr()->SetAncestorLimiter(nullptr);
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-  if (NS_WARN_IF(!presShell)) {
+  if (NS_WARN_IF(!GetPresShell())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  if (RefPtr<nsCaret> caret = presShell->GetCaret()) {
+  if (RefPtr<nsCaret> caret = GetCaret()) {
     caret->SetIgnoreUserModify(true);
   }
 
   selectionController->SetCaretEnabled(false);
 
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (NS_WARN_IF(!fm)) {
     return NS_ERROR_NOT_INITIALIZED;
@@ -4860,20 +4853,20 @@ int32_t EditorBase::GetIMESelectionStart
   return minOffset < INT32_MAX ? minOffset : -1;
 }
 
 void EditorBase::HideCaret(bool aHide) {
   if (mHidingCaret == aHide) {
     return;
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-  NS_ENSURE_TRUE_VOID(presShell);
-  RefPtr<nsCaret> caret = presShell->GetCaret();
-  NS_ENSURE_TRUE_VOID(caret);
+  RefPtr<nsCaret> caret = GetCaret();
+  if (NS_WARN_IF(!caret)) {
+    return;
+  }
 
   mHidingCaret = aHide;
   if (aHide) {
     caret->AddForceHide();
   } else {
     caret->RemoveForceHide();
   }
 }
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -35,22 +35,22 @@
 #include "nsLiteralString.h"         // for NS_LITERAL_STRING
 #include "nsString.h"                // for nsCString
 #include "nsTArray.h"                // for nsTArray and nsAutoTArray
 #include "nsWeakReference.h"         // for nsSupportsWeakReference
 #include "nscore.h"                  // for nsresult, nsAString, etc.
 
 class mozInlineSpellChecker;
 class nsAtom;
+class nsCaret;
 class nsIContent;
 class nsIDocumentStateListener;
 class nsIEditActionListener;
 class nsIEditorObserver;
 class nsINode;
-class nsIPresShell;
 class nsISupports;
 class nsITransferable;
 class nsITransaction;
 class nsITransactionListener;
 class nsIWidget;
 class nsRange;
 
 namespace mozilla {
@@ -72,16 +72,17 @@ class EditTransactionBase;
 class ErrorResult;
 class HTMLEditor;
 class HTMLEditUtils;
 class IMEContentObserver;
 class InsertNodeTransaction;
 class InsertTextTransaction;
 class JoinNodeTransaction;
 class PlaceholderTransaction;
+class PresShell;
 class SplitNodeResult;
 class SplitNodeTransaction;
 class TextComposition;
 class TextEditor;
 class TextEditRules;
 class TextInputListener;
 class TextServicesDocument;
 class TypeInState;
@@ -189,39 +190,41 @@ class EditorBase : public nsIEditor,
    */
   virtual void PreDestroy(bool aDestroyingFrames);
 
   bool IsInitialized() const { return !!mDocument; }
   bool Destroyed() const { return mDidPreDestroy; }
 
   Document* GetDocument() const { return mDocument; }
 
-  nsIPresShell* GetPresShell() const {
-    return mDocument ? mDocument->GetShell() : nullptr;
+  PresShell* GetPresShell() const {
+    return mDocument ? static_cast<PresShell*>(mDocument->GetShell()) : nullptr;
   }
   nsPresContext* GetPresContext() const {
-    nsIPresShell* presShell = GetPresShell();
+    PresShell* presShell = GetPresShell();
     return presShell ? presShell->GetPresContext() : nullptr;
   }
+  already_AddRefed<nsCaret> GetCaret() const {
+    PresShell* presShell = GetPresShell();
+    if (NS_WARN_IF(!presShell)) {
+      return nullptr;
+    }
+    return presShell->GetCaret();
+  }
 
   already_AddRefed<nsIWidget> GetWidget();
 
   nsISelectionController* GetSelectionController() const {
     if (mSelectionController) {
       return mSelectionController;
     }
     if (!mDocument) {
       return nullptr;
     }
-    nsIPresShell* presShell = mDocument->GetShell();
-    if (!presShell) {
-      return nullptr;
-    }
-    nsISelectionController* sc = static_cast<PresShell*>(presShell);
-    return sc;
+    return static_cast<PresShell*>(mDocument->GetShell());
   }
 
   nsresult GetSelection(SelectionType aSelectionType,
                         Selection** aSelection) const;
 
   Selection* GetSelection(
       SelectionType aSelectionType = SelectionType::eNormal) const {
     if (aSelectionType == SelectionType::eNormal &&
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc.
 #include "mozilla/AutoRestore.h"
 #include "mozilla/ContentEvents.h"         // for InternalFocusEvent
 #include "mozilla/EditorBase.h"            // for EditorBase, etc.
 #include "mozilla/EventListenerManager.h"  // for EventListenerManager
 #include "mozilla/EventStateManager.h"     // for EventStateManager
 #include "mozilla/IMEStateManager.h"       // for IMEStateManager
 #include "mozilla/Preferences.h"           // for Preferences
+#include "mozilla/PresShell.h"             // for PresShell
 #include "mozilla/TextEditor.h"            // for TextEditor
 #include "mozilla/TextEvents.h"            // for WidgetCompositionEvent
 #include "mozilla/dom/Element.h"           // for Element
 #include "mozilla/dom/Event.h"             // for Event
 #include "mozilla/dom/EventTarget.h"       // for EventTarget
 #include "mozilla/dom/MouseEvent.h"        // for MouseEvent
 #include "mozilla/dom/Selection.h"
 #include "nsAString.h"
@@ -33,17 +34,16 @@
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DragEvent.h"
 #include "mozilla/dom/Document.h"    // for Document
 #include "nsIFocusManager.h"         // for nsIFocusManager
 #include "nsIFormControl.h"          // for nsIFormControl, etc.
 #include "nsINode.h"                 // for nsINode, ::NODE_IS_EDITABLE, etc.
 #include "nsIPlaintextEditor.h"      // for nsIPlaintextEditor, etc.
-#include "nsIPresShell.h"            // for nsIPresShell
 #include "nsISelectionController.h"  // for nsISelectionController, etc.
 #include "nsITransferable.h"         // for kFileMime, kHTMLMime, etc.
 #include "nsIWidget.h"               // for nsIWidget
 #include "nsLiteralString.h"         // for NS_LITERAL_STRING
 #include "nsPIWindowRoot.h"          // for nsPIWindowRoot
 #include "nsPrintfCString.h"         // for nsPrintfCString
 #include "nsRange.h"
 #include "nsServiceManagerUtils.h"  // for do_GetService
@@ -249,23 +249,23 @@ void EditorEventListener::UninstallFromE
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("text"),
                                   TrustedEventsAtSystemGroupBubble());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("compositionstart"),
                                   TrustedEventsAtSystemGroupBubble());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("compositionend"),
                                   TrustedEventsAtSystemGroupBubble());
 }
 
-nsIPresShell* EditorEventListener::GetPresShell() const {
+PresShell* EditorEventListener::GetPresShell() const {
   MOZ_ASSERT(!DetachedFromEditor());
   return mEditorBase->GetPresShell();
 }
 
 nsPresContext* EditorEventListener::GetPresContext() const {
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  PresShell* presShell = GetPresShell();
   return presShell ? presShell->GetPresContext() : nullptr;
 }
 
 nsIContent* EditorEventListener::GetFocusedRootContent() {
   MOZ_ASSERT(!DetachedFromEditor());
   nsCOMPtr<nsIContent> focusedContent = mEditorBase->GetFocusedContent();
   if (!focusedContent) {
     return nullptr;
@@ -553,20 +553,24 @@ nsresult EditorEventListener::KeyPress(W
   if (!ShouldHandleNativeKeyBindings(aKeyboardEvent)) {
     return NS_OK;
   }
 
   // Now, ask the native key bindings to handle the event.
   nsIWidget* widget = aKeyboardEvent->mWidget;
   // If the event is created by chrome script, the widget is always nullptr.
   if (!widget) {
-    nsCOMPtr<nsIPresShell> ps = GetPresShell();
-    nsPresContext* pc = ps ? ps->GetPresContext() : nullptr;
-    widget = pc ? pc->GetNearestWidget() : nullptr;
-    NS_ENSURE_TRUE(widget, NS_OK);
+    nsPresContext* presContext = GetPresContext();
+    if (NS_WARN_IF(!presContext)) {
+      return NS_OK;
+    }
+    widget = presContext->GetNearestWidget();
+    if (NS_WARN_IF(!widget)) {
+      return NS_OK;
+    }
   }
 
   RefPtr<Document> doc = editorBase->GetDocument();
 
   // WidgetKeyboardEvent::ExecuteEditCommands() requires non-nullptr mWidget.
   // If the event is created by chrome script, it is nullptr but we need to
   // execute native key bindings.  Therefore, we need to set widget to
   // WidgetEvent::mWidget temporarily.
@@ -625,17 +629,17 @@ nsresult EditorEventListener::MouseClick
   //     though this makes web apps cannot prevent middle click paste with
   //     calling preventDefault() of "click" nor "auxclick".
 
   if (aMouseClickEvent->button != WidgetMouseEventBase::eMiddleButton ||
       !WidgetMouseEvent::IsMiddleClickPasteEnabled()) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (NS_WARN_IF(!presShell)) {
     return NS_OK;
   }
   nsPresContext* presContext = GetPresContext();
   if (NS_WARN_IF(!presContext)) {
     return NS_OK;
   }
   MOZ_ASSERT(!aMouseClickEvent->DefaultPrevented());
@@ -684,18 +688,20 @@ nsresult EditorEventListener::MouseDown(
  * Drag event implementation
  */
 
 nsresult EditorEventListener::DragEnter(DragEvent* aDragEvent) {
   if (NS_WARN_IF(!aDragEvent) || DetachedFromEditor()) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-  NS_ENSURE_TRUE(presShell, NS_OK);
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (NS_WARN_IF(!presShell)) {
+    return NS_OK;
+  }
 
   if (!mCaret) {
     mCaret = new nsCaret();
     mCaret->Init(presShell);
     mCaret->SetCaretReadOnly(true);
     // This is to avoid the requirement that the Selection is Collapsed which
     // it can't be when dragging a selection in the same shell.
     // See nsCaret::IsVisible().
@@ -746,17 +752,17 @@ nsresult EditorEventListener::DragOver(D
 
 void EditorEventListener::CleanupDragDropCaret() {
   if (!mCaret) {
     return;
   }
 
   mCaret->SetVisible(false);  // hide it, so that it turns off its timer
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (presShell) {
     presShell->RestoreCaret();
   }
 
   mCaret->Terminate();
   mCaret = nullptr;
 }
 
@@ -1020,21 +1026,22 @@ nsresult EditorEventListener::Focus(Inte
     }
   }
 
   editorBase->OnFocus(target);
   if (DetachedFromEditorOrDefaultPrevented(aFocusEvent)) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
-  NS_ENSURE_TRUE(ps, NS_OK);
+  nsPresContext* presContext = GetPresContext();
+  if (NS_WARN_IF(!presContext)) {
+    return NS_OK;
+  }
   nsCOMPtr<nsIContent> focusedContent = editorBase->GetFocusedContentForIME();
-  IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent,
-                                   *editorBase);
+  IMEStateManager::OnFocusInEditor(presContext, focusedContent, *editorBase);
 
   return NS_OK;
 }
 
 nsresult EditorEventListener::Blur(InternalFocusEvent* aBlurEvent) {
   if (NS_WARN_IF(!aBlurEvent) || DetachedFromEditor()) {
     return NS_OK;
   }
--- a/editor/libeditor/EditorEventListener.h
+++ b/editor/libeditor/EditorEventListener.h
@@ -11,32 +11,32 @@
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsIDOMEventListener.h"
 #include "nsISupportsImpl.h"
 #include "nscore.h"
 
 class nsCaret;
 class nsIContent;
-class nsIPresShell;
 class nsPresContext;
 
 // X.h defines KeyPress
 #ifdef KeyPress
 #  undef KeyPress
 #endif
 
 #ifdef XP_WIN
 // On Windows, we support switching the text direction by pressing Ctrl+Shift
 #  define HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
 #endif
 
 namespace mozilla {
 
 class EditorBase;
+class PresShell;
 
 namespace dom {
 class DragEvent;
 class MouseEvent;
 }  // namespace dom
 
 class EditorEventListener : public nsIDOMEventListener {
  public:
@@ -81,17 +81,17 @@ class EditorEventListener : public nsIDO
   nsresult Blur(InternalFocusEvent* aBlurEvent);
   MOZ_CAN_RUN_SCRIPT nsresult DragEnter(dom::DragEvent* aDragEvent);
   MOZ_CAN_RUN_SCRIPT nsresult DragOver(dom::DragEvent* aDragEvent);
   nsresult DragExit(dom::DragEvent* aDragEvent);
   MOZ_CAN_RUN_SCRIPT nsresult Drop(dom::DragEvent* aDragEvent);
 
   MOZ_CAN_RUN_SCRIPT bool CanDrop(dom::DragEvent* aEvent);
   void CleanupDragDropCaret();
-  nsIPresShell* GetPresShell() const;
+  PresShell* GetPresShell() const;
   nsPresContext* GetPresContext() const;
   nsIContent* GetFocusedRootContent();
   // Returns true if IME consumes the mouse event.
   bool NotifyIMEOfMouseButtonEvent(WidgetMouseEvent* aMouseEvent);
   bool EditorHasFocus();
   bool IsFileControlTextBox();
   bool ShouldHandleNativeKeyBindings(WidgetKeyboardEvent* aKeyboardEvent);
 
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -7,16 +7,17 @@
 #include <math.h>
 
 #include "HTMLEditorEventListener.h"
 #include "HTMLEditRules.h"
 #include "HTMLEditUtils.h"
 #include "TextEditUtils.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEditRules.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
@@ -25,17 +26,16 @@
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsROCSSPrimitiveValue.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMWindow.h"
 #include "nsIHTMLObjectResizer.h"
 #include "nsINode.h"
-#include "nsIPresShell.h"
 #include "nsISupportsImpl.h"
 #include "nsISupportsUtils.h"
 #include "nsLiteralString.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStringFwd.h"
 #include "nscore.h"
 #include <algorithm>
@@ -296,17 +296,17 @@ void HTMLEditor::HideGrabberInternal() {
 
   DebugOnly<nsresult> rv = absolutePositioningObject->UnsetAttr(
       kNameSpaceID_None, nsGkAtoms::_moz_abspos, true);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to unset the attribute");
 
   // We allow the pres shell to be null; when it is, we presume there
   // are no document observers to notify, but we still want to
   // UnbindFromTree.
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (grabber) {
     DeleteRefToAnonymousNode(std::move(grabber), presShell);
   }
   if (positioningShadow) {
     DeleteRefToAnonymousNode(std::move(positioningShadow), presShell);
   }
 }
 
@@ -399,20 +399,22 @@ nsresult HTMLEditor::GrabberClicked() {
     return NS_OK;
   }
   mGrabberClicked = true;
   return rv;
 }
 
 nsresult HTMLEditor::EndMoving() {
   if (mPositioningShadow) {
-    nsCOMPtr<nsIPresShell> ps = GetPresShell();
-    NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
+    RefPtr<PresShell> presShell = GetPresShell();
+    if (NS_WARN_IF(!presShell)) {
+      return NS_ERROR_NOT_INITIALIZED;
+    }
 
-    DeleteRefToAnonymousNode(std::move(mPositioningShadow), ps);
+    DeleteRefToAnonymousNode(std::move(mPositioningShadow), presShell);
 
     mPositioningShadow = nullptr;
   }
 
   if (mEventListener) {
     DebugOnly<nsresult> rvIgnored =
         static_cast<HTMLEditorEventListener*>(mEventListener.get())
             ->ListenToMouseMoveEventForGrabber(false);
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/HTMLEditor.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsCOMPtr.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDebug.h"
 #include "nsError.h"
@@ -21,17 +22,16 @@
 #include "nsIDOMWindow.h"
 #include "mozilla/dom/Document.h"
 #include "nsIDocumentObserver.h"
 #include "nsIHTMLAbsPosEditor.h"
 #include "nsIHTMLInlineTableEditor.h"
 #include "nsIHTMLObjectResizer.h"
 #include "nsStubMutationObserver.h"
 #include "nsINode.h"
-#include "nsIPresShell.h"
 #include "nsISupportsImpl.h"
 #include "nsISupportsUtils.h"
 #include "nsLiteralString.h"
 #include "nsPresContext.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStringFwd.h"
 #include "nsUnicharUtils.h"
@@ -141,18 +141,18 @@ ManualNACPtr HTMLEditor::CreateAnonymous
   }
 
   RefPtr<Document> doc = GetDocument();
   if (NS_WARN_IF(!doc)) {
     return nullptr;
   }
 
   // Get the pres shell
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
-  if (NS_WARN_IF(!ps)) {
+  RefPtr<PresShell> presShell = GetPresShell();
+  if (NS_WARN_IF(!presShell)) {
     return nullptr;
   }
 
   // Create a new node through the element factory
   RefPtr<Element> newContentRaw = CreateHTMLContent(aTag);
   if (NS_WARN_IF(!newContentRaw)) {
     return nullptr;
   }
@@ -187,17 +187,17 @@ ManualNACPtr HTMLEditor::CreateAnonymous
       return nullptr;
     }
   }
 
   ManualNACPtr newContent(newContentRaw.forget());
 
   // Must style the new element, otherwise the PostRecreateFramesFor call
   // below will do nothing.
-  ServoStyleSet* styleSet = ps->StyleSet();
+  ServoStyleSet* styleSet = presShell->StyleSet();
   // Sometimes editor likes to append anonymous content to elements
   // in display:none subtrees, so avoid styling in those cases.
   if (ServoStyleSet::MayTraverseFrom(newContent)) {
     styleSet->StyleNewSubtree(newContent);
   }
 
   ElementDeletionObserver* observer =
       new ElementDeletionObserver(newContent, &aParentContent);
@@ -210,60 +210,61 @@ ManualNACPtr HTMLEditor::CreateAnonymous
   // can't _really_ deal with anonymous content (because it can't get the frame
   // tree ordering right).  But for us the ordering doesn't matter so this is
   // sort of ok.
   newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
                           reinterpret_cast<void*>(true));
 #endif  // DEBUG
 
   // display the element
-  ps->PostRecreateFramesFor(newContent);
+  presShell->PostRecreateFramesFor(newContent);
 
   return newContent;
 }
 
 // Removes event listener and calls DeleteRefToAnonymousNode.
 void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
                                             nsIDOMEventListener* aListener,
                                             bool aUseCapture,
                                             ManualNACPtr aElement,
-                                            nsIPresShell* aShell) {
+                                            PresShell* aPresShell) {
   if (aElement) {
     aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
   }
-  DeleteRefToAnonymousNode(std::move(aElement), aShell);
+  DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
 }
 
 // Deletes all references to an anonymous element
 void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
-                                          nsIPresShell* aShell) {
+                                          PresShell* aPresShell) {
   // call ContentRemoved() for the anonymous content
   // node so its references get removed from the frame manager's
   // undisplay map, and its layout frames get destroyed!
 
   if (NS_WARN_IF(!aContent)) {
     return;
   }
 
   nsIContent* parentContent = aContent->GetParent();
   if (NS_WARN_IF(!parentContent)) {
     // aContent was already removed?
     return;
   }
 
   nsAutoScriptBlocker scriptBlocker;
-  // Need to check whether aShell has been destroyed (but not yet deleted).
+  // Need to check whether aPresShell has been destroyed (but not yet deleted).
   // See bug 338129.
-  if (aContent->IsInComposedDoc() && aShell && !aShell->IsDestroying()) {
+  if (aContent->IsInComposedDoc() && aPresShell &&
+      !aPresShell->IsDestroying()) {
     MOZ_ASSERT(aContent->IsRootOfAnonymousSubtree());
     MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
 
     // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
     // passes NAC into it. This is not great!
-    aShell->ContentRemoved(aContent, nullptr);
+    aPresShell->ContentRemoved(aContent, nullptr);
   }
 
   // The ManualNACPtr destructor will invoke UnbindFromTree.
 }
 
 void HTMLEditor::HideAnonymousEditingUIs() {
   if (mAbsolutelyPositionedObject) {
     HideGrabberInternal();
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -7,16 +7,17 @@
 
 #include "mozilla/ComposerCommandsUpdater.h"
 #include "mozilla/ContentIterator.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/mozInlineSpellChecker.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEvents.h"
 
 #include "nsCRT.h"
 
 #include "nsUnicharUtils.h"
 
 #include "HTMLEditorEventListener.h"
 #include "HTMLEditRules.h"
@@ -33,17 +34,16 @@
 
 #include "mozilla/css/Loader.h"
 
 #include "nsIContent.h"
 #include "nsIMutableArray.h"
 #include "nsContentUtils.h"
 #include "nsIDocumentEncoder.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 
 // netwerk
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 
@@ -191,20 +191,19 @@ HTMLEditor::HTMLEditor()
 HTMLEditor::~HTMLEditor() {
   if (mRules && mRules->AsHTMLEditRules()) {
     mRules->AsHTMLEditRules()->EndListeningToEditSubActions();
   }
 
   mTypeInState = nullptr;
 
   if (mLinkHandler && IsInitialized()) {
-    nsCOMPtr<nsIPresShell> ps = GetPresShell();
-
-    if (ps && ps->GetPresContext()) {
-      ps->GetPresContext()->SetLinkHandler(mLinkHandler);
+    PresShell* presShell = GetPresShell();
+    if (presShell && presShell->GetPresContext()) {
+      presShell->GetPresContext()->SetLinkHandler(mLinkHandler);
     }
   }
 
   RemoveEventListeners();
 
   HideAnonymousEditingUIs();
 }
 
@@ -296,18 +295,20 @@ nsresult HTMLEditor::Init(Document& aDoc
       SetAbsolutePositioningEnabled(false);
       SetSnapToGridEnabled(false);
     }
 
     // Init the HTML-CSS utils
     mCSSEditUtils = MakeUnique<CSSEditUtils>(this);
 
     // disable links
-    nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
+    PresShell* presShell = GetPresShell();
+    if (NS_WARN_IF(!presShell)) {
+      return NS_ERROR_FAILURE;
+    }
     nsPresContext* context = presShell->GetPresContext();
     NS_ENSURE_TRUE(context, NS_ERROR_NULL_POINTER);
     if (!IsPlaintextEditor() && !IsInteractionAllowed()) {
       mLinkHandler = context->GetLinkHandler();
       context->SetLinkHandler(nullptr);
     }
 
     // init the type-in state
@@ -3078,17 +3079,17 @@ HTMLEditor::AddOverrideStyleSheet(const 
 
 nsresult HTMLEditor::AddOverrideStyleSheetInternal(const nsAString& aURL) {
   // Enable existing sheet if already loaded.
   if (EnableExistingStyleSheet(aURL)) {
     return NS_OK;
   }
 
   // Make sure the pres shell doesn't disappear during the load.
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (NS_WARN_IF(!presShell)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   nsCOMPtr<nsIURI> uaURI;
   nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -3179,17 +3180,17 @@ nsresult HTMLEditor::RemoveOverrideStyle
 
   // Make sure we remove the stylesheet from our internal list in all
   // cases.
   RefPtr<StyleSheet> sheet = RemoveStyleSheetFromList(aURL);
   if (!sheet) {
     return NS_OK;  // It's okay even if not found.
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (NS_WARN_IF(!presShell)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   presShell->RemoveOverrideStyleSheet(sheet);
   presShell->ApplicableStylesChanged();
 
   return NS_OK;
@@ -3641,18 +3642,18 @@ nsresult HTMLEditor::SelectAllInternal()
   }
 
   nsIContent* anchorContent = anchorNode->AsContent();
   nsIContent* rootContent;
   if (anchorContent->HasIndependentSelection()) {
     SelectionRefPtr()->SetAncestorLimiter(nullptr);
     rootContent = mRootElement;
   } else {
-    nsCOMPtr<nsIPresShell> ps = GetPresShell();
-    rootContent = anchorContent->GetSelectionRootContent(ps);
+    RefPtr<PresShell> presShell = GetPresShell();
+    rootContent = anchorContent->GetSelectionRootContent(presShell);
   }
 
   if (NS_WARN_IF(!rootContent)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   Maybe<Selection::AutoUserInitiated> userSelection;
   if (!rootContent->IsEditable()) {
@@ -4599,24 +4600,28 @@ nsresult HTMLEditor::CopyLastEditableChi
 nsresult HTMLEditor::GetElementOrigin(Element& aElement, int32_t& aX,
                                       int32_t& aY) {
   aX = 0;
   aY = 0;
 
   if (NS_WARN_IF(!IsInitialized())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
-  NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
+  PresShell* presShell = GetPresShell();
+  if (NS_WARN_IF(!presShell)) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
 
   nsIFrame* frame = aElement.GetPrimaryFrame();
   NS_ENSURE_TRUE(frame, NS_OK);
 
-  nsIFrame* container = ps->GetAbsoluteContainingBlock(frame);
-  NS_ENSURE_TRUE(container, NS_OK);
+  nsIFrame* container = presShell->GetAbsoluteContainingBlock(frame);
+  if (NS_WARN_IF(!container)) {
+    return NS_OK;
+  }
   nsPoint off = frame->GetOffsetTo(container);
   aX = nsPresContext::AppUnitsToIntCSSPixels(off.x);
   aY = nsPresContext::AppUnitsToIntCSSPixels(off.y);
 
   return NS_OK;
 }
 
 Element* HTMLEditor::GetSelectionContainerElement() const {
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -2121,18 +2121,18 @@ class HTMLEditor final : public TextEdit
    *                    insure we reset the caret in a table-editing method.
    */
   void SetSelectionAfterTableEdit(Element* aTable, int32_t aRow, int32_t aCol,
                                   int32_t aDirection, bool aSelected);
 
   void RemoveListenerAndDeleteRef(const nsAString& aEvent,
                                   nsIDOMEventListener* aListener,
                                   bool aUseCapture, ManualNACPtr aElement,
-                                  nsIPresShell* aShell);
-  void DeleteRefToAnonymousNode(ManualNACPtr aContent, nsIPresShell* aShell);
+                                  PresShell* aPresShell);
+  void DeleteRefToAnonymousNode(ManualNACPtr aContent, PresShell* aPresShell);
 
   /**
    * RefereshEditingUI() may refresh editing UIs for current Selection, focus,
    * etc.  If this shows or hides some UIs, it causes reflow.  So, this is
    * not safe method.
    */
   nsresult RefereshEditingUI();
 
--- a/editor/libeditor/HTMLEditorDocumentCommands.cpp
+++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp
@@ -11,17 +11,16 @@
 #include "nsCRT.h"                       // for nsCRT
 #include "nsDebug.h"                     // for NS_ENSURE_ARG_POINTER, etc
 #include "nsError.h"                     // for NS_ERROR_INVALID_ARG, etc
 #include "nsIDocShell.h"                 // for nsIDocShell
 #include "mozilla/dom/Document.h"        // for Document
 #include "nsIEditingSession.h"           // for nsIEditingSession, etc
 #include "nsIEditor.h"                   // for nsIEditor
 #include "nsIPlaintextEditor.h"          // for nsIPlaintextEditor, etc
-#include "nsIPresShell.h"                // for nsIPresShell
 #include "nsISelectionController.h"      // for nsISelectionController
 #include "nsISupportsImpl.h"             // for nsPresContext::Release
 #include "nsISupportsUtils.h"            // for NS_IF_ADDREF
 #include "nsIURI.h"                      // for nsIURI
 #include "nsPresContext.h"               // for nsPresContext
 #include "nscore.h"                      // for NS_IMETHODIMP, nsresult, etc
 
 class nsISupports;
--- a/editor/libeditor/HTMLEditorObjectResizer.cpp
+++ b/editor/libeditor/HTMLEditorObjectResizer.cpp
@@ -6,31 +6,31 @@
 #include "mozilla/HTMLEditor.h"
 
 #include "HTMLEditorEventListener.h"
 #include "HTMLEditUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/dom/EventTarget.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsAtom.h"
 #include "nsIContent.h"
 #include "nsID.h"
 #include "mozilla/dom/Document.h"
-#include "nsIPresShell.h"
 #include "nsISupportsUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStringFwd.h"
 #include "nscore.h"
 #include <algorithm>
 
@@ -444,17 +444,17 @@ nsresult HTMLEditor::HideResizersInterna
   // Don't warn even if resizers are visible since script cannot check
   // if they are visible and this is non-virtual method.  So, the cost of
   // calling this can be ignored.
   if (!mResizedObject) {
     return NS_OK;
   }
 
   // get the presshell's document observer interface.
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   NS_WARNING_ASSERTION(presShell, "There is no presShell");
   // We allow the pres shell to be null; when it is, we presume there
   // are no document observers to notify, but we still want to
   // UnbindFromTree.
 
   NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
 
   // HTMLEditor should forget all members related to resizers first since
--- a/editor/libeditor/HTMLInlineTableEditor.cpp
+++ b/editor/libeditor/HTMLInlineTableEditor.cpp
@@ -1,24 +1,24 @@
 /* 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/HTMLEditor.h"
 
 #include "HTMLEditUtils.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIContent.h"
 #include "nsIHTMLObjectResizer.h"
-#include "nsIPresShell.h"
 #include "nsLiteralString.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nscore.h"
 
 namespace mozilla {
 
 NS_IMETHODIMP
@@ -162,38 +162,38 @@ void HTMLEditor::HideInlineTableEditingU
   RemoveMouseClickListener(mAddColumnBeforeButton);
   RemoveMouseClickListener(mRemoveColumnButton);
   RemoveMouseClickListener(mAddColumnAfterButton);
   RemoveMouseClickListener(mAddRowBeforeButton);
   RemoveMouseClickListener(mRemoveRowButton);
   RemoveMouseClickListener(mAddRowAfterButton);
 
   // get the presshell's document observer interface.
-  nsCOMPtr<nsIPresShell> ps = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   // We allow the pres shell to be null; when it is, we presume there
   // are no document observers to notify, but we still want to
   // UnbindFromTree.
 
   // Calling DeleteRefToAnonymousNode() may cause showing the UI again.
   // Therefore, we should forget all anonymous contents first.
   // Otherwise, we could leak the old content because of overwritten by
   // ShowInlineTableEditingUIInternal().
   ManualNACPtr addColumnBeforeButton(std::move(mAddColumnBeforeButton));
   ManualNACPtr removeColumnButton(std::move(mRemoveColumnButton));
   ManualNACPtr addColumnAfterButton(std::move(mAddColumnAfterButton));
   ManualNACPtr addRowBeforeButton(std::move(mAddRowBeforeButton));
   ManualNACPtr removeRowButton(std::move(mRemoveRowButton));
   ManualNACPtr addRowAfterButton(std::move(mAddRowAfterButton));
 
-  DeleteRefToAnonymousNode(std::move(addColumnBeforeButton), ps);
-  DeleteRefToAnonymousNode(std::move(removeColumnButton), ps);
-  DeleteRefToAnonymousNode(std::move(addColumnAfterButton), ps);
-  DeleteRefToAnonymousNode(std::move(addRowBeforeButton), ps);
-  DeleteRefToAnonymousNode(std::move(removeRowButton), ps);
-  DeleteRefToAnonymousNode(std::move(addRowAfterButton), ps);
+  DeleteRefToAnonymousNode(std::move(addColumnBeforeButton), presShell);
+  DeleteRefToAnonymousNode(std::move(removeColumnButton), presShell);
+  DeleteRefToAnonymousNode(std::move(addColumnAfterButton), presShell);
+  DeleteRefToAnonymousNode(std::move(addRowBeforeButton), presShell);
+  DeleteRefToAnonymousNode(std::move(removeRowButton), presShell);
+  DeleteRefToAnonymousNode(std::move(addRowAfterButton), presShell);
 }
 
 nsresult HTMLEditor::DoInlineTableEditingAction(const Element& aElement) {
   nsAutoString anonclass;
   aElement.GetAttr(kNameSpaceID_None, nsGkAtoms::_moz_anonclass, anonclass);
 
   if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable"))) {
     return NS_OK;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -8,30 +8,30 @@
 #include "mozilla/HTMLEditor.h"
 
 #include "HTMLEditUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/EditorUtils.h"
 #include "mozilla/FlushType.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsFrameSelection.h"
 #include "nsGkAtoms.h"
 #include "nsAtom.h"
 #include "nsIContent.h"
 #include "nsIFrame.h"
 #include "nsINode.h"
-#include "nsIPresShell.h"
 #include "nsISupportsUtils.h"
 #include "nsITableCellLayout.h"  // For efficient access to table cell
 #include "nsLiteralString.h"
 #include "nsQueryFrame.h"
 #include "nsRange.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsTableCellFrame.h"
@@ -767,17 +767,17 @@ nsresult HTMLEditor::InsertTableRowsWith
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // SetSelectionAfterTableEdit from AutoSelectionSetterAfterTableEdit will
   // access frame selection, so we need reframe.
   // Because GetTableCellElementAt() depends on frame.
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (presShell) {
     presShell->FlushPendingNotifications(FlushType::Frames);
   }
 
   return NS_OK;
 }
 
 nsresult HTMLEditor::DeleteTableElementAndChildrenWithTransaction(
--- a/editor/libeditor/TextEditRulesBidi.cpp
+++ b/editor/libeditor/TextEditRulesBidi.cpp
@@ -8,17 +8,16 @@
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/Selection.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsFrameSelection.h"
 #include "nsIContent.h"
 #include "nsIEditor.h"
-#include "nsIPresShell.h"
 #include "nsISupportsImpl.h"
 #include "nsPresContext.h"
 #include "nscore.h"
 
 namespace mozilla {
 
 using namespace dom;
 
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/ContentIterator.h"
 #include "mozilla/EditAction.h"
 #include "mozilla/EditorDOMPoint.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/PresShell.h"
 #include "mozilla/TextEditRules.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TextServicesDocument.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
@@ -37,17 +38,16 @@
 #include "nsDependentSubstring.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIAbsorbingTransaction.h"
 #include "nsIClipboard.h"
 #include "nsIContent.h"
 #include "nsIDocumentEncoder.h"
 #include "nsINode.h"
-#include "nsIPresShell.h"
 #include "nsISelectionController.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITransferable.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsNameSpaceManager.h"
 #include "nsLiteralString.h"
 #include "nsReadableUtils.h"
 #include "nsServiceManagerUtils.h"
@@ -1317,18 +1317,17 @@ nsresult TextEditor::OnCompositionChange
     MOZ_ASSERT(!aCompositionChangeEvent.mData.IsVoid());
     editActionData.SetData(aCompositionChangeEvent.mData);
   }
 
   if (!EnsureComposition(aCompositionChangeEvent)) {
     return NS_OK;
   }
 
-  nsIPresShell* presShell = GetPresShell();
-  if (NS_WARN_IF(!presShell)) {
+  if (NS_WARN_IF(!GetPresShell())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // NOTE: TextComposition should receive selection change notification before
   //       CompositionChangeEventHandlingMarker notifies TextComposition of the
   //       end of handling compositionchange event because TextComposition may
   //       need to ignore selection changes caused by composition.  Therefore,
   //       CompositionChangeEventHandlingMarker must be destroyed after a call
@@ -1337,31 +1336,31 @@ nsresult TextEditor::OnCompositionChange
   //       TextComposition of a selection change.
   MOZ_ASSERT(
       !mPlaceholderBatch,
       "UpdateIMEComposition() must be called without place holder batch");
   TextComposition::CompositionChangeEventHandlingMarker
       compositionChangeEventHandlingMarker(mComposition,
                                            &aCompositionChangeEvent);
 
-  RefPtr<nsCaret> caretP = presShell->GetCaret();
+  RefPtr<nsCaret> caret = GetCaret();
 
   nsresult rv;
   {
     AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::IMETxnName);
 
     MOZ_ASSERT(
         mIsInEditSubAction,
         "AutoPlaceholderBatch should've notified the observes of before-edit");
     rv = InsertTextAsSubAction(aCompositionChangeEvent.mData);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                          "Failed to insert new composition string");
 
-    if (caretP) {
-      caretP->SetSelection(SelectionRefPtr());
+    if (caret) {
+      caret->SetSelection(SelectionRefPtr());
     }
   }
 
   // If still composing, we should fire input event via observer.
   // Note that if the composition will be committed by the following
   // compositionend event, we don't need to notify editor observes of this
   // change.
   // NOTE: We must notify after the auto batch will be gone.
@@ -1750,17 +1749,17 @@ bool TextEditor::FireClipboardEvent(Even
                                     int32_t aSelectionType,
                                     bool* aActionTaken) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (aEventMessage == ePaste) {
     CommitComposition();
   }
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  RefPtr<PresShell> presShell = GetPresShell();
   if (NS_WARN_IF(!presShell)) {
     return false;
   }
 
   if (!nsCopySupport::FireClipboardEvent(aEventMessage, aSelectionType,
                                          presShell, SelectionRefPtr(),
                                          aActionTaken)) {
     return false;
--- a/mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
@@ -1,15 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
@@ -103,20 +104,25 @@ public class LauncherActivity extends Ac
         intent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
         startActivity(intent);
     }
 
     /**
      * Launch tab queue service to display overlay.
      */
+    @SuppressLint("NewApi")
     private void dispatchTabQueueIntent() {
         Intent intent = new Intent(getIntent());
         intent.setClass(getApplicationContext(), TabQueueService.class);
-        startService(intent);
+        if (AppConstants.Versions.preO) {
+            startService(intent);
+        } else {
+            startForegroundService(intent);
+        }
     }
 
     /**
      * Launch the browser activity.
      */
     private void dispatchNormalIntent() {
         Intent intent = new Intent(getIntent());
         intent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
--- a/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueHelper.java
@@ -1,22 +1,25 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.tabqueue;
 
+import android.annotation.TargetApi;
+import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.os.Build;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 
 import org.json.JSONArray;
@@ -258,16 +261,46 @@ public class TabQueueHelper {
             builder.setChannelId(NotificationHelper.getInstance(context)
                     .getNotificationChannel(NotificationHelper.Channel.DEFAULT).getId());
         }
 
         NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
         notificationManager.notify(TabQueueHelper.TAB_QUEUE_NOTIFICATION_ID, builder.build());
     }
 
+    /**
+     * Displays a foreground service notification used from Android O prompting the user that a tab
+     * is being added to the queue.
+     *
+     * @param context
+     * @return startupNotification
+     */
+    @TargetApi(Build.VERSION_CODES.O)
+    public static Notification getStartupNotification(final Context context) {
+        final Resources resources = context.getResources();
+
+        NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
+        inboxStyle.setBigContentTitle(resources.getString(R.string.tab_queue_notification_prompt));
+        inboxStyle.setSummaryText(resources.getString(R.string.tab_queue_notification_title));
+
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+                .setSmallIcon(R.drawable.ic_status_logo)
+                .setContentTitle(resources.getString(R.string.tab_queue_notification_prompt))
+                .setContentText(resources.getString(R.string.tab_queue_notification_title))
+                .setStyle(inboxStyle)
+                .setColor(ContextCompat.getColor(context, R.color.fennec_ui_accent));
+
+        if (!AppConstants.Versions.preO) {
+            builder.setChannelId(NotificationHelper.getInstance(context)
+                    .getNotificationChannel(NotificationHelper.Channel.DEFAULT).getId());
+        }
+
+        return builder.build();
+    }
+
     public static boolean shouldOpenTabQueueUrls(final Context context) {
         ThreadUtils.assertNotOnUiThread();
 
         // TODO: Use profile shared prefs when bug 1147925 gets fixed.
         final SharedPreferences prefs = GeckoSharedPrefs.forApp(context);
 
         int tabsQueued = prefs.getInt(PREF_TAB_QUEUE_COUNT, 0);
 
--- a/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueService.java
@@ -48,17 +48,18 @@ import java.util.concurrent.Executors;
 
 
 /**
  * On launch this Service displays a View over the currently running process with an action to open the url in Fennec
  * immediately.  If the user takes no action, allowing the runnable to be processed after the specified
  * timeout (TOAST_TIMEOUT), the url is added to a file which is then read in Fennec on next launch, this allows the
  * user to quickly queue urls to open without having to open Fennec each time. If the Service receives an Intent whilst
  * the created View is still active, the old url is immediately processed and the View is re-purposed with the new
- * Intent data.
+ * Intent data. From Android O, due to background limitations, this is a foreground service as it may be started
+ * from the background.
  * <p/>
  * The SYSTEM_ALERT_WINDOW permission is used to allow us to insert a View from this Service which responds to user
  * interaction, whilst still allowing whatever is in the background to be seen and interacted with.
  * <p/>
  * Using an Activity to do this doesn't seem to work as there's an issue to do with the native android intent resolver
  * dialog not being hidden when the toast is shown.  Using an IntentService instead of a Service doesn't work as
  * each new Intent received kicks off the IntentService lifecycle anew which means that a new View is created each time,
  * meaning that we can't quickly queue the current data and re-purpose the View.  The asynchronous nature of the
@@ -99,20 +100,20 @@ public class TabQueueService extends Ser
 
         windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
 
         LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
         toastLayout = layoutInflater.inflate(R.layout.tab_queue_toast, null);
 
         final Resources resources = getResources();
 
-        TextView messageView = (TextView) toastLayout.findViewById(R.id.toast_message);
+        TextView messageView = toastLayout.findViewById(R.id.toast_message);
         messageView.setText(resources.getText(R.string.tab_queue_toast_message));
 
-        openNowButton = (Button) toastLayout.findViewById(R.id.toast_button);
+        openNowButton = toastLayout.findViewById(R.id.toast_button);
         openNowButton.setText(resources.getText(R.string.tab_queue_toast_action));
 
         toastLayoutParams = new WindowManager.LayoutParams(
                 WindowManager.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.WRAP_CONTENT,
                 AppConstants.Versions.preO ?
                         WindowManager.LayoutParams.TYPE_PHONE :
                         WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
@@ -121,52 +122,54 @@ public class TabQueueService extends Ser
                         WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                 PixelFormat.TRANSLUCENT);
 
         toastLayoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
     }
 
     @Override
     public int onStartCommand(final Intent intent, final int flags, final int startId) {
+        if (!AppConstants.Versions.preO) {
+            startForeground(TabQueueHelper.TAB_QUEUE_NOTIFICATION_ID, TabQueueHelper.getStartupNotification(TabQueueService.this));
+        }
+
         // If this is a redelivery then lets bypass the entire double tap to open now code as that's a big can of worms,
         // we also don't expect redeliveries because of the short time window associated with this feature.
         if (flags != START_FLAG_REDELIVERY) {
             final Context applicationContext = getApplicationContext();
             final SharedPreferences sharedPreferences = GeckoSharedPrefs.forApp(applicationContext);
 
             final String lastUrl = sharedPreferences.getString(GeckoPreferences.PREFS_TAB_QUEUE_LAST_SITE, "");
 
             final SafeIntent safeIntent = new SafeIntent(intent);
             final String intentUrl = safeIntent.getDataString();
 
             final long lastRunTime = sharedPreferences.getLong(GeckoPreferences.PREFS_TAB_QUEUE_LAST_TIME, 0);
             final boolean isWithinDoubleTapTimeLimit = System.currentTimeMillis() - lastRunTime < TOAST_DOUBLE_TAP_TIMEOUT_MILLIS;
 
             if (!TextUtils.isEmpty(lastUrl) && lastUrl.equals(intentUrl) && isWithinDoubleTapTimeLimit) {
                 // Background thread because we could do some file IO if we have to remove a url from the list.
-                tabQueueHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        // If there is a runnable around, that means that the previous process hasn't yet completed, so
-                        // we will need to prevent it from running and remove the view from the window manager.
-                        // If there is no runnable around then the url has already been added to the list, so we'll
-                        // need to remove it before proceeding or that url will open multiple times.
-                        if (stopServiceRunnable != null) {
-                            tabQueueHandler.removeCallbacks(stopServiceRunnable);
-                            stopSelfResult(stopServiceRunnable.getStartId());
-                            stopServiceRunnable = null;
-                            removeView();
-                        } else {
-                            TabQueueHelper.removeURLFromFile(applicationContext, intentUrl, TabQueueHelper.FILE_NAME);
-                        }
-                        openNow(safeIntent.getUnsafe());
+                tabQueueHandler.post(() -> {
+                    // If there is a runnable around, that means that the previous process hasn't yet completed, so
+                    // we will need to prevent it from running and remove the view from the window manager.
+                    // If there is no runnable around then the url has already been added to the list, so we'll
+                    // need to remove it before proceeding or that url will open multiple times.
+                    if (stopServiceRunnable != null) {
+                        tabQueueHandler.removeCallbacks(stopServiceRunnable);
+                        stopForeground(false);
+                        stopSelfResult(stopServiceRunnable.getStartId());
+                        stopServiceRunnable = null;
+                        removeView();
+                    } else {
+                        TabQueueHelper.removeURLFromFile(applicationContext, intentUrl, TabQueueHelper.FILE_NAME);
+                    }
+                    openNow(safeIntent.getUnsafe());
 
-                        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "tabqueue-doubletap");
-                        stopSelfResult(startId);
-                    }
+                    Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "tabqueue-doubletap");
+                    stopSelfResult(startId);
                 });
 
                 return START_REDELIVER_INTENT;
             }
 
             sharedPreferences.edit().putString(GeckoPreferences.PREFS_TAB_QUEUE_LAST_SITE, intentUrl)
                                     .putLong(GeckoPreferences.PREFS_TAB_QUEUE_LAST_TIME, System.currentTimeMillis())
                                     .apply();
@@ -189,52 +192,47 @@ public class TabQueueService extends Ser
         stopServiceRunnable = new StopServiceRunnable(startId) {
             @Override
             public void onRun() {
                 addURLToTabQueue(intent, TabQueueHelper.FILE_NAME);
                 stopServiceRunnable = null;
             }
         };
 
-        openNowButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(final View view) {
-                tabQueueHandler.removeCallbacks(stopServiceRunnable);
-                stopServiceRunnable = null;
-                removeView();
-                openNow(intent);
+        openNowButton.setOnClickListener(view -> {
+            tabQueueHandler.removeCallbacks(stopServiceRunnable);
+            stopServiceRunnable = null;
+            removeView();
+            openNow(intent);
 
-                Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "tabqueue-now");
-                stopSelfResult(startId);
-            }
+            Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "tabqueue-now");
+            stopSelfResult(startId);
         });
 
         tabQueueHandler.postDelayed(stopServiceRunnable, TOAST_TIMEOUT);
 
         return START_REDELIVER_INTENT;
     }
 
     private void openNow(Intent intent) {
         Intent forwardIntent = new Intent(intent);
         forwardIntent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
         forwardIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(forwardIntent);
 
+        stopForeground(false);
         TabQueueHelper.removeNotification(getApplicationContext());
 
         GeckoSharedPrefs.forApp(getApplicationContext()).edit().remove(GeckoPreferences.PREFS_TAB_QUEUE_LAST_SITE)
                                                                .remove(GeckoPreferences.PREFS_TAB_QUEUE_LAST_TIME)
                                                                .apply();
 
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                int queuedTabCount = TabQueueHelper.getTabQueueLength(TabQueueService.this);
-                Telemetry.addToHistogram("FENNEC_TABQUEUE_QUEUESIZE", queuedTabCount);
-            }
+        executorService.submit(() -> {
+            int queuedTabCount = TabQueueHelper.getTabQueueLength(TabQueueService.this);
+            Telemetry.addToHistogram("FENNEC_TABQUEUE_QUEUESIZE", queuedTabCount);
         });
 
     }
 
     @SuppressLint("NewApi")
     @TargetApi(Build.VERSION_CODES.M)
     private void showSettingsNotification() {
         if (AppConstants.Versions.preMarshmallow) {
@@ -285,33 +283,30 @@ public class TabQueueService extends Ser
             // This should never happen, but let's return silently instead of crashing if it does.
             Log.w(LOGTAG, "Error adding URL to tab queue - invalid intent passed in.");
             return;
         }
         final SafeIntent safeIntent = new SafeIntent(intent);
         final String intentData = safeIntent.getDataString();
 
         // As we're doing disk IO, let's run this stuff in a separate thread.
-        executorService.submit(new Runnable() {
-            @Override
-            public void run() {
-                Context applicationContext = getApplicationContext();
-                final GeckoProfile profile = GeckoProfile.get(applicationContext);
-                int tabsQueued = TabQueueHelper.queueURL(profile, intentData, filename);
-                List<String> urls = TabQueueHelper.getLastURLs(applicationContext, filename);
+        executorService.submit(() -> {
+            Context applicationContext = getApplicationContext();
+            final GeckoProfile profile = GeckoProfile.get(applicationContext);
+            int tabsQueued = TabQueueHelper.queueURL(profile, intentData, filename);
+            List<String> urls = TabQueueHelper.getLastURLs(applicationContext, filename);
 
-                TabQueueHelper.showNotification(applicationContext, tabsQueued, urls);
+            TabQueueHelper.showNotification(applicationContext, tabsQueued, urls);
 
-                // Store the number of URLs queued so that we don't have to read and process the file to see if we have
-                // any urls to open.
-                // TODO: Use profile shared prefs when bug 1147925 gets fixed.
-                final SharedPreferences prefs = GeckoSharedPrefs.forApp(applicationContext);
+            // Store the number of URLs queued so that we don't have to read and process the file to see if we have
+            // any urls to open.
+            // TODO: Use profile shared prefs when bug 1147925 gets fixed.
+            final SharedPreferences prefs = GeckoSharedPrefs.forApp(applicationContext);
 
-                prefs.edit().putInt(TabQueueHelper.PREF_TAB_QUEUE_COUNT, tabsQueued).apply();
-            }
+            prefs.edit().putInt(TabQueueHelper.PREF_TAB_QUEUE_COUNT, tabsQueued).apply();
         });
     }
 
     @Override
     public void onDestroy() {
         super.onDestroy();
         handlerThread.quit();
     }
@@ -319,33 +314,34 @@ public class TabQueueService extends Ser
     /**
      * A modified Runnable which additionally removes the view from the window view hierarchy and stops the service
      * when run, unless explicitly instructed not to.
      */
     private abstract class StopServiceRunnable implements Runnable {
 
         private final int startId;
 
-        public StopServiceRunnable(final int startId) {
+        /*package*/ StopServiceRunnable(final int startId) {
             this.startId = startId;
         }
 
         public void run() {
             run(true);
         }
 
         public void run(final boolean shouldRemoveView) {
             onRun();
 
             if (shouldRemoveView) {
                 removeView();
             }
 
+            stopForeground(false);
             stopSelfResult(startId);
         }
 
-        public int getStartId() {
+        /*package*/ int getStartId() {
             return startId;
         }
 
         public abstract void onRun();
     }
 }
\ No newline at end of file
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -336,16 +336,19 @@
 <!-- Localization note (tab_queue_prompt_permit_drawing_over_apps): This additional text is shown if the
      user needs to enable an Android setting in order to enable tab queues. -->
 <!ENTITY tab_queue_prompt_permit_drawing_over_apps "Turn on Permit drawing over other apps">
 <!ENTITY tab_queue_prompt_positive_action_button "Enable">
 <!ENTITY tab_queue_prompt_negative_action_button "Not now">
 <!-- Localization note (tab_queue_prompt_settings_button): This button is shown if the user needs to
      enable a permission in Android's setting in order to enable tab queues. -->
 <!ENTITY tab_queue_prompt_settings_button "Go to Settings">
+<!-- Localization note (tab_queue_notification_prompt): This is the text of the default notification
+shown from Android O while a tab is being queued.-->
+<!ENTITY tab_queue_notification_prompt "Adding new tab to queue&#8230;">
 <!ENTITY tab_queue_notification_title "&brandShortName;">
 <!-- Localization note (tab_queue_notification_text_plural2) : The
      formatD is replaced with the number of tabs queued.  The
      number of tabs queued is always more than one.  We can't use
      Android plural forms, sadly. See Bug #753859. -->
 <!ENTITY tab_queue_notification_text_plural2 "&formatD; tabs waiting">
 <!-- Localization note (tab_queue_notification_text_singular2) : This is the
      text of a notification; we expect only one tab queued. -->
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -297,16 +297,17 @@
   <string name="tab_queue_prompt_positive_action_button">&tab_queue_prompt_positive_action_button;</string>
   <string name="tab_queue_prompt_negative_action_button">&tab_queue_prompt_negative_action_button;</string>
   <string name="tab_queue_prompt_permit_drawing_over_apps">&tab_queue_prompt_permit_drawing_over_apps;</string>
   <string name="tab_queue_prompt_settings_button">&tab_queue_prompt_settings_button;</string>
   <string name="tab_queue_toast_message">&tab_queue_toast_message3;</string>
   <string name="tab_queue_toast_action">&tab_queue_toast_action;</string>
   <string name="tab_queue_notification_text_singular">&tab_queue_notification_text_singular2;</string>
   <string name="tab_queue_notification_text_plural">&tab_queue_notification_text_plural2;</string>
+  <string name="tab_queue_notification_prompt">&tab_queue_notification_prompt;</string>
   <string name="tab_queue_notification_title">&tab_queue_notification_title;</string>
   <string name="tab_queue_notification_settings">&tab_queue_notification_settings;</string>
 
   <string name="pref_default_browser">&pref_default_browser;</string>
   <string name="pref_default_browser_mozilla_support_tablet">&pref_default_browser_mozilla_support_tablet;</string>
 
   <string name="pref_about_firefox">&pref_about_firefox;</string>
 
--- a/testing/web-platform/tests/dom/events/Event-dispatch-on-disabled-elements.html
+++ b/testing/web-platform/tests/dom/events/Event-dispatch-on-disabled-elements.html
@@ -159,29 +159,40 @@ promise_test(async () => {
 }, "CSS Transitions transitioncancel event fires on disabled form elements");
 
 promise_test(async () => {
   // For each form element type, set up transition event handlers.
   for (const localName of formElements) {
     const elem = document.createElement(localName);
     document.body.appendChild(elem);
     elem.disabled = true;
-    const eventPromises = [
-      "animationstart",
-      "animationiteration",
-      "animationend",
-    ].map(eventType => {
-      return new Promise(r => {
-        elem.addEventListener(eventType, r, { once: true });
+    const animationStartPromise = new Promise(r => {
+      elem.addEventListener("animationstart", () => {
+        // Seek to the second iteration to trigger the animationiteration event
+        elem.style.animationDelay = "-100s"
+        r();
       });
     });
-    elem.style.animation = "fade .1s 2";
+    const animationIterationPromise = new Promise(r => {
+      elem.addEventListener("animationiteration", ()=>{
+        elem.style.animationDelay = "-200s"
+        r();
+      });
+    });
+    const animationEndPromise = new Promise(r => {
+      elem.addEventListener("animationend", r);
+    });
+    elem.style.animation = "fade 100s 2";
     elem.classList.add("animate");
     // All the events fire...
-    await Promise.all(eventPromises);
+    await Promise.all([
+      animationStartPromise,
+      animationIterationPromise,
+      animationEndPromise,
+    ]);
     elem.remove();
   }
 }, "CSS Animation animationstart, animationiteration, animationend fire on disabled form elements");
 
 promise_test(async () => {
   // For each form element type, set up transition event handlers.
   for (const localName of formElements) {
     const elem = document.createElement(localName);
--- a/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
@@ -91,16 +91,17 @@ support-files =
   chrome_timeout.js
   subtst_master_pass.html
 [test_maxlength.html]
 [test_autocomplete_new_password.html]
 scheme = https
 skip-if = toolkit == 'android' # autocomplete
 [test_one_doorhanger_per_un_pw.html]
 scheme = https
+skip-if = toolkit == 'android' # bug 1535505
 [test_onsubmit_value_change.html]
 [test_passwords_in_type_password.html]
 [test_prompt.html]
 skip-if = os == "linux" || toolkit == 'android' # Tests desktop prompts
 [test_prompt_async.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
 support-files = subtst_prompt_async.html
 [test_prompt_http.html]
--- a/toolkit/components/thumbnails/PageThumbUtils.jsm
+++ b/toolkit/components/thumbnails/PageThumbUtils.jsm
@@ -16,27 +16,26 @@ ChromeUtils.defineModuleGetter(this, "Br
 
 var PageThumbUtils = {
   // The default background color for page thumbnails.
   THUMBNAIL_BG_COLOR: "#fff",
   // The namespace for thumbnail canvas elements.
   HTML_NAMESPACE: "http://www.w3.org/1999/xhtml",
 
   /**
-   * Creates a new canvas element in the context of aWindow, or if aWindow
-   * is undefined, in the context of hiddenDOMWindow.
+   * Creates a new canvas element in the context of aWindow.
    *
-   * @param aWindow (optional) The document of this window will be used to
-   *  create the canvas.  If not given, the hidden window will be used.
+   * @param aWindow The document of this window will be used to
+   *  create the canvas.
    * @param aWidth (optional) width of the canvas to create
    * @param aHeight (optional) height of the canvas to create
    * @return The newly created canvas.
    */
   createCanvas(aWindow, aWidth = 0, aHeight = 0) {
-    let doc = (aWindow || Services.appShell.hiddenDOMWindow).document;
+    let doc = aWindow.document;
     let canvas = doc.createElementNS(this.HTML_NAMESPACE, "canvas");
     canvas.mozOpaque = true;
     canvas.imageSmoothingEnabled = true;
     let [thumbnailWidth, thumbnailHeight] = this.getThumbnailSize(aWindow);
     canvas.width = aWidth ? aWidth : thumbnailWidth;
     canvas.height = aHeight ? aHeight : thumbnailHeight;
     return canvas;
   },
--- a/toolkit/components/thumbnails/PageThumbs.jsm
+++ b/toolkit/components/thumbnails/PageThumbs.jsm
@@ -158,17 +158,17 @@ var PageThumbs = {
    * @resolve {Blob} The thumbnail, as a Blob.
    */
   captureToBlob: function PageThumbs_captureToBlob(aBrowser) {
     if (!this._prefEnabled()) {
       return null;
     }
 
     return new Promise(resolve => {
-      let canvas = this.createCanvas(aBrowser.contentWindow);
+      let canvas = this.createCanvas(aBrowser.ownerGlobal);
       this.captureToCanvas(aBrowser, canvas, () => {
         canvas.toBlob(blob => {
           resolve(blob, this.contentType);
         });
       });
     });
   },
 
@@ -256,17 +256,17 @@ var PageThumbs = {
         aCanvas.getContext("2d").putImageData(imgData, 0, 0);
         if (aCallback) {
           aCallback(aCanvas);
         }
       })();
       return;
     }
     // The content is a local page, grab a thumbnail sync.
-    PageThumbUtils.createSnapshotThumbnail(aBrowser.contentWindow,
+    PageThumbUtils.createSnapshotThumbnail(aBrowser.ownerGlobal,
                                            aCanvas,
                                            aArgs);
 
     if (aCallback) {
       aCallback(aCanvas);
     }
   },
 
--- a/widget/gtk/IMContextWrapper.cpp
+++ b/widget/gtk/IMContextWrapper.cpp
@@ -401,17 +401,18 @@ nsDependentCSubstring IMContextWrapper::
     return nsDependentCSubstring();
   }
 
   nsDependentCSubstring im(contextIDChar, strlen(contextIDChar));
 
   // If the context is XIM, actual engine must be specified with
   // |XMODIFIERS=@im=foo|.
   const char* xmodifiersChar = PR_GetEnv("XMODIFIERS");
-  if (!im.EqualsLiteral("xim") || !xmodifiersChar) {
+  if (!xmodifiersChar ||
+      (!im.EqualsLiteral("xim") && !im.EqualsLiteral("wayland"))) {
     return im;
   }
 
   nsDependentCString xmodifiers(xmodifiersChar);
   int32_t atIMValueStart = xmodifiers.Find("@im=") + 4;
   if (atIMValueStart < 4 ||
       xmodifiers.Length() <= static_cast<size_t>(atIMValueStart)) {
     return im;