158 lines, 61 LOC, 38 covered (62%)
3 | 1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
|
3 | * |
|
4 | * The contents of this file are subject to the Mozilla Public License Version |
|
5 | * 1.1 (the "License"); you may not use this file except in compliance with |
|
6 | * the License. You may obtain a copy of the License at |
|
7 | * http://www.mozilla.org/MPL/ |
|
8 | * |
|
9 | * Software distributed under the License is distributed on an "AS IS" basis, |
|
10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
|
11 | * for the specific language governing rights and limitations under the |
|
12 | * License. |
|
13 | * |
|
14 | * The Original Code is Bookmarks Sync. |
|
15 | * |
|
16 | * The Initial Developer of the Original Code is Mozilla. |
|
17 | * Portions created by the Initial Developer are Copyright (C) 2007 |
|
18 | * the Initial Developer. All Rights Reserved. |
|
19 | * |
|
20 | * Contributor(s): |
|
21 | * Myk Melez <myk@mozilla.org> |
|
22 | * |
|
23 | * Alternatively, the contents of this file may be used under the terms of |
|
24 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
|
25 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
|
26 | * in which case the provisions of the GPL or the LGPL are applicable instead |
|
27 | * of those above. If you wish to allow use of your version of this file only |
|
28 | * under the terms of either the GPL or the LGPL, and not to allow others to |
|
29 | * use your version of this file under the terms of the MPL, indicate your |
|
30 | * decision by deleting the provisions above and replace them with the notice |
|
31 | * and other provisions required by the GPL or the LGPL. If you do not delete |
|
32 | * the provisions above, a recipient may use your version of this file under |
|
33 | * the terms of any one of the MPL, the GPL or the LGPL. |
|
34 | * |
|
35 | * ***** END LICENSE BLOCK ***** */ |
|
36 | ||
39 | 37 | const EXPORTED_SYMBOLS = ["Notifications", "Notification", "NotificationButton"]; |
38 | ||
12 | 39 | const Cc = Components.classes; |
12 | 40 | const Ci = Components.interfaces; |
12 | 41 | const Cr = Components.results; |
12 | 42 | const Cu = Components.utils; |
43 | ||
15 | 44 | Cu.import("resource://weave/ext/Observers.js"); |
15 | 45 | Cu.import("resource://weave/log4moz.js"); |
15 | 46 | Cu.import("resource://weave/util.js"); |
47 | ||
6 | 48 | let Notifications = { |
49 | // Match the referenced values in toolkit/content/widgets/notification.xml. |
|
15 | 50 | get PRIORITY_INFO() 1, // PRIORITY_INFO_LOW |
6 | 51 | get PRIORITY_WARNING() 4, // PRIORITY_WARNING_LOW |
6 | 52 | get PRIORITY_ERROR() 7, // PRIORITY_CRITICAL_LOW |
53 | ||
54 | // FIXME: instead of making this public, dress the Notifications object |
|
55 | // to behave like an iterator (using generators?) and have callers access |
|
56 | // this array through the Notifications object. |
|
9 | 57 | notifications: [], |
58 | ||
9 | 59 | _observers: [], |
60 | ||
61 | // XXX Should we have a helper method for adding a simple notification? |
|
62 | // I.e. something like |function notify(title, description, priority)|. |
|
63 | ||
6 | 64 | add: function Notifications_add(notification) { |
65 | this.notifications.push(notification); |
|
66 | Observers.notify("weave:notification:added", notification, null); |
|
67 | }, |
|
68 | ||
6 | 69 | remove: function Notifications_remove(notification) { |
70 | let index = this.notifications.indexOf(notification); |
|
71 | ||
72 | if (index != -1) { |
|
73 | this.notifications.splice(index, 1); |
|
74 | Observers.notify("weave:notification:removed", notification, null); |
|
75 | } |
|
76 | }, |
|
77 | ||
78 | /** |
|
79 | * Replace an existing notification. |
|
80 | */ |
|
6 | 81 | replace: function Notifications_replace(oldNotification, newNotification) { |
82 | let index = this.notifications.indexOf(oldNotification); |
|
83 | ||
84 | if (index != -1) |
|
85 | this.notifications.splice(index, 1, newNotification); |
|
86 | else { |
|
87 | this.notifications.push(newNotification); |
|
88 | // XXX Should we throw because we didn't find the existing notification? |
|
89 | // XXX Should we notify observers about weave:notification:added? |
|
90 | } |
|
91 | ||
92 | // XXX Should we notify observers about weave:notification:replaced? |
|
93 | }, |
|
94 | ||
95 | /** |
|
96 | * Remove all notifications that match a title. If no title is provided, all |
|
97 | * notifications are removed. |
|
98 | * |
|
99 | * @param title [optional] |
|
100 | * Title of notifications to remove; falsy value means remove all |
|
101 | */ |
|
6 | 102 | removeAll: function Notifications_removeAll(title) { |
103 | this.notifications.filter(function(old) old.title == title || !title). |
|
104 | forEach(function(old) this.remove(old), this); |
|
105 | }, |
|
106 | ||
107 | // replaces all existing notifications with the same title as the new one |
|
12 | 108 | replaceTitle: function Notifications_replaceTitle(notification) { |
109 | this.removeAll(notification.title); |
|
110 | this.add(notification); |
|
111 | } |
|
112 | }; |
|
113 | ||
114 | ||
115 | /** |
|
116 | * A basic notification. Subclass this to create more complex notifications. |
|
117 | */ |
|
6 | 118 | function Notification(title, description, iconURL, priority, buttons) { |
119 | this.title = title; |
|
120 | this.description = description; |
|
121 | ||
122 | if (iconURL) |
|
123 | this.iconURL = iconURL; |
|
124 | ||
125 | if (priority) |
|
126 | this.priority = priority; |
|
127 | ||
128 | if (buttons) |
|
129 | this.buttons = buttons; |
|
130 | } |
|
131 | ||
132 | // We set each prototype property individually instead of redefining |
|
133 | // the entire prototype to avoid blowing away existing properties |
|
134 | // of the prototype like the the "constructor" property, which we use |
|
135 | // to bind notification objects to their XBL representations. |
|
18 | 136 | Notification.prototype.priority = Notifications.PRIORITY_INFO; |
15 | 137 | Notification.prototype.iconURL = null; |
18 | 138 | Notification.prototype.buttons = []; |
139 | ||
140 | /** |
|
141 | * A button to display in a notification. |
|
142 | */ |
|
8 | 143 | function NotificationButton(label, accessKey, callback) { |
6 | 144 | function callbackWrapper() { |
2 | 145 | try { |
12 | 146 | callback.apply(this, arguments); |
3 | 147 | } catch (e) { |
6 | 148 | let logger = Log4Moz.repository.getLogger("Notifications"); |
10 | 149 | logger.error("An exception occurred: " + Utils.exceptionStr(e)); |
8 | 150 | logger.info(Utils.stackTrace(e)); |
2 | 151 | throw e; |
1 | 152 | } |
153 | } |
|
154 | ||
6 | 155 | this.label = label; |
6 | 156 | this.accessKey = accessKey; |
8 | 157 | this.callback = callbackWrapper; |
3 | 158 | } |