diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.js b/browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.js
index 4229e3a0d349..edbd64528d67 100644
--- a/browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.js
+++ b/browser/base/content/test/contextMenu/browser_contextmenu_loadblobinnewtab.js
@@ -135,12 +135,6 @@ async function openInNewTabAndReturnContent(selector) {
return blobDataFromContent;
}
-add_task(async function setup() {
- await SpecialPowers.pushPrefEnv({
- set: [["privacy.partition.bloburl_per_agent_cluster", false]],
- });
-});
-
add_task(async function test_rightclick_open_bloburl_in_new_tab() {
let blobDataFromLoadedPage = await rightClickOpenInNewTabAndReturnContent(
"blob-url-link"
diff --git a/dom/file/ipc/tests/browser_ipcBlob.js b/dom/file/ipc/tests/browser_ipcBlob.js
index 3ba0f05c9039..ee99131d411e 100644
--- a/dom/file/ipc/tests/browser_ipcBlob.js
+++ b/dom/file/ipc/tests/browser_ipcBlob.js
@@ -4,12 +4,6 @@ requestLongerTimeout(3);
const BASE_URI = "http://mochi.test:8888/browser/dom/file/ipc/tests/empty.html";
-add_task(async function setup() {
- await SpecialPowers.pushPrefEnv({
- set: [["privacy.partition.bloburl_per_agent_cluster", false]],
- });
-});
-
// More than 1mb memory blob childA-parent-childB.
add_task(async function test_CtoPtoC_big() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
diff --git a/dom/file/tests/test_agentcluster_bloburl.js b/dom/file/tests/test_agentcluster_bloburl.js
deleted file mode 100644
index cfb6013ab284..000000000000
--- a/dom/file/tests/test_agentcluster_bloburl.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-const { CookieXPCShellUtils } = ChromeUtils.import(
- "resource://testing-common/CookieXPCShellUtils.jsm"
-);
-
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-CookieXPCShellUtils.init(this);
-
-// Same agent cluster, all works fine: blobURLs can be opened.
-add_task(async () => {
- do_get_profile();
-
- Services.prefs.setBoolPref(
- "privacy.partition.bloburl_per_agent_cluster",
- true
- );
-
- const server = CookieXPCShellUtils.createServer({ hosts: ["example.org"] });
-
- let result = new Promise(resolve => {
- server.registerPathHandler("/result", (metadata, response) => {
- resolve(metadata.queryString == "ok");
-
- const body = "Done";
- response.bodyOutputStream.write(body, body.length);
- });
- });
-
- server.registerPathHandler("/test", (metadata, response) => {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = ``;
- response.bodyOutputStream.write(body, body.length);
- });
-
- let contentPage = await CookieXPCShellUtils.loadContentPage(
- "http://example.org/test"
- );
-
- Assert.ok(await result, "BlobURL works");
- await contentPage.close();
-});
-
-// Same agent cluster: frames
-add_task(async () => {
- do_get_profile();
-
- const server = CookieXPCShellUtils.createServer({ hosts: ["example.org"] });
-
- let result = new Promise(resolve => {
- server.registerPathHandler("/result", (metadata, response) => {
- resolve(metadata.queryString == "ok");
-
- const body = "Done";
- response.bodyOutputStream.write(body, body.length);
- });
- });
-
- server.registerPathHandler("/iframe", (metadata, response) => {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = ``;
- response.bodyOutputStream.write(body, body.length);
- });
-
- server.registerPathHandler("/test", (metadata, response) => {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = ``;
- response.bodyOutputStream.write(body, body.length);
- });
-
- let contentPage = await CookieXPCShellUtils.loadContentPage(
- "http://example.org/test"
- );
-
- Assert.ok(await result, "BlobURL works");
- await contentPage.close();
-});
-
-// Cross agent cluster: different tabs
-add_task(async () => {
- do_get_profile();
-
- const server = CookieXPCShellUtils.createServer({ hosts: ["example.org"] });
-
- let result = new Promise(resolve => {
- server.registerPathHandler("/result", (metadata, response) => {
- resolve(metadata.queryString == "ok");
-
- const body = "Done";
- response.bodyOutputStream.write(body, body.length);
- });
- });
-
- const step = new Promise(resolve => {
- server.registerPathHandler("/step", (metadata, response) => {
- resolve(metadata.queryString);
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = "Thanks!";
- response.bodyOutputStream.write(body, body.length);
- });
- });
-
- server.registerPathHandler("/test", (metadata, response) => {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = ``;
- response.bodyOutputStream.write(body, body.length);
- });
-
- let contentPage = await CookieXPCShellUtils.loadContentPage(
- "http://example.org/test"
- );
-
- const blobURL = await step;
- Assert.ok(blobURL.length, "We have a blobURL");
-
- server.registerPathHandler("/cross-test", (metadata, response) => {
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "text/html", false);
- const body = ``;
- response.bodyOutputStream.write(body, body.length);
- });
-
- let contentPage2 = await CookieXPCShellUtils.loadContentPage(
- "http://example.org/cross-test?" + blobURL
- );
-
- Assert.ok(!(await result), "BlobURL should not work");
- await contentPage.close();
- await contentPage2.close();
-});
diff --git a/dom/file/tests/xpcshell.ini b/dom/file/tests/xpcshell.ini
index 978377cdc17a..dc9faecf8c45 100644
--- a/dom/file/tests/xpcshell.ini
+++ b/dom/file/tests/xpcshell.ini
@@ -4,4 +4,3 @@
[test_createFile.js]
[test_ipc_messagemanager_blob.js]
skip-if = os == "android"
-[test_agentcluster_bloburl.js]
diff --git a/dom/file/uri/BlobURLInputStream.cpp b/dom/file/uri/BlobURLInputStream.cpp
index cff4ab51a616..eda701a9edab 100644
--- a/dom/file/uri/BlobURLInputStream.cpp
+++ b/dom/file/uri/BlobURLInputStream.cpp
@@ -363,25 +363,47 @@ void BlobURLInputStream::RetrieveBlobData(const MutexAutoLock& aProofOfLock) {
return;
}
- Maybe agentClusterId;
- Maybe clientInfo = loadInfo->GetClientInfo();
- if (clientInfo.isSome()) {
- agentClusterId = clientInfo->AgentClusterId();
- }
-
if (XRE_IsParentProcess() || !BlobURLSchemeIsHTTPOrHTTPS(mBlobURLSpec)) {
- RefPtr blobImpl;
+ nsIPrincipal* const dataEntryPrincipal =
+ BlobURLProtocolHandler::GetDataEntryPrincipal(mBlobURLSpec,
+ true /* AlsoIfRevoked */);
// Since revoked blobs are also retrieved, it is possible that the blob no
// longer exists (due to the 5 second timeout) when execution reaches here
- if (!BlobURLProtocolHandler::GetDataEntry(
- mBlobURLSpec, getter_AddRefs(blobImpl), loadingPrincipal,
- triggeringPrincipal, loadInfo->GetOriginAttributes(),
- agentClusterId, true /* AlsoIfRevoked */)) {
+ if (!dataEntryPrincipal) {
NS_WARNING("Failed to get data entry principal. URL revoked?");
return;
}
+ // We want to be sure that we stop the creation of the channel if the blob
+ // URL is copy-and-pasted on a different context (ex. private browsing or
+ // containers).
+ //
+ // We also allow the system principal to create the channel regardless of
+ // the OriginAttributes. This is primarily for the benefit of mechanisms
+ // like the Download API that explicitly create a channel with the system
+ // principal and which is never mutated to have a non-zero
+ // mPrivateBrowsingId or container.
+ if (NS_WARN_IF(!loadingPrincipal ||
+ !loadingPrincipal->IsSystemPrincipal()) &&
+ NS_WARN_IF(!ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
+ loadInfo->GetOriginAttributes(),
+ BasePrincipal::Cast(dataEntryPrincipal)->OriginAttributesRef()))) {
+ return;
+ }
+
+ if (NS_WARN_IF(!triggeringPrincipal->Subsumes(dataEntryPrincipal))) {
+ return;
+ }
+
+ RefPtr blobImpl;
+ nsresult rv = NS_GetBlobForBlobURISpec(
+ mBlobURLSpec, getter_AddRefs(blobImpl), true /* AlsoIfRevoked */);
+
+ if (NS_WARN_IF(NS_FAILED(rv)) || (NS_WARN_IF(!blobImpl))) {
+ return;
+ }
+
if (NS_WARN_IF(
NS_FAILED(StoreBlobImplStream(blobImpl.forget(), aProofOfLock)))) {
return;
@@ -409,7 +431,7 @@ void BlobURLInputStream::RetrieveBlobData(const MutexAutoLock& aProofOfLock) {
contentChild
->SendBlobURLDataRequest(mBlobURLSpec, triggeringPrincipal,
loadingPrincipal,
- loadInfo->GetOriginAttributes(), agentClusterId)
+ loadInfo->GetOriginAttributes())
->Then(
GetCurrentSerialEventTarget(), __func__,
[self](const BlobURLDataRequestResult& aResult) {
diff --git a/dom/file/uri/BlobURLProtocolHandler.cpp b/dom/file/uri/BlobURLProtocolHandler.cpp
index 3e12804ce697..ae871d900e30 100644
--- a/dom/file/uri/BlobURLProtocolHandler.cpp
+++ b/dom/file/uri/BlobURLProtocolHandler.cpp
@@ -19,7 +19,6 @@
#include "mozilla/BasePrincipal.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/NullPrincipal.h"
-#include "mozilla/OriginAttributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/SchedulerGroup.h"
#include "nsClassHashtable.h"
@@ -46,22 +45,18 @@ namespace dom {
struct DataInfo {
enum ObjectType { eBlobImpl, eMediaSource };
- DataInfo(BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId)
+ DataInfo(BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal)
: mObjectType(eBlobImpl),
mBlobImpl(aBlobImpl),
mPrincipal(aPrincipal),
- mAgentClusterId(aAgentClusterId),
mRevoked(false) {
MOZ_ASSERT(aPrincipal);
}
- DataInfo(MediaSource* aMediaSource, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId)
+ DataInfo(MediaSource* aMediaSource, nsIPrincipal* aPrincipal)
: mObjectType(eMediaSource),
mMediaSource(aMediaSource),
mPrincipal(aPrincipal),
- mAgentClusterId(aAgentClusterId),
mRevoked(false) {
MOZ_ASSERT(aPrincipal);
}
@@ -72,8 +67,6 @@ struct DataInfo {
RefPtr mMediaSource;
nsCOMPtr mPrincipal;
- Maybe mAgentClusterId;
-
nsCString mStack;
// When a blobURL is revoked, we keep it alive for RELEASING_TIMER
@@ -131,15 +124,14 @@ static DataInfo* GetDataInfoFromURI(nsIURI* aURI, bool aAlsoIfRevoked = false) {
// Memory reporting for the hash table.
void BroadcastBlobURLRegistration(const nsACString& aURI, BlobImpl* aBlobImpl,
- nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId) {
+ nsIPrincipal* aPrincipal) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobImpl);
MOZ_ASSERT(aPrincipal);
if (XRE_IsParentProcess()) {
- dom::ContentParent::BroadcastBlobURLRegistration(
- aURI, aBlobImpl, aPrincipal, aAgentClusterId);
+ dom::ContentParent::BroadcastBlobURLRegistration(aURI, aBlobImpl,
+ aPrincipal);
return;
}
@@ -152,7 +144,7 @@ void BroadcastBlobURLRegistration(const nsACString& aURI, BlobImpl* aBlobImpl,
}
Unused << NS_WARN_IF(!cc->SendStoreAndBroadcastBlobURLRegistration(
- nsCString(aURI), ipcBlob, IPC::Principal(aPrincipal), aAgentClusterId));
+ nsCString(aURI), ipcBlob, IPC::Principal(aPrincipal)));
}
void BroadcastBlobURLUnregistration(const nsCString& aURI,
@@ -518,15 +510,14 @@ NS_IMPL_ISUPPORTS_INHERITED(ReleasingTimerHolder, Runnable, nsITimerCallback,
template
static void AddDataEntryInternal(const nsACString& aURI, T aObject,
- nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId) {
+ nsIPrincipal* aPrincipal) {
MOZ_ASSERT(NS_IsMainThread(), "changing gDataTable is main-thread only");
StaticMutexAutoLock lock(sMutex);
if (!gDataTable) {
gDataTable = new nsClassHashtable;
}
- DataInfo* info = new DataInfo(aObject, aPrincipal, aAgentClusterId);
+ DataInfo* info = new DataInfo(aObject, aPrincipal);
BlobURLsReporter::GetJSStackForBlob(info);
gDataTable->Put(aURI, info);
@@ -546,9 +537,9 @@ BlobURLProtocolHandler::BlobURLProtocolHandler() { Init(); }
BlobURLProtocolHandler::~BlobURLProtocolHandler() = default;
/* static */
-nsresult BlobURLProtocolHandler::AddDataEntry(
- BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId, nsACString& aUri) {
+nsresult BlobURLProtocolHandler::AddDataEntry(BlobImpl* aBlobImpl,
+ nsIPrincipal* aPrincipal,
+ nsACString& aUri) {
MOZ_ASSERT(aBlobImpl);
MOZ_ASSERT(aPrincipal);
@@ -557,16 +548,16 @@ nsresult BlobURLProtocolHandler::AddDataEntry(
nsresult rv = GenerateURIString(aPrincipal, aUri);
NS_ENSURE_SUCCESS(rv, rv);
- AddDataEntryInternal(aUri, aBlobImpl, aPrincipal, aAgentClusterId);
+ AddDataEntryInternal(aUri, aBlobImpl, aPrincipal);
- BroadcastBlobURLRegistration(aUri, aBlobImpl, aPrincipal, aAgentClusterId);
+ BroadcastBlobURLRegistration(aUri, aBlobImpl, aPrincipal);
return NS_OK;
}
/* static */
-nsresult BlobURLProtocolHandler::AddDataEntry(
- MediaSource* aMediaSource, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId, nsACString& aUri) {
+nsresult BlobURLProtocolHandler::AddDataEntry(MediaSource* aMediaSource,
+ nsIPrincipal* aPrincipal,
+ nsACString& aUri) {
MOZ_ASSERT(aMediaSource);
MOZ_ASSERT(aPrincipal);
@@ -575,24 +566,23 @@ nsresult BlobURLProtocolHandler::AddDataEntry(
nsresult rv = GenerateURIString(aPrincipal, aUri);
NS_ENSURE_SUCCESS(rv, rv);
- AddDataEntryInternal(aUri, aMediaSource, aPrincipal, aAgentClusterId);
+ AddDataEntryInternal(aUri, aMediaSource, aPrincipal);
return NS_OK;
}
/* static */
void BlobURLProtocolHandler::AddDataEntry(const nsACString& aURI,
nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId,
BlobImpl* aBlobImpl) {
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aBlobImpl);
- AddDataEntryInternal(aURI, aBlobImpl, aPrincipal, aAgentClusterId);
+ AddDataEntryInternal(aURI, aBlobImpl, aPrincipal);
}
/* static */
bool BlobURLProtocolHandler::ForEachBlobURL(
- std::function&,
- const nsACString&, bool aRevoked)>&& aCb) {
+ std::function&& aCb) {
MOZ_ASSERT(NS_IsMainThread());
if (!gDataTable) {
@@ -608,8 +598,7 @@ bool BlobURLProtocolHandler::ForEachBlobURL(
}
MOZ_ASSERT(info->mBlobImpl);
- if (!aCb(info->mBlobImpl, info->mPrincipal, info->mAgentClusterId,
- iter.Key(), info->mRevoked)) {
+ if (!aCb(info->mBlobImpl, info->mPrincipal, iter.Key(), info->mRevoked)) {
return false;
}
}
@@ -644,34 +633,6 @@ void BlobURLProtocolHandler::RemoveDataEntry(const nsACString& aUri,
ReleasingTimerHolder::Create(aUri);
}
-/*static */
-bool BlobURLProtocolHandler::RemoveDataEntry(
- const nsACString& aUri, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId) {
- MOZ_ASSERT(NS_IsMainThread(), "changing gDataTable is main-thread only");
- if (!gDataTable) {
- return false;
- }
-
- DataInfo* info = GetDataInfo(aUri);
- if (!info) {
- return false;
- }
-
- if (!aPrincipal || !aPrincipal->Subsumes(info->mPrincipal)) {
- return false;
- }
-
- if (StaticPrefs::privacy_partition_bloburl_per_agent_cluster() &&
- aAgentClusterId.isSome() && info->mAgentClusterId.isSome() &&
- !aAgentClusterId.value().Equals(info->mAgentClusterId.value())) {
- return false;
- }
-
- RemoveDataEntry(aUri, true);
- return true;
-}
-
/* static */
void BlobURLProtocolHandler::RemoveDataEntries() {
MOZ_ASSERT(NS_IsMainThread(), "changing gDataTable is main-thread only");
@@ -727,57 +688,21 @@ nsresult BlobURLProtocolHandler::GenerateURIString(nsIPrincipal* aPrincipal,
}
/* static */
-bool BlobURLProtocolHandler::GetDataEntry(
- const nsACString& aUri, BlobImpl** aBlobImpl,
- nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal,
- const OriginAttributes& aOriginAttributes,
- const Maybe& aAgentClusterId, bool aAlsoIfRevoked) {
+nsIPrincipal* BlobURLProtocolHandler::GetDataEntryPrincipal(
+ const nsACString& aUri, bool aAlsoIfRevoked) {
MOZ_ASSERT(NS_IsMainThread(),
"without locking gDataTable is main-thread only");
- MOZ_ASSERT(aTriggeringPrincipal);
-
if (!gDataTable) {
- return false;
+ return nullptr;
}
- DataInfo* info = GetDataInfo(aUri, aAlsoIfRevoked);
- if (!info) {
- return false;
+ DataInfo* res = GetDataInfo(aUri, aAlsoIfRevoked);
+
+ if (!res) {
+ return nullptr;
}
- // We want to be sure that we stop the creation of the channel if the blob
- // URL is copy-and-pasted on a different context (ex. private browsing or
- // containers).
- //
- // We also allow the system principal to create the channel regardless of
- // the OriginAttributes. This is primarily for the benefit of mechanisms
- // like the Download API that explicitly create a channel with the system
- // principal and which is never mutated to have a non-zero
- // mPrivateBrowsingId or container.
-
- if (NS_WARN_IF(!aLoadingPrincipal ||
- !aLoadingPrincipal->IsSystemPrincipal()) &&
- NS_WARN_IF(!ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
- aOriginAttributes,
- BasePrincipal::Cast(info->mPrincipal)->OriginAttributesRef()))) {
- return false;
- }
-
- if (!aTriggeringPrincipal->Subsumes(info->mPrincipal)) {
- return false;
- }
-
- // BlobURLs are openable on the same agent-cluster-id only.
- if (StaticPrefs::privacy_partition_bloburl_per_agent_cluster() &&
- aAgentClusterId.isSome() && info->mAgentClusterId.isSome() &&
- !aAgentClusterId.value().Equals(info->mAgentClusterId.value())) {
- return false;
- }
-
- RefPtr blobImpl = info->mBlobImpl;
- blobImpl.forget(aBlobImpl);
-
- return true;
+ return res->mPrincipal;
}
/* static */
diff --git a/dom/file/uri/BlobURLProtocolHandler.h b/dom/file/uri/BlobURLProtocolHandler.h
index deca62826475..b9a97687c6ae 100644
--- a/dom/file/uri/BlobURLProtocolHandler.h
+++ b/dom/file/uri/BlobURLProtocolHandler.h
@@ -21,7 +21,6 @@ class nsIPrincipal;
namespace mozilla {
class BlobURLsReporter;
-class OriginAttributes;
namespace dom {
@@ -45,37 +44,23 @@ class BlobURLProtocolHandler final : public nsIProtocolHandler,
// Methods for managing uri->object mapping
// AddDataEntry creates the URI with the given scheme and returns it in aUri
- static nsresult AddDataEntry(BlobImpl*, nsIPrincipal*,
- const Maybe& aAgentClusterId,
- nsACString& aUri);
- static nsresult AddDataEntry(MediaSource*, nsIPrincipal*,
- const Maybe& aAgentClusterId,
- nsACString& aUri);
+ static nsresult AddDataEntry(BlobImpl*, nsIPrincipal*, nsACString& aUri);
+ static nsresult AddDataEntry(MediaSource*, nsIPrincipal*, nsACString& aUri);
// IPC only
- static void AddDataEntry(const nsACString& aURI, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId,
- BlobImpl* aBlobImpl);
+ static void AddDataEntry(const nsACString& aURI, nsIPrincipal*, BlobImpl*);
- // These methods revoke a blobURL. Because some operations could still be in
+ // This method revokes a blobURL. Because some operations could still be in
// progress, the revoking consists in marking the blobURL as revoked and in
// removing it after RELEASING_TIMER milliseconds.
static void RemoveDataEntry(const nsACString& aUri,
bool aBroadcastToOTherProcesses = true);
- // Returns true if the entry was allowed to be removed.
- static bool RemoveDataEntry(const nsACString& aUri, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId);
static void RemoveDataEntries();
static bool HasDataEntry(const nsACString& aUri);
- static bool GetDataEntry(const nsACString& aUri, BlobImpl** aBlobImpl,
- nsIPrincipal* aLoadingPrincipal,
- nsIPrincipal* aTriggeringPrincipal,
- const OriginAttributes& aOriginAttributes,
- const Maybe& blobAgentClusterId,
- bool aAlsoIfRevoked = false);
-
+ static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri,
+ bool aAlsoIfRevoked = false);
static void Traverse(const nsACString& aUri,
nsCycleCollectionTraversalCallback& aCallback);
@@ -85,8 +70,8 @@ class BlobURLProtocolHandler final : public nsIProtocolHandler,
// of an unexpected XPCOM or IPC error). This method returns false if already
// shutdown or if the helper method returns false, true otherwise.
static bool ForEachBlobURL(
- std::function&,
- const nsACString&, bool aRevoked)>&& aCb);
+ std::function&& aCb);
// This method returns false if aURI is not a known BlobURL. Otherwise it
// returns true.
diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp
index 1e591c0e9085..3a25904c0e2d 100644
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2648,9 +2648,8 @@ mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs(
RefPtr blobImpl = IPCBlobUtils::Deserialize(registration.blob());
MOZ_ASSERT(blobImpl);
- BlobURLProtocolHandler::AddDataEntry(
- registration.url(), registration.principal(),
- registration.agentClusterId(), blobImpl);
+ BlobURLProtocolHandler::AddDataEntry(registration.url(),
+ registration.principal(), blobImpl);
// If we have received an already-revoked blobURL, we have to keep it alive
// for a while (see BlobURLProtocolHandler) in order to support pending
// operations such as navigation, download and so on.
@@ -3140,12 +3139,11 @@ ContentChild::RecvNotifyPushSubscriptionModifiedObservers(
mozilla::ipc::IPCResult ContentChild::RecvBlobURLRegistration(
const nsCString& aURI, const IPCBlob& aBlob,
- const IPC::Principal& aPrincipal, const Maybe& aAgentClusterId) {
+ const IPC::Principal& aPrincipal) {
RefPtr blobImpl = IPCBlobUtils::Deserialize(aBlob);
MOZ_ASSERT(blobImpl);
- BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aAgentClusterId,
- blobImpl);
+ BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, blobImpl);
return IPC_OK();
}
diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h
index 5a0ddaf43146..e6e3a7f8999c 100644
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -528,7 +528,7 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvBlobURLRegistration(
const nsCString& aURI, const IPCBlob& aBlob,
- const IPC::Principal& aPrincipal, const Maybe& aAgentClusterId);
+ const IPC::Principal& aPrincipal);
mozilla::ipc::IPCResult RecvBlobURLUnregistration(const nsCString& aURI);
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index b8f1e4e0565f..5bde85da2921 100644
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2866,8 +2866,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
nsTArray registrations;
BlobURLProtocolHandler::ForEachBlobURL(
[&](BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId, const nsACString& aURI,
- bool aRevoked) {
+ const nsACString& aURI, bool aRevoked) {
nsAutoCString origin;
nsresult rv = aPrincipal->GetOrigin(origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -2891,7 +2890,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
}
registrations.AppendElement(BlobURLRegistrationData(
- nsCString(aURI), ipcBlob, aPrincipal, aAgentClusterId, aRevoked));
+ nsCString(aURI), ipcBlob, aPrincipal, aRevoked));
rv = TransmitPermissionsForPrincipal(aPrincipal);
Unused << NS_WARN_IF(NS_FAILED(rv));
@@ -5492,9 +5491,10 @@ ContentParent::RecvNotifyPushSubscriptionModifiedObservers(
}
/* static */
-void ContentParent::BroadcastBlobURLRegistration(
- const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId, ContentParent* aIgnoreThisCP) {
+void ContentParent::BroadcastBlobURLRegistration(const nsACString& aURI,
+ BlobImpl* aBlobImpl,
+ nsIPrincipal* aPrincipal,
+ ContentParent* aIgnoreThisCP) {
nsAutoCString origin;
nsresult rv = aPrincipal->GetOrigin(origin);
NS_ENSURE_SUCCESS_VOID(rv);
@@ -5524,8 +5524,7 @@ void ContentParent::BroadcastBlobURLRegistration(
break;
}
- Unused << cp->SendBlobURLRegistration(uri, ipcBlob, principal,
- aAgentClusterId);
+ Unused << cp->SendBlobURLRegistration(uri, ipcBlob, principal);
}
}
}
@@ -5554,18 +5553,14 @@ void ContentParent::BroadcastBlobURLUnregistration(
}
mozilla::ipc::IPCResult ContentParent::RecvStoreAndBroadcastBlobURLRegistration(
- const nsCString& aURI, const IPCBlob& aBlob, const Principal& aPrincipal,
- const Maybe& aAgentClusterId) {
+ const nsCString& aURI, const IPCBlob& aBlob, const Principal& aPrincipal) {
RefPtr blobImpl = IPCBlobUtils::Deserialize(aBlob);
if (NS_WARN_IF(!blobImpl)) {
return IPC_FAIL_NO_REASON(this);
}
- BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aAgentClusterId,
- blobImpl);
- BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, aAgentClusterId,
- this);
-
+ BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, blobImpl);
+ BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, this);
// We want to store this blobURL, so we can unregister it if the child
// crashes.
mBlobURLs.AppendElement(aURI);
@@ -5806,8 +5801,7 @@ void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal) {
nsTArray registrations;
BlobURLProtocolHandler::ForEachBlobURL(
[&](BlobImpl* aBlobImpl, nsIPrincipal* aBlobPrincipal,
- const Maybe& aAgentClusterId, const nsACString& aURI,
- bool aRevoked) {
+ const nsACString& aURI, bool aRevoked) {
if (!aPrincipal->Subsumes(aBlobPrincipal)) {
return true;
}
@@ -5819,7 +5813,7 @@ void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal) {
}
registrations.AppendElement(BlobURLRegistrationData(
- nsCString(aURI), ipcBlob, aPrincipal, aAgentClusterId, aRevoked));
+ nsCString(aURI), ipcBlob, aPrincipal, aRevoked));
rv = TransmitPermissionsForPrincipal(aPrincipal);
Unused << NS_WARN_IF(NS_FAILED(rv));
@@ -6832,24 +6826,60 @@ PFileDescriptorSetParent* ContentParent::SendPFileDescriptorSetConstructor(
}
mozilla::ipc::IPCResult ContentParent::RecvBlobURLDataRequest(
- const nsCString& aBlobURL, nsIPrincipal* aTriggeringPrincipal,
- nsIPrincipal* aLoadingPrincipal, const OriginAttributes& aOriginAttributes,
- const Maybe& aAgentClusterId,
+ const nsCString& aBlobURL, nsIPrincipal* pTriggeringPrincipal,
+ nsIPrincipal* pLoadingPrincipal, const OriginAttributes& aOriginAttributes,
BlobURLDataRequestResolver&& aResolver) {
RefPtr blobImpl;
+ nsresult rv = NS_GetBlobForBlobURISpec(aBlobURL, getter_AddRefs(blobImpl),
+ true /* AlsoIfRevoked */);
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aResolver(rv);
+ return IPC_OK();
+ }
+
+ if (NS_WARN_IF(!blobImpl)) {
+ aResolver(NS_ERROR_DOM_BAD_URI);
+ return IPC_OK();
+ }
// Since revoked blobs are also retrieved, it is possible that the blob no
// longer exists (due to the 5 second timeout) when execution reaches here
- if (!BlobURLProtocolHandler::GetDataEntry(
- aBlobURL, getter_AddRefs(blobImpl), aLoadingPrincipal,
- aTriggeringPrincipal, aOriginAttributes, aAgentClusterId,
- true /* AlsoIfRevoked */)) {
+ nsIPrincipal* const dataEntryPrincipal =
+ BlobURLProtocolHandler::GetDataEntryPrincipal(aBlobURL,
+ true /* AlsoIfRevoked */);
+
+ if (!dataEntryPrincipal) {
+ aResolver(NS_ERROR_DOM_BAD_URI);
+ return IPC_OK();
+ }
+
+ // We want to be sure that we stop the creation of the channel if the blob
+ // URL is copy-and-pasted on a different context (ex. private browsing or
+ // containers).
+ //
+ // We also allow the system principal to create the channel regardless of
+ // the OriginAttributes. This is primarily for the benefit of mechanisms
+ // like the Download API that explicitly create a channel with the system
+ // principal and which is never mutated to have a non-zero
+ // mPrivateBrowsingId or container.
+
+ if (NS_WARN_IF(!pLoadingPrincipal ||
+ !pLoadingPrincipal->IsSystemPrincipal()) &&
+ NS_WARN_IF(!ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
+ aOriginAttributes,
+ BasePrincipal::Cast(dataEntryPrincipal)->OriginAttributesRef()))) {
+ aResolver(NS_ERROR_DOM_BAD_URI);
+ return IPC_OK();
+ }
+
+ if (!pTriggeringPrincipal->Subsumes(dataEntryPrincipal)) {
aResolver(NS_ERROR_DOM_BAD_URI);
return IPC_OK();
}
IPCBlob ipcBlob;
- nsresult rv = IPCBlobUtils::Serialize(blobImpl, this, ipcBlob);
+ rv = IPCBlobUtils::Serialize(blobImpl, this, ipcBlob);
if (NS_WARN_IF(NS_FAILED(rv))) {
aResolver(rv);
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
index 59f88cf0c5c7..8ca49a475fde 100644
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -548,7 +548,6 @@ class ContentParent final
static void BroadcastBlobURLRegistration(
const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
- const Maybe& aAgentClusterId,
ContentParent* aIgnoreThisCP = nullptr);
static void BroadcastBlobURLUnregistration(
@@ -556,8 +555,7 @@ class ContentParent final
ContentParent* aIgnoreThisCP = nullptr);
mozilla::ipc::IPCResult RecvStoreAndBroadcastBlobURLRegistration(
- const nsCString& aURI, const IPCBlob& aBlob, const Principal& aPrincipal,
- const Maybe& aAgentCluster);
+ const nsCString& aURI, const IPCBlob& aBlob, const Principal& aPrincipal);
mozilla::ipc::IPCResult RecvUnstoreAndBroadcastBlobURLUnregistration(
const nsCString& aURI, const Principal& aPrincipal);
@@ -703,7 +701,6 @@ class ContentParent final
const nsCString& aBlobURL, nsIPrincipal* pTriggeringPrincipal,
nsIPrincipal* pLoadingPrincipal,
const OriginAttributes& aOriginAttributes,
- const Maybe& aAgentClusterId,
BlobURLDataRequestResolver&& aResolver);
protected:
diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl
index 0ee444f4dff1..72708034eb6a 100644
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -235,7 +235,6 @@ struct BlobURLRegistrationData
nsCString url;
IPCBlob blob;
nsIPrincipal principal;
- nsID? agentClusterId;
bool revoked;
};
@@ -750,8 +749,7 @@ child:
async GetFilesResponse(nsID aID, GetFilesResponseResult aResult);
async BlobURLRegistration(nsCString aURI, IPCBlob aBlob,
- Principal aPrincipal,
- nsID? aAgentClusterId);
+ Principal aPrincipal);
async BlobURLUnregistration(nsCString aURI);
@@ -1491,8 +1489,7 @@ parent:
async DeleteGetFilesRequest(nsID aID);
async StoreAndBroadcastBlobURLRegistration(nsCString url, IPCBlob blob,
- Principal principal,
- nsID? aAgentClusterId);
+ Principal principal);
async UnstoreAndBroadcastBlobURLUnregistration(nsCString url, Principal principal);
@@ -1660,12 +1657,7 @@ parent:
async HistoryGo(MaybeDiscardedBrowsingContext aContext,
int32_t aOffset) returns(int32_t requestedIndex);
- async BlobURLDataRequest(nsCString aBlobURL,
- nsIPrincipal aTriggeringPrincipal,
- nsIPrincipal aLoadingPrincipal,
- OriginAttributes aOriginAttributes,
- nsID? aAgentClusterId)
- returns (BlobURLDataRequestResult aResult);
+ async BlobURLDataRequest(nsCString aBlobURL, nsIPrincipal aTriggeringPrincipal, nsIPrincipal aLoadingPrincipal, OriginAttributes aOriginAttributes) returns (BlobURLDataRequestResult aResult);
both:
async ScriptError(nsString message, nsString sourceName, nsString sourceLine,
diff --git a/dom/url/URLMainThread.cpp b/dom/url/URLMainThread.cpp
index e67b3b8e48c0..5dcdc8697cb6 100644
--- a/dom/url/URLMainThread.cpp
+++ b/dom/url/URLMainThread.cpp
@@ -31,8 +31,7 @@ void URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
nsContentUtils::ObjectPrincipal(aGlobal.Get());
nsAutoCString url;
- aRv = BlobURLProtocolHandler::AddDataEntry(aBlob.Impl(), principal,
- global->GetAgentClusterId(), url);
+ aRv = BlobURLProtocolHandler::AddDataEntry(aBlob.Impl(), principal, url);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -47,18 +46,11 @@ void URLMainThread::CreateObjectURL(const GlobalObject& aGlobal,
ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports());
- if (NS_WARN_IF(!global)) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
-
nsCOMPtr principal =
nsContentUtils::ObjectPrincipal(aGlobal.Get());
nsAutoCString url;
- aRv = BlobURLProtocolHandler::AddDataEntry(&aSource, principal,
- global->GetAgentClusterId(), url);
+ aRv = BlobURLProtocolHandler::AddDataEntry(&aSource, principal, url);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -82,12 +74,16 @@ void URLMainThread::RevokeObjectURL(const GlobalObject& aGlobal,
return;
}
+ nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
+
NS_LossyConvertUTF16toASCII asciiurl(aURL);
- if (BlobURLProtocolHandler::RemoveDataEntry(
- asciiurl, nsContentUtils::ObjectPrincipal(aGlobal.Get()),
- global->GetAgentClusterId())) {
+ nsIPrincipal* urlPrincipal =
+ BlobURLProtocolHandler::GetDataEntryPrincipal(asciiurl);
+
+ if (urlPrincipal && principal->Subsumes(urlPrincipal)) {
global->UnregisterHostObjectURI(asciiurl);
+ BlobURLProtocolHandler::RemoveDataEntry(asciiurl);
}
}
diff --git a/dom/url/URLWorker.cpp b/dom/url/URLWorker.cpp
index bd06ddc6d06f..c06649a92337 100644
--- a/dom/url/URLWorker.cpp
+++ b/dom/url/URLWorker.cpp
@@ -38,8 +38,8 @@ class CreateURLRunnable : public WorkerMainThreadRunnable {
nsCOMPtr principal = mWorkerPrivate->GetPrincipal();
nsAutoCString url;
- nsresult rv = BlobURLProtocolHandler::AddDataEntry(
- mBlobImpl, principal, Some(mWorkerPrivate->AgentClusterId()), url);
+ nsresult rv =
+ BlobURLProtocolHandler::AddDataEntry(mBlobImpl, principal, url);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add data entry for the blob!");
@@ -67,9 +67,18 @@ class RevokeURLRunnable : public WorkerMainThreadRunnable {
NS_ConvertUTF16toUTF8 url(mURL);
- BlobURLProtocolHandler::RemoveDataEntry(
- url, mWorkerPrivate->GetPrincipal(),
- Some(mWorkerPrivate->AgentClusterId()));
+ nsIPrincipal* urlPrincipal =
+ BlobURLProtocolHandler::GetDataEntryPrincipal(url);
+
+ nsCOMPtr principal = mWorkerPrivate->GetPrincipal();
+
+ bool subsumes;
+ if (urlPrincipal &&
+ NS_SUCCEEDED(principal->Subsumes(urlPrincipal, &subsumes)) &&
+ subsumes) {
+ BlobURLProtocolHandler::RemoveDataEntry(url);
+ }
+
return true;
}
};
diff --git a/dom/url/tests/test_bloburl_location.html b/dom/url/tests/test_bloburl_location.html
index f8442cffc524..446b50836c37 100644
--- a/dom/url/tests/test_bloburl_location.html
+++ b/dom/url/tests/test_bloburl_location.html
@@ -19,14 +19,10 @@ onmessage = function(e) {
}
};
-SpecialPowers.pushPrefEnv({
- "set": [["privacy.partition.bloburl_per_agent_cluster", false]]
-}).then(() => {
- var ifr = document.createElement("iframe");
- document.body.appendChild(ifr);
+var ifr = document.createElement("iframe");
+document.body.appendChild(ifr);
- ifr.src = "data:text/html,