зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1265841 - Implement the `notificationclose` service worker event. r=wchen,baku
MozReview-Commit-ID: EQfCbQKqn9H --HG-- extra : rebase_source : 2dad51a3c148db794769fb7c64c28f81ea2ca6ff extra : histedit_source : 254e2e372ba605f74c1f5106f40b207e492e85e1
This commit is contained in:
Родитель
02d8a1e5d9
Коммит
d9d287a14e
|
@ -856,6 +856,7 @@ GK_ATOM(onmapsendmessagereq, "onmapsendmessagereq")
|
|||
GK_ATOM(onmapmessageupdatereq, "onmapmessageupdatereq")
|
||||
GK_ATOM(onnewrdsgroup, "onnewrdsgroup")
|
||||
GK_ATOM(onnotificationclick, "onnotificationclick")
|
||||
GK_ATOM(onnotificationclose, "onnotificationclose")
|
||||
GK_ATOM(onnoupdate, "onnoupdate")
|
||||
GK_ATOM(onobexpasswordreq, "onobexpasswordreq")
|
||||
GK_ATOM(onobsolete, "onobsolete")
|
||||
|
|
|
@ -185,6 +185,19 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
in AString aIcon,
|
||||
in AString aData,
|
||||
in AString aBehavior);
|
||||
|
||||
void sendNotificationCloseEvent(in ACString aOriginSuffix,
|
||||
in ACString scope,
|
||||
in AString aID,
|
||||
in AString aTitle,
|
||||
in AString aDir,
|
||||
in AString aLang,
|
||||
in AString aBody,
|
||||
in AString aTag,
|
||||
in AString aIcon,
|
||||
in AString aData,
|
||||
in AString aBehavior);
|
||||
|
||||
[optional_argc] void sendPushEvent(in ACString aOriginAttributes,
|
||||
in ACString aScope,
|
||||
[optional] in uint32_t aDataLength,
|
||||
|
|
|
@ -1590,29 +1590,31 @@ ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsAutoCString originSuffix;
|
||||
nsresult rv = mPrincipal->GetOriginSuffix(originSuffix);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
mozilla::services::GetServiceWorkerManager();
|
||||
if (NS_WARN_IF(!swm)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!strcmp("alertclickcallback", aTopic)) {
|
||||
nsAutoCString originSuffix;
|
||||
nsresult rv = mPrincipal->GetOriginSuffix(originSuffix);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
mozilla::services::GetServiceWorkerManager();
|
||||
|
||||
if (swm) {
|
||||
swm->SendNotificationClickEvent(originSuffix,
|
||||
NS_ConvertUTF16toUTF8(mScope),
|
||||
mID,
|
||||
mTitle,
|
||||
mDir,
|
||||
mLang,
|
||||
mBody,
|
||||
mTag,
|
||||
mIcon,
|
||||
mData,
|
||||
mBehavior);
|
||||
}
|
||||
rv = swm->SendNotificationClickEvent(originSuffix,
|
||||
NS_ConvertUTF16toUTF8(mScope),
|
||||
mID,
|
||||
mTitle,
|
||||
mDir,
|
||||
mLang,
|
||||
mBody,
|
||||
mTag,
|
||||
mIcon,
|
||||
mData,
|
||||
mBehavior);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1629,6 +1631,20 @@ ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
|
|||
if (notificationStorage) {
|
||||
notificationStorage->Delete(origin, mID);
|
||||
}
|
||||
|
||||
rv = swm->SendNotificationCloseEvent(originSuffix,
|
||||
NS_ConvertUTF16toUTF8(mScope),
|
||||
mID,
|
||||
mTitle,
|
||||
mDir,
|
||||
mLang,
|
||||
mBody,
|
||||
mTag,
|
||||
mIcon,
|
||||
mData,
|
||||
mBehavior);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -23,4 +23,5 @@ dictionary NotificationEventInit : ExtendableEventInit {
|
|||
|
||||
partial interface ServiceWorkerGlobalScope {
|
||||
attribute EventHandler onnotificationclick;
|
||||
attribute EventHandler onnotificationclose;
|
||||
};
|
||||
|
|
|
@ -959,6 +959,37 @@ ServiceWorkerManager::SendPushSubscriptionChangeEvent(const nsACString& aOriginA
|
|||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
ServiceWorkerManager::SendNotificationEvent(const nsAString& aEventName,
|
||||
const nsACString& aOriginSuffix,
|
||||
const nsACString& aScope,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior)
|
||||
{
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (!attrs.PopulateFromSuffix(aOriginSuffix)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ServiceWorkerInfo* info = GetActiveWorkerInfoForScope(attrs, aScope);
|
||||
if (!info) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ServiceWorkerPrivate* workerPrivate = info->WorkerPrivate();
|
||||
return workerPrivate->SendNotificationEvent(aEventName, aID, aTitle, aDir,
|
||||
aLang, aBody, aTag,
|
||||
aIcon, aData, aBehavior,
|
||||
NS_ConvertUTF8toUTF16(aScope));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::SendNotificationClickEvent(const nsACString& aOriginSuffix,
|
||||
const nsACString& aScope,
|
||||
|
@ -972,21 +1003,27 @@ ServiceWorkerManager::SendNotificationClickEvent(const nsACString& aOriginSuffix
|
|||
const nsAString& aData,
|
||||
const nsAString& aBehavior)
|
||||
{
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (!attrs.PopulateFromSuffix(aOriginSuffix)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return SendNotificationEvent(NS_LITERAL_STRING(NOTIFICATION_CLICK_EVENT_NAME),
|
||||
aOriginSuffix, aScope, aID, aTitle, aDir, aLang,
|
||||
aBody, aTag, aIcon, aData, aBehavior);
|
||||
}
|
||||
|
||||
ServiceWorkerInfo* info = GetActiveWorkerInfoForScope(attrs, aScope);
|
||||
if (!info) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ServiceWorkerPrivate* workerPrivate = info->WorkerPrivate();
|
||||
return workerPrivate->SendNotificationClickEvent(aID, aTitle, aDir,
|
||||
aLang, aBody, aTag,
|
||||
aIcon, aData, aBehavior,
|
||||
NS_ConvertUTF8toUTF16(aScope));
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::SendNotificationCloseEvent(const nsACString& aOriginSuffix,
|
||||
const nsACString& aScope,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior)
|
||||
{
|
||||
return SendNotificationEvent(NS_LITERAL_STRING(NOTIFICATION_CLOSE_EVENT_NAME),
|
||||
aOriginSuffix, aScope, aID, aTitle, aDir, aLang,
|
||||
aBody, aTag, aIcon, aData, aBehavior);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -431,6 +431,20 @@ private:
|
|||
|
||||
void
|
||||
MaybeSendUnregister(nsIPrincipal* aPrincipal, const nsACString& aScope);
|
||||
|
||||
nsresult
|
||||
SendNotificationEvent(const nsAString& aEventName,
|
||||
const nsACString& aOriginSuffix,
|
||||
const nsACString& aScope,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior);
|
||||
};
|
||||
|
||||
} // namespace workers
|
||||
|
|
|
@ -1079,8 +1079,9 @@ ClearWindowAllowedRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPriv
|
|||
return true;
|
||||
}
|
||||
|
||||
class SendNotificationClickEventRunnable final : public ExtendableEventWorkerRunnable
|
||||
class SendNotificationEventRunnable final : public ExtendableEventWorkerRunnable
|
||||
{
|
||||
const nsString mEventName;
|
||||
const nsString mID;
|
||||
const nsString mTitle;
|
||||
const nsString mDir;
|
||||
|
@ -1093,19 +1094,21 @@ class SendNotificationClickEventRunnable final : public ExtendableEventWorkerRun
|
|||
const nsString mScope;
|
||||
|
||||
public:
|
||||
SendNotificationClickEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
KeepAliveToken* aKeepAliveToken,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope)
|
||||
SendNotificationEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
KeepAliveToken* aKeepAliveToken,
|
||||
const nsAString& aEventName,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope)
|
||||
: ExtendableEventWorkerRunnable(aWorkerPrivate, aKeepAliveToken)
|
||||
, mEventName(aEventName)
|
||||
, mID(aID)
|
||||
, mTitle(aTitle)
|
||||
, mDir(aDir)
|
||||
|
@ -1144,8 +1147,7 @@ public:
|
|||
nei.mCancelable = false;
|
||||
|
||||
RefPtr<NotificationEvent> event =
|
||||
NotificationEvent::Constructor(target,
|
||||
NS_LITERAL_STRING("notificationclick"),
|
||||
NotificationEvent::Constructor(target, mEventName,
|
||||
nei, result);
|
||||
if (NS_WARN_IF(result.Failed())) {
|
||||
return false;
|
||||
|
@ -1170,27 +1172,37 @@ public:
|
|||
} // namespace anonymous
|
||||
|
||||
nsresult
|
||||
ServiceWorkerPrivate::SendNotificationClickEvent(const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope)
|
||||
ServiceWorkerPrivate::SendNotificationEvent(const nsAString& aEventName,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope)
|
||||
{
|
||||
nsresult rv = SpawnWorkerIfNeeded(NotificationClickEvent, nullptr);
|
||||
WakeUpReason why;
|
||||
if (aEventName.EqualsLiteral(NOTIFICATION_CLICK_EVENT_NAME)) {
|
||||
why = NotificationClickEvent;
|
||||
gDOMDisableOpenClickDelay = Preferences::GetInt("dom.disable_open_click_delay");
|
||||
} else if (aEventName.EqualsLiteral(NOTIFICATION_CLOSE_EVENT_NAME)) {
|
||||
why = NotificationCloseEvent;
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid notification event name");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = SpawnWorkerIfNeeded(why, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
gDOMDisableOpenClickDelay = Preferences::GetInt("dom.disable_open_click_delay");
|
||||
|
||||
RefPtr<WorkerRunnable> r =
|
||||
new SendNotificationClickEventRunnable(mWorkerPrivate, mKeepAliveToken,
|
||||
aID, aTitle, aDir, aLang,
|
||||
aBody, aTag, aIcon, aData,
|
||||
aBehavior, aScope);
|
||||
new SendNotificationEventRunnable(mWorkerPrivate, mKeepAliveToken,
|
||||
aEventName, aID, aTitle, aDir, aLang,
|
||||
aBody, aTag, aIcon, aData, aBehavior,
|
||||
aScope);
|
||||
if (NS_WARN_IF(!r->Dispatch())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
#define NOTIFICATION_CLICK_EVENT_NAME "notificationclick"
|
||||
#define NOTIFICATION_CLOSE_EVENT_NAME "notificationclose"
|
||||
|
||||
class nsIInterceptedChannel;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -93,16 +96,17 @@ public:
|
|||
SendPushSubscriptionChangeEvent();
|
||||
|
||||
nsresult
|
||||
SendNotificationClickEvent(const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope);
|
||||
SendNotificationEvent(const nsAString& aEventName,
|
||||
const nsAString& aID,
|
||||
const nsAString& aTitle,
|
||||
const nsAString& aDir,
|
||||
const nsAString& aLang,
|
||||
const nsAString& aBody,
|
||||
const nsAString& aTag,
|
||||
const nsAString& aIcon,
|
||||
const nsAString& aData,
|
||||
const nsAString& aBehavior,
|
||||
const nsAString& aScope);
|
||||
|
||||
nsresult
|
||||
SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
|
@ -149,6 +153,7 @@ private:
|
|||
PushSubscriptionChangeEvent,
|
||||
MessageEvent,
|
||||
NotificationClickEvent,
|
||||
NotificationCloseEvent,
|
||||
LifeCycleEvent,
|
||||
AttachEvent
|
||||
};
|
||||
|
|
|
@ -243,6 +243,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope,
|
||||
WorkerGlobalScope)
|
||||
IMPL_EVENT_HANDLER(notificationclick)
|
||||
IMPL_EVENT_HANDLER(notificationclose)
|
||||
|
||||
ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsACString& aScope);
|
||||
|
||||
|
|
|
@ -133,6 +133,8 @@ support-files =
|
|||
notificationclick.js
|
||||
notificationclick_focus.html
|
||||
notificationclick_focus.js
|
||||
notificationclose.html
|
||||
notificationclose.js
|
||||
worker_updatefoundevent.js
|
||||
worker_updatefoundevent2.js
|
||||
updatefoundevent.html
|
||||
|
@ -249,6 +251,7 @@ tags = mcb
|
|||
[test_notificationclick.html]
|
||||
[test_notificationclick_focus.html]
|
||||
[test_notificationclick-otherwindow.html]
|
||||
[test_notificationclose.html]
|
||||
[test_opaque_intercept.html]
|
||||
[test_openWindow.html]
|
||||
[test_origin_after_redirect.html]
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1265841 - controlled page</title>
|
||||
<script class="testbody" type="text/javascript">
|
||||
var testWindow = parent;
|
||||
if (opener) {
|
||||
testWindow = opener;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.ready.then(function(swr) {
|
||||
return swr.showNotification(
|
||||
"Hi there. The ServiceWorker should receive a close event for this.",
|
||||
{ data: { complex: ["jsval", 5] }}).then(function() {
|
||||
return swr;
|
||||
});
|
||||
}).then(function(swr) {
|
||||
return swr.getNotifications();
|
||||
}).then(function(notifications) {
|
||||
notifications.forEach(function(notification) {
|
||||
notification.close();
|
||||
});
|
||||
});
|
||||
|
||||
navigator.serviceWorker.onmessage = function(msg) {
|
||||
testWindow.callback(msg.data.result);
|
||||
};
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
//
|
||||
onnotificationclose = function(e) {
|
||||
self.clients.matchAll().then(function(clients) {
|
||||
if (clients.length === 0) {
|
||||
dump("********************* CLIENTS LIST EMPTY! Test will timeout! ***********************\n");
|
||||
return;
|
||||
}
|
||||
|
||||
clients.forEach(function(client) {
|
||||
client.postMessage({ result: e.notification.data &&
|
||||
e.notification.data['complex'] &&
|
||||
e.notification.data['complex'][0] == "jsval" &&
|
||||
e.notification.data['complex'][1] == 5 });
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1265841
|
||||
-->
|
||||
<head>
|
||||
<title>Bug 1265841 - Test ServiceWorkerGlobalScope.notificationclose event.</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265841">Bug 1265841</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<script type="text/javascript">
|
||||
SimpleTest.requestFlakyTimeout("Mock alert service dispatches show, click, and close events.");
|
||||
|
||||
function testFrame(src) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = src;
|
||||
window.callback = function(result) {
|
||||
window.callback = null;
|
||||
document.body.removeChild(iframe);
|
||||
iframe = null;
|
||||
ok(result, "Got notificationclose event with correct data.");
|
||||
MockServices.unregister();
|
||||
registration.unregister().then(function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
var registration;
|
||||
|
||||
function runTest() {
|
||||
MockServices.register();
|
||||
testFrame('notificationclose.html');
|
||||
navigator.serviceWorker.register("notificationclose.js", { scope: "notificationclose.html" }).then(function(reg) {
|
||||
registration = reg;
|
||||
}, function(e) {
|
||||
ok(false, "registration should have passed!");
|
||||
});
|
||||
};
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.webnotifications.workers.enabled", true],
|
||||
["dom.webnotifications.serviceworker.enabled", true],
|
||||
["notification.prompt.testing", true],
|
||||
]}, runTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче