| Index: lib/downloader.js | 
| =================================================================== | 
| deleted file mode 100644 | 
| --- a/lib/downloader.js | 
| +++ /dev/null | 
| @@ -1,394 +0,0 @@ | 
| -/* | 
| - * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| - * Copyright (C) 2006-2016 Eyeo GmbH | 
| - * | 
| - * Adblock Plus is free software: you can redistribute it and/or modify | 
| - * it under the terms of the GNU General Public License version 3 as | 
| - * published by the Free Software Foundation. | 
| - * | 
| - * Adblock Plus is distributed in the hope that it will be useful, | 
| - * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| - * GNU General Public License for more details. | 
| - * | 
| - * You should have received a copy of the GNU General Public License | 
| - * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| - */ | 
| - | 
| -/** | 
| - * @fileOverview Downloads a set of URLs in regular time intervals. | 
| - */ | 
| - | 
| -let {Utils} = require("utils"); | 
| - | 
| -let MILLIS_IN_SECOND = exports.MILLIS_IN_SECOND = 1000; | 
| -let MILLIS_IN_MINUTE = exports.MILLIS_IN_MINUTE = 60 * MILLIS_IN_SECOND; | 
| -let MILLIS_IN_HOUR = exports.MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE; | 
| -let MILLIS_IN_DAY = exports.MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR; | 
| - | 
| -/** | 
| - * Creates a new downloader instance. | 
| - * @param {Function} dataSource  Function that will yield downloadable objects on each check | 
| - * @param {Integer} initialDelay  Number of milliseconds to wait before the first check | 
| - * @param {Integer} checkInterval  Interval between the checks | 
| - * @constructor | 
| - */ | 
| -let Downloader = exports.Downloader = function Downloader(dataSource, initialDelay, checkInterval) | 
| -{ | 
| -  this.dataSource = dataSource; | 
| -  this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 
| -  this._timer.initWithCallback(function() | 
| -  { | 
| -    this._timer.delay = checkInterval; | 
| -    this._doCheck(); | 
| -  }.bind(this), initialDelay, Ci.nsITimer.TYPE_REPEATING_SLACK); | 
| -  this._downloading = Object.create(null); | 
| -} | 
| -Downloader.prototype = | 
| -{ | 
| -  /** | 
| -   * Timer triggering the downloads. | 
| -   * @type nsITimer | 
| -   */ | 
| -  _timer: null, | 
| - | 
| -  /** | 
| -   * Map containing the URLs of objects currently being downloaded as its keys. | 
| -   */ | 
| -  _downloading: null, | 
| - | 
| -  /** | 
| -   * Function that will yield downloadable objects on each check. | 
| -   * @type Function | 
| -   */ | 
| -  dataSource: null, | 
| - | 
| -  /** | 
| -   * Maximal time interval that the checks can be left out until the soft | 
| -   * expiration interval increases. | 
| -   * @type Integer | 
| -   */ | 
| -  maxAbsenceInterval: 1 * MILLIS_IN_DAY, | 
| - | 
| -  /** | 
| -   * Minimal time interval before retrying a download after an error. | 
| -   * @type Integer | 
| -   */ | 
| -  minRetryInterval: 1 * MILLIS_IN_DAY, | 
| - | 
| -  /** | 
| -   * Maximal allowed expiration interval, larger expiration intervals will be | 
| -   * corrected. | 
| -   * @type Integer | 
| -   */ | 
| -  maxExpirationInterval: 14 * MILLIS_IN_DAY, | 
| - | 
| -  /** | 
| -   * Maximal number of redirects before the download is considered as failed. | 
| -   * @type Integer | 
| -   */ | 
| -  maxRedirects: 5, | 
| - | 
| -  /** | 
| -   * Called whenever expiration intervals for an object need to be adapted. | 
| -   * @type Function | 
| -   */ | 
| -  onExpirationChange: null, | 
| - | 
| -  /** | 
| -   * Callback to be triggered whenever a download starts. | 
| -   * @type Function | 
| -   */ | 
| -  onDownloadStarted: null, | 
| - | 
| -  /** | 
| -   * Callback to be triggered whenever a download finishes successfully. The | 
| -   * callback can return an error code to indicate that the data is wrong. | 
| -   * @type Function | 
| -   */ | 
| -  onDownloadSuccess: null, | 
| - | 
| -  /** | 
| -   * Callback to be triggered whenever a download fails. | 
| -   * @type Function | 
| -   */ | 
| -  onDownloadError: null, | 
| - | 
| -  /** | 
| -   * Checks whether anything needs downloading. | 
| -   */ | 
| -  _doCheck: function() | 
| -  { | 
| -    let now = Date.now(); | 
| -    for (let downloadable of this.dataSource()) | 
| -    { | 
| -      if (downloadable.lastCheck && now - downloadable.lastCheck > this.maxAbsenceInterval) | 
| -      { | 
| -        // No checks for a long time interval - user must have been offline, e.g. | 
| -        // during a weekend. Increase soft expiration to prevent load peaks on the | 
| -        // server. | 
| -        downloadable.softExpiration += now - downloadable.lastCheck; | 
| -      } | 
| -      downloadable.lastCheck = now; | 
| - | 
| -      // Sanity check: do expiration times make sense? Make sure people changing | 
| -      // system clock don't get stuck with outdated subscriptions. | 
| -      if (downloadable.hardExpiration - now > this.maxExpirationInterval) | 
| -        downloadable.hardExpiration = now + this.maxExpirationInterval; | 
| -      if (downloadable.softExpiration - now > this.maxExpirationInterval) | 
| -        downloadable.softExpiration = now + this.maxExpirationInterval; | 
| - | 
| -      // Notify the caller about changes to expiration parameters | 
| -      if (this.onExpirationChange) | 
| -        this.onExpirationChange(downloadable); | 
| - | 
| -      // Does that object need downloading? | 
| -      if (downloadable.softExpiration > now && downloadable.hardExpiration > now) | 
| -        continue; | 
| - | 
| -      // Do not retry downloads too often | 
| -      if (downloadable.lastError && now - downloadable.lastError < this.minRetryInterval) | 
| -        continue; | 
| - | 
| -      this._download(downloadable, 0); | 
| -    } | 
| -  }, | 
| - | 
| -  /** | 
| -   * Stops the periodic checks. | 
| -   */ | 
| -  cancel: function() | 
| -  { | 
| -    this._timer.cancel(); | 
| -  }, | 
| - | 
| -  /** | 
| -   * Checks whether an address is currently being downloaded. | 
| -   */ | 
| -  isDownloading: function(/**String*/ url) /**Boolean*/ | 
| -  { | 
| -    return url in this._downloading; | 
| -  }, | 
| - | 
| -  /** | 
| -   * Starts downloading for an object. | 
| -   */ | 
| -  download: function(/**Downloadable*/ downloadable) | 
| -  { | 
| -    // Make sure to detach download from the current execution context | 
| -    Utils.runAsync(this._download.bind(this, downloadable, 0)); | 
| -  }, | 
| - | 
| -  /** | 
| -   * Generates the real download URL for an object by appending various | 
| -   * parameters. | 
| -   */ | 
| -  getDownloadUrl: function(/**Downloadable*/ downloadable)  /** String*/ | 
| -  { | 
| -    let {addonName, addonVersion, application, applicationVersion, platform, platformVersion} = require("info"); | 
| -    let url = downloadable.redirectURL || downloadable.url; | 
| -    if (url.indexOf("?") >= 0) | 
| -      url += "&"; | 
| -    else | 
| -      url += "?"; | 
| -    // We limit the download count to 4+ to keep the request anonymized | 
| -    let downloadCount = downloadable.downloadCount; | 
| -    if (downloadCount > 4) | 
| -      downloadCount = "4+"; | 
| -    url += "addonName=" + encodeURIComponent(addonName) + | 
| -        "&addonVersion=" + encodeURIComponent(addonVersion) + | 
| -        "&application=" + encodeURIComponent(application) + | 
| -        "&applicationVersion=" + encodeURIComponent(applicationVersion) + | 
| -        "&platform=" + encodeURIComponent(platform) + | 
| -        "&platformVersion=" + encodeURIComponent(platformVersion) + | 
| -        "&lastVersion=" + encodeURIComponent(downloadable.lastVersion) + | 
| -        "&downloadCount=" + encodeURIComponent(downloadCount); | 
| -    return url; | 
| -  }, | 
| - | 
| -  _download: function(downloadable, redirects) | 
| -  { | 
| -    if (this.isDownloading(downloadable.url)) | 
| -      return; | 
| - | 
| -    let downloadUrl = this.getDownloadUrl(downloadable); | 
| -    let request = null; | 
| - | 
| -    let errorCallback = function errorCallback(error) | 
| -    { | 
| -      let channelStatus = -1; | 
| -      try | 
| -      { | 
| -        channelStatus = request.channel.status; | 
| -      } catch (e) {} | 
| - | 
| -      let responseStatus = request.status; | 
| - | 
| -      Cu.reportError("Adblock Plus: Downloading URL " + downloadable.url + " failed (" + error + ")\n" + | 
| -                     "Download address: " + downloadUrl + "\n" + | 
| -                     "Channel status: " + channelStatus + "\n" + | 
| -                     "Server response: " + responseStatus); | 
| - | 
| -      if (this.onDownloadError) | 
| -      { | 
| -        // Allow one extra redirect if the error handler gives us a redirect URL | 
| -        let redirectCallback = null; | 
| -        if (redirects <= this.maxRedirects) | 
| -        { | 
| -          redirectCallback = function redirectCallback(url) | 
| -          { | 
| -            downloadable.redirectURL = url; | 
| -            this._download(downloadable, redirects + 1); | 
| -          }.bind(this); | 
| -        } | 
| - | 
| -        this.onDownloadError(downloadable, downloadUrl, error, channelStatus, responseStatus, redirectCallback); | 
| -      } | 
| -    }.bind(this); | 
| - | 
| -    try | 
| -    { | 
| -      request = new XMLHttpRequest(); | 
| -      request.mozBackgroundRequest = true; | 
| -      request.open("GET", downloadUrl); | 
| -    } | 
| -    catch (e) | 
| -    { | 
| -      errorCallback("synchronize_invalid_url"); | 
| -      return; | 
| -    } | 
| - | 
| -    try { | 
| -      request.overrideMimeType("text/plain"); | 
| -      request.channel.loadFlags = request.channel.loadFlags | | 
| -                                  request.channel.INHIBIT_CACHING | | 
| -                                  request.channel.VALIDATE_ALWAYS; | 
| - | 
| -      // Override redirect limit from preferences, user might have set it to 1 | 
| -      if (request.channel instanceof Ci.nsIHttpChannel) | 
| -        request.channel.redirectionLimit = this.maxRedirects; | 
| -    } | 
| -    catch (e) | 
| -    { | 
| -      Cu.reportError(e) | 
| -    } | 
| - | 
| -    request.addEventListener("error", function(event) | 
| -    { | 
| -      if (onShutdown.done) | 
| -        return; | 
| - | 
| -      delete this._downloading[downloadable.url]; | 
| -      errorCallback("synchronize_connection_error"); | 
| -    }.bind(this), false); | 
| - | 
| -    request.addEventListener("load", function(event) | 
| -    { | 
| -      if (onShutdown.done) | 
| -        return; | 
| - | 
| -      delete this._downloading[downloadable.url]; | 
| - | 
| -      // Status will be 0 for non-HTTP requests | 
| -      if (request.status && request.status != 200) | 
| -      { | 
| -        errorCallback("synchronize_connection_error"); | 
| -        return; | 
| -      } | 
| - | 
| -      downloadable.downloadCount++; | 
| - | 
| -      this.onDownloadSuccess(downloadable, request.responseText, errorCallback, function redirectCallback(url) | 
| -      { | 
| -        if (redirects >= this.maxRedirects) | 
| -          errorCallback("synchronize_connection_error"); | 
| -        else | 
| -        { | 
| -          downloadable.redirectURL = url; | 
| -          this._download(downloadable, redirects + 1); | 
| -        } | 
| -      }.bind(this)); | 
| -    }.bind(this), false); | 
| - | 
| -    request.send(null); | 
| - | 
| -    this._downloading[downloadable.url] = true; | 
| -    if (this.onDownloadStarted) | 
| -      this.onDownloadStarted(downloadable); | 
| -  }, | 
| - | 
| -  /** | 
| -   * Produces a soft and a hard expiration interval for a given supplied | 
| -   * expiration interval. | 
| -   * @return {Array} soft and hard expiration interval | 
| -   */ | 
| -  processExpirationInterval: function(/**Integer*/ interval) | 
| -  { | 
| -    interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval); | 
| -    let soft = Math.round(interval * (Math.random() * 0.4 + 0.8)); | 
| -    let hard = interval * 2; | 
| -    let now = Date.now(); | 
| -    return [now + soft, now + hard]; | 
| -  } | 
| -}; | 
| - | 
| -/** | 
| - * An object that can be downloaded by the downloadable | 
| - * @param {String} url  URL that has to be requested for the object | 
| - * @constructor | 
| - */ | 
| -let Downloadable = exports.Downloadable = function Downloadable(url) | 
| -{ | 
| -  this.url = url; | 
| -} | 
| -Downloadable.prototype = | 
| -{ | 
| -  /** | 
| -   * URL that has to be requested for the object. | 
| -   * @type String | 
| -   */ | 
| -  url: null, | 
| - | 
| -  /** | 
| -   * URL that the download was redirected to if any. | 
| -   * @type String | 
| -   */ | 
| -  redirectURL: null, | 
| - | 
| -  /** | 
| -   * Time of last download error or 0 if the last download was successful. | 
| -   * @type Integer | 
| -   */ | 
| -  lastError: 0, | 
| - | 
| -  /** | 
| -   * Time of last check whether the object needs downloading. | 
| -   * @type Integer | 
| -   */ | 
| -  lastCheck: 0, | 
| - | 
| -  /** | 
| -   * Object version corresponding to the last successful download. | 
| -   * @type Integer | 
| -   */ | 
| -  lastVersion: 0, | 
| - | 
| -  /** | 
| -   * Soft expiration interval, will increase if no checks are performed for a | 
| -   * while. | 
| -   * @type Integer | 
| -   */ | 
| -  softExpiration: 0, | 
| - | 
| -  /** | 
| -   * Hard expiration interval, this is fixed. | 
| -   * @type Integer | 
| -   */ | 
| -  hardExpiration: 0, | 
| - | 
| -  /** | 
| -   * Number indicating how often the object was downloaded. | 
| -   * @type Integer | 
| -   */ | 
| -  downloadCount: 0, | 
| -}; | 
|  |