commit f538052047ad61cf74f926381bc7c41b60fa2a3d
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Thu Jul 2 12:56:23 2015 -0700
Bug #15502. Isolate blob, mediasource & mediastream URLs to first party
This patch handles blob URLs created and retrieved in Web Workers.
See also #15703 and #16429.
---
dom/base/ThirdPartyUtil.cpp | 21 ++++++
dom/base/ThirdPartyUtil.h | 12 +++
dom/base/URL.cpp | 32 +++++---
dom/base/moz.build | 1 +
dom/base/nsDocument.cpp | 17 ++++-
dom/base/nsHostObjectProtocolHandler.cpp | 120 ++++++++++++++++++------------
dom/base/nsHostObjectProtocolHandler.h | 15 ++--
dom/fetch/Fetch.cpp | 17 ++++-
dom/fetch/FetchDriver.cpp | 8 +-
dom/fetch/FetchDriver.h | 5 +-
dom/html/HTMLMediaElement.cpp | 17 ++++-
dom/media/MediaResource.cpp | 6 +-
dom/workers/URL.cpp | 21 +++++-
dom/workers/WorkerPrivate.cpp | 22 +++++-
14 files changed, 232 insertions(+), 82 deletions(-)
diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp
index d0aed3a..e8ec06c 100644
--- a/dom/base/ThirdPartyUtil.cpp
+++ b/dom/base/ThirdPartyUtil.cpp
@@ -33,6 +33,27 @@ static PRLogModuleInfo *gThirdPartyLog;
#undef LOG
#define LOG(args) PR_LOG(gThirdPartyLog, PR_LOG_DEBUG, args)
+// static
+mozIThirdPartyUtil* ThirdPartyUtil::gThirdPartyUtilService = nullptr;
+
+//static
+nsresult
+ThirdPartyUtil::GetFirstPartyHost(nsIChannel* aChannel, nsIDocument* aDocument, nsACString& aResult)
+{
+ if (!gThirdPartyUtilService) {
+ CallGetService(THIRDPARTYUTIL_CONTRACTID, &gThirdPartyUtilService);
+ }
+ nsCOMPtr<nsIURI> isolationURI;
+ nsresult rv = gThirdPartyUtilService->GetFirstPartyIsolationURI(aChannel, aDocument, getter_AddRefs(isolationURI));
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isolationURI) {
+ // Isolation is not active.
+ aResult.Truncate();
+ return NS_OK;
+ }
+ return gThirdPartyUtilService->GetFirstPartyHostForIsolation(isolationURI, aResult);
+}
+
nsresult
ThirdPartyUtil::Init()
{
diff --git a/dom/base/ThirdPartyUtil.h b/dom/base/ThirdPartyUtil.h
index c03740e..77e73f7 100644
--- a/dom/base/ThirdPartyUtil.h
+++ b/dom/base/ThirdPartyUtil.h
@@ -24,6 +24,18 @@ public:
nsresult Init();
+ static mozIThirdPartyUtil* gThirdPartyUtilService;
+
+ static nsresult GetFirstPartyHost(nsIChannel* aChannel, nsIDocument* aDocument, nsACString& aResult);
+
+ static nsresult GetFirstPartyHost(nsIChannel* aChannel, nsACString& aResult) {
+ return GetFirstPartyHost(aChannel, nullptr, aResult);
+ }
+
+ static nsresult GetFirstPartyHost(nsIDocument* aDocument, nsACString& aResult) {
+ return GetFirstPartyHost(nullptr, aDocument, aResult);
+ }
+
private:
~ThirdPartyUtil() {}
diff --git a/dom/base/URL.cpp b/dom/base/URL.cpp
index fea8dd2..1931c28 100644
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -17,6 +17,7 @@
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIURL.h"
+#include "ThirdPartyUtil.h"
namespace mozilla {
namespace dom {
@@ -152,12 +153,6 @@ URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
nsCString url;
- nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
- principal, url);
- if (NS_FAILED(rv)) {
- aError.Throw(rv);
- return;
- }
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
@@ -172,6 +167,18 @@ URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
nsIDocument* doc = window->GetExtantDoc();
if (doc) {
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_FAILED(rv)) {
+ aError.Throw(rv);
+ return;
+ }
+ rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
+ principal, isolationKey, url);
+ if (NS_FAILED(rv)) {
+ aError.Throw(rv);
+ return;
+ }
doc->RegisterHostObjectUri(url);
}
}
@@ -193,10 +200,17 @@ URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL)
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
- if (window && window->GetExtantDoc()) {
- window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl);
+ if (window) {
+ nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
+ if (doc) {
+ doc->UnregisterHostObjectUri(asciiurl);
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_SUCCEEDED(rv)) {
+ nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl, isolationKey);
+ }
+ }
}
- nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl);
}
}
diff --git a/dom/base/moz.build b/dom/base/moz.build
index 27de87b..1d92f94 100644
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -194,6 +194,7 @@ EXPORTS.mozilla.dom += [
'StyleSheetList.h',
'SubtleCrypto.h',
'Text.h',
+ 'ThirdPartyUtil.h',
'TreeWalker.h',
'URL.h',
'URLSearchParams.h',
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 47f611e..e5f0a2f2 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -226,6 +226,7 @@
#include "nsLocation.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/BoxObject.h"
+#include "ThirdPartyUtil.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/MediaManager.h"
@@ -1776,8 +1777,12 @@ nsDocument::~nsDocument()
mPendingTitleChangeEvent.Revoke();
- for (uint32_t i = 0; i < mHostObjectURIs.Length(); ++i) {
- nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[i]);
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(this, isolationKey);
+ if (NS_SUCCEEDED(rv)) {
+ for (uint32_t i = 0; i < mHostObjectURIs.Length(); ++i) {
+ nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[i], isolationKey);
+ }
}
// We don't want to leave residual locks on images. Make sure we're in an
@@ -2156,8 +2161,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
}
- for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
- nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i]);
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(tmp, isolationKey);
+ if (NS_SUCCEEDED(rv)) {
+ for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
+ nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i], isolationKey);
+ }
}
// We own only the items in mDOMMediaQueryLists that have listeners;
diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp
index aac33f9..429938b 100644
--- a/dom/base/nsHostObjectProtocolHandler.cpp
+++ b/dom/base/nsHostObjectProtocolHandler.cpp
@@ -16,6 +16,7 @@
#include "mozilla/dom/File.h"
#include "mozilla/Preferences.h"
#include "mozilla/LoadInfo.h"
+#include "ThirdPartyUtil.h"
using mozilla::dom::FileImpl;
using mozilla::ErrorResult;
@@ -29,6 +30,7 @@ struct DataInfo
nsCOMPtr<nsISupports> mObject;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCString mStack;
+ nsCString mFirstPartyHost;
};
static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
@@ -298,6 +300,7 @@ nsresult
nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
+ const nsACString& aIsolationKey,
nsACString& aUri)
{
Init();
@@ -313,28 +316,55 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
info->mObject = aObject;
info->mPrincipal = aPrincipal;
+ // Record the first party host that originated this object.
+ info->mFirstPartyHost = aIsolationKey;
mozilla::BlobURLsReporter::GetJSStackForBlob(info);
gDataTable->Put(aUri, info);
return NS_OK;
}
+static DataInfo*
+GetDataInfo(const nsACString& aUri)
+{
+ if (!gDataTable) {
+ return nullptr;
+ }
+
+ DataInfo* res;
+ nsCString uriIgnoringRef;
+ int32_t hashPos = aUri.FindChar('#');
+ if (hashPos < 0) {
+ uriIgnoringRef = aUri;
+ }
+ else {
+ uriIgnoringRef = StringHead(aUri, hashPos);
+ }
+ gDataTable->Get(uriIgnoringRef, &res);
+
+ return res;
+}
+
void
-nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
+nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri,
+ const nsACString& aIsolationKey)
{
if (gDataTable) {
- nsCString uriIgnoringRef;
- int32_t hashPos = aUri.FindChar('#');
- if (hashPos < 0) {
- uriIgnoringRef = aUri;
- }
- else {
- uriIgnoringRef = StringHead(aUri, hashPos);
- }
- gDataTable->Remove(uriIgnoringRef);
- if (gDataTable->Count() == 0) {
- delete gDataTable;
- gDataTable = nullptr;
+ DataInfo* info = GetDataInfo(aUri);
+ if (info->mFirstPartyHost == aIsolationKey) {
+ nsCString uriIgnoringRef;
+ int32_t hashPos = aUri.FindChar('#');
+ if (hashPos < 0) {
+ uriIgnoringRef = aUri;
+ }
+ else {
+ uriIgnoringRef = StringHead(aUri, hashPos);
+ }
+ gDataTable->Remove(uriIgnoringRef);
+ if (gDataTable->Count() == 0) {
+ delete gDataTable;
+ gDataTable = nullptr;
+ }
}
}
}
@@ -375,27 +405,6 @@ nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
return NS_OK;
}
-static DataInfo*
-GetDataInfo(const nsACString& aUri)
-{
- if (!gDataTable) {
- return nullptr;
- }
-
- DataInfo* res;
- nsCString uriIgnoringRef;
- int32_t hashPos = aUri.FindChar('#');
- if (hashPos < 0) {
- uriIgnoringRef = aUri;
- }
- else {
- uriIgnoringRef = StringHead(aUri, hashPos);
- }
- gDataTable->Get(uriIgnoringRef, &res);
-
- return res;
-}
-
nsIPrincipal*
nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
{
@@ -431,13 +440,16 @@ nsHostObjectProtocolHandler::Traverse(const nsACString& aUri,
}
static nsISupports*
-GetDataObject(nsIURI* aURI)
+GetDataObject(nsIURI* aURI, const nsACString& aIsolationKey)
{
nsCString spec;
aURI->GetSpec(spec);
DataInfo* info = GetDataInfo(spec);
- return info ? info->mObject : nullptr;
+ // Deny access to this object if the current first-party host
+ // doesn't match the originating first-party host.
+ return (info && info->mFirstPartyHost == aIsolationKey)
+ ? info->mObject : nullptr;
}
// -----------------------------------------------------------------------
@@ -493,9 +505,19 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
nsCString spec;
uri->GetSpec(spec);
- DataInfo* info = GetDataInfo(spec);
+ nsCString firstPartyHost;
+ if (aLoadInfo) {
+ nsCOMPtr<nsIDOMDocument> loadingDOMDocument;
+ aLoadInfo->GetLoadingDocument(getter_AddRefs(loadingDOMDocument));
+ nsCOMPtr<nsIDocument> loadingDocument = do_QueryInterface(loadingDOMDocument);
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(loadingDocument, firstPartyHost);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
- if (!info) {
+ DataInfo* info = GetDataInfo(spec);
+ // Deny access to this URI if the current first party host
+ // doesn't match the first party host when it was created.
+ if (!info || (info->mFirstPartyHost != firstPartyHost)) {
return NS_ERROR_DOM_BAD_URI;
}
@@ -594,13 +616,13 @@ nsFontTableProtocolHandler::GetScheme(nsACString &result)
}
nsresult
-NS_GetBlobForBlobURI(nsIURI* aURI, FileImpl** aBlob)
+NS_GetBlobForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey, FileImpl** aBlob)
{
NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
*aBlob = nullptr;
- nsCOMPtr<FileImpl> blob = do_QueryInterface(GetDataObject(aURI));
+ nsCOMPtr<FileImpl> blob = do_QueryInterface(GetDataObject(aURI, aIsolationKey));
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
}
@@ -610,10 +632,12 @@ NS_GetBlobForBlobURI(nsIURI* aURI, FileImpl** aBlob)
}
nsresult
-NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
+NS_GetStreamForBlobURI(nsIURI* aURI,
+ const nsACString& aIsolationKey,
+ nsIInputStream** aStream)
{
nsRefPtr<FileImpl> blobImpl;
- nsresult rv = NS_GetBlobForBlobURI(aURI, getter_AddRefs(blobImpl));
+ nsresult rv = NS_GetBlobForBlobURI(aURI, aIsolationKey, getter_AddRefs(blobImpl));
if (NS_FAILED(rv)) {
return rv;
}
@@ -622,11 +646,13 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
}
nsresult
-NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream)
+NS_GetStreamForMediaStreamURI(nsIURI* aURI,
+ const nsACString& aIsolationKey,
+ mozilla::DOMMediaStream** aStream)
{
NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs");
- nsISupports* dataObject = GetDataObject(aURI);
+ nsISupports* dataObject = GetDataObject(aURI, aIsolationKey);
if (!dataObject) {
return NS_ERROR_DOM_BAD_URI;
}
@@ -669,13 +695,15 @@ nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
}
nsresult
-NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
+NS_GetSourceForMediaSourceURI(nsIURI* aURI,
+ const nsACString& aIsolationKey,
+ mozilla::dom::MediaSource** aSource)
{
NS_ASSERTION(IsMediaSourceURI(aURI), "Only call this with mediasource URIs");
*aSource = nullptr;
- nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI));
+ nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI, aIsolationKey));
if (!source) {
return NS_ERROR_DOM_BAD_URI;
}
diff --git a/dom/base/nsHostObjectProtocolHandler.h b/dom/base/nsHostObjectProtocolHandler.h
index 977e5e0..e335886 100644
--- a/dom/base/nsHostObjectProtocolHandler.h
+++ b/dom/base/nsHostObjectProtocolHandler.h
@@ -53,8 +53,9 @@ public:
static nsresult AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
+ const nsACString& aIsolationKey,
nsACString& aUri);
- static void RemoveDataEntry(const nsACString& aUri);
+ static void RemoveDataEntry(const nsACString& aUri, const nsACString& aIsolationKey);
static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri);
static void Traverse(const nsACString& aUri, nsCycleCollectionTraversalCallback& aCallback);
@@ -121,16 +122,20 @@ inline bool IsFontTableURI(nsIURI* aUri)
}
extern nsresult
-NS_GetBlobForBlobURI(nsIURI* aURI, mozilla::dom::FileImpl** aBlob);
+NS_GetBlobForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey,
+ mozilla::dom::FileImpl** aBlob);
extern nsresult
-NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
+NS_GetStreamForBlobURI(nsIURI* aURI, const nsACString& aIsolationKey,
+ nsIInputStream** aStream);
extern nsresult
-NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream);
+NS_GetStreamForMediaStreamURI(nsIURI* aURI, const nsACString& aIsolationKey,
+ mozilla::DOMMediaStream** aStream);
extern nsresult
-NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource);
+NS_GetSourceForMediaSourceURI(nsIURI* aURI, const nsACString& aIsolationKey,
+ mozilla::dom::MediaSource** aSource);
#define NS_BLOBPROTOCOLHANDLER_CID \
{ 0xb43964aa, 0xa078, 0x44b2, \
diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp
index b84393e..9a53555 100644
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -27,6 +27,7 @@
#include "mozilla/dom/Request.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/ThirdPartyUtil.h"
#include "mozilla/dom/URLSearchParams.h"
#include "InternalRequest.h"
@@ -174,13 +175,18 @@ public:
nsCOMPtr<nsIPrincipal> principal = mResolver->GetWorkerPrivate()->GetPrincipal();
nsCOMPtr<nsILoadGroup> loadGroup = mResolver->GetWorkerPrivate()->GetLoadGroup();
- nsRefPtr<FetchDriver> fetch = new FetchDriver(mRequest, principal, loadGroup);
nsIDocument* doc = mResolver->GetWorkerPrivate()->GetDocument();
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ nsRefPtr<FetchDriver> fetch = new FetchDriver(mRequest, principal, isolationKey, loadGroup);
if (doc) {
fetch->SetReferrerPolicy(doc->GetReferrerPolicy());
}
- nsresult rv = fetch->Fetch(mResolver);
+ rv = fetch->Fetch(mResolver);
// Right now we only support async fetch, which should never directly fail.
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -230,10 +236,15 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
return nullptr;
}
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
nsRefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
nsRefPtr<FetchDriver> fetch =
- new FetchDriver(r, doc->NodePrincipal(), loadGroup);
+ new FetchDriver(r, doc->NodePrincipal(), isolationKey, loadGroup);
fetch->SetReferrerPolicy(doc->GetReferrerPolicy());
aRv = fetch->Fetch(resolver);
if (NS_WARN_IF(aRv.Failed())) {
diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp
index ad54daf..b57141c 100644
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -28,6 +28,7 @@
#include "Fetch.h"
#include "InternalRequest.h"
#include "InternalResponse.h"
+#include "mozilla/dom/ThirdPartyUtil.h"
namespace mozilla {
namespace dom {
@@ -36,9 +37,12 @@ NS_IMPL_ISUPPORTS(FetchDriver,
nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
-FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
+FetchDriver::FetchDriver(InternalRequest* aRequest,
+ nsIPrincipal* aPrincipal,
+ const nsACString& aIsolationKey,
nsILoadGroup* aLoadGroup)
: mPrincipal(aPrincipal)
+ , mIsolationKey(aIsolationKey)
, mLoadGroup(aLoadGroup)
, mRequest(aRequest)
, mFetchRecursionCount(0)
@@ -187,7 +191,7 @@ FetchDriver::BasicFetch()
if (scheme.LowerCaseEqualsLiteral("blob")) {
nsRefPtr<FileImpl> blobImpl;
- rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl));
+ rv = NS_GetBlobForBlobURI(uri, mIsolationKey, getter_AddRefs(blobImpl));
FileImpl* blob = static_cast<FileImpl*>(blobImpl.get());
if (NS_WARN_IF(NS_FAILED(rv))) {
FailWithNetworkError();
diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h
index d58224209..c835149 100644
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -53,7 +53,9 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
- explicit FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
+ explicit FetchDriver(InternalRequest* aRequest,
+ nsIPrincipal* aPrincipal,
+ const nsACString& isolationKey,
nsILoadGroup* aLoadGroup);
NS_IMETHOD Fetch(FetchDriverObserver* aObserver);
@@ -67,6 +69,7 @@ public:
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
+ nsAutoCString mIsolationKey;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsRefPtr<InternalRequest> mRequest;
nsRefPtr<InternalResponse> mResponse;
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index 41a1505..d80cfff 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -90,6 +90,7 @@
#include "ImageContainer.h"
#include "nsRange.h"
#include <algorithm>
+#include "ThirdPartyUtil.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gMediaElementLog;
@@ -521,7 +522,11 @@ HTMLMediaElement::GetMozMediaSourceObject() const
{
nsRefPtr<MediaSource> source;
if (mLoadingSrc && IsMediaSourceURI(mLoadingSrc)) {
- NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source));
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey);
+ if (NS_SUCCEEDED(rv)) {
+ NS_GetSourceForMediaSourceURI(mLoadingSrc, isolationKey, getter_AddRefs(source));
+ }
}
return source.forget();
}
@@ -1191,7 +1196,10 @@ nsresult HTMLMediaElement::LoadResource()
if (IsMediaStreamURI(mLoadingSrc)) {
nsRefPtr<DOMMediaStream> stream;
- rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
+ nsCString isolationKey;
+ rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, isolationKey, getter_AddRefs(stream));
if (NS_FAILED(rv)) {
nsCString specUTF8;
mLoadingSrc->GetSpec(specUTF8);
@@ -1206,7 +1214,10 @@ nsresult HTMLMediaElement::LoadResource()
if (IsMediaSourceURI(mLoadingSrc)) {
nsRefPtr<MediaSource> source;
- rv = NS_GetSourceForMediaSourceURI(mLoadingSrc, getter_AddRefs(source));
+ nsCString isolationKey;
+ rv = ThirdPartyUtil::GetFirstPartyHost(GetOwnerDocument(), isolationKey);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = NS_GetSourceForMediaSourceURI(mLoadingSrc, isolationKey, getter_AddRefs(source));
if (NS_FAILED(rv)) {
nsCString specUTF8;
mLoadingSrc->GetSpec(specUTF8);
diff --git a/dom/media/MediaResource.cpp b/dom/media/MediaResource.cpp
index 956776c..618b10a 100644
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -32,6 +32,7 @@
#include <algorithm>
#include "nsProxyRelease.h"
#include "nsIContentPolicy.h"
+#include "mozilla/dom/ThirdPartyUtil.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gMediaResourceLog;
@@ -1365,7 +1366,10 @@ nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener)
rv = NS_NewLocalFileInputStream(getter_AddRefs(mInput), file);
} else if (IsBlobURI(mURI)) {
- rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput));
+ nsCString isolationKey;
+ rv = ThirdPartyUtil::GetFirstPartyHost(mChannel, isolationKey);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = NS_GetStreamForBlobURI(mURI, isolationKey, getter_AddRefs(mInput));
}
} else {
// Ensure that we never load a local file from some page on a
diff --git a/dom/workers/URL.cpp b/dom/workers/URL.cpp
index fbf6987..1eda4fd 100644
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -24,6 +24,7 @@
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
+#include "ThirdPartyUtil.h"
BEGIN_WORKERS_NAMESPACE
using mozilla::dom::GlobalObject;
@@ -140,10 +141,17 @@ public:
principal = mWorkerPrivate->GetPrincipal();
}
+ nsCString firstPartyHost;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, firstPartyHost);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Isolation failed; blob URL creation denied.");
+ return false;
+ }
+
nsCString url;
- nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
+ rv = nsHostObjectProtocolHandler::AddDataEntry(
NS_LITERAL_CSTRING(BLOBURI_SCHEME),
- mBlobImpl, principal, url);
+ mBlobImpl, principal, firstPartyHost, url);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add data entry for the blob!");
@@ -209,8 +217,13 @@ public:
if (doc) {
doc->UnregisterHostObjectUri(url);
}
-
- nsHostObjectProtocolHandler::RemoveDataEntry(url);
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Isolation failed; blob removal denied.");
+ return false;
+ }
+ nsHostObjectProtocolHandler::RemoveDataEntry(url, isolationKey);
}
if (!window) {
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index 0d4702d..d998471 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -99,6 +99,7 @@
#include "WorkerRunnable.h"
#include "WorkerScope.h"
#include "WorkerThread.h"
+#include "ThirdPartyUtil.h"
#ifdef XP_WIN
#undef PostMessage
@@ -708,14 +709,17 @@ class MainThreadReleaseRunnable final : public nsRunnable
nsTArray<nsCOMPtr<nsISupports>> mDoomed;
nsTArray<nsCString> mHostObjectURIs;
nsCOMPtr<nsILoadGroup> mLoadGroupToCancel;
+ nsRefPtr<WorkerPrivate> mWorkerPrivate;
public:
MainThreadReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>& aDoomed,
nsTArray<nsCString>& aHostObjectURIs,
+ WorkerPrivate* aWorkerPrivate,
nsCOMPtr<nsILoadGroup>& aLoadGroupToCancel)
{
mDoomed.SwapElements(aDoomed);
mHostObjectURIs.SwapElements(aHostObjectURIs);
+ mWorkerPrivate = aWorkerPrivate;
mLoadGroupToCancel.swap(aLoadGroupToCancel);
}
@@ -731,8 +735,17 @@ public:
mDoomed.Clear();
- for (uint32_t index = 0; index < mHostObjectURIs.Length(); index++) {
- nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]);
+ nsCOMPtr<nsIDocument> doc;
+ nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
+ if (window) {
+ doc = window->GetExtantDoc();
+ }
+ nsCString isolationKey;
+ nsresult rv = ThirdPartyUtil::GetFirstPartyHost(doc, isolationKey);
+ if (NS_SUCCEEDED(rv)) {
+ for (uint32_t index = 0; index < mHostObjectURIs.Length(); index++) {
+ nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[index], isolationKey);
+ }
}
return NS_OK;
@@ -782,7 +795,8 @@ private:
mFinishedWorker->StealHostObjectURIs(hostObjectURIs);
nsRefPtr<MainThreadReleaseRunnable> runnable =
- new MainThreadReleaseRunnable(doomed, hostObjectURIs, loadGroupToCancel);
+ new MainThreadReleaseRunnable(doomed, hostObjectURIs,
+ aWorkerPrivate, loadGroupToCancel);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_WARNING("Failed to dispatch, going to leak!");
}
@@ -840,7 +854,7 @@ private:
mFinishedWorker->StealHostObjectURIs(hostObjectURIs);
nsRefPtr<MainThreadReleaseRunnable> runnable =
- new MainThreadReleaseRunnable(doomed, hostObjectURIs, loadGroupToCancel);
+ new MainThreadReleaseRunnable(doomed, hostObjectURIs, mFinishedWorker, loadGroupToCancel);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
NS_WARNING("Failed to dispatch, going to leak!");
}