diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /toolkit/components/extensions/parent/ext-notifications.js | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/extensions/parent/ext-notifications.js')
-rw-r--r-- | toolkit/components/extensions/parent/ext-notifications.js | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/toolkit/components/extensions/parent/ext-notifications.js b/toolkit/components/extensions/parent/ext-notifications.js new file mode 100644 index 0000000000..5b42e6c936 --- /dev/null +++ b/toolkit/components/extensions/parent/ext-notifications.js @@ -0,0 +1,188 @@ +/* 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/. */ + +"use strict"; + +const ToolkitModules = {}; + +ChromeUtils.defineESModuleGetters(ToolkitModules, { + EventEmitter: "resource://gre/modules/EventEmitter.sys.mjs", +}); + +var { ignoreEvent } = ExtensionCommon; + +// Manages a notification popup (notifications API) created by the extension. +function Notification(context, notificationsMap, id, options) { + this.notificationsMap = notificationsMap; + this.id = id; + this.options = options; + + let imageURL; + if (options.iconUrl) { + imageURL = context.extension.baseURI.resolve(options.iconUrl); + } + + // Set before calling into nsIAlertsService, because the notification may be + // closed during the call. + notificationsMap.set(id, this); + + try { + let svc = Cc["@mozilla.org/alerts-service;1"].getService( + Ci.nsIAlertsService + ); + svc.showAlertNotification( + imageURL, + options.title, + options.message, + true, // textClickable + this.id, + this, + this.id, + undefined, + undefined, + undefined, + // Principal is not set because doing so reveals buttons to control + // notification preferences, which are currently not implemented for + // notifications triggered via this extension API (bug 1589693). + undefined, + context.incognito + ); + } catch (e) { + // This will fail if alerts aren't available on the system. + + this.observe(null, "alertfinished", id); + } +} + +Notification.prototype = { + clear() { + try { + let svc = Cc["@mozilla.org/alerts-service;1"].getService( + Ci.nsIAlertsService + ); + svc.closeAlert(this.id); + } catch (e) { + // This will fail if the OS doesn't support this function. + } + this.notificationsMap.delete(this.id); + }, + + observe(subject, topic, data) { + switch (topic) { + case "alertclickcallback": + this.notificationsMap.emit("clicked", data); + break; + case "alertfinished": + this.notificationsMap.emit("closed", data); + this.notificationsMap.delete(this.id); + break; + case "alertshow": + this.notificationsMap.emit("shown", data); + break; + } + }, +}; + +this.notifications = class extends ExtensionAPI { + constructor(extension) { + super(extension); + + this.nextId = 0; + this.notificationsMap = new Map(); + ToolkitModules.EventEmitter.decorate(this.notificationsMap); + } + + onShutdown() { + for (let notification of this.notificationsMap.values()) { + notification.clear(); + } + } + + getAPI(context) { + let notificationsMap = this.notificationsMap; + + return { + notifications: { + create: (notificationId, options) => { + if (!notificationId) { + notificationId = String(this.nextId++); + } + + if (notificationsMap.has(notificationId)) { + notificationsMap.get(notificationId).clear(); + } + + new Notification(context, notificationsMap, notificationId, options); + + return Promise.resolve(notificationId); + }, + + clear: function (notificationId) { + if (notificationsMap.has(notificationId)) { + notificationsMap.get(notificationId).clear(); + return Promise.resolve(true); + } + return Promise.resolve(false); + }, + + getAll: function () { + let result = {}; + notificationsMap.forEach((value, key) => { + result[key] = value.options; + }); + return Promise.resolve(result); + }, + + onClosed: new EventManager({ + context, + name: "notifications.onClosed", + register: fire => { + let listener = (event, notificationId) => { + // TODO Bug 1413188, Support the byUser argument. + fire.async(notificationId, true); + }; + + notificationsMap.on("closed", listener); + return () => { + notificationsMap.off("closed", listener); + }; + }, + }).api(), + + onClicked: new EventManager({ + context, + name: "notifications.onClicked", + register: fire => { + let listener = (event, notificationId) => { + fire.async(notificationId); + }; + + notificationsMap.on("clicked", listener); + return () => { + notificationsMap.off("clicked", listener); + }; + }, + }).api(), + + onShown: new EventManager({ + context, + name: "notifications.onShown", + register: fire => { + let listener = (event, notificationId) => { + fire.async(notificationId); + }; + + notificationsMap.on("shown", listener); + return () => { + notificationsMap.off("shown", listener); + }; + }, + }).api(), + + // TODO Bug 1190681, implement button support. + onButtonClicked: ignoreEvent(context, "notifications.onButtonClicked"), + }, + }; + } +}; |