Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
"use strict";
const RAND = Math.random();
const URL =
"browser/components/sessionstore/test/browser_sessionStorage.html" +
"?" +
RAND;
const HAS_FIRST_PARTY_DOMAIN = [
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
].includes(Services.prefs.getIntPref("network.cookie.cookieBehavior"));
const OUTER_ORIGIN = "http://mochi.test:8888";
const FIRST_PARTY_DOMAIN = escape("(http,mochi.test)");
const INNER_ORIGIN = HAS_FIRST_PARTY_DOMAIN
? `http://example.com^partitionKey=${FIRST_PARTY_DOMAIN}`
const SECURE_INNER_ORIGIN = HAS_FIRST_PARTY_DOMAIN
? `https://example.com^partitionKey=${FIRST_PARTY_DOMAIN}`
const OUTER_VALUE = "outer-value-" + RAND;
const INNER_VALUE = "inner-value-" + RAND;
/**
* This test ensures that setting, modifying and restoring sessionStorage data
* works as expected.
*/
add_task(async function session_storage() {
let tab = BrowserTestUtils.addTab(gBrowser, URL);
let browser = tab.linkedBrowser;
await promiseBrowserLoaded(browser);
// Flush to make sure chrome received all data.
await TabStateFlusher.flush(browser);
let { storage } = JSON.parse(ss.getTabState(tab));
is(
storage[INNER_ORIGIN].test,
INNER_VALUE,
"sessionStorage data for example.com has been serialized correctly"
);
is(
storage[OUTER_ORIGIN].test,
OUTER_VALUE,
"sessionStorage data for mochi.test has been serialized correctly"
);
// Ensure that modifying sessionStore values works for the inner frame only.
await modifySessionStorage(browser, { test: "modified1" }, { frameIndex: 0 });
await TabStateFlusher.flush(browser);
({ storage } = JSON.parse(ss.getTabState(tab)));
is(
storage[INNER_ORIGIN].test,
"modified1",
"sessionStorage data for example.com has been serialized correctly"
);
is(
storage[OUTER_ORIGIN].test,
OUTER_VALUE,
"sessionStorage data for mochi.test has been serialized correctly"
);
// Ensure that modifying sessionStore values works for both frames.
await modifySessionStorage(browser, { test: "modified" });
await modifySessionStorage(browser, { test: "modified2" }, { frameIndex: 0 });
await TabStateFlusher.flush(browser);
({ storage } = JSON.parse(ss.getTabState(tab)));
is(
storage[INNER_ORIGIN].test,
"modified2",
"sessionStorage data for example.com has been serialized correctly"
);
is(
storage[OUTER_ORIGIN].test,
"modified",
"sessionStorage data for mochi.test has been serialized correctly"
);
// Test that duplicating a tab works.
let tab2 = gBrowser.duplicateTab(tab);
let browser2 = tab2.linkedBrowser;
await promiseTabRestored(tab2);
// Flush to make sure chrome received all data.
await TabStateFlusher.flush(browser2);
({ storage } = JSON.parse(ss.getTabState(tab2)));
is(
storage[INNER_ORIGIN].test,
"modified2",
"sessionStorage data for example.com has been duplicated correctly"
);
is(
storage[OUTER_ORIGIN].test,
"modified",
"sessionStorage data for mochi.test has been duplicated correctly"
);
// Ensure that the content script retains restored data
// (by e.g. duplicateTab) and sends it along with new data.
await modifySessionStorage(browser2, { test: "modified3" });
await TabStateFlusher.flush(browser2);
({ storage } = JSON.parse(ss.getTabState(tab2)));
is(
storage[INNER_ORIGIN].test,
"modified2",
"sessionStorage data for example.com has been duplicated correctly"
);
is(
storage[OUTER_ORIGIN].test,
"modified3",
"sessionStorage data for mochi.test has been duplicated correctly"
);
// Check that loading a new URL discards data.
BrowserTestUtils.startLoadingURIString(browser2, "http://mochi.test:8888/");
await promiseBrowserLoaded(browser2);
await TabStateFlusher.flush(browser2);
({ storage } = JSON.parse(ss.getTabState(tab2)));
is(
storage[OUTER_ORIGIN].test,
"modified3",
"navigating retains correct storage data"
);
is(
storage[INNER_ORIGIN].test,
"modified2",
"sessionStorage data for example.com wasn't discarded after top-level same-site navigation"
);
// Test that clearing the data in the first tab works properly within
// the subframe
await modifySessionStorage(browser, {}, { frameIndex: 0 });
await TabStateFlusher.flush(browser);
({ storage } = JSON.parse(ss.getTabState(tab)));
is(
storage[INNER_ORIGIN],
undefined,
"sessionStorage data for example.com has been cleared correctly"
);
// Test that clearing the data in the first tab works properly within
// the top-level frame
await modifySessionStorage(browser, {});
await TabStateFlusher.flush(browser);
({ storage } = JSON.parse(ss.getTabState(tab)));
ok(
storage === null || storage === undefined,
"sessionStorage data for the entire tab has been cleared correctly"
);
// Clean up.
BrowserTestUtils.removeTab(tab);
BrowserTestUtils.removeTab(tab2);
});
/**
* This test ensures that purging domain data also purges data from the
* sessionStorage data collected for tabs.
*/
add_task(async function purge_domain() {
let tab = BrowserTestUtils.addTab(gBrowser, URL);
let browser = tab.linkedBrowser;
await promiseBrowserLoaded(browser);
// Purge data for "mochi.test".
await purgeDomainData(browser, "mochi.test");
// Flush to make sure chrome received all data.
await TabStateFlusher.flush(browser);
let { storage } = JSON.parse(ss.getTabState(tab));
ok(
!storage[OUTER_ORIGIN],
"sessionStorage data for mochi.test has been purged"
);
is(
storage[INNER_ORIGIN].test,
INNER_VALUE,
"sessionStorage data for example.com has been preserved"
);
BrowserTestUtils.removeTab(tab);
});
/**
* This test ensures that collecting sessionStorage data respects the privacy
* levels as set by the user.
*/
add_task(async function respect_privacy_level() {
let tab = BrowserTestUtils.addTab(gBrowser, URL + "&secure");
await promiseBrowserLoaded(tab.linkedBrowser);
await TabStateFlusher.flush(tab.linkedBrowser);
await promiseRemoveTabAndSessionState(tab);
let [
{
state: { storage },
},
] = ss.getClosedTabDataForWindow(window);
is(
storage[OUTER_ORIGIN].test,
OUTER_VALUE,
"http sessionStorage data has been saved"
);
is(
storage[SECURE_INNER_ORIGIN].test,
INNER_VALUE,
"https sessionStorage data has been saved"
);
// Disable saving data for encrypted sites.
Services.prefs.setIntPref("browser.sessionstore.privacy_level", 1);
tab = BrowserTestUtils.addTab(gBrowser, URL + "&secure");
await promiseBrowserLoaded(tab.linkedBrowser);
await TabStateFlusher.flush(tab.linkedBrowser);
await promiseRemoveTabAndSessionState(tab);
[
{
state: { storage },
},
] = ss.getClosedTabDataForWindow(window);
is(
storage[OUTER_ORIGIN].test,
OUTER_VALUE,
"http sessionStorage data has been saved"
);
ok(
!storage[SECURE_INNER_ORIGIN],
"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.
tab = BrowserTestUtils.addTab(gBrowser, URL + "&secure");
await promiseBrowserLoaded(tab.linkedBrowser);
let tab2 = gBrowser.duplicateTab(tab);
await promiseTabRestored(tab2);
await promiseRemoveTabAndSessionState(tab);
// With privacy_level=2 the |tab| shouldn't have any sessionStorage data.
[
{
state: { storage },
},
] = ss.getClosedTabDataForWindow(window);
ok(!storage, "sessionStorage data has *not* been saved");
// Remove all closed tabs before continuing with the next test.
// As Date.now() isn't monotonic we might sometimes check
// the wrong closedTabData entry.
forgetClosedTabs(window);
// Restore the default privacy level and close the duplicated tab.
Services.prefs.clearUserPref("browser.sessionstore.privacy_level");
await promiseRemoveTabAndSessionState(tab2);
// With privacy_level=0 the duplicated |tab2| should persist all data.
[
{
state: { storage },
},
] = ss.getClosedTabDataForWindow(window);
is(
storage[OUTER_ORIGIN].test,
OUTER_VALUE,
"http sessionStorage data has been saved"
);
is(
storage[SECURE_INNER_ORIGIN].test,
INNER_VALUE,
"https sessionStorage data has been saved"
);
});
function purgeDomainData(browser, domain) {
return new Promise(resolve => {
Services.clearData.deleteDataFromHost(
domain,
true,
Services.clearData.CLEAR_SESSION_HISTORY,
resolve
);
});
}