summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/Notifications.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/Notifications.jsm')
-rw-r--r--mobile/android/modules/Notifications.jsm259
1 files changed, 259 insertions, 0 deletions
diff --git a/mobile/android/modules/Notifications.jsm b/mobile/android/modules/Notifications.jsm
new file mode 100644
index 000000000..a035bb2e3
--- /dev/null
+++ b/mobile/android/modules/Notifications.jsm
@@ -0,0 +1,259 @@
+/* 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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+this.EXPORTED_SYMBOLS = ["Notifications"];
+
+function log(msg) {
+ // Services.console.logStringMessage(msg);
+}
+
+var _notificationsMap = {};
+var _handlersMap = {};
+
+function Notification(aId, aOptions) {
+ this._id = aId;
+ this._when = (new Date()).getTime();
+ this.fillWithOptions(aOptions);
+}
+
+Notification.prototype = {
+ fillWithOptions: function(aOptions) {
+ if ("icon" in aOptions && aOptions.icon != null)
+ this._icon = aOptions.icon;
+ else
+ throw "Notification icon is mandatory";
+
+ if ("title" in aOptions && aOptions.title != null)
+ this._title = aOptions.title;
+ else
+ throw "Notification title is mandatory";
+
+ if ("message" in aOptions && aOptions.message != null)
+ this._message = aOptions.message;
+ else
+ this._message = null;
+
+ if ("priority" in aOptions && aOptions.priority != null)
+ this._priority = aOptions.priority;
+
+ if ("buttons" in aOptions && aOptions.buttons != null) {
+ if (aOptions.buttons.length > 3)
+ throw "Too many buttons provided. The max number is 3";
+
+ this._buttons = {};
+ for (let i = 0; i < aOptions.buttons.length; i++) {
+ let button_id = aOptions.buttons[i].buttonId;
+ this._buttons[button_id] = aOptions.buttons[i];
+ }
+ } else {
+ this._buttons = null;
+ }
+
+ if ("ongoing" in aOptions && aOptions.ongoing != null)
+ this._ongoing = aOptions.ongoing;
+ else
+ this._ongoing = false;
+
+ if ("progress" in aOptions && aOptions.progress != null)
+ this._progress = aOptions.progress;
+ else
+ this._progress = null;
+
+ if ("onCancel" in aOptions && aOptions.onCancel != null)
+ this._onCancel = aOptions.onCancel;
+ else
+ this._onCancel = null;
+
+ if ("onClick" in aOptions && aOptions.onClick != null)
+ this._onClick = aOptions.onClick;
+ else
+ this._onClick = null;
+
+ if ("cookie" in aOptions && aOptions.cookie != null)
+ this._cookie = aOptions.cookie;
+ else
+ this._cookie = null;
+
+ if ("handlerKey" in aOptions && aOptions.handlerKey != null)
+ this._handlerKey = aOptions.handlerKey;
+
+ if ("persistent" in aOptions && aOptions.persistent != null)
+ this._persistent = aOptions.persistent;
+ else
+ this._persistent = false;
+ },
+
+ show: function() {
+ let msg = {
+ type: "Notification:Show",
+ id: this._id,
+ title: this._title,
+ smallIcon: this._icon,
+ ongoing: this._ongoing,
+ when: this._when,
+ persistent: this._persistent,
+ };
+
+ if (this._message)
+ msg.text = this._message;
+
+ if (this._progress) {
+ msg.progress_value = this._progress;
+ msg.progress_max = 100;
+ msg.progress_indeterminate = false;
+ } else if (Number.isNaN(this._progress)) {
+ msg.progress_value = 0;
+ msg.progress_max = 0;
+ msg.progress_indeterminate = true;
+ }
+
+ if (this._cookie)
+ msg.cookie = JSON.stringify(this._cookie);
+
+ if (this._priority)
+ msg.priority = this._priority;
+
+ if (this._buttons) {
+ msg.actions = [];
+ let buttonName;
+ for (buttonName in this._buttons) {
+ let button = this._buttons[buttonName];
+ let obj = {
+ buttonId: button.buttonId,
+ title : button.title,
+ icon : button.icon
+ };
+ msg.actions.push(obj);
+ }
+ }
+
+ if (this._light)
+ msg.light = this._light;
+
+ if (this._handlerKey)
+ msg.handlerKey = this._handlerKey;
+
+ Services.androidBridge.handleGeckoMessage(msg);
+ return this;
+ },
+
+ cancel: function() {
+ let msg = {
+ type: "Notification:Hide",
+ id: this._id,
+ handlerKey: this._handlerKey,
+ cookie: JSON.stringify(this._cookie),
+ };
+ Services.androidBridge.handleGeckoMessage(msg);
+ }
+}
+
+var Notifications = {
+ get idService() {
+ delete this.idService;
+ return this.idService = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+ },
+
+ registerHandler: function(key, handler) {
+ if (!_handlersMap[key]) {
+ _handlersMap[key] = [];
+ }
+ _handlersMap[key].push(handler);
+ },
+
+ unregisterHandler: function(key, handler) {
+ let h = _handlersMap[key];
+ if (!h) {
+ return;
+ }
+ let i = h.indexOf(handler);
+ if (i > -1) {
+ h.splice(i, 1);
+ }
+ },
+
+ create: function notif_notify(aOptions) {
+ let id = this.idService.generateUUID().toString();
+
+ let notification = new Notification(id, aOptions);
+ _notificationsMap[id] = notification;
+ notification.show();
+
+ return id;
+ },
+
+ update: function notif_update(aId, aOptions) {
+ let notification = _notificationsMap[aId];
+ if (!notification)
+ throw "Unknown notification id";
+ notification.fillWithOptions(aOptions);
+ notification.show();
+ },
+
+ cancel: function notif_cancel(aId) {
+ let notification = _notificationsMap[aId];
+ if (notification)
+ notification.cancel();
+ },
+
+ observe: function notif_observe(aSubject, aTopic, aData) {
+ Services.console.logStringMessage(aTopic + " " + aData);
+
+ let data = JSON.parse(aData);
+ let id = data.id;
+ let handlerKey = data.handlerKey;
+ let cookie = data.cookie ? JSON.parse(data.cookie) : undefined;
+ let notification = _notificationsMap[id];
+
+ switch (data.eventType) {
+ case "notification-clicked":
+ if (notification && notification._onClick)
+ notification._onClick(id, notification._cookie);
+
+ if (handlerKey) {
+ _handlersMap[handlerKey].forEach(function(handler) {
+ handler.onClick(cookie);
+ });
+ }
+
+ break;
+ case "notification-button-clicked":
+ if (handlerKey) {
+ _handlersMap[handlerKey].forEach(function(handler) {
+ handler.onButtonClick(data.buttonId, cookie);
+ });
+ }
+
+ break;
+ case "notification-cleared":
+ case "notification-closed":
+ if (handlerKey) {
+ _handlersMap[handlerKey].forEach(function(handler) {
+ handler.onCancel(cookie);
+ });
+ }
+
+ if (notification && notification._onCancel)
+ notification._onCancel(id, notification._cookie);
+ delete _notificationsMap[id]; // since the notification was dismissed, we no longer need to hold a reference.
+ break;
+ }
+ },
+
+ QueryInterface: function (aIID) {
+ if (!aIID.equals(Ci.nsISupports) &&
+ !aIID.equals(Ci.nsIObserver) &&
+ !aIID.equals(Ci.nsISupportsWeakReference))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+};
+
+Services.obs.addObserver(Notifications, "Notification:Event", false);