mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 867143 - Adapt testsuite to cached session restore. r=ttaubert
This commit is contained in:
parent
2b83439124
commit
327b5116d8
@ -27,6 +27,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_input.js \
|
||||
browser_input_sample.html \
|
||||
browser_pageshow.js \
|
||||
browser_sessionStorage.js \
|
||||
browser_upgrade_backup.js \
|
||||
browser_windowRestore_perwindowpb.js \
|
||||
browser_248970_b_perwindowpb.js \
|
||||
|
@ -2,13 +2,16 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let Scope = {};
|
||||
Cu.import("resource://gre/modules/Task.jsm", Scope);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", Scope);
|
||||
let {Task, Promise} = Scope;
|
||||
|
||||
|
||||
// This tests that a tab which is closed while loading is not lost.
|
||||
// Specifically, that session store does not rely on an invalid cache when
|
||||
// constructing data for a tab which is loading.
|
||||
|
||||
// The newly created tab which we load a URL into and try closing/undoing.
|
||||
let tab;
|
||||
|
||||
// This test steps through the following parts:
|
||||
// 1. Tab has been created is loading URI_TO_LOAD.
|
||||
// 2. Before URI_TO_LOAD finishes loading, browser.currentURI has changed and
|
||||
@ -17,69 +20,67 @@ let tab;
|
||||
// should fully load.
|
||||
const URI_TO_LOAD = "about:mozilla";
|
||||
|
||||
function waitForLoadStarted(aTab) {
|
||||
let deferred = Promise.defer();
|
||||
waitForContentMessage(aTab.linkedBrowser,
|
||||
"SessionStore:loadStart",
|
||||
1000,
|
||||
deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForTabLoaded(aTab) {
|
||||
let deferred = Promise.defer();
|
||||
whenBrowserLoaded(aTab.linkedBrowser, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForTabClosed() {
|
||||
let deferred = Promise.defer();
|
||||
let observer = function() {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", observer, true);
|
||||
deferred.resolve();
|
||||
};
|
||||
gBrowser.tabContainer.addEventListener("TabClose", observer, true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.addTabsProgressListener(tabsListener);
|
||||
Task.spawn(function() {
|
||||
try {
|
||||
// Open a new tab
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
yield waitForTabLoaded(tab);
|
||||
|
||||
tab = gBrowser.addTab();
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", firstOnLoad, true);
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabClose", onTabClose, true);
|
||||
}
|
||||
|
||||
function firstOnLoad(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", firstOnLoad, true);
|
||||
|
||||
let uri = aEvent.target.location;
|
||||
is(uri, "about:blank", "first load should be for about:blank");
|
||||
|
||||
// Trigger a save state.
|
||||
// Trigger a save state, to initialize any caches
|
||||
ss.getBrowserState();
|
||||
|
||||
is(gBrowser.tabs[1], tab, "newly created tab should exist by now");
|
||||
ok(tab.linkedBrowser.__SS_data, "newly created tab should be in save state");
|
||||
|
||||
// Start a load and interrupt it by closing the tab
|
||||
tab.linkedBrowser.loadURI(URI_TO_LOAD);
|
||||
}
|
||||
let loaded = yield waitForLoadStarted(tab);
|
||||
ok(loaded, "Load started");
|
||||
|
||||
let tabsListener = {
|
||||
onLocationChange: function onLocationChange(aBrowser) {
|
||||
gBrowser.removeTabsProgressListener(tabsListener);
|
||||
|
||||
is(aBrowser.currentURI.spec, URI_TO_LOAD,
|
||||
"should occur after about:blank load and be loading next page");
|
||||
|
||||
// Since we are running in the context of tabs listeners, we do not
|
||||
// want to disrupt other tabs listeners.
|
||||
executeSoon(function() {
|
||||
let tabClosing = waitForTabClosed();
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
}
|
||||
};
|
||||
info("Now waiting for TabClose to close");
|
||||
yield tabClosing;
|
||||
|
||||
function onTabClose(aEvent) {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, true);
|
||||
|
||||
is(tab.linkedBrowser.currentURI.spec, URI_TO_LOAD,
|
||||
"should only remove when loading page");
|
||||
|
||||
executeSoon(function() {
|
||||
// Undo the tab, ensure that it proceeds with loading
|
||||
tab = ss.undoCloseTab(window, 0);
|
||||
tab.linkedBrowser.addEventListener("load", secondOnLoad, true);
|
||||
});
|
||||
}
|
||||
yield waitForTabLoaded(tab);
|
||||
is(tab.linkedBrowser.currentURI.spec, URI_TO_LOAD, "loading proceeded as expected");
|
||||
|
||||
function secondOnLoad(aEvent) {
|
||||
let uri = aEvent.target.location;
|
||||
is(uri, URI_TO_LOAD, "should load page from undoCloseTab");
|
||||
done();
|
||||
}
|
||||
|
||||
function done() {
|
||||
tab.linkedBrowser.removeEventListener("load", secondOnLoad, true);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
executeSoon(finish);
|
||||
} catch (ex) {
|
||||
ok(false, ex);
|
||||
info(ex.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -30,6 +30,11 @@ function runTests() {
|
||||
docShell.allowImages = false;
|
||||
docShell.allowMetaRedirects = false;
|
||||
|
||||
// Now reload the document to ensure that these capabilities
|
||||
// are taken into account
|
||||
browser.reload();
|
||||
yield whenBrowserLoaded(browser);
|
||||
|
||||
// Check that we correctly save disallowed features.
|
||||
let disallowedState = JSON.parse(ss.getTabState(tab));
|
||||
let disallow = new Set(disallowedState.disallow.split(","));
|
||||
@ -52,7 +57,7 @@ function runTests() {
|
||||
|
||||
// Check that docShell flags are set.
|
||||
ok(!docShell.allowImages, "images not allowed");
|
||||
ok(!docShell.allowMetaRedirects, "meta redirects not allowed")
|
||||
ok(!docShell.allowMetaRedirects, "meta redirects not allowed");
|
||||
|
||||
// Check that we correctly restored features as disabled.
|
||||
state = JSON.parse(ss.getTabState(tab));
|
||||
|
@ -0,0 +1,91 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let Scope = {};
|
||||
Cu.import("resource://gre/modules/Task.jsm", Scope);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", Scope);
|
||||
let {Task, Promise} = Scope;
|
||||
|
||||
function promiseBrowserLoaded(aBrowser) {
|
||||
let deferred = Promise.defer();
|
||||
whenBrowserLoaded(aBrowser, () => deferred.resolve());
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function forceWriteState() {
|
||||
let deferred = Promise.defer();
|
||||
const PREF = "browser.sessionstore.interval";
|
||||
const TOPIC = "sessionstore-state-write";
|
||||
|
||||
Services.obs.addObserver(function observe() {
|
||||
Services.obs.removeObserver(observe, TOPIC);
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
deferred.resolve();
|
||||
}, TOPIC, false);
|
||||
|
||||
Services.prefs.setIntPref(PREF, 0);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForStorageChange(aTab) {
|
||||
let deferred = Promise.defer();
|
||||
waitForContentMessage(aTab.linkedBrowser,
|
||||
"SessionStore:MozStorageChanged",
|
||||
1000,
|
||||
deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tab;
|
||||
Task.spawn(function() {
|
||||
try {
|
||||
tab = gBrowser.addTab("http://example.com");
|
||||
// about:home supports sessionStorage and localStorage
|
||||
|
||||
let win = tab.linkedBrowser.contentWindow;
|
||||
|
||||
// Flush loading and next save, call getBrowserState()
|
||||
// a few times to ensure that everything is cached.
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
yield forceWriteState();
|
||||
info("Calling getBrowserState() to populate cache");
|
||||
ss.getBrowserState();
|
||||
|
||||
info("Change sessionStorage, ensure that state is saved");
|
||||
win.sessionStorage["SESSION_STORAGE_KEY"] = "SESSION_STORAGE_VALUE";
|
||||
let storageChanged = yield waitForStorageChange(tab);
|
||||
ok(storageChanged, "Changing sessionStorage triggered the right message");
|
||||
yield forceWriteState();
|
||||
|
||||
let state = ss.getBrowserState();
|
||||
ok(state.indexOf("SESSION_STORAGE_KEY") != -1, "Key appears in state");
|
||||
ok(state.indexOf("SESSION_STORAGE_VALUE") != -1, "Value appears in state");
|
||||
|
||||
|
||||
info("Change localStorage, ensure that state is not saved");
|
||||
win.localStorage["LOCAL_STORAGE_KEY"] = "LOCAL_STORAGE_VALUE";
|
||||
storageChanged = yield waitForStorageChange(tab);
|
||||
ok(!storageChanged, "Changing localStorage did not trigger a message");
|
||||
yield forceWriteState();
|
||||
|
||||
state = ss.getBrowserState();
|
||||
ok(state.indexOf("LOCAL_STORAGE_KEY") == -1, "Key does not appear in state");
|
||||
ok(state.indexOf("LOCAL_STORAGE_VALUE") == -1, "Value does not appear in state");
|
||||
} catch (ex) {
|
||||
ok(false, ex);
|
||||
info(ex.stack);
|
||||
} finally {
|
||||
// clean up
|
||||
if (tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
|
||||
executeSoon(finish);
|
||||
}
|
||||
});
|
||||
}
|
@ -156,31 +156,28 @@ function waitForTabState(aTab, aState, aCallback) {
|
||||
ss.setTabState(aTab, JSON.stringify(aState));
|
||||
}
|
||||
|
||||
// waitForSaveState waits for a state write but not necessarily for the state to
|
||||
// turn dirty.
|
||||
function waitForSaveState(aSaveStateCallback) {
|
||||
/**
|
||||
* Wait for a content -> chrome message.
|
||||
*/
|
||||
function waitForContentMessage(aBrowser, aTopic, aTimeout, aCallback) {
|
||||
let mm = aBrowser.messageManager;
|
||||
let observing = false;
|
||||
let topic = "sessionstore-state-write";
|
||||
|
||||
let sessionSaveTimeout = 1000 +
|
||||
Services.prefs.getIntPref("browser.sessionstore.interval");
|
||||
|
||||
function removeObserver() {
|
||||
if (!observing)
|
||||
return;
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
mm.removeMessageListener(aTopic, observer);
|
||||
observing = false;
|
||||
}
|
||||
|
||||
let timeout = setTimeout(function () {
|
||||
removeObserver();
|
||||
aSaveStateCallback();
|
||||
}, sessionSaveTimeout);
|
||||
aCallback(false);
|
||||
}, aTimeout);
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
removeObserver();
|
||||
timeout = clearTimeout(timeout);
|
||||
executeSoon(aSaveStateCallback);
|
||||
executeSoon(() => aCallback(true));
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
@ -191,8 +188,58 @@ function waitForSaveState(aSaveStateCallback) {
|
||||
});
|
||||
|
||||
observing = true;
|
||||
Services.obs.addObserver(observer, topic, false);
|
||||
};
|
||||
mm.addMessageListener(aTopic, observer);
|
||||
}
|
||||
|
||||
function waitForTopic(aTopic, aTimeout, aCallback) {
|
||||
let observing = false;
|
||||
function removeObserver() {
|
||||
if (!observing)
|
||||
return;
|
||||
Services.obs.removeObserver(observer, aTopic);
|
||||
observing = false;
|
||||
}
|
||||
|
||||
let timeout = setTimeout(function () {
|
||||
removeObserver();
|
||||
aCallback(false);
|
||||
}, aTimeout);
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
removeObserver();
|
||||
timeout = clearTimeout(timeout);
|
||||
executeSoon(() => aCallback(true));
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeObserver();
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
});
|
||||
|
||||
observing = true;
|
||||
Services.obs.addObserver(observer, aTopic, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until session restore has finished collecting its data and is
|
||||
* getting ready to write that data ("sessionstore-state-write").
|
||||
*
|
||||
* This function is meant to be called immediately after the code
|
||||
* that will trigger the saving.
|
||||
*
|
||||
* Note that this does not wait for the disk write to be complete.
|
||||
*
|
||||
* @param {function} aCallback If sessionstore-state-write is sent
|
||||
* within buffering interval + 100 ms, the callback is passed |true|,
|
||||
* otherwise, it is passed |false|.
|
||||
*/
|
||||
function waitForSaveState(aCallback) {
|
||||
let timeout = 100 +
|
||||
Services.prefs.getIntPref("browser.sessionstore.interval");
|
||||
return waitForTopic("sessionstore-state-write", timeout, aCallback);
|
||||
}
|
||||
|
||||
function whenBrowserLoaded(aBrowser, aCallback = next) {
|
||||
aBrowser.addEventListener("load", function onLoad() {
|
||||
|
Loading…
Reference in New Issue
Block a user