browser/metro/base/content/flyoutpanels/AboutFlyoutPanel.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial