Bug 1148032 - BroadcastChannel API should not bypass private browsing mode. r=ehsan, a=sledru
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 01 Apr 2015 12:41:29 +0100
changeset 258251 125623fcc804
parent 258250 d6ec30c02b8d
child 258252 8be55cae236f
push id4628
push userryanvm@gmail.com
push date2015-04-03 20:32 +0000
treeherdermozilla-beta@e4566e5991e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, sledru
bugs1148032
milestone38.0
Bug 1148032 - BroadcastChannel API should not bypass private browsing mode. r=ehsan, a=sledru
dom/broadcastchannel/BroadcastChannel.cpp
dom/broadcastchannel/BroadcastChannel.h
dom/broadcastchannel/BroadcastChannelChild.cpp
dom/broadcastchannel/BroadcastChannelChild.h
dom/broadcastchannel/BroadcastChannelParent.cpp
dom/broadcastchannel/BroadcastChannelParent.h
dom/broadcastchannel/BroadcastChannelService.cpp
dom/broadcastchannel/BroadcastChannelService.h
dom/broadcastchannel/moz.build
dom/broadcastchannel/tests/blank.html
dom/broadcastchannel/tests/chrome.ini
dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html
ipc/glue/BackgroundChildImpl.cpp
ipc/glue/BackgroundChildImpl.h
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -121,21 +121,23 @@ GetPrincipalFromWorkerPrivate(WorkerPriv
 
   return wp->GetPrincipal();
 }
 
 class InitializeRunnable final : public WorkerMainThreadRunnable
 {
 public:
   InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsAString& aOrigin,
-                     PrincipalInfo& aPrincipalInfo, ErrorResult& aRv)
+                     PrincipalInfo& aPrincipalInfo, bool& aPrivateBrowsing,
+                     ErrorResult& aRv)
     : WorkerMainThreadRunnable(aWorkerPrivate)
     , mWorkerPrivate(GetCurrentThreadWorkerPrivate())
     , mOrigin(aOrigin)
     , mPrincipalInfo(aPrincipalInfo)
+    , mPrivateBrowsing(aPrivateBrowsing)
     , mRv(aRv)
   {
     MOZ_ASSERT(mWorkerPrivate);
   }
 
   bool MainThreadRun() override
   {
     MOZ_ASSERT(NS_IsMainThread());
@@ -175,28 +177,31 @@ public:
 
     // Window doesn't exist for some kind of workers (eg: SharedWorkers)
     nsPIDOMWindow* window = wp->GetWindow();
     if (!window) {
       return true;
     }
 
     nsIDocument* doc = window->GetExtantDoc();
-    // No bfcache when BroadcastChannel is used.
     if (doc) {
+      mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
+
+      // No bfcache when BroadcastChannel is used.
       doc->DisallowBFCaching();
     }
 
     return true;
   }
 
 private:
   WorkerPrivate* mWorkerPrivate;
   nsAString& mOrigin;
   PrincipalInfo& mPrincipalInfo;
+  bool& mPrivateBrowsing;
   ErrorResult& mRv;
 };
 
 class BCPostMessageRunnable final : public nsICancelableRunnable
 {
 public:
   NS_DECL_ISUPPORTS
 
@@ -391,22 +396,24 @@ BroadcastChannel::IsEnabled(JSContext* a
   runnable->Dispatch(workerPrivate->GetJSContext());
 
   return runnable->IsEnabled();
 }
 
 BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow,
                                    const PrincipalInfo& aPrincipalInfo,
                                    const nsAString& aOrigin,
-                                   const nsAString& aChannel)
+                                   const nsAString& aChannel,
+                                   bool aPrivateBrowsing)
   : DOMEventTargetHelper(aWindow)
   , mWorkerFeature(nullptr)
   , mPrincipalInfo(new PrincipalInfo(aPrincipalInfo))
   , mOrigin(aOrigin)
   , mChannel(aChannel)
+  , mPrivateBrowsing(aPrivateBrowsing)
   , mIsKeptAlive(false)
   , mInnerID(0)
   , mState(StateActive)
 {
   // Window can be null in workers
 }
 
 BroadcastChannel::~BroadcastChannel()
