Bug 1218363 - nsIServiceWorkerManager should notify its listeners when a service worker is (un)registered;r=catalinb

This commit is contained in:
Eddy Bruel 2015-11-04 11:08:39 +01:00
Родитель a1dd9fc19e
Коммит 03e4076412
6 изменённых файлов: 215 добавлений и 1 удалений

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

@ -34,7 +34,15 @@ interface nsIServiceWorkerRegistrationInfo : nsISupports
readonly attribute DOMString waitingCacheName;
};
[scriptable, builtinclass, uuid(10f80c8c-7bf5-479e-a8d8-12ef50c802e8)]
[scriptable, uuid(9e523e7c-ad6f-4df0-8077-c74aebbc679d)]
interface nsIServiceWorkerManagerListener : nsISupports
{
void onRegister(in nsIServiceWorkerRegistrationInfo aInfo);
void onUnregister(in nsIServiceWorkerRegistrationInfo aInfo);
};
[scriptable, builtinclass, uuid(2f61820a-1e9a-4c16-bf1c-ce182c5f5d6d)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@ -145,6 +153,10 @@ interface nsIServiceWorkerManager : nsISupports
[optional, array, size_is(aDataLength)] in uint8_t aDataBytes);
void sendPushSubscriptionChangeEvent(in ACString aOriginAttributes,
in ACString scope);
void addListener(in nsIServiceWorkerManagerListener aListener);
void removeListener(in nsIServiceWorkerManagerListener aListener);
};
%{ C++

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

@ -2710,6 +2710,7 @@ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
// Perfect match!
if (aScope.Equals(current)) {
data->mInfos.Put(aScope, aInfo);
swm->NotifyListenersOnRegister(aInfo);
return;
}
@ -2719,12 +2720,14 @@ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
if (StringBeginsWith(aScope, current)) {
data->mOrderedScopes.InsertElementAt(i, aScope);
data->mInfos.Put(aScope, aInfo);
swm->NotifyListenersOnRegister(aInfo);
return;
}
}
data->mOrderedScopes.AppendElement(aScope);
data->mInfos.Put(aScope, aInfo);
swm->NotifyListenersOnRegister(aInfo);
}
/* static */ bool
@ -2791,8 +2794,12 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
return;
}
RefPtr<ServiceWorkerRegistrationInfo> info;
data->mInfos.Get(aRegistration->mScope, getter_AddRefs(info));
data->mInfos.Remove(aRegistration->mScope);
data->mOrderedScopes.RemoveElement(aRegistration->mScope);
swm->NotifyListenersOnUnregister(info);
swm->MaybeRemoveRegistrationInfo(scopeKey);
}
@ -3877,6 +3884,34 @@ ServiceWorkerManager::RemoveAllRegistrations(OriginAttributes* aParams)
}
}
NS_IMETHODIMP
ServiceWorkerManager::AddListener(nsIServiceWorkerManagerListener* aListener)
{
AssertIsOnMainThread();
if (mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}
mListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerManager::RemoveListener(nsIServiceWorkerManagerListener* aListener)
{
AssertIsOnMainThread();
if (!mListeners.Contains(aListener)) {
return NS_ERROR_INVALID_ARG;
}
mListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
ServiceWorkerManager::Observe(nsISupports* aSubject,
const char* aTopic,
@ -3997,6 +4032,26 @@ ServiceWorkerManager::PropagateUnregister(nsIPrincipal* aPrincipal,
return NS_OK;
}
void
ServiceWorkerManager::NotifyListenersOnRegister(
nsIServiceWorkerRegistrationInfo* aInfo)
{
nsTArray<nsCOMPtr<nsIServiceWorkerManagerListener>> listeners(mListeners);
for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnRegister(aInfo);
}
}
void
ServiceWorkerManager::NotifyListenersOnUnregister(
nsIServiceWorkerRegistrationInfo* aInfo)
{
nsTArray<nsCOMPtr<nsIServiceWorkerManagerListener>> listeners(mListeners);
for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnUnregister(aInfo);
}
}
void
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
{

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

@ -597,6 +597,14 @@ private:
nsTArray<PendingOperation> mPendingOperations;
bool mShuttingDown;
nsTArray<nsCOMPtr<nsIServiceWorkerManagerListener>> mListeners;
void
NotifyListenersOnRegister(nsIServiceWorkerRegistrationInfo* aRegistration);
void
NotifyListenersOnUnregister(nsIServiceWorkerRegistrationInfo* aRegistration);
};
} // namespace workers

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

@ -3,8 +3,10 @@ skip-if = buildapp == 'b2g' || os == 'android'
support-files =
app/*
app2/*
worker.js
[test_aboutserviceworkers.html]
skip-if = true #bug 1193319
[test_app_installation.html]
[test_privateBrowsing.html]
[test_serviceworkermanager.xul]

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

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
window.onmessage = function (event) {
if (event.data !== "register") {
return;
}
var promise = navigator.serviceWorker.register("worker.js");
window.onmessage = function (event) {
if (event.data !== "unregister") {
return;
}
promise.then(function (registration) {
registration.unregister();
});
window.onmessage = null;
};
};
</script>
</head>
<body>
This is a test page.
</body>
<html>

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

@ -0,0 +1,111 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<window title="Test for ServiceWorkerManager"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript">
<![CDATA[
let { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Task.jsm");
let swm = Cc["@mozilla.org/serviceworkers/manager;1"].
getService(Ci.nsIServiceWorkerManager);
function waitForIframeLoad(iframe) {
return new Promise(function (resolve) {
iframe.onload = resolve;
});
}
function waitForRegister(scope) {
return new Promise(function (resolve) {
let listener = {
onRegister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(registration);
}
};
swm.addListener(listener);
});
}
function waitForUnregister(scope) {
return new Promise(function (resolve) {
let listener = {
onUnregister: function (registration) {
if (registration.scope !== scope) {
return;
}
swm.removeListener(listener);
resolve(registration);
}
};
swm.addListener(listener);
});
}
let EXAMPLE_URL = "https://example.com/chrome/dom/workers/test/serviceworkers/";
let IFRAME_URL = EXAMPLE_URL + "serviceworkermanager_iframe.html";
function test() {
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, function () {
Task.spawn(function *() {
let registrations = swm.getAllRegistrations();
is(registrations.length, 0);
let iframe = $("iframe");
let promise = waitForIframeLoad(iframe);
iframe.src = IFRAME_URL;
yield promise;
info("Check that the service worker manager notifies its listeners " +
"when a service worker is registered.");
promise = waitForRegister(EXAMPLE_URL);
iframe.contentWindow.postMessage("register", "*");
let registration = yield promise;
registrations = swm.getAllRegistrations();
is(registrations.length, 1);
is(registrations.queryElementAt(0, Ci.nsIServiceWorkerRegistrationInfo),
registration);
info("Check that the service worker manager notifies its listeners " +
"when a service worker is unregistered.");
promise = waitForUnregister(EXAMPLE_URL);
iframe.contentWindow.postMessage("unregister", "*");
registration = yield promise;
registrations = swm.getAllRegistrations();
is(registrations.length, 0);
SimpleTest.finish();
});
});
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
<iframe id="iframe"></iframe>
</body>
<label id="test-result"/>
</window>