Left: | ||
Right: |
OLD | NEW |
---|---|
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-present 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 var EXPORTED_SYMBOLS = ["AdblockPlusApi"]; | 18 "use strict"; |
19 | 19 |
20 const Cc = Components.classes; | 20 const {defaultMatcher} = require("matcher"); |
21 const Ci = Components.interfaces; | 21 const {Filter, RegExpFilter} = require("filterClasses"); |
22 const Cr = Components.results; | 22 const {FilterNotifier} = require("filterNotifier"); |
23 const Cu = Components.utils; | 23 const {FilterStorage} = require("filterStorage"); |
24 | 24 const {Prefs} = require("prefs"); |
25 Cu.import("resource://gre/modules/Services.jsm"); | 25 const {Subscription, DownloadableSubscription, SpecialSubscription} = |
26 Cu.import("resource://gre/modules/Messaging.jsm"); | 26 require("subscriptionClasses"); |
27 | 27 const {Synchronizer} = require("synchronizer"); |
28 let XMLHttpRequest = Components.Constructor( | 28 |
29 "@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest"); | 29 const ENABLE_PROP = "enable"; |
30 | 30 const HOST_PROP = "host"; |
31 function require(module) | 31 const TITLE_PROP = "title"; |
32 { | 32 const URL_PROP = "url"; |
33 let result = {}; | 33 |
34 result.wrappedJSObject = result; | 34 function init() |
35 Services.obs.notifyObservers(result, "adblockplus-require", module); | 35 { |
36 return result.exports; | 36 Promise.all([FilterNotifier.once("load"), Prefs.untilLoaded]).then(onLoaded); |
37 } | 37 } |
38 | 38 |
39 let {Filter, RegExpFilter} = require("filterClasses"); | 39 function onLoaded() |
40 let {FilterNotifier} = require("filterNotifier"); | 40 { |
41 let {FilterStorage} = require("filterStorage"); | 41 browser.runtime.abbRegisterRequestListener(handleRequest); |
42 let {defaultMatcher} = require("matcher"); | 42 browser.runtime.abbSendRequest("Abb:OnLoaded"); |
Thomas Greiner
2018/08/27 15:24:41
Detail: The "Abb:" prefix seems redundant here sin
diegocarloslima
2018/08/27 21:19:16
Acknowledged.
| |
43 let {Prefs} = require("prefs"); | 43 FilterNotifier.on("save", onFiltersSaved); |
44 let {Subscription, SpecialSubscription, RegularSubscription, DownloadableSubscri ption, ExternalSubscription} = require("subscriptionClasses"); | 44 } |
45 let {Synchronizer} = require("synchronizer"); | 45 |
46 let {UI} = require("ui"); | 46 function onFiltersSaved() |
47 | 47 { |
48 const SUBSCRIPTIONS_SAVED_PREF = "subscriptions_saved"; | 48 browser.runtime.abbSendRequest("Abb:OnFiltersSaved"); |
49 const USER_REMOVED_BLOCK_SUBS_PREF = "user_removed_block_subscriptions"; | 49 } |
50 const USER_REMOVED_EXCEPTIONS_SUB_PREF = "user_removed_exception_subscription"; | 50 |
51 | 51 function handleRequest(data) |
52 function initFilterListeners() | 52 { |
53 { | 53 |
anton
2018/08/27 05:57:10
do we need this empty line?
diegocarloslima
2018/08/27 21:19:16
Acknowledged.
| |
54 FilterNotifier.on("load", onFiltersLoad); | 54 switch ((data["action"])) |
55 FilterNotifier.on("save", onFiltersSave); | 55 { |
56 } | 56 case "getAdblockPlusEnabled": |
57 | 57 return successData(Prefs.enabled); |
58 function onFiltersLoad() | 58 |
59 { | 59 case "setAdblockPlusEnabled": |
60 let detectedSubscriptionFailure = !hasBlockSubscription() && | 60 if (!checkData(data, ENABLE_PROP)) break; |
61 (!getBoolPref(SUBSCRIPTIONS_SAVED_PREF) || !getBoolPref(USER_REMOVED_BLOCK_S UBS_PREF) || FilterStorage.loadFromDiskFailed); | 61 Prefs.enabled = !!data[ENABLE_PROP]; |
62 | 62 return successData(); |
63 // We will only try to recover the default subscription settings if the addonV ersion hasn't changed, | 63 |
64 // otherwise it will be handled in firstRunActions(), inside ui.js | 64 case "getAcceptableAdsEnabled": |
65 let {addonVersion} = require("info"); | 65 return successData(isSubscriptionEnabled( |
66 if (Prefs.currentVersion == addonVersion && detectedSubscriptionFailure) | 66 Prefs.subscriptions_exceptionsurl)); |
67 { | 67 |
68 if (getBoolPref(USER_REMOVED_EXCEPTIONS_SUB_PREF)) | 68 case "setAcceptableAdsEnabled": |
69 { | 69 if (!checkData(data, ENABLE_PROP)) break; |
70 UI.addSubscription(UI.currentWindow, Prefs.currentVersion); | 70 const acceptableAdsTitle = "Allow non-intrusive advertising"; |
71 } | 71 setSubscriptionEnabled(!!data[ENABLE_PROP], |
72 else | 72 Prefs.subscriptions_exceptionsurl, acceptableAdsTitle); |
73 { | 73 return successData(getAllSubscriptions()); |
Thomas Greiner
2018/08/27 15:24:41
The previous version didn't return anything but I
diegocarloslima
2018/08/27 21:19:16
Yeah, this was some test code that I forgot to rem
| |
74 UI.addSubscription(UI.currentWindow, "0.0"); | 74 |
75 } | 75 case "getEnabledSubscriptions": |
76 } | 76 return successData(getEnabledSubscriptions()); |
77 EventDispatcher.instance.sendRequest({type: "Abb:OnFiltersLoad"}); | 77 |
78 } | 78 case "isSubscriptionEnabled": |
79 | 79 if (!checkData(data, URL_PROP)) break; |
80 function onFiltersSave() | 80 return successData(isSubscriptionEnabled(data[URL_PROP])); |
81 { | 81 |
82 if (hasBlockSubscription()) | 82 case "addSubscription": |
83 { | 83 if (!checkData(data, URL_PROP)) break; |
84 setBoolPref(SUBSCRIPTIONS_SAVED_PREF, true); | 84 setSubscriptionEnabled(true, data[URL_PROP], data[TITLE_PROP]); |
85 } | 85 return successData(); |
86 EventDispatcher.instance.sendRequest({type: "Abb:OnFiltersSave"}); | 86 |
87 } | 87 case "removeSubscription": |
88 | 88 if (!checkData(data, URL_PROP)) break; |
89 function getBoolPref(name) | 89 setSubscriptionEnabled(false, data[URL_PROP]); |
90 { | 90 return successData(); |
91 let branch = getPrefsBranch(); | 91 |
92 case "getWhitelistedDomains": | |
93 return successData(getWhitelistedDomains()); | |
94 | |
95 case "isDomainWhitelisted": | |
96 if (!checkData(data, [URL_PROP, HOST_PROP])) break; | |
97 return successData(isDomainWhitelisted(data[URL_PROP], data[HOST_PROP])); | |
98 | |
99 case "whitelistDomain": | |
100 if (!checkData(data, [ENABLE_PROP, URL_PROP, HOST_PROP])) break; | |
101 setDomainWhitelisted(!!data[ENABLE_PROP], data[URL_PROP], data[HOST_PROP]) ; | |
102 return successData(); | |
103 | |
104 } | |
105 return errorData("Malformed request"); | |
106 } | |
107 | |
108 // remove | |
109 function getAllSubscriptions() | |
110 { | |
111 return FilterStorage.subscriptions.map(sub => ({"title": sub.title, "url": sub .url, "downloadable": (sub instanceof DownloadableSubscription), "special": (sub instanceof SpecialSubscription), "disabled": sub.disabled})); | |
112 } | |
113 | |
114 function getEnabledSubscriptions() | |
115 { | |
116 return FilterStorage.subscriptions.filter(sub => !sub.disabled).map(sub => | |
117 ({[TITLE_PROP]: sub.title, [URL_PROP]: sub.url})); | |
118 } | |
119 | |
120 function isSubscriptionEnabled(url) | |
121 { | |
122 const sub = Subscription.fromURL(url); | |
123 return sub.url in FilterStorage.knownSubscriptions && !sub.disabled; | |
124 } | |
125 | |
126 function setSubscriptionEnabled(isEnabled, url, title) | |
127 { | |
128 if (isSubscriptionEnabled(url) == isEnabled) return; | |
129 if (isEnabled) addSubscription(url, title); | |
130 else removeSubscription(url); | |
131 } | |
132 | |
133 function addSubscription(url, title) | |
134 { | |
135 const sub = Subscription.fromURL(url); | |
136 sub.disabled = false; | |
137 if (title) sub.title = title; | |
138 FilterStorage.addSubscription(sub); | |
139 | |
140 if (sub instanceof DownloadableSubscription && !sub.lastDownload) | |
141 { | |
142 Synchronizer.execute(sub); | |
143 } | |
144 } | |
145 | |
146 function removeSubscription(url) | |
147 { | |
148 FilterStorage.removeSubscription(Subscription.fromURL(url)); | |
149 } | |
150 | |
151 function addFilter(text) | |
152 { | |
153 const filter = Filter.fromText(text); | |
154 if (filter.disabled) filter.disabled = false; | |
155 if (!filter.subscriptions.length) FilterStorage.addFilter(filter); | |
156 } | |
157 | |
158 function removeFilter(filter) | |
159 { | |
160 FilterStorage.removeFilter(filter); | |
161 if (filter.subscriptions.length) filter.disabled = true; | |
162 } | |
163 | |
164 function getWhitelistedDomains() | |
165 { | |
166 const whitelistRegex = /^@@\|\|([^/:]+)\^\$document$/; | |
167 const results = []; | |
168 | |
169 FilterStorage.subscriptions.forEach(function(sub) { | |
170 if (!(sub instanceof SpecialSubscription) || sub.disabled) return; | |
171 sub.filters.forEach(function(filter) { | |
Thomas Greiner
2018/08/27 15:24:41
Suggestion: If you want you can use a for-of loop
diegocarloslima
2018/08/27 21:19:16
Acknowledged.
| |
172 const match = filter.text.match(whitelistRegex); | |
173 if (match) results.push({[URL_PROP]: match[1]}); | |
174 }); | |
175 }); | |
176 | |
177 return results; | |
178 } | |
179 | |
180 function flatIt(array) | |
Thomas Greiner
2018/08/27 15:24:41
Detail: You can more efficiently implement that us
diegocarloslima
2018/08/27 21:19:16
This was also some test code ^^
| |
181 { | |
182 let flatArray = []; | |
183 array.forEach(function(item) { | |
184 flatArray = flatArray.concat(item); | |
185 }); | |
186 return flatArray; | |
187 } | |
188 | |
189 function isDomainWhitelisted(url, host) | |
190 { | |
191 return !!getWhitelistingFilter(url, host); | |
192 } | |
193 | |
194 function setDomainWhitelisted(isWhitelisted, url, host) | |
195 { | |
196 if (isDomainWhitelisted(url, host) == isWhitelisted) return; | |
197 if (isWhitelisted) addDomainToWhitelist(host); | |
198 else removeDomainFromWhitelist(url, host); | |
199 } | |
200 | |
201 function addDomainToWhitelist(host) | |
202 { | |
203 addFilter("@@||" + host + "^$document"); | |
204 } | |
205 | |
206 function removeDomainFromWhitelist(url, host) | |
207 { | |
208 let filter = getWhitelistingFilter(url, host); | |
209 while (filter) | |
210 { | |
211 removeFilter(filter); | |
212 filter = getWhitelistingFilter(url, host); | |
213 } | |
214 } | |
215 | |
216 function getWhitelistingFilter(url, host) | |
217 { | |
92 try | 218 try |
93 { | 219 { |
94 return branch.getBoolPref(name); | |
95 } | |
96 catch (e) | |
97 { | |
98 return null; | |
99 } | |
100 } | |
101 | |
102 function setBoolPref(name, value) | |
103 { | |
104 let branch = getPrefsBranch(); | |
105 branch.setBoolPref(name, value); | |
106 Services.prefs.savePrefFile(null); | |
107 } | |
108 | |
109 function getPrefsBranch() | |
110 { | |
111 let {addonRoot, addonName} = require("info"); | |
112 let branchName = "extensions." + addonName + "."; | |
113 return Services.prefs.getBranch(branchName); | |
114 } | |
115 | |
116 function hasBlockSubscription() | |
117 { | |
118 return FilterStorage.subscriptions.some( | |
119 subscription => subscription instanceof DownloadableSubscription && subscrip tion.url != Prefs.subscriptions_exceptionsurl); | |
120 } | |
121 | |
122 function getWhitelistingFilter(url, host) | |
123 { | |
124 try | |
125 { | |
126 return defaultMatcher.whitelist.matchesAny( | 220 return defaultMatcher.whitelist.matchesAny( |
127 url, RegExpFilter.typeMap.DOCUMENT, host, false, null, false); | 221 url, RegExpFilter.typeMap.DOCUMENT, host, false, null, false); |
128 } | 222 } |
129 catch (e) | 223 catch (e) {} |
130 { | 224 return null; |
131 return null; | 225 } |
132 } | 226 |
133 } | 227 function checkData(data, check) |
134 | 228 { |
135 var AdblockPlusApi = | 229 if (!data) return false; |
136 { | 230 const properties = [].concat(check || []); |
137 get filtersLoaded() | 231 return properties.every(function(item) { |
138 { | 232 return item in data; |
139 return !FilterStorage._loading; | 233 }); |
140 }, | 234 } |
141 get adblockPlusEnabled() | 235 |
142 { | 236 function successData(value) |
143 return Prefs.enabled; | 237 { |
144 }, | 238 const data = {}; |
145 set adblockPlusEnabled(adblockPlusEnabled) | 239 data.success = true; |
146 { | 240 if (value != null) data.value = value; |
147 Prefs.enabled = adblockPlusEnabled | 241 return data; |
148 }, | 242 } |
149 get acceptableAdsEnabled() | 243 |
150 { | 244 function errorData(errorMsg) |
151 return FilterStorage.subscriptions.some( | 245 { |
152 (subscription) => subscription.url == Prefs.subscriptions_exceptionsurl); | 246 const data = {}; |
153 }, | 247 if (errorMsg) data.errorMsg = errorMsg; |
Thomas Greiner
2018/08/27 15:24:42
The endpoint in ext-c-runtime.js expects this prop
diegocarloslima
2018/08/27 21:19:16
Acknowledged.
| |
154 set acceptableAdsEnabled(acceptableAdsEnabled) | 248 return data; |
155 { | 249 } |
156 if (acceptableAdsEnabled != AdblockPlusApi.acceptableAdsEnabled) | 250 |
157 UI.toggleAcceptableAds(); | 251 init(); |
158 }, | |
159 get subscriptionsXml() | |
160 { | |
161 let request = new XMLHttpRequest(); | |
162 // Synchronous requests are deprecated, but using an asynchronous request | |
163 // here (for a static resource that doesn't need to be downloaded anyway) | |
164 // would require a huge code change on the Java side, so we stick to | |
165 // synchronous requests | |
166 request.open("GET", | |
167 "chrome://adblockplus/content/ui/subscriptions.xml", | |
168 false); | |
169 request.send(); | |
170 return request.responseText; | |
171 }, | |
172 isSubscriptionListed: function(url) | |
173 { | |
174 return url in FilterStorage.knownSubscriptions; | |
175 }, | |
176 addSubscription: function(url, title) | |
177 { | |
178 let subscriptionToAdd = Subscription.fromURL(url); | |
179 if (title) | |
180 subscriptionToAdd.title = title; | |
181 FilterStorage.addSubscription(subscriptionToAdd); | |
182 let subscription = FilterStorage.knownSubscriptions[url]; | |
183 if (subscription) | |
184 { | |
185 subscription.disabled = false; | |
186 if (!subscription.lastDownload) | |
187 { | |
188 Synchronizer.execute(subscription); | |
189 } | |
190 } | |
191 if (url == Prefs.subscriptions_exceptionsurl) | |
192 { | |
193 setBoolPref(USER_REMOVED_EXCEPTIONS_SUB_PREF, false); | |
194 } | |
195 else if (hasBlockSubscription()) | |
196 { | |
197 setBoolPref(USER_REMOVED_BLOCK_SUBS_PREF, false); | |
198 } | |
199 }, | |
200 removeSubscription: function(url) | |
201 { | |
202 FilterStorage.removeSubscription(FilterStorage.knownSubscriptions[url]); | |
203 if (url == Prefs.subscriptions_exceptionsurl) | |
204 { | |
205 setBoolPref(USER_REMOVED_EXCEPTIONS_SUB_PREF, true); | |
206 } | |
207 else if (!hasBlockSubscription()) | |
208 { | |
209 setBoolPref(USER_REMOVED_BLOCK_SUBS_PREF, true); | |
210 } | |
211 }, | |
212 getActiveSubscriptions: function() | |
213 { | |
214 let subscriptions = []; | |
215 for (let i = 0; i < FilterStorage.subscriptions.length; i++) | |
216 { | |
217 let subscription = FilterStorage.subscriptions[i]; | |
218 if (!subscription.disabled) | |
219 subscriptions.push({"title": subscription.title, "url": subscription.url }); | |
220 } | |
221 return subscriptions; | |
222 }, | |
223 get whitelistedWebsites() | |
224 { | |
225 let whitelistedWebsites = []; | |
226 for (let i = 0; i < FilterStorage.subscriptions.length; i++) | |
227 { | |
228 let subscription = FilterStorage.subscriptions[i]; | |
229 if (subscription.url && subscription.url.startsWith("~user~") && subscript ion.filters) | |
230 { | |
231 for (let j = 0; j < subscription.filters.length; j++) | |
232 { | |
233 let filter = subscription.filters[j]; | |
234 let whitelistMatch = filter.text ? filter.text.match(/^@@\|\|([^/:]+)\ ^\$document$/) : null; | |
235 if(whitelistMatch) | |
236 { | |
237 whitelistedWebsites.push({"url": whitelistMatch[1]}) | |
238 } | |
239 } | |
240 } | |
241 } | |
242 return whitelistedWebsites; | |
243 }, | |
244 isWebsiteWhitelisted: function(url, host) | |
245 { | |
246 return !!getWhitelistingFilter(url, host); | |
247 }, | |
248 whitelistWebsite: function(url, host, whitelisted) | |
249 { | |
250 if (whitelisted) | |
251 { | |
252 var filter = Filter.fromText("@@||" + host + "^$document"); | |
253 if (filter.subscriptions.length && filter.disabled) | |
254 { | |
255 filter.disabled = false; | |
256 } | |
257 else | |
258 { | |
259 filter.disabled = false; | |
260 FilterStorage.addFilter(filter); | |
261 } | |
262 } | |
263 else | |
264 { | |
265 // Remove any exception rules applying to this URL | |
266 var filter = getWhitelistingFilter(url, host); | |
267 while (filter) | |
268 { | |
269 FilterStorage.removeFilter(filter); | |
270 if (filter.subscriptions.length) | |
271 { | |
272 filter.disabled = true; | |
273 } | |
274 filter = getWhitelistingFilter(url); | |
275 } | |
276 } | |
277 }, | |
278 initCommunication: function() | |
279 { | |
280 initFilterListeners(); | |
281 | |
282 EventDispatcher.instance.registerListener((event, data, callback) => | |
283 { | |
284 if (!data) | |
285 { | |
286 callback.onError("malformed request"); | |
287 return; | |
288 } | |
289 | |
290 if (!this.filtersLoaded) | |
291 { | |
292 callback.onError("filters not loaded"); | |
293 return; | |
294 } | |
295 | |
296 switch (data["action"]) | |
297 { | |
298 case "getAdblockPlusEnabled": | |
299 callback.onSuccess({"value": this.adblockPlusEnabled}); | |
300 return; | |
301 case "setAdblockPlusEnabled": | |
302 if ("enable" in data) | |
303 { | |
304 this.adblockPlusEnabled = !!data["enable"]; | |
305 callback.onSuccess({}); | |
306 return; | |
307 } | |
308 break; | |
309 case "getAcceptableAdsEnabled": | |
310 callback.onSuccess({"value": this.acceptableAdsEnabled}); | |
311 return; | |
312 case "setAcceptableAdsEnabled": | |
313 if ("enable" in data) | |
314 { | |
315 this.acceptableAdsEnabled = !!data["enable"]; | |
316 callback.onSuccess({}); | |
317 return; | |
318 } | |
319 break; | |
320 case "getSubscriptionsXml": | |
321 callback.onSuccess({"value": this.subscriptionsXml}); | |
322 return; | |
323 case "getActiveSubscriptions": | |
324 callback.onSuccess({"value": this.getActiveSubscriptions()}); | |
325 return; | |
326 case "isSubscriptionListed": | |
327 if ("url" in data) | |
328 { | |
329 callback.onSuccess({"value": this.isSubscriptionListed(data["url"])} ); | |
330 return; | |
331 } | |
332 break; | |
333 case "addSubscription": | |
334 if ("url" in data) | |
335 { | |
336 this.addSubscription(data["url"], data["title"]); | |
337 callback.onSuccess({}); | |
338 return; | |
339 } | |
340 break; | |
341 case "removeSubscription": | |
342 if ("url" in data) | |
343 { | |
344 this.removeSubscription(data["url"]); | |
345 callback.onSuccess({}); | |
346 return; | |
347 } | |
348 break; | |
349 case "getWhitelistedWebsites": | |
350 callback.onSuccess({"value": this.whitelistedWebsites}); | |
351 return; | |
352 case "isWebsiteWhitelisted": | |
353 if ("url" in data && "host" in data) | |
354 { | |
355 callback.onSuccess({"value": this.isWebsiteWhitelisted(data["url"], data["host"])}); | |
356 return; | |
357 } | |
358 break; | |
359 case "whitelistWebsite": | |
360 if ("url" in data && "host" in data && "whitelisted" in data) | |
361 { | |
362 this.whitelistWebsite(data["url"], data["host"], data["whitelisted"] ); | |
363 callback.onSuccess({}); | |
364 return; | |
365 } | |
366 break; | |
367 } | |
368 callback.onError("malformed request"); | |
369 }, "AdblockPlus:Api"); | |
370 } | |
371 }; | |
OLD | NEW |