commit f538052047ad61cf74f926381bc7c41b60fa2a3d Author: Arthur Edelstein arthuredelstein@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;
- nsCOMPtrmozilla::dom::MediaSource source = do_QueryInterface(GetDataObject(aURI)); + nsCOMPtrmozilla::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!"); }
tor-commits@lists.torproject.org