bug 939049 - staticly type nsIDocument::mDocumentContainer and nsDocumentViewerContainer::mContainer r=smaug
authorTrevor Saunders <trev.saunders@gmail.com>
Fri, 15 Nov 2013 02:12:43 -0500
changeset 156632 403bb511d10bd420bda0e211a02b2faf3e507dd6
parent 156631 59edeb46f2d661239684bd435d81d983c56c88a2
child 156633 0a0081b34af7bb85fdb70501b0f00c66eb95a670
push id36487
push usertrev.saunders@gmail.com
push dateWed, 20 Nov 2013 22:34:04 +0000
treeherdermozilla-inbound@0a0081b34af7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs939049
milestone28.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 939049 - staticly type nsIDocument::mDocumentContainer and nsDocumentViewerContainer::mContainer r=smaug
content/base/public/nsIDocument.h
content/base/src/moz.build
content/base/src/nsDocument.cpp
content/html/document/src/ImageDocument.cpp
content/html/document/src/moz.build
content/html/document/src/nsHTMLDocument.cpp
content/xul/document/src/XULDocument.cpp
content/xul/document/src/moz.build
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIContentViewer.idl
docshell/base/nsIDocumentLoaderFactory.idl
docshell/shistory/src/nsSHEntryShared.cpp
layout/base/moz.build
layout/base/nsDocumentViewer.cpp
layout/build/moz.build
layout/build/nsContentDLF.cpp
layout/build/nsContentDLF.h
layout/printing/nsPrintEngine.cpp
layout/printing/nsPrintEngine.h
uriloader/prefetch/nsOfflineCacheUpdateService.cpp
xpfe/components/directory/nsDirectoryViewer.cpp
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -15,24 +15,27 @@
 #include "nsIDocumentObserver.h"         // for typedef (nsUpdateType)
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
 #include "nsPIDOMWindow.h"               // for use in inline functions
 #include "nsPropertyTable.h"             // for member
 #include "nsTHashtable.h"                // for member
 #include "mozilla/dom/DocumentBinding.h"
+#include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsCSSStyleSheet;
+class nsIDocShell;
+class nsDocShell;
 class nsDOMNavigationTiming;
 class nsDOMTouchList;
 class nsEventStates;
 class nsFrameLoader;
 class nsHTMLCSSStyleSheet;
 class nsHTMLDocument;
 class nsHTMLStyleSheet;
 class nsIAtom;
@@ -1145,26 +1148,22 @@ public:
    */
   virtual void ResetToURI(nsIURI *aURI, nsILoadGroup* aLoadGroup,
                           nsIPrincipal* aPrincipal) = 0;
 
   /**
    * Set the container (docshell) for this document. Virtual so that
    * docshell can call it.
    */
-  virtual void SetContainer(nsISupports *aContainer);
+  virtual void SetContainer(nsDocShell* aContainer);
 
   /**
    * Get the container (docshell) for this document.
    */
-  already_AddRefed<nsISupports> GetContainer() const
-  {
-    nsCOMPtr<nsISupports> container = do_QueryReferent(mDocumentContainer);
-    return container.forget();
-  }
+  virtual nsISupports* GetContainer() const;
 
   /**
    * Get the container's load context for this document.
    */
   nsILoadContext* GetLoadContext() const;
 
   /**
    * Set and get XML declaration. If aVersion is null there is no declaration.
@@ -1691,17 +1690,17 @@ public:
    */
   bool IsStaticDocument() { return mIsStaticDocument; }
 
   /**
    * Clones the document and subdocuments and stylesheet etc.
    * @param aCloneContainer The container for the clone document.
    */
   virtual already_AddRefed<nsIDocument>