@@ -426,16 +433,17 @@ BroadcastChannel::Constructor(const Glob
                               const nsAString& aChannel,
                               ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
   // Window is null in workers.
 
   nsAutoString origin;
   PrincipalInfo principalInfo;
+  bool privateBrowsing = false;
   WorkerPrivate* workerPrivate = nullptr;
 
   if (NS_IsMainThread()) {
     nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal();
 
     if (!incumbent) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
@@ -464,36 +472,40 @@ BroadcastChannel::Constructor(const Glob
     }
 
     aRv = PrincipalToPrincipalInfo(principal, &principalInfo);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     nsIDocument* doc = window->GetExtantDoc();
-    // No bfcache when BroadcastChannel is used.
     if (doc) {
+      privateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
+
+      // No bfcache when BroadcastChannel is used.
       doc->DisallowBFCaching();
     }
   } else {
     JSContext* cx = aGlobal.Context();
     workerPrivate = GetWorkerPrivateFromContext(cx);
     MOZ_ASSERT(workerPrivate);
 
     nsRefPtr<InitializeRunnable> runnable =
-      new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
+      new InitializeRunnable(workerPrivate, origin, principalInfo,
+                             privateBrowsing, aRv);
     runnable->Dispatch(cx);
   }
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
   nsRefPtr<BroadcastChannel> bc =
-    new BroadcastChannel(window, principalInfo, origin, aChannel);
+    new BroadcastChannel(window, principalInfo, origin, aChannel,
+                         privateBrowsing);
 
   // Register this component to PBackground.
   PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
   if (actor) {
     bc->ActorCreated(actor);
   } else {
     BackgroundChild::GetOrCreateForCurrentThread(bc);
   }
@@ -609,17 +621,18 @@ BroadcastChannel::ActorCreated(PBackgrou
 {
   MOZ_ASSERT(aActor);
 
   if (mState == StateClosed) {
     return;
   }
 
   PBroadcastChannelChild* actor =
-    aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel);
+    aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel,
+                                             mPrivateBrowsing);
 
   mActor = static_cast<BroadcastChannelChild*>(actor);
   MOZ_ASSERT(mActor);
 
   mActor->SetParent(this);
 
   // Flush pending messages.
   for (uint32_t i = 0; i < mPendingMessages.Length(); ++i) {
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -87,17 +87,18 @@ public:
   {
     return mState != StateActive;
   }
 
 private:
   BroadcastChannel(nsPIDOMWindow* aWindow,
                    const PrincipalInfo& aPrincipalInfo,
                    const nsAString& aOrigin,
-                   const nsAString& aChannel);
+                   const nsAString& aChannel,
+                   bool aPrivateBrowsing);
 
   ~BroadcastChannel();
 
   void PostMessageData(BroadcastChannelMessage* aData);
 
   void PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                            ErrorResult& aRv);
 
@@ -107,16 +108,17 @@ private:
   nsTArray<nsRefPtr<BroadcastChannelMessage>> mPendingMessages;
 
   nsAutoPtr<workers::WorkerFeature> mWorkerFeature;
 
   nsAutoPtr<PrincipalInfo> mPrincipalInfo;
 
   nsString mOrigin;
   nsString mChannel;
