| Index: lib/synchronizer.js | 
| =================================================================== | 
| --- a/lib/synchronizer.js | 
| +++ b/lib/synchronizer.js | 
| @@ -31,123 +31,118 @@ | 
| const {Subscription, | 
| DownloadableSubscription} = require("./subscriptionClasses"); | 
|  | 
| const INITIAL_DELAY = 1 * MILLIS_IN_MINUTE; | 
| const CHECK_INTERVAL = 1 * MILLIS_IN_HOUR; | 
| const DEFAULT_EXPIRATION_INTERVAL = 5 * MILLIS_IN_DAY; | 
|  | 
| /** | 
| - * The object providing actual downloading functionality. | 
| - * @type {Downloader} | 
| - */ | 
| -let downloader = null; | 
| - | 
| -/** | 
| - * This object is responsible for downloading filter subscriptions whenever | 
| - * necessary. | 
| - * @class | 
| + * Downloads filter subscriptions whenever necessary. | 
| */ | 
| -let Synchronizer = exports.Synchronizer = | 
| +class Synchronizer | 
| { | 
| -  /** | 
| -   * Called on module startup. | 
| -   */ | 
| -  init() | 
| +  constructor() | 
| { | 
| -    downloader = new Downloader(this._getDownloadables.bind(this), | 
| -                                INITIAL_DELAY, CHECK_INTERVAL); | 
| +    /** | 
| +     * The object providing actual downloading functionality. | 
| +     * @type {Downloader} | 
| +     */ | 
| +    this._downloader = new Downloader(this._getDownloadables.bind(this), | 
| +                                      INITIAL_DELAY, CHECK_INTERVAL); | 
| onShutdown.add(() => | 
| { | 
| -      downloader.cancel(); | 
| +      this._downloader.cancel(); | 
| }); | 
|  | 
| -    downloader.onExpirationChange = this._onExpirationChange.bind(this); | 
| -    downloader.onDownloadStarted = this._onDownloadStarted.bind(this); | 
| -    downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this); | 
| -    downloader.onDownloadError = this._onDownloadError.bind(this); | 
| -  }, | 
| +    this._downloader.onExpirationChange = this._onExpirationChange.bind(this); | 
| +    this._downloader.onDownloadStarted = this._onDownloadStarted.bind(this); | 
| +    this._downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this); | 
| +    this._downloader.onDownloadError = this._onDownloadError.bind(this); | 
| +  } | 
|  | 
| /** | 
| * Checks whether a subscription is currently being downloaded. | 
| * @param {string} url  URL of the subscription | 
| -   * @return {boolean} | 
| +   * @returns {boolean} | 
| */ | 
| isExecuting(url) | 
| { | 
| -    return downloader.isDownloading(url); | 
| -  }, | 
| +    return this._downloader.isDownloading(url); | 
| +  } | 
|  | 
| /** | 
| * Starts the download of a subscription. | 
| * @param {DownloadableSubscription} subscription | 
| *   Subscription to be downloaded | 
| * @param {boolean} manual | 
| -   *   true for a manually started download (should not trigger fallback | 
| -   *   requests) | 
| +   *   <code>true</code> for a manually started download (should not trigger | 
| +   *   fallback requests) | 
| */ | 
| execute(subscription, manual) | 
| { | 
| -    downloader.download(this._getDownloadable(subscription, manual)); | 
| -  }, | 
| +    this._downloader.download(this._getDownloadable(subscription, manual)); | 
| +  } | 
|  | 
| /** | 
| -   * Yields Downloadable instances for all subscriptions that can be downloaded. | 
| +   * Yields {@link Downloadable} instances for all subscriptions that can be | 
| +   * downloaded. | 
| +   * @yields {Downloadable} | 
| */ | 
| *_getDownloadables() | 
| { | 
| if (!Prefs.subscriptions_autoupdate) | 
| return; | 
|  | 
| for (let subscription of FilterStorage.subscriptions) | 
| { | 
| if (subscription instanceof DownloadableSubscription) | 
| yield this._getDownloadable(subscription, false); | 
| } | 
| -  }, | 
| +  } | 
|  | 
| /** | 
| -   * Creates a Downloadable instance for a subscription. | 
| +   * Creates a {@link Downloadable} instance for a subscription. | 
| * @param {Subscription} subscription | 
| * @param {boolean} manual | 
| -   * @return {Downloadable} | 
| +   * @returns {Downloadable} | 
| */ | 
| _getDownloadable(subscription, manual) | 
| { | 
| let result = new Downloadable(subscription.url); | 
| if (subscription.lastDownload != subscription.lastSuccess) | 
| result.lastError = subscription.lastDownload * MILLIS_IN_SECOND; | 
| result.lastCheck = subscription.lastCheck * MILLIS_IN_SECOND; | 
| result.lastVersion = subscription.version; | 
| result.softExpiration = subscription.softExpiration * MILLIS_IN_SECOND; | 
| result.hardExpiration = subscription.expires * MILLIS_IN_SECOND; | 
| result.manual = manual; | 
| result.downloadCount = subscription.downloadCount; | 
| return result; | 
| -  }, | 
| +  } | 
|  | 
| _onExpirationChange(downloadable) | 
| { | 
| let subscription = Subscription.fromURL(downloadable.url); | 
| subscription.lastCheck = Math.round( | 
| downloadable.lastCheck / MILLIS_IN_SECOND | 
| ); | 
| subscription.softExpiration = Math.round( | 
| downloadable.softExpiration / MILLIS_IN_SECOND | 
| ); | 
| subscription.expires = Math.round( | 
| downloadable.hardExpiration / MILLIS_IN_SECOND | 
| ); | 
| -  }, | 
| +  } | 
|  | 
| _onDownloadStarted(downloadable) | 
| { | 
| let subscription = Subscription.fromURL(downloadable.url); | 
| filterNotifier.emit("subscription.downloading", subscription); | 
| -  }, | 
| +  } | 
|  | 
| _onDownloadSuccess(downloadable, responseText, errorCallback, | 
| redirectCallback) | 
| { | 
| let lines = responseText.split(/[\r\n]+/); | 
| let headerMatch = /\[Adblock(?:\s*Plus\s*([\d.]+)?)?\]/i.exec(lines[0]); | 
| if (!headerMatch) | 
| return errorCallback("synchronize_invalid_data"); | 
| @@ -246,17 +241,17 @@ | 
| else | 
| expirationInterval = interval * MILLIS_IN_DAY; | 
| } | 
| } | 
|  | 
| let [ | 
| softExpiration, | 
| hardExpiration | 
| -    ] = downloader.processExpirationInterval(expirationInterval); | 
| +    ] = this._downloader.processExpirationInterval(expirationInterval); | 
| subscription.softExpiration = Math.round(softExpiration / MILLIS_IN_SECOND); | 
| subscription.expires = Math.round(hardExpiration / MILLIS_IN_SECOND); | 
|  | 
| if (minVersion) | 
| subscription.requiredVersion = minVersion; | 
| else | 
| delete subscription.requiredVersion; | 
|  | 
| @@ -266,17 +261,17 @@ | 
| for (let line of lines) | 
| { | 
| line = Filter.normalize(line); | 
| if (line) | 
| filters.push(Filter.fromText(line)); | 
| } | 
|  | 
| FilterStorage.updateSubscriptionFilters(subscription, filters); | 
| -  }, | 
| +  } | 
|  | 
| _onDownloadError(downloadable, downloadURL, error, channelStatus, | 
| responseStatus, redirectCallback) | 
| { | 
| let subscription = Subscription.fromURL(downloadable.url); | 
| subscription.lastDownload = Math.round(Date.now() / MILLIS_IN_SECOND); | 
| subscription.downloadStatus = error; | 
|  | 
| @@ -333,10 +328,18 @@ | 
| subscription.filters.map(f => f.text).join("\n"); | 
| redirectCallback("data:text/plain," + encodeURIComponent(data)); | 
| } | 
| }, false); | 
| request.send(null); | 
| } | 
| } | 
| } | 
| -}; | 
| -Synchronizer.init(); | 
| +} | 
| + | 
| +/** | 
| + * This object is responsible for downloading filter subscriptions whenever | 
| + * necessary. | 
| + * @type {Synchronizer} | 
| + */ | 
| +let synchronizer = new Synchronizer(); | 
| + | 
| +exports.Synchronizer = synchronizer; | 
|  |