--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -1279,30 +1279,48 @@ NS_IMPL_ISUPPORTS_INHERITED0(WorkerNotif
class ServiceWorkerNotificationObserver final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
ServiceWorkerNotificationObserver(const nsAString& aScope,
nsIPrincipal* aPrincipal,
- const nsAString& aID)
- : mScope(aScope), mID(aID), mPrincipal(aPrincipal)
+ 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)
+ : mScope(aScope), mID(aID), mPrincipal(aPrincipal), mTitle(aTitle)
+ , mDir(aDir), mLang(aLang), mBody(aBody), mTag(aTag), mIcon(aIcon)
+ , mData(aData), mBehavior(aBehavior)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
}
private:
~ServiceWorkerNotificationObserver()
{}
const nsString mScope;
const nsString mID;
nsCOMPtr<nsIPrincipal> mPrincipal;
+ const nsString mTitle;
+ const nsString mDir;
+ const nsString mLang;
+ const nsString mBody;
+ const nsString mTag;
+ const nsString mIcon;
+ const nsString mData;
+ const nsString mBehavior;
};
NS_IMPL_ISUPPORTS(ServiceWorkerNotificationObserver, nsIObserver)
// For ServiceWorkers.
bool
Notification::DispatchNotificationClickEvent()
{
@@ -1549,112 +1567,61 @@ WorkerNotificationObserver::Observe(nsIS
MOZ_ASSERT(r);
if (!r->Dispatch()) {
NS_WARNING("Could not dispatch event to worker notification");
}
return NS_OK;
}
-class NotificationClickEventCallback final : public nsINotificationStorageCallback
+NS_IMETHODIMP
+ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
+ const char* aTopic,
+ const char16_t* aData)
{
-public:
- NS_DECL_ISUPPORTS
-
- NotificationClickEventCallback(nsIPrincipal* aPrincipal,
- const nsAString& aScope)
- : mPrincipal(aPrincipal), mScope(aScope)
- {
- MOZ_ASSERT(aPrincipal);
- }
+ AssertIsOnMainThread();
- NS_IMETHOD Handle(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& aServiceWorkerRegistrationID) override
- {
- MOZ_ASSERT(!aID.IsEmpty());
- MOZ_ASSERT(mScope.Equals(aServiceWorkerRegistrationID));
-
- AssertIsOnMainThread();
-
+ 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),
- aID,
- aTitle,
- aDir,
- aLang,
- aBody,
- aTag,
- aIcon,
- aData,
- aBehavior);
+ mID,
+ mTitle,
+ mDir,
+ mLang,
+ mBody,
+ mTag,
+ mIcon,
+ mData,
+ mBehavior);
}
return NS_OK;
}
- NS_IMETHOD Done() override
- {
- return NS_OK;
- }
-
-private:
- ~NotificationClickEventCallback()
- {
- }
-
- nsCOMPtr<nsIPrincipal> mPrincipal;
- nsString mScope;
-};
-
-NS_IMPL_ISUPPORTS(NotificationClickEventCallback, nsINotificationStorageCallback)
-
-NS_IMETHODIMP
-ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
-{
- AssertIsOnMainThread();
- // Persistent notifications only care about the click event.
- if (!strcmp("alertclickcallback", aTopic)) {
- nsresult rv;
- nsCOMPtr<nsINotificationStorage> notificationStorage =
- do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv);
+ if (!strcmp("alertfinished", aTopic)) {
+ nsString origin;
+ nsresult rv = Notification::GetOrigin(mPrincipal, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- nsCOMPtr<nsINotificationStorageCallback> callback =
- new NotificationClickEventCallback(mPrincipal, mScope);
-
- nsAutoString origin;
- rv = Notification::GetOrigin(mPrincipal, origin);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- rv = notificationStorage->GetByID(origin, mID, callback);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
+ // Remove closed or dismissed persistent notifications.
+ nsCOMPtr<nsINotificationStorage> notificationStorage =
+ do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID);
+ if (notificationStorage) {
+ notificationStorage->Delete(origin, mID);
}
}
return NS_OK;
}
bool
Notification::IsInPrivateBrowsing()
@@ -1752,17 +1719,31 @@ Notification::ShowInternal()
} else {
observer = new MainThreadNotificationObserver(Move(ownership));
}
} else {
// This observer does not care about the Notification. It will be released
// at the end of this function.
//
// The observer is wholly owned by the NotificationObserver passed to the alert service.
- observer = new ServiceWorkerNotificationObserver(mScope, GetPrincipal(), mID);
+ nsAutoString behavior;
+ if (NS_WARN_IF(!mBehavior.ToJSON(behavior))) {
+ behavior.Truncate();
+ }
+ observer = new ServiceWorkerNotificationObserver(mScope,
+ GetPrincipal(),
+ mID,
+ mTitle,
+ DirectionToString(mDir),
+ mLang,
+ mBody,
+ mTag,
+ iconUrl,
+ mDataAsBase64,
+ behavior);
}
MOZ_ASSERT(observer);
nsCOMPtr<nsIObserver> alertObserver = new NotificationObserver(observer,
GetPrincipal(),
IsInPrivateBrowsing());
#ifdef MOZ_B2G
--- a/dom/workers/test/serviceworkers/test_notification_get.html
+++ b/dom/workers/test/serviceworkers/test_notification_get.html
@@ -54,16 +54,50 @@
}
function unregisterAlternateSWAndAddNotification() {
return testFrame('notification_alt/unregister.html').then(function() {
ok(true, "unregistered alternate service worker.");
});
}
+ function testDismiss() {
+ // Dismissed persistent notifications should be removed from the
+ // notification list.
+ var alertsService = SpecialPowers.Cc["@mozilla.org/alerts-service;1"]
+ .getService(SpecialPowers.Ci.nsIAlertsService);
+ return navigator.serviceWorker.getRegistration("./notification/")
+ .then(function(reg) {
+ return reg.showNotification(
+ "This is a notification that will be closed", { tag: "dismiss" })
+ .then(function() {
+ return reg;
+ });
+ }).then(function(reg) {
+ return reg.getNotifications()
+ .then(function(notifications) {
+ is(notifications.length, 1, "There should be one visible notification");
+ is(notifications[0].tag, "dismiss", "Tag should match");
+
+ // Simulate dismissing the notification by using the alerts service
+ // directly, instead of `Notification#close`.
+ var principal = SpecialPowers.wrap(document).nodePrincipal;
+ var id = principal.origin + "#tag:dismiss";
+ alertsService.closeAlert(id, principal);
+
+ return reg;
+ });
+ }).then(function(reg) {
+ return reg.getNotifications();
+ }).then(function(notifications) {
+ // Make sure dismissed notifications are no longer retrieved.
+ is(notifications.length, 0, "There should be no more stored notifications");
+ });
+ }
+
function testGet() {
// Non persistent notifications will not show up in getNotification().
var n = new Notification("Scope does not match");
var options = NotificationTest.payload;
return navigator.serviceWorker.getRegistration("./notification/")
.then(function(reg) {
return reg.showNotification("This is a title", options)
.then(function() {
@@ -162,16 +196,17 @@
["dom.webnotifications.serviceworker.enabled", true],
["notification.prompt.testing", true],
]}, function() {
registerSW()
.then(testGet)
.then(testGetWorker)
.then(testGetServiceWorker)
.then(testAcrossThreads)
+ .then(testDismiss)
.then(unregisterSW)
.then(function() {
MockServices.unregister();
SimpleTest.finish();
});
});
</script>
</body>