Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
<!-- Any copyright is dedicated to the Public Domain.
<!DOCTYPE HTML>
<html>
<head>
<title>Test browsingData.removeLocalStorage also removes sessionStorage</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="text/javascript">
"use strict";
add_task(async function setup() {
// make sure userContext is enabled.
return SpecialPowers.pushPrefEnv({
set: [["privacy.userContext.enabled", true]],
});
});
add_task(async function testLocalStorage() {
async function background() {
function waitForTabs() {
return new Promise(resolve => {
let tabs = {};
let listener = async (msg, { tab }) => {
if (msg !== "content-script-ready") {
return;
}
tabs[tab.url] = tab;
if (Object.keys(tabs).length == 3) {
browser.runtime.onMessage.removeListener(listener);
resolve(tabs);
}
};
browser.runtime.onMessage.addListener(listener);
});
}
function sendMessageToTabs(tabs, message) {
return Promise.all(
Object.values(tabs).map(tab => {
return browser.tabs.sendMessage(tab.id, message);
})
);
}
let tabs = await waitForTabs();
browser.test.assertRejects(
browser.browsingData.removeLocalStorage({ since: Date.now() }),
"Firefox does not support clearing localStorage with 'since'.",
"Expected error received when using unimplemented parameter 'since'."
);
await sendMessageToTabs(tabs, "resetSessionStorage");
await browser.browsingData.removeLocalStorage({
hostnames: ["example.com"],
});
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
await browser.browsingData.removeLocalStorage({});
await sendMessageToTabs(tabs, "checkSessionStorageCleared");
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
await browser.browsingData.remove({}, { localStorage: true });
await sendMessageToTabs(tabs, "checkSessionStorageCleared");
// Can only delete cookieStoreId with LSNG enabled.
if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) {
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
// Now passing only the cookieStoreId should clear all sessionStorage for that container
await browser.browsingData.removeLocalStorage({
cookieStoreId: "firefox-container-1",
});
if (!navigator.userAgent.includes("Android")) {
await browser.tabs.sendMessage(tabs["https://test1.example.com/"].id, "checkSessionStorageCleared");
}
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
// Happy path: Passing both hostname and cookieStoreId would clear the sessionStorage.
await browser.browsingData.removeLocalStorage({
cookieStoreId: "firefox-container-1",
hostnames: ["test1.example.com"],
});
if (!navigator.userAgent.includes("Android")) {
await browser.tabs.sendMessage(tabs["https://test1.example.com/"].id, "checkSessionStorageCleared");
}
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
// Hostname doesn't match, so nothing cleared.
await browser.browsingData.removeLocalStorage({
cookieStoreId: "firefox-container-1",
hostnames: ["example.net"],
});
await sendMessageToTabs(tabs, "checkSessionStorageSet");
await sendMessageToTabs(tabs, "resetSessionStorage");
await sendMessageToTabs(tabs, "checkSessionStorageSet");
// Deleting private browsing mode data is silently ignored.
await browser.browsingData.removeLocalStorage({
cookieStoreId: "firefox-private",
});
await sendMessageToTabs(tabs, "checkSessionStorageSet");
} else {
await browser.test.assertRejects(
browser.browsingData.removeLocalStorage({
cookieStoreId: "firefox-container-1",
}),
"Firefox does not support clearing localStorage with 'cookieStoreId'.",
"removeLocalStorage with cookieStoreId requires LSNG"
);
}
await browser.browsingData.removeLocalStorage({});
browser.test.notifyPass("done");
}
function contentScript() {
browser.runtime.onMessage.addListener(async msg => {
if (msg === "resetSessionStorage") {
sessionStorage.clear();
sessionStorage.setItem("key", "value");
} else if (msg === "checkSessionStorageSet") {
browser.test.assertEq(
"value",
sessionStorage.getItem("key"),
`checkSessionStorageSet: ${location.href}`
);
} else if (msg === "checkSessionStorageCleared") {
browser.test.assertEq(
null,
sessionStorage.getItem("key"),
`checkSessionStorageCleared: ${location.href}`
);
}
});
browser.runtime.sendMessage("content-script-ready");
}
// This extension is responsible for opening tabs with a specified
// cookieStoreId, we use a separate extension to make sure that browsingData
// works without the cookies permission.
let openTabsExtension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
manifest: {
name: "Open tabs",
browser_specific_settings: { gecko: { id: "open-tabs@tests.mozilla.org" }, },
permissions: ["cookies"],
},
async background() {
const TABS = [
{
cookieStoreId: 'firefox-container-1',
},
];
function awaitLoad(tabId) {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(tabId_, changed) {
if (tabId == tabId_ && changed.status == "complete") {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
}
let tabs = [];
let loaded = [];
for (let options of TABS) {
let tab = await browser.tabs.create(options);
loaded.push(awaitLoad(tab.id));
tabs.push(tab);
}
await Promise.all(loaded);
browser.test.onMessage.addListener(async msg => {
if (msg === "cleanup") {
const tabIds = tabs.map(tab => tab.id);
let removedTabs = 0;
browser.tabs.onRemoved.addListener(tabId => {
browser.test.log(`Removing tab ${tabId}.`);
if (tabIds.includes(tabId)) {
removedTabs++;
if (removedTabs == tabIds.length) {
browser.test.sendMessage("done");
}
}
});
await browser.tabs.remove(tabIds);
}
});
}
});
let extension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
background,
manifest: {
name: "Test Extension",
browser_specific_settings: { gecko: { id: "localStorage@tests.mozilla.org" } },
permissions: ["browsingData", "tabs"],
content_scripts: [
{
matches: [
],
js: ["content-script.js"],
run_at: "document_end",
},
],
},
files: {
"content-script.js": contentScript,
},
});
await openTabsExtension.startup();
await extension.startup();
await extension.awaitFinish("done");
await extension.unload();
await openTabsExtension.sendMessage("cleanup");
await openTabsExtension.awaitMessage("done");
await openTabsExtension.unload();
});
</script>
</body>
</html>