-  CreateStaticClone(nsISupports* aCloneContainer);
+  CreateStaticClone(nsIDocShell* aCloneContainer);
 
   /**
    * If this document is a static clone, this returns the original
    * document.
    */
   nsIDocument* GetOriginalDocument()
   {
     MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
@@ -2222,17 +2221,17 @@ protected:
   nsString mLastModified;
 
   nsCOMPtr<nsIURI> mDocumentURI;
   nsCOMPtr<nsIURI> mOriginalURI;
   nsCOMPtr<nsIURI> mDocumentBaseURI;
 
   nsWeakPtr mDocumentLoadGroup;
 
-  nsWeakPtr mDocumentContainer;
+  mozilla::WeakPtr<nsDocShell> mDocumentContainer;
 
   nsCString mCharacterSet;
   int32_t mCharacterSetSource;
 
   // This is just a weak pointer; the parent document owns its children.
   nsIDocument* mParentDocument;
 
   // A reference to the element last returned from GetRootElement().
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -196,16 +196,17 @@ LOCAL_INCLUDES += [
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/xbl/src',
     '/content/xml/content/src',
     '/content/xml/document/src',
     '/content/xslt/src/xpath',
     '/content/xul/content/src',
     '/content/xul/document/src',
+    '/docshell/base',
     '/dom/base',
     '/dom/ipc',
     '/dom/workers',
     '/image/src',
     '/js/ipc',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/base',
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -29,17 +29,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsContentList.h"
 #include "nsIObserver.h"
 #include "nsIBaseWindow.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/css/ImageLoader.h"
-#include "nsIDocShell.h"
+#include "nsDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsCOMArray.h"
 #include "nsDOMClassInfo.h"
 #include "nsCxPusher.h"
 
 #include "mozilla/BasicEvents.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsIDOMNodeFilter.h"
@@ -2199,17 +2199,17 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
 
   // Now get our new principal
   if (aPrincipal) {
     SetPrincipal(aPrincipal);
   } else {
     nsIScriptSecurityManager *securityManager =
       nsContentUtils::GetSecurityManager();
     if (securityManager) {
-      nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+      nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
 
       if (!docShell && aLoadGroup) {
         nsCOMPtr<nsIInterfaceRequestor> cbs;
         aLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
         docShell = do_GetInterface(cbs);
       }
 
       MOZ_ASSERT(docShell,
@@ -2695,17 +2695,17 @@ nsDocument::InitCSP(nsIChannel* aChannel
     rv = AppendCSPFromHeader(csp, cspROHeaderValue, selfURI, true, true);
     NS_ENSURE_SUCCESS(rv, rv);
   } else if (!cspOldROHeaderValue.IsEmpty()) {
     rv = AppendCSPFromHeader(csp, cspOldROHeaderValue, selfURI, true, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // ----- Enforce frame-ancestor policy on any applied policies
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   if (docShell) {
     bool safeAncestry = false;
 
     // PermitsAncestry sends violation reports when necessary
     rv = csp->PermitsAncestry(docShell, &safeAncestry);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!safeAncestry) {
@@ -2926,17 +2926,17 @@ nsDocument::SetContentType(const nsAStri
 
   SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
 }
 
 nsresult
 nsDocument::GetAllowPlugins(bool * aAllowPlugins)
 {
   // First, we ask our docshell if it allows plugins.
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
 
   if (docShell) {
     docShell->GetAllowPlugins(aAllowPlugins);
 
     // If the docshell allows plugins, we check whether
     // we are sandboxed and plugins should not be allowed.
     if (*aAllowPlugins)
       *aAllowPlugins = !(mSandboxFlags & SANDBOXED_PLUGINS);
@@ -3394,17 +3394,17 @@ nsDocument::SetHeaderData(nsIAtom* aHead
       // to worry about null strings.
       EnableStyleSheetsForSetInternal(aData, true);
     }
   }
 
   if (aHeaderField == nsGkAtoms::refresh) {
     // We get into this code before we have a script global yet, so get to
     // our container via mDocumentContainer.
-    nsCOMPtr<nsIRefreshURI> refresher = do_QueryReferent(mDocumentContainer);
+    nsCOMPtr<nsIRefreshURI> refresher(mDocumentContainer);
     if (refresher) {
       // Note: using mDocumentURI instead of mBaseURI here, for consistency
       // (used to just use the current URI of our webnavigation, but that
       // should really be the same thing).  Note that this code can run
       // before the current URI of the webnavigation has been updated, so we
       // can't assert equality here.
       refresher->SetupRefreshURIFromHeader(mDocumentURI, NodePrincipal(),
                                            NS_ConvertUTF16toUTF8(aData));
@@ -3475,17 +3475,17 @@ nsDocument::doCreateShell(nsPresContext*
 
   nsRefPtr<PresShell> shell = new PresShell;
   shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   mPresShell = shell;
 
   // Make sure to never paint if we belong to an invisible DocShell.
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   if (docShell && docShell->IsInvisible())
     shell->SetNeverPainting(true);
 
   mExternalResourceMap.ShowViewers();
 
   MaybeRescheduleAnimationFrameNotifications();
 
   return shell.forget();
@@ -4188,37 +4188,49 @@ NotifyActivityChanged(nsIContent *aConte
   nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aContent));
   if (objectLoadingContent) {
     nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
     olc->NotifyOwnerDocumentActivityChanged();
   }
 }
 
 void
-nsIDocument::SetContainer(nsISupports* aContainer)
-{
-  mDocumentContainer = do_GetWeakReference(aContainer);
+nsIDocument::SetContainer(nsDocShell* aContainer)
+{
+  if (aContainer) {
+    mDocumentContainer = aContainer->asWeakPtr();
+  } else {
+    mDocumentContainer = WeakPtr<nsDocShell>();
+  }
+
   EnumerateFreezableElements(NotifyActivityChanged, nullptr);
+  if (!aContainer) {
+    return;
+  }
+
   // Get the Docshell
-  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
-  if (docShell) {
-    int32_t itemType;
-    docShell->GetItemType(&itemType);
-    // check itemtype
-    if (itemType == nsIDocShellTreeItem::typeContent) {
-      // check if same type root
-      nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
-      docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-      NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
-
-      if (sameTypeRoot == docShell) {
-        static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
-      }
-    }
-  }
+  int32_t itemType;
+  aContainer->GetItemType(&itemType);
+  // check itemtype
+  if (itemType == nsIDocShellTreeItem::typeContent) {
+    // check if same type root
+    nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
+    aContainer->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
+    NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
+
+    if (sameTypeRoot == aContainer) {
+      static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
+    }
+  }
+}
+
+nsISupports*
+nsIDocument::GetContainer() const
+{
+  return static_cast<nsIDocShell*>(mDocumentContainer);
 }
 
 void
 nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
 {
 #ifdef DEBUG
   {
     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobalObject));
@@ -4268,17 +4280,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
         JSObject *newScope = aScriptGlobalObject->GetGlobalJSObject();
         NS_ASSERTION(js::GetGlobalForObjectCrossCompartment(obj) == newScope,
                      "Wrong scope, this is really bad!");
       }
     }
 #endif
 
     if (mAllowDNSPrefetch) {
-      nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+      nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
       if (docShell) {
 #ifdef DEBUG
         nsCOMPtr<nsIWebNavigation> webNav =
           do_GetInterface(aScriptGlobalObject);
         NS_ASSERTION(SameCOMIdentity(webNav, docShell),
                      "Unexpected container or script global?");
 #endif
         bool allowDNSPrefetch;
@@ -4367,18 +4379,17 @@ nsDocument::SetIsTopLevelContentDocument
 nsPIDOMWindow *
 nsDocument::GetWindowInternal() const
 {
   MOZ_ASSERT(!mWindow, "This should not be called when mWindow is not null!");
   // Let's use mScriptGlobalObject. Even if the document is already removed from
   // the docshell, the outer window might be still obtainable from the it.
   nsCOMPtr<nsPIDOMWindow> win;
   if (mRemovedFromDocShell) {
-    nsCOMPtr<nsIInterfaceRequestor> requestor =
-      do_QueryReferent(mDocumentContainer);
+    nsCOMPtr<nsIInterfaceRequestor> requestor(mDocumentContainer);
     if (requestor) {
       // The docshell returns the outer window we are done.
       win = do_GetInterface(requestor);
     }
   } else {
     win = do_QueryInterface(mScriptGlobalObject);
     if (win) {
       // mScriptGlobalObject is always the inner window, let's get the outer.
@@ -7795,17 +7806,17 @@ nsDocument::RemovedFromDocShell()
 
 already_AddRefed<nsILayoutHistoryState>
 nsDocument::GetLayoutHistoryState() const
 {
   nsCOMPtr<nsILayoutHistoryState> state;
   if (!mScriptGlobalObject) {
     state = mLayoutHistoryState;
   } else {
-    nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocumentContainer));
+    nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
     if (docShell) {
       docShell->GetLayoutHistoryState(getter_AddRefs(state));
     }
   }
 
   return state.forget();
 }
 
@@ -8316,31 +8327,30 @@ nsDocument::CloneDocHelper(nsDocument* c
   clone->SetPrincipal(NodePrincipal());
   clone->mDocumentBaseURI = mDocumentBaseURI;
 
   if (mCreatingStaticClone) {
     nsCOMPtr<nsILoadGroup> loadGroup;
 
     // |mDocumentContainer| is the container of the document that is being
     // created and not the original container. See CreateStaticClone function().
-    nsCOMPtr<nsIDocumentLoader> docLoader = do_QueryReferent(mDocumentContainer);
+    nsCOMPtr<nsIDocumentLoader> docLoader(mDocumentContainer);
     if (docLoader) {
       docLoader->GetLoadGroup(getter_AddRefs(loadGroup));
     }
     nsCOMPtr<nsIChannel> channel = GetChannel();
     if (channel && loadGroup) {
       clone->Reset(channel, loadGroup);
     } else {
       nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
       if (uri) {
         clone->ResetToURI(uri, loadGroup, NodePrincipal());
       }
     }
-    nsCOMPtr<nsISupports> container = GetContainer();
-    clone->SetContainer(container);
+    clone->SetContainer(mDocumentContainer);
   }
 
   // Set scripting object
   bool hasHadScriptObject = true;
   nsIScriptGlobalObject* scriptObject =
     GetScriptHandlingObject(hasHadScriptObject);
   NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
   if (scriptObject) {
@@ -8847,28 +8857,29 @@ nsIDocument::FlushPendingLinkUpdates()
   mIsLinkUpdateRegistrationsForbidden = true;
 #endif
   mLinksToUpdate.EnumerateEntries(EnumeratePendingLinkUpdates, nullptr);
   mLinksToUpdate.Clear();
   mHasLinksToUpdate = false;
 }
 
 already_AddRefed<nsIDocument>
-nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
+nsIDocument::CreateStaticClone(nsIDocShell* aCloneContainer)
 {
   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
   NS_ENSURE_TRUE(domDoc, nullptr);
   mCreatingStaticClone = true;
 
   // Make document use different container during cloning.
   nsCOMPtr<nsISupports> originalContainer = GetContainer();
-  SetContainer(aCloneContainer);
+  nsCOMPtr<nsIDocShell> originalShell = do_QueryInterface(originalContainer);
+  SetContainer(static_cast<nsDocShell*>(aCloneContainer));
   nsCOMPtr<nsIDOMNode> clonedNode;
   nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
-  SetContainer(originalContainer);
+  SetContainer(static_cast<nsDocShell*>(originalShell.get()));
 
   nsCOMPtr<nsIDocument> clonedDoc;
   if (NS_SUCCEEDED(rv)) {
     clonedDoc = do_QueryInterface(clonedNode);
     if (clonedDoc) {
       if (IsStaticDocument()) {
         clonedDoc->mOriginalDocument = mOriginalDocument;
       } else {
@@ -10526,17 +10537,17 @@ nsDocument::IsFullScreenEnabled(bool aCa
   }
   if (HasFullScreenSubDocument(this)) {
     LogFullScreenDenied(aLogFailure, "FullScreenDeniedSubDocFullScreen", this);
     return false;
   }
 
   // Ensure that all ancestor <iframe> elements have the allowfullscreen
   // boolean attribute set.
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   bool allowed = false;
   if (docShell) {
     docShell->GetFullscreenAllowed(&allowed);
   }
   if (!allowed) {
     LogFullScreenDenied(aLogFailure, "FullScreenDeniedIframeNotAllowed", this);
   }
 
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ImageDocument.h"
 #include "mozilla/dom/ImageDocumentBinding.h"
 #include "nsRect.h"
 #include "nsIImageLoadingContent.h"
 #include "nsGenericHTMLElement.h"
+#include "nsDocShell.h"
 #include "nsIDocumentInlines.h"
 #include "nsDOMTokenList.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrame.h"
@@ -758,17 +759,17 @@ ImageDocument::UpdateTitleAndCharset()
 
   MediaDocument::UpdateTitleAndCharset(typeStr, formatNames,
                                        mImageWidth, mImageHeight, status);
 }
 
 void
 ImageDocument::ResetZoomLevel()
 {
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   if (docShell) {
     if (nsContentUtils::IsChildOfSameType(this)) {
       return;
     }
 
     nsCOMPtr<nsIContentViewer> cv;
     docShell->GetContentViewer(getter_AddRefs(cv));
     nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(cv);
@@ -777,17 +778,17 @@ ImageDocument::ResetZoomLevel()
     }
   }
 }
 
 float
 ImageDocument::GetZoomLevel()
 {
   float zoomLevel = mOriginalZoomLevel;
-  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   if (docShell) {
     nsCOMPtr<nsIContentViewer> cv;
     docShell->GetContentViewer(getter_AddRefs(cv));
     nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(cv);
     if (mdv) {
       mdv->GetFullZoom(&zoomLevel);
     }
   }
--- a/content/html/document/src/moz.build
+++ b/content/html/document/src/moz.build
@@ -27,14 +27,15 @@ FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '../../content/src',
     '/caps/include',
     '/content/base/src',
     '/content/events/src',
+    '/docshell/base',
     '/dom/base',
     '/layout/style',
     '/xpcom/ds',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -27,17 +27,17 @@
 #include "nsDOMString.h"
 #include "nsIStreamListener.h"
 #include "nsIURI.h"
 #include "nsIIOService.h"
 #include "nsNetUtil.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIContentViewer.h"
 #include "nsIMarkupDocumentViewer.h"
-#include "nsIDocShell.h"
+#include "nsDocShell.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIWebNavigation.h"
 #include "nsIBaseWindow.h"
 #include "nsIWebShellServices.h"
 #include "nsIScriptContext.h"
 #include "nsIXPConnect.h"
 #include "nsContentList.h"
 #include "nsError.h"
@@ -1357,17 +1357,17 @@ nsHTMLDocument::Open(JSContext* cx,
 
   nsPIDOMWindow* outer = GetWindow();
   if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) {
     nsCOMPtr<nsIDocument> ret = this;
     return ret.forget();
   }
 
   // check whether we're in the middle of unload.  If so, ignore this call.
-  nsCOMPtr<nsIDocShell> shell = do_QueryReferent(mDocumentContainer);
+  nsCOMPtr<nsIDocShell> shell(mDocumentContainer);
   if (!shell) {
     // We won't be able to create a parser anyway.
     nsCOMPtr<nsIDocument> ret = this;
     return ret.forget();
   }
 
   bool inUnload;
   shell->GetIsInUnload(&inUnload);
--- a/content/xul/document/src/XULDocument.cpp
+++ b/content/xul/document/src/XULDocument.cpp
@@ -33,17 +33,17 @@
 #include "nsViewManager.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMXULElement.h"
 #include "nsIRDFNode.h"
 #include "nsIRDFRemoteDataSource.h"
 #include "nsIRDFService.h"
 #include "nsIStreamListener.h"
 #include "nsITimer.h"
-#include "nsIDocShell.h"
+#include "nsDocShell.h"
 #include "nsGkAtoms.h"
 #include "nsXMLContentSink.h"
 #include "nsXULContentSink.h"
 #include "nsXULContentUtils.h"
 #include "nsIXULOverlayProvider.h"
 #include "nsNetUtil.h"
 #include "nsParserCIID.h"
 #include "nsPIBoxObject.h"
@@ -4655,17 +4655,17 @@ XULDocument::ParserObserver::OnStopReque
     mDocument = nullptr;
 
     return rv;
 }
 
 already_AddRefed<nsPIWindowRoot>
 XULDocument::GetWindowRoot()
 {
-    nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryReferent(mDocumentContainer);
+    nsCOMPtr<nsIInterfaceRequestor> ir(mDocumentContainer);
     nsCOMPtr<nsIDOMWindow> window(do_GetInterface(ir));
     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(window));
     return piWin ? piWin->GetTopWindowRoot() : nullptr;
 }
 
 bool
 XULDocument::IsDocumentRightToLeft()
 {
--- a/content/xul/document/src/moz.build
+++ b/content/xul/document/src/moz.build
@@ -23,16 +23,17 @@ MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/events/src',
     '/content/xbl/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/templates/src',
+    '/docshell/base',
     '/dom/base',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
     '/layout/xul/base/src',
     '/xpcom/ds',
 ]
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7254,29 +7254,29 @@ nsDocShell::CreateAboutBlankContentViewe
     // generate (about:blank) document to load
     docFactory->CreateBlankDocument(mLoadGroup, principal,
                                     getter_AddRefs(blankDoc));
     if (blankDoc) {
       // Hack: set the base URI manually, since this document never
       // got Reset() with a channel.
       blankDoc->SetBaseURI(aBaseURI);
 
-      blankDoc->SetContainer(static_cast<nsIDocShell *>(this));
+      blankDoc->SetContainer(this);
 
       // Copy our sandbox flags to the document. These are immutable
       // after being set here.
       blankDoc->SetSandboxFlags(mSandboxFlags);
 
       // create a content viewer for us and the new document
       docFactory->CreateInstanceForDocument(NS_ISUPPORTS_CAST(nsIDocShell *, this),
                     blankDoc, "view", getter_AddRefs(viewer));
 
       // hook 'em up
       if (viewer) {
-        viewer->SetContainer(static_cast<nsIContentViewerContainer *>(this));
+        viewer->SetContainer(this);
         Embed(viewer, "", 0);
 
         SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, true, 0);
         rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
       }
     }
   }
   mCreatingDocument = false;
@@ -7602,17 +7602,17 @@ nsDocShell::RestorePresentation(nsISHEnt
     }
 
     // We need to make sure the content viewer's container is this docshell.
     // In subframe navigation, it's possible for the docshell that the
     // content viewer was originally loaded into to be replaced with a
     // different one.  We don't currently support restoring the presentation
     // in that case.
 
-    nsCOMPtr<nsISupports> container;
+    nsCOMPtr<nsIDocShell> container;
     viewer->GetContainer(getter_AddRefs(container));
     if (!::SameCOMIdentity(container, GetAsSupports(this))) {
 #ifdef DEBUG_PAGE_CACHE
         printf("No valid container, clearing presentation\n");
 #endif
         aSHEntry->SetContentViewer(nullptr);
         return NS_ERROR_FAILURE;
     }
@@ -8328,23 +8328,23 @@ nsDocShell::NewContentViewerObj(const ch
         return NS_ERROR_FAILURE;
     }
 
     // Now create an instance of the content viewer
     // nsLayoutDLF makes the determination if it should be a "view-source" instead of "view"
     nsresult rv = docLoaderFactory->CreateInstance("view",
                                                    aOpenedChannel,
                                                    aLoadGroup, aContentType,
-                                                   static_cast<nsIContentViewerContainer*>(this),
+                                                   this,
                                                    nullptr,
                                                    aContentHandler,
                                                    aViewer);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    (*aViewer)->SetContainer(static_cast<nsIContentViewerContainer *>(this));
+    (*aViewer)->SetContainer(this);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
 {
     //
     // Copy content viewer state from previous or parent content viewer.
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -13,16 +13,17 @@
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIBaseWindow.h"
 #include "nsIScrollable.h"
 #include "nsITextScroll.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIDOMStorageManager.h"
 #include "nsDocLoader.h"
+#include "mozilla/WeakPtr.h"
 
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 
@@ -132,17 +133,18 @@ class nsDocShell : public nsDocLoader,
                    public nsIRefreshURI,
                    public nsIWebProgressListener,
                    public nsIWebPageDescriptor,
                    public nsIAuthPromptProvider,
                    public nsILoadContext,
                    public nsIWebShellServices,
                    public nsILinkHandler,
                    public nsIClipboardCommands,
-                   public nsIDOMStorageManager
+                   public nsIDOMStorageManager,
+                   public mozilla::SupportsWeakPtr<nsDocShell>
 {
     friend class nsDSURIContentListener;
 
 public:
     // Object Management
     nsDocShell();
 
     NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+interface nsIDocShell;
 interface nsIDOMDocument;
 interface nsISHEntry;
 interface nsIPrintSettings;
 
 
 %{ C++
 class nsIWidget;
 class nsIDocument;
@@ -29,17 +30,17 @@ class nsDOMNavigationTiming;
 
 [scriptable, builtinclass, uuid(b9d92b8b-5623-4079-ae11-36bb341f322e)]
 interface nsIContentViewer : nsISupports
 {
 
   [noscript] void init(in nsIWidgetPtr aParentWidget,
                        [const] in nsIntRectRef aBounds);
 
-  attribute nsISupports container;
+  attribute nsIDocShell container;
 
   void loadStart(in nsISupports aDoc);
   void loadComplete(in nsresult aStatus);
 
   /**
    * Checks if the document wants to prevent unloading by firing beforeunload on
    * the document, and if it does, prompts the user. The result is returned.
    *
--- a/docshell/base/nsIDocumentLoaderFactory.idl
+++ b/docshell/base/nsIDocumentLoaderFactory.idl
@@ -4,35 +4,36 @@
  * 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 "nsISupports.idl"
 
 interface nsIChannel;
 interface nsIContentViewer;
 interface nsIStreamListener;
+interface nsIDocShell;
 interface nsIDocument;
 interface nsILoadGroup;
 interface nsIPrincipal;
 
 /**
  * To get a component that implements nsIDocumentLoaderFactory
  * for a given mimetype, use nsICategoryManager to find an entry
  * with the mimetype as its name in the category "Gecko-Content-Viewers".
  * The value of the entry is the contractid of the component.
  * The component is a service, so use GetService, not CreateInstance to get it.
  */
 
-[scriptable, uuid(5e7d2967-5a07-444f-95d5-25b533252d38)]
+[scriptable, uuid(70905274-8494-4e39-b011-d559adde3733)]
 interface nsIDocumentLoaderFactory : nsISupports {
     nsIContentViewer createInstance(in string aCommand,
                               in nsIChannel aChannel,
                               in nsILoadGroup aLoadGroup,
                               in string aContentType, 
-                              in nsISupports aContainer,
+                              in nsIDocShell aContainer,
                               in nsISupports aExtraInfo,
                               out nsIStreamListener aDocListenerResult);
 
     nsIContentViewer createInstanceForDocument(in nsISupports aContainer,
                                          in nsIDocument aDocument,
                                          in string aCommand);
 
     /**
--- a/docshell/shistory/src/nsSHEntryShared.cpp
+++ b/docshell/shistory/src/nsSHEntryShared.cpp
@@ -5,16 +5,17 @@
 #include "nsSHEntryShared.h"
 
 #include "nsIDOMDocument.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIDocument.h"
 #include "nsIWebNavigation.h"
 #include "nsIContentViewer.h"
+#include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsDocShellEditorData.h"
 #include "nsThreadUtils.h"
 #include "nsILayoutHistoryState.h"
 #include "mozilla/Attributes.h"
 #include "nsISupportsArray.h"
 
 namespace dom = mozilla::dom;
@@ -162,17 +163,17 @@ nsSHEntryShared::DropPresentationState()
 void
 nsSHEntryShared::Expire()
 {
   // This entry has timed out. If we still have a content viewer, we need to
   // evict it.
   if (!mContentViewer) {
     return;
   }
-  nsCOMPtr<nsISupports> container;
+  nsCOMPtr<nsIDocShell> container;
   mContentViewer->GetContainer(getter_AddRefs(container));
   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
   if (!treeItem) {
     return;
   }
   // We need to find the root DocShell since only that object has an
   // SHistory and we need the SHistory to evict content viewers
   nsCOMPtr<nsIDocShellTreeItem> root;
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -106,9 +106,12 @@ SOURCES += [
 ]
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+LOCAL_INCLUDES += [
+    '/docshell/base',
+]
 FINAL_LIBRARY = 'gklayout'
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -31,29 +31,30 @@
 #include "nsISelectionPrivate.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsContentUtils.h"
 #include "nsLayoutStylesheetCache.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/WeakPtr.h"
 
 #include "nsViewManager.h"
 #include "nsView.h"
 
 #include "nsIPageSequenceFrame.h"
 #include "nsNetUtil.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIContentViewerFile.h"
 #include "mozilla/css/Loader.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "nsIDocShell.h"
+#include "nsDocShell.h"
 #include "nsIBaseWindow.h"
 #include "nsILayoutHistoryState.h"
 #include "nsCharsetSource.h"
 #include "nsHTMLReflowState.h"
 #include "nsIImageLoadingContent.h"
 #include "nsCopySupport.h"
 #include "nsIDOMHTMLFrameSetElement.h"
 #ifdef MOZ_XUL
@@ -343,17 +344,17 @@ protected:
   void DetachFromTopLevelWidget();
 
   // IMPORTANT: The ownership implicit in the following member
   // variables has been explicitly checked and set using nsCOMPtr
   // for owning pointers and raw COM interface pointers for weak
   // (ie, non owning) references. If you add any members to this
   // class, please make the ownership explicit (pinkerton, scc).
 
-  nsWeakPtr mContainer; // it owns me!
+  WeakPtr<nsDocShell> mContainer; // it owns me!
   nsWeakPtr mTopContainerWhilePrinting;
   nsRefPtr<nsDeviceContext> mDeviceContext;  // We create and own this baby
 
   // the following six items are explicitly in this order
   // so they will be destroyed in the reverse order (pinkerton, scc)
   nsCOMPtr<nsIDocument>    mDocument;
   nsCOMPtr<nsIWidget>      mWindow;      // may be null
   nsRefPtr<nsViewManager> mViewManager;
@@ -571,17 +572,17 @@ nsDocumentViewer::LoadStart(nsISupports 
   }
 
   return rv;
 }
 
 nsresult
 nsDocumentViewer::SyncParentSubDocMap()
 {
-  nsCOMPtr<nsIDocShellTreeItem> item(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeItem> item(mContainer);
   nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(item));
   nsCOMPtr<nsIContent> content;
 
   if (mDocument && pwin) {
     content = do_QueryInterface(pwin->GetFrameElementInternal());
   }
 
   if (content) {
@@ -605,37 +606,36 @@ nsDocumentViewer::SyncParentSubDocMap()
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocumentViewer::SetContainer(nsISupports* aContainer)
+nsDocumentViewer::SetContainer(nsIDocShell* aContainer)
 {
-  mContainer = do_GetWeakReference(aContainer);
+  mContainer = static_cast<nsDocShell*>(aContainer)->asWeakPtr();
   if (mPresContext) {
     mPresContext->SetContainer(aContainer);
   }
 
   // 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();
 }
 
 NS_IMETHODIMP
-nsDocumentViewer::GetContainer(nsISupports** aResult)
+nsDocumentViewer::GetContainer(nsIDocShell** aResult)
 {
    NS_ENSURE_ARG_POINTER(aResult);
 
-   *aResult = nullptr;
-   nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
+   nsCOMPtr<nsIDocShell> container(mContainer);
    container.swap(*aResult);
    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Init(nsIWidget* aParentWidget,
                          const nsIntRect& aBounds)
 {
@@ -868,17 +868,17 @@ nsDocumentViewer::InitInternal(nsIWidget
       // Avoid leaking the old viewer.
       if (mPreviousViewer) {
         mPreviousViewer->Destroy();
         mPreviousViewer = nullptr;
       }
     }
   }
 
-  nsCOMPtr<nsIInterfaceRequestor> requestor(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIInterfaceRequestor> requestor(mContainer);
   if (requestor) {
     if (mPresContext) {
       nsCOMPtr<nsILinkHandler> linkHandler;
       requestor->GetInterface(NS_GET_IID(nsILinkHandler),
                               getter_AddRefs(linkHandler));
 
       mPresContext->SetContainer(requestor);
       mPresContext->SetLinkHandler(linkHandler);
@@ -1102,17 +1102,17 @@ nsDocumentViewer::PermitUnload(bool aCal
     nsEventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext,
                                         nullptr);
     mInPermitUnload = false;
     if (dialogsWereEnabled) {
       utils->EnableDialogs();
     }
   }
 
-  nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeNode> docShellNode(mContainer);
   nsAutoString text;
   beforeUnload->GetReturnValue(text);
   if (event->GetInternalNSEvent()->mFlags.mDefaultPrevented ||
       !text.IsEmpty()) {
     // Ask the user if it's ok to unload the current page
 
     nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShellNode);
 
@@ -1193,17 +1193,17 @@ nsDocumentViewer::PermitUnload(bool aCal
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::ResetCloseWindow()
 {
   mCallerIsClosingWindow = false;
 
-  nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeNode> docShellNode(mContainer);
   if (docShellNode) {
     int32_t childCount;
     docShellNode->GetChildCount(&childCount);
 
     for (int32_t i = 0; i < childCount; ++i) {
       nsCOMPtr<nsIDocShellTreeItem> item;
       docShellNode->GetChildAt(i, getter_AddRefs(item));
 
@@ -1281,17 +1281,17 @@ nsDocumentViewer::PageHide(bool aIsUnloa
 static void
 AttachContainerRecurse(nsIDocShell* aShell)
 {
   nsCOMPtr<nsIContentViewer> viewer;
   aShell->GetContentViewer(getter_AddRefs(viewer));
   if (viewer) {
     nsIDocument* doc = viewer->GetDocument();
     if (doc) {
-      doc->SetContainer(aShell);
+      doc->SetContainer(static_cast<nsDocShell*>(aShell));
     }
     nsRefPtr<nsPresContext> pc;
     viewer->GetPresContext(getter_AddRefs(pc));
     if (pc) {
       pc->SetContainer(aShell);
       pc->SetLinkHandler(nsCOMPtr<nsILinkHandler>(do_QueryInterface(aShell)));
     }
     nsCOMPtr<nsIPresShell> presShell;
@@ -1312,17 +1312,17 @@ AttachContainerRecurse(nsIDocShell* aShe
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Open(nsISupports *aState, nsISHEntry *aSHEntry)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
 
   if (mDocument)
-    mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
+    mDocument->SetContainer(mContainer);
 
   nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHidden = false;
 
   if (mPresShell)
     mPresShell->SetForwardingContainer(nullptr);
@@ -1556,18 +1556,21 @@ nsDocumentViewer::Destroy()
 
     if (mDocument) {
       mDocument->SetContainer(nullptr);
     }
     if (mPresContext) {
       mPresContext->SetLinkHandler(nullptr);
       mPresContext->SetContainer(nullptr);
     }
-    if (mPresShell)
-      mPresShell->SetForwardingContainer(mContainer);
+    if (mPresShell) {
+      nsWeakPtr container =
+        do_GetWeakReference(static_cast<nsIDocShell*>(mContainer));
+      mPresShell->SetForwardingContainer(container);
+    }
 
     // Do the same for our children.  Note that we need to get the child
     // docshells from the SHEntry now; the docshell will have cleared them.
     nsCOMPtr<nsIDocShellTreeItem> item;
     int32_t itemIndex = 0;
     while (NS_SUCCEEDED(shEntry->ChildShellAt(itemIndex++,
                                               getter_AddRefs(item))) && item) {
       DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(item)));
@@ -1615,17 +1618,17 @@ nsDocumentViewer::Destroy()
   mDeviceContext = nullptr;
 
   if (mPresContext) {
     DestroyPresContext();
   }
 
   mWindow = nullptr;
   mViewManager = nullptr;
-  mContainer = nullptr;
+  mContainer = WeakPtr<nsDocShell>();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::Stop(void)
 {
   NS_ASSERTION(mDocument, "Stop called too early or too late");
@@ -1686,38 +1689,38 @@ nsDocumentViewer::SetDOMDocument(nsIDOMD
 
 NS_IMETHODIMP
 nsDocumentViewer::SetDocumentInternal(nsIDocument* aDocument,
                                         bool aForceReuseInnerWindow)
 {
   MOZ_ASSERT(aDocument);
 
   // Set new container
-  nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
-  aDocument->SetContainer(container);
+  aDocument->SetContainer(mContainer);
 
   if (mDocument != aDocument) {
     if (mDocument->IsStaticDocument()) {
       mDocument->SetScriptGlobalObject(nullptr);
       mDocument->Destroy();
     }
     // Replace the old document with the new one. Do this only when
     // the new document really is a new document.
     mDocument = aDocument;
 
     // Set the script global object on the new document
-    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
+    nsCOMPtr<nsPIDOMWindow> window =
+      do_GetInterface(static_cast<nsIDocShell*>(mContainer.get()));
     if (window) {
       window->SetNewDocument(aDocument, nullptr, aForceReuseInnerWindow);
     }
 
     // Clear the list of old child docshells. Child docshells for the new
     // document will be constructed as frames are created.
     if (!aDocument->IsStaticDocument()) {
-      nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
+      nsCOMPtr<nsIDocShellTreeNode> node(mContainer);
       if (node) {
         int32_t count;
         node->GetChildCount(&count);
         for (int32_t i = 0; i < count; ++i) {
           nsCOMPtr<nsIDocShellTreeItem> child;
           node->GetChildAt(0, getter_AddRefs(child));
           node->RemoveChild(child);
         }
@@ -1883,17 +1886,17 @@ nsDocumentViewer::Show(void)
   if (mPreviousViewer) {
     // This little dance *may* only be to keep
     // PresShell::EndObservingDocument happy, but I'm not sure.
     nsCOMPtr<nsIContentViewer> prevViewer(mPreviousViewer);
     mPreviousViewer = nullptr;
     prevViewer->Destroy();
 
     // Make sure we don't have too many cached ContentViewers
-    nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryReferent(mContainer);
+    nsCOMPtr<nsIDocShellTreeItem> treeItem(mContainer);
     if (treeItem) {
       // We need to find the root DocShell since only that object has an
       // SHistory and we need the SHistory to evict content viewers
       nsCOMPtr<nsIDocShellTreeItem> root;
       treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
       nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
       nsCOMPtr<nsISHistory> history;
       webNav->GetSessionHistory(getter_AddRefs(history));
@@ -1919,17 +1922,17 @@ nsDocumentViewer::Show(void)
     if (!mAttachedToParent) {
       mWindow->Show(true);
     }
   }
 
   if (mDocument && !mPresShell) {
     NS_ASSERTION(!mWindow, "Window already created but no presshell?");
 
-    nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
+    nsCOMPtr<nsIBaseWindow> base_win(mContainer);
     if (base_win) {
       base_win->GetParentWidget(&mParentWidget);
       if (mParentWidget) {
         mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
       }
     }
 
     nsView* containerView = FindContainerView();
@@ -2009,32 +2012,32 @@ nsDocumentViewer::Hide(void)
   if (mIsSticky) {
     // This window is sticky, that means that it might be shown again
     // and we don't want the presshell n' all that to be thrown away
     // just because the window is hidden.
 
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShell> docShell(mContainer);
   if (docShell) {
     nsCOMPtr<nsILayoutHistoryState> layoutState;
     mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
   }
 
   DestroyPresShell();
 
   DestroyPresContext();
 
   mViewManager   = nullptr;
   mWindow        = nullptr;
   mDeviceContext = nullptr;
   mParentWidget  = nullptr;
 
-  nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIBaseWindow> base_win(mContainer);
 
   if (base_win && !mAttachedToParent) {
     base_win->SetParentWidget(nullptr);
   }
 
   return NS_OK;
 }
 
@@ -2109,17 +2112,17 @@ nsDocumentViewer::CreateStyleSet(nsIDocu
 
   if (sheet)
     styleSet->AppendStyleSheet(nsStyleSet::eUserSheet, sheet);
 
   // Append chrome sheets (scrollbars + forms).
   bool shouldOverride = false;
   // We don't want a docshell here for external resource docs, so just
   // look at mContainer.
-  nsCOMPtr<nsIDocShell> ds(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShell> ds(mContainer);
   nsCOMPtr<nsIDOMEventTarget> chromeHandler;
   nsCOMPtr<nsIURI> uri;
   nsRefPtr<nsCSSStyleSheet> csssheet;
 
   if (ds) {
     ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
   }
   if (chromeHandler) {
@@ -2298,17 +2301,17 @@ nsDocumentViewer::DetachFromTopLevelWidg
 }
 
 nsView*
 nsDocumentViewer::FindContainerView()
 {
   nsView* containerView = nullptr;
 
   if (mContainer) {
-    nsCOMPtr<nsIDocShellTreeItem> docShellItem = do_QueryReferent(mContainer);
+    nsCOMPtr<nsIDocShellTreeItem> docShellItem(mContainer);
     nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(docShellItem));
     if (pwin) {
       nsCOMPtr<nsIContent> containerElement = do_QueryInterface(pwin->GetFrameElementInternal());
       if (!containerElement) {
         return nullptr;
       }
       nsCOMPtr<nsIPresShell> parentPresShell;
       if (docShellItem) {
@@ -2495,17 +2498,17 @@ NS_IMETHODIMP nsDocumentViewer::CopyLink
 NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
   nsCOMPtr<nsIImageLoadingContent> node;
   GetPopupImageNode(getter_AddRefs(node));
   // make noise if we're not in an image
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsILoadContext> loadContext(do_QueryReferent(mContainer));
+  nsCOMPtr<nsILoadContext> loadContext(mContainer);
   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
 }
 
 
 NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool *aCopyable)
 {
   NS_ENSURE_ARG_POINTER(aCopyable);
   *aCopyable = nsCopySupport::CanCopy(mDocument);
@@ -2627,17 +2630,17 @@ NS_IMETHODIMP nsDocumentViewer::ScrollTo
                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
     NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 void
 nsDocumentViewer::CallChildren(CallChildFunc aFunc, void* aClosure)
 {
-  nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeNode> docShellNode(mContainer);
   if (docShellNode)
   {
     int32_t i;
     int32_t n;
     docShellNode->GetChildCount(&n);
     for (i=0; i < n; i++)
     {
       nsCOMPtr<nsIDocShellTreeItem> child;
@@ -3221,17 +3224,17 @@ NS_IMETHODIMP nsDocumentViewer::ChangeMa
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight)
 {
    NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
    // Skip doing this on docshell-less documents for now
-   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryReferent(mContainer));
+   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(mContainer);
    NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_NOT_AVAILABLE);
    
    nsCOMPtr<nsIDocShellTreeItem> docShellParent;
    docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent));
 
    // It's only valid to access this from a top frame.  Doesn't work from
    // sub-frames.
    NS_ENSURE_TRUE(!docShellParent, NS_ERROR_FAILURE);
@@ -3549,17 +3552,17 @@ nsDocumentViewer::Print(nsIPrintSettings
   }
 #endif
 
   if (!mContainer) {
     PR_PL(("Container was destroyed yet we are still trying to use it!"));
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShell> docShell(mContainer);
   NS_ENSURE_STATE(docShell);
 
   // Check to see if this document is still busy
   // If it is busy and we aren't already "queued" up to print then
   // Indicate there is a print pending and cache the args for later
   uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
   if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
        (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && 
@@ -3659,17 +3662,17 @@ nsDocumentViewer::PrintPreview(nsIPrintS
   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
   if (xulDoc) {
     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
     nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, false);
     return NS_ERROR_FAILURE;
   }
 #endif
 
-  nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShell> docShell(mContainer);
   if (!docShell || !mDeviceContext) {
     PR_PL(("Can't Print Preview without device context and docshell"));
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   aChildDOMWin->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
@@ -4025,17 +4028,17 @@ nsDocumentViewer::SetIsPrintingInDocShel
 #endif // NS_PRINTING
 
 bool
 nsDocumentViewer::ShouldAttachToTopLevel()
 {
   if (!mParentWidget)
     return false;
 
-  nsCOMPtr<nsIDocShellTreeItem> containerItem = do_QueryReferent(mContainer);
+  nsCOMPtr<nsIDocShellTreeItem> containerItem(mContainer);
   if (!containerItem)
     return false;
 
   // We always attach when using puppet widgets
   if (nsIWidget::UsePuppetWidgets())
     return true;
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
@@ -4093,17 +4096,17 @@ nsDocumentViewer::GetIsPrinting()
 //------------------------------------------------------------
 // Notification from the PrintEngine of the current Printing status
 void
 nsDocumentViewer::SetIsPrinting(bool aIsPrinting)
 {
 #ifdef NS_PRINTING
   // Set all the docShells in the docshell tree to be printing.
   // that way if anyone of them tries to "navigate" it can't
-  nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(mContainer);
   if (docShellTreeNode || !aIsPrinting) {
     SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrinting, true);
   } else {
     NS_WARNING("Did you close a window before printing?");
   }
 
   if (!aIsPrinting) {
     mBeforeAndAfterPrint = nullptr;
@@ -4129,17 +4132,17 @@ nsDocumentViewer::GetIsPrintPreview()
 //------------------------------------------------------------
 // Notification from the PrintEngine of the current PP status
 void
 nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview)
 {
 #ifdef NS_PRINTING
   // Set all the docShells in the docshell tree to be printing.
   // that way if anyone of them tries to "navigate" it can't
-  nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(mContainer);
   if (docShellTreeNode || !aIsPrintPreview) {
     SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, true);
   }
   if (!aIsPrintPreview) {
     mBeforeAndAfterPrint = nullptr;
   }
 #endif
   if (!aIsPrintPreview) {
@@ -4203,17 +4206,17 @@ nsDocumentViewer::ReturnToGalleyPresenta
   }
 
   SetIsPrintPreview(false);
 
   mPrintEngine->TurnScriptingOn(true);
   mPrintEngine->Destroy();
   mPrintEngine = nullptr;
 
-  nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
+  nsCOMPtr<nsIDocShell> docShell(mContainer);
   ResetFocusState(docShell);
 
   SetTextZoom(mTextZoom);
   SetFullZoom(mPageZoom);
   SetMinFontSize(mMinFontSize);
   Show();
 
 #endif // NS_PRINTING && NS_PRINT_PREVIEW
@@ -4242,18 +4245,18 @@ nsDocumentViewer::OnDonePrinting()
     } else {
       mPrintEngine = nullptr;
       pe->Destroy();
     }
 
     // We are done printing, now cleanup 
     if (mDeferredWindowClose) {
       mDeferredWindowClose = false;
-      nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
-      nsCOMPtr<nsIDOMWindow> win = do_GetInterface(container);
+      nsCOMPtr<nsIDOMWindow> win =
+        do_GetInterface(static_cast<nsIDocShell*>(mContainer));
       if (win)
         win->Close();
     } else if (mClosingWhilePrinting) {
       if (mDocument) {
         mDocument->SetScriptGlobalObject(nullptr);
         mDocument->Destroy();
         mDocument = nullptr;
       }
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -24,9 +24,12 @@ if CONFIG['MOZ_NFC']:
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LIBRARY_NAME = 'gklayout'
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+LOCAL_INCLUDES += [
+    '/docshell/base',
+]
 FINAL_LIBRARY = 'xul'
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* 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 "nsCOMPtr.h"
 #include "nsContentDLF.h"
+#include "nsDocShell.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsIContentViewer.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIDocument.h"
@@ -130,17 +131,17 @@ MayUseXULXBL(nsIChannel* aChannel)
   return nsContentUtils::AllowXULXBLForPrincipal(principal);
 }
 
 NS_IMETHODIMP
 nsContentDLF::CreateInstance(const char* aCommand,
                              nsIChannel* aChannel,
                              nsILoadGroup* aLoadGroup,
                              const char* aContentType, 
-                             nsISupports* aContainer,
+                             nsIDocShell* aContainer,
                              nsISupports* aExtraInfo,
                              nsIStreamListener** aDocListener,
                              nsIContentViewer** aDocViewer)
 {
   // Declare "type" here.  This is because although the variable itself only
   // needs limited scope, we need to use the raw string memory -- as returned
   // by "type.get()" farther down in the function.
   nsAutoCString type;
@@ -365,17 +366,17 @@ nsContentDLF::CreateBlankDocument(nsILoa
   return rv;
 }
 
 
 nsresult
 nsContentDLF::CreateDocument(const char* aCommand,
                              nsIChannel* aChannel,
                              nsILoadGroup* aLoadGroup,
-                             nsISupports* aContainer,
+                             nsIDocShell* aContainer,
                              const nsCID& aDocumentCID,
                              nsIStreamListener** aDocListener,
                              nsIContentViewer** aContentViewer)
 {
   nsresult rv = NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIURI> aURL;
   rv = aChannel->GetURI(getter_AddRefs(aURL));
@@ -394,17 +395,17 @@ nsContentDLF::CreateDocument(const char*
   nsCOMPtr<nsIDocument> doc = do_CreateInstance(aDocumentCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create the content viewer  XXX: could reuse content viewer here!
   nsCOMPtr<nsIContentViewer> contentViewer;
   rv = NS_NewContentViewer(getter_AddRefs(contentViewer));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  doc->SetContainer(aContainer);
+  doc->SetContainer(static_cast<nsDocShell*>(aContainer));
 
   // Initialize the document to begin loading the data.  An
   // nsIStreamListener connected to the parser is returned in
   // aDocListener.
   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Bind the document to the Content Viewer
@@ -413,17 +414,17 @@ nsContentDLF::CreateDocument(const char*
   return rv;
 }
 
 nsresult
 nsContentDLF::CreateXULDocument(const char* aCommand,
                                 nsIChannel* aChannel,
                                 nsILoadGroup* aLoadGroup,
                                 const char* aContentType,
-                                nsISupports* aContainer,
+                                nsIDocShell* aContainer,
                                 nsISupports* aExtraInfo,
                                 nsIStreamListener** aDocListener,
                                 nsIContentViewer** aContentViewer)
 {
   nsresult rv;
   nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv);
   if (NS_FAILED(rv)) return rv;
 
@@ -437,17 +438,17 @@ nsContentDLF::CreateXULDocument(const ch
 
   /* 
    * Initialize the document to begin loading the data...
    *
    * An nsIStreamListener connected to the parser is returned in
    * aDocListener.
    */
 
-  doc->SetContainer(aContainer);
+  doc->SetContainer(static_cast<nsDocShell*>(aContainer));
 
   rv = doc->StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, true);
   if (NS_FAILED(rv)) return rv;
 
   /*
    * Bind the document to the Content Viewer...
    */
   rv = contentViewer->LoadStart(doc);
--- a/layout/build/nsContentDLF.h
+++ b/layout/build/nsContentDLF.h
@@ -28,26 +28,26 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOCUMENTLOADERFACTORY
 
   nsresult InitUAStyleSheet();
 
   nsresult CreateDocument(const char* aCommand,
                           nsIChannel* aChannel,
                           nsILoadGroup* aLoadGroup,
-                          nsISupports* aContainer,
+                          nsIDocShell* aContainer,
                           const nsCID& aDocumentCID,
                           nsIStreamListener** aDocListener,
                           nsIContentViewer** aContentViewer);
 
   nsresult CreateXULDocument(const char* aCommand,
                              nsIChannel* aChannel,
                              nsILoadGroup* aLoadGroup,
                              const char* aContentType,
-                             nsISupports* aContainer,
+                             nsIDocShell* aContainer,
                              nsISupports* aExtraInfo,
                              nsIStreamListener** aDocListener,
                              nsIContentViewer** aContentViewer);
 
 private:
   static nsresult EnsureUAStyleSheet();
   static bool IsImageContentType(const char* aContentType);
 };
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -288,27 +288,27 @@ void nsPrintEngine::DestroyPrintingData(
 }
 
 //---------------------------------------------------------------------------------
 //-- Section: Methods needed by the DocViewer
 //---------------------------------------------------------------------------------
 
 //--------------------------------------------------------
 nsresult nsPrintEngine::Initialize(nsIDocumentViewerPrint* aDocViewerPrint, 
-                                   nsIWeakReference*       aContainer,
+                                   nsIDocShell*            aContainer,
                                    nsIDocument*            aDocument,
                                    float                   aScreenDPI,
                                    FILE*                   aDebugFile)
 {
   NS_ENSURE_ARG_POINTER(aDocViewerPrint);
   NS_ENSURE_ARG_POINTER(aContainer);
   NS_ENSURE_ARG_POINTER(aDocument);
 
   mDocViewerPrint = aDocViewerPrint;
-  mContainer      = aContainer;
+  mContainer      = do_GetWeakReference(aContainer);
   mDocument       = aDocument;
   mScreenDPI      = aScreenDPI;
 
   mDebugFile      = aDebugFile;      // ok to be nullptr
 
   return NS_OK;
 }
 
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -77,17 +77,17 @@ public:
 
   nsPrintEngine();
   ~nsPrintEngine();
 
   void Destroy();
   void DestroyPrintingData();
 
   nsresult Initialize(nsIDocumentViewerPrint* aDocViewerPrint, 
-                      nsIWeakReference*       aContainer,
+                      nsIDocShell*            aContainer,
                       nsIDocument*            aDocument,
                       float                   aScreenDPI,
                       FILE*                   aDebugFile);
 
   nsresult GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, int32_t& aCount);
 
   //
   // The following three methods are used for printing...
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -18,16 +18,17 @@
 #include "nsIApplicationCacheContainer.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheService.h"
 #include "nsICache.h"
 #include "nsICacheService.h"
 #include "nsICacheSession.h"
 #include "nsICachingChannel.h"
 #include "nsIContent.h"
+#include "nsIDocShell.h"
 #include "nsIDocumentLoader.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMOfflineResourceList.h"
 #include "nsIDocument.h"
 #include "nsIObserverService.h"
 #include "nsIURL.h"
 #include "nsIWebProgress.h"
@@ -373,18 +374,17 @@ NS_IMETHODIMP
 nsOfflineCacheUpdateService::ScheduleOnDocumentStop(nsIURI *aManifestURI,
                                                     nsIURI *aDocumentURI,
                                                     nsIDOMDocument *aDocument)
 {
     LOG(("nsOfflineCacheUpdateService::ScheduleOnDocumentStop [%p, manifestURI=%p, documentURI=%p doc=%p]",
          this, aManifestURI, aDocumentURI, aDocument));
 
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
-    nsCOMPtr<nsISupports> container = doc->GetContainer();
-    nsCOMPtr<nsIWebProgress> progress = do_QueryInterface(container);
+    nsCOMPtr<nsIWebProgress> progress = do_QueryInterface(doc->GetContainer());
     NS_ENSURE_TRUE(progress, NS_ERROR_INVALID_ARG);
 
     // Proceed with cache update
     nsRefPtr<nsOfflineCachePendingUpdate> update =
         new nsOfflineCachePendingUpdate(this, aManifestURI,
                                         aDocumentURI, aDocument);
     NS_ENSURE_TRUE(update, NS_ERROR_OUT_OF_MEMORY);
 
--- a/xpfe/components/directory/nsDirectoryViewer.cpp
+++ b/xpfe/components/directory/nsDirectoryViewer.cpp
@@ -12,16 +12,17 @@
 
   One added change is for a description entry, for when the
   target does not match the filename
 
 */
 
 #include "nsDirectoryViewer.h"
 #include "nsIDirIndex.h"
+#include "nsIDocShell.h"
 #include "jsapi.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include "nsEnumeratorUtils.h"
 #include "nsEscape.h"
 #include "nsIRDFService.h"
 #include "nsRDFCID.h"
 #include "rdf.h"
@@ -1260,17 +1261,17 @@ NS_IMPL_ISUPPORTS1(nsDirectoryViewerFact
 
 
 
 NS_IMETHODIMP
 nsDirectoryViewerFactory::CreateInstance(const char *aCommand,
                                          nsIChannel* aChannel,
                                          nsILoadGroup* aLoadGroup,
                                          const char* aContentType, 
-                                         nsISupports* aContainer,
+                                         nsIDocShell* aContainer,
                                          nsISupports* aExtraInfo,
                                          nsIStreamListener** aDocListenerResult,
                                          nsIContentViewer** aDocViewerResult)
 {
   nsresult rv;
 
   bool viewSource = (PL_strstr(aContentType,"view-source") != 0);