commit 8a7950b34812259d857f65daaae766174dc48ce5
Author: Kathy Brade <brade(a)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);