Bug 1642051 - add PartitioningSkipList to relax partitioning on specific domains; r=baku

Differential Revision: https://phabricator.services.mozilla.com/D81591
This commit is contained in:
Liang-Heng Chen 2020-06-30 12:56:00 +00:00
Родитель 544e563e54
Коммит 3d1fd6f81d
7 изменённых файлов: 620 добавлений и 224 удалений

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsPIDOMWindow.h"
#include "nsSandboxFlags.h"
#include "nsScriptSecurityManager.h"
#include "PartitioningSkipList.h"
#define ANTITRACKING_PERM_KEY "3rdPartyStorage"
@ -341,6 +342,11 @@ bool AntiTrackingUtils::CheckStoragePermission(nsIPrincipal* aPrincipal,
return false;
}
nsAutoCString targetOrigin;
if (NS_WARN_IF(NS_FAILED(targetPrincipal->GetAsciiOrigin(targetOrigin)))) {
return false;
}
nsCOMPtr<nsIURI> trackingURI;
rv = aChannel->GetURI(getter_AddRefs(trackingURI));
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -358,6 +364,10 @@ bool AntiTrackingUtils::CheckStoragePermission(nsIPrincipal* aPrincipal,
uint32_t unusedReason = 0;
if (PartitioningSkipList::Check(targetOrigin, trackingOrigin)) {
return true;
}
return AntiTrackingUtils::CheckStoragePermission(
targetPrincipal, type, NS_UsePrivateBrowsing(aChannel), &unusedReason,
unusedReason);

Просмотреть файл

@ -0,0 +1,131 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "PartitioningSkipList.h"
#include "AntiTrackingLog.h"
#include "nsContentUtils.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace {
inline void CreateSkipListKey(const nsACString& aFirstPartyOrigin,
const nsACString& aThirdPartyOrigin,
nsACString& aSkipListKey) {
MOZ_ASSERT(!aFirstPartyOrigin.IsEmpty());
MOZ_ASSERT(!aThirdPartyOrigin.IsEmpty());
aSkipListKey.Assign(aFirstPartyOrigin);
aSkipListKey.Append(",");
aSkipListKey.Append(aThirdPartyOrigin);
}
inline void CreateSkipListKey(nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI,
nsACString& aSkipListKey) {
MOZ_ASSERT(aFirstPartyURI);
MOZ_ASSERT(aThirdPartyURI);
nsAutoCString firstPartyOrigin, thirdPartyOrigin;
nsContentUtils::GetASCIIOrigin(aFirstPartyURI, firstPartyOrigin);
nsContentUtils::GetASCIIOrigin(aThirdPartyURI, thirdPartyOrigin);
CreateSkipListKey(firstPartyOrigin, thirdPartyOrigin, aSkipListKey);
}
StaticRefPtr<PartitioningSkipList> gPartitioningSkipList;
} // namespace
NS_IMPL_ISUPPORTS(PartitioningSkipList, nsIPartitioningSkipListObserver)
bool PartitioningSkipList::Check(const nsACString& aFirstPartyOrigin,
const nsACString& aThirdPartyOrigin) {
if (aFirstPartyOrigin.IsEmpty() || aThirdPartyOrigin.IsEmpty()) {
return false;
}
LOG(("Check partitioning skip list for url %s and %s",
PromiseFlatCString(aFirstPartyOrigin).get(),
PromiseFlatCString(aThirdPartyOrigin).get()));
nsAutoCString key;
CreateSkipListKey(aFirstPartyOrigin, aThirdPartyOrigin, key);
if (GetOrCreate()->mSkipList.Contains(key)) {
LOG(("URI is in skip list"));
return true;
}
return false;
}
PartitioningSkipList* PartitioningSkipList::GetOrCreate() {
if (!gPartitioningSkipList) {
gPartitioningSkipList = new PartitioningSkipList();
gPartitioningSkipList->Init();
RunOnShutdown([&] {
gPartitioningSkipList->Shutdown();
gPartitioningSkipList = nullptr;
});
}
return gPartitioningSkipList;
}
nsresult PartitioningSkipList::Init() {
mService = do_GetService("@mozilla.org/partitioning/skip-list-service;1");
if (NS_WARN_IF(!mService)) {
return NS_ERROR_FAILURE;
}
mService->RegisterAndRunSkipListObserver(this);
return NS_OK;
}
void PartitioningSkipList::Shutdown() {
if (mService) {
mService->UnregisterSkipListObserver(this);
mService = nullptr;
}
mSkipList.Clear();
}
NS_IMETHODIMP
PartitioningSkipList::OnSkipListUpdate(const nsACString& aList) {
mSkipList.Clear();
nsresult rv;
for (const nsACString& item : aList.Split(';')) {
auto origins = item.Split(',');
nsCOMPtr<nsIURI> firstPartyURI;
rv = NS_NewURI(getter_AddRefs(firstPartyURI), origins.Get(0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIURI> thirdPartyURI;
rv = NS_NewURI(getter_AddRefs(thirdPartyURI), origins.Get(1));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoCString key;
CreateSkipListKey(firstPartyURI, thirdPartyURI, key);
LOG(("onSkipListUpdate: %s", key.get()));
mSkipList.AppendElement(key);
}
return NS_OK;
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_PartitioningSkipList_h
#define mozilla_PartitioningSkipList_h
#include "nsIPartitioningSkipListService.h"
#include "nsTArrayForwardDeclare.h"
class nsIChannel;
class nsIPrincipal;
namespace mozilla {
class PartitioningSkipList : public nsIPartitioningSkipListObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPARTITIONINGSKIPLISTOBSERVER
static bool Check(const nsACString& aFirstPartyOrigin,
const nsACString& aThirdPartyOrigin);
private:
static PartitioningSkipList* GetOrCreate();
PartitioningSkipList() = default;
virtual ~PartitioningSkipList() = default;
nsresult Init();
void Shutdown();
nsCOMPtr<nsIPartitioningSkipListService> mService;
nsTArray<nsCString> mSkipList;
};
} // namespace mozilla
#endif // mozilla_PartitioningSkipList_h

Просмотреть файл

@ -56,6 +56,7 @@ UNIFIED_SOURCES += [
'ContentBlockingNotifier.cpp',
'ContentBlockingUserInteraction.cpp',
'DynamicFpiRedirectHeuristic.cpp',
'PartitioningSkipList.cpp',
'RejectForeignAllowList.cpp',
'SettingsChangeObserver.cpp',
'StorageAccess.cpp',

Просмотреть файл

@ -106,7 +106,7 @@ support-files = tracker.js
[browser_storageAccessRemovalNavigateTopframe.js]
[browser_storageAccessSandboxed.js]
[browser_storageAccessThirdPartyChecks.js]
[browser_storageAccessWithDynamicFpiHeuristics.js]
[browser_storageAccessWithDynamicFpi.js]
[browser_storageAccessWithHeuristics.js]
[browser_networkIsolation.js]
[browser_allowPermissionForTracker.js]

Просмотреть файл

@ -0,0 +1,436 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
/* import-globals-from head.js */
"use strict";
const { RemoteSettings } = ChromeUtils.import(
"resource://services-settings/remote-settings.js"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"peuService",
"@mozilla.org/partitioning/skip-list-service;1",
"nsIPartitioningSkipListService"
);
const TEST_REDIRECT_TOP_PAGE =
TEST_3RD_PARTY_DOMAIN + TEST_PATH + "redirect.sjs?" + TEST_TOP_PAGE;
const TEST_REDIRECT_3RD_PARTY_PAGE =
TEST_DOMAIN + TEST_PATH + "redirect.sjs?" + TEST_3RD_PARTY_PARTITIONED_PAGE;
const COLLECTION_NAME = "partitioning-exempt-urls";
const SKIP_LIST_PREF_NAME = "privacy.restrict3rdpartystorage.skip_list";
async function cleanup() {
Services.prefs.clearUserPref(SKIP_LIST_PREF_NAME);
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
resolve()
);
});
}
add_task(async function setup() {
await SpecialPowers.flushPrefEnv();
await SpecialPowers.pushPrefEnv({
set: [
[
"network.cookie.cookieBehavior",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
],
["privacy.restrict3rdpartystorage.heuristic.redirect", false],
["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.pbmode.enabled", false],
["privacy.trackingprotection.annotate_channels", true],
],
});
registerCleanupFunction(cleanup);
});
function executeContentScript(browser, callback, options = {}) {
return SpecialPowers.spawn(
browser,
[
{
callback: callback.toString(),
...options,
},
],
obj => {
return new content.Promise(async resolve => {
if (obj.page) {
// third-party
let ifr = content.document.createElement("iframe");
ifr.onload = async () => {
info("Sending code to the 3rd party content");
ifr.contentWindow.postMessage(
{ cb: obj.callback, value: obj.value },
"*"
);
};
content.addEventListener("message", event => resolve(event.data), {
once: true,
});
content.document.body.appendChild(ifr);
ifr.src = obj.page;
} else {
// first-party
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
resolve(await runnable.call(content, content, obj.value));
}
});
}
);
}
function readNetworkCookie(win) {
return win
.fetch("cookies.sjs")
.then(r => r.text())
.then(text => {
return text.substring("cookie:foopy=".length);
});
}
async function writeNetworkCookie(win, value) {
await win.fetch("cookies.sjs?" + value).then(r => r.text());
return true;
}
function createDataInFirstParty(browser, value) {
return executeContentScript(browser, writeNetworkCookie, { value });
}
function getDataFromFirstParty(browser) {
return executeContentScript(browser, readNetworkCookie, {});
}
function createDataInThirdParty(browser, value) {
return executeContentScript(browser, writeNetworkCookie, {
page: TEST_3RD_PARTY_PARTITIONED_PAGE,
value,
});
}
function getDataFromThirdParty(browser) {
return executeContentScript(browser, readNetworkCookie, {
page: TEST_3RD_PARTY_PARTITIONED_PAGE,
});
}
async function redirectWithUserInteraction(browser, url, wait = null) {
await executeContentScript(
browser,
(content, value) => {
content.document.userInteractionForTesting();
let link = content.document.createElement("a");
link.appendChild(content.document.createTextNode("click me!"));
link.href = value;
content.document.body.appendChild(link);
link.click();
},
{
value: url,
}
);
await BrowserTestUtils.browserLoaded(browser, false, wait || url);
}
async function checkData(browser, options) {
if ("firstParty" in options) {
is(
await getDataFromFirstParty(browser),
options.firstParty,
"correct first-party data"
);
}
if ("thirdParty" in options) {
is(
await getDataFromThirdParty(browser),
options.thirdParty,
"correct third-party data"
);
}
}
add_task(async function testRedirectHeuristic() {
info("Starting Dynamic FPI Redirect Heuristic test...");
await SpecialPowers.pushPrefEnv({
set: [["privacy.restrict3rdpartystorage.heuristic.recently_visited", true]],
});
// mark third-party as tracker
await UrlClassifierTestUtils.addTestTrackers();
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("initializing...");
await checkData(browser, { firstParty: "", thirdParty: "" });
await Promise.all([
createDataInFirstParty(browser, "firstParty"),
createDataInThirdParty(browser, "thirdParty"),
]);
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "",
});
info("load third-party content as first-party");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_3RD_PARTY_PAGE,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
await checkData(browser, { firstParty: "" });
await createDataInFirstParty(browser, "heuristicFirstParty");
await checkData(browser, { firstParty: "heuristicFirstParty" });
info("redirect back to first-party page");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_TOP_PAGE,
TEST_TOP_PAGE
);
info("third-party tracker should NOT able to access first-party data");
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "",
});
// remove third-party from tracker
await UrlClassifierTestUtils.cleanupTestTrackers();
info("load third-party content as first-party");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_3RD_PARTY_PAGE,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
await checkData(browser, {
firstParty: "heuristicFirstParty",
});
info("redirect back to first-party page");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_TOP_PAGE,
TEST_TOP_PAGE
);
info("third-party page should able to access first-party data");
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "heuristicFirstParty",
});
info("Removing the tab");
BrowserTestUtils.removeTab(tab);
await cleanup();
});
class UpdateEvent extends EventTarget {}
function waitForEvent(element, eventName) {
return new Promise(function(resolve) {
element.addEventListener(eventName, e => resolve(e.detail), { once: true });
});
}
add_task(async function testSkipListPref() {
info("Starting Dynamic FPI skip list test pref");
await SpecialPowers.pushPrefEnv({
set: [
["privacy.restrict3rdpartystorage.heuristic.recently_visited", false],
],
});
info("Creating new tabs");
let tabThirdParty = BrowserTestUtils.addTab(
gBrowser,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
gBrowser.selectedTab = tabThirdParty;
let browserThirdParty = gBrowser.getBrowserForTab(tabThirdParty);
await BrowserTestUtils.browserLoaded(browserThirdParty);
let tabFirstParty = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
gBrowser.selectedTab = tabFirstParty;
let browserFirstParty = gBrowser.getBrowserForTab(tabFirstParty);
await BrowserTestUtils.browserLoaded(browserFirstParty);
info("initializing...");
await Promise.all([
checkData(browserFirstParty, { firstParty: "", thirdParty: "" }),
checkData(browserThirdParty, { firstParty: "" }),
]);
info("fill default data");
await Promise.all([
createDataInFirstParty(browserFirstParty, "firstParty"),
createDataInThirdParty(browserFirstParty, "thirdParty"),
createDataInFirstParty(browserThirdParty, "SkipListFirstParty"),
]);
info("check data");
await Promise.all([
checkData(browserFirstParty, {
firstParty: "firstParty",
thirdParty: "thirdParty",
}),
checkData(browserThirdParty, { firstParty: "SkipListFirstParty" }),
]);
info("set skip list pref");
Services.prefs.setStringPref(
SKIP_LIST_PREF_NAME,
`${TEST_DOMAIN},${TEST_3RD_PARTY_DOMAIN}`
);
info("check data");
await Promise.all([
checkData(browserFirstParty, {
firstParty: "firstParty",
thirdParty: "SkipListFirstParty",
}),
checkData(browserThirdParty, { firstParty: "SkipListFirstParty" }),
]);
info("Removing the tab");
BrowserTestUtils.removeTab(tabFirstParty);
BrowserTestUtils.removeTab(tabThirdParty);
await cleanup();
});
add_task(async function testSkipListRemoteSettings() {
info("Starting Dynamic FPI skip list test (remote settings)");
await SpecialPowers.pushPrefEnv({
set: [
["privacy.restrict3rdpartystorage.heuristic.recently_visited", false],
],
});
// Make sure we have a pref initially, since the skip list service requires it.
Services.prefs.setStringPref(SKIP_LIST_PREF_NAME, "");
// Add some initial data
let db = await RemoteSettings(COLLECTION_NAME).db;
await db.importChanges({}, 42, []);
// make peuSerivce start working by calling registerAndRunSkipListObserver
let updateEvent = new UpdateEvent();
let obs = data => {
let event = new CustomEvent("update", { detail: data });
updateEvent.dispatchEvent(event);
};
let promise = waitForEvent(updateEvent, "update");
peuService.registerAndRunSkipListObserver(obs);
await promise;
info("Creating new tabs");
let tabThirdParty = BrowserTestUtils.addTab(
gBrowser,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
gBrowser.selectedTab = tabThirdParty;
let browserThirdParty = gBrowser.getBrowserForTab(tabThirdParty);
await BrowserTestUtils.browserLoaded(browserThirdParty);
let tabFirstParty = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
gBrowser.selectedTab = tabFirstParty;
let browserFirstParty = gBrowser.getBrowserForTab(tabFirstParty);
await BrowserTestUtils.browserLoaded(browserFirstParty);
info("initializing...");
await Promise.all([
checkData(browserFirstParty, { firstParty: "", thirdParty: "" }),
checkData(browserThirdParty, { firstParty: "" }),
]);
info("fill default data");
await Promise.all([
createDataInFirstParty(browserFirstParty, "firstParty"),
createDataInThirdParty(browserFirstParty, "thirdParty"),
createDataInFirstParty(browserThirdParty, "SkipListFirstParty"),
]);
info("check data");
await Promise.all([
checkData(browserFirstParty, {
firstParty: "firstParty",
thirdParty: "thirdParty",
}),
checkData(browserThirdParty, { firstParty: "SkipListFirstParty" }),
]);
info("set skip list remote settings");
// set records
promise = waitForEvent(updateEvent, "update");
await RemoteSettings(COLLECTION_NAME).emit("sync", {
data: {
current: [
{
id: "1",
last_modified: 100000000000000000001,
firstPartyOrigin: TEST_DOMAIN,
thirdPartyOrigin: TEST_3RD_PARTY_DOMAIN,
},
],
},
});
let list = await promise;
is(
list,
`${TEST_DOMAIN},${TEST_3RD_PARTY_DOMAIN}`,
"skip list is correctly set"
);
info("check data");
await Promise.all([
checkData(browserFirstParty, {
firstParty: "firstParty",
thirdParty: "SkipListFirstParty",
}),
checkData(browserThirdParty, { firstParty: "SkipListFirstParty" }),
]);
info("Removing the tab");
BrowserTestUtils.removeTab(tabFirstParty);
BrowserTestUtils.removeTab(tabThirdParty);
promise = waitForEvent(updateEvent, "update");
await RemoteSettings(COLLECTION_NAME).emit("sync", {
data: {
current: [],
},
});
is(await promise, "", "skip list is cleared");
peuService.unregisterSkipListObserver(obs);
await cleanup();
});

Просмотреть файл

@ -1,223 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
/* import-globals-from head.js */
"use strict";
const TEST_REDIRECT_TOP_PAGE =
TEST_3RD_PARTY_DOMAIN + TEST_PATH + "redirect.sjs?" + TEST_TOP_PAGE;
const TEST_REDIRECT_3RD_PARTY_PAGE =
TEST_DOMAIN + TEST_PATH + "redirect.sjs?" + TEST_3RD_PARTY_PARTITIONED_PAGE;
async function cleanup() {
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
resolve()
);
});
}
add_task(async () => {
await SpecialPowers.flushPrefEnv();
await SpecialPowers.pushPrefEnv({
set: [
[
"network.cookie.cookieBehavior",
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
],
["privacy.restrict3rdpartystorage.heuristic.redirect", false],
["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.pbmode.enabled", false],
["privacy.trackingprotection.annotate_channels", true],
],
});
registerCleanupFunction(cleanup);
});
function executeContentScript(browser, callback, options = {}) {
return SpecialPowers.spawn(
browser,
[
{
callback: callback.toString(),
...options,
},
],
obj => {
return new content.Promise(async resolve => {
if (obj.page) {
// third-party
let ifr = content.document.createElement("iframe");
ifr.onload = async () => {
info("Sending code to the 3rd party content");
ifr.contentWindow.postMessage({ cb: obj.callback }, "*");
};
content.addEventListener("message", event => resolve(event.data), {
once: true,
});
content.document.body.appendChild(ifr);
ifr.src = obj.page;
} else {
// first-party
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
resolve(await runnable.call(content, content, obj.value));
}
});
}
);
}
function readNetworkCookie(win) {
return win
.fetch("cookies.sjs")
.then(r => r.text())
.then(text => {
return text.substring("cookie:foopy=".length);
});
}
async function writeNetworkCookie(win, value) {
await win.fetch("cookies.sjs?" + value).then(r => r.text());
return true;
}
function createDataInFirstParty(browser, value) {
return executeContentScript(browser, writeNetworkCookie, { value });
}
function getDataFromFirstParty(browser) {
return executeContentScript(browser, readNetworkCookie, {});
}
function createDataInThirdParty(browser, value) {
return executeContentScript(browser, writeNetworkCookie, {
page: TEST_3RD_PARTY_PARTITIONED_PAGE,
value,
});
}
function getDataFromThirdParty(browser) {
return executeContentScript(browser, readNetworkCookie, {
page: TEST_3RD_PARTY_PARTITIONED_PAGE,
});
}
async function redirectWithUserInteraction(browser, url, wait = null) {
await executeContentScript(
browser,
(content, value) => {
content.document.userInteractionForTesting();
let link = content.document.createElement("a");
link.appendChild(content.document.createTextNode("click me!"));
link.href = value;
content.document.body.appendChild(link);
link.click();
},
{
value: url,
}
);
await BrowserTestUtils.browserLoaded(browser, false, wait || url);
}
async function checkData(browser, options) {
if ("firstParty" in options) {
is(
await getDataFromFirstParty(browser),
options.firstParty,
"currect first-party data"
);
}
if ("thirdParty" in options) {
is(
await getDataFromThirdParty(browser),
options.thirdParty,
"currect third-party data"
);
}
}
add_task(async () => {
info("Starting Dynamic FPI Redirect Heuristic test...");
// mark third-party as tracker
await UrlClassifierTestUtils.addTestTrackers();
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("initializing...");
await checkData(browser, { firstParty: "", thirdParty: "" });
await Promise.all([
createDataInFirstParty(browser, "firstParty"),
createDataInThirdParty(browser, "thirdParty"),
]);
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "",
});
info("load third-party content as first-party");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_3RD_PARTY_PAGE,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
await checkData(browser, { firstParty: "" });
await createDataInFirstParty(browser, "heuristicFirstParty");
await checkData(browser, { firstParty: "heuristicFirstParty" });
info("redirect back to first-party page");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_TOP_PAGE,
TEST_TOP_PAGE
);
info("third-party tracker should NOT able to access first-party data");
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "",
});
// remove third-party from tracker
await UrlClassifierTestUtils.cleanupTestTrackers();
info("load third-party content as first-party");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_3RD_PARTY_PAGE,
TEST_3RD_PARTY_PARTITIONED_PAGE
);
await checkData(browser, {
firstParty: "heuristicFirstParty",
});
info("redirect back to first-party page");
await redirectWithUserInteraction(
browser,
TEST_REDIRECT_TOP_PAGE,
TEST_TOP_PAGE
);
info("third-party page should able to access first-party data");
await checkData(browser, {
firstParty: "firstParty",
thirdParty: "heuristicFirstParty",
});
info("Removing the tab");
BrowserTestUtils.removeTab(tab);
});