browser/base/content/aboutDialog.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4
michael@0 5 // Services = object with smart getters for common XPCOM services
michael@0 6 Components.utils.import("resource://gre/modules/Services.jsm");
michael@0 7
michael@0 8 const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
michael@0 9
michael@0 10 #ifdef TOR_BROWSER_VERSION
michael@0 11 # Add double-quotes back on (stripped by JarMaker.py).
michael@0 12 #expand const TOR_BROWSER_VERSION = "__TOR_BROWSER_VERSION__";
michael@0 13 #endif
michael@0 14
michael@0 15 function init(aEvent)
michael@0 16 {
michael@0 17 if (aEvent.target != document)
michael@0 18 return;
michael@0 19
michael@0 20 try {
michael@0 21 var distroId = Services.prefs.getCharPref("distribution.id");
michael@0 22 if (distroId) {
michael@0 23 var distroVersion = Services.prefs.getCharPref("distribution.version");
michael@0 24
michael@0 25 var distroIdField = document.getElementById("distributionId");
michael@0 26 distroIdField.value = distroId + " - " + distroVersion;
michael@0 27 distroIdField.style.display = "block";
michael@0 28
michael@0 29 try {
michael@0 30 // This is in its own try catch due to bug 895473 and bug 900925.
michael@0 31 var distroAbout = Services.prefs.getComplexValue("distribution.about",
michael@0 32 Components.interfaces.nsISupportsString);
michael@0 33 var distroField = document.getElementById("distribution");
michael@0 34 distroField.value = distroAbout;
michael@0 35 distroField.style.display = "block";
michael@0 36 }
michael@0 37 catch (ex) {
michael@0 38 // Pref is unset
michael@0 39 Components.utils.reportError(ex);
michael@0 40 }
michael@0 41 }
michael@0 42 }
michael@0 43 catch (e) {
michael@0 44 // Pref is unset
michael@0 45 }
michael@0 46
michael@0 47 // Include the build ID and display warning if this is an "a#" (nightly or aurora) build
michael@0 48 let version = Services.appinfo.version;
michael@0 49 if (/a\d+$/.test(version)) {
michael@0 50 document.getElementById("experimental").hidden = false;
michael@0 51 document.getElementById("communityDesc").hidden = true;
michael@0 52 }
michael@0 53
michael@0 54 #ifdef TOR_BROWSER_VERSION
michael@0 55 let versionElem = document.getElementById("version");
michael@0 56 if (versionElem)
michael@0 57 versionElem.textContent += " (Tor Browser " + TOR_BROWSER_VERSION + ")";
michael@0 58 #endif
michael@0 59
michael@0 60 #ifdef MOZ_UPDATER
michael@0 61 gAppUpdater = new appUpdater();
michael@0 62
michael@0 63 #if MOZ_UPDATE_CHANNEL != release
michael@0 64 let defaults = Services.prefs.getDefaultBranch("");
michael@0 65 let channelLabel = document.getElementById("currentChannel");
michael@0 66 channelLabel.value = defaults.getCharPref("app.update.channel");
michael@0 67 #endif
michael@0 68 #endif
michael@0 69
michael@0 70 #ifdef XP_MACOSX
michael@0 71 // it may not be sized at this point, and we need its width to calculate its position
michael@0 72 window.sizeToContent();
michael@0 73 window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5);
michael@0 74 #endif
michael@0 75 }
michael@0 76
michael@0 77 #ifdef MOZ_UPDATER
michael@0 78 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 79 Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
michael@0 80 Components.utils.import("resource://gre/modules/AddonManager.jsm");
michael@0 81
michael@0 82 var gAppUpdater;
michael@0 83
michael@0 84 function onUnload(aEvent) {
michael@0 85 if (gAppUpdater.isChecking)
michael@0 86 gAppUpdater.checker.stopChecking(Components.interfaces.nsIUpdateChecker.CURRENT_CHECK);
michael@0 87 // Safe to call even when there isn't a download in progress.
michael@0 88 gAppUpdater.removeDownloadListener();
michael@0 89 gAppUpdater = null;
michael@0 90 }
michael@0 91
michael@0 92
michael@0 93 function appUpdater()
michael@0 94 {
michael@0 95 this.updateDeck = document.getElementById("updateDeck");
michael@0 96
michael@0 97 // Hide the update deck when there is already an update window open to avoid
michael@0 98 // syncing issues between them.
michael@0 99 if (Services.wm.getMostRecentWindow("Update:Wizard")) {
michael@0 100 this.updateDeck.hidden = true;
michael@0 101 return;
michael@0 102 }
michael@0 103
michael@0 104 XPCOMUtils.defineLazyServiceGetter(this, "aus",
michael@0 105 "@mozilla.org/updates/update-service;1",
michael@0 106 "nsIApplicationUpdateService");
michael@0 107 XPCOMUtils.defineLazyServiceGetter(this, "checker",
michael@0 108 "@mozilla.org/updates/update-checker;1",
michael@0 109 "nsIUpdateChecker");
michael@0 110 XPCOMUtils.defineLazyServiceGetter(this, "um",
michael@0 111 "@mozilla.org/updates/update-manager;1",
michael@0 112 "nsIUpdateManager");
michael@0 113
michael@0 114 this.bundle = Services.strings.
michael@0 115 createBundle("chrome://browser/locale/browser.properties");
michael@0 116
michael@0 117 let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual");
michael@0 118 let manualLink = document.getElementById("manualLink");
michael@0 119 manualLink.value = manualURL;
michael@0 120 manualLink.href = manualURL;
michael@0 121 document.getElementById("failedLink").href = manualURL;
michael@0 122
michael@0 123 if (this.updateDisabledAndLocked) {
michael@0 124 this.selectPanel("adminDisabled");
michael@0 125 return;
michael@0 126 }
michael@0 127
michael@0 128 if (this.isPending || this.isApplied) {
michael@0 129 this.selectPanel("apply");
michael@0 130 return;
michael@0 131 }
michael@0 132
michael@0 133 if (this.aus.isOtherInstanceHandlingUpdates) {
michael@0 134 this.selectPanel("otherInstanceHandlingUpdates");
michael@0 135 return;
michael@0 136 }
michael@0 137
michael@0 138 if (this.isDownloading) {
michael@0 139 this.startDownload();
michael@0 140 // selectPanel("downloading") is called from setupDownloadingUI().
michael@0 141 return;
michael@0 142 }
michael@0 143
michael@0 144 // Honor the "Never check for updates" option by not only disabling background
michael@0 145 // update checks, but also in the About dialog, by presenting a
michael@0 146 // "Check for updates" button.
michael@0 147 // If updates are found, the user is then asked if he wants to "Update to <version>".
michael@0 148 if (!this.updateEnabled) {
michael@0 149 this.selectPanel("checkForUpdates");
michael@0 150 return;
michael@0 151 }
michael@0 152
michael@0 153 // That leaves the options
michael@0 154 // "Check for updates, but let me choose whether to install them", and
michael@0 155 // "Automatically install updates".
michael@0 156 // In both cases, we check for updates without asking.
michael@0 157 // In the "let me choose" case, we ask before downloading though, in onCheckComplete.
michael@0 158 this.checkForUpdates();
michael@0 159 }
michael@0 160
michael@0 161 appUpdater.prototype =
michael@0 162 {
michael@0 163 // true when there is an update check in progress.
michael@0 164 isChecking: false,
michael@0 165
michael@0 166 // true when there is an update already staged / ready to be applied.
michael@0 167 get isPending() {
michael@0 168 if (this.update) {
michael@0 169 return this.update.state == "pending" ||
michael@0 170 this.update.state == "pending-service";
michael@0 171 }
michael@0 172 return this.um.activeUpdate &&
michael@0 173 (this.um.activeUpdate.state == "pending" ||
michael@0 174 this.um.activeUpdate.state == "pending-service");
michael@0 175 },
michael@0 176
michael@0 177 // true when there is an update already installed in the background.
michael@0 178 get isApplied() {
michael@0 179 if (this.update)
michael@0 180 return this.update.state == "applied" ||
michael@0 181 this.update.state == "applied-service";
michael@0 182 return this.um.activeUpdate &&
michael@0 183 (this.um.activeUpdate.state == "applied" ||
michael@0 184 this.um.activeUpdate.state == "applied-service");
michael@0 185 },
michael@0 186
michael@0 187 // true when there is an update download in progress.
michael@0 188 get isDownloading() {
michael@0 189 if (this.update)
michael@0 190 return this.update.state == "downloading";
michael@0 191 return this.um.activeUpdate &&
michael@0 192 this.um.activeUpdate.state == "downloading";
michael@0 193 },
michael@0 194
michael@0 195 // true when updating is disabled by an administrator.
michael@0 196 get updateDisabledAndLocked() {
michael@0 197 return !this.updateEnabled &&
michael@0 198 Services.prefs.prefIsLocked("app.update.enabled");
michael@0 199 },
michael@0 200
michael@0 201 // true when updating is enabled.
michael@0 202 get updateEnabled() {
michael@0 203 try {
michael@0 204 return Services.prefs.getBoolPref("app.update.enabled");
michael@0 205 }
michael@0 206 catch (e) { }
michael@0 207 return true; // Firefox default is true
michael@0 208 },
michael@0 209
michael@0 210 // true when updating in background is enabled.
michael@0 211 get backgroundUpdateEnabled() {
michael@0 212 return this.updateEnabled &&
michael@0 213 gAppUpdater.aus.canStageUpdates;
michael@0 214 },
michael@0 215
michael@0 216 // true when updating is automatic.
michael@0 217 get updateAuto() {
michael@0 218 try {
michael@0 219 return Services.prefs.getBoolPref("app.update.auto");
michael@0 220 }
michael@0 221 catch (e) { }
michael@0 222 return true; // Firefox default is true
michael@0 223 },
michael@0 224
michael@0 225 /**
michael@0 226 * Sets the panel of the updateDeck.
michael@0 227 *
michael@0 228 * @param aChildID
michael@0 229 * The id of the deck's child to select, e.g. "apply".
michael@0 230 */
michael@0 231 selectPanel: function(aChildID) {
michael@0 232 let panel = document.getElementById(aChildID);
michael@0 233
michael@0 234 let button = panel.querySelector("button");
michael@0 235 if (button) {
michael@0 236 if (aChildID == "downloadAndInstall") {
michael@0 237 let updateVersion = gAppUpdater.update.displayVersion;
michael@0 238 button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1);
michael@0 239 button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
michael@0 240 }
michael@0 241 this.updateDeck.selectedPanel = panel;
michael@0 242 if (!document.commandDispatcher.focusedElement || // don't steal the focus
michael@0 243 document.commandDispatcher.focusedElement.localName == "button") // except from the other buttons
michael@0 244 button.focus();
michael@0 245
michael@0 246 } else {
michael@0 247 this.updateDeck.selectedPanel = panel;
michael@0 248 }
michael@0 249 },
michael@0 250
michael@0 251 /**
michael@0 252 * Check for updates
michael@0 253 */
michael@0 254 checkForUpdates: function() {
michael@0 255 this.selectPanel("checkingForUpdates");
michael@0 256 this.isChecking = true;
michael@0 257 this.checker.checkForUpdates(this.updateCheckListener, true);
michael@0 258 // after checking, onCheckComplete() is called
michael@0 259 },
michael@0 260
michael@0 261 /**
michael@0 262 * Check for addon compat, or start the download right away
michael@0 263 */
michael@0 264 doUpdate: function() {
michael@0 265 // skip the compatibility check if the update doesn't provide appVersion,
michael@0 266 // or the appVersion is unchanged, e.g. nightly update
michael@0 267 #ifdef TOR_BROWSER_UPDATE
michael@0 268 let pkgVersion = TOR_BROWSER_VERSION;
michael@0 269 #else
michael@0 270 let pkgVersion = Services.appinfo.version;
michael@0 271 #endif
michael@0 272 if (!this.update.appVersion ||
michael@0 273 Services.vc.compare(gAppUpdater.update.appVersion, pkgVersion) == 0) {
michael@0 274 this.startDownload();
michael@0 275 } else {
michael@0 276 this.checkAddonCompatibility();
michael@0 277 }
michael@0 278 },
michael@0 279
michael@0 280 /**
michael@0 281 * Handles oncommand for the "Restart to Update" button
michael@0 282 * which is presented after the download has been downloaded.
michael@0 283 */
michael@0 284 buttonRestartAfterDownload: function() {
michael@0 285 if (!this.isPending && !this.isApplied)
michael@0 286 return;
michael@0 287
michael@0 288 // Notify all windows that an application quit has been requested.
michael@0 289 let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
michael@0 290 createInstance(Components.interfaces.nsISupportsPRBool);
michael@0 291 Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
michael@0 292
michael@0 293 // Something aborted the quit process.
michael@0 294 if (cancelQuit.data)
michael@0 295 return;
michael@0 296
michael@0 297 let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
michael@0 298 getService(Components.interfaces.nsIAppStartup);
michael@0 299
michael@0 300 // If already in safe mode restart in safe mode (bug 327119)
michael@0 301 if (Services.appinfo.inSafeMode) {
michael@0 302 appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
michael@0 303 return;
michael@0 304 }
michael@0 305
michael@0 306 appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
michael@0 307 Components.interfaces.nsIAppStartup.eRestart);
michael@0 308 },
michael@0 309
michael@0 310 /**
michael@0 311 * Handles oncommand for the "Apply Update…" button
michael@0 312 * which is presented if we need to show the billboard or license.
michael@0 313 */
michael@0 314 buttonApplyBillboard: function() {
michael@0 315 const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
michael@0 316 var ary = null;
michael@0 317 ary = Components.classes["@mozilla.org/supports-array;1"].
michael@0 318 createInstance(Components.interfaces.nsISupportsArray);
michael@0 319 ary.AppendElement(this.update);
michael@0 320 var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no";
michael@0 321 Services.ww.openWindow(null, URI_UPDATE_PROMPT_DIALOG, "", openFeatures, ary);
michael@0 322 window.close(); // close the "About" window; updates.xul takes over.
michael@0 323 },
michael@0 324
michael@0 325 /**
michael@0 326 * Implements nsIUpdateCheckListener. The methods implemented by
michael@0 327 * nsIUpdateCheckListener are in a different scope from nsIIncrementalDownload
michael@0 328 * to make it clear which are used by each interface.
michael@0 329 */
michael@0 330 updateCheckListener: {
michael@0 331 /**
michael@0 332 * See nsIUpdateService.idl
michael@0 333 */
michael@0 334 onCheckComplete: function(aRequest, aUpdates, aUpdateCount) {
michael@0 335 gAppUpdater.isChecking = false;
michael@0 336 gAppUpdater.update = gAppUpdater.aus.
michael@0 337 selectUpdate(aUpdates, aUpdates.length);
michael@0 338 if (!gAppUpdater.update) {
michael@0 339 gAppUpdater.selectPanel("noUpdatesFound");
michael@0 340 return;
michael@0 341 }
michael@0 342
michael@0 343 if (gAppUpdater.update.unsupported) {
michael@0 344 if (gAppUpdater.update.detailsURL) {
michael@0 345 let unsupportedLink = document.getElementById("unsupportedLink");
michael@0 346 unsupportedLink.href = gAppUpdater.update.detailsURL;
michael@0 347 }
michael@0 348 gAppUpdater.selectPanel("unsupportedSystem");
michael@0 349 return;
michael@0 350 }
michael@0 351
michael@0 352 if (!gAppUpdater.aus.canApplyUpdates) {
michael@0 353 gAppUpdater.selectPanel("manualUpdate");
michael@0 354 return;
michael@0 355 }
michael@0 356
michael@0 357 // Firefox no longer displays a license for updates and the licenseURL
michael@0 358 // check is just in case a distibution does.
michael@0 359 if (gAppUpdater.update.billboardURL || gAppUpdater.update.licenseURL) {
michael@0 360 gAppUpdater.selectPanel("applyBillboard");
michael@0 361 return;
michael@0 362 }
michael@0 363
michael@0 364 if (gAppUpdater.updateAuto) // automatically download and install
michael@0 365 gAppUpdater.doUpdate();
michael@0 366 else // ask
michael@0 367 gAppUpdater.selectPanel("downloadAndInstall");
michael@0 368 },
michael@0 369
michael@0 370 /**
michael@0 371 * See nsIUpdateService.idl
michael@0 372 */
michael@0 373 onError: function(aRequest, aUpdate) {
michael@0 374 // Errors in the update check are treated as no updates found. If the
michael@0 375 // update check fails repeatedly without a success the user will be
michael@0 376 // notified with the normal app update user interface so this is safe.
michael@0 377 gAppUpdater.isChecking = false;
michael@0 378 gAppUpdater.selectPanel("noUpdatesFound");
michael@0 379 },
michael@0 380
michael@0 381 /**
michael@0 382 * See nsISupports.idl
michael@0 383 */
michael@0 384 QueryInterface: function(aIID) {
michael@0 385 if (!aIID.equals(Components.interfaces.nsIUpdateCheckListener) &&
michael@0 386 !aIID.equals(Components.interfaces.nsISupports))
michael@0 387 throw Components.results.NS_ERROR_NO_INTERFACE;
michael@0 388 return this;
michael@0 389 }
michael@0 390 },
michael@0 391
michael@0 392 /**
michael@0 393 * Checks the compatibility of add-ons for the application update.
michael@0 394 */
michael@0 395 checkAddonCompatibility: function() {
michael@0 396 try {
michael@0 397 var hotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID);
michael@0 398 }
michael@0 399 catch (e) { }
michael@0 400
michael@0 401 var self = this;
michael@0 402 AddonManager.getAllAddons(function(aAddons) {
michael@0 403 self.addons = [];
michael@0 404 self.addonsCheckedCount = 0;
michael@0 405 aAddons.forEach(function(aAddon) {
michael@0 406 // Protect against code that overrides the add-ons manager and doesn't
michael@0 407 // implement the isCompatibleWith or the findUpdates method.
michael@0 408 if (!("isCompatibleWith" in aAddon) || !("findUpdates" in aAddon)) {
michael@0 409 let errMsg = "Add-on doesn't implement either the isCompatibleWith " +
michael@0 410 "or the findUpdates method!";
michael@0 411 if (aAddon.id)
michael@0 412 errMsg += " Add-on ID: " + aAddon.id;
michael@0 413 Components.utils.reportError(errMsg);
michael@0 414 return;
michael@0 415 }
michael@0 416
michael@0 417 // If an add-on isn't appDisabled and isn't userDisabled then it is
michael@0 418 // either active now or the user expects it to be active after the
michael@0 419 // restart. If that is the case and the add-on is not installed by the
michael@0 420 // application and is not compatible with the new application version
michael@0 421 // then the user should be warned that the add-on will become
michael@0 422 // incompatible. If an addon's type equals plugin it is skipped since
michael@0 423 // checking plugins compatibility information isn't supported and
michael@0 424 // getting the scope property of a plugin breaks in some environments
michael@0 425 // (see bug 566787). The hotfix add-on is also ignored as it shouldn't
michael@0 426 // block the user from upgrading.
michael@0 427 try {
michael@0 428 #ifdef TOR_BROWSER_UPDATE
michael@0 429 let compatVersion = self.update.platformVersion;
michael@0 430 #else
michael@0 431 let compatVersion = self.update.appVersion;
michael@0 432 #endif
michael@0 433 if (aAddon.type != "plugin" && aAddon.id != hotfixID &&
michael@0 434 !aAddon.appDisabled && !aAddon.userDisabled &&
michael@0 435 aAddon.scope != AddonManager.SCOPE_APPLICATION &&
michael@0 436 aAddon.isCompatible &&
michael@0 437 !aAddon.isCompatibleWith(compatVersion,
michael@0 438 self.update.platformVersion))
michael@0 439 self.addons.push(aAddon);
michael@0 440 }
michael@0 441 catch (e) {
michael@0 442 Components.utils.reportError(e);
michael@0 443 }
michael@0 444 });
michael@0 445 self.addonsTotalCount = self.addons.length;
michael@0 446 if (self.addonsTotalCount == 0) {
michael@0 447 self.startDownload();
michael@0 448 return;
michael@0 449 }
michael@0 450
michael@0 451 self.checkAddonsForUpdates();
michael@0 452 });
michael@0 453 },
michael@0 454
michael@0 455 /**
michael@0 456 * Checks if there are updates for add-ons that are incompatible with the
michael@0 457 * application update.
michael@0 458 */
michael@0 459 checkAddonsForUpdates: function() {
michael@0 460 this.addons.forEach(function(aAddon) {
michael@0 461 #ifdef TOR_BROWSER_UPDATE
michael@0 462 let compatVersion = this.update.platformVersion;
michael@0 463 #else
michael@0 464 let compatVersion = this.update.appVersion;
michael@0 465 #endif
michael@0 466 aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED,
michael@0 467 compatVersion,
michael@0 468 this.update.platformVersion);
michael@0 469 }, this);
michael@0 470 },
michael@0 471
michael@0 472 /**
michael@0 473 * See XPIProvider.jsm
michael@0 474 */
michael@0 475 onCompatibilityUpdateAvailable: function(aAddon) {
michael@0 476 for (var i = 0; i < this.addons.length; ++i) {
michael@0 477 if (this.addons[i].id == aAddon.id) {
michael@0 478 this.addons.splice(i, 1);
michael@0 479 break;
michael@0 480 }
michael@0 481 }
michael@0 482 },
michael@0 483
michael@0 484 /**
michael@0 485 * See XPIProvider.jsm
michael@0 486 */
michael@0 487 onUpdateAvailable: function(aAddon, aInstall) {
michael@0 488 #ifdef TOR_BROWSER_UPDATE
michael@0 489 let compatVersion = this.update.platformVersion;
michael@0 490 #else
michael@0 491 let compatVersion = this.update.appVersion;
michael@0 492 #endif
michael@0 493 if (!Services.blocklist.isAddonBlocklisted(aAddon,
michael@0 494 compatVersion,
michael@0 495 this.update.platformVersion)) {
michael@0 496 // Compatibility or new version updates mean the same thing here.
michael@0 497 this.onCompatibilityUpdateAvailable(aAddon);
michael@0 498 }
michael@0 499 },
michael@0 500
michael@0 501 /**
michael@0 502 * See XPIProvider.jsm
michael@0 503 */
michael@0 504 onUpdateFinished: function(aAddon) {
michael@0 505 ++this.addonsCheckedCount;
michael@0 506
michael@0 507 if (this.addonsCheckedCount < this.addonsTotalCount)
michael@0 508 return;
michael@0 509
michael@0 510 if (this.addons.length == 0) {
michael@0 511 // Compatibility updates or new version updates were found for all add-ons
michael@0 512 this.startDownload();
michael@0 513 return;
michael@0 514 }
michael@0 515
michael@0 516 this.selectPanel("apply");
michael@0 517 },
michael@0 518
michael@0 519 /**
michael@0 520 * Starts the download of an update mar.
michael@0 521 */
michael@0 522 startDownload: function() {
michael@0 523 if (!this.update)
michael@0 524 this.update = this.um.activeUpdate;
michael@0 525 this.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
michael@0 526 this.update.setProperty("foregroundDownload", "true");
michael@0 527
michael@0 528 this.aus.pauseDownload();
michael@0 529 let state = this.aus.downloadUpdate(this.update, false);
michael@0 530 if (state == "failed") {
michael@0 531 this.selectPanel("downloadFailed");
michael@0 532 return;
michael@0 533 }
michael@0 534
michael@0 535 this.setupDownloadingUI();
michael@0 536 },
michael@0 537
michael@0 538 /**
michael@0 539 * Switches to the UI responsible for tracking the download.
michael@0 540 */
michael@0 541 setupDownloadingUI: function() {
michael@0 542 this.downloadStatus = document.getElementById("downloadStatus");
michael@0 543 this.downloadStatus.value =
michael@0 544 DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size);
michael@0 545 this.selectPanel("downloading");
michael@0 546 this.aus.addDownloadListener(this);
michael@0 547 },
michael@0 548
michael@0 549 removeDownloadListener: function() {
michael@0 550 if (this.aus) {
michael@0 551 this.aus.removeDownloadListener(this);
michael@0 552 }
michael@0 553 },
michael@0 554
michael@0 555 /**
michael@0 556 * See nsIRequestObserver.idl
michael@0 557 */
michael@0 558 onStartRequest: function(aRequest, aContext) {
michael@0 559 },
michael@0 560
michael@0 561 /**
michael@0 562 * See nsIRequestObserver.idl
michael@0 563 */
michael@0 564 onStopRequest: function(aRequest, aContext, aStatusCode) {
michael@0 565 switch (aStatusCode) {
michael@0 566 case Components.results.NS_ERROR_UNEXPECTED:
michael@0 567 if (this.update.selectedPatch.state == "download-failed" &&
michael@0 568 (this.update.isCompleteUpdate || this.update.patchCount != 2)) {
michael@0 569 // Verification error of complete patch, informational text is held in
michael@0 570 // the update object.
michael@0 571 this.removeDownloadListener();
michael@0 572 this.selectPanel("downloadFailed");
michael@0 573 break;
michael@0 574 }
michael@0 575 // Verification failed for a partial patch, complete patch is now
michael@0 576 // downloading so return early and do NOT remove the download listener!
michael@0 577 break;
michael@0 578 case Components.results.NS_BINDING_ABORTED:
michael@0 579 // Do not remove UI listener since the user may resume downloading again.
michael@0 580 break;
michael@0 581 case Components.results.NS_OK:
michael@0 582 this.removeDownloadListener();
michael@0 583 if (this.backgroundUpdateEnabled) {
michael@0 584 this.selectPanel("applying");
michael@0 585 let update = this.um.activeUpdate;
michael@0 586 let self = this;
michael@0 587 Services.obs.addObserver(function (aSubject, aTopic, aData) {
michael@0 588 // Update the UI when the background updater is finished
michael@0 589 let status = aData;
michael@0 590 if (status == "applied" || status == "applied-service" ||
michael@0 591 status == "pending" || status == "pending-service") {
michael@0 592 // If the update is successfully applied, or if the updater has
michael@0 593 // fallen back to non-staged updates, show the "Restart to Update"
michael@0 594 // button.
michael@0 595 self.selectPanel("apply");
michael@0 596 } else if (status == "failed") {
michael@0 597 // Background update has failed, let's show the UI responsible for
michael@0 598 // prompting the user to update manually.
michael@0 599 self.selectPanel("downloadFailed");
michael@0 600 } else if (status == "downloading") {
michael@0 601 // We've fallen back to downloading the full update because the
michael@0 602 // partial update failed to get staged in the background.
michael@0 603 // Therefore we need to keep our observer.
michael@0 604 self.setupDownloadingUI();
michael@0 605 return;
michael@0 606 }
michael@0 607 Services.obs.removeObserver(arguments.callee, "update-staged");
michael@0 608 }, "update-staged", false);
michael@0 609 } else {
michael@0 610 this.selectPanel("apply");
michael@0 611 }
michael@0 612 break;
michael@0 613 default:
michael@0 614 this.removeDownloadListener();
michael@0 615 this.selectPanel("downloadFailed");
michael@0 616 break;
michael@0 617 }
michael@0 618 },
michael@0 619
michael@0 620 /**
michael@0 621 * See nsIProgressEventSink.idl
michael@0 622 */
michael@0 623 onStatus: function(aRequest, aContext, aStatus, aStatusArg) {
michael@0 624 },
michael@0 625
michael@0 626 /**
michael@0 627 * See nsIProgressEventSink.idl
michael@0 628 */
michael@0 629 onProgress: function(aRequest, aContext, aProgress, aProgressMax) {
michael@0 630 this.downloadStatus.value =
michael@0 631 DownloadUtils.getTransferTotal(aProgress, aProgressMax);
michael@0 632 },
michael@0 633
michael@0 634 /**
michael@0 635 * See nsISupports.idl
michael@0 636 */
michael@0 637 QueryInterface: function(aIID) {
michael@0 638 if (!aIID.equals(Components.interfaces.nsIProgressEventSink) &&
michael@0 639 !aIID.equals(Components.interfaces.nsIRequestObserver) &&
michael@0 640 !aIID.equals(Components.interfaces.nsISupports))
michael@0 641 throw Components.results.NS_ERROR_NO_INTERFACE;
michael@0 642 return this;
michael@0 643 }
michael@0 644 };
michael@0 645 #endif

mercurial