mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 930967 - Add tests for broadcasting sessionstore data r=yoric,billm,smacleod
From 31c74a1bd1244404b5a98348b1b4ca4e3698afce Mon Sep 17 00:00:00 2001
This commit is contained in:
parent
c9ef718ff6
commit
0fdfb159bb
@ -10,13 +10,15 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
content.js
|
||||
browser_form_restore_events_sample.html
|
||||
browser_formdata_format_sample.html
|
||||
browser_input_sample.html
|
||||
browser_pageStyle_sample.html
|
||||
browser_pageStyle_sample_nested.html
|
||||
browser_248970_b_sample.html
|
||||
browser_339445_sample.html
|
||||
browser_346337_sample.html
|
||||
browser_408470_sample.html
|
||||
browser_423132_sample.html
|
||||
browser_447951_sample.html
|
||||
browser_454908_sample.html
|
||||
@ -47,6 +49,7 @@ support-files =
|
||||
#disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html
|
||||
|
||||
[browser_attributes.js]
|
||||
[browser_broadcast.js]
|
||||
[browser_capabilities.js]
|
||||
[browser_dying_cache.js]
|
||||
[browser_form_restore_events.js]
|
||||
@ -54,6 +57,7 @@ support-files =
|
||||
[browser_global_store.js]
|
||||
[browser_input.js]
|
||||
[browser_pageshow.js]
|
||||
[browser_pageStyle.js]
|
||||
[browser_sessionStorage.js]
|
||||
[browser_swapDocShells.js]
|
||||
[browser_tabStateCache.js]
|
||||
@ -74,7 +78,6 @@ skip-if = true
|
||||
[browser_394759_behavior.js]
|
||||
[browser_394759_perwindowpb.js]
|
||||
[browser_394759_purge.js]
|
||||
[browser_408470.js]
|
||||
[browser_423132.js]
|
||||
[browser_447951.js]
|
||||
[browser_448741.js]
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
||||
EventUtils.sendMouseEvent({type: "click"}, chk);
|
||||
|
||||
let browser = newWin.gBrowser.selectedBrowser;
|
||||
waitForContentMessage(browser, "SessionStore:input", 1000, result => {
|
||||
promiseContentMessage(browser, "SessionStore:input").then(result => {
|
||||
ok(result, "received message for input changes");
|
||||
|
||||
newWin.close();
|
||||
|
@ -1,56 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 408470 **/
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let pendingCount = 1;
|
||||
let rootDir = getRootDirectory(gTestPath);
|
||||
let testUrl = rootDir + "browser_408470_sample.html";
|
||||
let tab = gBrowser.addTab(testUrl);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// enable all stylesheets and verify that they're correctly persisted
|
||||
Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) {
|
||||
pendingCount++;
|
||||
let ssTitle = aSS.title;
|
||||
gPageStyleMenu.switchStyleSheet(ssTitle, tab.linkedBrowser.contentWindow);
|
||||
|
||||
let newTab = gBrowser.duplicateTab(tab);
|
||||
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets,
|
||||
function(aSS) !aSS.disabled);
|
||||
let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1;
|
||||
|
||||
if (/^fail_/.test(ssTitle))
|
||||
ok(!correct, "didn't restore stylesheet " + ssTitle);
|
||||
else
|
||||
ok(correct, "restored stylesheet " + ssTitle);
|
||||
|
||||
gBrowser.removeTab(newTab);
|
||||
if (--pendingCount == 0)
|
||||
finish();
|
||||
}, true);
|
||||
});
|
||||
|
||||
// disable all styles and verify that this is correctly persisted
|
||||
tab.linkedBrowser.markupDocumentViewer.authorStyleDisabled = true;
|
||||
let newTab = gBrowser.duplicateTab(tab);
|
||||
newTab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
newTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
is(newTab.linkedBrowser.markupDocumentViewer.authorStyleDisabled, true,
|
||||
"disabled all stylesheets");
|
||||
|
||||
gBrowser.removeTab(newTab);
|
||||
if (--pendingCount == 0)
|
||||
finish();
|
||||
}, true);
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
}, true);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for bug 408470</title>
|
||||
|
||||
<link href="404.css" title="default" rel="stylesheet">
|
||||
<link href="404.css" title="alternate" rel="alternate stylesheet">
|
||||
<link href="404.css" title="altERnate" rel=" styLEsheet altERnate ">
|
||||
<link href="404.css" title="media_empty" rel="alternate stylesheet" media="">
|
||||
<link href="404.css" title="media_all" rel="alternate stylesheet" media="all">
|
||||
<link href="404.css" title="media_ALL" rel="alternate stylesheet" media=" ALL ">
|
||||
<link href="404.css" title="media_screen" rel="alternate stylesheet" media="screen">
|
||||
<link href="404.css" title="media_print_screen" rel="alternate stylesheet" media="print,screen">
|
||||
<link href="404.css" title="fail_media_print" rel="alternate stylesheet" media="print">
|
||||
<link href="404.css" title="fail_media_projection" rel="stylesheet" media="projection">
|
||||
<link href="404.css" title="fail_media_invalid" rel="alternate stylesheet" media="hallo">
|
||||
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
@ -21,12 +21,7 @@ let {Task, Promise} = Scope;
|
||||
const URI_TO_LOAD = "about:mozilla";
|
||||
|
||||
function waitForLoadStarted(aTab) {
|
||||
let deferred = Promise.defer();
|
||||
waitForContentMessage(aTab.linkedBrowser,
|
||||
"SessionStore:loadStart",
|
||||
1000,
|
||||
deferred.resolve);
|
||||
return deferred.promise;
|
||||
return promiseContentMessage(aTab.linkedBrowser, "SessionStore:loadStart");
|
||||
}
|
||||
|
||||
function waitForTabLoaded(aTab) {
|
||||
|
@ -1,6 +1,10 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let tmp;
|
||||
Cu.import("resource:///modules/sessionstore/TabStateCache.jsm", tmp);
|
||||
let {TabStateCache} = tmp;
|
||||
|
||||
const URL = "http://mochi.test:8888/browser/" +
|
||||
"browser/components/sessionstore/test/browser_916390_sample.html";
|
||||
|
||||
@ -24,11 +28,9 @@ function runTests() {
|
||||
let {formdata} = state.windows[0].tabs[1].entries[0];
|
||||
is(formdata.id.txt, "m", "txt's value is correct");
|
||||
|
||||
// Change the number of session history entries and modify
|
||||
// DOMSessionStorage data to invalidate the TabStateCache.
|
||||
// Change the number of session history entries to invalidate the cache.
|
||||
browser.loadURI(URL + "#");
|
||||
browser.contentWindow.sessionStorage.foo = "bar";
|
||||
yield waitForStorageChange();
|
||||
TabStateCache.delete(browser);
|
||||
|
||||
// Check that we'll save the form data state correctly.
|
||||
let state = JSON.parse(ss.getBrowserState());
|
||||
|
196
browser/components/sessionstore/test/browser_broadcast.js
Normal file
196
browser/components/sessionstore/test/browser_broadcast.js
Normal file
@ -0,0 +1,196 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const INITIAL_VALUE = "initial-value-" + Date.now();
|
||||
|
||||
/**
|
||||
* This test ensures we won't lose tab data queued in the content script when
|
||||
* closing a tab.
|
||||
*/
|
||||
add_task(function flush_on_tabclose() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield modifySessionStorage(browser, {test: "on-tab-close"});
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(storage["http://example.com"].test, "on-tab-close",
|
||||
"sessionStorage data has been flushed on TabClose");
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures we won't lose tab data queued in the content script when
|
||||
* the application tries to quit.
|
||||
*/
|
||||
add_task(function flush_on_quit_requested() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield modifySessionStorage(browser, {test: "on-quit-requested"});
|
||||
|
||||
// Note that sending quit-application-requested should not interfere with
|
||||
// other tests and code. We're just notifying about a shutdown request but
|
||||
// we will not send quit-application-granted. Observers will thus assume
|
||||
// that some other observer has canceled the request.
|
||||
sendQuitApplicationRequested();
|
||||
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
is(storage["http://example.com"].test, "on-quit-requested",
|
||||
"sessionStorage data has been flushed when a quit is requested");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures we won't lose tab data queued in the content script when
|
||||
* duplicating a tab.
|
||||
*/
|
||||
add_task(function flush_on_duplicate() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield modifySessionStorage(browser, {test: "on-duplicate"});
|
||||
let tab2 = ss.duplicateTab(window, tab);
|
||||
let {storage} = JSON.parse(ss.getTabState(tab2));
|
||||
is(storage["http://example.com"].test, "on-duplicate",
|
||||
"sessionStorage data has been flushed when duplicating tabs");
|
||||
|
||||
yield promiseTabRestored(tab2);
|
||||
let {storage} = JSON.parse(ss.getTabState(tab2));
|
||||
is(storage["http://example.com"].test, "on-duplicate",
|
||||
"sessionStorage data has been flushed when duplicating tabs");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTab(tab2);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures we won't lose tab data queued in the content script when
|
||||
* a window is closed.
|
||||
*/
|
||||
add_task(function flush_on_windowclose() {
|
||||
let win = yield promiseNewWindow();
|
||||
let tab = yield createTabWithStorageData(["http://example.com"], win);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield modifySessionStorage(browser, {test: "on-window-close"});
|
||||
yield closeWindow(win);
|
||||
|
||||
let [{tabs: [_, {storage}]}] = JSON.parse(ss.getClosedWindowData());
|
||||
is(storage["http://example.com"].test, "on-window-close",
|
||||
"sessionStorage data has been flushed when closing a window");
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that stale tab data is ignored when reusing a tab
|
||||
* (via e.g. setTabState) and does not overwrite the new data.
|
||||
*/
|
||||
add_task(function flush_on_settabstate() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// Flush to make sure our tab state is up-to-date.
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
let state = ss.getTabState(tab);
|
||||
yield modifySessionStorage(browser, {test: "on-set-tab-state"});
|
||||
|
||||
// Flush all data contained in the content script but send it using
|
||||
// asynchronous messages.
|
||||
SyncHandlers.get(browser).flushAsync();
|
||||
|
||||
ss.setTabState(tab, state);
|
||||
yield promiseTabRestored(tab);
|
||||
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data has not been overwritten");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that we won't lose tab data that has been sent
|
||||
* asynchronously just before closing a tab. Flushing must re-send all data
|
||||
* that hasn't been received by chrome, yet.
|
||||
*/
|
||||
add_task(function flush_on_tabclose_racy() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// Flush to make sure we start with an empty queue.
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
yield modifySessionStorage(browser, {test: "on-tab-close-racy"});
|
||||
|
||||
// Flush all data contained in the content script but send it using
|
||||
// asynchronous messages.
|
||||
SyncHandlers.get(browser).flushAsync();
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(storage["http://example.com"].test, "on-tab-close-racy",
|
||||
"sessionStorage data has been merged correctly to prevent data loss");
|
||||
});
|
||||
|
||||
function promiseNewWindow() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
whenNewWindowLoaded({private: false}, function (win) {
|
||||
win.messageManager.loadFrameScript(FRAME_SCRIPT, true);
|
||||
deferred.resolve(win);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function closeWindow(win) {
|
||||
let deferred = Promise.defer();
|
||||
let outerID = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
|
||||
Services.obs.addObserver(function obs(subject, topic) {
|
||||
let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (id == outerID) {
|
||||
Services.obs.removeObserver(obs, topic);
|
||||
deferred.resolve();
|
||||
}
|
||||
}, "outer-window-destroyed", false);
|
||||
|
||||
win.close();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function createTabWithStorageData(urls, win = window) {
|
||||
return Task.spawn(function task() {
|
||||
let tab = win.gBrowser.addTab();
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
for (let url of urls) {
|
||||
browser.loadURI(url);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield modifySessionStorage(browser, {test: INITIAL_VALUE});
|
||||
}
|
||||
|
||||
throw new Task.Result(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForStorageEvent(browser) {
|
||||
return promiseContentMessage(browser, "ss-test:MozStorageChanged");
|
||||
}
|
||||
|
||||
function sendQuitApplicationRequested() {
|
||||
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
|
||||
}
|
||||
|
||||
function modifySessionStorage(browser, data) {
|
||||
browser.messageManager.sendAsyncMessage("ss-test:modifySessionStorage", data);
|
||||
return waitForStorageEvent(browser);
|
||||
}
|
@ -1,22 +1,17 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
TestRunner.run();
|
||||
}
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This test ensures that disabling features by flipping nsIDocShell.allow*
|
||||
* These tests ensures that disabling features by flipping nsIDocShell.allow*
|
||||
* properties are (re)stored as disabled. Disallowed features must be
|
||||
* re-enabled when the tab is re-used by another tab restoration.
|
||||
*/
|
||||
|
||||
function runTests() {
|
||||
// Create a tab that we're going to use for our tests.
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
|
||||
add_task(function docshell_capabilities() {
|
||||
let tab = yield createTab();
|
||||
let browser = tab.linkedBrowser;
|
||||
let docShell = browser.docShell;
|
||||
yield waitForLoad(browser);
|
||||
|
||||
// Get the list of capabilities for docShells.
|
||||
let flags = Object.keys(docShell).filter(k => k.startsWith("allow"));
|
||||
@ -31,9 +26,12 @@ function runTests() {
|
||||
docShell.allowMetaRedirects = false;
|
||||
|
||||
// Now reload the document to ensure that these capabilities
|
||||
// are taken into account
|
||||
// are taken into account.
|
||||
browser.reload();
|
||||
yield whenBrowserLoaded(browser);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
// Flush to make sure chrome received all data.
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
// Check that we correctly save disallowed features.
|
||||
let disallowedState = JSON.parse(ss.getTabState(tab));
|
||||
@ -44,7 +42,10 @@ function runTests() {
|
||||
|
||||
// Reuse the tab to restore a new, clean state into it.
|
||||
ss.setTabState(tab, JSON.stringify({ entries: [{url: "about:robots"}] }));
|
||||
yield waitForLoad(browser);
|
||||
yield promiseTabRestored(tab);
|
||||
|
||||
// Flush to make sure chrome received all data.
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
// After restoring disallowed features must be available again.
|
||||
state = JSON.parse(ss.getTabState(tab));
|
||||
@ -53,7 +54,7 @@ function runTests() {
|
||||
|
||||
// Restore the state with disallowed features.
|
||||
ss.setTabState(tab, JSON.stringify(disallowedState));
|
||||
yield waitForLoad(browser);
|
||||
yield promiseTabRestored(tab);
|
||||
|
||||
// Check that docShell flags are set.
|
||||
ok(!docShell.allowImages, "images not allowed");
|
||||
@ -68,11 +69,10 @@ function runTests() {
|
||||
|
||||
// Clean up after ourselves.
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
});
|
||||
|
||||
function waitForLoad(aElement) {
|
||||
aElement.addEventListener("load", function onLoad() {
|
||||
aElement.removeEventListener("load", onLoad, true);
|
||||
executeSoon(next);
|
||||
}, true);
|
||||
function createTab() {
|
||||
let tab = gBrowser.addTab("about:mozilla");
|
||||
let browser = tab.linkedBrowser;
|
||||
return promiseBrowserLoaded(browser).then(() => tab);
|
||||
}
|
||||
|
88
browser/components/sessionstore/test/browser_pageStyle.js
Normal file
88
browser/components/sessionstore/test/browser_pageStyle.js
Normal file
@ -0,0 +1,88 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const URL = getRootDirectory(gTestPath) + "browser_pageStyle_sample.html";
|
||||
const URL_NESTED = getRootDirectory(gTestPath) + "browser_pageStyle_sample_nested.html";
|
||||
|
||||
/**
|
||||
* This test ensures that page style information is correctly persisted.
|
||||
*/
|
||||
add_task(function page_style() {
|
||||
let tab = gBrowser.addTab(URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
yield promiseBrowserLoaded(browser);
|
||||
let sheets = yield getStyleSheets(browser);
|
||||
|
||||
// Enable all style sheets one by one.
|
||||
for (let [title, disabled] of sheets) {
|
||||
yield enableStyleSheetsForSet(browser, title);
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
yield promiseTabRestored(tab2);
|
||||
|
||||
let sheets = yield getStyleSheets(tab2.linkedBrowser);
|
||||
let enabled = sheets.filter(([title, disabled]) => !disabled);
|
||||
|
||||
if (title.startsWith("fail_")) {
|
||||
ok(!enabled.length, "didn't restore " + title);
|
||||
} else {
|
||||
ok(enabled.length == 1 && enabled[0][0] == title, "restored " + title);
|
||||
}
|
||||
|
||||
gBrowser.removeTab(tab2);
|
||||
}
|
||||
|
||||
// Disable all styles and verify that this is correctly persisted.
|
||||
yield setAuthorStyleDisabled(browser, true);
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
yield promiseTabRestored(tab2);
|
||||
|
||||
let authorStyleDisabled = yield getAuthorStyleDisabled(tab2.linkedBrowser);
|
||||
ok(authorStyleDisabled, "disabled all stylesheets");
|
||||
|
||||
// Clean up.
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTab(tab2);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that page style notification from nested documents are
|
||||
* received and the page style is persisted correctly.
|
||||
*/
|
||||
add_task(function nested_page_style() {
|
||||
let tab = gBrowser.addTab(URL_NESTED);
|
||||
let browser = tab.linkedBrowser;
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
yield enableSubDocumentStyleSheetsForSet(browser, "alternate");
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let [{state: {pageStyle}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(pageStyle, "alternate", "correct pageStyle persisted");
|
||||
});
|
||||
|
||||
function getStyleSheets(browser) {
|
||||
return sendMessage(browser, "ss-test:getStyleSheets").then(({data}) => data);
|
||||
}
|
||||
|
||||
function enableStyleSheetsForSet(browser, name) {
|
||||
return sendMessage(browser, "ss-test:enableStyleSheetsForSet", name);
|
||||
}
|
||||
|
||||
function enableSubDocumentStyleSheetsForSet(browser, name) {
|
||||
return sendMessage(browser, "ss-test:enableSubDocumentStyleSheetsForSet", {
|
||||
id: "iframe", set: name
|
||||
});
|
||||
}
|
||||
|
||||
function getAuthorStyleDisabled(browser) {
|
||||
return sendMessage(browser, "ss-test:getAuthorStyleDisabled")
|
||||
.then(({data}) => data);
|
||||
}
|
||||
|
||||
function setAuthorStyleDisabled(browser, val) {
|
||||
return sendMessage(browser, "ss-test:setAuthorStyleDisabled", val)
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>pageStyle sample</title>
|
||||
|
||||
<link href="404.css" title="default" rel="stylesheet">
|
||||
<link href="404.css" title="alternate" rel="alternate stylesheet">
|
||||
<link href="404.css" title="altERnate" rel=" styLEsheet altERnate ">
|
||||
<link href="404.css" title="media_empty" rel="alternate stylesheet" media="">
|
||||
<link href="404.css" title="media_all" rel="alternate stylesheet" media="all">
|
||||
<link href="404.css" title="media_ALL" rel="alternate stylesheet" media=" ALL ">
|
||||
<link href="404.css" title="media_screen" rel="alternate stylesheet" media="screen">
|
||||
<link href="404.css" title="media_print_screen" rel="alternate stylesheet" media="print,screen">
|
||||
<link href="404.css" title="fail_media_print" rel="alternate stylesheet" media="print">
|
||||
<link href="404.css" title="fail_media_projection" rel="stylesheet" media="projection">
|
||||
<link href="404.css" title="fail_media_invalid" rel="alternate stylesheet" media="hallo">
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>pageStyle sample (nested)</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="iframe" src="browser_pageStyle_sample.html"/>
|
||||
</body>
|
||||
</html>
|
@ -1,78 +1,194 @@
|
||||
/* 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/. */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let Scope = {};
|
||||
Cu.import("resource://gre/modules/Task.jsm", Scope);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", Scope);
|
||||
let {Task, Promise} = Scope;
|
||||
"use strict";
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/Promise.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/ForgetAboutSite.jsm", tmp);
|
||||
let {Promise, ForgetAboutSite} = tmp;
|
||||
|
||||
function waitForStorageChange(aTab) {
|
||||
let deferred = Promise.defer();
|
||||
waitForContentMessage(aTab.linkedBrowser,
|
||||
"SessionStore:MozStorageChanged",
|
||||
1000,
|
||||
deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
const INITIAL_VALUE = "initial-value-" + Date.now();
|
||||
|
||||
function test() {
|
||||
/**
|
||||
* This test ensures that setting, modifying and restoring sessionStorage data
|
||||
* works as expected.
|
||||
*/
|
||||
add_task(function session_storage() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "http://mochi.test:8888"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
waitForExplicitFinish();
|
||||
// Flush to make sure chrome received all data.
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
let tab;
|
||||
Task.spawn(function() {
|
||||
try {
|
||||
let SESSION_STORAGE_KEY = "SESSION_STORAGE_KEY " + Math.random();
|
||||
let SESSION_STORAGE_VALUE = "SESSION_STORAGE_VALUE " + Math.random();
|
||||
let LOCAL_STORAGE_KEY = "LOCAL_STORAGE_KEY " + Math.random();
|
||||
let LOCAL_STORAGE_VALUE = "LOCAL_STORAGE_VALUE " + Math.random();
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for example.com has been serialized correctly");
|
||||
is(storage["http://mochi.test:8888"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for mochi.test has been serialized correctly");
|
||||
|
||||
tab = gBrowser.addTab("http://example.com");
|
||||
// about:home supports sessionStorage and localStorage
|
||||
// Ensure that modifying sessionStore values works.
|
||||
yield modifySessionStorage(browser, {test: "modified"});
|
||||
SyncHandlers.get(browser).flush();
|
||||
|
||||
let win = tab.linkedBrowser.contentWindow;
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for example.com has been serialized correctly");
|
||||
is(storage["http://mochi.test:8888"].test, "modified",
|
||||
"sessionStorage data for mochi.test has been serialized correctly");
|
||||
|
||||
// Flush loading and next save, call getBrowserState()
|
||||
// a few times to ensure that everything is cached.
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
yield forceSaveState();
|
||||
info("Calling getBrowserState() to populate cache");
|
||||
ss.getBrowserState();
|
||||
// Test that duplicating a tab works.
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
let browser2 = tab2.linkedBrowser;
|
||||
yield promiseTabRestored(tab2);
|
||||
|
||||
info("Change sessionStorage, ensure that state is saved");
|
||||
let storageChangedPromise = waitForStorageChange(tab);
|
||||
win.sessionStorage[SESSION_STORAGE_KEY] = SESSION_STORAGE_VALUE;
|
||||
let storageChanged = yield storageChangedPromise;
|
||||
ok(storageChanged, "Changing sessionStorage triggered the right message");
|
||||
yield forceSaveState();
|
||||
// Flush to make sure chrome received all data.
|
||||
SyncHandlers.get(browser2).flush();
|
||||
|
||||
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");
|
||||
let {storage} = JSON.parse(ss.getTabState(tab2));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for example.com has been duplicated correctly");
|
||||
is(storage["http://mochi.test:8888"].test, "modified",
|
||||
"sessionStorage data for mochi.test has been duplicated correctly");
|
||||
|
||||
// Ensure that the content script retains restored data
|
||||
// (by e.g. duplicateTab) and send it along with new data.
|
||||
yield modifySessionStorage(browser2, {test: "modified2"});
|
||||
SyncHandlers.get(browser2).flush();
|
||||
|
||||
info("Change localStorage, ensure that state is not saved");
|
||||
storageChangedPromise = waitForStorageChange(tab);
|
||||
win.localStorage[LOCAL_STORAGE_KEY] = LOCAL_STORAGE_VALUE;
|
||||
storageChanged = yield storageChangedPromise;
|
||||
ok(!storageChanged, "Changing localStorage did not trigger a message");
|
||||
yield forceSaveState();
|
||||
let {storage} = JSON.parse(ss.getTabState(tab2));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for example.com has been duplicated correctly");
|
||||
is(storage["http://mochi.test:8888"].test, "modified2",
|
||||
"sessionStorage data for mochi.test has been duplicated correctly");
|
||||
|
||||
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);
|
||||
}
|
||||
// Clean up.
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTab(tab2);
|
||||
});
|
||||
|
||||
executeSoon(finish);
|
||||
/**
|
||||
* This test ensures that purging domain data also purges data from the
|
||||
* sessionStorage data collected for tabs.
|
||||
*/
|
||||
add_task(function purge_domain() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "http://mochi.test:8888"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
ForgetAboutSite.removeDataFromDomain("mochi.test");
|
||||
yield waitForUpdateMessage(browser);
|
||||
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
ok(!storage["http://mochi.test:8888"],
|
||||
"sessionStorage data for mochi.test has been purged");
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for example.com has been preserved");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that purging session history data also purges data from
|
||||
* sessionStorage data collected for tabs
|
||||
*/
|
||||
add_task(function purge_shistory() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "http://mochi.test:8888"]);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
yield notifyObservers(browser, "browser:purge-session-history");
|
||||
|
||||
let {storage} = JSON.parse(ss.getTabState(tab));
|
||||
ok(!storage["http://example.com"],
|
||||
"sessionStorage data for example.com has been purged");
|
||||
is(storage["http://mochi.test:8888"].test, INITIAL_VALUE,
|
||||
"sessionStorage data for mochi.test has been preserved");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that collecting sessionStorage data respects the privacy
|
||||
* levels as set by the user.
|
||||
*/
|
||||
add_task(function respect_privacy_level() {
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "https://example.com"]);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"http sessionStorage data has been saved");
|
||||
is(storage["https://example.com"].test, INITIAL_VALUE,
|
||||
"https sessionStorage data has been saved");
|
||||
|
||||
// Disable saving data for encrypted sites.
|
||||
Services.prefs.setIntPref("browser.sessionstore.privacy_level", 1);
|
||||
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "https://example.com"]);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"http sessionStorage data has been saved");
|
||||
ok(!storage["https://example.com"],
|
||||
"https sessionStorage data has *not* been saved");
|
||||
|
||||
// Disable saving data for any site.
|
||||
Services.prefs.setIntPref("browser.sessionstore.privacy_level", 2);
|
||||
|
||||
// Check that duplicating a tab copies all private data.
|
||||
let tab = yield createTabWithStorageData(["http://example.com", "https://example.com"]);
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
yield promiseBrowserLoaded(tab2.linkedBrowser);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
// With privacy_level=2 the |tab| shouldn't have any sessionStorage data.
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
ok(!storage["http://example.com"],
|
||||
"http sessionStorage data has *not* been saved");
|
||||
ok(!storage["https://example.com"],
|
||||
"https sessionStorage data has *not* been saved");
|
||||
|
||||
// Restore the default privacy level and close the duplicated tab.
|
||||
Services.prefs.clearUserPref("browser.sessionstore.privacy_level");
|
||||
gBrowser.removeTab(tab2);
|
||||
|
||||
// With privacy_level=0 the duplicated |tab2| should persist all data.
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
is(storage["http://example.com"].test, INITIAL_VALUE,
|
||||
"http sessionStorage data has been saved");
|
||||
is(storage["https://example.com"].test, INITIAL_VALUE,
|
||||
"https sessionStorage data has been saved");
|
||||
});
|
||||
|
||||
function createTabWithStorageData(urls) {
|
||||
return Task.spawn(function task() {
|
||||
let tab = gBrowser.addTab();
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
for (let url of urls) {
|
||||
browser.loadURI(url);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
yield modifySessionStorage(browser, {test: INITIAL_VALUE});
|
||||
}
|
||||
|
||||
throw new Task.Result(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForStorageEvent(browser) {
|
||||
return promiseContentMessage(browser, "ss-test:MozStorageChanged");
|
||||
}
|
||||
|
||||
function waitForUpdateMessage(browser) {
|
||||
return promiseContentMessage(browser, "SessionStore:update");
|
||||
}
|
||||
|
||||
function modifySessionStorage(browser, data) {
|
||||
browser.messageManager.sendAsyncMessage("ss-test:modifySessionStorage", data);
|
||||
return waitForStorageEvent(browser);
|
||||
}
|
||||
|
||||
function notifyObservers(browser, topic) {
|
||||
browser.messageManager.sendAsyncMessage("ss-test:notifyObservers", topic);
|
||||
return waitForUpdateMessage(browser);
|
||||
}
|
||||
|
52
browser/components/sessionstore/test/content.js
Normal file
52
browser/components/sessionstore/test/content.js
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This frame script is only loaded for sessionstore mochitests. It enables us
|
||||
* to modify and query docShell data when running with multiple processes.
|
||||
*/
|
||||
|
||||
addEventListener("MozStorageChanged", function () {
|
||||
sendSyncMessage("ss-test:MozStorageChanged");
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:modifySessionStorage", function (msg) {
|
||||
for (let key of Object.keys(msg.data)) {
|
||||
content.sessionStorage[key] = msg.data[key];
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:notifyObservers", function (msg) {
|
||||
Services.obs.notifyObservers(null, msg.data, "");
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:getStyleSheets", function (msg) {
|
||||
let sheets = content.document.styleSheets;
|
||||
let titles = Array.map(sheets, ss => [ss.title, ss.disabled]);
|
||||
sendSyncMessage("ss-test:getStyleSheets", titles);
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:enableStyleSheetsForSet", function (msg) {
|
||||
content.document.enableStyleSheetsForSet(msg.data);
|
||||
sendSyncMessage("ss-test:enableStyleSheetsForSet");
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:enableSubDocumentStyleSheetsForSet", function (msg) {
|
||||
let iframe = content.document.getElementById(msg.data.id);
|
||||
iframe.contentDocument.enableStyleSheetsForSet(msg.data.set);
|
||||
sendSyncMessage("ss-test:enableSubDocumentStyleSheetsForSet");
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:getAuthorStyleDisabled", function (msg) {
|
||||
let {authorStyleDisabled} =
|
||||
docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
sendSyncMessage("ss-test:getAuthorStyleDisabled", authorStyleDisabled);
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:setAuthorStyleDisabled", function (msg) {
|
||||
let markupDocumentViewer =
|
||||
docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
|
||||
markupDocumentViewer.authorStyleDisabled = msg.data;
|
||||
sendSyncMessage("ss-test:setAuthorStyleDisabled");
|
||||
});
|
@ -5,9 +5,33 @@
|
||||
const TAB_STATE_NEEDS_RESTORE = 1;
|
||||
const TAB_STATE_RESTORING = 2;
|
||||
|
||||
const FRAME_SCRIPT = "chrome://mochitests/content/browser/browser/components/" +
|
||||
"sessionstore/test/content.js";
|
||||
|
||||
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
mm.loadFrameScript(FRAME_SCRIPT, true);
|
||||
mm.addMessageListener("SessionStore:setupSyncHandler", onSetupSyncHandler);
|
||||
|
||||
/**
|
||||
* This keeps track of all SyncHandlers passed to chrome from frame scripts.
|
||||
* We need this to let tests communicate with frame scripts and cause (a)sync
|
||||
* flushes.
|
||||
*/
|
||||
let SyncHandlers = new WeakMap();
|
||||
function onSetupSyncHandler(msg) {
|
||||
SyncHandlers.set(msg.target, msg.objects.handler);
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
mm.removeDelayedFrameScript(FRAME_SCRIPT);
|
||||
mm.removeMessageListener("SessionStore:setupSyncHandler", onSetupSyncHandler);
|
||||
});
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/Promise.jsm", tmp);
|
||||
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
|
||||
let SessionStore = tmp.SessionStore;
|
||||
let {Promise, SessionStore} = tmp;
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
|
||||
@ -159,36 +183,32 @@ function waitForTabState(aTab, aState, aCallback) {
|
||||
/**
|
||||
* Wait for a content -> chrome message.
|
||||
*/
|
||||
function waitForContentMessage(aBrowser, aTopic, aTimeout, aCallback) {
|
||||
let mm = aBrowser.messageManager;
|
||||
let observing = false;
|
||||
function removeObserver() {
|
||||
if (!observing)
|
||||
return;
|
||||
mm.removeMessageListener(aTopic, observer);
|
||||
observing = false;
|
||||
function promiseContentMessage(browser, name, timeout = 1000) {
|
||||
let deferred = Promise.defer();
|
||||
let mm = browser.messageManager;
|
||||
|
||||
function removeListener() {
|
||||
mm.removeMessageListener(name, listener);
|
||||
}
|
||||
|
||||
let timeout = setTimeout(function () {
|
||||
removeObserver();
|
||||
aCallback(false);
|
||||
}, aTimeout);
|
||||
removeListener();
|
||||
deferred.resolve(false);
|
||||
}, timeout);
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
removeObserver();
|
||||
timeout = clearTimeout(timeout);
|
||||
executeSoon(() => aCallback(true));
|
||||
function listener(msg) {
|
||||
removeListener();
|
||||
clearTimeout(timeout);
|
||||
deferred.resolve(msg);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeObserver();
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
removeListener();
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
|
||||
observing = true;
|
||||
mm.addMessageListener(aTopic, observer);
|
||||
mm.addMessageListener(name, listener);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForTopic(aTopic, aTimeout, aCallback) {
|
||||
@ -456,3 +476,19 @@ let TestRunner = {
|
||||
function next() {
|
||||
TestRunner.next();
|
||||
}
|
||||
|
||||
function promiseTabRestored(tab) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
tab.addEventListener("SSTabRestored", function onRestored() {
|
||||
tab.removeEventListener("SSTabRestored", onRestored);
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function sendMessage(browser, name, data = {}) {
|
||||
browser.messageManager.sendAsyncMessage(name, data);
|
||||
return promiseContentMessage(browser, name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user