new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_cookies_first_party.html
@@ -0,0 +1,218 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/SpawnTask.js"></script>
+<script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+<script src="head.js"></script>
+<script>
+"use strict";
+
+async function background() {
+ const url = "http://ext-cookie-first-party.mochi.test/";
+ const firstPartyDomain = "ext-cookie-first-party.mochi.test";
+ const expectedError = "First-Party Isolation is enabled, but the required 'firstPartyDomain' attribute was not set.";
+
+ const assertExpectedCookies = (expected, cookies, message) => {
+ let matches = (cookie, expected) => {
+ for (let key of Object.keys(expected)) {
+ if (cookie[key] !== expected[key]) {
+ return false;
+ }
+ }
+ return true;
+ };
+ browser.test.assertEq(expected.length, cookies.length, `Got expected number of cookies - ${message}`);
+ if (cookies.length !== expected.length) {
+ return;
+ }
+ for (let expect of expected) {
+ let foundCookies = cookies.filter(cookie => matches(cookie, expect));
+ browser.test.assertEq(1, foundCookies.length,
+ `Expected cookie ${JSON.stringify(expect)} found - ${message}`);
+ }
+ };
+
+ // Test when FPI is disabled.
+ const test_fpi_disabled = async () => {
+ let cookie, cookies;
+
+ // set
+ cookie = await browser.cookies.set({url, name: "foo1", value: "bar1"});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ ], [cookie], "set: FPI off, w/o firstPartyDomain, non-FP cookie");
+ cookie = await browser.cookies.set({url, name: "foo2", value: "bar2", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], [cookie], "set: FPI off, w/ firstPartyDomain, FP cookie");
+
+ // get
+ cookie = await browser.cookies.get({url, name: "foo1"});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ ], [cookie], "get: FPI off, w/o firstPartyDomain, non-FP cookie");
+ cookie = await browser.cookies.get({url, name: "foo2", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], [cookie], "get: FPI off, w/ firstPartyDomain, FP cookie");
+
+ // getAll
+ cookies = await browser.cookies.getAll({});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ ], cookies, "getAll: FPI off, w/o firstPartyDomain, non-FP cookies");
+ cookies = await browser.cookies.getAll({firstPartyDomain: null});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], cookies, "getAll: FPI off, w/ null firstPartyDomain, all cookies");
+ cookies = await browser.cookies.getAll({firstPartyDomain: undefined});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], cookies, "getAll: FPI off, w/ undefined firstPartyDomain, all cookies");
+ cookies = await browser.cookies.getAll({firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], cookies, "getAll: FPI off, w/ firstPartyDomain, FP cookies");
+
+ // remove
+ cookie = await browser.cookies.remove({url, name: "foo1"});
+ assertExpectedCookies([
+ {url, name: "foo1", firstPartyDomain: ""},
+ ], [cookie], "remove: FPI off, w/o firstPartyDomain, non-FP cookie");
+ cookie = await browser.cookies.remove({url, name: "foo2", firstPartyDomain});
+ assertExpectedCookies([
+ {url, name: "foo2", firstPartyDomain},
+ ], [cookie], "remove: FPI off, w/ firstPartyDomain, FP cookie");
+
+ // Test if FP cookies set when FPI off can be accessed when FPI on.
+ await browser.cookies.set({url, name: "foo1", value: "bar1"});
+ await browser.cookies.set({url, name: "foo2", value: "bar2", firstPartyDomain});
+
+ browser.test.sendMessage("test_fpi_disabled");
+ };
+
+ // Test when FPI is enabled.
+ const test_fpi_enabled = async () => {
+ let cookie, cookies;
+
+ // set
+ browser.test.assertRejects(browser.cookies.set({url, name: "foo3", value: "bar3"}),
+ expectedError,
+ "set: FPI on, w/o firstPartyDomain, rejection");
+ cookie = await browser.cookies.set({url, name: "foo4", value: "bar4", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo4", value: "bar4", firstPartyDomain},
+ ], [cookie], "set: FPI on, w/ firstPartyDomain, FP cookie");
+
+ // get
+ browser.test.assertRejects(browser.cookies.get({url, name: "foo3"}),
+ expectedError,
+ "get: FPI on, w/o firstPartyDomain, rejection");
+ cookie = await browser.cookies.get({url, name: "foo4", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo4", value: "bar4", firstPartyDomain},
+ ], [cookie], "get: FPI on, w/ firstPartyDomain, FP cookie");
+ cookie = await browser.cookies.get({url, name: "foo2", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ ], [cookie], "get: FPI on, w/ firstPartyDomain, FP cookie (set when FPI off)");
+
+ // getAll
+ browser.test.assertRejects(browser.cookies.getAll({}),
+ expectedError,
+ "getAll: FPI on, w/o firstPartyDomain, rejection");
+ cookies = await browser.cookies.getAll({firstPartyDomain: null});
+ assertExpectedCookies([
+ {name: "foo1", value: "bar1", firstPartyDomain: ""},
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ {name: "foo4", value: "bar4", firstPartyDomain},
+ ], cookies, "getAll: FPI on, w/ null firstPartyDomain, all cookies");
+ cookies = await browser.cookies.getAll({firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo2", value: "bar2", firstPartyDomain},
+ {name: "foo4", value: "bar4", firstPartyDomain},
+ ], cookies, "getAll: FPI on, w/ firstPartyDomain, FP cookies");
+
+ // remove
+ browser.test.assertRejects(browser.cookies.remove({url, name: "foo3"}),
+ expectedError,
+ "remove: FPI on, w/o firstPartyDomain, rejection");
+ cookie = await browser.cookies.remove({url, name: "foo4", firstPartyDomain});
+ assertExpectedCookies([
+ {url, name: "foo4", firstPartyDomain},
+ ], [cookie], "remove: FPI on, w/ firstPartyDomain, FP cookie");
+ cookie = await browser.cookies.remove({url, name: "foo2", firstPartyDomain});
+ assertExpectedCookies([
+ {url, name: "foo2", firstPartyDomain},
+ ], [cookie], "remove: FPI on, w/ firstPartyDomain, FP cookie (set when FPI off)");
+
+ // Test if FP cookies set when FPI on can be accessed when FPI off.
+ await browser.cookies.set({url, name: "foo4", value: "bar4", firstPartyDomain});
+
+ browser.test.sendMessage("test_fpi_enabled");
+ };
+
+ // Test when FPI is disabled again, accessing FP cookies set when FPI is enabled.
+ const test_fpd_cookies_on_fpi_disabled = async () => {
+ let cookie, cookies;
+ cookie = await browser.cookies.get({url, name: "foo4", firstPartyDomain});
+ assertExpectedCookies([
+ {name: "foo4", value: "bar4", firstPartyDomain},
+ ], [cookie], "get: FPI off, w/ firstPartyDomain, FP cookie (set when FPI on)");
+ cookie = await browser.cookies.remove({url, name: "foo4", firstPartyDomain});
+ assertExpectedCookies([
+ {url, name: "foo4", firstPartyDomain},
+ ], [cookie], "remove: FPI off, w/ firstPartyDomain, FP cookie (set when FPI on)");
+
+ // Clean up.
+ await browser.cookies.remove({url, name: "foo1"});
+
+ cookies = await browser.cookies.getAll({firstPartyDomain: null});
+ assertExpectedCookies([], cookies, "Test is finishing, all cookies removed");
+
+ browser.test.sendMessage("test_fpd_cookies_on_fpi_disabled");
+ };
+
+ browser.test.onMessage.addListener((message) => {
+ switch (message) {
+ case "test_fpi_disabled": return test_fpi_disabled();
+ case "test_fpi_enabled": return test_fpi_enabled();
+ case "test_fpd_cookies_on_fpi_disabled": return test_fpd_cookies_on_fpi_disabled();
+ default: return browser.test.notifyFail("unknown-message");
+ }
+ });
+}
+
+function enableFirstPartyIsolation() {
+ return SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.firstparty.isolate", true],
+ ],
+ });
+}
+
+function disableFirstPartyIsolation() {
+ return SpecialPowers.popPrefEnv();
+}
+
+add_task(async () => {
+ let extension = ExtensionTestUtils.loadExtension({
+ background,
+ manifest: {
+ permissions: ["cookies", "*://ext-cookie-first-party.mochi.test/"],
+ },
+ });
+ await extension.startup();
+ extension.sendMessage("test_fpi_disabled");
+ await extension.awaitMessage("test_fpi_disabled");
+ await enableFirstPartyIsolation();
+ extension.sendMessage("test_fpi_enabled");
+ await extension.awaitMessage("test_fpi_enabled");
+ await disableFirstPartyIsolation();
+ extension.sendMessage("test_fpd_cookies_on_fpi_disabled");
+ await extension.awaitMessage("test_fpd_cookies_on_fpi_disabled");
+ await extension.unload();
+});
+</script>