Bug 867143 - sessionStorage/localStorage tests. r=ttaubert

This commit is contained in:
David Rajchenbach-Teller 2013-07-19 10:32:52 -04:00
parent fc122275c0
commit c6c561735c
3 changed files with 151 additions and 14 deletions

View File

@ -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 \

View File

@ -0,0 +1,89 @@
/* 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",
200,
((x) => deferred.resolve(x)));
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";
yield waitForStorageChange(tab);
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";
yield waitForStorageChange(tab);
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);
}
});
}

View File

@ -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() {