summaryrefslogtreecommitdiffstats
path: root/browser/components/sessionstore/test/browser_async_remove_tab.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/sessionstore/test/browser_async_remove_tab.js')
-rw-r--r--browser/components/sessionstore/test/browser_async_remove_tab.js242
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");
+});