Bug 1141274 - Allocate shared workers and service workers from separate namespaces; r=nsm

This patch makes sure that we never reuse a WorkerPrivate belonging
to a shared worker for a service worker and vice versa.
This commit is contained in:
Ehsan Akhgari 2015-03-10 11:44:04 -04:00
parent c27574a87c
commit 890be1ec6d
4 changed files with 114 additions and 7 deletions

View File

@ -265,14 +265,23 @@ GetWorkerPref(const nsACString& aPref,
return result;
}
// This function creates a key for a SharedWorker composed by "name|scriptSpec".
// This function creates a key for a SharedWorker composed by "shared|name|scriptSpec"
// and a key for a ServiceWorker composed by "service|scope|scriptSpec".
// If the name contains a '|', this will be replaced by '||'.
void
GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName,
nsCString& aKey)
WorkerType aWorkerType, nsCString& aKey)
{
aKey.Truncate();
aKey.SetCapacity(aScriptSpec.Length() + aName.Length() + 1);
NS_NAMED_LITERAL_CSTRING(sharedPrefix, "shared|");
NS_NAMED_LITERAL_CSTRING(servicePrefix, "service|");
MOZ_ASSERT(servicePrefix.Length() > sharedPrefix.Length());
MOZ_ASSERT(aWorkerType == WorkerTypeShared ||
aWorkerType == WorkerTypeService);
aKey.SetCapacity(servicePrefix.Length() + aScriptSpec.Length() +
aName.Length() + 1);
aKey.Append(aWorkerType == WorkerTypeService ? servicePrefix : sharedPrefix);
nsACString::const_iterator start, end;
aName.BeginReading(start);
@ -1463,7 +1472,8 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
const nsCString& sharedWorkerName = aWorkerPrivate->SharedWorkerName();
nsAutoCString key;
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName, key);
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName,
aWorkerPrivate->Type(), key);
MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key));
SharedWorkerInfo* sharedWorkerInfo =
@ -1568,7 +1578,8 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
if (match.mSharedWorkerInfo) {
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
match.mSharedWorkerInfo->mName,
aWorkerPrivate->Type(), key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}
@ -2297,7 +2308,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString key;
GenerateSharedWorkerKey(scriptSpec, aName, key);
GenerateSharedWorkerKey(scriptSpec, aName, aType, key);
if (mDomainMap.Get(aLoadInfo->mDomain, &domainInfo) &&
domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) {
@ -2372,7 +2383,8 @@ RuntimeService::ForgetSharedWorker(WorkerPrivate* aWorkerPrivate)
if (match.mSharedWorkerInfo) {
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
match.mSharedWorkerInfo->mName,
aWorkerPrivate->Type(), key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}

View File

@ -30,6 +30,7 @@ support-files =
serviceworker_wrapper.js
message_receiver.html
close_test.js
serviceworker_not_sharedworker.js
[test_unregister.html]
[test_installation_simple.html]
@ -46,3 +47,4 @@ support-files =
[test_match_all_client_properties.html]
[test_close.html]
[test_serviceworker_interfaces.html]
[test_serviceworker_not_sharedworker.html]

View File

@ -0,0 +1,21 @@
function OnMessage(e)
{
if (e.data.msg == "whoareyou") {
if ("ServiceWorker" in self) {
self.clients.matchAll().then(function(clients) {
clients[0].postMessage({result: "serviceworker"});
});
} else {
port.postMessage({result: "sharedworker"});
}
}
};
var port;
onconnect = function(e) {
port = e.ports[0];
port.onmessage = OnMessage;
port.start();
};
onmessage = OnMessage;

View File

@ -0,0 +1,72 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1141274 - test that service workers and shared workers are separate</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
const SCOPE = "http://mochi.test:8888/tests/dom/workers/test/serviceworkers/";
function runTest() {
navigator.serviceWorker.register("serviceworker_not_sharedworker.js",
{scope: SCOPE})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
e.target.onstatechange = null;
setupSW(registration);
};
} else {
setupSW(registration);
}
});
}
var sw, worker;
function setupSW(registration) {
sw = registration.waiting || registration.active;
worker = new SharedWorker("serviceworker_not_sharedworker.js", SCOPE);
worker.port.start();
iframe = document.querySelector("iframe");
iframe.src = "message_receiver.html";
iframe.onload = function() {
window.onmessage = function(e) {
is(e.data.result, "serviceworker", "We should be talking to a service worker");
window.onmessage = null;
worker.port.onmessage = function(e) {
is(e.data.result, "sharedworker", "We should be talking to a shared worker");
registration.unregister().then(function(success) {
ok(success, "unregister should succeed");
SimpleTest.finish();
});
};
worker.port.postMessage({msg: "whoareyou"});
};
sw.postMessage({msg: "whoareyou"});
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
};
</script>
</pre>
</body>
</html>