+  bool mPrivateBrowsing;
 
   bool mIsKeptAlive;
 
   uint64_t mInnerID;
 
   enum {
     StateActive,
     StateClosing,
--- a/dom/broadcastchannel/BroadcastChannelChild.cpp
+++ b/dom/broadcastchannel/BroadcastChannelChild.cpp
@@ -20,20 +20,18 @@
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
 using namespace workers;
 
-BroadcastChannelChild::BroadcastChannelChild(const nsAString& aOrigin,
-                                             const nsAString& aChannel)
+BroadcastChannelChild::BroadcastChannelChild(const nsAString& aOrigin)
   : mOrigin(aOrigin)
-  , mChannel(aChannel)
   , mActorDestroyed(false)
 {
 }
 
 BroadcastChannelChild::~BroadcastChannelChild()
 {
   MOZ_ASSERT(!mBC);
 }
--- a/dom/broadcastchannel/BroadcastChannelChild.h
+++ b/dom/broadcastchannel/BroadcastChannelChild.h
@@ -32,29 +32,26 @@ public:
   virtual bool RecvNotify(const ClonedMessageData& aData) override;
 
   bool IsActorDestroyed() const
   {
     return mActorDestroyed;
   }
 
 private:
-  BroadcastChannelChild(const nsAString& aOrigin,
-                        const nsAString& aChannel);
-
+  explicit BroadcastChannelChild(const nsAString& aOrigin);
   ~BroadcastChannelChild();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   // This raw pointer is actually the parent object.
   // It's set to null when the parent object is deleted.
   BroadcastChannel* mBC;
 
   nsString mOrigin;
-  nsString mChannel;
 
   bool mActorDestroyed;
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_BroadcastChannelChild_h
--- a/dom/broadcastchannel/BroadcastChannelParent.cpp
+++ b/dom/broadcastchannel/BroadcastChannelParent.cpp
@@ -13,20 +13,22 @@
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
 BroadcastChannelParent::BroadcastChannelParent(
                                             const nsAString& aOrigin,
-                                            const nsAString& aChannel)
+                                            const nsAString& aChannel,
+                                            bool aPrivateBrowsing)
   : mService(BroadcastChannelService::GetOrCreate())
   , mOrigin(aOrigin)
   , mChannel(aChannel)
+  , mPrivateBrowsing(aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
   mService->RegisterActor(this);
 }
 
 BroadcastChannelParent::~BroadcastChannelParent()
 {
   AssertIsOnBackgroundThread();
@@ -36,17 +38,17 @@ bool
 BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData)
 {
   AssertIsOnBackgroundThread();
 
   if (NS_WARN_IF(!mService)) {
     return false;
   }
 
-  mService->PostMessage(this, aData, mOrigin, mChannel);
+  mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing);
   return true;
 }
 
 bool
 BroadcastChannelParent::RecvClose()
 {
   AssertIsOnBackgroundThread();
 
@@ -72,21 +74,24 @@ BroadcastChannelParent::ActorDestroy(Act
     // released too.
     mService->UnregisterActor(this);
   }
 }
 
 void
 BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData,
                                         const nsString& aOrigin,
-                                        const nsString& aChannel)
+                                        const nsString& aChannel,
+                                        bool aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
 
