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

Delta Between Two Patch Sets: lib/downloader.js

Issue 29375915: Issue 4878 - Start using ESLint for adblockpluscore (Closed)
Left Patch Set: Created Feb. 20, 2017, 10:02 a.m.
Right Patch Set: Removed unused imports Created March 15, 2017, 3:11 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « lib/coreUtils.js ('k') | lib/elemHide.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 "use strict"; 18 "use strict";
19 19
20 /* globals XMLHttpRequest */
Sebastian Noack 2017/02/20 13:14:51 I would rather put this in the .eslintrc.json. Gen
kzar 2017/02/21 06:13:58 Done.
21
22 /** 20 /**
23 * @fileOverview Downloads a set of URLs in regular time intervals. 21 * @fileOverview Downloads a set of URLs in regular time intervals.
24 */ 22 */
25 23
26 let {Utils} = require("utils"); 24 const {Utils} = require("utils");
27 25
28 let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000; 26 const MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000;
29 let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; 27 const MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
30 let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; 28 const MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
31 let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; 29 const MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
32 30
33 let Downloader = 31 let Downloader =
34 /** 32 /**
35 * Creates a new downloader instance. 33 * Creates a new downloader instance.
36 * @param {Function} dataSource Function that will yield downloadable objects 34 * @param {Function} dataSource
37 * on each check 35 * Function that will yield downloadable objects on each check
38 * @param {Integer} initialDelay Number of milliseconds to wait before the 36 * @param {number} initialDelay
39 * first check 37 * Number of milliseconds to wait before the first check
40 * @param {Integer} checkInterval Interval between the checks 38 * @param {number} checkInterval
39 * Interval between the checks
41 * @constructor 40 * @constructor
42 */ 41 */
43 exports.Downloader = function(dataSource, initialDelay, checkInterval) 42 exports.Downloader = function(dataSource, initialDelay, checkInterval)
44 { 43 {
45 this.dataSource = dataSource; 44 this.dataSource = dataSource;
46 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 45 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
47 this._timer.initWithCallback(() => 46 this._timer.initWithCallback(() =>
48 { 47 {
49 this._timer.delay = checkInterval; 48 this._timer.delay = checkInterval;
50 this._doCheck(); 49 this._doCheck();
(...skipping 15 matching lines...) Expand all
66 65
67 /** 66 /**
68 * Function that will yield downloadable objects on each check. 67 * Function that will yield downloadable objects on each check.
69 * @type {Function} 68 * @type {Function}
70 */ 69 */
71 dataSource: null, 70 dataSource: null,
72 71
73 /** 72 /**
74 * Maximal time interval that the checks can be left out until the soft 73 * Maximal time interval that the checks can be left out until the soft
75 * expiration interval increases. 74 * expiration interval increases.
76 * @type {Integer} 75 * @type {number}
Sebastian Noack 2017/02/20 13:14:51 There is no type or class called "Integer". This s
kzar 2017/02/21 06:13:58 Done.
77 */ 76 */
78 maxAbsenceInterval: 1 * MILLIS_IN_DAY, 77 maxAbsenceInterval: 1 * MILLIS_IN_DAY,
79 78
80 /** 79 /**
81 * Minimal time interval before retrying a download after an error. 80 * Minimal time interval before retrying a download after an error.
82 * @type {Integer} 81 * @type {number}
83 */ 82 */
84 minRetryInterval: 1 * MILLIS_IN_DAY, 83 minRetryInterval: 1 * MILLIS_IN_DAY,
85 84
86 /** 85 /**
87 * Maximal allowed expiration interval, larger expiration intervals will be 86 * Maximal allowed expiration interval, larger expiration intervals will be
88 * corrected. 87 * corrected.
89 * @type {Integer} 88 * @type {number}
90 */ 89 */
91 maxExpirationInterval: 14 * MILLIS_IN_DAY, 90 maxExpirationInterval: 14 * MILLIS_IN_DAY,
92 91
93 /** 92 /**
94 * Maximal number of redirects before the download is considered as failed. 93 * Maximal number of redirects before the download is considered as failed.
95 * @type {Integer} 94 * @type {number}
96 */ 95 */
97 maxRedirects: 5, 96 maxRedirects: 5,
98 97
99 /** 98 /**
100 * Called whenever expiration intervals for an object need to be adapted. 99 * Called whenever expiration intervals for an object need to be adapted.
101 * @type {Function} 100 * @type {Function}
102 */ 101 */
103 onExpirationChange: null, 102 onExpirationChange: null,
104 103
105 /** 104 /**
(...skipping 19 matching lines...) Expand all
125 * Checks whether anything needs downloading. 124 * Checks whether anything needs downloading.
126 */ 125 */
127 _doCheck() 126 _doCheck()
128 { 127 {
129 let now = Date.now(); 128 let now = Date.now();
130 for (let downloadable of this.dataSource()) 129 for (let downloadable of this.dataSource())
131 { 130 {
132 if (downloadable.lastCheck && 131 if (downloadable.lastCheck &&
133 now - downloadable.lastCheck > this.maxAbsenceInterval) 132 now - downloadable.lastCheck > this.maxAbsenceInterval)
134 { 133 {
135 // No checks for a long time interval - user must have been 134 // No checks for a long time interval - user must have been offline,
136 // offline, e.g. during a weekend. Increase soft expiration 135 // e.g. during a weekend. Increase soft expiration to prevent load
137 // to prevent load peaks on the server. 136 // peaks on the server.
138 downloadable.softExpiration += now - downloadable.lastCheck; 137 downloadable.softExpiration += now - downloadable.lastCheck;
139 } 138 }
140 downloadable.lastCheck = now; 139 downloadable.lastCheck = now;
141 140
142 // Sanity check: do expiration times make sense? Make sure people changing 141 // Sanity check: do expiration times make sense? Make sure people changing
143 // system clock don't get stuck with outdated subscriptions. 142 // system clock don't get stuck with outdated subscriptions.
144 if (downloadable.hardExpiration - now > this.maxExpirationInterval) 143 if (downloadable.hardExpiration - now > this.maxExpirationInterval)
145 downloadable.hardExpiration = now + this.maxExpirationInterval; 144 downloadable.hardExpiration = now + this.maxExpirationInterval;
146 if (downloadable.softExpiration - now > this.maxExpirationInterval) 145 if (downloadable.softExpiration - now > this.maxExpirationInterval)
147 downloadable.softExpiration = now + this.maxExpirationInterval; 146 downloadable.softExpiration = now + this.maxExpirationInterval;
148 147
149 // Notify the caller about changes to expiration parameters 148 // Notify the caller about changes to expiration parameters
150 if (this.onExpirationChange) 149 if (this.onExpirationChange)
151 this.onExpirationChange(downloadable); 150 this.onExpirationChange(downloadable);
152 151
153 // Does that object need downloading? 152 // Does that object need downloading?
154 if (downloadable.softExpiration > now && 153 if (downloadable.softExpiration > now &&
155 downloadable.hardExpiration > now) 154 downloadable.hardExpiration > now)
155 {
156 continue; 156 continue;
157 }
157 158
158 // Do not retry downloads too often 159 // Do not retry downloads too often
159 if (downloadable.lastError && 160 if (downloadable.lastError &&
160 now - downloadable.lastError < this.minRetryInterval) 161 now - downloadable.lastError < this.minRetryInterval)
162 {
161 continue; 163 continue;
164 }
162 165
163 this._download(downloadable, 0); 166 this._download(downloadable, 0);
164 } 167 }
165 }, 168 },
166 169
167 /** 170 /**
168 * Stops the periodic checks. 171 * Stops the periodic checks.
169 */ 172 */
170 cancel() 173 cancel()
171 { 174 {
172 this._timer.cancel(); 175 this._timer.cancel();
173 }, 176 },
174 177
175 /** 178 /**
176 * Checks whether an address is currently being downloaded. 179 * Checks whether an address is currently being downloaded.
177 * @param {String} url 180 * @param {string} url
178 * @return {Boolean} 181 * @return {boolean}
179 */ 182 */
180 isDownloading(url) 183 isDownloading(url)
181 { 184 {
182 return url in this._downloading; 185 return url in this._downloading;
183 }, 186 },
184 187
185 /** 188 /**
186 * Starts downloading for an object. 189 * Starts downloading for an object.
187 * @param {Downloadable} downloadable 190 * @param {Downloadable} downloadable
188 */ 191 */
189 download(downloadable) 192 download(downloadable)
190 { 193 {
191 // Make sure to detach download from the current execution context 194 // Make sure to detach download from the current execution context
192 Utils.runAsync(this._download.bind(this, downloadable, 0)); 195 Utils.runAsync(this._download.bind(this, downloadable, 0));
193 }, 196 },
194 197
195 /** 198 /**
196 * Generates the real download URL for an object by appending various 199 * Generates the real download URL for an object by appending various
197 * parameters. 200 * parameters.
198 * @param {Downloadable} downloadable 201 * @param {Downloadable} downloadable
199 * @return {String} 202 * @return {string}
200 */ 203 */
201 getDownloadUrl(downloadable) 204 getDownloadUrl(downloadable)
202 { 205 {
203 let {addonName, addonVersion, application, applicationVersion, 206 const {addonName, addonVersion, application, applicationVersion,
204 platform, platformVersion} = require("info"); 207 platform, platformVersion} = require("info");
205 let url = downloadable.redirectURL || downloadable.url; 208 let url = downloadable.redirectURL || downloadable.url;
206 if (url.indexOf("?") >= 0) 209 if (url.indexOf("?") >= 0)
207 url += "&"; 210 url += "&";
208 else 211 else
209 url += "?"; 212 url += "?";
210 // We limit the download count to 4+ to keep the request anonymized 213 // We limit the download count to 4+ to keep the request anonymized
211 let {downloadCount} = downloadable; 214 let {downloadCount} = downloadable;
212 if (downloadCount > 4) 215 if (downloadCount > 4)
213 downloadCount = "4+"; 216 downloadCount = "4+";
214 url += "addonName=" + encodeURIComponent(addonName) + 217 url += "addonName=" + encodeURIComponent(addonName) +
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 "Download address: " + downloadUrl + "\n" + 249 "Download address: " + downloadUrl + "\n" +
247 "Channel status: " + channelStatus + "\n" + 250 "Channel status: " + channelStatus + "\n" +
248 "Server response: " + responseStatus); 251 "Server response: " + responseStatus);
249 252
250 if (this.onDownloadError) 253 if (this.onDownloadError)
251 { 254 {
252 // Allow one extra redirect if the error handler gives us a redirect URL 255 // Allow one extra redirect if the error handler gives us a redirect URL
253 let redirectCallback = null; 256 let redirectCallback = null;
254 if (redirects <= this.maxRedirects) 257 if (redirects <= this.maxRedirects)
255 { 258 {
256 redirectCallback = (url) => 259 redirectCallback = url =>
257 { 260 {
258 downloadable.redirectURL = url; 261 downloadable.redirectURL = url;
259 this._download(downloadable, redirects + 1); 262 this._download(downloadable, redirects + 1);
260 }; 263 };
261 } 264 }
262 265
263 this.onDownloadError(downloadable, downloadUrl, error, channelStatus, 266 this.onDownloadError(downloadable, downloadUrl, error, channelStatus,
264 responseStatus, redirectCallback); 267 responseStatus, redirectCallback);
265 } 268 }
266 }.bind(this); 269 }.bind(this);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 request.send(null); 339 request.send(null);
337 340
338 this._downloading[downloadable.url] = true; 341 this._downloading[downloadable.url] = true;
339 if (this.onDownloadStarted) 342 if (this.onDownloadStarted)
340 this.onDownloadStarted(downloadable); 343 this.onDownloadStarted(downloadable);
341 }, 344 },
342 345
343 /** 346 /**
344 * Produces a soft and a hard expiration interval for a given supplied 347 * Produces a soft and a hard expiration interval for a given supplied
345 * expiration interval. 348 * expiration interval.
346 * @param {Integer} interval 349 * @param {number} interval
347 * @return {Array} soft and hard expiration interval 350 * @return {Array} soft and hard expiration interval
348 */ 351 */
349 processExpirationInterval(interval) 352 processExpirationInterval(interval)
350 { 353 {
351 interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval); 354 interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval);
352 let soft = Math.round(interval * (Math.random() * 0.4 + 0.8)); 355 let soft = Math.round(interval * (Math.random() * 0.4 + 0.8));
353 let hard = interval * 2; 356 let hard = interval * 2;
354 let now = Date.now(); 357 let now = Date.now();
355 return [now + soft, now + hard]; 358 return [now + soft, now + hard];
356 } 359 }
357 }; 360 };
358 361
359 /** 362 /**
360 * An object that can be downloaded by the downloadable 363 * An object that can be downloaded by the downloadable
361 * @param {String} url URL that has to be requested for the object 364 * @param {string} url URL that has to be requested for the object
362 * @constructor 365 * @constructor
363 */ 366 */
364 let Downloadable = exports.Downloadable = function Downloadable(url) 367 let Downloadable = exports.Downloadable = function Downloadable(url)
365 { 368 {
366 this.url = url; 369 this.url = url;
367 }; 370 };
368 Downloadable.prototype = 371 Downloadable.prototype =
369 { 372 {
370 /** 373 /**
371 * URL that has to be requested for the object. 374 * URL that has to be requested for the object.
372 * @type {String} 375 * @type {string}
373 */ 376 */
374 url: null, 377 url: null,
375 378
376 /** 379 /**
377 * URL that the download was redirected to if any. 380 * URL that the download was redirected to if any.
378 * @type {String} 381 * @type {string}
379 */ 382 */
380 redirectURL: null, 383 redirectURL: null,
381 384
382 /** 385 /**
383 * Time of last download error or 0 if the last download was successful. 386 * Time of last download error or 0 if the last download was successful.
384 * @type {Integer} 387 * @type {number}
385 */ 388 */
386 lastError: 0, 389 lastError: 0,
387 390
388 /** 391 /**
389 * Time of last check whether the object needs downloading. 392 * Time of last check whether the object needs downloading.
390 * @type {Integer} 393 * @type {number}
391 */ 394 */
392 lastCheck: 0, 395 lastCheck: 0,
393 396
394 /** 397 /**
395 * Object version corresponding to the last successful download. 398 * Object version corresponding to the last successful download.
396 * @type {Integer} 399 * @type {number}
397 */ 400 */
398 lastVersion: 0, 401 lastVersion: 0,
399 402
400 /** 403 /**
401 * Soft expiration interval, will increase if no checks are performed for a 404 * Soft expiration interval, will increase if no checks are performed for a
402 * while. 405 * while.
403 * @type {Integer} 406 * @type {number}
404 */ 407 */
405 softExpiration: 0, 408 softExpiration: 0,
406 409
407 /** 410 /**
408 * Hard expiration interval, this is fixed. 411 * Hard expiration interval, this is fixed.
409 * @type {Integer} 412 * @type {number}
410 */ 413 */
411 hardExpiration: 0, 414 hardExpiration: 0,
412 415
413 /** 416 /**
414 * Number indicating how often the object was downloaded. 417 * Number indicating how often the object was downloaded.
415 * @type {Integer} 418 * @type {number}
416 */ 419 */
417 downloadCount: 0 420 downloadCount: 0
418 }; 421 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld