| 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 |