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); +});