requestLongerTimeout(2); const DUMMY_PATH = "browser/browser/base/content/test/general/dummy_page.html"; const gExpectedHistory = { index: -1, entries: [] }; function get_remote_history(browser) { function frame_script() { let webNav = docShell.QueryInterface(Components.interfaces.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); result.entries.push({ uri: entry.URI.spec, title: entry.title }); } sendAsyncMessage("Test:History", result); } return new Promise(resolve => { browser.messageManager.addMessageListener("Test:History", function listener({data}) { browser.messageManager.removeMessageListener("Test:History", listener); resolve(data); }); browser.messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); }); } var check_history = Task.async(function*() { let sessionHistory = yield get_remote_history(gBrowser.selectedBrowser); let count = sessionHistory.entries.length; is(count, gExpectedHistory.entries.length, "Should have the right number of history entries"); is(sessionHistory.index, gExpectedHistory.index, "Should have the right history index"); for (let i = 0; i < count; i++) { let entry = sessionHistory.entries[i]; is(entry.uri, gExpectedHistory.entries[i].uri, "Should have the right URI"); is(entry.title, gExpectedHistory.entries[i].title, "Should have the right title"); } }); function clear_history() { gExpectedHistory.index = -1; gExpectedHistory.entries = []; } // Waits for a load and updates the known history var waitForLoad = Task.async(function*(uri) { info("Loading " + uri); // Longwinded but this ensures we don't just shortcut to LoadInNewProcess gBrowser.selectedBrowser.webNavigation.loadURI(uri, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null); yield waitForDocLoadComplete(); gExpectedHistory.index++; gExpectedHistory.entries.push({ uri: gBrowser.currentURI.spec, title: gBrowser.contentTitle }); }); // Waits for a load and updates the known history var waitForLoadWithFlags = Task.async(function*(uri, flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE) { info("Loading " + uri + " flags = " + flags); gBrowser.selectedBrowser.loadURIWithFlags(uri, flags, null, null, null); yield waitForDocLoadComplete(); if (!(flags & Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY)) { if (flags & Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY) { gExpectedHistory.entries.pop(); } else { gExpectedHistory.index++; } gExpectedHistory.entries.push({ uri: gBrowser.currentURI.spec, title: gBrowser.contentTitle }); } }); var back = Task.async(function*() { info("Going back"); gBrowser.goBack(); yield waitForDocLoadComplete(); gExpectedHistory.index--; }); var forward = Task.async(function*() { info("Going forward"); gBrowser.goForward(); yield waitForDocLoadComplete(); gExpectedHistory.index++; }); // Tests that navigating from a page that should be in the remote process and // a page that should be in the main process works and retains history add_task(function* test_navigation() { let expectedRemote = gMultiProcessBrowser; info("1"); // Create a tab and load a remote page in it gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true}); let {permanentKey} = gBrowser.selectedBrowser; yield waitForLoad("http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("2"); // Load another page yield waitForLoad("http://example.com/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("3"); // Load a non-remote page yield waitForLoad("about:robots"); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("4"); // Load a remote page yield waitForLoad("http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("5"); yield back(); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("6"); yield back(); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("7"); yield forward(); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("8"); yield forward(); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("9"); yield back(); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("10"); // Load a new remote page, this should replace the last history entry gExpectedHistory.entries.splice(gExpectedHistory.entries.length - 1, 1); yield waitForLoad("http://example.com/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield check_history(); info("11"); gBrowser.removeCurrentTab(); clear_history(); }); // Tests that calling gBrowser.loadURI or browser.loadURI to load a page in a // different process updates the browser synchronously add_task(function* test_synchronous() { let expectedRemote = gMultiProcessBrowser; info("1"); // Create a tab and load a remote page in it gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true}); let {permanentKey} = gBrowser.selectedBrowser; yield waitForLoad("http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("2"); // Load another page info("Loading about:robots"); yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:robots"); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield waitForDocLoadComplete(); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("3"); // Load the remote page again info("Loading http://example.org/" + DUMMY_PATH); yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield waitForDocLoadComplete(); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("4"); gBrowser.removeCurrentTab(); clear_history(); }); // Tests that load flags are correctly passed through to the child process with // normal loads add_task(function* test_loadflags() { let expectedRemote = gMultiProcessBrowser; info("1"); // Create a tab and load a remote page in it gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true}); yield waitForLoadWithFlags("about:robots"); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); yield check_history(); info("2"); // Load a page in the remote process with some custom flags yield waitForLoadWithFlags("http://example.com/" + DUMMY_PATH, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); yield check_history(); info("3"); // Load a non-remote page yield waitForLoadWithFlags("about:robots"); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); yield check_history(); info("4"); // Load another remote page yield waitForLoadWithFlags("http://example.org/" + DUMMY_PATH, Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); yield check_history(); is(gExpectedHistory.entries.length, 2, "Should end with the right number of history entries"); info("5"); gBrowser.removeCurrentTab(); clear_history(); });