/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
NS_IMETHODIMP
NotificationParent::Observe(nsISupports* aSubject, constchar* aTopic, const char16_t* aData) { if (!strcmp("alertdisablecallback", aTopic)) { return RemovePermission(mPrincipal);
} if (!strcmp("alertsettingscallback", aTopic)) { return OpenSettings(mPrincipal);
} if (!strcmp("alertclickcallback", aTopic)) { return FireClickEvent();
} if (!strcmp("alertshow", aTopic)) {
(void)NS_WARN_IF(NS_FAILED(
AdjustPushQuota(mPrincipal, NotificationStatusChange::Shown))); if (!mResolver) { #ifdef ANDROID // XXX: This can happen as we resolve showNotification() immediately on // Android for now and a mock service may still call this. return NS_OK; #else
MOZ_ASSERT_UNREACHABLE("Are we getting double show events?"); return NS_ERROR_FAILURE; #endif
}
mResolver.take().value()(CopyableErrorResult()); return NS_OK;
} if (!strcmp("alertfinished", aTopic)) { // XXX: QM_TRY?
(void)NS_WARN_IF(NS_FAILED(
AdjustPushQuota(mPrincipal, NotificationStatusChange::Closed)));
(void)NS_WARN_IF(NS_FAILED(UnpersistNotification(mPrincipal, mId)));
if (mResolver) { // alertshow happens first before alertfinished, and it should have // nullified mResolver. If not it means it failed to show and is bailing // out. // XXX: Apparently XUL manual do not disturb mode does this without firing // alertshow at all.
mResolver.take().value()(CopyableErrorResult(NS_ERROR_FAILURE));
} else {
(void)NS_WARN_IF(NS_FAILED(FireCloseEvent()));
}
// Unpersisted already and being unregistered already by nsIAlertsService
mDangling = true;
Close();
nsresult NotificationParent::FireClickEvent() { if (mScope.IsEmpty()) { if (SendNotifyClick()) { return NS_OK;
} return NS_ERROR_FAILURE;
}
// This needs to be done here rather than in the child actor's // RecvNotifyClick because the caller might not be in the service worker // context but in the window context if (nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::components::ServiceWorkerManager::Service()) {
nsAutoCString originSuffix;
MOZ_TRY(mPrincipal->GetOriginSuffix(originSuffix));
MOZ_TRY(swm->SendNotificationClickEvent(
originSuffix, mScope, mId, mOptions.title(),
NS_ConvertASCIItoUTF16(GetEnumString(mOptions.dir())), mOptions.lang(),
mOptions.body(), mOptions.tag(), mOptions.icon(),
mOptions.dataSerialized()));
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult NotificationParent::FireCloseEvent() { // This needs to be done here rather than in the child actor's // RecvNotifyClose because the caller might not be in the service worker // context but in the window context if (nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::components::ServiceWorkerManager::Service()) {
nsAutoCString originSuffix;
MOZ_TRY(mPrincipal->GetOriginSuffix(originSuffix));
MOZ_TRY(swm->SendNotificationCloseEvent(
originSuffix, mScope, mId, mOptions.title(),
NS_ConvertASCIItoUTF16(GetEnumString(mOptions.dir())), mOptions.lang(),
mOptions.body(), mOptions.tag(), mOptions.icon(),
mOptions.dataSerialized())); return NS_OK;
} return NS_ERROR_FAILURE;
}
// 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.
NotificationPermission permission = GetNotificationPermission(
mPrincipal, mEffectiveStoragePrincipal, mIsSecureContext,
PermissionCheckPurpose::NotificationShow); if (permission != NotificationPermission::Granted) {
CopyableErrorResult rv;
rv.ThrowTypeError("Permission to show Notification denied.");
mResolver.take().value()(rv);
mDangling = true; return IPC_OK();
}
// Step 4.2: Run the fetch steps for notification. (Will happen in // nsIAlertNotification::LoadImage) // Step 4.3: Run the show steps for notification.
nsresult rv = Show(); // It's possible that we synchronously received a notification while in Show, // so mResolver may now be empty. if (NS_FAILED(rv) && mResolver) {
mResolver.take().value()(CopyableErrorResult(rv));
} // If not failed, the resolver will be called asynchronously by // NotificationObserver return IPC_OK();
}
nsresult NotificationParent::Show() { // Step 4.3 the show steps, which are almost all about processing `tag` and // then displaying the notification. Both are handled by // nsIAlertsService::ShowAlert. 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
nsAutoString alertName;
GetAlertName(alertName);
nsresult rv =
PersistNotification(mPrincipal, mId, alertName, mOptions, mScope); if (NS_FAILED(rv)) {
NS_WARNING("Could not persist Notification");
}
// In the case of IPC, the parent process uses the cookie to map to // nsIObserver. Thus the cookie must be unique to differentiate observers. // XXX(krosylight): This is about ContentChild::mAlertObserver which is not // useful when called by the parent process. This should be removed when we // make nsIAlertsService parent process only.
nsString obsoleteCookie = u"notification:"_ns;
#ifdef ANDROID // XXX: the Android nsIAlertsService is broken and doesn't send alertshow // properly, which means we cannot depend on it to resolve the promise. For // now we resolve the promise here. // (This now fires onshow event regardless of the actual result, but it should // be better than the previous behavior that did not do anything at all)
mResolver.take().value()(CopyableErrorResult()); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.