Bug 1965048 - Fire alertfinished for the previous same-tagged alert notification r=nalexander,geckoview-reviewers

Extracting from D242583 to land it separately.

Differential Revision: https://phabricator.services.mozilla.com/D248312
This commit is contained in:
Kagami Sascha Rosylight
2025-05-07 22:33:30 +00:00
committed by krosylight@mozilla.com
parent 3989028ce4
commit 4db6b6e5e0
3 changed files with 45 additions and 40 deletions

View File

@@ -1,10 +0,0 @@
[tag.https.html]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1891536
expected:
if os == "android": TIMEOUT
[Opening two notifications with the same tag should close the first one]
expected:
if os == "android": TIMEOUT
[Opening two notifications with the same tag should fire close event before show event]
expected:
if os == "android": NOTRUN

View File

@@ -14,9 +14,19 @@ namespace widget {
NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService) NS_IMPL_ISUPPORTS(AndroidAlerts, nsIAlertsService)
StaticAutoPtr<AndroidAlerts::ListenerMap> AndroidAlerts::sListenerMap; struct AndroidNotificationTuple {
MOZ_RUNINIT nsTHashMap<nsStringHashKey, java::WebNotification::GlobalRef> // Can be null if the caller doesn't care about the result.
AndroidAlerts::mNotificationsMap; nsCOMPtr<nsIObserver> mObserver;
// The Gecko alert notification.
nsCOMPtr<nsIAlertNotification> mAlert;
// The Java represented form of mAlert.
mozilla::java::WebNotification::GlobalRef mNotificationRef;
};
using NotificationMap = nsTHashMap<nsStringHashKey, AndroidNotificationTuple>;
static StaticAutoPtr<NotificationMap> sNotificationMap;
NS_IMETHODIMP NS_IMETHODIMP
AndroidAlerts::ShowAlertNotification( AndroidAlerts::ShowAlertNotification(
@@ -92,45 +102,55 @@ AndroidAlerts::ShowAlert(nsIAlertNotification* aAlert,
rv = aAlert->GetVibrate(vibrate); rv = aAlert->GetVibrate(vibrate);
NS_ENSURE_SUCCESS(rv, NS_OK); NS_ENSURE_SUCCESS(rv, NS_OK);
if (aAlertListener) { if (!sNotificationMap) {
if (!sListenerMap) { sNotificationMap = new NotificationMap();
sListenerMap = new ListenerMap(); } else if (Maybe<AndroidNotificationTuple> tuple =
sNotificationMap->Extract(name)) {
if (tuple->mObserver) {
tuple->mObserver->Observe(nullptr, "alertfinished", nullptr);
} }
// This will remove any observers already registered for this name.
sListenerMap->InsertOrUpdate(name, aAlertListener);
} }
java::WebNotification::LocalRef notification = notification->New( java::WebNotification::LocalRef notification = notification->New(
title, name, cookie, text, imageUrl, dir, lang, requireInteraction, spec, title, name, cookie, text, imageUrl, dir, lang, requireInteraction, spec,
silent, privateBrowsing, jni::IntArray::From(vibrate)); silent, privateBrowsing, jni::IntArray::From(vibrate));
java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance(); AndroidNotificationTuple tuple{
if (runtime != NULL) { .mObserver = aAlertListener,
.mAlert = aAlert,
.mNotificationRef = notification,
};
sNotificationMap->InsertOrUpdate(name, std::move(tuple));
if (java::GeckoRuntime::LocalRef runtime =
java::GeckoRuntime::GetInstance()) {
runtime->NotifyOnShow(notification); runtime->NotifyOnShow(notification);
} }
mNotificationsMap.InsertOrUpdate(name, notification);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
AndroidAlerts::CloseAlert(const nsAString& aAlertName, bool aContextClosed) { AndroidAlerts::CloseAlert(const nsAString& aAlertName, bool aContextClosed) {
java::WebNotification::LocalRef notification = if (!sNotificationMap) {
mNotificationsMap.Get(aAlertName); return NS_OK;
if (!notification) { }
Maybe<AndroidNotificationTuple> tuple =
sNotificationMap->MaybeGet(aAlertName);
if (!tuple) {
return NS_OK; return NS_OK;
} }
java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance(); java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
if (runtime != NULL) { if (runtime != NULL) {
runtime->NotifyOnClose(notification); runtime->NotifyOnClose(tuple->mNotificationRef);
} }
mNotificationsMap.Remove(aAlertName);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP AndroidAlerts::Teardown() { NS_IMETHODIMP AndroidAlerts::Teardown() {
mNotificationsMap.Clear(); sNotificationMap = nullptr;
return NS_OK; return NS_OK;
} }
@@ -138,20 +158,21 @@ NS_IMETHODIMP AndroidAlerts::PbmTeardown() { return NS_ERROR_NOT_IMPLEMENTED; }
void AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic, void AndroidAlerts::NotifyListener(const nsAString& aName, const char* aTopic,
const char16_t* aCookie) { const char16_t* aCookie) {
if (!sListenerMap) { if (!sNotificationMap) {
return; return;
} }
nsCOMPtr<nsIObserver> listener = sListenerMap->Get(aName); Maybe<AndroidNotificationTuple> tuple = sNotificationMap->MaybeGet(aName);
if (!listener) { if (!tuple) {
return; return;
} }
listener->Observe(nullptr, aTopic, aCookie); if (tuple->mObserver) {
tuple->mObserver->Observe(nullptr, aTopic, nullptr);
}
if ("alertfinished"_ns.Equals(aTopic)) { if ("alertfinished"_ns.Equals(aTopic)) {
sListenerMap->Remove(aName); sNotificationMap->Remove(aName);
mNotificationsMap.Remove(aName);
} }
} }

View File

@@ -30,14 +30,8 @@ class AndroidAlerts : public nsIAlertsService {
static void NotifyListener(const nsAString& aName, const char* aTopic, static void NotifyListener(const nsAString& aName, const char* aTopic,
const char16_t* aCookie); const char16_t* aCookie);
static nsTHashMap<nsStringHashKey, mozilla::java::WebNotification::GlobalRef>
mNotificationsMap;
protected: protected:
virtual ~AndroidAlerts() { sListenerMap = nullptr; } virtual ~AndroidAlerts() = default;
using ListenerMap = nsInterfaceHashtable<nsStringHashKey, nsIObserver>;
static StaticAutoPtr<ListenerMap> sListenerMap;
}; };
} // namespace widget } // namespace widget