Bug 1434768 - Part 3: Rewrite JS consumers of .sessionHistory, r=bz
authorNika Layzell <nika@thelayzells.com>
Thu, 01 Feb 2018 17:17:00 -0500
changeset 412755 3bc418e5727e0f682909f0543db3c92376840d7c
parent 412754 c1dc655523000be37d89f5231636c47d70f6d141
child 412756 0171a483cd7b062b797b1773812c8ce0a0e0ae3c
push id33818
push userapavel@mozilla.com
push dateWed, 11 Apr 2018 14:36:40 +0000
treeherdermozilla-central@cfe6399e142c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1434768
milestone61.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 1434768 - Part 3: Rewrite JS consumers of .sessionHistory, r=bz
browser/base/content/tab-content.js
browser/base/content/test/general/browser_e10s_switchbrowser.js
browser/base/content/web-panels.js
browser/components/sessionstore/ContentRestore.jsm
browser/components/sessionstore/content/content-sessionStore.js
browser/components/sessionstore/test/browser_705597.js
browser/components/sessionstore/test/browser_707862.js
browser/components/sessionstore/test/browser_async_remove_tab.js
browser/components/sessionstore/test/browser_async_window_flushing.js
browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
browser/components/sessionstore/test/browser_purge_shistory.js
browser/components/sessionstore/test/browser_replace_load.js
browser/components/sessionstore/test/browser_switch_remoteness.js
browser/components/sessionstore/test/content.js
docshell/test/browser/browser_bug422543.js
docshell/test/browser/browser_bug655273.js
docshell/test/browser/browser_bug670318.js
docshell/test/browser/file_bug422543_script.js
docshell/test/chrome/bug112564_window.xul
docshell/test/chrome/bug215405_window.xul
docshell/test/chrome/bug396519_window.xul
docshell/test/chrome/bug92598_window.xul
docshell/test/chrome/docshell_helpers.js
docshell/test/navigation/file_bug1300461.html
docshell/test/navigation/file_bug1300461_back.html
docshell/test/navigation/file_bug1326251_evict_cache.html
docshell/test/navigation/test_bug1375833.html
docshell/test/test_bug509055.html
docshell/test/test_bug590573.html
dom/browser-element/BrowserElementChildPreload.js
dom/html/test/browser_bug649778.js
dom/tests/mochitest/whatwg/test_bug500328.html
mobile/android/chrome/content/browser.js
testing/firefox-ui/tests/puppeteer/test_toolbars.py
toolkit/components/reader/ReaderMode.jsm
toolkit/components/viewsource/content/viewSource-content.js
toolkit/content/browser-content.js
toolkit/modules/E10SUtils.jsm
toolkit/modules/sessionstore/SessionHistory.jsm
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -59,28 +59,29 @@ addMessageListener("Browser:HideSessionR
   let container;
   if (doc.documentURI.toLowerCase() == "about:home" &&
       (container = doc.getElementById("sessionRestoreContainer"))) {
     container.hidden = true;
   }
 });
 
 
