1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/modules/Notifications.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,223 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +"use strict" 1.8 + 1.9 +let Cc = Components.classes; 1.10 +let Ci = Components.interfaces; 1.11 + 1.12 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.13 + 1.14 +this.EXPORTED_SYMBOLS = ["Notifications"]; 1.15 + 1.16 +function log(msg) { 1.17 + // Services.console.logStringMessage(msg); 1.18 +} 1.19 + 1.20 +var _notificationsMap = {}; 1.21 + 1.22 +function Notification(aId, aOptions) { 1.23 + this._id = aId; 1.24 + this._when = (new Date).getTime(); 1.25 + this.fillWithOptions(aOptions); 1.26 +} 1.27 + 1.28 +Notification.prototype = { 1.29 + fillWithOptions: function(aOptions) { 1.30 + if ("icon" in aOptions && aOptions.icon != null) 1.31 + this._icon = aOptions.icon; 1.32 + else 1.33 + throw "Notification icon is mandatory"; 1.34 + 1.35 + if ("title" in aOptions && aOptions.title != null) 1.36 + this._title = aOptions.title; 1.37 + else 1.38 + throw "Notification title is mandatory"; 1.39 + 1.40 + if ("message" in aOptions && aOptions.message != null) 1.41 + this._message = aOptions.message; 1.42 + else 1.43 + this._message = null; 1.44 + 1.45 + if ("priority" in aOptions && aOptions.priority != null) 1.46 + this._priority = aOptions.priority; 1.47 + 1.48 + if ("buttons" in aOptions && aOptions.buttons != null) { 1.49 + if (aOptions.buttons.length > 3) 1.50 + throw "Too many buttons provided. The max number is 3"; 1.51 + 1.52 + this._buttons = {}; 1.53 + for (let i = 0; i < aOptions.buttons.length; i++) { 1.54 + let button_id = aOptions.buttons[i].buttonId; 1.55 + this._buttons[button_id] = aOptions.buttons[i]; 1.56 + } 1.57 + } else { 1.58 + this._buttons = null; 1.59 + } 1.60 + 1.61 + if ("ongoing" in aOptions && aOptions.ongoing != null) 1.62 + this._ongoing = aOptions.ongoing; 1.63 + else 1.64 + this._ongoing = false; 1.65 + 1.66 + if ("progress" in aOptions && aOptions.progress != null) 1.67 + this._progress = aOptions.progress; 1.68 + else 1.69 + this._progress = null; 1.70 + 1.71 + if ("onCancel" in aOptions && aOptions.onCancel != null) 1.72 + this._onCancel = aOptions.onCancel; 1.73 + else 1.74 + this._onCancel = null; 1.75 + 1.76 + if ("onClick" in aOptions && aOptions.onClick != null) 1.77 + this._onClick = aOptions.onClick; 1.78 + else 1.79 + this._onClick = null; 1.80 + 1.81 + if ("cookie" in aOptions && aOptions.cookie != null) 1.82 + this._cookie = aOptions.cookie; 1.83 + else 1.84 + this._cookie = null; 1.85 + 1.86 + if ("persistent" in aOptions && aOptions.persistent != null) 1.87 + this._persistent = aOptions.persistent; 1.88 + else 1.89 + this._persistent = false; 1.90 + }, 1.91 + 1.92 + show: function() { 1.93 + let msg = { 1.94 + type: "Notification:Show", 1.95 + id: this._id, 1.96 + title: this._title, 1.97 + smallIcon: this._icon, 1.98 + ongoing: this._ongoing, 1.99 + when: this._when, 1.100 + persistent: this._persistent 1.101 + }; 1.102 + 1.103 + if (this._message) 1.104 + msg.text = this._message; 1.105 + 1.106 + if (this._progress) { 1.107 + msg.progress_value = this._progress; 1.108 + msg.progress_max = 100; 1.109 + msg.progress_indeterminate = false; 1.110 + } else if (Number.isNaN(this._progress)) { 1.111 + msg.progress_value = 0; 1.112 + msg.progress_max = 0; 1.113 + msg.progress_indeterminate = true; 1.114 + } 1.115 + 1.116 + if (this._priority) 1.117 + msg.priority = this._priority; 1.118 + 1.119 + if (this._buttons) { 1.120 + msg.actions = []; 1.121 + let buttonName; 1.122 + for (buttonName in this._buttons) { 1.123 + let button = this._buttons[buttonName]; 1.124 + let obj = { 1.125 + buttonId: button.buttonId, 1.126 + title : button.title, 1.127 + icon : button.icon 1.128 + }; 1.129 + msg.actions.push(obj); 1.130 + } 1.131 + } 1.132 + 1.133 + if (this._light) 1.134 + msg.light = this._light; 1.135 + 1.136 + Services.androidBridge.handleGeckoMessage(msg); 1.137 + return this; 1.138 + }, 1.139 + 1.140 + cancel: function() { 1.141 + let msg = { 1.142 + type: "Notification:Hide", 1.143 + id: this._id 1.144 + }; 1.145 + Services.androidBridge.handleGeckoMessage(msg); 1.146 + } 1.147 +} 1.148 + 1.149 +var Notifications = { 1.150 + _initObserver: function() { 1.151 + if (!this._observerAdded) { 1.152 + Services.obs.addObserver(this, "Notification:Event", true); 1.153 + this._observerAdded = true; 1.154 + } 1.155 + }, 1.156 + 1.157 + get idService() { 1.158 + delete this.idService; 1.159 + return this.idService = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); 1.160 + }, 1.161 + 1.162 + create: function notif_notify(aOptions) { 1.163 + this._initObserver(); 1.164 + let id = this.idService.generateUUID().toString(); 1.165 + let notification = new Notification(id, aOptions); 1.166 + _notificationsMap[id] = notification; 1.167 + notification.show(); 1.168 + return id; 1.169 + }, 1.170 + 1.171 + update: function notif_update(aId, aOptions) { 1.172 + let notification = _notificationsMap[aId]; 1.173 + if (!notification) 1.174 + throw "Unknown notification id"; 1.175 + notification.fillWithOptions(aOptions); 1.176 + notification.show(); 1.177 + }, 1.178 + 1.179 + cancel: function notif_cancel(aId) { 1.180 + let notification = _notificationsMap[aId]; 1.181 + if (notification) 1.182 + notification.cancel(); 1.183 + }, 1.184 + 1.185 + observe: function notif_observe(aSubject, aTopic, aData) { 1.186 + let data = JSON.parse(aData); 1.187 + let id = data.id; 1.188 + let notification = _notificationsMap[id]; 1.189 + if (!notification) { 1.190 + Services.console.logStringMessage("Notifications.jsm observe: received unknown event id " + id); 1.191 + return; 1.192 + } 1.193 + 1.194 + switch (data.eventType) { 1.195 + case "notification-clicked": 1.196 + if (notification._onClick) 1.197 + notification._onClick(id, notification._cookie); 1.198 + break; 1.199 + case "notification-button-clicked": { 1.200 + if (!notification._buttons) { 1.201 + Services.console.logStringMessage("Notifications.jsm: received button clicked event but no buttons are available"); 1.202 + break; 1.203 + } 1.204 + 1.205 + let button = notification._buttons[data.buttonId]; 1.206 + if (button) 1.207 + button.onClicked(id, notification._cookie); 1.208 + } 1.209 + break; 1.210 + case "notification-cleared": 1.211 + case "notification-closed": 1.212 + if (notification._onCancel) 1.213 + notification._onCancel(id, notification._cookie); 1.214 + delete _notificationsMap[id]; // since the notification was dismissed, we no longer need to hold a reference. 1.215 + break; 1.216 + } 1.217 + }, 1.218 + 1.219 + QueryInterface: function (aIID) { 1.220 + if (!aIID.equals(Ci.nsISupports) && 1.221 + !aIID.equals(Ci.nsIObserver) && 1.222 + !aIID.equals(Ci.nsISupportsWeakReference)) 1.223 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.224 + return this; 1.225 + } 1.226 +}