Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/notification.js

Issue 29375915: Issue 4878 - Start using ESLint for adblockpluscore (Closed)
Patch Set: Created Feb. 20, 2017, 10:02 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 /* globals Services, URL */
19
20 "use strict";
21
18 /** 22 /**
19 * @fileOverview Handles notifications. 23 * @fileOverview Handles notifications.
20 */ 24 */
21 25
22 Cu.import("resource://gre/modules/Services.jsm"); 26 Cu.import("resource://gre/modules/Services.jsm");
23 27
24 var {Prefs} = require("prefs"); 28 let {Prefs} = require("prefs");
25 var {Downloader, Downloadable, MILLIS_IN_MINUTE, MILLIS_IN_HOUR, MILLIS_IN_DAY} = require("downloader"); 29 let {Downloader, Downloadable,
26 var {Utils} = require("utils"); 30 MILLIS_IN_MINUTE, MILLIS_IN_HOUR, MILLIS_IN_DAY} = require("downloader");
27 var {Matcher, defaultMatcher} = require("matcher"); 31 let {Utils} = require("utils");
28 var {Filter, RegExpFilter, WhitelistFilter} = require("filterClasses"); 32 let {Matcher, defaultMatcher} = require("matcher");
33 let {Filter, RegExpFilter, WhitelistFilter} = require("filterClasses");
29 34
30 var INITIAL_DELAY = 1 * MILLIS_IN_MINUTE; 35 let INITIAL_DELAY = 1 * MILLIS_IN_MINUTE;
31 var CHECK_INTERVAL = 1 * MILLIS_IN_HOUR; 36 let CHECK_INTERVAL = 1 * MILLIS_IN_HOUR;
32 var EXPIRATION_INTERVAL = 1 * MILLIS_IN_DAY; 37 let EXPIRATION_INTERVAL = 1 * MILLIS_IN_DAY;
33 var TYPE = { 38 let TYPE = {
34 information: 0, 39 information: 0,
35 question: 1, 40 question: 1,
36 relentless: 2, 41 relentless: 2,
37 critical: 3 42 critical: 3
38 }; 43 };
39 44
40 var showListeners = []; 45 let showListeners = [];
41 var questionListeners = {}; 46 let questionListeners = {};
42 47
43 function getNumericalSeverity(notification) 48 function getNumericalSeverity(notification)
44 { 49 {
45 return (notification.type in TYPE ? TYPE[notification.type] : TYPE.information ); 50 if (notification.type in TYPE)
51 return TYPE[notification.type];
52 return TYPE.information;
46 } 53 }
47 54
48 function saveNotificationData() 55 function saveNotificationData()
49 { 56 {
50 // HACK: JSON values aren't saved unless they are assigned a different object. 57 // HACK: JSON values aren't saved unless they are assigned a different object.
51 Prefs.notificationdata = JSON.parse(JSON.stringify(Prefs.notificationdata)); 58 Prefs.notificationdata = JSON.parse(JSON.stringify(Prefs.notificationdata));
52 } 59 }
53 60
54 function localize(translations, locale) 61 function localize(translations, locale)
55 { 62 {
56 if (locale in translations) 63 if (locale in translations)
57 return translations[locale]; 64 return translations[locale];
58 65
59 let languagePart = locale.substring(0, locale.indexOf("-")); 66 let languagePart = locale.substring(0, locale.indexOf("-"));
60 if (languagePart && languagePart in translations) 67 if (languagePart && languagePart in translations)
61 return translations[languagePart]; 68 return translations[languagePart];
62 69
63 let defaultLocale = "en-US"; 70 let defaultLocale = "en-US";
64 return translations[defaultLocale]; 71 return translations[defaultLocale];
65 } 72 }
66 73
67 /** 74 /**
68 * The object providing actual downloading functionality. 75 * The object providing actual downloading functionality.
69 * @type Downloader 76 * @type {Downloader}
70 */ 77 */
71 var downloader = null; 78 let downloader = null;
72 var localData = []; 79 let localData = [];
73 80
74 /** 81 /**
75 * Regularly fetches notifications and decides which to show. 82 * Regularly fetches notifications and decides which to show.
76 * @class 83 * @class
77 */ 84 */
78 var Notification = exports.Notification = 85 let Notification = exports.Notification =
79 { 86 {
80 /** 87 /**
81 * Called on module startup. 88 * Called on module startup.
82 */ 89 */
83 init: function() 90 init()
84 { 91 {
85 downloader = new Downloader(this._getDownloadables.bind(this), INITIAL_DELAY , CHECK_INTERVAL); 92 downloader = new Downloader(this._getDownloadables.bind(this),
93 INITIAL_DELAY, CHECK_INTERVAL);
86 downloader.onExpirationChange = this._onExpirationChange.bind(this); 94 downloader.onExpirationChange = this._onExpirationChange.bind(this);
87 downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this); 95 downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this);
88 downloader.onDownloadError = this._onDownloadError.bind(this); 96 downloader.onDownloadError = this._onDownloadError.bind(this);
89 onShutdown.add(() => downloader.cancel()); 97 onShutdown.add(() => downloader.cancel());
90 }, 98 },
91 99
92 /** 100 /**
93 * Yields a Downloadable instances for the notifications download. 101 * Yields a Downloadable instances for the notifications download.
94 */ 102 */
95 _getDownloadables: function*() 103 *_getDownloadables()
96 { 104 {
97 let downloadable = new Downloadable(Prefs.notificationurl); 105 let downloadable = new Downloadable(Prefs.notificationurl);
98 if (typeof Prefs.notificationdata.lastError === "number") 106 if (typeof Prefs.notificationdata.lastError === "number")
99 downloadable.lastError = Prefs.notificationdata.lastError; 107 downloadable.lastError = Prefs.notificationdata.lastError;
100 if (typeof Prefs.notificationdata.lastCheck === "number") 108 if (typeof Prefs.notificationdata.lastCheck === "number")
101 downloadable.lastCheck = Prefs.notificationdata.lastCheck; 109 downloadable.lastCheck = Prefs.notificationdata.lastCheck;
102 if (typeof Prefs.notificationdata.data === "object" && "version" in Prefs.no tificationdata.data) 110 if (typeof Prefs.notificationdata.data === "object" &&
111 "version" in Prefs.notificationdata.data)
103 downloadable.lastVersion = Prefs.notificationdata.data.version; 112 downloadable.lastVersion = Prefs.notificationdata.data.version;
104 if (typeof Prefs.notificationdata.softExpiration === "number") 113 if (typeof Prefs.notificationdata.softExpiration === "number")
105 downloadable.softExpiration = Prefs.notificationdata.softExpiration; 114 downloadable.softExpiration = Prefs.notificationdata.softExpiration;
106 if (typeof Prefs.notificationdata.hardExpiration === "number") 115 if (typeof Prefs.notificationdata.hardExpiration === "number")
107 downloadable.hardExpiration = Prefs.notificationdata.hardExpiration; 116 downloadable.hardExpiration = Prefs.notificationdata.hardExpiration;
108 if (typeof Prefs.notificationdata.downloadCount === "number") 117 if (typeof Prefs.notificationdata.downloadCount === "number")
109 downloadable.downloadCount = Prefs.notificationdata.downloadCount; 118 downloadable.downloadCount = Prefs.notificationdata.downloadCount;
110 yield downloadable; 119 yield downloadable;
111 }, 120 },
112 121
113 _onExpirationChange: function(downloadable) 122 _onExpirationChange(downloadable)
114 { 123 {
115 Prefs.notificationdata.lastCheck = downloadable.lastCheck; 124 Prefs.notificationdata.lastCheck = downloadable.lastCheck;
116 Prefs.notificationdata.softExpiration = downloadable.softExpiration; 125 Prefs.notificationdata.softExpiration = downloadable.softExpiration;
117 Prefs.notificationdata.hardExpiration = downloadable.hardExpiration; 126 Prefs.notificationdata.hardExpiration = downloadable.hardExpiration;
118 saveNotificationData(); 127 saveNotificationData();
119 }, 128 },
120 129
121 _onDownloadSuccess: function(downloadable, responseText, errorCallback, redire ctCallback) 130 _onDownloadSuccess(downloadable, responseText, errorCallback,
131 redirectCallback)
122 { 132 {
123 try 133 try
124 { 134 {
125 let data = JSON.parse(responseText); 135 let data = JSON.parse(responseText);
126 for (let notification of data.notifications) 136 for (let notification of data.notifications)
127 { 137 {
128 if ("severity" in notification) 138 if ("severity" in notification)
129 { 139 {
130 if (!("type" in notification)) 140 if (!("type" in notification))
131 notification.type = notification.severity; 141 notification.type = notification.severity;
132 delete notification.severity; 142 delete notification.severity;
133 } 143 }
134 } 144 }
135 Prefs.notificationdata.data = data; 145 Prefs.notificationdata.data = data;
136 } 146 }
137 catch (e) 147 catch (e)
138 { 148 {
139 Cu.reportError(e); 149 Cu.reportError(e);
140 errorCallback("synchronize_invalid_data"); 150 errorCallback("synchronize_invalid_data");
141 return; 151 return;
142 } 152 }
143 153
144 Prefs.notificationdata.lastError = 0; 154 Prefs.notificationdata.lastError = 0;
145 Prefs.notificationdata.downloadStatus = "synchronize_ok"; 155 Prefs.notificationdata.downloadStatus = "synchronize_ok";
146 [Prefs.notificationdata.softExpiration, Prefs.notificationdata.hardExpiratio n] = downloader.processExpirationInterval(EXPIRATION_INTERVAL); 156 [Prefs.notificationdata.softExpiration,
157 Prefs.notificationdata.hardExpiration] =
158 downloader.processExpirationInterval(EXPIRATION_INTERVAL);
147 Prefs.notificationdata.downloadCount = downloadable.downloadCount; 159 Prefs.notificationdata.downloadCount = downloadable.downloadCount;
148 saveNotificationData(); 160 saveNotificationData();
149 161
150 Notification.showNext(); 162 Notification.showNext();
151 }, 163 },
152 164
153 _onDownloadError: function(downloadable, downloadURL, error, channelStatus, re sponseStatus, redirectCallback) 165 _onDownloadError(downloadable, downloadURL, error, channelStatus,
166 responseStatus, redirectCallback)
154 { 167 {
155 Prefs.notificationdata.lastError = Date.now(); 168 Prefs.notificationdata.lastError = Date.now();
156 Prefs.notificationdata.downloadStatus = error; 169 Prefs.notificationdata.downloadStatus = error;
157 saveNotificationData(); 170 saveNotificationData();
158 }, 171 },
159 172
160 /** 173 /**
161 * Adds a listener for notifications to be shown. 174 * Adds a listener for notifications to be shown.
162 * @param {Function} listener Listener to be invoked when a notification is 175 * @param {Function} listener Listener to be invoked when a notification is
163 * to be shown 176 * to be shown
164 */ 177 */
165 addShowListener: function(listener) 178 addShowListener(listener)
166 { 179 {
167 if (showListeners.indexOf(listener) == -1) 180 if (showListeners.indexOf(listener) == -1)
168 showListeners.push(listener); 181 showListeners.push(listener);
169 }, 182 },
170 183
171 /** 184 /**
172 * Removes the supplied listener. 185 * Removes the supplied listener.
173 * @param {Function} listener Listener that was added via addShowListener() 186 * @param {Function} listener Listener that was added via addShowListener()
174 */ 187 */
175 removeShowListener: function(listener) 188 removeShowListener(listener)
176 { 189 {
177 let index = showListeners.indexOf(listener); 190 let index = showListeners.indexOf(listener);
178 if (index != -1) 191 if (index != -1)
179 showListeners.splice(index, 1); 192 showListeners.splice(index, 1);
180 }, 193 },
181 194
182 /** 195 /**
183 * Determines which notification is to be shown next. 196 * Determines which notification is to be shown next.
184 * @param {String} url URL to match notifications to (optional) 197 * @param {String} url URL to match notifications to (optional)
185 * @return {Object} notification to be shown, or null if there is none 198 * @return {Object} notification to be shown, or null if there is none
186 */ 199 */
187 _getNextToShow: function(url) 200 _getNextToShow(url)
188 { 201 {
189 function checkTarget(target, parameter, name, version) 202 function checkTarget(target, parameter, name, version)
190 { 203 {
191 let minVersionKey = parameter + "MinVersion"; 204 let minVersionKey = parameter + "MinVersion";
192 let maxVersionKey = parameter + "MaxVersion"; 205 let maxVersionKey = parameter + "MaxVersion";
193 return !((parameter in target && target[parameter] != name) || 206 return !((parameter in target && target[parameter] != name) ||
194 (minVersionKey in target && Services.vc.compare(version, target[m inVersionKey]) < 0) || 207 (minVersionKey in target &&
195 (maxVersionKey in target && Services.vc.compare(version, target[m axVersionKey]) > 0)); 208 Services.vc.compare(version, target[minVersionKey]) < 0) ||
209 (maxVersionKey in target &&
210 Services.vc.compare(version, target[maxVersionKey]) > 0));
196 } 211 }
197 212
198 let remoteData = []; 213 let remoteData = [];
199 if (typeof Prefs.notificationdata.data == "object" && Prefs.notificationdata .data.notifications instanceof Array) 214 if (typeof Prefs.notificationdata.data == "object" &&
215 Prefs.notificationdata.data.notifications instanceof Array)
200 remoteData = Prefs.notificationdata.data.notifications; 216 remoteData = Prefs.notificationdata.data.notifications;
201 217
202 let notifications = localData.concat(remoteData); 218 let notifications = localData.concat(remoteData);
203 if (notifications.length === 0) 219 if (notifications.length === 0)
204 return null; 220 return null;
205 221
206 let {addonName, addonVersion, application, applicationVersion, platform, pla tformVersion} = require("info"); 222 let {addonName, addonVersion, application,
223 applicationVersion, platform, platformVersion} = require("info");
207 let notificationToShow = null; 224 let notificationToShow = null;
208 for (let notification of notifications) 225 for (let notification of notifications)
209 { 226 {
210 if (typeof notification.type === "undefined" || notification.type !== "cri tical") 227 if (typeof notification.type === "undefined" ||
228 notification.type !== "critical")
211 { 229 {
212 let shown; 230 let shown;
213 if (typeof Prefs.notificationdata.shown == "object") 231 if (typeof Prefs.notificationdata.shown == "object")
214 shown = Prefs.notificationdata.shown[notification.id]; 232 shown = Prefs.notificationdata.shown[notification.id];
215 233
216 if (typeof shown != "undefined") 234 if (typeof shown != "undefined")
217 { 235 {
218 if (typeof notification.interval == "number") 236 if (typeof notification.interval == "number")
219 { 237 {
220 if (shown + notification.interval > Date.now()) 238 if (shown + notification.interval > Date.now())
221 continue; 239 continue;
222 } 240 }
223 else if (shown) 241 else if (shown)
224 continue; 242 continue;
225 } 243 }
226 244
227 if (notification.type !== "relentless" && Prefs.notifications_ignoredcat egories.indexOf("*") != -1) 245 if (notification.type !== "relentless" &&
246 Prefs.notifications_ignoredcategories.indexOf("*") != -1)
228 continue; 247 continue;
229 } 248 }
230 249
231 if (typeof url === "string" || notification.urlFilters instanceof Array) 250 if (typeof url === "string" || notification.urlFilters instanceof Array)
232 { 251 {
233 if (Prefs.enabled && typeof url === "string" && notification.urlFilters instanceof Array) 252 if (Prefs.enabled && typeof url === "string" &&
253 notification.urlFilters instanceof Array)
234 { 254 {
235 let host; 255 let host;
236 try 256 try
237 { 257 {
238 host = new URL(url).hostname; 258 host = new URL(url).hostname;
239 } 259 }
240 catch (e) 260 catch (e)
241 { 261 {
242 host = ""; 262 host = "";
243 } 263 }
244 264
245 let exception = defaultMatcher.matchesAny(url, RegExpFilter.typeMap.DO CUMENT, host, false, null); 265 let exception = defaultMatcher.matchesAny(
266 url, RegExpFilter.typeMap.DOCUMENT, host, false, null
267 );
246 if (exception instanceof WhitelistFilter) 268 if (exception instanceof WhitelistFilter)
247 continue; 269 continue;
248 270
249 let matcher = new Matcher(); 271 let matcher = new Matcher();
250 for (let urlFilter of notification.urlFilters) 272 for (let urlFilter of notification.urlFilters)
251 matcher.add(Filter.fromText(urlFilter)); 273 matcher.add(Filter.fromText(urlFilter));
252 if (!matcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, host, fals e, null)) 274 if (!matcher.matchesAny(url, RegExpFilter.typeMap.DOCUMENT, host,
275 false, null))
253 continue; 276 continue;
254 } 277 }
255 else 278 else
256 continue; 279 continue;
257 } 280 }
258 281
259 if (notification.targets instanceof Array) 282 if (notification.targets instanceof Array)
260 { 283 {
261 let match = false; 284 let match = false;
262 for (let target of notification.targets) 285 for (let target of notification.targets)
263 { 286 {
264 if (checkTarget(target, "extension", addonName, addonVersion) && 287 if (checkTarget(target, "extension", addonName, addonVersion) &&
265 checkTarget(target, "application", application, applicationVersion ) && 288 checkTarget(target, "application", application,
289 applicationVersion) &&
266 checkTarget(target, "platform", platform, platformVersion)) 290 checkTarget(target, "platform", platform, platformVersion))
267 { 291 {
268 match = true; 292 match = true;
269 break; 293 break;
270 } 294 }
271 } 295 }
272 if (!match) 296 if (!match)
273 continue; 297 continue;
274 } 298 }
275 299
276 if (!notificationToShow 300 if (!notificationToShow ||
277 || getNumericalSeverity(notification) > getNumericalSeverity(notificat ionToShow)) 301 getNumericalSeverity(notification) >
302 getNumericalSeverity(notificationToShow))
278 notificationToShow = notification; 303 notificationToShow = notification;
279 } 304 }
280 305
281 return notificationToShow; 306 return notificationToShow;
282 }, 307 },
283 308
284 /** 309 /**
285 * Invokes the listeners added via addShowListener() with the next 310 * Invokes the listeners added via addShowListener() with the next
286 * notification to be shown. 311 * notification to be shown.
287 * @param {String} url URL to match notifications to (optional) 312 * @param {String} url URL to match notifications to (optional)
288 */ 313 */
289 showNext: function(url) 314 showNext(url)
290 { 315 {
291 let notification = Notification._getNextToShow(url); 316 let notification = Notification._getNextToShow(url);
292 if (notification) 317 if (notification)
318 {
293 for (let showListener of showListeners) 319 for (let showListener of showListeners)
294 showListener(notification); 320 showListener(notification);
321 }
295 }, 322 },
296 323
297 /** 324 /**
298 * Marks a notification as shown. 325 * Marks a notification as shown.
299 * @param {String} id ID of the notification to be marked as shown 326 * @param {String} id ID of the notification to be marked as shown
300 */ 327 */
301 markAsShown: function(id) 328 markAsShown(id)
302 { 329 {
303 let now = Date.now(); 330 let now = Date.now();
304 let data = Prefs.notificationdata; 331 let data = Prefs.notificationdata;
305 332
306 if (data.shown instanceof Array) 333 if (data.shown instanceof Array)
307 { 334 {
308 let newShown = {}; 335 let newShown = {};
309 for (let oldId of data.shown) 336 for (let oldId of data.shown)
310 newShown[oldId] = now; 337 newShown[oldId] = now;
311 data.shown = newShown; 338 data.shown = newShown;
312 } 339 }
313 340
314 if (typeof data.shown != "object") 341 if (typeof data.shown != "object")
315 data.shown = {}; 342 data.shown = {};
316 343
317 data.shown[id] = now; 344 data.shown[id] = now;
318 345
319 saveNotificationData(); 346 saveNotificationData();
320 }, 347 },
321 348
322 /** 349 /**
323 * Localizes the texts of the supplied notification. 350 * Localizes the texts of the supplied notification.
324 * @param {Object} notification notification to translate 351 * @param {Object} notification notification to translate
325 * @param {String} locale the target locale (optional, defaults to the 352 * @param {String} locale the target locale (optional, defaults to the
326 * application locale) 353 * application locale)
327 * @return {Object} the translated texts 354 * @return {Object} the translated texts
328 */ 355 */
329 getLocalizedTexts: function(notification, locale) 356 getLocalizedTexts(notification, locale)
330 { 357 {
331 locale = locale || Utils.appLocale; 358 locale = locale || Utils.appLocale;
332 let textKeys = ["title", "message"]; 359 let textKeys = ["title", "message"];
333 let localizedTexts = []; 360 let localizedTexts = [];
334 for (let key of textKeys) 361 for (let key of textKeys)
335 { 362 {
336 if (key in notification) 363 if (key in notification)
337 { 364 {
338 if (typeof notification[key] == "string") 365 if (typeof notification[key] == "string")
339 localizedTexts[key] = notification[key]; 366 localizedTexts[key] = notification[key];
340 else 367 else
341 localizedTexts[key] = localize(notification[key], locale); 368 localizedTexts[key] = localize(notification[key], locale);
342 } 369 }
343 } 370 }
344 return localizedTexts; 371 return localizedTexts;
345 }, 372 },
346 373
347 /** 374 /**
348 * Adds a local notification. 375 * Adds a local notification.
349 * @param {Object} notification notification to add 376 * @param {Object} notification notification to add
350 */ 377 */
351 addNotification: function(notification) 378 addNotification(notification)
352 { 379 {
353 if (localData.indexOf(notification) == -1) 380 if (localData.indexOf(notification) == -1)
354 localData.push(notification); 381 localData.push(notification);
355 }, 382 },
356 383
357 /** 384 /**
358 * Removes an existing local notification. 385 * Removes an existing local notification.
359 * @param {Object} notification notification to remove 386 * @param {Object} notification notification to remove
360 */ 387 */
361 removeNotification: function(notification) 388 removeNotification(notification)
362 { 389 {
363 let index = localData.indexOf(notification); 390 let index = localData.indexOf(notification);
364 if (index > -1) 391 if (index > -1)
365 localData.splice(index, 1); 392 localData.splice(index, 1);
366 }, 393 },
367 394
368 /** 395 /**
396 * A callback function which listens to see if notifications were approved.
397 *
398 * @callback approvedListener
399 * @param {Boolean} approved
400 */
401
402 /**
369 * Adds a listener for question-type notifications 403 * Adds a listener for question-type notifications
404 * @param {String} id
405 * @param {approvedListener} listener
370 */ 406 */
371 addQuestionListener: function(/**string*/ id, /**function(approved)*/ listener ) 407 addQuestionListener(id, listener)
372 { 408 {
373 if (!(id in questionListeners)) 409 if (!(id in questionListeners))
374 questionListeners[id] = []; 410 questionListeners[id] = [];
375 if (questionListeners[id].indexOf(listener) === -1) 411 if (questionListeners[id].indexOf(listener) === -1)
376 questionListeners[id].push(listener); 412 questionListeners[id].push(listener);
377 }, 413 },
378 414
379 /** 415 /**
380 * Removes a listener that was previously added via addQuestionListener 416 * Removes a listener that was previously added via addQuestionListener
417 * @param {String} id
418 * @param {approvedListener} listener
381 */ 419 */
382 removeQuestionListener: function(/**string*/ id, /**function(approved)*/ liste ner) 420 removeQuestionListener(id, listener)
383 { 421 {
384 if (!(id in questionListeners)) 422 if (!(id in questionListeners))
385 return; 423 return;
386 let index = questionListeners[id].indexOf(listener); 424 let index = questionListeners[id].indexOf(listener);
387 if (index > -1) 425 if (index > -1)
388 questionListeners[id].splice(index, 1); 426 questionListeners[id].splice(index, 1);
389 if (questionListeners[id].length === 0) 427 if (questionListeners[id].length === 0)
390 delete questionListeners[id]; 428 delete questionListeners[id];
391 }, 429 },
392 430
393 /** 431 /**
394 * Notifies question listeners about interactions with a notification 432 * Notifies question listeners about interactions with a notification
395 * @param {String} id notification ID 433 * @param {String} id notification ID
396 * @param {Boolean} approved indicator whether notification has been approved or not 434 * @param {Boolean} approved indicator whether notification has been approved
397 */ 435 */
398 triggerQuestionListeners: function(id, approved) 436 triggerQuestionListeners(id, approved)
399 { 437 {
400 if (!(id in questionListeners)) 438 if (!(id in questionListeners))
401 return; 439 return;
402 let listeners = questionListeners[id]; 440 let listeners = questionListeners[id];
403 for (let listener of listeners) 441 for (let listener of listeners)
404 listener(approved); 442 listener(approved);
405 }, 443 },
406 444
407 /** 445 /**
408 * Toggles whether notifications of a specific category should be ignored 446 * Toggles whether notifications of a specific category should be ignored
409 * @param {String} category notification category identifier 447 * @param {String} category notification category identifier
410 * @param {Boolean} [forceValue] force specified value 448 * @param {Boolean} [forceValue] force specified value
411 */ 449 */
412 toggleIgnoreCategory: function(category, forceValue) 450 toggleIgnoreCategory(category, forceValue)
413 { 451 {
414 let categories = Prefs.notifications_ignoredcategories; 452 let categories = Prefs.notifications_ignoredcategories;
415 let index = categories.indexOf(category); 453 let index = categories.indexOf(category);
416 if (index == -1 && forceValue !== false) 454 if (index == -1 && forceValue !== false)
417 { 455 {
418 categories.push(category); 456 categories.push(category);
419 Prefs.notifications_showui = true; 457 Prefs.notifications_showui = true;
420 } 458 }
421 else if (index != -1 && forceValue !== true) 459 else if (index != -1 && forceValue !== true)
422 categories.splice(index, 1); 460 categories.splice(index, 1);
423 461
424 // HACK: JSON values aren't saved unless they are assigned a different objec t. 462 // HACK: JSON values aren't saved unless they are assigned a
425 Prefs.notifications_ignoredcategories = JSON.parse(JSON.stringify(categories )); 463 // different object.
464 Prefs.notifications_ignoredcategories =
465 JSON.parse(JSON.stringify(categories));
426 } 466 }
427 }; 467 };
428 Notification.init(); 468 Notification.init();
OLDNEW
« lib/filterStorage.js ('K') | « lib/matcher.js ('k') | lib/rsa.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld