1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/aboutDialog.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,645 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +// Services = object with smart getters for common XPCOM services 1.9 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.10 + 1.11 +const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; 1.12 + 1.13 +#ifdef TOR_BROWSER_VERSION 1.14 +# Add double-quotes back on (stripped by JarMaker.py). 1.15 +#expand const TOR_BROWSER_VERSION = "__TOR_BROWSER_VERSION__"; 1.16 +#endif 1.17 + 1.18 +function init(aEvent) 1.19 +{ 1.20 + if (aEvent.target != document) 1.21 + return; 1.22 + 1.23 + try { 1.24 + var distroId = Services.prefs.getCharPref("distribution.id"); 1.25 + if (distroId) { 1.26 + var distroVersion = Services.prefs.getCharPref("distribution.version"); 1.27 + 1.28 + var distroIdField = document.getElementById("distributionId"); 1.29 + distroIdField.value = distroId + " - " + distroVersion; 1.30 + distroIdField.style.display = "block"; 1.31 + 1.32 + try { 1.33 + // This is in its own try catch due to bug 895473 and bug 900925. 1.34 + var distroAbout = Services.prefs.getComplexValue("distribution.about", 1.35 + Components.interfaces.nsISupportsString); 1.36 + var distroField = document.getElementById("distribution"); 1.37 + distroField.value = distroAbout; 1.38 + distroField.style.display = "block"; 1.39 + } 1.40 + catch (ex) { 1.41 + // Pref is unset 1.42 + Components.utils.reportError(ex); 1.43 + } 1.44 + } 1.45 + } 1.46 + catch (e) { 1.47 + // Pref is unset 1.48 + } 1.49 + 1.50 + // Include the build ID and display warning if this is an "a#" (nightly or aurora) build 1.51 + let version = Services.appinfo.version; 1.52 + if (/a\d+$/.test(version)) { 1.53 + document.getElementById("experimental").hidden = false; 1.54 + document.getElementById("communityDesc").hidden = true; 1.55 + } 1.56 + 1.57 +#ifdef TOR_BROWSER_VERSION 1.58 + let versionElem = document.getElementById("version"); 1.59 + if (versionElem) 1.60 + versionElem.textContent += " (Tor Browser " + TOR_BROWSER_VERSION + ")"; 1.61 +#endif 1.62 + 1.63 +#ifdef MOZ_UPDATER 1.64 + gAppUpdater = new appUpdater(); 1.65 + 1.66 +#if MOZ_UPDATE_CHANNEL != release 1.67 + let defaults = Services.prefs.getDefaultBranch(""); 1.68 + let channelLabel = document.getElementById("currentChannel"); 1.69 + channelLabel.value = defaults.getCharPref("app.update.channel"); 1.70 +#endif 1.71 +#endif 1.72 + 1.73 +#ifdef XP_MACOSX 1.74 + // it may not be sized at this point, and we need its width to calculate its position 1.75 + window.sizeToContent(); 1.76 + window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5); 1.77 +#endif 1.78 +} 1.79 + 1.80 +#ifdef MOZ_UPDATER 1.81 +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 1.82 +Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); 1.83 +Components.utils.import("resource://gre/modules/AddonManager.jsm"); 1.84 + 1.85 +var gAppUpdater; 1.86 + 1.87 +function onUnload(aEvent) { 1.88 + if (gAppUpdater.isChecking) 1.89 + gAppUpdater.checker.stopChecking(Components.interfaces.nsIUpdateChecker.CURRENT_CHECK); 1.90 + // Safe to call even when there isn't a download in progress. 1.91 + gAppUpdater.removeDownloadListener(); 1.92 + gAppUpdater = null; 1.93 +} 1.94 + 1.95 + 1.96 +function appUpdater() 1.97 +{ 1.98 + this.updateDeck = document.getElementById("updateDeck"); 1.99 + 1.100 + // Hide the update deck when there is already an update window open to avoid 1.101 + // syncing issues between them. 1.102 + if (Services.wm.getMostRecentWindow("Update:Wizard")) { 1.103 + this.updateDeck.hidden = true; 1.104 + return; 1.105 + } 1.106 + 1.107 + XPCOMUtils.defineLazyServiceGetter(this, "aus", 1.108 + "@mozilla.org/updates/update-service;1", 1.109 + "nsIApplicationUpdateService"); 1.110 + XPCOMUtils.defineLazyServiceGetter(this, "checker", 1.111 + "@mozilla.org/updates/update-checker;1", 1.112 + "nsIUpdateChecker"); 1.113 + XPCOMUtils.defineLazyServiceGetter(this, "um", 1.114 + "@mozilla.org/updates/update-manager;1", 1.115 + "nsIUpdateManager"); 1.116 + 1.117 + this.bundle = Services.strings. 1.118 + createBundle("chrome://browser/locale/browser.properties"); 1.119 + 1.120 + let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual"); 1.121 + let manualLink = document.getElementById("manualLink"); 1.122 + manualLink.value = manualURL; 1.123 + manualLink.href = manualURL; 1.124 + document.getElementById("failedLink").href = manualURL; 1.125 + 1.126 + if (this.updateDisabledAndLocked) { 1.127 + this.selectPanel("adminDisabled"); 1.128 + return; 1.129 + } 1.130 + 1.131 + if (this.isPending || this.isApplied) { 1.132 + this.selectPanel("apply"); 1.133 + return; 1.134 + } 1.135 + 1.136 + if (this.aus.isOtherInstanceHandlingUpdates) { 1.137 + this.selectPanel("otherInstanceHandlingUpdates"); 1.138 + return; 1.139 + } 1.140 + 1.141 + if (this.isDownloading) { 1.142 + this.startDownload(); 1.143 + // selectPanel("downloading") is called from setupDownloadingUI(). 1.144 + return; 1.145 + } 1.146 + 1.147 + // Honor the "Never check for updates" option by not only disabling background 1.148 + // update checks, but also in the About dialog, by presenting a 1.149 + // "Check for updates" button. 1.150 + // If updates are found, the user is then asked if he wants to "Update to <version>". 1.151 + if (!this.updateEnabled) { 1.152 + this.selectPanel("checkForUpdates"); 1.153 + return; 1.154 + } 1.155 + 1.156 + // That leaves the options 1.157 + // "Check for updates, but let me choose whether to install them", and 1.158 + // "Automatically install updates". 1.159 + // In both cases, we check for updates without asking. 1.160 + // In the "let me choose" case, we ask before downloading though, in onCheckComplete. 1.161 + this.checkForUpdates(); 1.162 +} 1.163 + 1.164 +appUpdater.prototype = 1.165 +{ 1.166 + // true when there is an update check in progress. 1.167 + isChecking: false, 1.168 + 1.169 + // true when there is an update already staged / ready to be applied. 1.170 + get isPending() { 1.171 + if (this.update) { 1.172 + return this.update.state == "pending" || 1.173 + this.update.state == "pending-service"; 1.174 + } 1.175 + return this.um.activeUpdate && 1.176 + (this.um.activeUpdate.state == "pending" || 1.177 + this.um.activeUpdate.state == "pending-service"); 1.178 + }, 1.179 + 1.180 + // true when there is an update already installed in the background. 1.181 + get isApplied() { 1.182 + if (this.update) 1.183 + return this.update.state == "applied" || 1.184 + this.update.state == "applied-service"; 1.185 + return this.um.activeUpdate && 1.186 + (this.um.activeUpdate.state == "applied" || 1.187 + this.um.activeUpdate.state == "applied-service"); 1.188 + }, 1.189 + 1.190 + // true when there is an update download in progress. 1.191 + get isDownloading() { 1.192 + if (this.update) 1.193 + return this.update.state == "downloading"; 1.194 + return this.um.activeUpdate && 1.195 + this.um.activeUpdate.state == "downloading"; 1.196 + }, 1.197 + 1.198 + // true when updating is disabled by an administrator. 1.199 + get updateDisabledAndLocked() { 1.200 + return !this.updateEnabled && 1.201 + Services.prefs.prefIsLocked("app.update.enabled"); 1.202 + }, 1.203 + 1.204 + // true when updating is enabled. 1.205 + get updateEnabled() { 1.206 + try { 1.207 + return Services.prefs.getBoolPref("app.update.enabled"); 1.208 + } 1.209 + catch (e) { } 1.210 + return true; // Firefox default is true 1.211 + }, 1.212 + 1.213 + // true when updating in background is enabled. 1.214 + get backgroundUpdateEnabled() { 1.215 + return this.updateEnabled && 1.216 + gAppUpdater.aus.canStageUpdates; 1.217 + }, 1.218 + 1.219 + // true when updating is automatic. 1.220 + get updateAuto() { 1.221 + try { 1.222 + return Services.prefs.getBoolPref("app.update.auto"); 1.223 + } 1.224 + catch (e) { } 1.225 + return true; // Firefox default is true 1.226 + }, 1.227 + 1.228 + /** 1.229 + * Sets the panel of the updateDeck. 1.230 + * 1.231 + * @param aChildID 1.232 + * The id of the deck's child to select, e.g. "apply". 1.233 + */ 1.234 + selectPanel: function(aChildID) { 1.235 + let panel = document.getElementById(aChildID); 1.236 + 1.237 + let button = panel.querySelector("button"); 1.238 + if (button) { 1.239 + if (aChildID == "downloadAndInstall") { 1.240 + let updateVersion = gAppUpdater.update.displayVersion; 1.241 + button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1); 1.242 + button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey"); 1.243 + } 1.244 + this.updateDeck.selectedPanel = panel; 1.245 + if (!document.commandDispatcher.focusedElement || // don't steal the focus 1.246 + document.commandDispatcher.focusedElement.localName == "button") // except from the other buttons 1.247 + button.focus(); 1.248 + 1.249 + } else { 1.250 + this.updateDeck.selectedPanel = panel; 1.251 + } 1.252 + }, 1.253 + 1.254 + /** 1.255 + * Check for updates 1.256 + */ 1.257 + checkForUpdates: function() { 1.258 + this.selectPanel("checkingForUpdates"); 1.259 + this.isChecking = true; 1.260 + this.checker.checkForUpdates(this.updateCheckListener, true); 1.261 + // after checking, onCheckComplete() is called 1.262 + }, 1.263 + 1.264 + /** 1.265 + * Check for addon compat, or start the download right away 1.266 + */ 1.267 + doUpdate: function() { 1.268 + // skip the compatibility check if the update doesn't provide appVersion, 1.269 + // or the appVersion is unchanged, e.g. nightly update 1.270 +#ifdef TOR_BROWSER_UPDATE 1.271 + let pkgVersion = TOR_BROWSER_VERSION; 1.272 +#else 1.273 + let pkgVersion = Services.appinfo.version; 1.274 +#endif 1.275 + if (!this.update.appVersion || 1.276 + Services.vc.compare(gAppUpdater.update.appVersion, pkgVersion) == 0) { 1.277 + this.startDownload(); 1.278 + } else { 1.279 + this.checkAddonCompatibility(); 1.280 + } 1.281 + }, 1.282 + 1.283 + /** 1.284 + * Handles oncommand for the "Restart to Update" button 1.285 + * which is presented after the download has been downloaded. 1.286 + */ 1.287 + buttonRestartAfterDownload: function() { 1.288 + if (!this.isPending && !this.isApplied) 1.289 + return; 1.290 + 1.291 + // Notify all windows that an application quit has been requested. 1.292 + let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]. 1.293 + createInstance(Components.interfaces.nsISupportsPRBool); 1.294 + Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); 1.295 + 1.296 + // Something aborted the quit process. 1.297 + if (cancelQuit.data) 1.298 + return; 1.299 + 1.300 + let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]. 1.301 + getService(Components.interfaces.nsIAppStartup); 1.302 + 1.303 + // If already in safe mode restart in safe mode (bug 327119) 1.304 + if (Services.appinfo.inSafeMode) { 1.305 + appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit); 1.306 + return; 1.307 + } 1.308 + 1.309 + appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit | 1.310 + Components.interfaces.nsIAppStartup.eRestart); 1.311 + }, 1.312 + 1.313 + /** 1.314 + * Handles oncommand for the "Apply Update…" button 1.315 + * which is presented if we need to show the billboard or license. 1.316 + */ 1.317 + buttonApplyBillboard: function() { 1.318 + const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul"; 1.319 + var ary = null; 1.320 + ary = Components.classes["@mozilla.org/supports-array;1"]. 1.321 + createInstance(Components.interfaces.nsISupportsArray); 1.322 + ary.AppendElement(this.update); 1.323 + var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no"; 1.324 + Services.ww.openWindow(null, URI_UPDATE_PROMPT_DIALOG, "", openFeatures, ary); 1.325 + window.close(); // close the "About" window; updates.xul takes over. 1.326 + }, 1.327 + 1.328 + /** 1.329 + * Implements nsIUpdateCheckListener. The methods implemented by 1.330 + * nsIUpdateCheckListener are in a different scope from nsIIncrementalDownload 1.331 + * to make it clear which are used by each interface. 1.332 + */ 1.333 + updateCheckListener: { 1.334 + /** 1.335 + * See nsIUpdateService.idl 1.336 + */ 1.337 + onCheckComplete: function(aRequest, aUpdates, aUpdateCount) { 1.338 + gAppUpdater.isChecking = false; 1.339 + gAppUpdater.update = gAppUpdater.aus. 1.340 + selectUpdate(aUpdates, aUpdates.length); 1.341 + if (!gAppUpdater.update) { 1.342 + gAppUpdater.selectPanel("noUpdatesFound"); 1.343 + return; 1.344 + } 1.345 + 1.346 + if (gAppUpdater.update.unsupported) { 1.347 + if (gAppUpdater.update.detailsURL) { 1.348 + let unsupportedLink = document.getElementById("unsupportedLink"); 1.349 + unsupportedLink.href = gAppUpdater.update.detailsURL; 1.350 + } 1.351 + gAppUpdater.selectPanel("unsupportedSystem"); 1.352 + return; 1.353 + } 1.354 + 1.355 + if (!gAppUpdater.aus.canApplyUpdates) { 1.356 + gAppUpdater.selectPanel("manualUpdate"); 1.357 + return; 1.358 + } 1.359 + 1.360 + // Firefox no longer displays a license for updates and the licenseURL 1.361 + // check is just in case a distibution does. 1.362 + if (gAppUpdater.update.billboardURL || gAppUpdater.update.licenseURL) { 1.363 + gAppUpdater.selectPanel("applyBillboard"); 1.364 + return; 1.365 + } 1.366 + 1.367 + if (gAppUpdater.updateAuto) // automatically download and install 1.368 + gAppUpdater.doUpdate(); 1.369 + else // ask 1.370 + gAppUpdater.selectPanel("downloadAndInstall"); 1.371 + }, 1.372 + 1.373 + /** 1.374 + * See nsIUpdateService.idl 1.375 + */ 1.376 + onError: function(aRequest, aUpdate) { 1.377 + // Errors in the update check are treated as no updates found. If the 1.378 + // update check fails repeatedly without a success the user will be 1.379 + // notified with the normal app update user interface so this is safe. 1.380 + gAppUpdater.isChecking = false; 1.381 + gAppUpdater.selectPanel("noUpdatesFound"); 1.382 + }, 1.383 + 1.384 + /** 1.385 + * See nsISupports.idl 1.386 + */ 1.387 + QueryInterface: function(aIID) { 1.388 + if (!aIID.equals(Components.interfaces.nsIUpdateCheckListener) && 1.389 + !aIID.equals(Components.interfaces.nsISupports)) 1.390 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.391 + return this; 1.392 + } 1.393 + }, 1.394 + 1.395 + /** 1.396 + * Checks the compatibility of add-ons for the application update. 1.397 + */ 1.398 + checkAddonCompatibility: function() { 1.399 + try { 1.400 + var hotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); 1.401 + } 1.402 + catch (e) { } 1.403 + 1.404 + var self = this; 1.405 + AddonManager.getAllAddons(function(aAddons) { 1.406 + self.addons = []; 1.407 + self.addonsCheckedCount = 0; 1.408 + aAddons.forEach(function(aAddon) { 1.409 + // Protect against code that overrides the add-ons manager and doesn't 1.410 + // implement the isCompatibleWith or the findUpdates method. 1.411 + if (!("isCompatibleWith" in aAddon) || !("findUpdates" in aAddon)) { 1.412 + let errMsg = "Add-on doesn't implement either the isCompatibleWith " + 1.413 + "or the findUpdates method!"; 1.414 + if (aAddon.id) 1.415 + errMsg += " Add-on ID: " + aAddon.id; 1.416 + Components.utils.reportError(errMsg); 1.417 + return; 1.418 + } 1.419 + 1.420 + // If an add-on isn't appDisabled and isn't userDisabled then it is 1.421 + // either active now or the user expects it to be active after the 1.422 + // restart. If that is the case and the add-on is not installed by the 1.423 + // application and is not compatible with the new application version 1.424 + // then the user should be warned that the add-on will become 1.425 + // incompatible. If an addon's type equals plugin it is skipped since 1.426 + // checking plugins compatibility information isn't supported and 1.427 + // getting the scope property of a plugin breaks in some environments 1.428 + // (see bug 566787). The hotfix add-on is also ignored as it shouldn't 1.429 + // block the user from upgrading. 1.430 + try { 1.431 +#ifdef TOR_BROWSER_UPDATE 1.432 + let compatVersion = self.update.platformVersion; 1.433 +#else 1.434 + let compatVersion = self.update.appVersion; 1.435 +#endif 1.436 + if (aAddon.type != "plugin" && aAddon.id != hotfixID && 1.437 + !aAddon.appDisabled && !aAddon.userDisabled && 1.438 + aAddon.scope != AddonManager.SCOPE_APPLICATION && 1.439 + aAddon.isCompatible && 1.440 + !aAddon.isCompatibleWith(compatVersion, 1.441 + self.update.platformVersion)) 1.442 + self.addons.push(aAddon); 1.443 + } 1.444 + catch (e) { 1.445 + Components.utils.reportError(e); 1.446 + } 1.447 + }); 1.448 + self.addonsTotalCount = self.addons.length; 1.449 + if (self.addonsTotalCount == 0) { 1.450 + self.startDownload(); 1.451 + return; 1.452 + } 1.453 + 1.454 + self.checkAddonsForUpdates(); 1.455 + }); 1.456 + }, 1.457 + 1.458 + /** 1.459 + * Checks if there are updates for add-ons that are incompatible with the 1.460 + * application update. 1.461 + */ 1.462 + checkAddonsForUpdates: function() { 1.463 + this.addons.forEach(function(aAddon) { 1.464 +#ifdef TOR_BROWSER_UPDATE 1.465 + let compatVersion = this.update.platformVersion; 1.466 +#else 1.467 + let compatVersion = this.update.appVersion; 1.468 +#endif 1.469 + aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, 1.470 + compatVersion, 1.471 + this.update.platformVersion); 1.472 + }, this); 1.473 + }, 1.474 + 1.475 + /** 1.476 + * See XPIProvider.jsm 1.477 + */ 1.478 + onCompatibilityUpdateAvailable: function(aAddon) { 1.479 + for (var i = 0; i < this.addons.length; ++i) { 1.480 + if (this.addons[i].id == aAddon.id) { 1.481 + this.addons.splice(i, 1); 1.482 + break; 1.483 + } 1.484 + } 1.485 + }, 1.486 + 1.487 + /** 1.488 + * See XPIProvider.jsm 1.489 + */ 1.490 + onUpdateAvailable: function(aAddon, aInstall) { 1.491 +#ifdef TOR_BROWSER_UPDATE 1.492 + let compatVersion = this.update.platformVersion; 1.493 +#else 1.494 + let compatVersion = this.update.appVersion; 1.495 +#endif 1.496 + if (!Services.blocklist.isAddonBlocklisted(aAddon, 1.497 + compatVersion, 1.498 + this.update.platformVersion)) { 1.499 + // Compatibility or new version updates mean the same thing here. 1.500 + this.onCompatibilityUpdateAvailable(aAddon); 1.501 + } 1.502 + }, 1.503 + 1.504 + /** 1.505 + * See XPIProvider.jsm 1.506 + */ 1.507 + onUpdateFinished: function(aAddon) { 1.508 + ++this.addonsCheckedCount; 1.509 + 1.510 + if (this.addonsCheckedCount < this.addonsTotalCount) 1.511 + return; 1.512 + 1.513 + if (this.addons.length == 0) { 1.514 + // Compatibility updates or new version updates were found for all add-ons 1.515 + this.startDownload(); 1.516 + return; 1.517 + } 1.518 + 1.519 + this.selectPanel("apply"); 1.520 + }, 1.521 + 1.522 + /** 1.523 + * Starts the download of an update mar. 1.524 + */ 1.525 + startDownload: function() { 1.526 + if (!this.update) 1.527 + this.update = this.um.activeUpdate; 1.528 + this.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag); 1.529 + this.update.setProperty("foregroundDownload", "true"); 1.530 + 1.531 + this.aus.pauseDownload(); 1.532 + let state = this.aus.downloadUpdate(this.update, false); 1.533 + if (state == "failed") { 1.534 + this.selectPanel("downloadFailed"); 1.535 + return; 1.536 + } 1.537 + 1.538 + this.setupDownloadingUI(); 1.539 + }, 1.540 + 1.541 + /** 1.542 + * Switches to the UI responsible for tracking the download. 1.543 + */ 1.544 + setupDownloadingUI: function() { 1.545 + this.downloadStatus = document.getElementById("downloadStatus"); 1.546 + this.downloadStatus.value = 1.547 + DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size); 1.548 + this.selectPanel("downloading"); 1.549 + this.aus.addDownloadListener(this); 1.550 + }, 1.551 + 1.552 + removeDownloadListener: function() { 1.553 + if (this.aus) { 1.554 + this.aus.removeDownloadListener(this); 1.555 + } 1.556 + }, 1.557 + 1.558 + /** 1.559 + * See nsIRequestObserver.idl 1.560 + */ 1.561 + onStartRequest: function(aRequest, aContext) { 1.562 + }, 1.563 + 1.564 + /** 1.565 + * See nsIRequestObserver.idl 1.566 + */ 1.567 + onStopRequest: function(aRequest, aContext, aStatusCode) { 1.568 + switch (aStatusCode) { 1.569 + case Components.results.NS_ERROR_UNEXPECTED: 1.570 + if (this.update.selectedPatch.state == "download-failed" && 1.571 + (this.update.isCompleteUpdate || this.update.patchCount != 2)) { 1.572 + // Verification error of complete patch, informational text is held in 1.573 + // the update object. 1.574 + this.removeDownloadListener(); 1.575 + this.selectPanel("downloadFailed"); 1.576 + break; 1.577 + } 1.578 + // Verification failed for a partial patch, complete patch is now 1.579 + // downloading so return early and do NOT remove the download listener! 1.580 + break; 1.581 + case Components.results.NS_BINDING_ABORTED: 1.582 + // Do not remove UI listener since the user may resume downloading again. 1.583 + break; 1.584 + case Components.results.NS_OK: 1.585 + this.removeDownloadListener(); 1.586 + if (this.backgroundUpdateEnabled) { 1.587 + this.selectPanel("applying"); 1.588 + let update = this.um.activeUpdate; 1.589 + let self = this; 1.590 + Services.obs.addObserver(function (aSubject, aTopic, aData) { 1.591 + // Update the UI when the background updater is finished 1.592 + let status = aData; 1.593 + if (status == "applied" || status == "applied-service" || 1.594 + status == "pending" || status == "pending-service") { 1.595 + // If the update is successfully applied, or if the updater has 1.596 + // fallen back to non-staged updates, show the "Restart to Update" 1.597 + // button. 1.598 + self.selectPanel("apply"); 1.599 + } else if (status == "failed") { 1.600 + // Background update has failed, let's show the UI responsible for 1.601 + // prompting the user to update manually. 1.602 + self.selectPanel("downloadFailed"); 1.603 + } else if (status == "downloading") { 1.604 + // We've fallen back to downloading the full update because the 1.605 + // partial update failed to get staged in the background. 1.606 + // Therefore we need to keep our observer. 1.607 + self.setupDownloadingUI(); 1.608 + return; 1.609 + } 1.610 + Services.obs.removeObserver(arguments.callee, "update-staged"); 1.611 + }, "update-staged", false); 1.612 + } else { 1.613 + this.selectPanel("apply"); 1.614 + } 1.615 + break; 1.616 + default: 1.617 + this.removeDownloadListener(); 1.618 + this.selectPanel("downloadFailed"); 1.619 + break; 1.620 + } 1.621 + }, 1.622 + 1.623 + /** 1.624 + * See nsIProgressEventSink.idl 1.625 + */ 1.626 + onStatus: function(aRequest, aContext, aStatus, aStatusArg) { 1.627 + }, 1.628 + 1.629 + /** 1.630 + * See nsIProgressEventSink.idl 1.631 + */ 1.632 + onProgress: function(aRequest, aContext, aProgress, aProgressMax) { 1.633 + this.downloadStatus.value = 1.634 + DownloadUtils.getTransferTotal(aProgress, aProgressMax); 1.635 + }, 1.636 + 1.637 + /** 1.638 + * See nsISupports.idl 1.639 + */ 1.640 + QueryInterface: function(aIID) { 1.641 + if (!aIID.equals(Components.interfaces.nsIProgressEventSink) && 1.642 + !aIID.equals(Components.interfaces.nsIRequestObserver) && 1.643 + !aIID.equals(Components.interfaces.nsISupports)) 1.644 + throw Components.results.NS_ERROR_NO_INTERFACE; 1.645 + return this; 1.646 + } 1.647 +}; 1.648 +#endif