+// XXX(nika): Should we try to call this in the parent process instead?
 addMessageListener("Browser:Reload", function(message) {
   /* First, we'll try to use the session history object to reload so
    * that framesets are handled properly. If we're in a special
    * window (such as view-source) that has no session history, fall
    * back on using the web navigation's reload method.
    */
 
   let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
   try {
-    let sh = webNav.sessionHistory;
-    if (sh)
-      webNav = sh.QueryInterface(Ci.nsIWebNavigation);
+    if (webNav.sessionHistory) {
+      webNav = webNav.sessionHistory;
+    }
   } catch (e) {
   }
 
   let reloadFlags = message.data.flags;
   try {
     E10SUtils.wrapHandlingUserInput(content, message.data.handlingUserInput,
                                     () => webNav.reload(reloadFlags));
   } catch (e) {
--- a/browser/base/content/test/general/browser_e10s_switchbrowser.js
+++ b/browser/base/content/test/general/browser_e10s_switchbrowser.js
@@ -14,17 +14,17 @@ function get_remote_history(browser) {
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     let sessionHistory = webNav.sessionHistory;
     let result = {
       index: sessionHistory.index,
       entries: []
     };
 
     for (let i = 0; i < sessionHistory.count; i++) {
-      let entry = sessionHistory.getEntryAtIndex(i, false);
+      let entry = sessionHistory.legacySHistory.getEntryAtIndex(i, false);
       result.entries.push({
         uri: entry.URI.spec,
         title: entry.title
       });
     }
 
     sendAsyncMessage("Test:History", result);
   }
--- a/browser/base/content/web-panels.js
+++ b/browser/base/content/web-panels.js
@@ -88,11 +88,10 @@ function unload() {
 
 function PanelBrowserStop() {
     getPanelBrowser().webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
 }
 
 function PanelBrowserReload() {
     getPanelBrowser().webNavigation
                      .sessionHistory
-                     .QueryInterface(Ci.nsIWebNavigation)
                      .reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
 }
--- a/browser/components/sessionstore/ContentRestore.jsm
+++ b/browser/components/sessionstore/ContentRestore.jsm
@@ -159,17 +159,17 @@ ContentRestoreInternal.prototype = {
     SessionHistory.restore(this.docShell, tabData);
 
     // Add a listener to watch for reloads.
     let listener = new HistoryListener(this.docShell, () => {
       // On reload, restore tab contents.
       this.restoreTabContent(null, false, callbacks.onLoadFinished);
     });
 
-    webNavigation.sessionHistory.addSHistoryListener(listener);
+    webNavigation.sessionHistory.legacySHistory.addSHistoryListener(listener);
     this._historyListener = listener;
 
     // Make sure to reset the capabilities and attributes in case this tab gets
     // reused.
     let disallow = new Set(tabData.disallow && tabData.disallow.split(","));
     DocShellCapabilities.restore(this.docShell, disallow);
 
     if (tabData.storage && this.docShell instanceof Ci.nsIDocShell) {
@@ -198,17 +198,17 @@ ContentRestoreInternal.prototype = {
    * Start loading the current page. When the data has finished loading from the
    * network, finishCallback is called. Returns true if the load was successful.
    */
   restoreTabContent(loadArguments, isRemotenessUpdate, finishCallback) {
     let tabData = this._tabData;
     this._tabData = null;
 
     let webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory;
+    let history = webNavigation.sessionHistory.legacySHistory;
 
     // Listen for the tab to finish loading.
     this.restoreTabContentStarted(finishCallback);
 
     // Reset the current URI to about:blank. We changed it above for
     // switch-to-tab, but now it must go back to the correct value before the
     // load happens. Don't bother doing this if we're restoring immediately
     // due to a process switch.
@@ -360,29 +360,29 @@ ContentRestoreInternal.prototype = {
 
 /*
  * This listener detects when a page being restored is reloaded. It triggers a
  * callback and cancels the reload. The callback will send a message to
  * SessionStore.jsm so that it can restore the content immediately.
  */
 function HistoryListener(docShell, callback) {
   let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-  webNavigation.sessionHistory.addSHistoryListener(this);
+  webNavigation.sessionHistory.legacySHistory.addSHistoryListener(this);
 
   this.webNavigation = webNavigation;
   this.callback = callback;
 }
 HistoryListener.prototype = {
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsISHistoryListener,
     Ci.nsISupportsWeakReference
   ]),
 
   uninstall() {
-    let shistory = this.webNavigation.sessionHistory;
+    let shistory = this.webNavigation.sessionHistory.legacySHistory;
     if (shistory) {
       shistory.removeSHistoryListener(this);
     }
   },
 
   OnHistoryGoBack(backURI) { return true; },
   OnHistoryGoForward(forwardURI) { return true; },
   OnHistoryGotoIndex(index, gotoURI) { return true; },
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -315,18 +315,18 @@ var SessionHistoryListener = {
     // but these invalidations are very cheap.
     StateChangeNotifier.addObserver(this);
 
     // By adding the SHistoryListener immediately, we will unfortunately be
     // notified of every history entry as the tab is restored. We don't bother
     // waiting to add the listener later because these notifications are cheap.
     // We will likely only collect once since we are batching collection on
     // a delay.
-    docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.
-      addSHistoryListener(this);
+    docShell.QueryInterface(Ci.nsIWebNavigation).
+      sessionHistory.legacySHistory.addSHistoryListener(this);
 
     // Collect data if we start with a non-empty shistory.
     if (!SessionHistory.isEmpty(docShell)) {
       this.collect();
       // When a tab is detached from the window, for the new window there is a
       // new SessionHistoryListener created. Normally it is empty at this point
       // but in a test env. the initial about:blank might have a children in which
       // case we fire off a history message here with about:blank in it. If we
@@ -337,17 +337,17 @@ var SessionHistoryListener = {
 
     // Listen for page title changes.
     addEventListener("DOMTitleChanged", this);
   },
 
   uninit() {
     let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
     if (sessionHistory) {
-      sessionHistory.removeSHistoryListener(this);
+      sessionHistory.legacySHistory.removeSHistoryListener(this);
     }
   },
 
   collect() {
     // We want to send down a historychange even for full collects in case our
     // session history is a partial session history, in which case we don't have
     // enough information for a full update. collectFrom(-1) tells the collect
     // function to collect all data avaliable in this process.
--- a/browser/components/sessionstore/test/browser_705597.js
+++ b/browser/components/sessionstore/test/browser_705597.js
@@ -19,17 +19,17 @@ function test() {
   });
 
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
 
   let browser = tab.linkedBrowser;
 
   promiseTabState(tab, tabState).then(() => {
     let sessionHistory = browser.sessionHistory;
-    let entry = sessionHistory.getEntryAtIndex(0, false);
+    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));
--- a/browser/components/sessionstore/test/browser_707862.js
+++ b/browser/components/sessionstore/test/browser_707862.js
@@ -19,24 +19,24 @@ function test() {
   });
 
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
 
   let browser = tab.linkedBrowser;
 
   promiseTabState(tab, tabState).then(() => {
     let sessionHistory = browser.sessionHistory;
-    let entry = sessionHistory.getEntryAtIndex(0, false);
+    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.getEntryAtIndex(0, false);
+          let newEntry = newSessionHistory.legacySHistory.getEntryAtIndex(0, false);
 
           whenChildCount(newEntry, 0, function() {
             // Make sure that we reset the state.
             let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank",
                                                                 triggeringPrincipal_base64 }] }]}]};
             waitForBrowserState(blankState, finish);
           });
         });
--- a/browser/components/sessionstore/test/browser_async_remove_tab.js
+++ b/browser/components/sessionstore/test/browser_async_remove_tab.js
@@ -30,17 +30,17 @@ function restoreClosedTabWithValue(rval)
   }
 
   return ss.undoCloseTab(window, index);
 }
 
 function promiseNewLocationAndHistoryEntryReplaced(browser, snippet) {
   return ContentTask.spawn(browser, snippet, async function(codeSnippet) {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let shistory = webNavigation.sessionHistory;
+    let shistory = webNavigation.sessionHistory.legacySHistory;
 
     // Evaluate the snippet that the changes the location.
     // eslint-disable-next-line no-eval
     eval(codeSnippet);
 
     return new Promise(resolve => {
       let listener = {
         OnHistoryReplaceEntry() {
@@ -65,17 +65,17 @@ function promiseNewLocationAndHistoryEnt
     });
   });
 }
 
 function promiseHistoryEntryReplacedNonRemote(browser) {
   let {listeners} = promiseHistoryEntryReplacedNonRemote;
 
   return new Promise(resolve => {
-    let shistory = browser.webNavigation.sessionHistory;
+    let shistory = browser.webNavigation.sessionHistory.legacySHistory;
 
     let listener = {
       OnHistoryReplaceEntry() {
         shistory.removeSHistoryListener(this);
         executeSoon(resolve);
       },
 
       QueryInterface: XPCOMUtils.generateQI([
--- a/browser/components/sessionstore/test/browser_async_window_flushing.js
+++ b/browser/components/sessionstore/test/browser_async_window_flushing.js
@@ -104,17 +104,17 @@ add_task(async function test_remove_unin
 
   // Send a message that will cause the content to purge its
   // history entries and make itself seem uninteresting.
   await ContentTask.spawn(browser, null, async function() {
     // Epic hackery to make this browser seem suddenly boring.
     docShell.setCurrentURI(Services.io.newURI("about:blank"));
 
     let {sessionHistory} = docShell.QueryInterface(Ci.nsIWebNavigation);
-    sessionHistory.PurgeHistory(sessionHistory.count);
+    sessionHistory.legacySHistory.PurgeHistory(sessionHistory.count);
   });
 
   // Once this windowClosed Promise resolves, we should have finished
   // the flush and revisited our decision to put this window into
   // the closed windows array.
   let windowClosed = BrowserTestUtils.windowClosed(newWin);
 
   let handled = false;
--- a/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
+++ b/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
@@ -3,28 +3,28 @@ add_task(async function duplicateTab() {
   const TEST_URL = "data:text/html,foo";
   let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
 
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebNavigation)
                                  .QueryInterface(Ci.nsIDocShell);
-    let shEntry = docshell.sessionHistory.getEntryAtIndex(0, false);
+    let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0, false);
     is(shEntry.docshellID.toString(), docshell.historyID.toString());
   });
 
   let tab2 = gBrowser.duplicateTab(tab);
   await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
 
   await ContentTask.spawn(tab2.linkedBrowser, null, function() {
     let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebNavigation)
                                  .QueryInterface(Ci.nsIDocShell);
-    let shEntry = docshell.sessionHistory.getEntryAtIndex(0, false);
+    let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0, false);
     is(shEntry.docshellID.toString(), docshell.historyID.toString());
   });
 
   BrowserTestUtils.removeTab(tab);
   BrowserTestUtils.removeTab(tab2);
 });
 
 // Second test - open a tab and navigate across processes, which triggers sessionrestore to persist history.
@@ -34,17 +34,17 @@ add_task(async function contentToChromeN
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
 
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebNavigation)
                                  .QueryInterface(Ci.nsIDocShell);
     let sh = docshell.sessionHistory;
     is(sh.count, 1);
-    is(sh.getEntryAtIndex(0, false).docshellID.toString(), docshell.historyID.toString());
+    is(sh.legacySHistory.getEntryAtIndex(0, false).docshellID.toString(), docshell.historyID.toString());
   });
 
   // Force the browser to navigate to the chrome process.
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     const CHROME_URL = "about:config";
     let webnav = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation);
     webnav.loadURI(CHROME_URL, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
@@ -53,13 +53,13 @@ add_task(async function contentToChromeN
 
   // Check to be sure that we're in the chrome process.
   let docShell = tab.linkedBrowser.frameLoader.docShell;
 
   // 'cause we're in the chrome process, we can just directly poke at the shistory.
   let sh = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
 
   is(sh.count, 2);
-  is(sh.getEntryAtIndex(0, false).docshellID.toString(), docShell.historyID.toString());
-  is(sh.getEntryAtIndex(1, false).docshellID.toString(), docShell.historyID.toString());
+  is(sh.legacySHistory.getEntryAtIndex(0, false).docshellID.toString(), docShell.historyID.toString());
+  is(sh.legacySHistory.getEntryAtIndex(1, false).docshellID.toString(), docShell.historyID.toString());
 
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/sessionstore/test/browser_purge_shistory.js
+++ b/browser/components/sessionstore/test/browser_purge_shistory.js
@@ -10,17 +10,17 @@ const TAB_STATE = {
   entries: [{url: "about:mozilla", triggeringPrincipal_base64},
             {url: "about:robots", triggeringPrincipal_base64}],
   index: 1,
 };
 
 function checkTabContents(browser) {
   return ContentTask.spawn(browser, null, async function() {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
+    let history = webNavigation.sessionHistory;
     Assert.ok(history && history.count == 1 && content.document.documentURI == "about:mozilla",
       "expected tab contents found");
   });
 }
 
 add_task(async function() {
   // Create a new tab.
   let tab = BrowserTestUtils.addTab(gBrowser, "about:blank");
--- a/browser/components/sessionstore/test/browser_replace_load.js
+++ b/browser/components/sessionstore/test/browser_replace_load.js
@@ -37,15 +37,15 @@ var testSwitchToTab = async function(url
 
   // Tab should now restore
   await promiseTabRestored(tab);
   is(browser.currentURI.spec, url, "correct URL loaded");
 
   // Check that we didn't lose any history entries.
   await ContentTask.spawn(browser, null, async function() {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
+    let history = webNavigation.sessionHistory;
     Assert.equal(history && history.count, 3, "three history entries");
   });
 
   // Cleanup.
   gBrowser.removeTab(tab);
 };
--- a/browser/components/sessionstore/test/browser_switch_remoteness.js
+++ b/browser/components/sessionstore/test/browser_switch_remoteness.js
@@ -1,16 +1,16 @@
 "use strict";
 
 const URL = "http://example.com/browser_switch_remoteness_";
 
 function countHistoryEntries(browser, expected) {
   return ContentTask.spawn(browser, { expected }, async function(args) {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
+    let history = webNavigation.sessionHistory;
     Assert.equal(history && history.count, args.expected,
       "correct number of shistory entries");
   });
 }
 
 add_task(async function() {
   // Open a new window.
   let win = await promiseNewWindowLoaded();
--- a/browser/components/sessionstore/test/content.js
+++ b/browser/components/sessionstore/test/content.js
@@ -49,17 +49,17 @@ var historyListener = {
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsISHistoryListener,
     Ci.nsISupportsWeakReference
   ])
 };
 
 var {sessionHistory} = docShell.QueryInterface(Ci.nsIWebNavigation);
 if (sessionHistory) {
-  sessionHistory.addSHistoryListener(historyListener);
+  sessionHistory.legacySHistory.addSHistoryListener(historyListener);
 }
 
 /**
  * This frame script is only loaded for sessionstore mochitests. It enables us
  * to modify and query docShell data when running with multiple processes.
  */
 
 addEventListener("hashchange", function() {
--- a/docshell/test/browser/browser_bug422543.js
+++ b/docshell/test/browser/browser_bug422543.js
@@ -9,21 +9,21 @@ add_task(async function runTests() {
 
   // Check if all history listeners are always notified.
   info("# part 1");
   await whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
   await checkListeners("newentry", "shistory has a new entry");
   ok(browser.canGoBack, "we can go back");
 
   await whenPageShown(browser, () => browser.goBack());
-  await checkListeners("goback", "back to the first shentry");
+  await checkListeners("gotoindex", "back to the first shentry");
   ok(browser.canGoForward, "we can go forward");
 
   await whenPageShown(browser, () => browser.goForward());
-  await checkListeners("goforward", "forward to the second shentry");
+  await checkListeners("gotoindex", "forward to the second shentry");
 
   await whenPageShown(browser, () => browser.reload());
   await checkListeners("reload", "current shentry reloaded");
 
   await whenPageShown(browser, () => browser.gotoIndex(0));
   await checkListeners("gotoindex", "back to the first index");
 
   // Check nsISHistoryInternal.notifyOnHistoryReload
--- a/docshell/test/browser/browser_bug655273.js
+++ b/docshell/test/browser/browser_bug655273.js
@@ -18,13 +18,13 @@ add_task(async function test() {
         let oldTitle = cw.document.title;
         ok(oldTitle, 'Content window should initially have a title.');
         cw.history.pushState('', '', 'new_page');
 
         let shistory = cw.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIWebNavigation)
                          .sessionHistory;
 
-        is(shistory.getEntryAtIndex(shistory.index, false).title,
+        is(shistory.legacySHistory.getEntryAtIndex(shistory.index, false).title,
            oldTitle, 'SHEntry title after pushstate.');
       });
     });
 });
--- a/docshell/test/browser/browser_bug670318.js
+++ b/docshell/test/browser/browser_bug670318.js
@@ -25,17 +25,17 @@ add_task(async function test() {
           if (aNewURI.spec == URL && 5 == ++count) {
             addEventListener("load", function onLoad() {
               removeEventListener("load", onLoad, true);
 
               Assert.ok(history.index < history.count, "history.index is valid");
               testDone.resolve();
             }, true);
 
-            history.removeSHistoryListener(listener);
+            history.legacySHistory.removeSHistoryListener(listener);
             delete content._testListener;
             content.setTimeout(() => { content.location.reload(); }, 0);
           }
 
           return true;
         },
 
         OnHistoryReload: () => true,
@@ -50,17 +50,17 @@ add_task(async function test() {
           ++count;
           return true;
         },
 
         QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
                                                Ci.nsISupportsWeakReference])
       };
 
-      history.addSHistoryListener(listener);
+      history.legacySHistory.addSHistoryListener(listener);
       // Since listener implements nsISupportsWeakReference, we are
       // responsible for keeping it alive so that the GC doesn't clear
       // it before the test completes. We do this by anchoring the listener
       // to the content global window, and clearing it just before the test
       // completes.
       content._testListener = listener;
       content.location = URL;
 
--- a/docshell/test/browser/file_bug422543_script.js
+++ b/docshell/test/browser/file_bug422543_script.js
@@ -45,23 +45,23 @@ SHistoryListener.prototype = {
 let testAPI = {
   shistory: null,
   listeners: [ new SHistoryListener(),
                new SHistoryListener() ],
 
   init() {
     this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
     for (let listener of this.listeners) {
-      this.shistory.addSHistoryListener(listener);
+      this.shistory.legacySHistory.addSHistoryListener(listener);
     }
   },
 
   cleanup() {
     for (let listener of this.listeners) {
-      this.shistory.removeSHistoryListener(listener);
+      this.shistory.legacySHistory.removeSHistoryListener(listener);
     }
     this.shistory = null;
     sendAsyncMessage("bug422543:cleanup:return", {});
   },
 
   getListenerStatus() {
     sendAsyncMessage("bug422543:getListenerStatus:return",
                      this.listeners.map(l => l.last));
@@ -71,17 +71,17 @@ let testAPI = {
     for (let listener of this.listeners) {
       listener.last = "initial";
     }
 
     sendAsyncMessage("bug422543:resetListeners:return", {});
   },
 
   notifyReload() {
-    let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
+    let internal = this.shistory.legacySHistory.QueryInterface(Ci.nsISHistoryInternal);
     let rval =
       internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
     sendAsyncMessage("bug422543:notifyReload:return", { rval });
   },
 
   setRetval({ num, val }) {
     this.listeners[num].retval = val;
     sendAsyncMessage("bug422543:setRetval:return", {});
--- a/docshell/test/chrome/bug112564_window.xul
+++ b/docshell/test/chrome/bug112564_window.xul
@@ -30,17 +30,17 @@
 
     function finish() {
       for (let eventType of LISTEN_EVENTS) {
         gBrowser.removeEventListener(eventType, eventListener, true);
       }
 
       // Work around bug 467960
       var history = gBrowser.webNavigation.sessionHistory;
-      history.PurgeHistory(history.count);
+      history.legacySHistory.PurgeHistory(history.count);
 
       window.close();
       window.opener.wrappedJSObject.SimpleTest.finish();
     }
 
     function onLoad() {
       gBrowser = document.getElementById("content");
       for (let eventType of LISTEN_EVENTS) {
--- a/docshell/test/chrome/bug215405_window.xul
+++ b/docshell/test/chrome/bug215405_window.xul
@@ -29,17 +29,17 @@
     var gTestsIterator;
     var scrollX = 0;
     var scrollY = 0;
 
     function finish() {
       gBrowser.removeEventListener("pageshow", eventListener, true);
       // Work around bug 467960
       var history = gBrowser.webNavigation.sessionHistory;
-      history.PurgeHistory(history.count);
+      history.legacySHistory.PurgeHistory(history.count);
 
       window.close();
       window.opener.wrappedJSObject.SimpleTest.finish();
     }
 
     function onLoad(e) {
       gBrowser = document.getElementById("content");
       gBrowser.addEventListener("pageshow", eventListener, true);
--- a/docshell/test/chrome/bug396519_window.xul
+++ b/docshell/test/chrome/bug396519_window.xul
@@ -54,31 +54,31 @@
       // runs, we should should be in a testable state
       setTimeout(doTest, 0);
     }
 
     function doTest() {
       var history = gBrowser.webNavigation.sessionHistory;
       if (history.count == gExpected.length) {
         for (var i=0; i<history.count; i++) {
-          var shEntry = history.getEntryAtIndex(i,false).
+          var shEntry = history.legacySHistory.getEntryAtIndex(i,false).
                           QueryInterface(Ci.nsISHEntry);
           is(!!shEntry.contentViewer, gExpected[i], "content viewer "+i+", test "+gTestCount);
         }
 
         // Make sure none of the SHEntries share bfcache entries with one
         // another.
         for (var i = 0; i < history.count; i++) {
           for (var j = 0; j < history.count; j++) {
             if (j == i)
               continue;
 
-            let shentry1 = history.getEntryAtIndex(i, false)
+            let shentry1 = history.legacySHistory.getEntryAtIndex(i, false)
                                   .QueryInterface(Ci.nsISHEntry);
-            let shentry2 = history.getEntryAtIndex(j, false)
+            let shentry2 = history.legacySHistory.getEntryAtIndex(j, false)
                                   .QueryInterface(Ci.nsISHEntry);
             ok(!shentry1.sharesDocumentWith(shentry2),
                'Test ' + gTestCount + ': shentry[' + i + "] shouldn't " +
                "share document with shentry[" + j + ']');
           }
         }
       }
       else {
--- a/docshell/test/chrome/bug92598_window.xul
+++ b/docshell/test/chrome/bug92598_window.xul
@@ -30,17 +30,17 @@
 
     function finish() {
       for (let eventType of LISTEN_EVENTS) {
         gBrowser.removeEventListener(eventType, eventListener, true);
       }
      
       // Work around bug 467960
       var history = gBrowser.webNavigation.sessionHistory;
-      history.PurgeHistory(history.count);
+      history.legacySHistory.PurgeHistory(history.count);
 
       window.close();
       window.opener.wrappedJSObject.SimpleTest.finish();
     }
 
     function onLoad() {
       gBrowser = document.getElementById("content");
       for (let eventType of LISTEN_EVENTS) {
--- a/docshell/test/chrome/docshell_helpers.js
+++ b/docshell/test/chrome/docshell_helpers.js
@@ -336,17 +336,17 @@ function pageEventListener(event) {
 }
 
 /**
  * End a test.  
  */
 function finish() {
   // Work around bug 467960.
   var history = TestWindow.getBrowser().webNavigation.sessionHistory;
-  history.PurgeHistory(history.count);
+  history.legacySHistory.PurgeHistory(history.count);
   
   // If the test changed the value of max_total_viewers via a call to
   // enableBFCache(), then restore it now.
   if (typeof(gOrigMaxTotalViewers) != "undefined") {
     var prefs = Cc["@mozilla.org/preferences-service;1"]
                 .getService(Ci.nsIPrefBranch);
     prefs.setIntPref("browser.sessionhistory.max_total_viewers",
       gOrigMaxTotalViewers);
--- a/docshell/test/navigation/file_bug1300461.html
+++ b/docshell/test/navigation/file_bug1300461.html
@@ -35,17 +35,17 @@
           opener.ok(!webNav.canGoForward, 'check canGoForward');
           setTimeout(() => window.location = 'file_bug1300461_back.html', 0);
         },
         function() {
           opener.is(shistory.count, 2, 'check history length');
           opener.is(shistory.index, 0, 'check history index');
           opener.ok(webNav.canGoForward, 'check canGoForward');
           window.history.forward();
-          opener.is(shistory.requestedIndex, 1, 'check requestedIndex');
+          opener.is(shistory.legacySHistory.requestedIndex, 1, 'check requestedIndex');
         },
         function() {
           opener.is(shistory.count, 2, 'check history length');
           opener.is(shistory.index, 0, 'check history index');
           opener.ok(webNav.canGoForward, 'check canGoForward');
           opener.info('file_bug1300461.html tests finished');
           opener.nextTest();
           window.close();
--- a/docshell/test/navigation/file_bug1300461_back.html
+++ b/docshell/test/navigation/file_bug1300461_back.html
@@ -12,17 +12,17 @@
                      .QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIWebNavigation);
       let shistory = webNav.sessionHistory;
       function test() {
         if (opener) {
           opener.info("file_bug1300461_back.html");
           opener.is(shistory.count, 2, 'check history length');
           opener.is(shistory.index, 1, 'check history index');
-          opener.is(shistory.requestedIndex, -1, 'check requestedIndex');
+          opener.is(shistory.legacySHistory.requestedIndex, -1, 'check requestedIndex');
           opener.ok(webNav.canGoBack, 'check canGoBack');
           if (opener.testCount == 1) {
             opener.info('replaceState to redirect.html');
             window.history.replaceState({}, '', 'file_bug1300461_redirect.html');
           }
           window.history.back();
         }
       }
--- a/docshell/test/navigation/file_bug1326251_evict_cache.html
+++ b/docshell/test/navigation/file_bug1326251_evict_cache.html
@@ -7,17 +7,17 @@
     SpecialPowers.Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
 
     // Evict bfcache and then go back.
     async function evictCache() {
       let shistory = SpecialPowers.wrap(window)
                        .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
                        .getInterface(SpecialPowers.Ci.nsIWebNavigation)
                        .sessionHistory;
-      let shPrivate = shistory.QueryInterface(SpecialPowers.Ci.nsISHistoryInternal);
+      let shPrivate = shistory.legacySHistory.QueryInterface(SpecialPowers.Ci.nsISHistoryInternal);
       shPrivate.evictAllContentViewers();
       history.back();
     }
     </script>
   </head>
   <body onload="setTimeout(evictCache, 0);">
   </body>
 </html>
--- a/docshell/test/navigation/test_bug1375833.html
+++ b/docshell/test/navigation/test_bug1375833.html
@@ -44,17 +44,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       ok(e.data.endsWith("file_bug1375833-frame2.html"), "check location");
       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.getEntryAtIndex(shistory.index, false);
+      let entry = shistory.legacySHistory.getEntryAtIndex(shistory.index, false);
       let frameEntry = SpecialPowers.wrap(entry)
                        .QueryInterface(SpecialPowers.Ci.nsISHContainer)
                        .GetChildAt(0);
       is(String(frameEntry.docshellID), frameDocShellId, "check newly added shentry uses the same docshell ID");
 
       webNav.goBack();
       break;
     case 2:
--- a/docshell/test/test_bug509055.html
+++ b/docshell/test/test_bug509055.html
@@ -70,18 +70,18 @@ function* runTest() {
   dump('Got second hashchange.  Spinning event loop.\n');
   yield undefined;
 
   var sh = SpecialPowers.wrap(popup)
                         .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
                         .getInterface(SpecialPowers.Ci.nsIWebNavigation)
                         .sessionHistory;
 
-  // Get the title of the inner popup's current SHEntry 
-  var sheTitle = sh.getEntryAtIndex(sh.index, false).title;
+  // Get the title of the inner popup's current SHEntry
+  var sheTitle = sh.legacySHistory.getEntryAtIndex(sh.index, false).title;
   is(sheTitle, "Changed", "SHEntry's title should change when we change.");
 
   popup.close();
 
   SimpleTest.executeSoon(SimpleTest.finish);
 }
 
 window.addEventListener('load', function() {
--- a/docshell/test/test_bug590573.html
+++ b/docshell/test/test_bug590573.html
@@ -101,20 +101,20 @@ function dumpSHistory(theWindow)
                     .sessionHistory;
   if (!sh) {
     dump(" window has no shistory.\n");
     return;
   }
 
   dump(" count: " + sh.count + "\n");
   dump(" index: " + sh.index + "\n");
-  dump(" requestedIndex: " + sh.requestedIndex + "\n");
+  dump(" requestedIndex: " + sh.legacySHistory.requestedIndex + "\n");
 
   for (let i = 0; i < sh.count; i++) {
-    let shentry = sh.getEntryAtIndex(i, false);
+    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');
     }
   }
 
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -134,17 +134,19 @@ BrowserElementChild.prototype = {
     docShell.QueryInterface(Ci.nsIWebProgress)
             .addProgressListener(this._progressListener,
                                  Ci.nsIWebProgress.NOTIFY_LOCATION |
                                  Ci.nsIWebProgress.NOTIFY_SECURITY |
                                  Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
 
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
     if (!webNavigation.sessionHistory) {
-      // XXX(nika): We might need to start this up some other way?
+      // XXX(nika): I don't think this code should ever be hit? We should run
+      // TabChild::Init before we run this code which will perform this setup
+      // for us.
       docShell.initSessionHistory();
     }
 
     // This is necessary to get security web progress notifications.
     var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
                        .createInstance(Ci.nsISecureBrowserUI);
     securityUI.init(content);
 
@@ -914,17 +916,17 @@ BrowserElementChild.prototype = {
 
   _recvPurgeHistory: function(data) {
     debug("Received purgeHistory message: (" + data.json.id + ")");
 
     let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
 
     try {
       if (history && history.count) {
-        history.PurgeHistory(history.count);
+        history.legacySHistory.PurgeHistory(history.count);
       }
     } catch(e) {}
 
     sendAsyncMsg('got-purge-history', { id: data.json.id, successRv: true });
   },
 
   _recvGetScreenshot: function(data) {
     debug("Received getScreenshot message: (" + data.json.id + ")");
--- a/dom/html/test/browser_bug649778.js
+++ b/dom/html/test/browser_bug649778.js
@@ -38,17 +38,17 @@ function checkCache(url, inMemory, shoul
                        Ci.nsICacheStorage.OPEN_READONLY,
                        new CheckCacheListener(inMemory, shouldExist));
 }
 function getPopupURL() {
   var sh = popup.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIWebNavigation)
                 .sessionHistory;
 
-  return sh.getEntryAtIndex(sh.index, false).URI.spec;
+  return sh.legacySHistory.getEntryAtIndex(sh.index, false).URI.spec;
 }
 
 var wyciwygURL;
 function testContinue() {
   wyciwygURL = getPopupURL();
   is(wyciwygURL.substring(0, 10), "wyciwyg://", "Unexpected URL.");
   popup.close()
 
--- a/dom/tests/mochitest/whatwg/test_bug500328.html
+++ b/dom/tests/mochitest/whatwg/test_bug500328.html
@@ -172,17 +172,17 @@ function getSHistory(theWindow)
 }
 
 function getSHTitle(sh, offset)
 {
   if (!offset)
     offset = 0;
 
   // False instructs the SHistory not to modify its current index.
-  return sh.getEntryAtIndex(sh.index + offset, false).title;
+  return sh.legacySHistory.getEntryAtIndex(sh.index + offset, false).title;
 }
 
 // Tests that win's location ends with str
 function locationEndsWith(win, str) {
   var exp = new RegExp(str + "$");
   ok(win.location.toString().match(exp),
      "Wrong window location.  Expected it to end with " +
      str + ", but actuall was " + win.location);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1879,17 +1879,17 @@ var BrowserApp = {
 
         // Try to use the session history to reload so that framesets are
         // handled properly. If the window has no session history, fall back
         // to using the web navigation's reload method.
         let webNav = browser.webNavigation;
         try {
           let sh = webNav.sessionHistory;
           if (sh)
-            webNav = sh.QueryInterface(Ci.nsIWebNavigation);
+            webNav = sh.legacySHistory.QueryInterface(Ci.nsIWebNavigation);
         } catch (e) {}
         webNav.reload(flags);
         break;
       }
 
       case "Session:Restore":
         GlobalEventDispatcher.dispatch("Session:Restore", data);
         break;
@@ -2235,17 +2235,17 @@ var BrowserApp = {
       // return empty list immediately.
       return {
         "historyItems": listitems,
         "toIndex": toIndex
       };
     }
 
     let browser = this.selectedBrowser;
-    let hist = browser.sessionHistory;
+    let hist = browser.sessionHistory.legacySHistory;
     for (let i = toIndex; i >= fromIndex; i--) {
       let entry = hist.getEntryAtIndex(i, false);
       let item = {
         title: entry.title || entry.URI.displaySpec,
         url: entry.URI.displaySpec,
         selected: (i == selIndex)
       };
       listitems.push(item);
@@ -3713,17 +3713,17 @@ Tab.prototype = {
     }
 
     let flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL |
                 Ci.nsIWebProgress.NOTIFY_LOCATION |
                 Ci.nsIWebProgress.NOTIFY_SECURITY;
     this.filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"].createInstance(Ci.nsIWebProgress);
     this.filter.addProgressListener(this, flags)
     this.browser.addProgressListener(this.filter, flags);
-    this.browser.sessionHistory.addSHistoryListener(this);
+    this.browser.sessionHistory.legacySHistory.addSHistoryListener(this);
 
     this.browser.addEventListener("DOMContentLoaded", this, true);
     this.browser.addEventListener("DOMFormHasPassword", this, true);
     this.browser.addEventListener("DOMLinkAdded", this, true);
     this.browser.addEventListener("DOMLinkChanged", this, true);
     this.browser.addEventListener("DOMMetaAdded", this);
     this.browser.addEventListener("DOMTitleChanged", this, true);
     this.browser.addEventListener("DOMAudioPlaybackStarted", this, true);
@@ -3837,17 +3837,17 @@ Tab.prototype = {
 
   destroy: function() {
     if (!this.browser)
       return;
 
     this.browser.removeProgressListener(this.filter);
     this.filter.removeProgressListener(this);
     this.filter = null;
-    this.browser.sessionHistory.removeSHistoryListener(this);
+    this.browser.sessionHistory.legacySHistory.removeSHistoryListener(this);
 
     this.browser.removeEventListener("DOMContentLoaded", this, true);
     this.browser.removeEventListener("DOMFormHasPassword", this, true);
     this.browser.removeEventListener("DOMLinkAdded", this, true);
     this.browser.removeEventListener("DOMLinkChanged", this, true);
     this.browser.removeEventListener("DOMMetaAdded", this);
     this.browser.removeEventListener("DOMTitleChanged", this, true);
     this.browser.removeEventListener("DOMAudioPlaybackStarted", this, true);
--- a/testing/firefox-ui/tests/puppeteer/test_toolbars.py
+++ b/testing/firefox-ui/tests/puppeteer/test_toolbars.py
@@ -17,17 +17,17 @@ class TestNavBar(PuppeteerMixin, Marione
         self.url = self.marionette.absolute_url('layout/mozilla.html')
 
         with self.marionette.using_context('content'):
             self.marionette.navigate('about:blank')
 
         # TODO: check why self.puppeteer.places.remove_all_history() does not work here
         self.marionette.execute_script("""
             let count = gBrowser.sessionHistory.count;
-            gBrowser.sessionHistory.PurgeHistory(count);
+            gBrowser.sessionHistory.legacySHistory.PurgeHistory(count);
         """)
 
     def test_elements(self):
         self.assertEqual(self.navbar.back_button.get_property('localName'), 'toolbarbutton')
         self.assertEqual(self.navbar.forward_button.get_property('localName'), 'toolbarbutton')
         self.assertEqual(self.navbar.home_button.get_property('localName'), 'toolbarbutton')
         self.assertEqual(self.navbar.menu_button.get_property('localName'), 'toolbarbutton')
         self.assertEqual(self.navbar.toolbar.get_property('localName'), 'toolbar')
--- a/toolkit/components/reader/ReaderMode.jsm
+++ b/toolkit/components/reader/ReaderMode.jsm
@@ -97,17 +97,17 @@ var ReaderMode = {
    * if not, append the about:reader page in the history instead.
    */
   enterReaderMode(docShell, win) {
     let url = win.document.location.href;
     let readerURL = "about:reader?url=" + encodeURIComponent(url);
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     let sh = webNav.sessionHistory;
     if (webNav.canGoForward) {
-      let forwardEntry = sh.getEntryAtIndex(sh.index + 1, false);
+      let forwardEntry = sh.legacySHistory.getEntryAtIndex(sh.index + 1, false);
       let forwardURL = forwardEntry.URI.spec;
       if (forwardURL && (forwardURL == readerURL || !readerURL)) {
         webNav.goForward();
         return;
       }
     }
 
     win.document.location = readerURL;
@@ -118,17 +118,17 @@ var ReaderMode = {
    * if not, append the original page in the history instead.
    */
   leaveReaderMode(docShell, win) {
     let url = win.document.location.href;
     let originalURL = this.getOriginalUrl(url);
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     let sh = webNav.sessionHistory;
     if (webNav.canGoBack) {
-      let prevEntry = sh.getEntryAtIndex(sh.index - 1, false);
+      let prevEntry = sh.legacySHistory.getEntryAtIndex(sh.index - 1, false);
       let prevURL = prevEntry.URI.spec;
       if (prevURL && (prevURL == originalURL || !originalURL)) {
         webNav.goBack();
         return;
       }
     }
 
     win.document.location = originalURL;
--- a/toolkit/components/viewsource/content/viewSource-content.js
+++ b/toolkit/components/viewsource/content/viewSource-content.js
@@ -265,16 +265,17 @@ var ViewSourceContent = {
     shEntry.setURI(Services.io.newURI(viewSrcURL));
     shEntry.setTitle(viewSrcURL);
     let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
     shEntry.triggeringPrincipal = systemPrincipal;
     shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
     shEntry.cacheKey = shEntrySource.cacheKey;
     docShell.QueryInterface(Ci.nsIWebNavigation)
             .sessionHistory
+            .legacySHistory
             .QueryInterface(Ci.nsISHistoryInternal)
             .addEntry(shEntry, true);
   },
 
   /**
    * Load some URL in the browser.
    *
    * @param URL
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -1272,29 +1272,30 @@ UnselectedTabHoverObserver.init();
 addMessageListener("Browser:PurgeSessionHistory", function BrowserPurgeHistory() {
   let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
   if (!sessionHistory) {
     return;
   }
 
   // place the entry at current index at the end of the history list, so it won't get removed
   if (sessionHistory.index < sessionHistory.count - 1) {
-    let indexEntry = sessionHistory.getEntryAtIndex(sessionHistory.index, false);
-    sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
+    let legacy = sessionHistory.legacySHistory;
+    legacy.QueryInterface(Ci.nsISHistoryInternal);
+    let indexEntry = legacy.getEntryAtIndex(sessionHistory.index, false);
     indexEntry.QueryInterface(Ci.nsISHEntry);
-    sessionHistory.addEntry(indexEntry, true);
+    legacy.addEntry(indexEntry, true);
   }
 
   let purge = sessionHistory.count;
   if (global.content.location.href != "about:blank") {
     --purge; // Don't remove the page the user's staring at from shistory
   }
 
   if (purge > 0) {
-    sessionHistory.PurgeHistory(purge);
+    sessionHistory.legacySHistory.PurgeHistory(purge);
   }
 });
 
 var ViewSelectionSource = {
   init() {
     addMessageListener("ViewSource:GetSelection", this);
   },
 
--- a/toolkit/modules/E10SUtils.jsm
+++ b/toolkit/modules/E10SUtils.jsm
@@ -219,19 +219,19 @@ var E10SUtils = {
         !aDocShell.awaitingLargeAlloc &&
         aDocShell.isOnlyToplevelInTabGroup) {
       return false;
     }
 
     // Allow history load if loaded in this process before.
     let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation);
     let sessionHistory = webNav.sessionHistory;
-    let requestedIndex = sessionHistory.requestedIndex;
+    let requestedIndex = sessionHistory.legacySHistory.requestedIndex;
     if (requestedIndex >= 0) {
-      if (sessionHistory.getEntryAtIndex(requestedIndex, false).loadedInThisProcess) {
+      if (sessionHistory.legacySHistory.getEntryAtIndex(requestedIndex, false).loadedInThisProcess) {
         return true;
       }
 
       // If not originally loaded in this process allow it if the URI would
       // normally be allowed to load in this process by default.
       let remoteType = Services.appinfo.remoteType;
       return remoteType ==
         this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI);
@@ -260,17 +260,17 @@ var E10SUtils = {
         uri: aURI.spec,
         flags: aFlags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
         referrer: aReferrer ? aReferrer.spec : null,
         triggeringPrincipal: aTriggeringPrincipal
                              ? Utils.serializePrincipal(aTriggeringPrincipal)
                              : null,
         reloadInFreshProcess: !!aFreshProcess,
       },
-      historyIndex: sessionHistory.requestedIndex,
+      historyIndex: sessionHistory.legacySHistory.requestedIndex,
     });
     return false;
   },
 
   wrapHandlingUserInput(aWindow, aIsHandling, aCallback) {
     var handlingUserInput;
     try {
       handlingUserInput = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -67,28 +67,29 @@ var SessionHistoryInternal = {
    *        The docShell that owns the session history.
    * @param aFromIdx
    *        The starting local index to collect the history from.
    * @return An object reprereseting a partial global history update.
    */
   collect(docShell, aFromIdx = -1) {
     let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
+    let history = webNavigation.sessionHistory;
 
     let data = {entries: [], userContextId: loadContext.originAttributes.userContextId };
     // We want to keep track how many entries we *could* have collected and
     // how many we skipped, so we can sanitiy-check the current history index
     // and also determine whether we need to get any fallback data or not.
     let skippedCount = 0, entryCount = 0;
 
     if (history && history.count > 0) {
       // Loop over the transaction linked list directly so we can get the
       // persist property for each transaction.
-      for (let txn = history.rootTransaction; txn; entryCount++, txn = txn.next) {
+      for (let txn = history.legacySHistory.QueryInterface(Ci.nsISHistoryInternal).rootTransaction;
+           txn; entryCount++, txn = txn.next) {
         if (entryCount <= aFromIdx) {
           skippedCount++;
           continue;
         }
         let entry = this.serializeEntry(txn.sHEntry);
         entry.persist = txn.persist;
         data.entries.push(entry);
       }
@@ -312,17 +313,17 @@ var SessionHistoryInternal = {
    * @param docShell
    *        The docShell that owns the session history.
    * @param tabData
    *        The tabdata including all history entries.
    * @return A reference to the docShell's nsISHistoryInternal interface.
    */
   restore(docShell, tabData) {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
-    let history = webNavigation.sessionHistory;
+    let history = webNavigation.sessionHistory.legacySHistory;
     if (history.count > 0) {
       history.PurgeHistory(history.count);
     }
     history.QueryInterface(Ci.nsISHistoryInternal);
 
     let idMap = { used: {} };
     let docIdentMap = {};
     for (let i = 0; i < tabData.entries.length; i++) {