michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: "use strict" michael@0: michael@0: let Cc = Components.classes; michael@0: let Ci = Components.interfaces; michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: this.EXPORTED_SYMBOLS = ["Notifications"]; michael@0: michael@0: function log(msg) { michael@0: // Services.console.logStringMessage(msg); michael@0: } michael@0: michael@0: var _notificationsMap = {}; michael@0: michael@0: function Notification(aId, aOptions) { michael@0: this._id = aId; michael@0: this._when = (new Date).getTime(); michael@0: this.fillWithOptions(aOptions); michael@0: } michael@0: michael@0: Notification.prototype = { michael@0: fillWithOptions: function(aOptions) { michael@0: if ("icon" in aOptions && aOptions.icon != null) michael@0: this._icon = aOptions.icon; michael@0: else michael@0: throw "Notification icon is mandatory"; michael@0: michael@0: if ("title" in aOptions && aOptions.title != null) michael@0: this._title = aOptions.title; michael@0: else michael@0: throw "Notification title is mandatory"; michael@0: michael@0: if ("message" in aOptions && aOptions.message != null) michael@0: this._message = aOptions.message; michael@0: else michael@0: this._message = null; michael@0: michael@0: if ("priority" in aOptions && aOptions.priority != null) michael@0: this._priority = aOptions.priority; michael@0: michael@0: if ("buttons" in aOptions && aOptions.buttons != null) { michael@0: if (aOptions.buttons.length > 3) michael@0: throw "Too many buttons provided. The max number is 3"; michael@0: michael@0: this._buttons = {}; michael@0: for (let i = 0; i < aOptions.buttons.length; i++) { michael@0: let button_id = aOptions.buttons[i].buttonId; michael@0: this._buttons[button_id] = aOptions.buttons[i]; michael@0: } michael@0: } else { michael@0: this._buttons = null; michael@0: } michael@0: michael@0: if ("ongoing" in aOptions && aOptions.ongoing != null) michael@0: this._ongoing = aOptions.ongoing; michael@0: else michael@0: this._ongoing = false; michael@0: michael@0: if ("progress" in aOptions && aOptions.progress != null) michael@0: this._progress = aOptions.progress; michael@0: else michael@0: this._progress = null; michael@0: michael@0: if ("onCancel" in aOptions && aOptions.onCancel != null) michael@0: this._onCancel = aOptions.onCancel; michael@0: else michael@0: this._onCancel = null; michael@0: michael@0: if ("onClick" in aOptions && aOptions.onClick != null) michael@0: this._onClick = aOptions.onClick; michael@0: else michael@0: this._onClick = null; michael@0: michael@0: if ("cookie" in aOptions && aOptions.cookie != null) michael@0: this._cookie = aOptions.cookie; michael@0: else michael@0: this._cookie = null; michael@0: michael@0: if ("persistent" in aOptions && aOptions.persistent != null) michael@0: this._persistent = aOptions.persistent; michael@0: else michael@0: this._persistent = false; michael@0: }, michael@0: michael@0: show: function() { michael@0: let msg = { michael@0: type: "Notification:Show", michael@0: id: this._id, michael@0: title: this._title, michael@0: smallIcon: this._icon, michael@0: ongoing: this._ongoing, michael@0: when: this._when, michael@0: persistent: this._persistent michael@0: }; michael@0: michael@0: if (this._message) michael@0: msg.text = this._message; michael@0: michael@0: if (this._progress) { michael@0: msg.progress_value = this._progress; michael@0: msg.progress_max = 100; michael@0: msg.progress_indeterminate = false; michael@0: } else if (Number.isNaN(this._progress)) { michael@0: msg.progress_value = 0; michael@0: msg.progress_max = 0; michael@0: msg.progress_indeterminate = true; michael@0: } michael@0: michael@0: if (this._priority) michael@0: msg.priority = this._priority; michael@0: michael@0: if (this._buttons) { michael@0: msg.actions = []; michael@0: let buttonName; michael@0: for (buttonName in this._buttons) { michael@0: let button = this._buttons[buttonName]; michael@0: let obj = { michael@0: buttonId: button.buttonId, michael@0: title : button.title, michael@0: icon : button.icon michael@0: }; michael@0: msg.actions.push(obj); michael@0: } michael@0: } michael@0: michael@0: if (this._light) michael@0: msg.light = this._light; michael@0: michael@0: Services.androidBridge.handleGeckoMessage(msg); michael@0: return this; michael@0: }, michael@0: michael@0: cancel: function() { michael@0: let msg = { michael@0: type: "Notification:Hide", michael@0: id: this._id michael@0: }; michael@0: Services.androidBridge.handleGeckoMessage(msg); michael@0: } michael@0: } michael@0: michael@0: var Notifications = { michael@0: _initObserver: function() { michael@0: if (!this._observerAdded) { michael@0: Services.obs.addObserver(this, "Notification:Event", true); michael@0: this._observerAdded = true; michael@0: } michael@0: }, michael@0: michael@0: get idService() { michael@0: delete this.idService; michael@0: return this.idService = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); michael@0: }, michael@0: michael@0: create: function notif_notify(aOptions) { michael@0: this._initObserver(); michael@0: let id = this.idService.generateUUID().toString(); michael@0: let notification = new Notification(id, aOptions); michael@0: _notificationsMap[id] = notification; michael@0: notification.show(); michael@0: return id; michael@0: }, michael@0: michael@0: update: function notif_update(aId, aOptions) { michael@0: let notification = _notificationsMap[aId]; michael@0: if (!notification) michael@0: throw "Unknown notification id"; michael@0: notification.fillWithOptions(aOptions); michael@0: notification.show(); michael@0: }, michael@0: michael@0: cancel: function notif_cancel(aId) { michael@0: let notification = _notificationsMap[aId]; michael@0: if (notification) michael@0: notification.cancel(); michael@0: }, michael@0: michael@0: observe: function notif_observe(aSubject, aTopic, aData) { michael@0: let data = JSON.parse(aData); michael@0: let id = data.id; michael@0: let notification = _notificationsMap[id]; michael@0: if (!notification) { michael@0: Services.console.logStringMessage("Notifications.jsm observe: received unknown event id " + id); michael@0: return; michael@0: } michael@0: michael@0: switch (data.eventType) { michael@0: case "notification-clicked": michael@0: if (notification._onClick) michael@0: notification._onClick(id, notification._cookie); michael@0: break; michael@0: case "notification-button-clicked": { michael@0: if (!notification._buttons) { michael@0: Services.console.logStringMessage("Notifications.jsm: received button clicked event but no buttons are available"); michael@0: break; michael@0: } michael@0: michael@0: let button = notification._buttons[data.buttonId]; michael@0: if (button) michael@0: button.onClicked(id, notification._cookie); michael@0: } michael@0: break; michael@0: case "notification-cleared": michael@0: case "notification-closed": michael@0: if (notification._onCancel) michael@0: notification._onCancel(id, notification._cookie); michael@0: delete _notificationsMap[id]; // since the notification was dismissed, we no longer need to hold a reference. michael@0: break; michael@0: } michael@0: }, michael@0: michael@0: QueryInterface: function (aIID) { michael@0: if (!aIID.equals(Ci.nsISupports) && michael@0: !aIID.equals(Ci.nsIObserver) && michael@0: !aIID.equals(Ci.nsISupportsWeakReference)) michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: return this; michael@0: } michael@0: }