-  if (aOrigin == mOrigin && aChannel == mChannel) {
+  if (aOrigin == mOrigin &&
+      aChannel == mChannel &&
+      aPrivateBrowsing == mPrivateBrowsing) {
     // We need to duplicate data only if we have blobs or if the manager of
     // them is different than the manager of this parent actor.
     if (aData.blobsParent().IsEmpty() ||
         static_cast<BlobParent*>(aData.blobsParent()[0])->GetBackgroundManager() == Manager()) {
       unused << SendNotify(aData);
       return;
     }
 
--- a/dom/broadcastchannel/BroadcastChannelParent.h
+++ b/dom/broadcastchannel/BroadcastChannelParent.h
@@ -19,31 +19,34 @@ class BroadcastChannelService;
 
 class BroadcastChannelParent final : public PBroadcastChannelParent
 {
   friend class mozilla::ipc::BackgroundParentImpl;
 
 public:
   void CheckAndDeliver(const ClonedMessageData& aData,
                        const nsString& aOrigin,
-                       const nsString& aChannel);
+                       const nsString& aChannel,
+                       bool aPrivateBrowsing);
 
 private:
   BroadcastChannelParent(const nsAString& aOrigin,
-                         const nsAString& aChannel);
+                         const nsAString& aChannel,
+                         bool aPrivateBrowsing);
   ~BroadcastChannelParent();
 
   virtual bool
   RecvPostMessage(const ClonedMessageData& aData) override;
 
   virtual bool RecvClose() override;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   nsRefPtr<BroadcastChannelService> mService;
   nsString mOrigin;
   nsString mChannel;
+  bool mPrivateBrowsing;
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_BroadcastChannelParent_h
--- a/dom/broadcastchannel/BroadcastChannelService.cpp
+++ b/dom/broadcastchannel/BroadcastChannelService.cpp
@@ -78,21 +78,23 @@ BroadcastChannelService::UnregisterActor
 
 namespace {
 
 struct MOZ_STACK_CLASS PostMessageData final
 {
   PostMessageData(BroadcastChannelParent* aParent,
                   const ClonedMessageData& aData,
                   const nsAString& aOrigin,
-                  const nsAString& aChannel)
+                  const nsAString& aChannel,
+                  bool aPrivateBrowsing)
     : mParent(aParent)
     , mData(aData)
     , mOrigin(aOrigin)
     , mChannel(aChannel)
+    , mPrivateBrowsing(aPrivateBrowsing)
   {
     MOZ_ASSERT(aParent);
     MOZ_COUNT_CTOR(PostMessageData);
 
     // We need to keep the array alive for the life-time of this
     // PostMessageData.
     if (!aData.blobsParent().IsEmpty()) {
       mFiles.SetCapacity(aData.blobsParent().Length());
@@ -111,44 +113,47 @@ struct MOZ_STACK_CLASS PostMessageData f
     MOZ_COUNT_DTOR(PostMessageData);
   }
 
   BroadcastChannelParent* mParent;
   const ClonedMessageData& mData;
   nsTArray<nsRefPtr<FileImpl>> mFiles;
   const nsString mOrigin;
   const nsString mChannel;
+  bool mPrivateBrowsing;
 };
 
 PLDHashOperator
 PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
 {
   AssertIsOnBackgroundThread();
 
   auto* data = static_cast<PostMessageData*>(aPtr);
   BroadcastChannelParent* parent = aKey->GetKey();
   MOZ_ASSERT(parent);
 
   if (parent != data->mParent) {
-    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mChannel);
+    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mChannel,
+                            data->mPrivateBrowsing);
   }
 
   return PL_DHASH_NEXT;
 }
 
 } // anonymous namespace
 
 void
 BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
                                      const ClonedMessageData& aData,
                                      const nsAString& aOrigin,
-                                     const nsAString& aChannel)
+                                     const nsAString& aChannel,
+                                     bool aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aParent);
   MOZ_ASSERT(mAgents.Contains(aParent));
 
-  PostMessageData data(aParent, aData, aOrigin, aChannel);
+  PostMessageData data(aParent, aData, aOrigin, aChannel, aPrivateBrowsing);
   mAgents.EnumerateEntries(PostMessageEnumerator, &data);
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/broadcastchannel/BroadcastChannelService.h
+++ b/dom/broadcastchannel/BroadcastChannelService.h
@@ -27,17 +27,18 @@ public:
   static already_AddRefed<BroadcastChannelService> GetOrCreate();
 
   void RegisterActor(BroadcastChannelParent* aParent);
   void UnregisterActor(BroadcastChannelParent* aParent);
 
   void PostMessage(BroadcastChannelParent* aParent,
                    const ClonedMessageData& aData,
                    const nsAString& aOrigin,
-                   const nsAString& aChannel);
+                   const nsAString& aChannel,
+                   bool aPrivateBrowsing);
 
 private:
   BroadcastChannelService();
   ~BroadcastChannelService();
 
   nsTHashtable<nsPtrHashKey<BroadcastChannelParent>> mAgents;
 };
 
