diff --git a/browser/components/originattributes/test/browser/browser_blobURLIsolation.js b/browser/components/originattributes/test/browser/browser_blobURLIsolation.js
index 4777223c2827..fe3ea6506f1c 100644
--- a/browser/components/originattributes/test/browser/browser_blobURLIsolation.js
+++ b/browser/components/originattributes/test/browser/browser_blobURLIsolation.js
@@ -114,7 +114,7 @@ for (let blobify of [page_blobify, worker_blobify]) {
async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
- ["privacy.partition.bloburl_per_agent_cluster", false],
+ ["privacy.partition.bloburl_per_partition_key", false],
["dom.security.https_first", false],
],
});
diff --git a/toolkit/components/antitracking/test/browser/blobPartitionPage.html b/toolkit/components/antitracking/test/browser/blobPartitionPage.html
new file mode 100644
index 000000000000..d0dd156bc51e
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/blobPartitionPage.html
@@ -0,0 +1,26 @@
+
+
+
+ Blob URL Partitioning Test
+
+
+
+
+
diff --git a/toolkit/components/antitracking/test/browser/browser.ini b/toolkit/components/antitracking/test/browser/browser.ini
index 4003046eb7ae..d181f78dd0ca 100644
--- a/toolkit/components/antitracking/test/browser/browser.ini
+++ b/toolkit/components/antitracking/test/browser/browser.ini
@@ -56,6 +56,7 @@ support-files =
3rdPartyStorageWO.html
3rdPartyPartitioned.html
localStorage.html
+ blobPartitionPage.html
raptor.jpg
!/browser/modules/test/browser/head.js
!/browser/base/content/test/general/head.js
@@ -165,6 +166,7 @@ support-files = cookies.sjs
support-files = dedicatedWorker.js matchAll.js serviceWorker.js
[browser_partitionedSharedWorkers.js]
support-files = sharedWorker.js partitionedSharedWorker.js
+[browser_partitionkey_bloburl.js]
[browser_PBMCookieBehavior.js]
[browser_socialtracking.js]
[browser_socialtracking_save_image.js]
diff --git a/toolkit/components/antitracking/test/browser/browser_partitionkey_bloburl.js b/toolkit/components/antitracking/test/browser/browser_partitionkey_bloburl.js
new file mode 100644
index 000000000000..83f7ce37d1e1
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/browser_partitionkey_bloburl.js
@@ -0,0 +1,196 @@
+const BASE_URI =
+ "https://example.net/browser/toolkit/components/antitracking/test/browser/blobPartitionPage.html";
+const EMPTY_URI =
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "https://example.com/browser/toolkit/components/antitracking/test/browser/empty.html";
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.partition.bloburl_per_partition_key", true],
+ ["privacy.partition.bloburl_per_agent_cluster", false],
+ ],
+ });
+});
+
+// Ensuring Blob URL cannot be resolved under a different
+// top-level domain other than its original creation top-level domain
+add_task(async function test_different_tld_with_iframe() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+ let blobURL = await SpecialPowers.spawn(browser1, [], function () {
+ return content.URL.createObjectURL(new content.Blob(["hello world!"]));
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, EMPTY_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ await SpecialPowers.spawn(
+ browser2,
+ [
+ {
+ page: BASE_URI,
+ blob: blobURL,
+ },
+ ],
+ async obj => {
+ let ifr = content.document.createElement("iframe");
+ ifr.setAttribute("id", "ifr");
+ ifr.setAttribute("src", obj.page);
+
+ info("Iframe loading...");
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ });
+
+ let value = await new content.Promise(resolve => {
+ content.addEventListener(
+ "message",
+ e => {
+ resolve(e.data == "error");
+ },
+ { once: true }
+ );
+ ifr.contentWindow.postMessage(obj.blob, "*");
+ });
+
+ ok(value, "Blob URL was unable to be resolved");
+ }
+ );
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Ensuring if Blob URL can be resolved if a domain1 creates a blob URL
+// and domain1 trys to resolve blob URL within an iframe of itself
+add_task(async function test_same_tld_with_iframe() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+ let blobURL = await SpecialPowers.spawn(browser1, [], function () {
+ return content.URL.createObjectURL(new content.Blob(["hello world!"]));
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ await SpecialPowers.spawn(
+ browser2,
+ [
+ {
+ page: BASE_URI,
+ blob: blobURL,
+ },
+ ],
+ async obj => {
+ let ifr = content.document.createElement("iframe");
+ ifr.setAttribute("id", "ifr");
+ ifr.setAttribute("src", obj.page);
+
+ info("Iframe loading...");
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ });
+
+ let value = await new content.Promise(resolve => {
+ content.addEventListener(
+ "message",
+ e => {
+ resolve(e.data == "hello world!");
+ },
+ { once: true }
+ );
+ ifr.contentWindow.postMessage(obj.blob, "*");
+ });
+
+ ok(value, "Blob URL was able to be resolved");
+ }
+ );
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Ensuring Blob URL can be resolved in an iframe
+// under the same top-level domain where it creates.
+add_task(async function test_no_iframes_same_tld() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let blobURL = await SpecialPowers.spawn(browser1, [], function () {
+ return content.URL.createObjectURL(new content.Blob(["hello world!"]));
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(
+ browser2,
+ [blobURL],
+ function (blobURL) {
+ return new content.Promise(resolve => {
+ var xhr = new content.XMLHttpRequest();
+ xhr.open("GET", blobURL);
+ xhr.onloadend = function () {
+ resolve(xhr.response == "hello world!");
+ };
+
+ xhr.send();
+ });
+ }
+ );
+
+ ok(status, "Blob URL was able to be resolved");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Ensuring Blob URL can be resolved in a sandboxed
+// iframe under the top-level domain where it creates.
+add_task(async function test_same_tld_with_iframe() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+ let blobURL = await SpecialPowers.spawn(browser1, [], function () {
+ return content.URL.createObjectURL(new content.Blob(["hello world!"]));
+ });
+
+ await SpecialPowers.spawn(
+ browser1,
+ [
+ {
+ page: BASE_URI,
+ blob: blobURL,
+ },
+ ],
+ async obj => {
+ let ifr = content.document.createElement("iframe");
+ ifr.setAttribute("id", "ifr");
+ ifr.setAttribute("sandbox", "allow-scripts allow-same-origin");
+ ifr.setAttribute("src", obj.page);
+
+ info("Iframe loading...");
+ await new content.Promise(resolve => {
+ ifr.onload = resolve;
+ content.document.body.appendChild(ifr);
+ });
+
+ let value = await new content.Promise(resolve => {
+ content.addEventListener(
+ "message",
+ e => {
+ resolve(e.data == "hello world!");
+ },
+ { once: true }
+ );
+ ifr.contentWindow.postMessage(obj.blob, "*");
+ });
+
+ ok(value, "Blob URL was able to be resolved");
+ }
+ );
+
+ BrowserTestUtils.removeTab(tab1);
+});