зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1879934 - Observe window events only for non-persistent notifications r=asuth
Differential Revision: https://phabricator.services.mozilla.com/D201627
This commit is contained in:
Родитель
3033f5b2ba
Коммит
4963aba94b
|
@ -714,7 +714,12 @@ Notification::Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
|
|||
}
|
||||
}
|
||||
|
||||
nsresult Notification::Init() {
|
||||
nsresult Notification::MaybeObserveWindowFrozenOrDestroyed() {
|
||||
// NOTE: Non-persistent notifications can also be opened from workers, but we
|
||||
// don't care and nobody else cares. And it's not clear whether we even should
|
||||
// do this for window at all, see
|
||||
// https://github.com/whatwg/notifications/issues/204.
|
||||
// TODO: Somehow extend GlobalTeardownObserver to deal with FROZEN_TOPIC?
|
||||
if (!mWorkerPrivate) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
||||
|
@ -776,6 +781,10 @@ already_AddRefed<Notification> Notification::Constructor(
|
|||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
if (NS_WARN_IF(
|
||||
NS_FAILED(notification->MaybeObserveWindowFrozenOrDestroyed()))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is be ok since we are on the worker thread where this function will
|
||||
// run to completion before the Notification has a chance to go away.
|
||||
|
@ -915,8 +924,6 @@ already_AddRefed<Notification> Notification::CreateInternal(
|
|||
aGlobal, id, aTitle, aOptions.mBody, aOptions.mDir, aOptions.mLang,
|
||||
aOptions.mTag, aOptions.mIcon, aOptions.mRequireInteraction, silent,
|
||||
std::move(vibrate), aOptions.mMozbehavior);
|
||||
rv = notification->Init();
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
return notification.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -245,7 +245,8 @@ class Notification : public DOMEventTargetHelper,
|
|||
nsIGlobalObject* aGlobal, const nsAString& aID, const nsAString& aTitle,
|
||||
const NotificationOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
nsresult Init();
|
||||
// Triggers CloseInternal for non-persistent notifications if window goes away
|
||||
nsresult MaybeObserveWindowFrozenOrDestroyed();
|
||||
bool IsInPrivateBrowsing();
|
||||
void ShowInternal();
|
||||
void CloseInternal(bool aContextClosed = false);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [notification.prompt.testing:true,marionette.setpermission.enabled:true]
|
|
@ -12,9 +12,24 @@ async function getActiveServiceWorker(script) {
|
|||
return reg;
|
||||
}
|
||||
|
||||
|
||||
async function closeAllNotifications() {
|
||||
for (const n of await registration.getNotifications()) {
|
||||
n.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function trySettingPermission(perm) {
|
||||
try {
|
||||
await test_driver.set_permission({ name: "notifications" }, perm);
|
||||
} catch {
|
||||
// Not all implementations support this yet, but the permission may already be set to be able to continue
|
||||
}
|
||||
|
||||
// Using Notification.permission instead of permissions.query() as
|
||||
// some implementation without set_permission support overrides
|
||||
// Notification.permission.
|
||||
const permission = Notification.permission === "default" ? "prompt" : Notification.permission;
|
||||
if (permission !== perm) {
|
||||
throw new Error(`Should have the permission ${perm} to continue`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
async function showNotification() {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
await registration.showNotification('foo');
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="resources/helpers.js"></script>
|
||||
<iframe id="iframe" src="resources/shownotification-window-iframe.html"></iframe>
|
||||
<script>
|
||||
/** @type {ServiceWorkerRegistration} */
|
||||
let registration;
|
||||
|
||||
promise_setup(async (t) => {
|
||||
await trySettingPermission("granted");
|
||||
registration = await getActiveServiceWorker("noop-sw.js");
|
||||
await closeAllNotifications();
|
||||
});
|
||||
|
||||
promise_test(async (t) => {
|
||||
t.add_cleanup(closeAllNotifications);
|
||||
|
||||
if (iframe.contentDocument.readyState !== "complete") {
|
||||
await new Promise(resolve => iframe.onload = resolve);
|
||||
}
|
||||
|
||||
await iframe.contentWindow.showNotification();
|
||||
let notifications = await registration.getNotifications();
|
||||
assert_equals(notifications.length, 1, "Should persist the notification");
|
||||
|
||||
iframe.contentWindow.location.reload();
|
||||
// Wait for some time for potential notification close requests to be sent
|
||||
await new Promise(resolve => iframe.onload = resolve);
|
||||
notifications = await registration.getNotifications();
|
||||
assert_equals(notifications.length, 1, "Should keep the notification");
|
||||
}, 'Refreshing window does not clear persistent notifications');
|
||||
</script>
|
||||
</body>
|
|
@ -8,20 +8,14 @@
|
|||
let registration;
|
||||
|
||||
promise_setup(async () => {
|
||||
await trySettingPermission("prompt");
|
||||
registration = await getActiveServiceWorker("noop-sw.js");
|
||||
await closeAllNotifications();
|
||||
});
|
||||
|
||||
promise_test(async (t) => {
|
||||
promise_test(async t => {
|
||||
t.add_cleanup(closeAllNotifications);
|
||||
|
||||
try {
|
||||
await test_driver.set_permission({ name: "notifications" }, "prompt");
|
||||
} catch {
|
||||
// Not all implementations support this yet, but it may already be "prompt" to be able to continue
|
||||
}
|
||||
|
||||
assert_equals(Notification.permission, "default", "Should have the default permission to continue");
|
||||
|
||||
await promise_rejects_js(t, TypeError, registration.showNotification(""), "Should throw TypeError");
|
||||
const notifications = await registration.getNotifications();
|
||||
assert_equals(notifications.length, 0, "Should return zero notification");
|
||||
|
|
Загрузка…
Ссылка в новой задаче