commit 8a7950b34812259d857f65daaae766174dc48ce5 Author: Kathy Brade brade@pearlcrescent.com Date: Fri Jun 19 10:53:28 2015 -0400
Bug 16300: Isolate Broadcast Channels to first party.
Note that when the privacy.thirdparty.isolate pref. is set to 1 or 2, we disable use of Broadcast Channels by SharedWorkers since we cannot obtain the isolation host. --- dom/broadcastchannel/BroadcastChannel.cpp | 77 ++++++++++++++++++++-- dom/broadcastchannel/BroadcastChannel.h | 2 + dom/broadcastchannel/BroadcastChannelParent.cpp | 7 +- dom/broadcastchannel/BroadcastChannelParent.h | 3 + dom/broadcastchannel/BroadcastChannelService.cpp | 11 +++- dom/broadcastchannel/BroadcastChannelService.h | 1 + ipc/glue/BackgroundChildImpl.cpp | 1 + ipc/glue/BackgroundChildImpl.h | 1 + ipc/glue/BackgroundParentImpl.cpp | 5 +- ipc/glue/BackgroundParentImpl.h | 2 + ipc/glue/PBackground.ipdl | 3 +- 11 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index 6d16c2d..92ec729 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -20,6 +20,7 @@ #include "nsIScriptSecurityManager.h" #include "nsServiceManagerUtils.h" #include "nsISupportsPrimitives.h" +#include "mozIThirdPartyUtil.h"
#ifdef XP_WIN #undef PostMessage @@ -105,6 +106,44 @@ GetOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin, ErrorResult& aRv) appsService->GetManifestURLByLocalId(appId, aOrigin); }
+bool +IsFirstPartyIsolationEnabled() +{ + return 0 != mozilla::Preferences::GetInt("privacy.thirdparty.isolate"); +} + +void +GetFirstPartyHost(nsIDocument* aDoc, nsAString& aFirstPartyHost, + ErrorResult& aRv) +{ + if (!aDoc) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc = + do_GetService(THIRDPARTYUTIL_CONTRACTID); + nsCOMPtr<nsIURI> firstPartyIsolationURI; + nsresult rv = thirdPartySvc->GetFirstPartyIsolationURI(nullptr, aDoc, + getter_AddRefs(firstPartyIsolationURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + return; + } + + if (firstPartyIsolationURI) { + nsAutoCString hostCStr; + rv = thirdPartySvc->GetFirstPartyHostForIsolation(firstPartyIsolationURI, + hostCStr); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + return; + } + + aFirstPartyHost = NS_ConvertUTF8toUTF16(hostCStr); + } +} + nsIPrincipal* GetPrincipalFromWorkerPrivate(WorkerPrivate* aWorkerPrivate) { @@ -126,11 +165,13 @@ class InitializeRunnable final : public WorkerMainThreadRunnable { public: InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsAString& aOrigin, + nsAString& aFirstPartyHost, PrincipalInfo& aPrincipalInfo, bool& aPrivateBrowsing, ErrorResult& aRv) : WorkerMainThreadRunnable(aWorkerPrivate) , mWorkerPrivate(GetCurrentThreadWorkerPrivate()) , mOrigin(aOrigin) + , mFirstPartyHost(aFirstPartyHost) , mPrincipalInfo(aPrincipalInfo) , mPrivateBrowsing(aPrivateBrowsing) , mRv(aRv) @@ -175,9 +216,16 @@ public: wp = wp->GetParent(); }
+ bool isIsolationEnabled = IsFirstPartyIsolationEnabled(); + // Window doesn't exist for some kind of workers (eg: SharedWorkers) nsPIDOMWindow* window = wp->GetWindow(); if (!window) { + // If we lack a window and first party isolation is enabled, disallow + // use of Broadcast Channels. This is the safe thing to do, e.g., if + // a SharedWorker is being used. + if (isIsolationEnabled) + mRv.Throw(NS_ERROR_FAILURE); return true; }
@@ -189,12 +237,20 @@ public: doc->DisallowBFCaching(); }
+ if (isIsolationEnabled) { + GetFirstPartyHost(doc, mFirstPartyHost, mRv); + if (NS_WARN_IF(mRv.Failed())) { + return true; + } + } + return true; }
private: WorkerPrivate* mWorkerPrivate; nsAString& mOrigin; + nsAString& mFirstPartyHost; PrincipalInfo& mPrincipalInfo; bool& mPrivateBrowsing; ErrorResult& mRv; @@ -401,12 +457,14 @@ BroadcastChannel::IsEnabled(JSContext* aCx, JSObject* aGlobal) BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow, const PrincipalInfo& aPrincipalInfo, const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing) : DOMEventTargetHelper(aWindow) , mWorkerFeature(nullptr) , mPrincipalInfo(new PrincipalInfo(aPrincipalInfo)) , mOrigin(aOrigin) + , mFirstPartyHost(aFirstPartyHost) , mChannel(aChannel) , mPrivateBrowsing(aPrivateBrowsing) , mIsKeptAlive(false) @@ -437,6 +495,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, // Window is null in workers.
nsAutoString origin; + nsAutoString firstPartyHost; PrincipalInfo principalInfo; bool privateBrowsing = false; WorkerPrivate* workerPrivate = nullptr; @@ -483,14 +542,21 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, // No bfcache when BroadcastChannel is used. doc->DisallowBFCaching(); } + + if (IsFirstPartyIsolationEnabled()) { + GetFirstPartyHost(doc, firstPartyHost, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + } } else { JSContext* cx = aGlobal.Context(); workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate);
nsRefPtr<InitializeRunnable> runnable = - new InitializeRunnable(workerPrivate, origin, principalInfo, - privateBrowsing, aRv); + new InitializeRunnable(workerPrivate, origin, firstPartyHost, + principalInfo, privateBrowsing, aRv); runnable->Dispatch(cx); }
@@ -499,8 +565,8 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, }
nsRefPtr<BroadcastChannel> bc = - new BroadcastChannel(window, principalInfo, origin, aChannel, - privateBrowsing); + new BroadcastChannel(window, principalInfo, origin, firstPartyHost, + aChannel, privateBrowsing);
// Register this component to PBackground. PBackgroundChild* actor = BackgroundChild::GetForCurrentThread(); @@ -626,7 +692,8 @@ BroadcastChannel::ActorCreated(PBackgroundChild* aActor) }
PBroadcastChannelChild* actor = - aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel, + aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, + mFirstPartyHost, mChannel, mPrivateBrowsing);
mActor = static_cast<BroadcastChannelChild*>(actor); diff --git a/dom/broadcastchannel/BroadcastChannel.h b/dom/broadcastchannel/BroadcastChannel.h index 9208114..eac335f 100644 --- a/dom/broadcastchannel/BroadcastChannel.h +++ b/dom/broadcastchannel/BroadcastChannel.h @@ -92,6 +92,7 @@ private: BroadcastChannel(nsPIDOMWindow* aWindow, const PrincipalInfo& aPrincipalInfo, const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing);
@@ -112,6 +113,7 @@ private: nsAutoPtr<PrincipalInfo> mPrincipalInfo;
nsString mOrigin; + nsString mFirstPartyHost; nsString mChannel; bool mPrivateBrowsing;
diff --git a/dom/broadcastchannel/BroadcastChannelParent.cpp b/dom/broadcastchannel/BroadcastChannelParent.cpp index 7a1740d..f5fd9f3 100644 --- a/dom/broadcastchannel/BroadcastChannelParent.cpp +++ b/dom/broadcastchannel/BroadcastChannelParent.cpp @@ -18,10 +18,12 @@ namespace dom {
BroadcastChannelParent::BroadcastChannelParent( const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing) : mService(BroadcastChannelService::GetOrCreate()) , mOrigin(aOrigin) + , mFirstPartyHost(aFirstPartyHost) , mChannel(aChannel) , mPrivateBrowsing(aPrivateBrowsing) { @@ -43,7 +45,8 @@ BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData) return false; }
- mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing); + mService->PostMessage(this, aData, mOrigin, mFirstPartyHost, + mChannel, mPrivateBrowsing); return true; }
@@ -79,12 +82,14 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy) void BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, bool aPrivateBrowsing) { AssertIsOnBackgroundThread();
if (aOrigin == mOrigin && + aFirstPartyHost == mFirstPartyHost && aChannel == mChannel && aPrivateBrowsing == mPrivateBrowsing) { // We need to duplicate data only if we have blobs or if the manager of diff --git a/dom/broadcastchannel/BroadcastChannelParent.h b/dom/broadcastchannel/BroadcastChannelParent.h index 6ab3bb9..fc2d9de 100644 --- a/dom/broadcastchannel/BroadcastChannelParent.h +++ b/dom/broadcastchannel/BroadcastChannelParent.h @@ -24,11 +24,13 @@ class BroadcastChannelParent final : public PBroadcastChannelParent public: void CheckAndDeliver(const ClonedMessageData& aData, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, bool aPrivateBrowsing);
private: BroadcastChannelParent(const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing); ~BroadcastChannelParent(); @@ -42,6 +44,7 @@ private:
nsRefPtr<BroadcastChannelService> mService; nsString mOrigin; + nsString mFirstPartyHost; nsString mChannel; bool mPrivateBrowsing; }; diff --git a/dom/broadcastchannel/BroadcastChannelService.cpp b/dom/broadcastchannel/BroadcastChannelService.cpp index 7b73c72..debc111 100644 --- a/dom/broadcastchannel/BroadcastChannelService.cpp +++ b/dom/broadcastchannel/BroadcastChannelService.cpp @@ -83,11 +83,13 @@ struct MOZ_STACK_CLASS PostMessageData final PostMessageData(BroadcastChannelParent* aParent, const ClonedMessageData& aData, const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing) : mParent(aParent) , mData(aData) , mOrigin(aOrigin) + , mFirstPartyHost(aFirstPartyHost) , mChannel(aChannel) , mPrivateBrowsing(aPrivateBrowsing) { @@ -117,6 +119,7 @@ struct MOZ_STACK_CLASS PostMessageData final const ClonedMessageData& mData; nsTArray<nsRefPtr<FileImpl>> mFiles; const nsString mOrigin; + const nsString mFirstPartyHost; const nsString mChannel; bool mPrivateBrowsing; }; @@ -131,8 +134,8 @@ PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr) MOZ_ASSERT(parent);
if (parent != data->mParent) { - parent->CheckAndDeliver(data->mData, data->mOrigin, data->mChannel, - data->mPrivateBrowsing); + parent->CheckAndDeliver(data->mData, data->mOrigin, data->mFirstPartyHost, + data->mChannel, data->mPrivateBrowsing); }
return PL_DHASH_NEXT; @@ -144,6 +147,7 @@ void BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent, const ClonedMessageData& aData, const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing) { @@ -151,7 +155,8 @@ BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent, MOZ_ASSERT(aParent); MOZ_ASSERT(mAgents.Contains(aParent));
- PostMessageData data(aParent, aData, aOrigin, aChannel, aPrivateBrowsing); + PostMessageData data(aParent, aData, aOrigin, aFirstPartyHost, + aChannel, aPrivateBrowsing); mAgents.EnumerateEntries(PostMessageEnumerator, &data); }
diff --git a/dom/broadcastchannel/BroadcastChannelService.h b/dom/broadcastchannel/BroadcastChannelService.h index 3864e78..30345c5 100644 --- a/dom/broadcastchannel/BroadcastChannelService.h +++ b/dom/broadcastchannel/BroadcastChannelService.h @@ -32,6 +32,7 @@ public: void PostMessage(BroadcastChannelParent* aParent, const ClonedMessageData& aData, const nsAString& aOrigin, + const nsAString& aFirstPartyHost, const nsAString& aChannel, bool aPrivateBrowsing);
diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index c29f9b7..4c6e7e5 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -214,6 +214,7 @@ BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor) dom::PBroadcastChannelChild* BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, const bool& aPrivateBrowsing) { diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index 267fb3c..27f78ba 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -80,6 +80,7 @@ protected: virtual PBroadcastChannelChild* AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, const bool& aPrivateBrowsing) override;
diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 54a0afe..3bf16f0 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -250,13 +250,15 @@ mozilla::dom::PBroadcastChannelParent* BackgroundParentImpl::AllocPBroadcastChannelParent( const PrincipalInfo& aPrincipalInfo, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, const bool& aPrivateBrowsing) { AssertIsInMainProcess(); AssertIsOnBackgroundThread();
- return new BroadcastChannelParent(aOrigin, aChannel, aPrivateBrowsing); + return new BroadcastChannelParent(aOrigin, aFirstPartyHost, + aChannel, aPrivateBrowsing); }
namespace { @@ -324,6 +326,7 @@ BackgroundParentImpl::RecvPBroadcastChannelConstructor( PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, const bool& aPrivateBrowsing) { diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 1b58cf0..aeccd53 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -73,6 +73,7 @@ protected: virtual PBroadcastChannelParent* AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo, const nsString& aOrigin, + const nsString& aFirstPartyHost, const nsString& aChannel, const bool& aPrivateBrowsing) override;
@@ -80,6 +81,7 @@ protected: RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo, const nsString& origin, + const nsString& firstPartyHost, const nsString& channel, const bool& aPrivateBrowsing) override;
diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 6533290..dd5fdea 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -34,7 +34,8 @@ parent:
PVsync();
- PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel, + PBroadcastChannel(PrincipalInfo pInfo, nsString origin, + nsString firstPartyHost, nsString channel, bool privateBrowsing);
RegisterServiceWorker(ServiceWorkerRegistrationData data);