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

Delta Between Two Patch Sets: lib/downloader.js

Issue 29336735: Issue 394 - hit statistics tool data collection (core) (Closed)
Left Patch Set: Include modules conditionally update Downloader to accept callback for download event Created March 17, 2016, 6:09 p.m.
Right Patch Set: Use Downloader to send the data to server Created April 6, 2016, 2:55 p.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 | « no previous file | lib/filterListener.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
(...skipping 13 matching lines...) Expand all
24 let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000; 24 let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000;
25 let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; 25 let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND;
26 let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; 26 let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
27 let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; 27 let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
28 28
29 /** 29 /**
30 * Creates a new downloader instance. 30 * Creates a new downloader instance.
31 * @param {Function} dataSource Function that will yield downloadable objects o n each check 31 * @param {Function} dataSource Function that will yield downloadable objects o n each check
32 * @param {Integer} initialDelay Number of milliseconds to wait before the firs t check 32 * @param {Integer} initialDelay Number of milliseconds to wait before the firs t check
33 * @param {Integer} checkInterval Interval between the checks 33 * @param {Integer} checkInterval Interval between the checks
34 * @param {function} downloadCallback optional function that's being called when something needs to be downloaded
35 * @constructor 34 * @constructor
36 */ 35 */
37 let Downloader = exports.Downloader = function Downloader(dataSource, initialDel ay, checkInterval, downloadCallback) 36 let Downloader = exports.Downloader = function Downloader(dataSource, initialDel ay, checkInterval)
saroyanm 2016/03/18 18:24:48 Maybe this changes will be reverted if you agree w
Wladimir Palant 2016/03/23 11:06:01 You are still duplicating quite a bit of the logic
saroyanm 2016/04/06 15:12:49 Thanks for detailed explanation, Done.
38 { 37 {
39 this.dataSource = dataSource; 38 this.dataSource = dataSource;
40 this.downloadCallback = downloadCallback || this._download;
41 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 39 this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
42 this._timer.initWithCallback(function() 40 this._timer.initWithCallback(function()
43 { 41 {
44 this._timer.delay = checkInterval; 42 this._timer.delay = checkInterval;
45 this._doCheck(); 43 this._doCheck();
46 }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK); 44 }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK);
47 this._downloading = Object.create(null); 45 this._downloading = Object.create(null);
48 } 46 }
49 Downloader.prototype = 47 Downloader.prototype =
50 { 48 {
51 /** 49 /**
52 * Timer triggering the downloads. 50 * Timer triggering the downloads.
53 * @type nsITimer 51 * @type nsITimer
54 */ 52 */
55 _timer: null, 53 _timer: null,
56 54
57 /** 55 /**
58 * Map containing the URLs of objects currently being downloaded as its keys. 56 * Map containing the URLs of objects currently being downloaded as its keys.
59 */ 57 */
60 _downloading: null, 58 _downloading: null,
61 59
62 /** 60 /**
63 * Function that will yield downloadable objects on each check. 61 * Function that will yield downloadable objects on each check.
64 * @type Function 62 * @type Function
65 */ 63 */
66 dataSource: null, 64 dataSource: null,
67 65
68 /** 66 /**
69 * Function that's being called when something needs to be downloaded.
70 * @type Function
71 */
72 downloadCallback: null,
73
74 /**
75 * Maximal time interval that the checks can be left out until the soft 67 * Maximal time interval that the checks can be left out until the soft
76 * expiration interval increases. 68 * expiration interval increases.
77 * @type Integer 69 * @type Integer
78 */ 70 */
79 maxAbsenceInterval: 1 * MILLIS_IN_DAY, 71 maxAbsenceInterval: 1 * MILLIS_IN_DAY,
80 72
81 /** 73 /**
82 * Minimal time interval before retrying a download after an error. 74 * Minimal time interval before retrying a download after an error.
83 * @type Integer 75 * @type Integer
84 */ 76 */
(...skipping 29 matching lines...) Expand all
114 * callback can return an error code to indicate that the data is wrong. 106 * callback can return an error code to indicate that the data is wrong.
115 * @type Function 107 * @type Function
116 */ 108 */
117 onDownloadSuccess: null, 109 onDownloadSuccess: null,
118 110
119 /** 111 /**
120 * Callback to be triggered whenever a download fails. 112 * Callback to be triggered whenever a download fails.
121 * @type Function 113 * @type Function
122 */ 114 */
123 onDownloadError: null, 115 onDownloadError: null,
116
117 /**
118 * Callback to be triggered for POST request data generation.
119 * @type Function
120 */
121 generateRequestData: null,
122
123 /**
124 * List of valid responses.
125 * @type Array
126 */
127 validResponses: [200],
124 128
125 /** 129 /**
126 * Checks whether anything needs downloading. 130 * Checks whether anything needs downloading.
127 */ 131 */
128 _doCheck: function() 132 _doCheck: function()
129 { 133 {
130 let now = Date.now(); 134 let now = Date.now();
131 for (let downloadable of this.dataSource()) 135 for (let downloadable of this.dataSource())
132 { 136 {
133 if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsen ceInterval) 137 if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsen ceInterval)
(...skipping 17 matching lines...) Expand all
151 this.onExpirationChange(downloadable); 155 this.onExpirationChange(downloadable);
152 156
153 // Does that object need downloading? 157 // Does that object need downloading?
154 if (downloadable.softExpiration > now && downloadable.hardExpiration > now ) 158 if (downloadable.softExpiration > now && downloadable.hardExpiration > now )
155 continue; 159 continue;
156 160
157 // Do not retry downloads too often 161 // Do not retry downloads too often
158 if (downloadable.lastError && now - downloadable.lastError < this.minRetry Interval) 162 if (downloadable.lastError && now - downloadable.lastError < this.minRetry Interval)
159 continue; 163 continue;
160 164
161 this.downloadCallback(downloadable, 0); 165 this._download(downloadable, 0);
162 } 166 }
163 }, 167 },
164 168
165 /** 169 /**
166 * Stops the periodic checks. 170 * Stops the periodic checks.
167 */ 171 */
168 cancel: function() 172 cancel: function()
169 { 173 {
170 this._timer.cancel(); 174 this._timer.cancel();
171 }, 175 },
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 } 255 }
252 256
253 this.onDownloadError(downloadable, downloadUrl, error, channelStatus, re sponseStatus, redirectCallback); 257 this.onDownloadError(downloadable, downloadUrl, error, channelStatus, re sponseStatus, redirectCallback);
254 } 258 }
255 }.bind(this); 259 }.bind(this);
256 260
257 try 261 try
258 { 262 {
259 request = new XMLHttpRequest(); 263 request = new XMLHttpRequest();
260 request.mozBackgroundRequest = true; 264 request.mozBackgroundRequest = true;
261 request.open("GET", downloadUrl); 265 request.open(this.generateRequestData ? "POST" : "GET", downloadUrl);
262 } 266 }
263 catch (e) 267 catch (e)
264 { 268 {
265 errorCallback("synchronize_invalid_url"); 269 errorCallback("synchronize_invalid_url");
266 return; 270 return;
267 } 271 }
268 272
269 try { 273 try {
270 request.overrideMimeType("text/plain"); 274 request.overrideMimeType("text/plain");
271 request.channel.loadFlags = request.channel.loadFlags | 275 request.channel.loadFlags = request.channel.loadFlags |
(...skipping 19 matching lines...) Expand all
291 }.bind(this), false); 295 }.bind(this), false);
292 296
293 request.addEventListener("load", function(event) 297 request.addEventListener("load", function(event)
294 { 298 {
295 if (onShutdown.done) 299 if (onShutdown.done)
296 return; 300 return;
297 301
298 delete this._downloading[downloadable.url]; 302 delete this._downloading[downloadable.url];
299 303
300 // Status will be 0 for non-HTTP requests 304 // Status will be 0 for non-HTTP requests
301 if (request.status && request.status != 200) 305 if (request.status && this.validResponses.indexOf(request.status) == -1)
302 { 306 {
303 errorCallback("synchronize_connection_error"); 307 errorCallback("synchronize_connection_error");
304 return; 308 return;
305 } 309 }
306 310
307 downloadable.downloadCount++; 311 downloadable.downloadCount++;
308 312
309 this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url) 313 this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url)
310 { 314 {
311 if (redirects >= this.maxRedirects) 315 if (redirects >= this.maxRedirects)
312 errorCallback("synchronize_connection_error"); 316 errorCallback("synchronize_connection_error");
313 else 317 else
314 { 318 {
315 downloadable.redirectURL = url; 319 downloadable.redirectURL = url;
316 this._download(downloadable, redirects + 1); 320 this._download(downloadable, redirects + 1);
317 } 321 }
318 }.bind(this)); 322 }.bind(this));
319 }.bind(this), false); 323 }.bind(this), false);
320 324
321 request.send(null); 325 if (this.generateRequestData)
326 {
327 Promise.resolve(this.generateRequestData(downloadable))
328 .then(data => {
329 request.setRequestHeader("Content-Type", "application/json");
330 request.send(JSON.stringify(data));
331 });
332 }
333 else
334 request.send(null);
322 335
323 this._downloading[downloadable.url] = true; 336 this._downloading[downloadable.url] = true;
324 if (this.onDownloadStarted) 337 if (this.onDownloadStarted)
325 this.onDownloadStarted(downloadable); 338 this.onDownloadStarted(downloadable);
326 }, 339 },
327 340
328 /** 341 /**
329 * Produces a soft and a hard expiration interval for a given supplied 342 * Produces a soft and a hard expiration interval for a given supplied
330 * expiration interval. 343 * expiration interval.
331 * @return {Array} soft and hard expiration interval 344 * @return {Array} soft and hard expiration interval
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 * @type Integer 406 * @type Integer
394 */ 407 */
395 hardExpiration: 0, 408 hardExpiration: 0,
396 409
397 /** 410 /**
398 * Number indicating how often the object was downloaded. 411 * Number indicating how often the object was downloaded.
399 * @type Integer 412 * @type Integer
400 */ 413 */
401 downloadCount: 0, 414 downloadCount: 0,
402 }; 415 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld