| Index: lib/updater.js |
| =================================================================== |
| --- a/lib/updater.js |
| +++ b/lib/updater.js |
| @@ -11,82 +11,95 @@ |
| * 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/>. |
| */ |
| let {Prefs} = require("prefs"); |
| +let {Downloader, Downloadable, MILLIS_IN_HOUR} = require("downloader"); |
| + |
| let updateUrl = (_appInfo.developmentBuild ? Prefs.update_url_devbuild : Prefs.update_url_release); |
| -updateUrl = updateUrl.replace(/%NAME%/g, encodeURIComponent(_appInfo.name)) |
| - .replace(/%ID%/g, encodeURIComponent(_appInfo.id)) |
| - .replace(/%VERSION%/g, encodeURIComponent(_appInfo.version)) |
| - .replace(/%APP%/g, encodeURIComponent(_appInfo.platform)); |
| +updateUrl = updateUrl.replace(/%NAME%/g, encodeURIComponent(_appInfo.name)); |
| -const HOURS_TO_MILLIS = 60 * 60 * 1000; |
| -const MIN_CHECK_INTERVAL = 18 * HOURS_TO_MILLIS; |
| -const MAX_CHECK_INTERVAL = 30 * HOURS_TO_MILLIS; |
| +let callback = null; |
| +const INITIAL_DELAY = 0.1 * MILLIS_IN_HOUR; |
| +const CHECK_INTERVAL = 1 * MILLIS_IN_HOUR; |
| +const EXPIRATION_INTERVAL = 24 * MILLIS_IN_HOUR; |
| const TYPE_AUTOMATIC = 0; |
| const TYPE_MANUAL = 1; |
| -let checkForUpdates = exports.checkForUpdates = function checkForUpdates(forceCheck, callback) |
| +let downloader = new Downloader(getDownloadables, INITIAL_DELAY, CHECK_INTERVAL); |
| +downloader.onExpirationChange = onExpirationChange; |
| +downloader.onDownloadSuccess = onDownloadSuccess; |
| +downloader.onDownloadError = onDownloadError; |
| + |
| +function getDownloadable(forceCheck) |
| { |
| - let now = Date.now(); |
| - if (!forceCheck && now < Prefs.next_update_check) |
| + let url = updateUrl.replace(/%TYPE%/g, forceCheck ? TYPE_MANUAL : TYPE_AUTOMATIC); |
| + let downloadable = new Downloadable(url); |
| + downloadable.lastError = Prefs.update_last_error; |
| + downloadable.lastCheck = Prefs.update_last_check; |
| + downloadable.softExpiration = Prefs.update_soft_expiration; |
| + downloadable.hardExpiration = Prefs.update_hard_expiration; |
| + return downloadable; |
| +} |
| + |
| +function getDownloadables() |
| +{ |
| + yield getDownloadable(false); |
| +} |
| + |
| +function onExpirationChange(downloadable) |
| +{ |
| + Prefs.update_last_check = downloadable.lastCheck; |
| + Prefs.update_soft_expiration = downloadable.softExpiration; |
| + Prefs.update_hard_expiration = downloadable.hardExpiration; |
| +} |
| + |
| +function onDownloadSuccess(downloadable, responseText, errorCallback, redirectCallback) |
| +{ |
| + Prefs.update_last_error = 0; |
| + [Prefs.update_soft_expiration, Prefs.update_hard_expiration] = downloader.processExpirationInterval(EXPIRATION_INTERVAL); |
| + |
| + try |
| { |
| - if (Prefs.next_update_check - now > MAX_CHECK_INTERVAL) |
| - Prefs.next_update_check = now + MAX_CHECK_INTERVAL; |
| + let data = JSON.parse(responseText); |
| + let updateInfo = null; |
| + if (_appInfo.name in data) |
| + updateInfo = data[_appInfo.name]; |
| + else if (_appInfo.name + "/" + _appInfo.application in data) |
| + updateInfo = data[_appInfo.name + "/" + _appInfo.application]; |
| - window.setTimeout(checkForUpdates, Prefs.next_update_check - now); |
| - return; |
| + if (updateInfo && "version" in updateInfo && "url" in updateInfo && |
| + Services.vc.compare(updateInfo.version, _appInfo.version) > 0) |
| + { |
| + if (updateInfo.url.indexOf("https://") != 0) |
| + throw new Error("Invalid update URL, HTTPS is mandatory for updates"); |
| + _triggerEvent("updateAvailable", updateInfo.url); |
| + } |
| + if (callback) |
| + callback(null); |
| + } |
| + catch (e) |
| + { |
| + Cu.reportError(e); |
| + errorCallback(e); |
| } |
| - Prefs.next_update_check = now + MIN_CHECK_INTERVAL + |
| - Math.random() * (MAX_CHECK_INTERVAL - MIN_CHECK_INTERVAL); |
| - if (!forceCheck) |
| - window.setTimeout(checkForUpdates, Prefs.next_update_check - now); |
| - |
| - let url = updateUrl.replace(/%TYPE%/g, forceCheck ? TYPE_MANUAL : TYPE_AUTOMATIC); |
| - let request = new XMLHttpRequest(); |
| - request.open("GET", url); |
| - request.addEventListener("load", function() |
| - { |
| - try |
| - { |
| - let data = JSON.parse(request.responseText); |
| - let updateInfo = null; |
| - if (_appInfo.name in data) |
| - updateInfo = data[_appInfo.name]; |
| - else if (_appInfo.name + "/" + _appInfo.platform in data) |
| - updateInfo = data[_appInfo.name + "/" + _appInfo.platform]; |
| - |
| - if (updateInfo && "version" in updateInfo && "url" in updateInfo && |
| - Services.vc.compare(updateInfo.version, _appInfo.version) > 0) |
| - { |
| - if (updateInfo.url.indexOf("https://") != 0) |
| - throw new Error("Invalid update URL, HTTPS is mandatory for updates"); |
| - _triggerEvent("updateAvailable", updateInfo.url); |
| - } |
| - if (callback) |
| - callback(null); |
| - } |
| - catch (e) |
| - { |
| - Cu.reportError(e); |
| - if (callback) |
| - callback(e); |
| - } |
| - }, false); |
| - |
| - request.addEventListener("error", function() |
| - { |
| - let e = new Error("Update check failed (channel status " + request.channel.status + ")"); |
| - Cu.reportError(e); |
| - if (callback) |
| - callback(e); |
| - }, false); |
| - |
| - request.send(null); |
| + callback = null; |
| } |
| -window.setTimeout(checkForUpdates, 0.1 * HOURS_TO_MILLIS); |
| +function onDownloadError(downloadable, downloadURL, error, channelStatus, responseStatus, redirectCallback) |
| +{ |
| + Prefs.update_last_error = Date.now(); |
| + if (callback) |
| + callback(error); |
| + callback = null; |
| +} |
| + |
| +let checkForUpdates = exports.checkForUpdates = function checkForUpdates(_callback) |
| +{ |
| + callback = _callback; |
| + downloader.download(getDownloadable(true)); |
| +} |