LEFT | RIGHT |
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-present 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 require */ |
| 19 |
| 20 "use strict"; |
| 21 |
18 (function(global) | 22 (function(global) |
19 { | 23 { |
20 if (!global.ext) | 24 let ext = global.ext || require("ext_background"); |
21 global.ext = require("ext_background"); | 25 |
22 | 26 const {port} = require("messaging"); |
23 var Prefs = require("prefs").Prefs; | 27 const {Prefs} = require("prefs"); |
24 var Utils = require("utils").Utils; | 28 const {Utils} = require("utils"); |
25 var FilterStorage = require("filterStorage").FilterStorage; | 29 const {FilterStorage} = require("filterStorage"); |
26 var FilterNotifier = require("filterNotifier").FilterNotifier; | 30 const {FilterNotifier} = require("filterNotifier"); |
27 var defaultMatcher = require("matcher").defaultMatcher; | 31 const {defaultMatcher} = require("matcher"); |
28 var CSSRules = require("cssRules").CSSRules; | 32 const {ElemHideEmulation} = require("elemHideEmulation"); |
29 var NotificationStorage = require("notification").Notification; | 33 const {Notification: NotificationStorage} = require("notification"); |
30 | 34 |
31 var filterClasses = require("filterClasses"); | 35 const {Filter, BlockingFilter, RegExpFilter} = require("filterClasses"); |
32 var Filter = filterClasses.Filter; | 36 const {Synchronizer} = require("synchronizer"); |
33 var BlockingFilter = filterClasses.BlockingFilter; | 37 |
34 var RegExpFilter = filterClasses.RegExpFilter; | 38 const info = require("info"); |
35 var Synchronizer = require("synchronizer").Synchronizer; | 39 const {Subscription, |
36 | 40 DownloadableSubscription, |
37 var info = require("info"); | 41 SpecialSubscription} = require("subscriptionClasses"); |
38 var subscriptionClasses = require("subscriptionClasses"); | |
39 var Subscription = subscriptionClasses.Subscription; | |
40 var DownloadableSubscription = subscriptionClasses.DownloadableSubscription; | |
41 var SpecialSubscription = subscriptionClasses.SpecialSubscription; | |
42 | 42 |
43 // Some modules doesn't exist on Firefox. Moreover, | 43 // Some modules doesn't exist on Firefox. Moreover, |
44 // require() throws an exception on Firefox in that case. | 44 // require() throws an exception on Firefox in that case. |
45 // However, try/catch causes the whole function to to be | 45 // However, try/catch causes the whole function to to be |
46 // deoptimized on V8. So we wrap it into another function. | 46 // deoptimized on V8. So we wrap it into another function. |
47 function tryRequire(module) | 47 function tryRequire(module) |
48 { | 48 { |
49 try | 49 try |
50 { | 50 { |
51 return require(module); | 51 return require(module); |
52 } | 52 } |
53 catch (e) | 53 catch (e) |
54 { | 54 { |
55 return null; | 55 return null; |
56 } | 56 } |
57 } | 57 } |
58 | 58 |
59 function convertObject(keys, obj) | 59 function convertObject(keys, obj) |
60 { | 60 { |
61 var result = {}; | 61 let result = {}; |
62 for (var i = 0; i < keys.length; i++) | 62 for (let key of keys) |
63 { | 63 { |
64 var key = keys[i]; | |
65 if (key in obj) | 64 if (key in obj) |
66 result[key] = obj[key]; | 65 result[key] = obj[key]; |
67 } | 66 } |
68 return result; | 67 return result; |
69 } | 68 } |
70 | 69 |
71 function convertSubscription(subscription) | 70 function convertSubscription(subscription) |
72 { | 71 { |
73 var obj = convertObject(["disabled", "downloadStatus", "homepage", | 72 let obj = convertObject(["disabled", "downloadStatus", "homepage", |
74 "lastDownload", "title", "url"], subscription); | 73 "lastDownload", "title", "url"], subscription); |
| 74 if (subscription instanceof SpecialSubscription) |
| 75 obj.filters = subscription.filters.map(convertFilter); |
75 obj.isDownloading = Synchronizer.isExecuting(subscription.url); | 76 obj.isDownloading = Synchronizer.isExecuting(subscription.url); |
76 return obj; | 77 return obj; |
77 } | 78 } |
78 | 79 |
79 var convertFilter = convertObject.bind(null, ["text"]); | 80 let convertFilter = convertObject.bind(null, ["text"]); |
80 | 81 |
81 var changeListeners = new global.ext.PageMap(); | 82 let changeListeners = new ext.PageMap(); |
82 var listenedPreferences = Object.create(null); | 83 let listenedPreferences = Object.create(null); |
83 var listenedFilterChanges = Object.create(null); | 84 let listenedFilterChanges = Object.create(null); |
84 var messageTypes = { | 85 let messageTypes = new Map([ |
85 "app": "app.respond", | 86 ["app", "app.respond"], |
86 "filter": "filters.respond", | 87 ["filter", "filters.respond"], |
87 "pref": "prefs.respond", | 88 ["pref", "prefs.respond"], |
88 "subscription": "subscriptions.respond" | 89 ["subscription", "subscriptions.respond"] |
89 }; | 90 ]); |
90 | 91 |
91 function sendMessage(type, action) | 92 function sendMessage(type, action, ...args) |
92 { | 93 { |
93 var pages = changeListeners.keys(); | 94 let pages = changeListeners.keys(); |
94 if (pages.length == 0) | 95 if (pages.length == 0) |
95 return; | 96 return; |
96 | 97 |
97 var args = []; | 98 let convertedArgs = []; |
98 for (var i = 2; i < arguments.length; i++) | 99 for (let arg of args) |
99 { | 100 { |
100 var arg = arguments[i]; | |
101 if (arg instanceof Subscription) | 101 if (arg instanceof Subscription) |
102 args.push(convertSubscription(arg)); | 102 convertedArgs.push(convertSubscription(arg)); |
103 else if (arg instanceof Filter) | 103 else if (arg instanceof Filter) |
104 args.push(convertFilter(arg)); | 104 convertedArgs.push(convertFilter(arg)); |
105 else | 105 else |
106 args.push(arg); | 106 convertedArgs.push(arg); |
107 } | 107 } |
108 | 108 |
109 for (var j = 0; j < pages.length; j++) | 109 for (let page of pages) |
110 { | 110 { |
111 var page = pages[j]; | 111 let filters = changeListeners.get(page); |
112 var filters = changeListeners.get(page); | 112 let actions = filters[type]; |
113 var actions = filters[type]; | |
114 if (actions && actions.indexOf(action) != -1) | 113 if (actions && actions.indexOf(action) != -1) |
115 { | 114 { |
116 page.sendMessage({ | 115 page.sendMessage({ |
117 type: messageTypes[type], | 116 type: messageTypes.get(type), |
118 action: action, | 117 action, |
119 args: args | 118 args: convertedArgs |
120 }); | 119 }); |
121 } | 120 } |
122 } | 121 } |
123 } | 122 } |
124 | 123 |
125 function addFilterListeners(type, actions) | 124 function addFilterListeners(type, actions) |
126 { | 125 { |
127 actions.forEach(function(action) | 126 for (let action of actions) |
128 { | 127 { |
129 var name; | 128 let name; |
130 if (type == "filter" && action == "loaded") | 129 if (type == "filter" && action == "loaded") |
131 name = "load"; | 130 name = "load"; |
132 else | 131 else |
133 name = type + "." + action; | 132 name = type + "." + action; |
134 | 133 |
135 if (!(name in listenedFilterChanges)) | 134 if (!(name in listenedFilterChanges)) |
136 { | 135 { |
137 listenedFilterChanges[name] = null; | 136 listenedFilterChanges[name] = null; |
138 FilterNotifier.on(name, function() | 137 FilterNotifier.on(name, (...args) => |
139 { | 138 { |
140 var args = [type, action]; | 139 sendMessage(type, action, ...args); |
141 for (var i = 0; i < arguments.length; i++) | |
142 args.push(arguments[i]); | |
143 sendMessage.apply(null, args); | |
144 }); | 140 }); |
145 } | 141 } |
146 }); | 142 } |
147 } | 143 } |
148 | 144 |
149 function getListenerFilters(page) | 145 function getListenerFilters(page) |
150 { | 146 { |
151 var listenerFilters = changeListeners.get(page); | 147 let listenerFilters = changeListeners.get(page); |
152 if (!listenerFilters) | 148 if (!listenerFilters) |
153 { | 149 { |
154 listenerFilters = Object.create(null); | 150 listenerFilters = Object.create(null); |
155 changeListeners.set(page, listenerFilters); | 151 changeListeners.set(page, listenerFilters); |
156 } | 152 } |
157 return listenerFilters; | 153 return listenerFilters; |
158 } | 154 } |
159 | 155 |
160 global.ext.onMessage.addListener(function(message, sender, callback) | 156 port.on("app.get", (message, sender) => |
161 { | 157 { |
162 switch (message.type) | 158 if (message.what == "issues") |
163 { | 159 { |
164 case "app.get": | 160 let subscriptionInit = tryRequire("subscriptionInit"); |
165 if (message.what == "issues") | 161 let result = subscriptionInit ? subscriptionInit.reinitialized : false; |
| 162 return {filterlistsReinitialized: result}; |
| 163 } |
| 164 |
| 165 if (message.what == "doclink") |
| 166 return Utils.getDocLink(message.link); |
| 167 |
| 168 if (message.what == "localeInfo") |
| 169 { |
| 170 let bidiDir; |
| 171 if ("chromeRegistry" in Utils) |
| 172 { |
| 173 let isRtl = Utils.chromeRegistry.isLocaleRTL("adblockplus"); |
| 174 bidiDir = isRtl ? "rtl" : "ltr"; |
| 175 } |
| 176 else |
| 177 bidiDir = Utils.readingDirection; |
| 178 |
| 179 return {locale: Utils.appLocale, bidiDir}; |
| 180 } |
| 181 |
| 182 if (message.what == "features") |
| 183 { |
| 184 return { |
| 185 devToolsPanel: info.platform == "chromium" |
| 186 }; |
| 187 } |
| 188 |
| 189 return info[message.what]; |
| 190 }); |
| 191 |
| 192 port.on("app.listen", (message, sender) => |
| 193 { |
| 194 getListenerFilters(sender.page).app = message.filter; |
| 195 }); |
| 196 |
| 197 port.on("app.open", (message, sender) => |
| 198 { |
| 199 if (message.what == "options") |
| 200 ext.showOptions(); |
| 201 }); |
| 202 |
| 203 port.on("filters.add", (message, sender) => |
| 204 { |
| 205 let result = require("filterValidation").parseFilter(message.text); |
| 206 let errors = []; |
| 207 if (result.error) |
| 208 errors.push(result.error.toString()); |
| 209 else if (result.filter) |
| 210 FilterStorage.addFilter(result.filter); |
| 211 |
| 212 return errors; |
| 213 }); |
| 214 |
| 215 port.on("filters.blocked", (message, sender) => |
| 216 { |
| 217 let filter = defaultMatcher.matchesAny(message.url, |
| 218 RegExpFilter.typeMap[message.requestType], message.docDomain, |
| 219 message.thirdParty); |
| 220 |
| 221 return filter instanceof BlockingFilter; |
| 222 }); |
| 223 |
| 224 port.on("filters.get", (message, sender) => |
| 225 { |
| 226 if (message.what == "elemhideemulation") |
| 227 { |
| 228 let filters = []; |
| 229 const {checkWhitelisted} = require("whitelisting"); |
| 230 |
| 231 if (Prefs.enabled && !checkWhitelisted(sender.page, sender.frame, |
| 232 RegExpFilter.typeMap.DOCUMENT | |
| 233 RegExpFilter.typeMap.ELEMHIDE)) |
| 234 { |
| 235 let {hostname} = sender.frame.url; |
| 236 filters = ElemHideEmulation.getRulesForDomain(hostname); |
| 237 filters = filters.map((filter) => |
166 { | 238 { |
167 var subscriptionInit = tryRequire("subscriptionInit"); | 239 return { |
168 callback({ | 240 selector: filter.selector, |
169 filterlistsReinitialized: subscriptionInit ? subscriptionInit.reinit
ialized : false, | 241 text: filter.text |
170 legacySafariVersion: (info.platform == "safari" && ( | 242 }; |
171 Services.vc.compare(info.platformVersion, "6.0") < 0 || // bef
oreload breaks websites in Safari 5 | 243 }); |
172 Services.vc.compare(info.platformVersion, "6.1") == 0 || // ext
ensions are broken in 6.1 and 7.0 | 244 } |
173 Services.vc.compare(info.platformVersion, "7.0") == 0)) | 245 return filters; |
174 }); | 246 } |
175 } | 247 |
176 else if (message.what == "doclink") | 248 let subscription = Subscription.fromURL(message.subscriptionUrl); |
177 callback(Utils.getDocLink(message.link)); | 249 if (!subscription) |
178 else if (message.what == "localeInfo") | 250 return []; |
| 251 |
| 252 return subscription.filters.map(convertFilter); |
| 253 }); |
| 254 |
| 255 port.on("filters.importRaw", (message, sender) => |
| 256 { |
| 257 let result = require("filterValidation").parseFilters(message.text); |
| 258 let errors = []; |
| 259 for (let error of result.errors) |
| 260 { |
| 261 if (error.type != "unexpected-filter-list-header") |
| 262 errors.push(error.toString()); |
| 263 } |
| 264 |
| 265 if (errors.length > 0) |
| 266 return errors; |
| 267 |
| 268 let seenFilter = Object.create(null); |
| 269 for (let filter of result.filters) |
| 270 { |
| 271 FilterStorage.addFilter(filter); |
| 272 seenFilter[filter.text] = null; |
| 273 } |
| 274 |
| 275 if (!message.removeExisting) |
| 276 return errors; |
| 277 |
| 278 for (let subscription of FilterStorage.subscriptions) |
| 279 { |
| 280 if (!(subscription instanceof SpecialSubscription)) |
| 281 continue; |
| 282 |
| 283 for (let j = subscription.filters.length - 1; j >= 0; j--) |
| 284 { |
| 285 let filter = subscription.filters[j]; |
| 286 if (/^@@\|\|([^/:]+)\^\$document$/.test(filter.text)) |
| 287 continue; |
| 288 |
| 289 if (!(filter.text in seenFilter)) |
| 290 FilterStorage.removeFilter(filter); |
| 291 } |
| 292 } |
| 293 |
| 294 return errors; |
| 295 }); |
| 296 |
| 297 port.on("filters.listen", (message, sender) => |
| 298 { |
| 299 getListenerFilters(sender.page).filter = message.filter; |
| 300 addFilterListeners("filter", message.filter); |
| 301 }); |
| 302 |
| 303 port.on("filters.remove", (message, sender) => |
| 304 { |
| 305 let filter = Filter.fromText(message.text); |
| 306 let subscription = null; |
| 307 if (message.subscriptionUrl) |
| 308 subscription = Subscription.fromURL(message.subscriptionUrl); |
| 309 |
| 310 if (!subscription) |
| 311 FilterStorage.removeFilter(filter); |
| 312 else |
| 313 FilterStorage.removeFilter(filter, subscription, message.index); |
| 314 }); |
| 315 |
| 316 port.on("prefs.get", (message, sender) => |
| 317 { |
| 318 return Prefs[message.key]; |
| 319 }); |
| 320 |
| 321 port.on("prefs.listen", (message, sender) => |
| 322 { |
| 323 getListenerFilters(sender.page).pref = message.filter; |
| 324 for (let preference of message.filter) |
| 325 { |
| 326 if (!(preference in listenedPreferences)) |
| 327 { |
| 328 listenedPreferences[preference] = null; |
| 329 Prefs.on(preference, () => |
179 { | 330 { |
180 var bidiDir; | 331 sendMessage("pref", preference, Prefs[preference]); |
181 if ("chromeRegistry" in Utils) | |
182 bidiDir = Utils.chromeRegistry.isLocaleRTL("adblockplus") ? "rtl" :
"ltr"; | |
183 else | |
184 bidiDir = Utils.readingDirection; | |
185 | |
186 callback({locale: Utils.appLocale, bidiDir: bidiDir}); | |
187 } | |
188 else if (message.what == "features") | |
189 { | |
190 callback({ | |
191 devToolsPanel: info.platform == "chromium", | |
192 safariContentBlocker: "safari" in global | |
193 && "extension" in global.safari | |
194 && "setContentBlocker" in global.safari.extension | |
195 }); | |
196 } | |
197 else | |
198 callback(info[message.what]); | |
199 break; | |
200 case "app.listen": | |
201 getListenerFilters(sender.page).app = message.filter; | |
202 break; | |
203 case "app.open": | |
204 if (message.what == "options") | |
205 ext.showOptions(); | |
206 break; | |
207 case "filters.add": | |
208 var result = require("filterValidation").parseFilter(message.text); | |
209 var errors = []; | |
210 if (result.error) | |
211 errors.push(result.error.toString()); | |
212 else if (result.filter) | |
213 FilterStorage.addFilter(result.filter); | |
214 callback(errors); | |
215 break; | |
216 case "filters.blocked": | |
217 var filter = defaultMatcher.matchesAny(message.url, | |
218 RegExpFilter.typeMap[message.requestType], message.docDomain, | |
219 message.thirdParty); | |
220 callback(filter instanceof BlockingFilter); | |
221 break; | |
222 case "filters.get": | |
223 if (message.what == "cssproperties") | |
224 { | |
225 var filters = []; | |
226 var checkWhitelisted = require("whitelisting").checkWhitelisted; | |
227 | |
228 if (!checkWhitelisted(sender.page, sender.frame, | |
229 RegExpFilter.typeMap.DOCUMENT | | |
230 RegExpFilter.typeMap.ELEMHIDE)) | |
231 { | |
232 filters = CSSRules.getRulesForDomain(sender.frame.url.hostname); | |
233 filters = filters.map(function(filter) | |
234 { | |
235 return { | |
236 prefix: filter.selectorPrefix, | |
237 suffix: filter.selectorSuffix, | |
238 regexp: filter.regexpString | |
239 }; | |
240 }); | |
241 } | |
242 callback(filters); | |
243 break; | |
244 } | |
245 | |
246 var subscription = Subscription.fromURL(message.subscriptionUrl); | |
247 if (!subscription) | |
248 { | |
249 callback([]); | |
250 break; | |
251 } | |
252 | |
253 callback(subscription.filters.map(convertFilter)); | |
254 break; | |
255 case "filters.importRaw": | |
256 var result = require("filterValidation").parseFilters(message.text); | |
257 var errors = []; | |
258 for (var i = 0; i < result.errors.length; i++) | |
259 { | |
260 var error = result.errors[i]; | |
261 if (error.type != "unexpected-filter-list-header") | |
262 errors.push(error.toString()); | |
263 } | |
264 | |
265 callback(errors); | |
266 if (errors.length > 0) | |
267 return; | |
268 | |
269 var seenFilter = Object.create(null); | |
270 for (var i = 0; i < result.filters.length; i++) | |
271 { | |
272 var filter = result.filters[i]; | |
273 FilterStorage.addFilter(filter); | |
274 seenFilter[filter.text] = null; | |
275 } | |
276 | |
277 if (!message.removeExisting) | |
278 return; | |
279 | |
280 for (var i = 0; i < FilterStorage.subscriptions.length; i++) | |
281 { | |
282 var subscription = FilterStorage.subscriptions[i]; | |
283 if (!(subscription instanceof SpecialSubscription)) | |
284 continue; | |
285 | |
286 for (var j = subscription.filters.length - 1; j >= 0; j--) | |
287 { | |
288 var filter = subscription.filters[j]; | |
289 if (/^@@\|\|([^\/:]+)\^\$document$/.test(filter.text)) | |
290 continue; | |
291 | |
292 if (!(filter.text in seenFilter)) | |
293 FilterStorage.removeFilter(filter); | |
294 } | |
295 } | |
296 break; | |
297 case "filters.listen": | |
298 getListenerFilters(sender.page).filter = message.filter; | |
299 addFilterListeners("filter", message.filter); | |
300 break; | |
301 case "filters.remove": | |
302 var filter = Filter.fromText(message.text); | |
303 var subscription = null; | |
304 if (message.subscriptionUrl) | |
305 subscription = Subscription.fromURL(message.subscriptionUrl); | |
306 | |
307 if (!subscription) | |
308 FilterStorage.removeFilter(filter); | |
309 else | |
310 FilterStorage.removeFilter(filter, subscription, message.index); | |
311 break; | |
312 case "prefs.get": | |
313 callback(Prefs[message.key]); | |
314 break; | |
315 case "prefs.listen": | |
316 getListenerFilters(sender.page).pref = message.filter; | |
317 message.filter.forEach(function(preference) | |
318 { | |
319 if (!(preference in listenedPreferences)) | |
320 { | |
321 listenedPreferences[preference] = null; | |
322 Prefs.on(preference, function() | |
323 { | |
324 sendMessage("pref", preference, Prefs[preference]); | |
325 }); | |
326 } | |
327 }); | 332 }); |
328 break; | 333 } |
329 case "prefs.toggle": | 334 } |
330 if (message.key == "notifications_ignoredcategories") | 335 }); |
331 NotificationStorage.toggleIgnoreCategory("*"); | 336 |
332 else | 337 port.on("prefs.toggle", (message, sender) => |
333 Prefs[message.key] = !Prefs[message.key]; | 338 { |
334 break; | 339 if (message.key == "notifications_ignoredcategories") |
335 case "subscriptions.add": | 340 NotificationStorage.toggleIgnoreCategory("*"); |
336 var subscription = Subscription.fromURL(message.url); | 341 else |
337 if ("title" in message) | 342 Prefs[message.key] = !Prefs[message.key]; |
338 subscription.title = message.title; | 343 }); |
339 if ("homepage" in message) | 344 |
340 subscription.homepage = message.homepage; | 345 port.on("subscriptions.add", (message, sender) => |
341 | 346 { |
342 if (message.confirm) | 347 let subscription = Subscription.fromURL(message.url); |
343 { | 348 if ("title" in message) |
344 ext.showOptions(function() | 349 subscription.title = message.title; |
345 { | 350 if ("homepage" in message) |
346 sendMessage("app", "addSubscription", subscription); | 351 subscription.homepage = message.homepage; |
347 }); | 352 |
348 } | 353 if (message.confirm) |
349 else | 354 { |
350 { | 355 ext.showOptions(() => |
351 subscription.disabled = false; | 356 { |
352 FilterStorage.addSubscription(subscription); | 357 sendMessage("app", "addSubscription", subscription); |
353 | 358 }); |
354 if (subscription instanceof DownloadableSubscription && !subscription.
lastDownload) | 359 } |
355 Synchronizer.execute(subscription); | 360 else |
356 } | 361 { |
357 break; | 362 subscription.disabled = false; |
358 case "subscriptions.get": | 363 FilterStorage.addSubscription(subscription); |
359 var subscriptions = FilterStorage.subscriptions.filter(function(s) | 364 |
360 { | 365 if (subscription instanceof DownloadableSubscription && |
361 if (message.ignoreDisabled && s.disabled) | 366 !subscription.lastDownload) |
362 return false; | 367 Synchronizer.execute(subscription); |
363 if (s instanceof DownloadableSubscription && message.downloadable) | 368 } |
364 return true; | 369 }); |
365 if (s instanceof SpecialSubscription && message.special) | 370 |
366 return true; | 371 port.on("subscriptions.get", (message, sender) => |
367 return false; | 372 { |
368 }); | 373 let subscriptions = FilterStorage.subscriptions.filter((s) => |
369 callback(subscriptions.map(convertSubscription)); | 374 { |
370 break; | 375 if (message.ignoreDisabled && s.disabled) |
371 case "subscriptions.listen": | 376 return false; |
372 getListenerFilters(sender.page).subscription = message.filter; | 377 if (s instanceof DownloadableSubscription && message.downloadable) |
373 addFilterListeners("subscription", message.filter); | 378 return true; |
374 break; | 379 if (s instanceof SpecialSubscription && message.special) |
375 case "subscriptions.remove": | 380 return true; |
376 var subscription = Subscription.fromURL(message.url); | 381 return false; |
377 if (subscription.url in FilterStorage.knownSubscriptions) | 382 }); |
378 FilterStorage.removeSubscription(subscription); | 383 |
379 break; | 384 return subscriptions.map(convertSubscription); |
380 case "subscriptions.toggle": | 385 }); |
381 var subscription = Subscription.fromURL(message.url); | 386 |
382 if (subscription.url in FilterStorage.knownSubscriptions) | 387 port.on("subscriptions.listen", (message, sender) => |
383 { | 388 { |
384 if (subscription.disabled || message.keepInstalled) | 389 getListenerFilters(sender.page).subscription = message.filter; |
385 subscription.disabled = !subscription.disabled; | 390 addFilterListeners("subscription", message.filter); |
386 else | 391 }); |
387 FilterStorage.removeSubscription(subscription); | 392 |
388 } | 393 port.on("subscriptions.remove", (message, sender) => |
389 else | 394 { |
390 { | 395 let subscription = Subscription.fromURL(message.url); |
391 subscription.disabled = false; | 396 if (subscription.url in FilterStorage.knownSubscriptions) |
392 subscription.title = message.title; | 397 FilterStorage.removeSubscription(subscription); |
393 subscription.homepage = message.homepage; | 398 }); |
394 FilterStorage.addSubscription(subscription); | 399 |
395 if (!subscription.lastDownload) | 400 port.on("subscriptions.toggle", (message, sender) => |
396 Synchronizer.execute(subscription); | 401 { |
397 } | 402 let subscription = Subscription.fromURL(message.url); |
398 break; | 403 if (subscription.url in FilterStorage.knownSubscriptions) |
399 case "subscriptions.update": | 404 { |
400 var subscriptions = message.url ? [Subscription.fromURL(message.url)] : | 405 if (subscription.disabled || message.keepInstalled) |
401 FilterStorage.subscriptions; | 406 subscription.disabled = !subscription.disabled; |
402 for (var i = 0; i < subscriptions.length; i++) | 407 else |
403 { | 408 FilterStorage.removeSubscription(subscription); |
404 var subscription = subscriptions[i]; | 409 } |
405 if (subscription instanceof DownloadableSubscription) | 410 else |
406 Synchronizer.execute(subscription, true); | 411 { |
407 } | 412 subscription.disabled = false; |
408 break; | 413 subscription.title = message.title; |
| 414 subscription.homepage = message.homepage; |
| 415 FilterStorage.addSubscription(subscription); |
| 416 if (!subscription.lastDownload) |
| 417 Synchronizer.execute(subscription); |
| 418 } |
| 419 }); |
| 420 |
| 421 port.on("subscriptions.update", (message, sender) => |
| 422 { |
| 423 let {subscriptions} = FilterStorage; |
| 424 if (message.url) |
| 425 subscriptions = [Subscription.fromURL(message.url)]; |
| 426 |
| 427 for (let subscription of subscriptions) |
| 428 { |
| 429 if (subscription instanceof DownloadableSubscription) |
| 430 Synchronizer.execute(subscription, true); |
409 } | 431 } |
410 }); | 432 }); |
411 })(this); | 433 })(this); |
LEFT | RIGHT |