Bug 1528914 - Tidy the relationship between the doc shell and the pres context. r=qdot
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 19 Feb 2019 22:53:40 +0000
changeset 517842 8ed0dbecf030b172f2f12a7cc9716559c4db241b
parent 517841 ab11369b0f9699b1badda1e8f757dc1a6ff159b6
child 517843 a8e8102f8558245ed52420484bdc3803493a7d0e
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1528914, 1490401, 1418159
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
Bug 1528914 - Tidy the relationship between the doc shell and the pres context. r=qdot Make it always forward to the document's docshell. We rely on it being setup by the time our stuff runs, and we cannot have multiple pres contexts per document in different docshells anymore. This allows me to also move some state to the document (about whether it's currently loaded in a chrome docshell (nsPresContext::mIsChrome) and whether it's a chrome origin image (nsPresContext::mIsChromeOriginImage), which will help for bug 1490401 / bug 1418159. The pres context already relies on having the docshell available on `Init` and we don't properly handle dynamic changes to it. The reason I store some state like whether the doc URI is chrome:// and whether we're in a chrome docshell is not (only) to avoid recomputing it over and over, but also to allow me to read them from Stylo (main-thread blocked, but poke at that from multiple non-main-threads). Differential Revision: https://phabricator.services.mozilla.com/D20301
dom/base/Document.cpp
dom/base/Document.h
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
layout/base/nsDocumentViewer.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/printing/nsPrintJob.cpp
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -1222,16 +1222,18 @@ Document::Document(const char* aContentT
       // unless we get a window, and in that case the docshell value will get
       // &&-ed in, this is safe.
       mAllowDNSPrefetch(true),
       mIsStaticDocument(false),
       mCreatingStaticClone(false),
       mInUnlinkOrDeletion(false),
       mHasHadScriptHandlingObject(false),
       mIsBeingUsedAsImage(false),
+      mDocURISchemeIsChrome(false),
+      mInChromeDocShell(false),
       mIsSyntheticDocument(false),
       mHasLinksToUpdateRunnable(false),
       mFlushingPendingLinkUpdates(false),
       mMayHaveDOMMutationObservers(false),
       mMayHaveAnimationObservers(false),
       mHasMixedActiveContentLoaded(false),
       mHasMixedActiveContentBlocked(false),
       mHasMixedDisplayContentLoaded(false),
@@ -2830,16 +2832,18 @@ void Document::StopDocumentLoad() {
   }
 }
 
 void Document::SetDocumentURI(nsIURI* aURI) {
   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
   mDocumentURI = aURI;
   nsIURI* newBase = GetDocBaseURI();
 
+  mDocURISchemeIsChrome = aURI && IsChromeURI(aURI);
+
   bool equalBases = false;
   // Changing just the ref of a URI does not change how relative URIs would
   // resolve wrt to it, so we can treat the bases as equal as long as they're
   // equal ignoring the ref.
   if (oldBase && newBase) {
     oldBase->EqualsExceptRef(newBase, &equalBases);
   } else {
     equalBases = !oldBase && !newBase;
@@ -4296,16 +4300,19 @@ bool Document::IsTopLevelWindowInactive(
 
 void Document::SetContainer(nsDocShell* aContainer) {
   if (aContainer) {
     mDocumentContainer = aContainer;
   } else {
     mDocumentContainer = WeakPtr<nsDocShell>();
   }
 
+  mInChromeDocShell =
+      aContainer && aContainer->ItemType() == nsIDocShellTreeItem::typeChrome;
+
   EnumerateActivityObservers(NotifyActivityChanged, nullptr);
 
   // IsTopLevelWindowInactive depends on the docshell, so
   // update the cached value now that it's available.
   UpdateDocumentStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
   if (!aContainer) {
     return;
   }
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -2469,16 +2469,26 @@ class Document : public nsINode,
   /**
    * Check whether this document is a root document that is not an
    * external resource.
    */
   bool IsRootDisplayDocument() const {
     return !mParentDocument && !mDisplayDocument;
   }
 
+  bool IsDocumentURISchemeChrome() const { return mDocURISchemeIsChrome; }
+
+  bool IsInChromeDocShell() const {
+    const Document* root = this;
+    while (const Document* displayDoc = root->GetDisplayDocument()) {
+      root = displayDoc;
+    }
+    return root->mInChromeDocShell;
+  }
+
   bool IsBeingUsedAsImage() const { return mIsBeingUsedAsImage; }
 
   void SetIsBeingUsedAsImage() { mIsBeingUsedAsImage = true; }
 
   bool IsSVGGlyphsDocument() const { return mIsSVGGlyphsDocument; }
 
   void SetIsSVGGlyphsDocument() { mIsSVGGlyphsDocument = true; }
 
@@ -4002,16 +4012,22 @@ class Document : public nsINode,
   bool mInUnlinkOrDeletion : 1;
 
   // True if document has ever had script handling object.
   bool mHasHadScriptHandlingObject : 1;
 
   // True if we're an SVG document being used as an image.
   bool mIsBeingUsedAsImage : 1;
 
+  // True if our current document URI's scheme is chrome://
+  bool mDocURISchemeIsChrome : 1;
+
+  // True if we're loaded in a chrome docshell.
+  bool mInChromeDocShell : 1;
+
   // True is this document is synthetic : stand alone image, video, audio
   // file, etc.
   bool mIsSyntheticDocument : 1;
 
   // True is there is a pending runnable which will call
   // FlushPendingLinkUpdates().
   bool mHasLinksToUpdateRunnable : 1;
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3846,20 +3846,16 @@ void nsContentUtils::LogMessageToConsole
     CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
     if (!sConsoleService) {
       return;
     }
   }
   sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
 }
 
-bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
-  return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
-}
-
 bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
   nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
   if (docShellAsItem) {
     docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
   }
   return sameTypeParent != nullptr;
 }