--- a/dom/broadcastchannel/moz.build
+++ b/dom/broadcastchannel/moz.build
@@ -19,13 +19,14 @@ IPDL_SOURCES += [
     'PBroadcastChannel.ipdl',
 ]
 
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 FAIL_ON_WARNINGS = True
new file mode 100644
--- /dev/null
+++ b/dom/broadcastchannel/tests/blank.html
@@ -0,0 +1,2 @@
+<!DOCTYPE HTML>
+<html><body></body></html>
new file mode 100644
--- /dev/null
+++ b/dom/broadcastchannel/tests/chrome.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+skip-if = buildapp == 'b2g'
+support-files =
+  blank.html
+
+[test_broadcastchannel_private_browsing.html]
new file mode 100644
--- /dev/null
+++ b/dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html
@@ -0,0 +1,118 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>Test for BroadcastChannel - Private Browsing</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+</head>
+<body>
+
+<script type="application/javascript">
+
+const Ci = Components.interfaces;
+var mainWindow;
+
+var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+                           .getService(Components.interfaces.nsIPrefBranch);
+prefBranch.setIntPref("browser.startup.page", 0);
+prefBranch.setCharPref("browser.startup.homepage_override.mstone", "ignore");
+
+var contentPage = "http://mochi.test:8888/chrome/dom/broadcastchannel/tests/blank.html";
+
+function testOnWindow(aIsPrivate, aCallback) {
+  var win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
+  win.addEventListener("load", function onLoad() {
+    win.removeEventListener("load", onLoad, false);
+    win.addEventListener("DOMContentLoaded", function onInnerLoad() {
+      if (win.content.location.href != contentPage) {
+        win.gBrowser.loadURI(contentPage);
+        return;
+      }
+
+      win.removeEventListener("DOMContentLoaded", onInnerLoad, true);
+      SimpleTest.executeSoon(function() { aCallback(win); });
+    }, true);
+
+    if (!aIsPrivate) {
+      win.gBrowser.loadURI(contentPage);
+    }
+  }, true);
+}
+
+function setupWindow() {
+  mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                     .getInterface(Ci.nsIWebNavigation)
+                     .QueryInterface(Ci.nsIDocShellTreeItem)
+                     .rootTreeItem
+                     .QueryInterface(Ci.nsIInterfaceRequestor)
+                     .getInterface(Ci.nsIDOMWindow);
+  runTest();
+}
+
+var gCounter = 0;
+
+function check(msg, private) {
+  is(msg, private ? "private" : "public", "Correct context!");
+  gCounter++;
+
+  if (gCounter > 1) {
+    runTest();
+  }
+}
+
+var wN;
+var wP;
+
+function doTests() {
+  testOnWindow(false, function(aWin) {
+    wN = aWin;
+
+    testOnWindow(true, function(aWin) {
+      wP = aWin;
+
+      var bcP = new wP.content.BroadcastChannel('foobar');
+      bcP.onmessage = function(e) { ok(false, "This should not be called!"); }
+
+      var bc = new wP.content.BroadcastChannel('foobar');
+      bc.onmessage = function(e) { check(e.data, true); }
+
+      var bcN = new wN.content.BroadcastChannel('foobar');
+      bcN.onmessage = function(e) { ok(false, "This should not be called!"); }
+
+      var bc = new wN.content.BroadcastChannel('foobar');
+      bc.onmessage = function(e) { check(e.data, false); }
+
+      bcP.postMessage('private');
+      bcN.postMessage('public');
+    });
+  });
+}
+
+var steps = [
+  setupWindow,
+  doTests
+];
+
+function runTest() {
+  if (!steps.length) {
+    wN.close();
+    wP.close();
+
+    prefBranch.clearUserPref("browser.startup.page")
+    prefBranch.clearUserPref("browser.startup.homepage_override.mstone");
+
+    SimpleTest.finish();
+    return;
+  }
+
+  var step = steps.shift();
+  step();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
+
+</script>
+</body>
+</html>
+
+
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -209,20 +209,21 @@ BackgroundChildImpl::DeallocPVsyncChild(
 
 // -----------------------------------------------------------------------------
 // BroadcastChannel API
 // -----------------------------------------------------------------------------
 
 dom::PBroadcastChannelChild*
 BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
                                                  const nsString& aOrigin,
-                                                 const nsString& aChannel)
+                                                 const nsString& aChannel,
+                                                 const bool& aPrivateBrowsing)
 {
   nsRefPtr<dom::BroadcastChannelChild> agent =
-    new dom::BroadcastChannelChild(aOrigin, aChannel);
+    new dom::BroadcastChannelChild(aOrigin);
   return agent.forget().take();
 }
 
 bool
 BackgroundChildImpl::DeallocPBroadcastChannelChild(
                                                  PBroadcastChannelChild* aActor)
 {
   nsRefPtr<dom::BroadcastChannelChild> child =
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -75,17 +75,18 @@ protected:
   AllocPVsyncChild() override;
 
   virtual bool
   DeallocPVsyncChild(PVsyncChild* aActor) override;
 
   virtual PBroadcastChannelChild*
   AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
                               const nsString& aOrigin,
-                              const nsString& aChannel) override;
+                              const nsString& aChannel,
+                              const bool& aPrivateBrowsing) override;
 
   virtual bool
   DeallocPBroadcastChannelChild(PBroadcastChannelChild* aActor) override;
 };
 
 class BackgroundChildImpl::ThreadLocal final
 {
   friend class nsAutoPtr<ThreadLocal>;
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -245,22 +245,23 @@ BackgroundParentImpl::DeallocPVsyncParen
       dont_AddRef(static_cast<mozilla::layout::VsyncParent*>(aActor));
   return true;
 }
 
 mozilla::dom::PBroadcastChannelParent*
 BackgroundParentImpl::AllocPBroadcastChannelParent(
                                             const PrincipalInfo& aPrincipalInfo,
                                             const nsString& aOrigin,
-                                            const nsString& aChannel)
+                                            const nsString& aChannel,
+                                            const bool& aPrivateBrowsing)
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
-  return new BroadcastChannelParent(aOrigin, aChannel);
+  return new BroadcastChannelParent(aOrigin, aChannel, aPrivateBrowsing);
 }
 
 namespace {
 
 class CheckPrincipalRunnable final : public nsRunnable
 {
 public:
   CheckPrincipalRunnable(already_AddRefed<ContentParent> aParent,
@@ -318,17 +319,18 @@ private:
 
 } // anonymous namespace
 
 bool
 BackgroundParentImpl::RecvPBroadcastChannelConstructor(
                                             PBroadcastChannelParent* actor,
                                             const PrincipalInfo& aPrincipalInfo,
                                             const nsString& aOrigin,
-                                            const nsString& aChannel)
+                                            const nsString& aChannel,
+                                            const bool& aPrivateBrowsing)
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
   nsRefPtr<ContentParent> parent = BackgroundParent::GetContentParent(this);
 
   // If the ContentParent is null we are dealing with a same-process actor.
   if (!parent) {
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -68,23 +68,25 @@ protected:
   AllocPVsyncParent() override;
 
   virtual bool
   DeallocPVsyncParent(PVsyncParent* aActor) override;
 
   virtual PBroadcastChannelParent*
   AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
                                const nsString& aOrigin,
-                               const nsString& aChannel) override;
+                               const nsString& aChannel,
+                               const bool& aPrivateBrowsing) override;
 
   virtual bool
   RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor,
                                    const PrincipalInfo& aPrincipalInfo,
                                    const nsString& origin,
-                                   const nsString& channel) override;
+                                   const nsString& channel,
+                                   const bool& aPrivateBrowsing) override;
 
   virtual bool
   DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override;
 
   virtual bool
   RecvRegisterServiceWorker(const ServiceWorkerRegistrationData& aData)
                             override;
 
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -29,17 +29,18 @@ sync protocol PBackground
 parent:
   // Only called at startup during mochitests to check the basic infrastructure.
   PBackgroundTest(nsCString testArg);
 
   PBackgroundIDBFactory(LoggingInfo loggingInfo);
 
   PVsync();
 
-  PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel);
+  PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel,
+                    bool privateBrowsing);
 
   RegisterServiceWorker(ServiceWorkerRegistrationData data);
   UnregisterServiceWorker(PrincipalInfo principalInfo,
                           nsString scope);
   ShutdownServiceWorkerRegistrar();
 
 both:
   PBlob(BlobConstructorParams params);