зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1218363 - nsIServiceWorkerManager should notify its listeners when a service worker is (un)registered;r=catalinb
This commit is contained in:
Родитель
a1dd9fc19e
Коммит
03e4076412
|
@ -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>
|
Загрузка…
Ссылка в новой задаче