forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			242 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "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");
 | |
| });
 | 
