diff options
Diffstat (limited to 'browser/components/sessionstore/test/browser_async_remove_tab.js')
-rw-r--r-- | browser/components/sessionstore/test/browser_async_remove_tab.js | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/browser/components/sessionstore/test/browser_async_remove_tab.js b/browser/components/sessionstore/test/browser_async_remove_tab.js new file mode 100644 index 000000000..20f3463d0 --- /dev/null +++ b/browser/components/sessionstore/test/browser_async_remove_tab.js @@ -0,0 +1,242 @@ +"use strict"; + +function* createTabWithRandomValue(url) { + let tab = gBrowser.addTab(url); + let browser = tab.linkedBrowser; + yield promiseBrowserLoaded(browser); + + // Set a random value. + let r = `rand-${Math.random()}`; + ss.setTabValue(tab, "foobar", r); + + // Flush to ensure there are no scheduled messages. + yield TabStateFlusher.flush(browser); + + return {tab, r}; +} + +function isValueInClosedData(rval) { + return ss.getClosedTabData(window).includes(rval); +} + +function restoreClosedTabWithValue(rval) { + let closedTabData = JSON.parse(ss.getClosedTabData(window)); + let index = closedTabData.findIndex(function (data) { + return (data.state.extData && data.state.extData.foobar) == rval; + }); + + if (index == -1) { + throw new Error("no closed tab found for given rval"); + } + + return ss.undoCloseTab(window, index); +} + +function promiseNewLocationAndHistoryEntryReplaced(browser, snippet) { + return ContentTask.spawn(browser, snippet, function* (snippet) { + let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); + let shistory = webNavigation.sessionHistory; + + // Evaluate the snippet that the changes the location. + eval(snippet); + + return new Promise(resolve => { + let listener = { + OnHistoryReplaceEntry() { + shistory.removeSHistoryListener(this); + resolve(); + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsISHistoryListener, + Ci.nsISupportsWeakReference + ]) + }; + + shistory.addSHistoryListener(listener); + + /* Keep the weak shistory listener alive. */ + addEventListener("unload", function () { + try { + shistory.removeSHistoryListener(listener); + } catch (e) { /* Will most likely fail. */ } + }); + }); + }); +} + +function promiseHistoryEntryReplacedNonRemote(browser) { + let {listeners} = promiseHistoryEntryReplacedNonRemote; + + return new Promise(resolve => { + let shistory = browser.webNavigation.sessionHistory; + + let listener = { + OnHistoryReplaceEntry() { + shistory.removeSHistoryListener(this); + resolve(); + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsISHistoryListener, + Ci.nsISupportsWeakReference + ]) + }; + + shistory.addSHistoryListener(listener); + listeners.set(browser, listener); + }); +} +promiseHistoryEntryReplacedNonRemote.listeners = new WeakMap(); + +add_task(function* dont_save_empty_tabs() { + let {tab, r} = yield createTabWithRandomValue("about:blank"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // No tab state worth saving. + ok(!isValueInClosedData(r), "closed tab not saved"); + yield promise; + + // Still no tab state worth saving. + ok(!isValueInClosedData(r), "closed tab not saved"); +}); + +add_task(function* save_worthy_tabs_remote() { + let {tab, r} = yield createTabWithRandomValue("https://example.com/"); + ok(tab.linkedBrowser.isRemoteBrowser, "browser is remote"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // Tab state deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); + yield promise; + + // Tab state still deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); +}); + +add_task(function* save_worthy_tabs_nonremote() { + let {tab, r} = yield createTabWithRandomValue("about:robots"); + ok(!tab.linkedBrowser.isRemoteBrowser, "browser is not remote"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // Tab state deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); + yield promise; + + // Tab state still deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); +}); + +add_task(function* save_worthy_tabs_remote_final() { + let {tab, r} = yield createTabWithRandomValue("about:blank"); + let browser = tab.linkedBrowser; + ok(browser.isRemoteBrowser, "browser is remote"); + + // Replace about:blank with a new remote page. + let snippet = 'webNavigation.loadURI("https://example.com/", null, null, null, null)'; + yield promiseNewLocationAndHistoryEntryReplaced(browser, snippet); + + // Remotness shouldn't have changed. + ok(browser.isRemoteBrowser, "browser is still remote"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // No tab state worth saving (that we know about yet). + ok(!isValueInClosedData(r), "closed tab not saved"); + yield promise; + + // Turns out there is a tab state worth saving. + ok(isValueInClosedData(r), "closed tab saved"); +}); + +add_task(function* save_worthy_tabs_nonremote_final() { + let {tab, r} = yield createTabWithRandomValue("about:blank"); + let browser = tab.linkedBrowser; + ok(browser.isRemoteBrowser, "browser is remote"); + + // Replace about:blank with a non-remote entry. + yield BrowserTestUtils.loadURI(browser, "about:robots"); + ok(!browser.isRemoteBrowser, "browser is not remote anymore"); + + // Wait until the new entry replaces about:blank. + yield promiseHistoryEntryReplacedNonRemote(browser); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // No tab state worth saving (that we know about yet). + ok(!isValueInClosedData(r), "closed tab not saved"); + yield promise; + + // Turns out there is a tab state worth saving. + ok(isValueInClosedData(r), "closed tab saved"); +}); + +add_task(function* dont_save_empty_tabs_final() { + let {tab, r} = yield createTabWithRandomValue("https://example.com/"); + let browser = tab.linkedBrowser; + + // Replace the current page with an about:blank entry. + let snippet = 'content.location.replace("about:blank")'; + yield promiseNewLocationAndHistoryEntryReplaced(browser, snippet); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // Tab state deemed worth saving (yet). + ok(isValueInClosedData(r), "closed tab saved"); + yield promise; + + // Turns out we don't want to save the tab state. + ok(!isValueInClosedData(r), "closed tab not saved"); +}); + +add_task(function* undo_worthy_tabs() { + let {tab, r} = yield createTabWithRandomValue("https://example.com/"); + ok(tab.linkedBrowser.isRemoteBrowser, "browser is remote"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // Tab state deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); + + // Restore the closed tab before receiving its final message. + tab = restoreClosedTabWithValue(r); + + // Wait for the final update message. + yield promise; + + // Check we didn't add the tab back to the closed list. + ok(!isValueInClosedData(r), "tab no longer closed"); + + // Cleanup. + yield promiseRemoveTab(tab); +}); + +add_task(function* forget_worthy_tabs_remote() { + let {tab, r} = yield createTabWithRandomValue("https://example.com/"); + ok(tab.linkedBrowser.isRemoteBrowser, "browser is remote"); + + // Remove the tab before the update arrives. + let promise = promiseRemoveTab(tab); + + // Tab state deemed worth saving. + ok(isValueInClosedData(r), "closed tab saved"); + + // Forget the closed tab. + ss.forgetClosedTab(window, 0); + + // Wait for the final update message. + yield promise; + + // Check we didn't add the tab back to the closed list. + ok(!isValueInClosedData(r), "we forgot about the tab"); +}); |