Bug 1485279 - Merge nsISHContainer into nsISHEntry. r=qdot
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 22 Aug 2018 19:20:56 +1000
changeset 488065 6d3cc173cddeccedbad05d45d9bad8afb3466e9e
parent 488064 33169047e42572dbd7c2fa6ec62034937bc0f7fc
child 488066 394f359ada2d0523879dae282e8080a379a42d7a
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1485279
milestone63.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 1485279 - Merge nsISHContainer into nsISHEntry. r=qdot nsSHEntry is the only class that instantiates those two interfaces, so the separation is not useful. This lets us remove numerous pointless QIs.
browser/components/sessionstore/test/browser_687710_2.js
browser/components/sessionstore/test/browser_705597.js
browser/components/sessionstore/test/browser_707862.js
docshell/base/nsDocShell.cpp
docshell/shistory/moz.build
docshell/shistory/nsISHContainer.idl
docshell/shistory/nsISHEntry.idl
docshell/shistory/nsISHistoryInternal.idl
docshell/shistory/nsSHEntry.cpp
docshell/shistory/nsSHEntry.h
docshell/shistory/nsSHistory.cpp
docshell/test/navigation/test_bug1375833.html
docshell/test/test_bug590573.html
dom/base/nsCCUncollectableMarker.cpp
toolkit/modules/sessionstore/SessionHistory.jsm
--- a/browser/components/sessionstore/test/browser_687710_2.js
+++ b/browser/components/sessionstore/test/browser_687710_2.js
@@ -25,23 +25,18 @@ var state = {entries: [
   }
 ]};
 
 add_task(async function test() {
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
   await promiseTabState(tab, state);
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     function compareEntries(i, j, history) {
-      let e1 = history.getEntryAtIndex(i, false)
-                      .QueryInterface(Ci.nsISHEntry)
-                      .QueryInterface(Ci.nsISHContainer);
-
-      let e2 = history.getEntryAtIndex(j, false)
-                      .QueryInterface(Ci.nsISHEntry)
-                      .QueryInterface(Ci.nsISHContainer);
+      let e1 = history.getEntryAtIndex(i, false);
+      let e2 = history.getEntryAtIndex(j, false);
 
       ok(e1.sharesDocumentWith(e2),
          `${i} should share doc with ${j}`);
       is(e1.childCount, e2.childCount,
          `Child count mismatch (${i}, ${j})`);
 
       for (let c = 0; c < e1.childCount; c++) {
         let c1 = e1.GetChildAt(c);
--- a/browser/components/sessionstore/test/browser_705597.js
+++ b/browser/components/sessionstore/test/browser_705597.js
@@ -20,17 +20,16 @@ function test() {
 
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
 
   let browser = tab.linkedBrowser;
 
   promiseTabState(tab, tabState).then(() => {
     let sessionHistory = browser.sessionHistory;
     let entry = sessionHistory.legacySHistory.getEntryAtIndex(0, false);
-    entry.QueryInterface(Ci.nsISHContainer);
 
     whenChildCount(entry, 1, function() {
       whenChildCount(entry, 2, function() {
         promiseBrowserLoaded(browser).then(() => {
           return TabStateFlusher.flush(browser);
         }).then(() => {
           let {entries} = JSON.parse(ss.getTabState(tab));
           is(entries.length, 1, "tab has one history entry");
--- a/browser/components/sessionstore/test/browser_707862.js
+++ b/browser/components/sessionstore/test/browser_707862.js
@@ -20,17 +20,16 @@ function test() {
 
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
 
   let browser = tab.linkedBrowser;
 
   promiseTabState(tab, tabState).then(() => {
     let sessionHistory = browser.sessionHistory;
     let entry = sessionHistory.legacySHistory.getEntryAtIndex(0, false);
-    entry.QueryInterface(Ci.nsISHContainer);
 
     whenChildCount(entry, 1, function() {
       whenChildCount(entry, 2, function() {
         promiseBrowserLoaded(browser).then(() => {
           let newSessionHistory = browser.sessionHistory;
           let newEntry = newSessionHistory.legacySHistory.getEntryAtIndex(0, false);
 
           whenChildCount(newEntry, 0, function() {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -112,17 +112,16 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsIScrollObserver.h"
 #include "nsISecureBrowserUI.h"
 #include "nsISecurityUITelemetry.h"
 #include "nsISeekableStream.h"
 #include "nsISelectionDisplay.h"
-#include "nsISHContainer.h"
 #include "nsISHEntry.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsISiteSecurityService.h"
 #include "nsISocketProvider.h"
 #include "nsIStringBundle.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsISupportsPrimitives.h"
@@ -1064,20 +1063,19 @@ nsDocShell::FirePageHideNotificationInte
         // Skip checking dynamic subframe entries in our children.
         child->FirePageHideNotificationInternal(aIsUnload, true);
       }
     }
 
     // If the document is unloading, remove all dynamic subframe entries.
     if (aIsUnload && !aSkipCheckingDynEntries) {
       RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
-      nsCOMPtr<nsISHContainer> container(do_QueryInterface(mOSHE));
-      if (rootSH && container) {
+      if (rootSH && mOSHE) {
         int32_t index = rootSH->Index();
-        rootSH->LegacySHistoryInternal()->RemoveDynEntries(index, container);
+        rootSH->LegacySHistoryInternal()->RemoveDynEntries(index, mOSHE);
       }
     }
 
     // Now make sure our editor, if any, is detached before we go
     // any farther.
     DetachEditorFromWindow();
   }
 }
@@ -3724,50 +3722,43 @@ nsDocShell::GetChildSHEntry(int32_t aChi
      *  from cache, we do not want to load the child frame from history.
      */
     if (parentExpired && (loadType == LOAD_RELOAD_NORMAL)) {
       // The parent has expired. Return null.
       *aResult = nullptr;
       return rv;
     }
 
-    nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE));
-    if (container) {
-      // Get the child subframe from session history.
-      rv = container->GetChildAt(aChildOffset, aResult);
-      if (*aResult) {
-        (*aResult)->SetLoadType(loadType);
-      }
+    // Get the child subframe from session history.
+    rv = mLSHE->GetChildAt(aChildOffset, aResult);
+    if (*aResult) {
+      (*aResult)->SetLoadType(loadType);
     }
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
                             int32_t aChildOffset, uint32_t aLoadType,
                             bool aCloneChildren)
 {
   nsresult rv = NS_OK;
 
   if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
     /* You get here if you are currently building a
      * hierarchy ie.,you just visited a frameset page
      */
-    nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE, &rv));
-    if (container) {
-      if (NS_FAILED(container->ReplaceChild(aNewEntry))) {
-        rv = container->AddChild(aNewEntry, aChildOffset);
-      }
+    if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))) {
+      rv = mLSHE->AddChild(aNewEntry, aChildOffset);
     }
   } else if (!aCloneRef) {
     /* This is an initial load in some subframe.  Just append it if we can */
-    nsCOMPtr<nsISHContainer> container(do_QueryInterface(mOSHE, &rv));
-    if (container) {
-      rv = container->AddChild(aNewEntry, aChildOffset);
+    if (mOSHE) {
+      rv = mOSHE->AddChild(aNewEntry, aChildOffset);
     }
   } else {
     rv = AddChildSHEntryInternal(aCloneRef, aNewEntry, aChildOffset,
                                  aLoadType, aCloneChildren);
   }
   return rv;
 }
 
@@ -3992,28 +3983,27 @@ nsDocShell::GetDeviceSizeIsPageSize(bool
 {
   *aValue = mDeviceSizeIsPageSize;
   return NS_OK;
 }
 
 void
 nsDocShell::ClearFrameHistory(nsISHEntry* aEntry)
 {
-  nsCOMPtr<nsISHContainer> shcontainer = do_QueryInterface(aEntry);
   RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
-  if (!rootSH || !shcontainer) {
+  if (!rootSH || !aEntry) {
     return;
   }
 
   int32_t count = 0;
-  shcontainer->GetChildCount(&count);
+  aEntry->GetChildCount(&count);
   AutoTArray<nsID, 16> ids;
   for (int32_t i = 0; i < count; ++i) {
     nsCOMPtr<nsISHEntry> child;
-    shcontainer->GetChildAt(i, getter_AddRefs(child));
+    aEntry->GetChildAt(i, getter_AddRefs(child));
     if (child) {
       ids.AppendElement(child->DocshellID());
     }
   }
   int32_t index = rootSH->Index();
   rootSH->LegacySHistoryInternal()->RemoveEntries(ids, index);
 }
 
@@ -12039,25 +12029,24 @@ nsDocShell::AddToSessionHistory(nsIURI* 
    * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
    * the existing SH entry in the page and replace the url and
    * other vitalities.
    */
   if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY) &&
       root != static_cast<nsIDocShellTreeItem*>(this)) {
     // This is a subframe
     entry = mOSHE;
-    nsCOMPtr<nsISHContainer> shContainer(do_QueryInterface(entry));
-    if (shContainer) {
+    if (entry) {
       int32_t childCount = 0;
-      shContainer->GetChildCount(&childCount);
+      entry->GetChildCount(&childCount);
       // Remove all children of this entry
       for (int32_t i = childCount - 1; i >= 0; i--) {
         nsCOMPtr<nsISHEntry> child;
-        shContainer->GetChildAt(i, getter_AddRefs(child));
-        shContainer->RemoveChild(child);
+        entry->GetChildAt(i, getter_AddRefs(child));
+        entry->RemoveChild(child);
       }
       entry->AbandonBFCacheEntry();
     }
   }
 
   // Create a new entry if necessary.
   if (!entry) {
     entry = do_CreateInstance(NS_SHENTRY_CONTRACTID);
--- a/docshell/shistory/moz.build
+++ b/docshell/shistory/moz.build
@@ -1,17 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPIDL_SOURCES += [
     'nsIBFCacheEntry.idl',
-    'nsISHContainer.idl',
     'nsISHEntry.idl',
     'nsISHistory.idl',
     'nsISHistoryInternal.idl',
     'nsISHistoryListener.idl',
     'nsISHTransaction.idl',
 ]
 
 XPIDL_MODULE = 'shistory'
deleted file mode 100644
--- a/docshell/shistory/nsISHContainer.idl
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsISHEntry;
-
-/**
- * The nsISHEntryContainer. The interface to access child entries
- * of an nsISHEntry.
- * 
- */
-
-[scriptable, uuid(67dd0357-8372-4122-bff6-217435e8b7e4)]
-interface nsISHContainer : nsISupports
-{
-	/**
-     * The current number of nsISHEntries which are immediate children of the 
-	 * current SHEntry
-     */
-	readonly attribute long childCount;
-
-	/**
-	 * Add a new child SHEntry.  If offset is -1 adds to the end of the list.
-	 */
-	void AddChild(in nsISHEntry child, in long offset);
-
-	/**
-	 * Removes a child SHEntry
-	 */
-	void RemoveChild(in nsISHEntry child);
-
-	/**
-	 * Get child at an index
-	 */
-	nsISHEntry GetChildAt(in long index);
-
-	/**
-	 * Replaces a child which is for the same docshell as aNewChild
-	 * with aNewChild.
-	 * @throw if nothing was replaced.
-	 */
-	void ReplaceChild(in nsISHEntry aNewChild);
-
-};
-
--- a/docshell/shistory/nsISHEntry.idl
+++ b/docshell/shistory/nsISHEntry.idl
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 /**
- * The interface to nsISHentry. Each document or subframe in 
+ * The interface to nsISHentry. Each document or subframe in
  * Session History will have a nsISHEntry associated with it which will
  * hold all information required to recreate the document from history
- * 
  */
 
 #include "nsISupports.idl"
 
 interface nsIMutableArray;
 interface nsILayoutHistoryState;
 interface nsIContentViewer;
 interface nsIURI;
@@ -175,31 +174,31 @@ interface nsISHEntry : nsISupports
 
     /** attribute to indicate whether the page is already expired in cache */
     attribute boolean expirationStatus;
 
     /**
      * attribute to indicate the content-type of the document that this
      * is a session history entry for
      */
-    attribute ACString contentType; 
+    attribute ACString contentType;
 
     /**
      * If we created this SHEntry via history.pushState or modified it via
      * history.replaceState, and if we changed the SHEntry's URI via the
      * push/replaceState call, and if the SHEntry's new URI differs from its
      * old URI by more than just the hash, then we set this field to true.
      *
      * Additionally, if this SHEntry was created by calling pushState from a
      * SHEntry whose URI was modified, this SHEntry's URIWasModified field is
      * true.
      *
      */
     attribute boolean URIWasModified;
- 
+
     /** Set/Get scrollers' positon in anchored pages */
     void setScrollPosition(in long x, in long y);
     void getScrollPosition(out long x, out long y);
 
     /** Additional ways to create an entry */
     [noscript] void create(in nsIURI URI, in AString title,
                            in nsIInputStream inputStream,
                            in nsILayoutHistoryState layoutHistoryState,
@@ -368,20 +367,47 @@ interface nsISHEntry : nsISupports
      * shared between SHEntries which correspond to the same document.  This
      * method gets a pointer to that shared state.
      *
      * This shared state is the SHEntry's BFCacheEntry.  So
      * hasBFCacheEntry(getSharedState()) is guaranteed to return true.
      */
     [noscript, notxpcom]
     nsSHEntryShared getSharedState();
+
+    /**
+     * The current number of nsISHEntries which are immediate children of this
+     * SHEntry.
+     */
+    readonly attribute long childCount;
+
+    /**
+     * Add a new child SHEntry. If offset is -1 adds to the end of the list.
+     */
+    void AddChild(in nsISHEntry aChild, in long aOffset);
+
+    /**
+     * Remove a child SHEntry.
+     */
+    void RemoveChild(in nsISHEntry aChild);
+
+    /**
+     * Get child at an index.
+     */
+    nsISHEntry GetChildAt(in long aIndex);
+
+    /**
+     * Replaces a child which is for the same docshell as aNewChild
+     * with aNewChild.
+     * @throw if nothing was replaced.
+     */
+    void ReplaceChild(in nsISHEntry aNewChild);
 };
 
 %{ C++
 // {BFD1A791-AD9F-11d3-BDC7-0050040A9B44}
 #define NS_SHENTRY_CID \
 {0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
 
 #define NS_SHENTRY_CONTRACTID \
     "@mozilla.org/browser/session-history-entry;1"
-
 %}
 
--- a/docshell/shistory/nsISHistoryInternal.idl
+++ b/docshell/shistory/nsISHistoryInternal.idl
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 nsIBFCacheEntry;
-interface nsISHContainer;
 interface nsISHEntry;
 interface nsISHistoryListener;
 interface nsISHTransaction;
 interface nsIDocShell;
 interface nsIURI;
 
 %{C++
 #include "nsTArrayForwardDeclare.h"
@@ -101,23 +100,23 @@ interface nsISHistoryInternal: nsISuppor
    void removeFromExpirationTracker(in nsIBFCacheEntry aEntry);
 
    /**
     * Remove dynamic entries found at given index.
     *
     * @param aIndex
     *        Index to remove dynamic entries from. It will be passed to
     *        RemoveEntries as aStartIndex.
-    * @param aContainer (optional)
-    *        The container to start looking for dynamic entries. Only the
-    *        dynamic descendants of the container will be removed. If not given,
+    * @param aEntry (optional)
+    *        The entry to start looking in for dynamic entries. Only the
+    *        dynamic descendants of the entry will be removed. If not given,
     *        all dynamic entries at the index will be removed.
     */
    [noscript, notxpcom] void RemoveDynEntries(in long aIndex,
-                                              in nsISHContainer aContainer);
+                                              in nsISHEntry aEntry);
 
    /**
     * Similar to RemoveDynEntries, but instead of specifying an index, use the
     * given BFCacheEntry to find the index and remove dynamic entries from the
     * index.
     *
     * The method takes no effect if the bfcache entry is not or no longer hold
     * by the SHistory instance.
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -71,17 +71,17 @@ nsSHEntry::~nsSHEntry()
   // Null out the mParent pointers on all our kids.
   for (nsISHEntry* entry : mChildren) {
     if (entry) {
       entry->SetParent(nullptr);
     }
   }
 }
 
-NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry)
+NS_IMPL_ISUPPORTS(nsSHEntry, nsISHEntry)
 
 NS_IMETHODIMP
 nsSHEntry::SetScrollPosition(int32_t aX, int32_t aY)
 {
   mScrollPositionX = aX;
   mScrollPositionY = aY;
   return NS_OK;
 }
--- a/docshell/shistory/nsSHEntry.h
+++ b/docshell/shistory/nsSHEntry.h
@@ -4,36 +4,33 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsSHEntry_h
 #define nsSHEntry_h
 
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsISHContainer.h"
 #include "nsISHEntry.h"
 #include "nsString.h"
 
 #include "mozilla/Attributes.h"
 
 class nsSHEntryShared;
 class nsIInputStream;
 class nsIURI;
 
-class nsSHEntry final : public nsISHEntry,
-                        public nsISHContainer
+class nsSHEntry final : public nsISHEntry
 {
 public:
   nsSHEntry();
   nsSHEntry(const nsSHEntry& aOther);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISHENTRY
-  NS_DECL_NSISHCONTAINER
 
   void DropPresentationState();
 
   static nsresult Startup();
   static void Shutdown();
 
 private:
   ~nsSHEntry();
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -12,17 +12,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsDocShellLoadInfo.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIObserverService.h"
-#include "nsISHContainer.h"
 #include "nsISHEntry.h"
 #include "nsISHistoryListener.h"
 #include "nsISHTransaction.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsTArray.h"
 #include "prsystem.h"
 
@@ -228,18 +227,17 @@ nsSHistory::EvictContentViewerForTransac
     ownerEntry->SyncPresentationState();
     viewer->Destroy();
   }
 
   // When dropping bfcache, we have to remove associated dynamic entries as well.
   int32_t index = -1;
   GetIndexOfEntry(entry, &index);
   if (index != -1) {
-    nsCOMPtr<nsISHContainer> container(do_QueryInterface(entry));
-    RemoveDynEntries(index, container);
+    RemoveDynEntries(index, entry);
   }
 }
 
 nsSHistory::nsSHistory()
   : mIndex(-1)
   , mLength(0)
   , mRequestedIndex(-1)
   , mRootDocShell(nullptr)
@@ -414,26 +412,21 @@ nsSHistory::GetRootSHEntry(nsISHEntry* a
 nsresult
 nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
                                nsDocShell* aRootShell,
                                WalkHistoryEntriesFunc aCallback,
                                void* aData)
 {
   NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsISHContainer> container(do_QueryInterface(aRootEntry));
-  if (!container) {
-    return NS_ERROR_FAILURE;
-  }
-
   int32_t childCount;
-  container->GetChildCount(&childCount);
+  aRootEntry->GetChildCount(&childCount);
   for (int32_t i = 0; i < childCount; i++) {
     nsCOMPtr<nsISHEntry> childEntry;
-    container->GetChildAt(i, getter_AddRefs(childEntry));
+    aRootEntry->GetChildAt(i, getter_AddRefs(childEntry));
     if (!childEntry) {
       // childEntry can be null for valid reasons, for example if the
       // docshell at index i never loaded anything useful.
       // Remember to clone also nulls in the child array (bug 464064).
       aCallback(nullptr, nullptr, i, aData);
       continue;
     }
 
@@ -488,20 +481,19 @@ nsSHistory::CloneAndReplaceChild(nsISHEn
                                           void* aData)
 {
   nsCOMPtr<nsISHEntry> dest;
 
   CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
   uint32_t cloneID = data->cloneID;
   nsISHEntry* replaceEntry = data->replaceEntry;
 
-  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
   if (!aEntry) {
-    if (container) {
-      container->AddChild(nullptr, aEntryIndex);
+    if (data->destTreeParent) {
+      data->destTreeParent->AddChild(nullptr, aEntryIndex);
     }
     return NS_OK;
   }
 
   uint32_t srcID;
   aEntry->GetID(&srcID);
 
   nsresult rv = NS_OK;
@@ -523,18 +515,18 @@ nsSHistory::CloneAndReplaceChild(nsISHEn
                             CloneAndReplaceChild, &childData);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (srcID != cloneID && aShell) {
     aShell->SwapHistoryEntries(aEntry, dest);
   }
 
-  if (container) {
-    container->AddChild(dest, aEntryIndex);
+  if (data->destTreeParent) {
+    data->destTreeParent->AddChild(dest, aEntryIndex);
   }
 
   data->resultEntry = dest;
   return rv;
 }
 
 // static
 nsresult
@@ -565,37 +557,36 @@ nsSHistory::SetChildHistoryEntry(nsISHEn
 
   if (!aShell || aShell == ignoreShell) {
     return NS_OK;
   }
 
   nsISHEntry* destTreeRoot = data->destTreeRoot;
 
   nsCOMPtr<nsISHEntry> destEntry;
-  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
 
-  if (container) {
+  if (data->destTreeParent) {
     // aEntry is a clone of some child of destTreeParent, but since the
     // trees aren't necessarily in sync, we'll have to locate it.
     // Note that we could set aShell's entry to null if we don't find a
     // corresponding entry under destTreeParent.
 
     uint32_t targetID, id;
     aEntry->GetID(&targetID);
 
     // First look at the given index, since this is the common case.
     nsCOMPtr<nsISHEntry> entry;
-    container->GetChildAt(aEntryIndex, getter_AddRefs(entry));
+    data->destTreeParent->GetChildAt(aEntryIndex, getter_AddRefs(entry));
     if (entry && NS_SUCCEEDED(entry->GetID(&id)) && id == targetID) {
       destEntry.swap(entry);
     } else {
       int32_t childCount;
-      container->GetChildCount(&childCount);
+      data->destTreeParent->GetChildCount(&childCount);
       for (int32_t i = 0; i < childCount; ++i) {
-        container->GetChildAt(i, getter_AddRefs(entry));
+        data->destTreeParent->GetChildAt(i, getter_AddRefs(entry));
         if (!entry) {
           continue;
         }
 
         entry->GetID(&id);
         if (id == targetID) {
           destEntry.swap(entry);
           break;
@@ -1516,84 +1507,71 @@ nsSHistory::GloballyEvictAllContentViewe
 {
   int32_t maxViewers = sHistoryMaxTotalViewers;
   sHistoryMaxTotalViewers = 0;
   GloballyEvictContentViewers();
   sHistoryMaxTotalViewers = maxViewers;
 }
 
 void
-GetDynamicChildren(nsISHContainer* aContainer,
+GetDynamicChildren(nsISHEntry* aEntry,
                    nsTArray<nsID>& aDocshellIDs,
                    bool aOnlyTopLevelDynamic)
 {
   int32_t count = 0;
-  aContainer->GetChildCount(&count);
+  aEntry->GetChildCount(&count);
   for (int32_t i = 0; i < count; ++i) {
     nsCOMPtr<nsISHEntry> child;
-    aContainer->GetChildAt(i, getter_AddRefs(child));
+    aEntry->GetChildAt(i, getter_AddRefs(child));
     if (child) {
       bool dynAdded = false;
       child->IsDynamicallyAdded(&dynAdded);
       if (dynAdded) {
         nsID docshellID = child->DocshellID();
         aDocshellIDs.AppendElement(docshellID);
       }
       if (!dynAdded || !aOnlyTopLevelDynamic) {
-        nsCOMPtr<nsISHContainer> childAsContainer = do_QueryInterface(child);
-        if (childAsContainer) {
-          GetDynamicChildren(childAsContainer, aDocshellIDs,
-                             aOnlyTopLevelDynamic);
-        }
+        GetDynamicChildren(child, aDocshellIDs, aOnlyTopLevelDynamic);
       }
     }
   }
 }
 
 bool
-RemoveFromSessionHistoryContainer(nsISHContainer* aContainer,
-                                  nsTArray<nsID>& aDocshellIDs)
+RemoveFromSessionHistoryEntry(nsISHEntry* aRoot, nsTArray<nsID>& aDocshellIDs)
 {
-  nsCOMPtr<nsISHEntry> root = do_QueryInterface(aContainer);
-  NS_ENSURE_TRUE(root, false);
-
   bool didRemove = false;
   int32_t childCount = 0;
-  aContainer->GetChildCount(&childCount);
+  aRoot->GetChildCount(&childCount);
   for (int32_t i = childCount - 1; i >= 0; --i) {
     nsCOMPtr<nsISHEntry> child;
-    aContainer->GetChildAt(i, getter_AddRefs(child));
+    aRoot->GetChildAt(i, getter_AddRefs(child));
     if (child) {
       nsID docshelldID = child->DocshellID();
       if (aDocshellIDs.Contains(docshelldID)) {
         didRemove = true;
-        aContainer->RemoveChild(child);
+        aRoot->RemoveChild(child);
       } else {
-        nsCOMPtr<nsISHContainer> container = do_QueryInterface(child);
-        if (container) {
-          bool childRemoved =
-            RemoveFromSessionHistoryContainer(container, aDocshellIDs);
-          if (childRemoved) {
-            didRemove = true;
-          }
+        bool childRemoved = RemoveFromSessionHistoryEntry(child, aDocshellIDs);
+        if (childRemoved) {
+          didRemove = true;
         }
       }
     }
   }
   return didRemove;
 }
 
 bool
 RemoveChildEntries(nsISHistory* aHistory, int32_t aIndex,
                    nsTArray<nsID>& aEntryIDs)
 {
-  nsCOMPtr<nsISHEntry> rootHE;
-  aHistory->GetEntryAtIndex(aIndex, false, getter_AddRefs(rootHE));
-  nsCOMPtr<nsISHContainer> root = do_QueryInterface(rootHE);
-  return root ? RemoveFromSessionHistoryContainer(root, aEntryIDs) : false;
+  nsCOMPtr<nsISHEntry> root;
+  aHistory->GetEntryAtIndex(aIndex, false, getter_AddRefs(root));
+  return root ? RemoveFromSessionHistoryEntry(root, aEntryIDs) : false;
 }
 
 bool
 IsSameTree(nsISHEntry* aEntry1, nsISHEntry* aEntry2)
 {
   if (!aEntry1 && !aEntry2) {
     return true;
   }
@@ -1602,27 +1580,25 @@ IsSameTree(nsISHEntry* aEntry1, nsISHEnt
   }
   uint32_t id1, id2;
   aEntry1->GetID(&id1);
   aEntry2->GetID(&id2);
   if (id1 != id2) {
     return false;
   }
 
-  nsCOMPtr<nsISHContainer> container1 = do_QueryInterface(aEntry1);
-  nsCOMPtr<nsISHContainer> container2 = do_QueryInterface(aEntry2);
   int32_t count1, count2;
-  container1->GetChildCount(&count1);
-  container2->GetChildCount(&count2);
+  aEntry1->GetChildCount(&count1);
+  aEntry2->GetChildCount(&count2);
   // We allow null entries in the end of the child list.
   int32_t count = std::max(count1, count2);
   for (int32_t i = 0; i < count; ++i) {
     nsCOMPtr<nsISHEntry> child1, child2;
-    container1->GetChildAt(i, getter_AddRefs(child1));
-    container2->GetChildAt(i, getter_AddRefs(child2));
+    aEntry1->GetChildAt(i, getter_AddRefs(child1));
+    aEntry2->GetChildAt(i, getter_AddRefs(child2));
     if (!IsSameTree(child1, child2)) {
       return false;
     }
   }
 
   return true;
 }
 
@@ -1717,46 +1693,43 @@ nsSHistory::RemoveEntries(nsTArray<nsID>
     --index;
   }
   if (didRemove && mRootDocShell) {
     mRootDocShell->DispatchLocationChangeEvent();
   }
 }
 
 void
-nsSHistory::RemoveDynEntries(int32_t aIndex, nsISHContainer* aContainer)
+nsSHistory::RemoveDynEntries(int32_t aIndex, nsISHEntry* aEntry)
 {
   // Remove dynamic entries which are at the index and belongs to the container.
-  nsCOMPtr<nsISHContainer> container(aContainer);
-  if (!container) {
-    nsCOMPtr<nsISHEntry> entry;
+  nsCOMPtr<nsISHEntry> entry(aEntry);
+  if (!entry) {
     GetEntryAtIndex(aIndex, false, getter_AddRefs(entry));
-    container = do_QueryInterface(entry);
   }
 
-  if (container) {
+  if (entry) {
     AutoTArray<nsID, 16> toBeRemovedEntries;
-    GetDynamicChildren(container, toBeRemovedEntries, true);
+    GetDynamicChildren(entry, toBeRemovedEntries, true);
     if (toBeRemovedEntries.Length()) {
       RemoveEntries(toBeRemovedEntries, aIndex);
     }
   }
 }
 
 void
 nsSHistory::RemoveDynEntriesForBFCacheEntry(nsIBFCacheEntry* aEntry)
 {
   int32_t index;
   nsCOMPtr<nsISHTransaction> trans;
   FindTransactionForBFCache(aEntry, getter_AddRefs(trans), &index);
   if (trans) {
     nsCOMPtr<nsISHEntry> entry;
     trans->GetSHEntry(getter_AddRefs(entry));
-    nsCOMPtr<nsISHContainer> container(do_QueryInterface(entry));
-    RemoveDynEntries(index, container);
+    RemoveDynEntries(index, entry);
   }
 }
 
 NS_IMETHODIMP
 nsSHistory::UpdateIndex()
 {
   // Update the actual index with the right value.
   if (mIndex != mRequestedIndex && mRequestedIndex != -1) {
@@ -1962,25 +1935,19 @@ nsSHistory::LoadDifferingEntries(nsISHEn
     aNextEntry->SetIsSubFrame(aParent != mRootDocShell);
     return InitiateLoad(aNextEntry, aParent, aLoadType);
   }
 
   // The entries are the same, so compare any child frames
   int32_t pcnt = 0;
   int32_t ncnt = 0;
   int32_t dsCount = 0;
-  nsCOMPtr<nsISHContainer> prevContainer(do_QueryInterface(aPrevEntry));
-  nsCOMPtr<nsISHContainer> nextContainer(do_QueryInterface(aNextEntry));
 
-  if (!prevContainer || !nextContainer) {
-    return NS_ERROR_FAILURE;
-  }
-
-  prevContainer->GetChildCount(&pcnt);
-  nextContainer->GetChildCount(&ncnt);
+  aPrevEntry->GetChildCount(&pcnt);
+  aNextEntry->GetChildCount(&ncnt);
   aParent->GetChildCount(&dsCount);
 
   // Create an array for child docshells.
   nsCOMArray<nsIDocShell> docshells;
   for (int32_t i = 0; i < dsCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> treeItem;
     aParent->GetChildAt(i, getter_AddRefs(treeItem));
     nsCOMPtr<nsIDocShell> shell = do_QueryInterface(treeItem);
@@ -1988,17 +1955,17 @@ nsSHistory::LoadDifferingEntries(nsISHEn
       docshells.AppendElement(shell.forget());
     }
   }
 
   // Search for something to load next.
   for (int32_t i = 0; i < ncnt; ++i) {
     // First get an entry which may cause a new page to be loaded.
     nsCOMPtr<nsISHEntry> nChild;
-    nextContainer->GetChildAt(i, getter_AddRefs(nChild));
+    aNextEntry->GetChildAt(i, getter_AddRefs(nChild));
     if (!nChild) {
       continue;
     }
     nsID docshellID = nChild->DocshellID();
 
     // Then find the associated docshell.
     nsIDocShell* dsChild = nullptr;
     int32_t count = docshells.Count();
@@ -2014,17 +1981,17 @@ nsSHistory::LoadDifferingEntries(nsISHEn
       continue;
     }
 
     // Then look at the previous entries to see if there was
     // an entry for the docshell.
     nsCOMPtr<nsISHEntry> pChild;
     for (int32_t k = 0; k < pcnt; ++k) {
       nsCOMPtr<nsISHEntry> child;
-      prevContainer->GetChildAt(k, getter_AddRefs(child));
+      aPrevEntry->GetChildAt(k, getter_AddRefs(child));
       if (child) {
         nsID dID = child->DocshellID();
         if (dID == docshellID) {
           pChild = child;
           break;
         }
       }
     }
--- a/docshell/test/navigation/test_bug1375833.html
+++ b/docshell/test/navigation/test_bug1375833.html
@@ -45,19 +45,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       is(shistory.count, 4, "check history length");
       is(shistory.index, 3, "check history index");
 
       let newFrameDocShellId = String(getFrameDocShell().historyID);
       ok(newFrameDocShellId, "sanity check for docshell ID");
       is(newFrameDocShellId, frameDocShellId, "check docshell ID remains after reload");
 
       let entry = shistory.legacySHistory.getEntryAtIndex(shistory.index, false);
-      let frameEntry = SpecialPowers.wrap(entry)
-                       .QueryInterface(SpecialPowers.Ci.nsISHContainer)
-                       .GetChildAt(0);
+      let frameEntry = entry.GetChildAt(0);
       is(String(frameEntry.docshellID), frameDocShellId, "check newly added shentry uses the same docshell ID");
 
       webNav.goBack();
       break;
     case 2:
       ok(e.data.endsWith("file_bug1375833-frame1.html"), "check location");
       is(shistory.count, 4, "check history length");
       is(shistory.index, 2, "check history index");
--- a/docshell/test/test_bug590573.html
+++ b/docshell/test/test_bug590573.html
@@ -106,17 +106,16 @@ function dumpSHistory(theWindow)
 
   dump(" count: " + sh.count + "\n");
   dump(" index: " + sh.index + "\n");
   dump(" requestedIndex: " + sh.legacySHistory.requestedIndex + "\n");
 
   for (let i = 0; i < sh.count; i++) {
     let shentry = sh.legacySHistory.getEntryAtIndex(i, false);
     dump(" " + i + ": " + shentry.URI.spec + '\n');
-    shentry.QueryInterface(SpecialPowers.Ci.nsISHContainer);
     for (let j = 0; j < shentry.childCount; j++) {
       let child = shentry.GetChildAt(j);
       dump("   child " + j + ": " + child.URI.spec + '\n');
     }
   }
 
   return sh;
 }
--- a/dom/base/nsCCUncollectableMarker.cpp
+++ b/dom/base/nsCCUncollectableMarker.cpp
@@ -12,17 +12,16 @@
 #include "nsIDocument.h"
 #include "XULDocument.h"
 #include "InProcessTabChildMessageManager.h"
 #include "nsIWindowMediator.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsISHistory.h"
 #include "nsISHEntry.h"
-#include "nsISHContainer.h"
 #include "nsIWindowWatcher.h"
 #include "mozilla/Services.h"
 #include "nsIXULWindow.h"
 #include "nsIAppShellService.h"
 #include "nsAppShellCID.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsJSEnvironment.h"
@@ -228,25 +227,23 @@ MarkSHEntry(nsISHEntry* aSHEntry, bool a
 
   nsCOMPtr<nsIDocShellTreeItem> child;
   int32_t i = 0;
   while (NS_SUCCEEDED(aSHEntry->ChildShellAt(i++, getter_AddRefs(child))) &&
          child) {
     MarkDocShell(child, aCleanupJS);
   }
 
-  nsCOMPtr<nsISHContainer> shCont = do_QueryInterface(aSHEntry);
   int32_t count;
-  shCont->GetChildCount(&count);
+  aSHEntry->GetChildCount(&count);
   for (i = 0; i < count; ++i) {
     nsCOMPtr<nsISHEntry> childEntry;
-    shCont->GetChildAt(i, getter_AddRefs(childEntry));
+    aSHEntry->GetChildAt(i, getter_AddRefs(childEntry));
     MarkSHEntry(childEntry, aCleanupJS);
   }
-
 }
 
 void
 MarkDocShell(nsIDocShellTreeItem* aNode, bool aCleanupJS)
 {
   nsCOMPtr<nsIDocShell> shell = do_QueryInterface(aNode);
   if (!shell) {
     return;
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -223,20 +223,16 @@ var SessionHistoryInternal = {
 
     entry.docIdentifier = shEntry.BFCacheEntry.ID;
 
     if (shEntry.stateData != null) {
       entry.structuredCloneState = shEntry.stateData.getDataAsBase64();
       entry.structuredCloneVersion = shEntry.stateData.formatVersion;
     }
 
-    if (!(shEntry instanceof Ci.nsISHContainer)) {
-      return entry;
-    }
-
     if (shEntry.childCount > 0 && !shEntry.hasDynamicallyAddedChild()) {
       let children = [];
       for (let i = 0; i < shEntry.childCount; i++) {
         let child = shEntry.GetChildAt(i);
 
         if (child) {
           // Don't try to restore framesets containing wyciwyg URLs.
           // (cf. bug 424689 and bug 450595)
@@ -452,17 +448,17 @@ var SessionHistoryInternal = {
     if (!shEntry.triggeringPrincipal) {
       debug("Couldn't deserialize the triggeringPrincipal, falling back to NullPrincipal");
       shEntry.triggeringPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
     }
     if (entry.principalToInherit_base64) {
       shEntry.principalToInherit = Utils.deserializePrincipal(entry.principalToInherit_base64);
     }
 
-    if (entry.children && shEntry instanceof Ci.nsISHContainer) {
+    if (entry.children) {
       for (var i = 0; i < entry.children.length; i++) {
         // XXXzpao Wallpaper patch for bug 514751
         if (!entry.children[i].url)
           continue;
 
         // We're getting sessionrestore.js files with a cycle in the
         // doc-identifier graph, likely due to bug 698656.  (That is, we have
         // an entry where doc identifier A is an ancestor of doc identifier B,