916 lines
25 KiB
JavaScript
916 lines
25 KiB
JavaScript
function waitStoragePermission() {
|
|
return new Promise(resolve => {
|
|
let id = setInterval(async _ => {
|
|
if (
|
|
await SpecialPowers.testPermission(
|
|
`3rdPartyStorage^${TEST_3RD_PARTY_DOMAIN.slice(0, -1)}`,
|
|
SpecialPowers.Services.perms.ALLOW_ACTION,
|
|
TEST_DOMAIN
|
|
)
|
|
) {
|
|
clearInterval(id);
|
|
resolve();
|
|
}
|
|
}, 0);
|
|
});
|
|
}
|
|
|
|
add_setup(async function () {
|
|
info("Starting subResources test");
|
|
|
|
await SpecialPowers.flushPrefEnv();
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.storage_access.enabled", true],
|
|
[
|
|
"network.cookie.cookieBehavior",
|
|
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
|
|
],
|
|
[
|
|
"network.cookie.cookieBehavior.pbmode",
|
|
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
|
|
],
|
|
["privacy.trackingprotection.enabled", false],
|
|
["privacy.trackingprotection.pbmode.enabled", false],
|
|
["privacy.trackingprotection.annotate_channels", true],
|
|
["privacy.restrict3rdpartystorage.heuristic.window_open", true],
|
|
[
|
|
"privacy.restrict3rdpartystorage.userInteractionRequiredForHosts",
|
|
"tracking.example.com,tracking.example.org",
|
|
],
|
|
// Enable SA heuristics for trackers because the test depends on it.
|
|
[
|
|
"privacy.restrict3rdpartystorage.heuristic.exclude_third_party_trackers",
|
|
false,
|
|
],
|
|
],
|
|
});
|
|
|
|
await UrlClassifierTestUtils.addTestTrackers();
|
|
});
|
|
|
|
async function runTestWindowOpenHeuristic(disableHeuristics) {
|
|
info(
|
|
`Starting window.open() heuristic test with heuristic ${
|
|
disableHeuristics ? "disabled" : "enabled"
|
|
}.`
|
|
);
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["privacy.antitracking.enableWebcompat", !disableHeuristics]],
|
|
});
|
|
|
|
info("Creating a new tab");
|
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
|
gBrowser.selectedTab = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
await BrowserTestUtils.browserLoaded(browser);
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_WO,
|
|
disableHeuristics,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
// If the heuristic is disabled, we won't get storage access.
|
|
if (obj.disableHeuristics) {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await stillNoStorageAccess();
|
|
}).toString();
|
|
} else {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await hasStorageAccessInitially();
|
|
}).toString();
|
|
}
|
|
|
|
info("Checking if storage access is denied");
|
|
await new content.Promise(resolve => {
|
|
let ifr = content.document.createElement("iframe");
|
|
ifr.onload = function () {
|
|
info("Sending code to the 3rd party content");
|
|
ifr.contentWindow.postMessage(msg, "*");
|
|
};
|
|
|
|
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");
|
|
});
|
|
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
});
|
|
}
|
|
);
|
|
|
|
info("Removing the tab");
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
|
|
info("Cleaning up.");
|
|
await new Promise(resolve => {
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
|
|
resolve()
|
|
);
|
|
});
|
|
}
|
|
|
|
add_task(async function testWindowOpenHeuristic() {
|
|
await runTestWindowOpenHeuristic(false);
|
|
});
|
|
|
|
add_task(async function testWindowOpenHeuristicDisabled() {
|
|
await runTestWindowOpenHeuristic(true);
|
|
});
|
|
|
|
add_task(async function testDoublyNestedWindowOpenHeuristic() {
|
|
info("Starting doubly nested window.open() heuristic test...");
|
|
|
|
info("Creating a new tab");
|
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
|
gBrowser.selectedTab = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
await BrowserTestUtils.browserLoaded(browser);
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_RELAY + "?" + TEST_3RD_PARTY_PAGE_WO,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await hasStorageAccessInitially();
|
|
}).toString();
|
|
|
|
info("Checking if storage access is denied");
|
|
await new content.Promise(resolve => {
|
|
let ifr = content.document.createElement("iframe");
|
|
ifr.onload = function () {
|
|
info("Sending code to the 3rd party content");
|
|
ifr.contentWindow.postMessage(msg, "*");
|
|
};
|
|
|
|
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");
|
|
});
|
|
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
});
|
|
}
|
|
);
|
|
|
|
info("Removing the tab");
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("Cleaning up.");
|
|
await new Promise(resolve => {
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
|
|
resolve()
|
|
);
|
|
});
|
|
});
|
|
|
|
async function runTestUserInteractionHeuristic(disableHeuristics) {
|
|
info(
|
|
`Starting user interaction heuristic test with heuristic ${
|
|
disableHeuristics ? "disabled" : "enabled"
|
|
}.`
|
|
);
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["privacy.antitracking.enableWebcompat", !disableHeuristics]],
|
|
});
|
|
|
|
info("Creating a new tab");
|
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
|
gBrowser.selectedTab = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
await BrowserTestUtils.browserLoaded(browser);
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_UI,
|
|
popup: TEST_POPUP_PAGE,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
info("Checking if storage access is denied");
|
|
|
|
let ifr = content.document.createElement("iframe");
|
|
let loading = new content.Promise(resolve => {
|
|
ifr.onload = resolve;
|
|
});
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
await loading;
|
|
|
|
info(
|
|
"The 3rd party content should not have access to first party storage."
|
|
);
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
|
|
info("Opening a window from the iframe.");
|
|
await SpecialPowers.spawn(ifr, [obj.popup], async popup => {
|
|
let windowClosed = new content.Promise(resolve => {
|
|
Services.ww.registerNotification(
|
|
function notification(aSubject, aTopic) {
|
|
// We need to check the document URI for Fission. It's because the
|
|
// 'domwindowclosed' would be triggered twice, one for the
|
|
// 'about:blank' page and another for the tracker page.
|
|
if (
|
|
aTopic == "domwindowclosed" &&
|
|
aSubject.document.documentURI ==
|
|
"https://tracking.example.org/browser/toolkit/components/antitracking/test/browser/3rdPartyOpenUI.html"
|
|
) {
|
|
Services.ww.unregisterNotification(notification);
|
|
resolve();
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
content.open(popup);
|
|
|
|
info("Let's wait for the window to be closed");
|
|
await windowClosed;
|
|
});
|
|
|
|
info("The 3rd party content should have access to first party storage.");
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
}
|
|
);
|
|
|
|
await AntiTracking.interactWithTracker();
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_UI,
|
|
popup: TEST_POPUP_PAGE,
|
|
disableHeuristics,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
|
|
msg.blockingCallback = (async _ => {
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
// If the heuristic is disabled, we won't get storage access.
|
|
if (obj.disableHeuristics) {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await stillNoStorageAccess();
|
|
}).toString();
|
|
} else {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await hasStorageAccessInitially();
|
|
}).toString();
|
|
}
|
|
|
|
info("Checking if storage access is denied");
|
|
|
|
let ifr = content.document.createElement("iframe");
|
|
let loading = new content.Promise(resolve => {
|
|
ifr.onload = resolve;
|
|
});
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
await loading;
|
|
|
|
info(
|
|
"The 3rd party content should not have access to first party storage."
|
|
);
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
|
|
info("Opening a window from the iframe.");
|
|
await SpecialPowers.spawn(ifr, [obj.popup], async popup => {
|
|
let windowClosed = new content.Promise(resolve => {
|
|
Services.ww.registerNotification(
|
|
function notification(aSubject, aTopic) {
|
|
// We need to check the document URI here as well for the same
|
|
// reason above.
|
|
if (
|
|
aTopic == "domwindowclosed" &&
|
|
aSubject.document.documentURI ==
|
|
"https://tracking.example.org/browser/toolkit/components/antitracking/test/browser/3rdPartyOpenUI.html"
|
|
) {
|
|
Services.ww.unregisterNotification(notification);
|
|
resolve();
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
content.open(popup);
|
|
|
|
info("Let's wait for the window to be closed");
|
|
await windowClosed;
|
|
});
|
|
|
|
info("The 3rd party content should have access to first party storage.");
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage(
|
|
{ callback: msg.nonBlockingCallback },
|
|
"*"
|
|
);
|
|
});
|
|
}
|
|
);
|
|
|
|
info("Removing the tab");
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
if (!disableHeuristics) {
|
|
info("Wait until the storage permission is ready before cleaning up.");
|
|
await waitStoragePermission();
|
|
}
|
|
|
|
info("Cleaning up.");
|
|
await new Promise(resolve => {
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
|
|
resolve()
|
|
);
|
|
});
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
}
|
|
|
|
add_task(async function testUserInteractionHeuristic() {
|
|
await runTestUserInteractionHeuristic(false);
|
|
});
|
|
|
|
add_task(async function testUserInteractionHeuristicWithoutTracker() {
|
|
UrlClassifierTestUtils.cleanupTestTrackers();
|
|
await runTestUserInteractionHeuristic(false);
|
|
await UrlClassifierTestUtils.addTestTrackers();
|
|
});
|
|
|
|
add_task(async function testUserInteractionHeuristicDisabled() {
|
|
await runTestUserInteractionHeuristic(true);
|
|
});
|
|
|
|
add_task(async function testDoublyNestedUserInteractionHeuristic() {
|
|
info("Starting doubly nested user interaction heuristic test...");
|
|
|
|
info("Creating a new tab");
|
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
|
gBrowser.selectedTab = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
await BrowserTestUtils.browserLoaded(browser);
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_RELAY + "?" + TEST_3RD_PARTY_PAGE_UI,
|
|
popup: TEST_POPUP_PAGE,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
msg.openWindowCallback = (async url => {
|
|
open(url);
|
|
}).toString();
|
|
|
|
info("Checking if storage access is denied");
|
|
|
|
let ifr = content.document.createElement("iframe");
|
|
let loading = new content.Promise(resolve => {
|
|
ifr.onload = resolve;
|
|
});
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
await loading;
|
|
|
|
info(
|
|
"The 3rd party content should not have access to first party storage."
|
|
);
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
|
|
let windowClosed = new content.Promise(resolve => {
|
|
Services.ww.registerNotification(
|
|
function notification(aSubject, aTopic) {
|
|
if (aTopic == "domwindowclosed") {
|
|
Services.ww.unregisterNotification(notification);
|
|
resolve();
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
info("Opening a window from the iframe.");
|
|
ifr.contentWindow.postMessage(
|
|
{ callback: msg.openWindowCallback, arg: obj.popup },
|
|
"*"
|
|
);
|
|
|
|
info("Let's wait for the window to be closed");
|
|
await windowClosed;
|
|
|
|
info("The 3rd party content should have access to first party storage.");
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
}
|
|
);
|
|
|
|
await AntiTracking.interactWithTracker();
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE_RELAY + "?" + TEST_3RD_PARTY_PAGE_UI,
|
|
popup: TEST_POPUP_PAGE,
|
|
},
|
|
],
|
|
async obj => {
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await hasStorageAccessInitially();
|
|
}).toString();
|
|
|
|
msg.openWindowCallback = (async url => {
|
|
open(url);
|
|
}).toString();
|
|
|
|
info("Checking if storage access is denied");
|
|
|
|
let ifr = content.document.createElement("iframe");
|
|
let loading = new content.Promise(resolve => {
|
|
ifr.onload = resolve;
|
|
});
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
await loading;
|
|
|
|
info(
|
|
"The 3rd party content should not have access to first party storage."
|
|
);
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage({ callback: msg.blockingCallback }, "*");
|
|
});
|
|
|
|
let windowClosed = new content.Promise(resolve => {
|
|
Services.ww.registerNotification(
|
|
function notification(aSubject, aTopic) {
|
|
if (aTopic == "domwindowclosed") {
|
|
Services.ww.unregisterNotification(notification);
|
|
resolve();
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
info("Opening a window from the iframe.");
|
|
ifr.contentWindow.postMessage(
|
|
{ callback: msg.openWindowCallback, arg: obj.popup },
|
|
"*"
|
|
);
|
|
|
|
info("Let's wait for the window to be closed");
|
|
await windowClosed;
|
|
|
|
info("The 3rd party content should have access to first party storage.");
|
|
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");
|
|
});
|
|
ifr.contentWindow.postMessage(
|
|
{ callback: msg.nonBlockingCallback },
|
|
"*"
|
|
);
|
|
});
|
|
}
|
|
);
|
|
|
|
info("Removing the tab");
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function () {
|
|
info("Wait until the storage permission is ready before cleaning up.");
|
|
await waitStoragePermission();
|
|
|
|
info("Cleaning up.");
|
|
await new Promise(resolve => {
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
|
|
resolve()
|
|
);
|
|
});
|
|
});
|
|
|
|
async function runTestFirstPartyWindowOpenHeuristic(disableHeuristics) {
|
|
info(
|
|
`Starting first-party window.open() heuristic test with heuristic ${
|
|
disableHeuristics ? "disabled" : "enabled"
|
|
}.`
|
|
);
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["privacy.antitracking.enableWebcompat", !disableHeuristics]],
|
|
});
|
|
|
|
// Interact with the tracker first before testing window.open heuristic
|
|
await AntiTracking.interactWithTracker();
|
|
|
|
info("Creating a new tab");
|
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
|
gBrowser.selectedTab = tab;
|
|
|
|
let browser = gBrowser.getBrowserForTab(tab);
|
|
await BrowserTestUtils.browserLoaded(browser);
|
|
|
|
info("Loading tracking scripts");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_3RD_PARTY_PAGE,
|
|
},
|
|
],
|
|
async obj => {
|
|
info("Tracker shouldn't have storage access initially");
|
|
let msg = {};
|
|
msg.blockingCallback = (async _ => {
|
|
await noStorageAccessInitially();
|
|
}).toString();
|
|
|
|
await new content.Promise(resolve => {
|
|
let ifr = content.document.createElement("iframe");
|
|
ifr.onload = function () {
|
|
info("Sending code to the 3rd party content");
|
|
ifr.contentWindow.postMessage(msg.blockingCallback, "*");
|
|
};
|
|
|
|
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");
|
|
});
|
|
|
|
content.document.body.appendChild(ifr);
|
|
ifr.id = "ifr";
|
|
ifr.src = obj.page;
|
|
});
|
|
}
|
|
);
|
|
|
|
info("Calling window.open in a first-party iframe");
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[
|
|
{
|
|
page: TEST_IFRAME_PAGE,
|
|
popup: TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartyOpen.html",
|
|
},
|
|
],
|
|
async obj => {
|
|
let ifr = content.document.createElement("iframe");
|
|
let loading = new content.Promise(resolve => {
|
|
ifr.onload = resolve;
|
|
});
|
|
content.document.body.appendChild(ifr);
|
|
ifr.src = obj.page;
|
|
await loading;
|
|
|
|
info("Opening a window from the iframe.");
|
|
await SpecialPowers.spawn(ifr, [obj.popup], async popup => {
|
|
await new content.Promise(resolve => {
|
|
content.open(popup);
|
|
content.addEventListener("message", function msg(event) {
|
|
if (event.data == "hello!") {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
await SpecialPowers.spawn(browser, [{ disableHeuristics }], async obj => {
|
|
info(
|
|
"If the heuristic is enabled, the tracker should have storage access now."
|
|
);
|
|
let msg = {};
|
|
|
|
// If the heuristic is disabled, we won't get storage access.
|
|
if (obj.disableHeuristics) {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await stillNoStorageAccess();
|
|
}).toString();
|
|
} else {
|
|
msg.nonBlockingCallback = (async _ => {
|
|
/* import-globals-from storageAccessAPIHelpers.js */
|
|
await hasStorageAccessInitially();
|
|
}).toString();
|
|
}
|
|
|
|
await new content.Promise(resolve => {
|
|
let ifr = content.document.getElementById("ifr");
|
|
info("Sending code to the 3rd party content");
|
|
ifr.contentWindow.postMessage(msg.nonBlockingCallback, "*");
|
|
|
|
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");
|
|
});
|
|
});
|
|
});
|
|
|
|
info("Removing the tab");
|
|
BrowserTestUtils.removeTab(tab);
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
|
|
info("Cleaning up.");
|
|
await new Promise(resolve => {
|
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, () =>
|
|
resolve()
|
|
);
|
|
});
|
|
}
|
|
|
|
add_task(async function testFirstPartyWindowOpenHeuristic() {
|
|
await runTestFirstPartyWindowOpenHeuristic(false);
|
|
});
|
|
|
|
add_task(async function testFirstPartyWindowOpenHeuristicDisabled() {
|
|
await runTestFirstPartyWindowOpenHeuristic(true);
|
|
});
|
|
|
|
add_task(async function () {
|
|
UrlClassifierTestUtils.cleanupTestTrackers();
|
|
});
|