Bug 1525245 - Stabilize cookiePolicy/cookiePermission for live documents - part 5 - BroadcastChannel must be blocked when cookie jar access is denied to avoid communication between live and new documents, r=Ehsan

Differential Revision: https://phabricator.services.mozilla.com/D18953

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrea Marchesini 2019-02-26 17:37:46 +00:00
Родитель 29eaa174c6
Коммит 084ddbbf6d
3 изменённых файлов: 91 добавлений и 19 удалений

Просмотреть файл

@ -67,15 +67,13 @@ nsIPrincipal* GetPrincipalFromThreadSafeWorkerRef(
class InitializeRunnable final : public WorkerMainThreadRunnable {
public:
InitializeRunnable(ThreadSafeWorkerRef* aWorkerRef, nsACString& aOrigin,
PrincipalInfo& aPrincipalInfo, bool* aThirdPartyWindow,
ErrorResult& aRv)
PrincipalInfo& aPrincipalInfo, ErrorResult& aRv)
: WorkerMainThreadRunnable(
aWorkerRef->Private(),
NS_LITERAL_CSTRING("BroadcastChannel :: Initialize")),
mWorkerRef(aWorkerRef),
mOrigin(aOrigin),
mPrincipalInfo(aPrincipalInfo),
mThirdPartyWindow(aThirdPartyWindow),
mRv(aRv) {
MOZ_ASSERT(mWorkerRef);
}
@ -111,9 +109,6 @@ class InitializeRunnable final : public WorkerMainThreadRunnable {
return true;
}
*mThirdPartyWindow =
nsContentUtils::IsThirdPartyWindowOrChannel(window, nullptr, nullptr);
return true;
}
@ -121,7 +116,6 @@ class InitializeRunnable final : public WorkerMainThreadRunnable {
RefPtr<ThreadSafeWorkerRef> mWorkerRef;
nsACString& mOrigin;
PrincipalInfo& mPrincipalInfo;
bool* mThirdPartyWindow;
ErrorResult& mRv;
};
@ -247,6 +241,14 @@ JSObject* BroadcastChannel::WrapObject(JSContext* aCx,
return nullptr;
}
// We want to allow opaque origins.
if (!principal->GetIsNullPrincipal() &&
nsContentUtils::StorageAllowedForWindow(window) <=
nsContentUtils::StorageAccess::eDeny) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
aRv = principal->GetOrigin(origin);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
@ -256,13 +258,6 @@ JSObject* BroadcastChannel::WrapObject(JSContext* aCx,
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
if (nsContentUtils::IsThirdPartyWindowOrChannel(window, nullptr, nullptr) &&
nsContentUtils::StorageAllowedForWindow(window) !=
nsContentUtils::StorageAccess::eAllow) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
} else {
JSContext* cx = aGlobal.Context();
@ -280,16 +275,15 @@ JSObject* BroadcastChannel::WrapObject(JSContext* aCx,
RefPtr<ThreadSafeWorkerRef> tsr = new ThreadSafeWorkerRef(workerRef);
bool thirdPartyWindow = false;
RefPtr<InitializeRunnable> runnable = new InitializeRunnable(
tsr, origin, principalInfo, &thirdPartyWindow, aRv);
RefPtr<InitializeRunnable> runnable =
new InitializeRunnable(tsr, origin, principalInfo, aRv);
runnable->Dispatch(Canceling, aRv);
if (aRv.Failed()) {
return nullptr;
}
if (thirdPartyWindow && !workerPrivate->IsStorageAllowed()) {
if (principalInfo.type() != PrincipalInfo::TNullPrincipalInfo &&
!workerPrivate->IsStorageAllowed()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}

Просмотреть файл

@ -3,5 +3,6 @@ support-files =
file_empty.html
head.js
[browser_broadcastChannel.js]
[browser_originattributes.js]
[browser_storage.js]

Просмотреть файл

@ -0,0 +1,77 @@
// BroadcastChannel is not considered part of CookieJar. It's not allowed to
// communicate with other windows with different cookie settings.
CookiePolicyHelper.runTest("BroadcastChannel", {
cookieJarAccessAllowed: async _ => {
new content.BroadcastChannel("hello");
ok(true, "BroadcastChannel be used");
},
cookieJarAccessDenied: async _ => {
try {
new content.BroadcastChannel("hello");
ok(false, "BroadcastChannel cannot be used!");
} catch (e) {
ok(true, "BroadcastChannel cannot be used!");
is(e.name, "SecurityError", "We want a security error message.");
}
}
});
CookiePolicyHelper.runTest("BroadcastChannel in workers", {
cookieJarAccessAllowed: async _ => {
function nonBlockingCode() {
new BroadcastChannel("hello");
postMessage(true);
}
let blob = new content.Blob([nonBlockingCode.toString() + "; nonBlockingCode();"]);
ok(blob, "Blob has been created");
let blobURL = content.URL.createObjectURL(blob);
ok(blobURL, "Blob URL has been created");
let worker = new content.Worker(blobURL);
ok(worker, "Worker has been created");
await new content.Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
resolve();
} else {
reject();
}
};
});
},
cookieJarAccessDenied: async _ => {
function blockingCode() {
try {
new BroadcastChannel("hello");
postMessage(false);
} catch (e) {
postMessage(e.name == "SecurityError");
}
}
let blob = new content.Blob([blockingCode.toString() + "; blockingCode();"]);
ok(blob, "Blob has been created");
let blobURL = content.URL.createObjectURL(blob);
ok(blobURL, "Blob URL has been created");
let worker = new content.Worker(blobURL);
ok(worker, "Worker has been created");
await new content.Promise((resolve, reject) => {
worker.onmessage = function(e) {
if (e) {
resolve();
} else {
reject();
}
};
});
}
});