Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
/* eslint-disable mozilla/no-arbitrary-setTimeout */
/**
* This test makes sure the when we grant the storage permission, the
* permission is also propagated to iframes within the same agent cluster,
* but not to iframes in the other tabs.
*/
async function createTab(topUrl, iframeCount, opener, params) {
let newTab;
let browser;
if (opener) {
let promise = BrowserTestUtils.waitForNewTab(gBrowser, topUrl);
await SpecialPowers.spawn(opener, [topUrl], function (url) {
content.window.open(url, "_blank");
});
newTab = await promise;
browser = gBrowser.getBrowserForTab(newTab);
} else {
newTab = BrowserTestUtils.addTab(gBrowser, topUrl);
browser = gBrowser.getBrowserForTab(newTab);
await BrowserTestUtils.browserLoaded(browser);
}
await SpecialPowers.spawn(
browser,
[params, iframeCount, createTrackerFrame.toString()],
async function (params, count, fn) {
// eslint-disable-next-line no-eval
let fnCreateTrackerFrame = eval(`(() => (${fn}))()`);
await fnCreateTrackerFrame(params, count, ifr => {
ifr.contentWindow.postMessage(
{ callback: params.msg.blockingCallback },
"*"
);
});
}
);
return Promise.resolve(newTab);
}
async function createTrackerFrame(params, count, callback) {
let iframes = [];
for (var i = 0; i < count; i++) {
iframes[i] = content.document.createElement("iframe");
await new content.Promise(resolve => {
iframes[i].id = "ifr" + i;
iframes[i].src = params.page;
iframes[i].onload = resolve;
content.document.body.appendChild(iframes[i]);
});
await new content.Promise(resolve => {
content.addEventListener("message", function msg(event) {
if (event.data.type == "finish") {
content.removeEventListener("message", msg);
resolve();
return;
}
if (event.data.type == "ok") {
ok(event.data.what, event.data.msg);
return;
}
if (event.data.type == "info") {
info(event.data.msg);
return;
}
ok(false, "Unknown message");
});
callback(iframes[i]);
});
}
}
async function testPermission(browser, block, params, frameNumber) {
await SpecialPowers.spawn(
browser,
[block, params, frameNumber],
async function (block, params, frameNumber) {
for (let i = 0; ; i++) {
let ifr = content.document.getElementById("ifr" + i);
if (!ifr || (frameNumber !== undefined && i != frameNumber)) {
break;
}
await new content.Promise(resolve => {
content.addEventListener("message", function msg(event) {
if (event.data.type == "finish") {
content.removeEventListener("message", msg);
resolve();
return;
}
if (event.data.type == "ok") {
ok(event.data.what, event.data.msg);
return;
}
if (event.data.type == "info") {
info(event.data.msg);
return;
}
ok(false, "Unknown message");
});
if (block) {
ifr.contentWindow.postMessage(
{ callback: params.msg.blockingCallback },
"*"
);
} else {
ifr.contentWindow.postMessage(
{ callback: params.msg.nonBlockingCallback },
"*"
);
}
});
}
}
);
}
add_task(async function testPermissionGrantedOn3rdParty() {
info("Starting permission propagation test");
await SpecialPowers.flushPrefEnv();
await SpecialPowers.pushPrefEnv({
set: [
["dom.storage_access.enabled", true],
[
"network.cookie.cookieBehavior",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
],
[
"network.cookie.cookieBehavior.pbmode",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
],
["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.pbmode.enabled", false],
["privacy.trackingprotection.annotate_channels", true],
[
"privacy.restrict3rdpartystorage.userInteractionRequiredForHosts",
"tracking.example.com,tracking.example.org",
],
],
});
await UrlClassifierTestUtils.addTestTrackers();
let msg = {};
msg.blockingCallback = (async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
await noStorageAccessInitially();
await new Promise(resolve => {
// eslint-disable-next-line no-undef
let w = worker;
w.addEventListener(
"message",
e => {
ok(!e.data, "IDB is disabled");
resolve();
},
{ once: true }
);
w.postMessage("go");
});
}).toString();
msg.nonBlockingCallback = (async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
console.log("test hasStorageAccessInitially\n");
await hasStorageAccessInitially();
await new Promise(resolve => {
// eslint-disable-next-line no-undef
let w = worker;
w.addEventListener(
"message",
e => {
ok(e.data, "IDB is enabled");
resolve();
},
{ once: true }
);
w.postMessage("go");
});
}).toString();
let top = TEST_TOP_PAGE;
let page = TEST_3RD_PARTY_PAGE_WORKER;
let pageOther =
TEST_ANOTHER_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartyWorker.html";
let params = { page, msg, pageOther };
// Create 4 tabs:
// 1. The first tab has two tracker iframes, said A & B.
// 2. The second tab is opened by the first tab, and it has one tracker iframe, said C.
// 3. The third tab has one tracker iframe, said D.
// 4. The fourth tab is opened by the first tab but with a different top-level url).
// The tab has one tracker iframe, said E.
//
// This test grants permission on iframe A, which then should not propagate storage
// permission to iframe B, C, D, E
info("Creating the first tab");
let tab1 = await createTab(top, 2, null, params);
let browser1 = gBrowser.getBrowserForTab(tab1);
info("Creating the second tab");
let tab2 = await createTab(top, 1, browser1 /* opener */, params);
let browser2 = gBrowser.getBrowserForTab(tab2);
info("Creating the third tab");
let tab3 = await createTab(top, 1, null, params);
let browser3 = gBrowser.getBrowserForTab(tab3);
info("Creating the fourth tab");
let tab4 = await createTab(TEST_TOP_PAGE_2, 1, browser1, params);
let browser4 = gBrowser.getBrowserForTab(tab4);
info("Grant storage permission to the first iframe in the first tab");
await SpecialPowers.spawn(browser1, [page, msg], async function () {
await new content.Promise(resolve => {
content.addEventListener("message", function msg(event) {
if (event.data.type == "finish") {
content.removeEventListener("message", msg);
resolve();
return;
}
if (event.data.type == "ok") {
ok(event.data.what, event.data.msg);
return;
}
if (event.data.type == "info") {
info(event.data.msg);
return;
}
ok(false, "Unknown message");
});
let ifr = content.document.getElementById("ifr0");
ifr.contentWindow.postMessage(
{
callback: (async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
await callRequestStorageAccess();
}).toString(),
},
"*"
);
});
});
info("Second iframe of the first tab should not have stroage permission");
await testPermission(browser1, false /* block */, params, 0);
await testPermission(browser1, true /* block */, params, 1);
info("The iframe of the second tab should not have storage permission");
await testPermission(browser2, true /* block */, params);
info("The iframe of the third tab should not have storage permission");
await testPermission(browser3, true /* block */, params);
info("The iframe of the fourth tab should not have storage permission");
await testPermission(browser4, true /* block */, params);
info("Removing the tabs");
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
BrowserTestUtils.removeTab(tab3);
BrowserTestUtils.removeTab(tab4);
UrlClassifierTestUtils.cleanupTestTrackers();
});
add_task(async function () {
info("Cleaning up.");
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
});
add_task(async function testPermissionGrantedOnFirstParty() {
info("Starting permission propagation test");
await SpecialPowers.flushPrefEnv();
await SpecialPowers.pushPrefEnv({
set: [
["dom.storage_access.enabled", true],
[
"network.cookie.cookieBehavior",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
],
[
"network.cookie.cookieBehavior.pbmode",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
],
["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.pbmode.enabled", false],
["privacy.trackingprotection.annotate_channels", true],
],
});
await UrlClassifierTestUtils.addTestTrackers();
let msg = {};
msg.blockingCallback = (async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
await noStorageAccessInitially();
await new Promise(resolve => {
// eslint-disable-next-line no-undef
let w = worker;
w.addEventListener(
"message",
e => {
ok(!e.data, "IDB is disabled");
resolve();
},
{ once: true }
);
w.postMessage("go");
});
}).toString();
msg.nonBlockingCallback = (async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
console.log("test hasStorageAccessInitially\n");
await hasStorageAccessInitially();
await new Promise(resolve => {
// eslint-disable-next-line no-undef
let w = worker;
w.addEventListener(
"message",
e => {
ok(e.data, "IDB is enabled");
resolve();
},
{ once: true }
);
w.postMessage("go");
});
}).toString();
let top = TEST_TOP_PAGE;
let page = TEST_3RD_PARTY_PAGE_WORKER;
let params = { page, msg };
// Create 4 tabs:
// 1. The first tab has two tracker iframes, said A & B.
// 2. The second tab is opened by the first tab, and it has one tracker iframe, said C.
// 3. The third tab has one tracker iframe, said D.
// 4. The fourth tab is opened by the first tab but with a different top-level url).
// The tab has one tracker iframe, said E.
//
// This test grants permission on iframe A, which then should propagate storage
// permission to iframe B & C, but not D, E
info("Creating the first tab");
let tab1 = await createTab(top, 2, null, params);
let browser1 = gBrowser.getBrowserForTab(tab1);
info("Creating the second tab");
let tab2 = await createTab(top, 1, browser1 /* opener */, params);
let browser2 = gBrowser.getBrowserForTab(tab2);
info("Creating the third tab");
let tab3 = await createTab(top, 1, null, params);
let browser3 = gBrowser.getBrowserForTab(tab3);
info("Creating the fourth tab");
let tab4 = await createTab(TEST_TOP_PAGE_2, 1, browser1, params);
let browser4 = gBrowser.getBrowserForTab(tab4);
info("Grant storage permission to the first iframe in the first tab");
let promise = BrowserTestUtils.waitForNewTab(gBrowser, page);
await SpecialPowers.spawn(browser1, [page], async function (page) {
content.window.open(page, "_blank");
});
let tab = await promise;
BrowserTestUtils.removeTab(tab);
info("Both iframs of the first tab should have stroage permission");
await testPermission(browser1, false /* block */, params);
info("The iframe of the second tab should have storage permission");
await testPermission(browser2, false /* block */, params);
info("The iframe of the third tab should not have storage permission");
await testPermission(browser3, true /* block */, params);
info("The iframe of the fourth tab should not have storage permission");
await testPermission(browser4, true /* block */, params);
info("Removing the tabs");
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
BrowserTestUtils.removeTab(tab3);
BrowserTestUtils.removeTab(tab4);
UrlClassifierTestUtils.cleanupTestTrackers();
});
add_task(async function () {
info("Cleaning up.");
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
resolve()
);
});
});