Backed out 4 changesets (bug 1658878) for blob related leaks CLOSED TREE

Backed out changeset 0288ef9ab65b (bug 1658878)
Backed out changeset a5af0e097560 (bug 1658878)
Backed out changeset 33c4b81f99a1 (bug 1658878)
Backed out changeset 16a33c7b4ff3 (bug 1658878)
This commit is contained in:
Bogdan Tara 2020-08-14 22:41:05 +03:00
Родитель a560af420d
Коммит 694be205aa
18 изменённых файлов: 163 добавлений и 404 удалений

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

@ -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"

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

@ -109,10 +109,4 @@ for (let blobify of [page_blobify, worker_blobify]) {
}
}
async function setup() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.partition.bloburl_per_agent_cluster", false]],
});
}
IsolationTestTools.runTests(TEST_PAGE, tests, null, setup);
IsolationTestTools.runTests(TEST_PAGE, tests);

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

@ -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);

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

@ -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 = `<script>
let b = new Blob(["Hello world!"]);
let u = URL.createObjectURL(b);
fetch(u).then(r => r.text()).then(t => {
if (t !== "Hello world!") {
throw new Error(42);
}
}).then(() => fetch("/result?ok"), () => fetch("/result?failure")).then(() => {});
</script>`;
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 = `<script>
fetch("${metadata.queryString}").then(r => r.text()).then(t => {
if (t !== "Hello world!") {
throw new Error(42);
}
}).then(() => fetch("/result?ok"), () => fetch("/result?failure")).then(() => {});
</script>`;
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 = `<iframe id="a"></iframe><script>
let b = new Blob(["Hello world!"]);
let u = URL.createObjectURL(b);
document.getElementById("a").src = "/iframe?" + u;
</script>`;
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 = `<script>
let b = new Blob(["Hello world!"]);
let u = URL.createObjectURL(b);
fetch("/step?" + u).then(() => {});
</script>`;
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 = `<script>
fetch("${metadata.queryString}").then(r => r.text()).then(t => {
if (t !== "Hello world!") {
throw new Error(42);
}
}).then(() => fetch("/result?ok"), () => fetch("/result?failure")).then(() => {});
</script>`;
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();
});

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

@ -4,4 +4,3 @@
[test_createFile.js]
[test_ipc_messagemanager_blob.js]
skip-if = os == "android"
[test_agentcluster_bloburl.js]

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

@ -363,25 +363,47 @@ void BlobURLInputStream::RetrieveBlobData(const MutexAutoLock& aProofOfLock) {
return;
}
Maybe<nsID> agentClusterId;
Maybe<ClientInfo> clientInfo = loadInfo->GetClientInfo();
if (clientInfo.isSome()) {
agentClusterId = clientInfo->AgentClusterId();
}
if (XRE_IsParentProcess() || !BlobURLSchemeIsHTTPOrHTTPS(mBlobURLSpec)) {
RefPtr<BlobImpl> 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> 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) {

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

@ -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<nsID>& 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<nsID>& 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<MediaSource> mMediaSource;
nsCOMPtr<nsIPrincipal> mPrincipal;
Maybe<nsID> 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<nsID>& 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 <typename T>
static void AddDataEntryInternal(const nsACString& aURI, T aObject,
nsIPrincipal* aPrincipal,
const Maybe<nsID>& aAgentClusterId) {
nsIPrincipal* aPrincipal) {
MOZ_ASSERT(NS_IsMainThread(), "changing gDataTable is main-thread only");
StaticMutexAutoLock lock(sMutex);
if (!gDataTable) {
gDataTable = new nsClassHashtable<nsCStringHashKey, DataInfo>;
}
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<nsID>& 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<nsID>& 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<nsID>& aAgentClusterId,
BlobImpl* aBlobImpl) {
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aBlobImpl);
AddDataEntryInternal(aURI, aBlobImpl, aPrincipal, aAgentClusterId);
AddDataEntryInternal(aURI, aBlobImpl, aPrincipal);
}
/* static */
bool BlobURLProtocolHandler::ForEachBlobURL(
std::function<bool(BlobImpl*, nsIPrincipal*, const Maybe<nsID>&,
const nsACString&, bool aRevoked)>&& aCb) {
std::function<bool(BlobImpl*, nsIPrincipal*, const nsACString&,
bool aRevoked)>&& 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<nsID>& 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<nsID>& 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> blobImpl = info->mBlobImpl;
blobImpl.forget(aBlobImpl);
return true;
return res->mPrincipal;
}
/* static */

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

