Bug 1148032 - BroadcastChannel API should not bypass private browsing mode, r=ehsan

This commit is contained in:
Andrea Marchesini 2015-03-31 22:11:47 +01:00
parent 1a65d1c1e9
commit 621d7068b8
17 changed files with 192 additions and 35 deletions

View File

@ -126,11 +126,13 @@ 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);
@ -180,8 +182,10 @@ public:
}
nsIDocument* doc = window->GetExtantDoc();
// No bfcache when BroadcastChannel is used.
if (doc) {
mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc);
// No bfcache when BroadcastChannel is used.
doc->DisallowBFCaching();
}
@ -192,6 +196,7 @@ private:
WorkerPrivate* mWorkerPrivate;
nsAString& mOrigin;
PrincipalInfo& mPrincipalInfo;
bool& mPrivateBrowsing;
ErrorResult& mRv;
};
@ -396,12 +401,14 @@ BroadcastChannel::IsEnabled(JSContext* aCx, JSObject* aGlobal)
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)
@ -431,6 +438,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
nsAutoString origin;
PrincipalInfo principalInfo;
bool privateBrowsing = false;
WorkerPrivate* workerPrivate = nullptr;
if (NS_IsMainThread()) {
@ -469,8 +477,10 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
}
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 {
@ -479,7 +489,8 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
MOZ_ASSERT(workerPrivate);
nsRefPtr<InitializeRunnable> runnable =
new InitializeRunnable(workerPrivate, origin, principalInfo, aRv);
new InitializeRunnable(workerPrivate, origin, principalInfo,
privateBrowsing, aRv);
runnable->Dispatch(cx);
}
@ -488,7 +499,8 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
}
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();
@ -614,7 +626,8 @@ BroadcastChannel::ActorCreated(PBackgroundChild* aActor)
}
PBroadcastChannelChild* actor =
aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel);
aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel,
mPrivateBrowsing);
mActor = static_cast<BroadcastChannelChild*>(actor);
MOZ_ASSERT(mActor);

View File

@ -92,7 +92,8 @@ private:
BroadcastChannel(nsPIDOMWindow* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsAString& aOrigin,
const nsAString& aChannel);
const nsAString& aChannel,
bool aPrivateBrowsing);
~BroadcastChannel();
@ -112,6 +113,7 @@ private:
nsString mOrigin;
nsString mChannel;
bool mPrivateBrowsing;
bool mIsKeptAlive;

View File

@ -25,10 +25,8 @@ namespace dom {
using namespace workers;
BroadcastChannelChild::BroadcastChannelChild(const nsAString& aOrigin,
const nsAString& aChannel)
BroadcastChannelChild::BroadcastChannelChild(const nsAString& aOrigin)
: mOrigin(aOrigin)
, mChannel(aChannel)
, mActorDestroyed(false)
{
}

View File

@ -37,9 +37,7 @@ public:
}
private:
BroadcastChannelChild(const nsAString& aOrigin,
const nsAString& aChannel);
explicit BroadcastChannelChild(const nsAString& aOrigin);
~BroadcastChannelChild();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
@ -49,7 +47,6 @@ private:
BroadcastChannel* mBC;
nsString mOrigin;
nsString mChannel;
bool mActorDestroyed;
};

View File

@ -18,10 +18,12 @@ 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);
@ -41,7 +43,7 @@ BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData)
return false;
}
mService->PostMessage(this, aData, mOrigin, mChannel);
mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing);
return true;
}
@ -77,11 +79,14 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy)
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() ||

View File

@ -24,11 +24,13 @@ class BroadcastChannelParent final : public PBroadcastChannelParent
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
@ -41,6 +43,7 @@ private:
nsRefPtr<BroadcastChannelService> mService;
nsString mOrigin;
nsString mChannel;
bool mPrivateBrowsing;
};
} // dom namespace

View File

@ -83,11 +83,13 @@ 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);
@ -116,6 +118,7 @@ struct MOZ_STACK_CLASS PostMessageData final
nsTArray<nsRefPtr<FileImpl>> mFiles;
const nsString mOrigin;
const nsString mChannel;
bool mPrivateBrowsing;
};
PLDHashOperator
@ -128,7 +131,8 @@ PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
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;
@ -140,13 +144,14 @@ 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);
}

View File

@ -32,7 +32,8 @@ public:
void PostMessage(BroadcastChannelParent* aParent,
const ClonedMessageData& aData,
const nsAString& aOrigin,
const nsAString& aChannel);
const nsAString& aChannel,
bool aPrivateBrowsing);
private:
BroadcastChannelService();

View File

@ -24,6 +24,7 @@ LOCAL_INCLUDES += [
]
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -0,0 +1,2 @@
<!DOCTYPE HTML>
<html><body></body></html>

View File

@ -0,0 +1,5 @@
[DEFAULT]
support-files =
blank.html
[test_broadcastchannel_private_browsing.html]

View File

@ -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>

View File

@ -220,10 +220,11 @@ BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
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();
}

View File

@ -86,7 +86,8 @@ protected:
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;

View File

@ -255,12 +255,13 @@ 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 {
@ -328,7 +329,8 @@ BackgroundParentImpl::RecvPBroadcastChannelConstructor(
PBroadcastChannelParent* actor,
const PrincipalInfo& aPrincipalInfo,
const nsString& aOrigin,
const nsString& aChannel)
const nsString& aChannel,
const bool& aPrivateBrowsing)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();

View File

@ -73,13 +73,15 @@ protected:
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;

View File

@ -46,7 +46,8 @@ parent:
PVsync();
PMedia();
PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel);
PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel,
bool privateBrowsing);
RegisterServiceWorker(ServiceWorkerRegistrationData data);
UnregisterServiceWorker(PrincipalInfo principalInfo,