OLD | NEW |
| (Empty) |
1 /* | |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | |
3 * Copyright (C) 2006-2014 Eyeo GmbH | |
4 * | |
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 | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
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/>. | |
16 */ | |
17 | |
18 | |
19 // | |
20 // This file has been generated automatically from Adblock Plus source code | |
21 // | |
22 | |
23 (function (_patchFunc5) { | |
24 const MILLISECONDS_IN_SECOND = 1000; | |
25 const SECONDS_IN_MINUTE = 60; | |
26 const SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE; | |
27 const SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR; | |
28 const INITIAL_DELAY = 6 * SECONDS_IN_MINUTE; | |
29 const CHECK_INTERVAL = SECONDS_IN_HOUR; | |
30 const MIN_EXPIRATION_INTERVAL = 1 * SECONDS_IN_DAY; | |
31 const MAX_EXPIRATION_INTERVAL = 14 * SECONDS_IN_DAY; | |
32 const MAX_ABSENSE_INTERVAL = 1 * SECONDS_IN_DAY; | |
33 var XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttpreq
uest;1", "nsIJSXMLHttpRequest"); | |
34 var timer = null; | |
35 var executing = { | |
36 __proto__: null | |
37 }; | |
38 var Synchronizer = { | |
39 startup: function () { | |
40 var callback = function () { | |
41 timer.delay = CHECK_INTERVAL * MILLISECONDS_IN_SECOND; | |
42 checkSubscriptions(); | |
43 } | |
44 ; | |
45 timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | |
46 timer.initWithCallback(callback, INITIAL_DELAY * MILLISECONDS_IN_SECOND, C
i.nsITimer.TYPE_REPEATING_SLACK); | |
47 } | |
48 , | |
49 isExecuting: function (url) { | |
50 return url in executing; | |
51 } | |
52 , | |
53 execute: function (subscription, manual, forceDownload) { | |
54 Utils.runAsync(this.executeInternal, this, subscription, manual, forceDown
load); | |
55 } | |
56 , | |
57 executeInternal: function (subscription, manual, forceDownload) { | |
58 var url = subscription.url; | |
59 if (url in executing) | |
60 return ; | |
61 var newURL = subscription.nextURL; | |
62 var hadTemporaryRedirect = false; | |
63 subscription.nextURL = null; | |
64 var curVersion = Utils.addonVersion; | |
65 var loadFrom = newURL; | |
66 var isBaseLocation = true; | |
67 if (!loadFrom) | |
68 loadFrom = url; | |
69 if (loadFrom == url) { | |
70 if (subscription.alternativeLocations) { | |
71 var options = [[1, url]]; | |
72 var totalWeight = 1; | |
73 for (var _loopIndex0 = 0; | |
74 _loopIndex0 < subscription.alternativeLocations.split(",").length; ++
_loopIndex0) { | |
75 var alternative = subscription.alternativeLocations.split(",")[_loop
Index0]; | |
76 if (!/^https?:\/\//.test(alternative)) | |
77 continue; | |
78 var weight = 1; | |
79 var weightingRegExp = /;q=([\d\.]+)$/; | |
80 if (weightingRegExp.test(alternative)) { | |
81 weight = parseFloat(RegExp["$1"]); | |
82 if (isNaN(weight) || !isFinite(weight) || weight < 0) | |
83 weight = 1; | |
84 if (weight > 10) | |
85 weight = 10; | |
86 alternative = alternative.replace(weightingRegExp, ""); | |
87 } | |
88 options.push([weight, alternative]); | |
89 totalWeight += weight; | |
90 } | |
91 var choice = Math.random() * totalWeight; | |
92 for (var _loopIndex1 = 0; | |
93 _loopIndex1 < options.length; ++ _loopIndex1) { | |
94 var weight = options[_loopIndex1][0]; | |
95 var alternative = options[_loopIndex1][1]; | |
96 choice -= weight; | |
97 if (choice < 0) { | |
98 loadFrom = alternative; | |
99 break; | |
100 } | |
101 } | |
102 isBaseLocation = (loadFrom == url); | |
103 } | |
104 } | |
105 else { | |
106 forceDownload = true; | |
107 } | |
108 loadFrom = loadFrom.replace(/%VERSION%/, "ABP" + curVersion); | |
109 var request = null; | |
110 function errorCallback(error) { | |
111 var channelStatus = -1; | |
112 try { | |
113 channelStatus = request.channel.status; | |
114 } | |
115 catch (e){} | |
116 var responseStatus = ""; | |
117 try { | |
118 responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).res
ponseStatus; | |
119 } | |
120 catch (e){} | |
121 setError(subscription, error, channelStatus, responseStatus, loadFrom, i
sBaseLocation, manual); | |
122 } | |
123 try { | |
124 request = new XMLHttpRequest(); | |
125 request.mozBackgroundRequest = true; | |
126 request.open("GET", loadFrom); | |
127 } | |
128 catch (e){ | |
129 errorCallback("synchronize_invalid_url"); | |
130 return ; | |
131 } | |
132 try { | |
133 request.overrideMimeType("text/plain"); | |
134 request.channel.loadFlags = request.channel.loadFlags | request.channel.
INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; | |
135 if (request.channel instanceof Ci.nsIHttpChannel) | |
136 request.channel.redirectionLimit = 5; | |
137 var oldNotifications = request.channel.notificationCallbacks; | |
138 var oldEventSink = null; | |
139 request.channel.notificationCallbacks = { | |
140 QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, Ci.ns
IChannelEventSink]), | |
141 getInterface: function (iid) { | |
142 if (iid.equals(Ci.nsIChannelEventSink)) { | |
143 try { | |
144 oldEventSink = oldNotifications.QueryInterface(iid); | |
145 } | |
146 catch (e){} | |
147 return this; | |
148 } | |
149 if (oldNotifications) | |
150 return oldNotifications.QueryInterface(iid); | |
151 else | |
152 throw Cr.NS_ERROR_NO_INTERFACE; | |
153 } | |
154 , | |
155 onChannelRedirect: function (oldChannel, newChannel, flags) { | |
156 if (isBaseLocation && !hadTemporaryRedirect && oldChannel instanceof
Ci.nsIHttpChannel) { | |
157 try { | |
158 subscription.alternativeLocations = oldChannel.getResponseHeader
("X-Alternative-Locations"); | |
159 } | |
160 catch (e){ | |
161 subscription.alternativeLocations = null; | |
162 } | |
163 } | |
164 if (flags & Ci.nsIChannelEventSink.REDIRECT_TEMPORARY) | |
165 hadTemporaryRedirect = true; | |
166 else | |
167 if (!hadTemporaryRedirect) | |
168 newURL = newChannel.URI.spec; | |
169 if (oldEventSink) | |
170 oldEventSink.onChannelRedirect(oldChannel, newChannel, flags); | |
171 } | |
172 , | |
173 asyncOnChannelRedirect: function (oldChannel, newChannel, flags, callb
ack) { | |
174 this.onChannelRedirect(oldChannel, newChannel, flags); | |
175 callback.onRedirectVerifyCallback(Cr.NS_OK); | |
176 } | |
177 | |
178 }; | |
179 } | |
180 catch (e){ | |
181 Cu.reportError(e); | |
182 } | |
183 if (subscription.lastModified && !forceDownload) | |
184 request.setRequestHeader("If-Modified-Since", subscription.lastModified)
; | |
185 request.addEventListener("error", function (ev) { | |
186 delete executing[url]; | |
187 try { | |
188 request.channel.notificationCallbacks = null; | |
189 } | |
190 catch (e){} | |
191 errorCallback("synchronize_connection_error"); | |
192 } | |
193 , false); | |
194 request.addEventListener("load", function (ev) { | |
195 delete executing[url]; | |
196 try { | |
197 request.channel.notificationCallbacks = null; | |
198 } | |
199 catch (e){} | |
200 if (request.status && request.status != 200 && request.status != 304) { | |
201 errorCallback("synchronize_connection_error"); | |
202 return ; | |
203 } | |
204 var newFilters = null; | |
205 if (request.status != 304) { | |
206 newFilters = readFilters(subscription, request.responseText, errorCall
back); | |
207 if (!newFilters) | |
208 return ; | |
209 subscription.lastModified = request.getResponseHeader("Last-Modified")
; | |
210 } | |
211 if (isBaseLocation && !hadTemporaryRedirect) | |
212 subscription.alternativeLocations = request.getResponseHeader("X-Alter
native-Locations"); | |
213 subscription.lastSuccess = subscription.lastDownload = Math.round(Date.n
ow() / MILLISECONDS_IN_SECOND); | |
214 subscription.downloadStatus = "synchronize_ok"; | |
215 subscription.errors = 0; | |
216 var now = Math.round((new Date(request.getResponseHeader("Date")).getTim
e() || Date.now()) / MILLISECONDS_IN_SECOND); | |
217 var expires = Math.round(new Date(request.getResponseHeader("Expires")).
getTime() / MILLISECONDS_IN_SECOND) || 0; | |
218 var expirationInterval = (expires ? expires - now : 0); | |
219 for (var _loopIndex2 = 0; | |
220 _loopIndex2 < (newFilters || subscription.filters).length; ++ _loopIndex
2) { | |
221 var filter = (newFilters || subscription.filters)[_loopIndex2]; | |
222 if (filter instanceof CommentFilter && /\bExpires\s*(?::|after)\s*(\d+
)\s*(h)?/i.test(filter.text)) { | |
223 var interval = parseInt(RegExp["$1"]); | |
224 if (RegExp["$2"]) | |
225 interval *= SECONDS_IN_HOUR; | |
226 else | |
227 interval *= SECONDS_IN_DAY; | |
228 if (interval > expirationInterval) | |
229 expirationInterval = interval; | |
230 } | |
231 } | |
232 expirationInterval = Math.min(Math.max(expirationInterval, MIN_EXPIRATIO
N_INTERVAL), MAX_EXPIRATION_INTERVAL); | |
233 subscription.expires = (subscription.lastDownload + expirationInterval *
2); | |
234 subscription.softExpiration = (subscription.lastDownload + Math.round(ex
pirationInterval * (Math.random() * 0.4 + 0.8))); | |
235 if (newFilters) { | |
236 for (var i = 0; | |
237 i < newFilters.length; i++) { | |
238 var filter = newFilters[i]; | |
239 if (filter instanceof CommentFilter && /^!\s*(\w+)\s*:\s*(.*)/.test(
filter.text)) { | |
240 var keyword = RegExp["$1"].toLowerCase(); | |
241 var value = RegExp["$2"]; | |
242 var known = true; | |
243 if (keyword == "redirect") { | |
244 if (isBaseLocation && value != url) | |
245 subscription.nextURL = value; | |
246 } | |
247 else | |
248 if (keyword == "homepage") { | |
249 var uri = Utils.makeURI(value); | |
250 if (uri && (uri.scheme == "http" || uri.scheme == "https")) | |
251 subscription.homepage = uri.spec; | |
252 } | |
253 else | |
254 known = false; | |
255 if (known) | |
256 newFilters.splice(i--, 1); | |
257 } | |
258 } | |
259 } | |
260 if (isBaseLocation && newURL && newURL != url) { | |
261 var listed = (subscription.url in FilterStorage.knownSubscriptions); | |
262 if (listed) | |
263 FilterStorage.removeSubscription(subscription); | |
264 url = newURL; | |
265 var newSubscription = Subscription.fromURL(url); | |
266 for (var key in newSubscription) | |
267 delete newSubscription[key]; | |
268 for (var key in subscription) | |
269 newSubscription[key] = subscription[key]; | |
270 delete Subscription.knownSubscriptions[subscription.url]; | |
271 newSubscription.oldSubscription = subscription; | |
272 subscription = newSubscription; | |
273 subscription.url = url; | |
274 if (!(subscription.url in FilterStorage.knownSubscriptions) && listed) | |
275 FilterStorage.addSubscription(subscription); | |
276 } | |
277 if (newFilters) | |
278 FilterStorage.updateSubscriptionFilters(subscription, newFilters); | |
279 delete subscription.oldSubscription; | |
280 } | |
281 , false); | |
282 executing[url] = true; | |
283 FilterNotifier.triggerListeners("subscription.downloadStatus", subscriptio
n); | |
284 try { | |
285 request.send(null); | |
286 } | |
287 catch (e){ | |
288 delete executing[url]; | |
289 errorCallback("synchronize_connection_error"); | |
290 return ; | |
291 } | |
292 } | |
293 | |
294 }; | |
295 function checkSubscriptions() { | |
296 if (!Prefs.subscriptions_autoupdate) | |
297 return ; | |
298 var time = Math.round(Date.now() / MILLISECONDS_IN_SECOND); | |
299 for (var _loopIndex3 = 0; | |
300 _loopIndex3 < FilterStorage.subscriptions.length; ++ _loopIndex3) { | |
301 var subscription = FilterStorage.subscriptions[_loopIndex3]; | |
302 if (!(subscription instanceof DownloadableSubscription)) | |
303 continue; | |
304 if (subscription.lastCheck && time - subscription.lastCheck > MAX_ABSENSE_
INTERVAL) { | |
305 subscription.softExpiration += time - subscription.lastCheck; | |
306 } | |
307 subscription.lastCheck = time; | |
308 if (subscription.expires - time > MAX_EXPIRATION_INTERVAL) | |
309 subscription.expires = time + MAX_EXPIRATION_INTERVAL; | |
310 if (subscription.softExpiration - time > MAX_EXPIRATION_INTERVAL) | |
311 subscription.softExpiration = time + MAX_EXPIRATION_INTERVAL; | |
312 if (subscription.softExpiration > time && subscription.expires > time) | |
313 continue; | |
314 if (time - subscription.lastDownload >= MIN_EXPIRATION_INTERVAL) | |
315 Synchronizer.execute(subscription, false); | |
316 } | |
317 } | |
318 function readFilters(subscription, text, errorCallback) { | |
319 var lines = text.split(/[\r\n]+/); | |
320 if (!/\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.test(lines[0])) { | |
321 errorCallback("synchronize_invalid_data"); | |
322 return null; | |
323 } | |
324 var minVersion = RegExp["$1"]; | |
325 for (var i = 0; | |
326 i < lines.length; i++) { | |
327 if (/!\s*checksum[\s\-:]+([\w\+\/]+)/i.test(lines[i])) { | |
328 lines.splice(i, 1); | |
329 var checksumExpected = RegExp["$1"]; | |
330 var checksum = Utils.generateChecksum(lines); | |
331 if (checksum && checksum != checksumExpected) { | |
332 errorCallback("synchronize_checksum_mismatch"); | |
333 return null; | |
334 } | |
335 break; | |
336 } | |
337 } | |
338 delete subscription.requiredVersion; | |
339 delete subscription.upgradeRequired; | |
340 if (minVersion) { | |
341 subscription.requiredVersion = minVersion; | |
342 if (Utils.versionComparator.compare(minVersion, Utils.addonVersion) > 0) | |
343 subscription.upgradeRequired = true; | |
344 } | |
345 lines.shift(); | |
346 var result = []; | |
347 for (var _loopIndex4 = 0; | |
348 _loopIndex4 < lines.length; ++ _loopIndex4) { | |
349 var line = lines[_loopIndex4]; | |
350 var filter = Filter.fromText(Filter.normalize(line)); | |
351 if (filter && !(filter instanceof ElemHideFilter)) | |
352 result.push(filter); | |
353 } | |
354 return result; | |
355 } | |
356 function setError(subscription, error, channelStatus, responseStatus, download
URL, isBaseLocation, manual) { | |
357 if (!isBaseLocation) | |
358 subscription.alternativeLocations = null; | |
359 try { | |
360 Cu.reportError("Adblock Plus: Downloading filter subscription " + subscrip
tion.title + " failed (" + Utils.getString(error) + ")\n" + "Download address: "
+ downloadURL + "\n" + "Channel status: " + channelStatus + "\n" + "Server resp
onse: " + responseStatus); | |
361 } | |
362 catch (e){} | |
363 subscription.lastDownload = Math.round(Date.now() / MILLISECONDS_IN_SECOND); | |
364 subscription.downloadStatus = error; | |
365 if (!manual) { | |
366 if (error == "synchronize_checksum_mismatch") { | |
367 subscription.errors = 0; | |
368 } | |
369 else | |
370 subscription.errors++; | |
371 if (subscription.errors >= Prefs.subscriptions_fallbackerrors && /^https?:
\/\//i.test(subscription.url)) { | |
372 subscription.errors = 0; | |
373 var fallbackURL = Prefs.subscriptions_fallbackurl; | |
374 fallbackURL = fallbackURL.replace(/%VERSION%/g, encodeURIComponent(Utils
.addonVersion)); | |
375 fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g, encodeURIComponent(
subscription.url)); | |
376 fallbackURL = fallbackURL.replace(/%URL%/g, encodeURIComponent(downloadU
RL)); | |
377 fallbackURL = fallbackURL.replace(/%ERROR%/g, encodeURIComponent(error))
; | |
378 fallbackURL = fallbackURL.replace(/%CHANNELSTATUS%/g, encodeURIComponent
(channelStatus)); | |
379 fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g, encodeURIComponen
t(responseStatus)); | |
380 var request = new XMLHttpRequest(); | |
381 request.mozBackgroundRequest = true; | |
382 request.open("GET", fallbackURL); | |
383 request.overrideMimeType("text/plain"); | |
384 request.channel.loadFlags = request.channel.loadFlags | request.channel.
INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; | |
385 request.addEventListener("load", function (ev) { | |
386 if (!(subscription.url in FilterStorage.knownSubscriptions)) | |
387 return ; | |
388 if (/^301\s+(\S+)/.test(request.responseText)) | |
389 subscription.nextURL = RegExp["$1"]; | |
390 else | |
391 if (/^410\b/.test(request.responseText)) { | |
392 var data = "[Adblock]\n" + subscription.filters.map(function (f) { | |
393 return f.text; | |
394 }).join("\n"); | |
395 var url = "data:text/plain," + encodeURIComponent(data); | |
396 var newSubscription = Subscription.fromURL(url); | |
397 newSubscription.title = subscription.title; | |
398 newSubscription.disabled = subscription.disabled; | |
399 FilterStorage.removeSubscription(subscription); | |
400 FilterStorage.addSubscription(newSubscription); | |
401 Synchronizer.execute(newSubscription); | |
402 } | |
403 } | |
404 , false); | |
405 request.send(null); | |
406 } | |
407 } | |
408 } | |
409 if (typeof _patchFunc5 != "undefined") | |
410 eval("(" + _patchFunc5.toString() + ")()"); | |
411 window.Synchronizer = Synchronizer; | |
412 } | |
413 )(window.SynchronizerPatch); | |
OLD | NEW |