| 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-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  Loading... | 
| 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) | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 }; | 
| LEFT | RIGHT | 
|---|