summaryrefslogtreecommitdiffstats
path: root/dom/notification/Notification.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/notification/Notification.cpp')
-rw-r--r--dom/notification/Notification.cpp114
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;