@@ -3884,34 +3880,16 @@ bool nsContentUtils::IsUtf8OnlyPlainText
   // NOTE: This must be a subset of the list in IsPlainTextType().
   return aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
          aContentType.EqualsLiteral(APPLICATION_JSON) ||
          aContentType.EqualsLiteral(TEXT_JSON) ||
          aContentType.EqualsLiteral(TEXT_VTT);
 }
 
 // static
-bool nsContentUtils::IsInChromeDocshell(Document* aDocument) {
-  if (!aDocument) {
-    return false;
-  }
-
-  if (aDocument->GetDisplayDocument()) {
-    return IsInChromeDocshell(aDocument->GetDisplayDocument());
-  }
-
-  nsCOMPtr<nsIDocShellTreeItem> docShell = aDocument->GetDocShell();
-  if (!docShell) {
-    return false;
-  }
-
-  return docShell->ItemType() == nsIDocShellTreeItem::typeChrome;
-}
-
-// static
 nsIContentPolicy* nsContentUtils::GetContentPolicy() {
   if (!sTriedToGetContentPolicy) {
     CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
     // It's OK to not have a content policy service
     sTriedToGetContentPolicy = true;
   }
 
   return sContentPolicyService;
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1222,17 +1222,19 @@ class nsContentUtils {
    */
   static nsresult FormatLocalizedString(PropertiesFile aFile, const char* aKey,
                                         const nsTArray<nsString>& aParamArray,
                                         nsAString& aResult);
 
   /**
    * Returns true if aDocument is a chrome document
    */
-  static bool IsChromeDoc(const Document* aDocument);
+  static bool IsChromeDoc(const Document* aDocument) {
+    return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
+  }
 
   /**
    * Returns true if aDocument is in a docshell whose parent is the same type
    */
   static bool IsChildOfSameType(Document* aDoc);
 
   /**
    * Returns true if the content-type will be rendered as plain-text.
@@ -1245,17 +1247,19 @@ class nsContentUtils {
    */
   static bool IsUtf8OnlyPlainTextType(const nsACString& aContentType);
 
   /**
    * Returns true if aDocument belongs to a chrome docshell for
    * display purposes.  Returns false for null documents or documents
    * which do not belong to a docshell.
    */
-  static bool IsInChromeDocshell(Document* aDocument);
+  static bool IsInChromeDocshell(const Document* aDocument) {
+    return aDocument && aDocument->IsInChromeDocShell();
+  }
 
   /**
    * Return the content policy service
    */
   static nsIContentPolicy* GetContentPolicy();
 
   /**
    * Map internal content policy types to external ones.
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -684,19 +684,16 @@ nsresult nsDocumentViewer::SyncParentSub
     mDocument->SuppressEventHandling(parent_doc->EventHandlingSuppressed());
   }
   return parent_doc->SetSubDocumentFor(element, mDocument);
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::SetContainer(nsIDocShell* aContainer) {
   mContainer = static_cast<nsDocShell*>(aContainer);
-  if (mPresContext) {
-    mPresContext->SetContainer(mContainer);
-  }
 
   // We're loading a new document into the window where this document
   // viewer lives, sync the parent document's frame element -> sub
   // document map
 
   return SyncParentSubDocMap();
 }
 
@@ -948,18 +945,16 @@ nsresult nsDocumentViewer::InitInternal(
   }
 
   nsCOMPtr<nsIInterfaceRequestor> requestor(mContainer);
   if (requestor) {
     if (mPresContext) {
       nsCOMPtr<nsILinkHandler> linkHandler;
       requestor->GetInterface(NS_GET_IID(nsILinkHandler),
                               getter_AddRefs(linkHandler));
-
-      mPresContext->SetContainer(mContainer);
       mPresContext->SetLinkHandler(linkHandler);
     }
 
     // Set script-context-owner in the document
 
     nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(requestor);
 
     if (window) {
@@ -1471,17 +1466,16 @@ static void AttachContainerRecurse(nsIDo
   if (viewer) {
     viewer->SetIsHidden(false);
     Document* doc = viewer->GetDocument();
     if (doc) {
       doc->SetContainer(static_cast<nsDocShell*>(aShell));
     }
     RefPtr<nsPresContext> pc = viewer->GetPresContext();
     if (pc) {
-      pc->SetContainer(static_cast<nsDocShell*>(aShell));
       nsCOMPtr<nsILinkHandler> handler = do_QueryInterface(aShell);
       pc->SetLinkHandler(handler);
     }
     nsCOMPtr<nsIPresShell> presShell = viewer->GetPresShell();
     if (presShell) {
       presShell->SetForwardingContainer(WeakPtr<nsDocShell>());
     }
   }
@@ -1496,17 +1490,19 @@ static void AttachContainerRecurse(nsIDo
     AttachContainerRecurse(shell);
   }
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
 
-  if (mDocument) mDocument->SetContainer(mContainer);
+  if (mDocument) {
+    mDocument->SetContainer(mContainer);
+  }
 
   nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHidden = false;
 
   if (mPresShell) mPresShell->SetForwardingContainer(WeakPtr<nsDocShell>());
 
@@ -2166,18 +2162,16 @@ nsDocumentViewer::Show(void) {
     if (NS_FAILED(rv)) return rv;
 
     if (mPresContext && base_win) {
       nsCOMPtr<nsILinkHandler> linkHandler(do_GetInterface(base_win));
 
       if (linkHandler) {
         mPresContext->SetLinkHandler(linkHandler);
       }
-
-      mPresContext->SetContainer(mContainer);
     }
 
     if (mPresContext) {
       Hide();
 
       rv = InitPresentationStuff(mDocument->MayStartLayout());
     }
 
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -217,24 +217,21 @@ nsPresContext::nsPresContext(dom::Docume
       mIsEmulatingMedia(false),
       mIsGlyph(false),
       mUsesRootEMUnits(false),
       mUsesExChUnits(false),
       mCounterStylesDirty(true),
       mFontFeatureValuesDirty(true),
       mSuppressResizeReflow(false),
       mIsVisual(false),
-      mIsChrome(false),
-      mIsChromeOriginImage(false),
       mPaintFlashing(false),
       mPaintFlashingInitialized(false),
       mHasWarnedAboutPositionedTableParts(false),
       mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
       mQuirkSheetAdded(false),
-      mNeedsPrefUpdate(false),
       mHadNonBlankPaint(false),
       mHadContentfulPaint(false),
       mHadContentfulPaintComposite(false)
 #ifdef DEBUG
       ,
       mInitialized(false)
 #endif
 {
@@ -354,49 +351,42 @@ static bool sNoTheme = false;
 // more than one prescontext.
 static bool sLookAndFeelChanged;
 
 // Set to true when ThemeChanged needs to be called on mTheme.  This is used
 // because mTheme is a service, so there's no need to notify it from more than
 // one prescontext.
 static bool sThemeChanged;
 
+bool nsPresContext::IsChrome() const {
+  return Document()->IsInChromeDocShell();
+}
+
+bool nsPresContext::IsChromeOriginImage() const {
+  return Document()->IsBeingUsedAsImage() &&
+         Document()->IsDocumentURISchemeChrome();
+}
+
 void nsPresContext::GetDocumentColorPreferences() {
   // Make sure the preferences are initialized.  In the normal run,
   // they would already be, because gfxPlatform would have been created,
   // but in some reference tests, that is not the case.
   gfxPrefs::GetSingleton();
 
   int32_t useAccessibilityTheme = 0;
   bool usePrefColors = true;
-  bool isChromeDocShell = false;
   static int32_t sDocumentColorsSetting;
   static bool sDocumentColorsSettingPrefCached = false;
   if (!sDocumentColorsSettingPrefCached) {
     sDocumentColorsSettingPrefCached = true;
     Preferences::AddIntVarCache(&sDocumentColorsSetting,
                                 "browser.display.document_color_use", 0);
   }
 
-  dom::Document* doc = mDocument->GetDisplayDocument();
-  if (doc && doc->GetDocShell()) {
-    isChromeDocShell =
-        nsIDocShellTreeItem::typeChrome == doc->GetDocShell()->ItemType();
-  } else {
-    nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
-    if (docShell) {
-      isChromeDocShell =
-          nsIDocShellTreeItem::typeChrome == docShell->ItemType();
-    }
-  }
-
-  mIsChromeOriginImage = mDocument->IsBeingUsedAsImage() &&
-                         IsChromeURI(mDocument->GetDocumentURI());
-
-  if (isChromeDocShell || mIsChromeOriginImage) {
+  if (IsChrome() || IsChromeOriginImage()) {
     usePrefColors = false;
   } else {
     useAccessibilityTheme =
         LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
     usePrefColors = !useAccessibilityTheme;
   }
   if (usePrefColors) {
     usePrefColors =
@@ -436,21 +426,20 @@ void nsPresContext::GetDocumentColorPref
 
   // Now deal with the pref:
   // 0 = default: always, except in high contrast mode
   // 1 = always
   // 2 = never
   if (sDocumentColorsSetting == 1 || mDocument->IsBeingUsedAsImage()) {
     mUseDocumentColors = true;
   } else if (sDocumentColorsSetting == 2) {
-    mUseDocumentColors = isChromeDocShell || mIsChromeOriginImage;
+    mUseDocumentColors = IsChrome() || IsChromeOriginImage();
   } else {
-    MOZ_ASSERT(
-        !useAccessibilityTheme || !(isChromeDocShell || mIsChromeOriginImage),
-        "The accessibility theme should only be on for non-chrome");
+    MOZ_ASSERT(!useAccessibilityTheme || !(IsChrome() || IsChromeOriginImage()),
+               "The accessibility theme should only be on for non-chrome");
     mUseDocumentColors = !useAccessibilityTheme;
   }
 }
 
 void nsPresContext::GetUserPreferences() {
   if (!GetPresShell()) {
     // No presshell means nothing to do here.  We'll do this when we
     // get a presshell.
@@ -673,24 +662,17 @@ void nsPresContext::DispatchPrefChangedR
 }
 
 void nsPresContext::UpdateAfterPreferencesChanged() {
   mPostedPrefChangedRunnable = false;
   if (!mShell) {
     return;
   }
 
-  if (!mContainer) {
-    // Delay updating until there is a container
-    mNeedsPrefUpdate = true;
-    return;
-  }
-
-  nsCOMPtr<nsIDocShellTreeItem> docShell(mContainer);
-  if (docShell && nsIDocShellTreeItem::typeChrome == docShell->ItemType()) {
+  if (mDocument->IsInChromeDocShell()) {
     return;
   }
 
   // Initialize our state from the user preferences
   GetUserPreferences();
 
   // update the presShell: tell it to set the preference style rules up
   mShell->UpdatePreferenceStyles();
@@ -748,17 +730,16 @@ nsresult nsPresContext::Init(nsDeviceCon
     // Unfortunately, sometimes |parent| here has no presshell because
     // printing screws up things.  Assert that in other cases it does,
     // but whenever the shell is null just fall back on using our own
     // refresh driver.
     NS_ASSERTION(!parent || mDocument->IsStaticDocument() || parent->GetShell(),
                  "How did we end up with a presshell if our parent doesn't "
                  "have one?");
     if (parent && parent->GetPresContext()) {
-      // We don't have our container set yet at this point
       nsCOMPtr<nsIDocShellTreeItem> ourItem = mDocument->GetDocShell();
       if (ourItem) {
         nsCOMPtr<nsIDocShellTreeItem> parentItem;
         ourItem->GetSameTypeParent(getter_AddRefs(parentItem));
         if (parentItem) {
           Element* containingElement =
               parent->FindContentForSubDocument(mDocument);
           if (!containingElement->IsXULElement() ||
@@ -807,42 +788,38 @@ void nsPresContext::AttachShell(nsIPresS
   mRestyleManager = MakeUnique<mozilla::RestyleManager>(this);
 
   // Since CounterStyleManager is also the name of a method of
   // nsPresContext, it is necessary to prefix the class with the mozilla
   // namespace here.
   mCounterStyleManager = new mozilla::CounterStyleManager(this);
 
   dom::Document* doc = mShell->GetDocument();
-  NS_ASSERTION(doc, "expect document here");
-  if (doc) {
-    // Have to update PresContext's mDocument before calling any other methods.
-    mDocument = doc;
-  }
+  MOZ_ASSERT(doc);
+  // Have to update PresContext's mDocument before calling any other methods.
+  mDocument = doc;
   // Initialize our state from the user preferences, now that we
   // have a presshell, and hence a document.
   GetUserPreferences();
 
-  if (doc) {
-    nsIURI* docURI = doc->GetDocumentURI();
-
-    if (IsDynamic() && docURI) {
-      bool isChrome = false;
-      bool isRes = false;
-      docURI->SchemeIs("chrome", &isChrome);
-      docURI->SchemeIs("resource", &isRes);
-
-      if (!isChrome && !isRes)
-        mImageAnimationMode = mImageAnimationModePref;
-      else
-        mImageAnimationMode = imgIContainer::kNormalAnimMode;
-    }
-
-    UpdateCharSet(doc->GetDocumentCharacterSet());
+  nsIURI* docURI = doc->GetDocumentURI();
+
+  if (IsDynamic() && docURI) {
+    bool isChrome = false;
+    bool isRes = false;
+    docURI->SchemeIs("chrome", &isChrome);
+    docURI->SchemeIs("resource", &isRes);
+
+    if (!isChrome && !isRes)
+      mImageAnimationMode = mImageAnimationModePref;
+    else
+      mImageAnimationMode = imgIContainer::kNormalAnimMode;
   }
+
+  UpdateCharSet(doc->GetDocumentCharacterSet());
 }
 
 void nsPresContext::DetachShell() {
   // The counter style manager's destructor needs to deallocate with the
   // presshell arena. Disconnect it before nulling out the shell.
   //
   // XXXbholley: Given recent refactorings, it probably makes more sense to
   // just null our mShell at the bottom of this function. I'm leaving it
@@ -1297,55 +1274,27 @@ bool nsPresContext::ElementWouldPropagat
   // a dummy ScrollStyles we don't care about.  It'll do a bit of extra work,
   // but saves us having to have more complicated code or more code duplication;
   // in practice we will make this call quite rarely, because we checked for all
   // the common cases above.
   ScrollStyles dummy(StyleOverflow::Auto, StyleOverflow::Auto);
   return GetPropagatedScrollStylesForViewport(this, &dummy) == &aElement;
 }
 
-void nsPresContext::SetContainer(nsIDocShell* aDocShell) {
-  if (aDocShell) {
-    NS_ASSERTION(!(mContainer && mNeedsPrefUpdate),
-                 "Should only need pref update if mContainer is null.");
-    mContainer = static_cast<nsDocShell*>(aDocShell);
-    if (mNeedsPrefUpdate) {
-      DispatchPrefChangedRunnableIfNeeded();
-      mNeedsPrefUpdate = false;
-    }
-  } else {
-    mContainer = WeakPtr<nsDocShell>();
-  }
-  UpdateIsChrome();
-  if (mContainer) {
-    GetDocumentColorPreferences();
-  }
+nsISupports* nsPresContext::GetContainerWeak() const { return GetDocShell(); }
+
+nsIDocShell* nsPresContext::GetDocShell() const {
+  return mDocument->GetDocShell();
 }
 
-nsISupports* nsPresContext::GetContainerWeak() const {
-  return static_cast<nsIDocShell*>(mContainer);
-}
-
-nsIDocShell* nsPresContext::GetDocShell() const { return mContainer; }
-
-/* virtual */ void nsPresContext::Detach() {
-  SetContainer(nullptr);
-  SetLinkHandler(nullptr);
-}
+/* virtual */ void nsPresContext::Detach() { SetLinkHandler(nullptr); }
 
 bool nsPresContext::BidiEnabled() const { return Document()->GetBidiEnabled(); }
 
-void nsPresContext::SetBidiEnabled() const {
-  if (mShell) {
-    dom::Document* doc = mShell->GetDocument();
-    if (doc) {
-      doc->SetBidiEnabled();
-    }
-  }
-}
+void nsPresContext::SetBidiEnabled() const { Document()->SetBidiEnabled(); }
 
 void nsPresContext::SetBidi(uint32_t aSource) {
   // Don't do all this stuff unless the options have changed.
   if (aSource == GetBidi()) {
     return;
   }
 
   Document()->SetBidiOptions(aSource);
@@ -1353,20 +1302,17 @@ void nsPresContext::SetBidi(uint32_t aSo
       IBMBIDI_NUMERAL_HINDI == GET_BIDI_OPTION_NUMERAL(aSource)) {
     SetBidiEnabled();
   }
   if (IBMBIDI_TEXTTYPE_VISUAL == GET_BIDI_OPTION_TEXTTYPE(aSource)) {
     SetVisualMode(true);
   } else if (IBMBIDI_TEXTTYPE_LOGICAL == GET_BIDI_OPTION_TEXTTYPE(aSource)) {
     SetVisualMode(false);
   } else {
-    dom::Document* doc = mShell->GetDocument();
-    if (doc) {
-      SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
-    }
+    SetVisualMode(IsVisualCharset(Document()->GetDocumentCharacterSet()));
   }
 }
 
 uint32_t nsPresContext::GetBidi() const { return Document()->GetBidiOptions(); }
 
 bool nsPresContext::IsTopLevelWindowInactive() {
   return Document()->IsTopLevelWindowInactive();
 }
@@ -1785,45 +1731,39 @@ void nsPresContext::SetPaginatedScrollin
     mCanPaginatedScroll = aPaginated;
 }
 
 void nsPresContext::SetPrintSettings(nsIPrintSettings* aPrintSettings) {
   if (mMedium == nsGkAtoms::print) mPrintSettings = aPrintSettings;
 }
 
 bool nsPresContext::EnsureVisible() {
-  nsCOMPtr<nsIDocShell> docShell(mContainer);
-  if (docShell) {
-    nsCOMPtr<nsIContentViewer> cv;
-    docShell->GetContentViewer(getter_AddRefs(cv));
-    // Make sure this is the content viewer we belong with
-    if (cv && cv->GetPresContext() == this) {
-      // OK, this is us.  We want to call Show() on the content viewer.
-      nsresult result = cv->Show();
-      if (NS_SUCCEEDED(result)) {
-        return true;
-      }
-    }
+  nsCOMPtr<nsIDocShell> docShell(GetDocShell());
+  if (!docShell) {
+    return false;
   }
-  return false;
+  nsCOMPtr<nsIContentViewer> cv;
+  docShell->GetContentViewer(getter_AddRefs(cv));
+  // Make sure this is the content viewer we belong with
+  if (!cv || cv->GetPresContext() != this) {
+    return false;
+  }
+  // OK, this is us.  We want to call Show() on the content viewer.
+  nsresult result = cv->Show();
+  return NS_SUCCEEDED(result);
 }
 
 #ifdef MOZ_REFLOW_PERF
 void nsPresContext::CountReflows(const char* aName, nsIFrame* aFrame) {
   if (mShell) {
     mShell->CountReflows(aName, aFrame);
   }
 }
 #endif
 
-void nsPresContext::UpdateIsChrome() {
-  mIsChrome =
-      mContainer && nsIDocShellTreeItem::typeChrome == mContainer->ItemType();
-}
-
 bool nsPresContext::HasAuthorSpecifiedRules(const nsIFrame* aFrame,
                                             uint32_t aRuleTypeMask) const {
   Element* elem = aFrame->GetContent()->AsElement();
 
   // We need to handle non-generated content pseudos too, so we use
   // the parent of generated content pseudo to be consistent.
   if (elem->GetPseudoElementType() != PseudoStyleType::NotPseudo) {
     MOZ_ASSERT(elem->GetParent(), "Pseudo element has no parent element?");
@@ -2587,22 +2527,18 @@ gfxFloat nsPresContext::AppUnitsToGfxUni
 
 nscoord nsPresContext::PhysicalMillimetersToAppUnits(float aMM) const {
   float inches = aMM / MM_PER_INCH_FLOAT;
   return NSToCoordFloorClamped(
       inches * float(DeviceContext()->AppUnitsPerPhysicalInch()));
 }
 
 bool nsPresContext::IsDeviceSizePageSize() {
-  bool isDeviceSizePageSize = false;
-  nsCOMPtr<nsIDocShell> docShell(mContainer);
-  if (docShell) {
-    isDeviceSizePageSize = docShell->GetDeviceSizeIsPageSize();
-  }
-  return isDeviceSizePageSize;
+  nsIDocShell* docShell = GetDocShell();
+  return docShell && docShell->GetDeviceSizeIsPageSize();
 }
 
 uint64_t nsPresContext::GetRestyleGeneration() const {
   if (!mRestyleManager) {
     return 0;
   }
   return mRestyleManager->GetRestyleGeneration();
 }
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -408,29 +408,28 @@ class nsPresContext : public nsISupports
   nscolor BodyTextColor() const { return mBodyTextColor; }
   void SetBodyTextColor(nscolor aColor) { mBodyTextColor = aColor; }
 
   bool GetUseFocusColors() const { return mUseFocusColors; }
   uint8_t FocusRingWidth() const { return mFocusRingWidth; }
   bool GetFocusRingOnAnything() const { return mFocusRingOnAnything; }
   uint8_t GetFocusRingStyle() const { return mFocusRingStyle; }
 
-  void SetContainer(nsIDocShell* aContainer);
 
   nsISupports* GetContainerWeak() const;
 
   nsIDocShell* GetDocShell() const;
 
   // XXX this are going to be replaced with set/get container
   void SetLinkHandler(nsILinkHandler* aHandler) { mLinkHandler = aHandler; }
   nsILinkHandler* GetLinkHandler() { return mLinkHandler; }
 
   /**
    * Detach this pres context - i.e. cancel relevant timers,
-   * SetLinkHandler(null), SetContainer(null) etc.
+   * SetLinkHandler(null), etc.
    * Only to be used by the DocumentViewer.
    */
   virtual void Detach();
 
   /**
    * Get the visible area associated with this presentation context.
    * This is the size of the visible area that is used for
    * presenting the document. The returned value is in the standard
@@ -866,19 +865,18 @@ class nsPresContext : public nsISupports
     return (mMedium == nsGkAtoms::screen || mType == eContext_PageLayout ||
             mType == eContext_PrintPreview);
   }
   bool IsPrintingOrPrintPreview() {
     return (mType == eContext_Print || mType == eContext_PrintPreview);
   }
 
   // Is this presentation in a chrome docshell?
-  bool IsChrome() const { return mIsChrome; }
-  bool IsChromeOriginImage() const { return mIsChromeOriginImage; }
-  void UpdateIsChrome();
+  bool IsChrome() const;
+  bool IsChromeOriginImage() const;
 
   // Public API for native theme code to get style internals.
   bool HasAuthorSpecifiedRules(const nsIFrame* aFrame,
                                uint32_t ruleTypeMask) const;
 
   // Is it OK to let the page specify colors and backgrounds?
   bool UseDocumentColors() const {
     MOZ_ASSERT(mUseDocumentColors || !(IsChrome() || IsChromeOriginImage()),
@@ -1190,18 +1188,16 @@ class nsPresContext : public nsISupports
   // The following are public member variables so that we can use them
   // with mozilla::AutoToggle or mozilla::AutoRestore.
 
   // Should we disable font size inflation because we're inside of
   // shrink-wrapping calculations on an inflation container?
   bool mInflationDisabledForShrinkWrap;
 
  protected:
-  mozilla::WeakPtr<nsDocShell> mContainer;
-
   float mSystemFontScale;    // Internal text zoom factor, defaults to 1.0
   float mTextZoom;           // Text zoom, defaults to 1.0
   float mEffectiveTextZoom;  // Text zoom * system font scale
   float mFullZoom;           // Page zoom, defaults to 1.0
   float mOverrideDPPX;       // DPPX overrided, defaults to 0.0
   gfxSize mLastFontInflationScreenSize;
 
   int32_t mCurAppUnitsPerDevPixel;
@@ -1318,34 +1314,28 @@ class nsPresContext : public nsISupports
   unsigned mFontFeatureValuesDirty : 1;
 
   // resize reflow is suppressed when the only change has been to zoom
   // the document rather than to change the document's dimensions
   unsigned mSuppressResizeReflow : 1;
 
   unsigned mIsVisual : 1;
 
-  unsigned mIsChrome : 1;
-  unsigned mIsChromeOriginImage : 1;
-
   // Should we paint flash in this context? Do not use this variable directly.
   // Use GetPaintFlashing() method instead.
   mutable unsigned mPaintFlashing : 1;
   mutable unsigned mPaintFlashingInitialized : 1;
 
   unsigned mHasWarnedAboutPositionedTableParts : 1;
 
   unsigned mHasWarnedAboutTooLargeDashedOrDottedRadius : 1;
 
   // Have we added quirk.css to the style set?
   unsigned mQuirkSheetAdded : 1;
 
-  // Is there a pref update to process once we have a container?
-  unsigned mNeedsPrefUpdate : 1;
-
   // Has NotifyNonBlankPaint been called on this PresContext?
   unsigned mHadNonBlankPaint : 1;
   // Has NotifyContentfulPaint been called on this PresContext?
   unsigned mHadContentfulPaint : 1;
   // Has NotifyDidPaintForSubtree been called for a contentful paint?
   unsigned mHadContentfulPaintComposite : 1;
 
 #ifdef DEBUG
--- a/layout/printing/nsPrintJob.cpp
+++ b/layout/printing/nsPrintJob.cpp
@@ -2265,20 +2265,16 @@ nsresult nsPrintJob::ReflowPrintObject(c
   if (NS_FAILED(rv) || doReturn) {
     return rv;
   }
 
   PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n",
          aPO.get(), aPO->mPresShell.get(), gFrameTypesStr[aPO->mFrameType],
          adjSize.width, adjSize.height));
 
-  // This docshell stuff is weird; will go away when we stop having multiple
-  // presentations per document
-  aPO->mPresContext->SetContainer(aPO->mDocShell);
-
   aPO->mPresShell->BeginObservingDocument();
 
   aPO->mPresContext->SetPageSize(adjSize);
   aPO->mPresContext->SetVisibleArea(
       nsRect(0, 0, adjSize.width, adjSize.height));
   aPO->mPresContext->SetIsRootPaginatedDocument(documentIsTopLevel);
   aPO->mPresContext->SetPageScale(aPO->mZoomRatio);
   // Calculate scale factor from printer to screen