@ -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<nsID>& aAgentClusterId,
nsACString& aUri);
static nsresult AddDataEntry(MediaSource*, nsIPrincipal*,
const Maybe<nsID>& 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<nsID>& 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<nsID>& 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<nsID>& 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<bool(BlobImpl*, nsIPrincipal*, const Maybe<nsID>&,
const nsACString&, bool aRevoked)>&& aCb);
std::function<bool(BlobImpl*, nsIPrincipal*, const nsACString&,
bool aRevoked)>&& aCb);
// This method returns false if aURI is not a known BlobURL. Otherwise it
// returns true.

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

@ -2648,9 +2648,8 @@ mozilla::ipc::IPCResult ContentChild::RecvInitBlobURLs(
RefPtr<BlobImpl> 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<nsID>& aAgentClusterId) {
const IPC::Principal& aPrincipal) {
RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(aBlob);
MOZ_ASSERT(blobImpl);
BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, aAgentClusterId,
blobImpl);
BlobURLProtocolHandler::AddDataEntry(aURI, aPrincipal, blobImpl);
return IPC_OK();
}

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

@ -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<nsID>& aAgentClusterId);
const IPC::Principal& aPrincipal);
mozilla::ipc::IPCResult RecvBlobURLUnregistration(const nsCString& aURI);

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

@ -2866,8 +2866,7 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
nsTArray<BlobURLRegistrationData> registrations;
BlobURLProtocolHandler::ForEachBlobURL(
[&](BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
const Maybe<nsID>& 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<nsID>& 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<nsID>& aAgentClusterId) {
const nsCString& aURI, const IPCBlob& aBlob, const Principal& aPrincipal) {
RefPtr<BlobImpl> 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<BlobURLRegistrationData> registrations;
BlobURLProtocolHandler::ForEachBlobURL(
[&](BlobImpl* aBlobImpl, nsIPrincipal* aBlobPrincipal,
const Maybe<nsID>& 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<nsID>& aAgentClusterId,
const nsCString& aBlobURL, nsIPrincipal* pTriggeringPrincipal,
nsIPrincipal* pLoadingPrincipal, const OriginAttributes& aOriginAttributes,
BlobURLDataRequestResolver&& aResolver) {
RefPtr<BlobImpl> 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);

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

@ -548,7 +548,6 @@ class ContentParent final
static void BroadcastBlobURLRegistration(
const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal,
const Maybe<nsID>& 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<nsID>& 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<nsID>& aAgentClusterId,
BlobURLDataRequestResolver&& aResolver);
protected:

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

@ -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,

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

@ -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<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<nsIPrincipal> 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);
}
}

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

@ -38,8 +38,8 @@ class CreateURLRunnable : public WorkerMainThreadRunnable {
nsCOMPtr<nsIPrincipal> 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<nsIPrincipal> principal = mWorkerPrivate->GetPrincipal();
bool subsumes;
if (urlPrincipal &&
NS_SUCCEEDED(principal->Subsumes(urlPrincipal, &subsumes)) &&
subsumes) {
BlobURLProtocolHandler::RemoveDataEntry(url);
}
return true;
}
};

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

@ -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,<script>location=URL.createObjectURL(new%20Blob(['<script>parent.postMessage(location.pathname,\"*\");location.pathname=\"foo\";parent.postMessage(location.pathname,\"*\");<\/s' +'cript>'], {type:\"text/html\"}));<\/script>";
});
ifr.src = "data:text/html,<script>location=URL.createObjectURL(new%20Blob(['<script>parent.postMessage(location.pathname,\"*\");location.pathname=\"foo\";parent.postMessage(location.pathname,\"*\");<\/s' +'cript>'], {type:\"text/html\"}));<\/script>";
SimpleTest.waitForExplicitFinish();

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

@ -8766,11 +8766,6 @@
value: @IS_NIGHTLY_BUILD@
mirror: always
- name: privacy.partition.bloburl_per_agent_cluster
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
mirror: always
# By default, the network state isolation is not active when there is a proxy
# setting. This pref forces the network isolation even in these scenarios.
- name: privacy.partition.network_state.connection_with_proxy

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

@ -1 +0,0 @@
prefs: [privacy.partition.bloburl_per_agent_cluster:false]