diff options
Diffstat (limited to 'dom/notification/Notification.cpp')
-rw-r--r-- | dom/notification/Notification.cpp | 114 |
1 files changed, 71 insertions, 43 deletions
diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index fb5b0ea9a3..d0006941e9 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -161,29 +161,36 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NotificationStorageCallback) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END +nsCOMPtr<nsINotificationStorage> GetNotificationStorage(bool isPrivate) { + return do_GetService(isPrivate ? NS_MEMORY_NOTIFICATION_STORAGE_CONTRACTID + : NS_NOTIFICATION_STORAGE_CONTRACTID); +} + class NotificationGetRunnable final : public Runnable { + bool mIsPrivate; const nsString mOrigin; const nsString mTag; nsCOMPtr<nsINotificationStorageCallback> mCallback; public: NotificationGetRunnable(const nsAString& aOrigin, const nsAString& aTag, - nsINotificationStorageCallback* aCallback) + nsINotificationStorageCallback* aCallback, + bool aIsPrivate) : Runnable("NotificationGetRunnable"), + mIsPrivate(aIsPrivate), mOrigin(aOrigin), mTag(aTag), mCallback(aCallback) {} NS_IMETHOD Run() override { - nsresult rv; nsCOMPtr<nsINotificationStorage> notificationStorage = - do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + GetNotificationStorage(mIsPrivate); + if (NS_WARN_IF(!notificationStorage)) { + return NS_ERROR_UNEXPECTED; } - rv = notificationStorage->Get(mOrigin, mTag, mCallback); + nsresult rv = notificationStorage->Get(mOrigin, mTag, mCallback); // XXXnsm Is it guaranteed mCallback will be called in case of failure? Unused << NS_WARN_IF(NS_FAILED(rv)); return rv; @@ -236,7 +243,7 @@ class ReleaseNotificationControlRunnable final public: explicit ReleaseNotificationControlRunnable(Notification* aNotification) - : MainThreadWorkerControlRunnable(aNotification->mWorkerPrivate), + : MainThreadWorkerControlRunnable("ReleaseNotificationControlRunnable"), mNotification(aNotification) {} bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { @@ -310,7 +317,7 @@ class NotificationWorkerRunnable : public MainThreadWorkerRunnable { explicit NotificationWorkerRunnable( WorkerPrivate* aWorkerPrivate, const char* aName = "NotificationWorkerRunnable") - : MainThreadWorkerRunnable(aWorkerPrivate, aName) {} + : MainThreadWorkerRunnable(aName) {} bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { aWorkerPrivate->AssertIsOnWorkerThread(); @@ -426,10 +433,10 @@ class NotificationRef final { RefPtr<ReleaseNotificationRunnable> r = new ReleaseNotificationRunnable(notification); - if (!r->Dispatch()) { + if (!r->Dispatch(notification->mWorkerPrivate)) { RefPtr<ReleaseNotificationControlRunnable> r = new ReleaseNotificationControlRunnable(notification); - MOZ_ALWAYS_TRUE(r->Dispatch()); + MOZ_ALWAYS_TRUE(r->Dispatch(notification->mWorkerPrivate)); } } else { notification->AssertIsOnTargetThread(); @@ -822,15 +829,15 @@ Notification::ConstructFromFields( nsresult Notification::PersistNotification() { AssertIsOnMainThread(); - nsresult rv; + nsCOMPtr<nsINotificationStorage> notificationStorage = - do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - return rv; + GetNotificationStorage(IsInPrivateBrowsing()); + if (NS_WARN_IF(!notificationStorage)) { + return NS_ERROR_UNEXPECTED; } nsString origin; - rv = GetOrigin(GetPrincipal(), origin); + nsresult rv = GetOrigin(GetPrincipal(), origin); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -862,7 +869,7 @@ void Notification::UnpersistNotification() { AssertIsOnMainThread(); if (IsStored()) { nsCOMPtr<nsINotificationStorage> notificationStorage = - do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID); + GetNotificationStorage(IsInPrivateBrowsing()); if (notificationStorage) { nsString origin; nsresult rv = GetOrigin(GetPrincipal(), origin); @@ -1067,15 +1074,16 @@ class NotificationClickWorkerRunnable final "NotificationClickWorkerRunnable"), mNotification(aNotification), mWindow(aWindow) { - MOZ_ASSERT_IF(mWorkerPrivate->IsServiceWorker(), !mWindow); + MOZ_ASSERT_IF(mNotification->mWorkerPrivate->IsServiceWorker(), !mWindow); } void WorkerRunInternal(WorkerPrivate* aWorkerPrivate) override { bool doDefaultAction = mNotification->DispatchClickEvent(); - MOZ_ASSERT_IF(mWorkerPrivate->IsServiceWorker(), !doDefaultAction); + MOZ_ASSERT_IF(mNotification->mWorkerPrivate->IsServiceWorker(), + !doDefaultAction); if (doDefaultAction) { RefPtr<FocusWindowRunnable> r = new FocusWindowRunnable(mWindow); - mWorkerPrivate->DispatchToMainThread(r.forget()); + mNotification->mWorkerPrivate->DispatchToMainThread(r.forget()); } } }; @@ -1175,7 +1183,7 @@ WorkerNotificationObserver::Observe(nsISupports* aSubject, const char* aTopic, MOZ_ASSERT(notification->mWorkerPrivate); - RefPtr<WorkerRunnable> r; + RefPtr<WorkerThreadRunnable> r; if (!strcmp("alertclickcallback", aTopic)) { nsPIDOMWindowInner* window = nullptr; if (!notification->mWorkerPrivate->IsServiceWorker()) { @@ -1207,7 +1215,7 @@ WorkerNotificationObserver::Observe(nsISupports* aSubject, const char* aTopic, } MOZ_ASSERT(r); - if (!r->Dispatch()) { + if (!r->Dispatch(notification->mWorkerPrivate)) { NS_WARNING("Could not dispatch event to worker notification"); } return NS_OK; @@ -1256,7 +1264,7 @@ ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject, // Remove closed or dismissed persistent notifications. nsCOMPtr<nsINotificationStorage> notificationStorage = - do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID); + GetNotificationStorage(mPrincipal->GetPrivateBrowsingId() != 0); if (notificationStorage) { notificationStorage->Delete(origin, mID); } @@ -1316,6 +1324,8 @@ bool Notification::IsInPrivateBrowsing() { return false; } +// Step 4 of +// https://notifications.spec.whatwg.org/#dom-notification-notification void Notification::ShowInternal() { AssertIsOnMainThread(); MOZ_ASSERT(mTempRef, @@ -1330,13 +1340,15 @@ void Notification::ShowInternal() { std::swap(ownership, mTempRef); MOZ_ASSERT(ownership->GetNotification() == this); - nsresult rv = PersistNotification(); - if (NS_FAILED(rv)) { - NS_WARNING("Could not persist Notification"); - } - nsCOMPtr<nsIAlertsService> alertService = components::Alerts::Service(); + // Step 4.1: If the result of getting the notifications permission state is + // not "granted", then queue a task to fire an event named error on this, and + // abort these steps. + // + // XXX(krosylight): But this function is also triggered by + // Notification::ShowPersistentNotification which already does its own + // permission check. Can we split this? ErrorResult result; NotificationPermission permission = NotificationPermission::Denied; if (mWorkerPrivate) { @@ -1351,19 +1363,34 @@ void Notification::ShowInternal() { if (mWorkerPrivate) { RefPtr<NotificationEventWorkerRunnable> r = new NotificationEventWorkerRunnable(this, u"error"_ns); - if (!r->Dispatch()) { + if (!r->Dispatch(mWorkerPrivate)) { NS_WARNING("Could not dispatch event to worker notification"); } } else { DispatchTrustedEvent(u"error"_ns); } + mIsClosed = true; return; } + // Preparing for Step 4.2 the fetch steps. The actual work happens in + // nsIAlertNotification::LoadImage nsAutoString iconUrl; nsAutoString soundUrl; ResolveIconAndSoundURL(iconUrl, soundUrl); + // Step 4.3 the show steps, which are almost all about processing `tag` and + // then displaying the notification. Both are handled by + // nsIAlertsService::ShowAlert/PersistentNotification. The below is all about + // constructing the observer (for show and close events) right and ultimately + // call the alerts service function. + + // XXX(krosylight): Non-persistent notifications probably don't need this + nsresult rv = PersistNotification(); + if (NS_FAILED(rv)) { + NS_WARNING("Could not persist Notification"); + } + bool isPersistent = false; nsCOMPtr<nsIObserver> observer; if (mScope.IsEmpty()) { @@ -1688,8 +1715,8 @@ already_AddRefed<Promise> Notification::Get( nsCOMPtr<nsINotificationStorageCallback> callback = new NotificationStorageCallback(aWindow->AsGlobal(), aScope, promise); - RefPtr<NotificationGetRunnable> r = - new NotificationGetRunnable(origin, aFilter.mTag, callback); + RefPtr<NotificationGetRunnable> r = new NotificationGetRunnable( + origin, aFilter.mTag, callback, doc->IsInPrivateBrowsing()); aRv = aWindow->AsGlobal()->Dispatch(r.forget()); if (NS_WARN_IF(aRv.Failed())) { @@ -1765,7 +1792,7 @@ class WorkerGetCallback final : public ScopeCheckingGetCallback { RefPtr<WorkerGetResultRunnable> r = new WorkerGetResultRunnable( proxy->GetWorkerPrivate(), proxy, std::move(mStrings)); - r->Dispatch(); + r->Dispatch(proxy->GetWorkerPrivate()); return NS_OK; } @@ -1793,25 +1820,26 @@ class WorkerGetRunnable final : public Runnable { NS_IMETHOD Run() override { AssertIsOnMainThread(); - nsCOMPtr<nsINotificationStorageCallback> callback = - new WorkerGetCallback(mPromiseProxy, mScope); - - nsresult rv; - nsCOMPtr<nsINotificationStorage> notificationStorage = - do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - callback->Done(); - return rv; - } MutexAutoLock lock(mPromiseProxy->Lock()); if (mPromiseProxy->CleanedUp()) { return NS_OK; } + auto* principal = mPromiseProxy->GetWorkerPrivate()->GetPrincipal(); + auto isPrivate = principal->GetPrivateBrowsingId() != 0; + + nsCOMPtr<nsINotificationStorageCallback> callback = + new WorkerGetCallback(mPromiseProxy, mScope); + + nsCOMPtr<nsINotificationStorage> notificationStorage = + GetNotificationStorage(isPrivate); + if (NS_WARN_IF(!notificationStorage)) { + callback->Done(); + return NS_ERROR_UNEXPECTED; + } nsString origin; - rv = Notification::GetOrigin( - mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), origin); + nsresult rv = Notification::GetOrigin(principal, origin); if (NS_WARN_IF(NS_FAILED(rv))) { callback->Done(); return rv; |