diff --git a/mozilla/browser/app/profile/firefox.js b/mozilla/browser/app/profile/firefox.js
index 03658f6c70e..2490deaa2fc 100644
--- a/mozilla/browser/app/profile/firefox.js
+++ b/mozilla/browser/app/profile/firefox.js
@@ -75,13 +75,17 @@ pref("extensions.logging.enabled", false);
// Whether or not app updates are enabled
pref("app.update.enabled", false);
+// This preference turns on app.update.mode and allows automatic download and
+// install to take place. We use a separate boolean toggle for this to make
+// the UI easier to construct.
+pref("app.update.auto", true);
+
// Defines how the Application Update Service notifies the user about updates:
//
// AUM Set to: Minor Releases: Major Releases:
// 0 download no prompt download no prompt
// 1 download no prompt download no prompt if no incompatibilities
// 2 download no prompt prompt
-// 3 prompt prompt
//
// See chart in nsUpdateService.js.in for more details
//
diff --git a/mozilla/browser/components/preferences/advanced.js b/mozilla/browser/components/preferences/advanced.js
index 001a85fac77..3b32b367620 100644
--- a/mozilla/browser/components/preferences/advanced.js
+++ b/mozilla/browser/components/preferences/advanced.js
@@ -101,19 +101,17 @@ var gAdvancedPane = {
getService(Components.interfaces.nsIApplicationUpdateService);
var checkNowButton = document.getElementById("checkNowButton");
checkNowButton.disabled = !aus.canUpdate;
-
- this.updateAutoInstallUI();
+
+ this.updateAutoPref();
return undefined;
},
- updateAutoInstallUI: function ()
+ updateAutoPref: function ()
{
- var autoInstallPref = document.getElementById("app.update.autoInstallEnabled");
+ var preference = document.getElementById("app.update.auto");
var updateEnabledPref = document.getElementById("app.update.enabled");
- var ids = ["autoInstallMode", "updateAnd"];
- var disabled = !updateEnabledPref.value || !autoInstallPref.value;
- for (var i = 0; i < ids.length; ++i)
- document.getElementById(ids[i]).disabled = disabled;
+ var autoInstallOptions = document.getElementById("autoInstallOptions");
+ autoInstallOptions.disabled = !preference.value || !updateEnabledPref.value;
return undefined;
},
@@ -149,6 +147,12 @@ var gAdvancedPane = {
prompter.checkForUpdates(window);
},
+ showAutoInstallOptions: function ()
+ {
+ document.documentElement.openSubDialog("chrome://browser/content/preferences/update.xul",
+ "", null);
+ },
+
showUpdates: function ()
{
var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]
diff --git a/mozilla/browser/components/preferences/advanced.xul b/mozilla/browser/components/preferences/advanced.xul
index 989791789ca..1d2864444e1 100644
--- a/mozilla/browser/components/preferences/advanced.xul
+++ b/mozilla/browser/components/preferences/advanced.xul
@@ -58,8 +58,7 @@
-
-
+
@@ -131,34 +130,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Firefox Preferences System.
+#
+# The Initial Developer of the Original Code is Google Inc.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Ben Goodger (Original Author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+
+%brandDTD;
+
+%updateDTD;
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+ &update.intro;
+
+
+
+
+ &ausMode0Name.info;
+
+
+
+ &ausMode1Name.info;
+
+ &ausMode2Name.info;
+
+
+
+
+
+
diff --git a/mozilla/browser/locales/en-US/chrome/browser/preferences/advanced.dtd b/mozilla/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
index 6bae08435fb..d41f113144a 100644
--- a/mozilla/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/mozilla/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -15,15 +15,13 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/mozilla/browser/locales/en-US/chrome/browser/preferences/update.dtd b/mozilla/browser/locales/en-US/chrome/browser/preferences/update.dtd
new file mode 100755
index 00000000000..f32fd515308
--- /dev/null
+++ b/mozilla/browser/locales/en-US/chrome/browser/preferences/update.dtd
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mozilla/browser/locales/jar.mn b/mozilla/browser/locales/jar.mn
index 742fa6c4b1a..ab97ab04b2d 100644
--- a/mozilla/browser/locales/jar.mn
+++ b/mozilla/browser/locales/jar.mn
@@ -44,6 +44,7 @@
locale/browser/preferences/privacy.dtd (%chrome/browser/preferences/privacy.dtd)
locale/browser/preferences/sanitize.dtd (%chrome/browser/preferences/sanitize.dtd)
locale/browser/preferences/tabs.dtd (%chrome/browser/preferences/tabs.dtd)
+ locale/browser/preferences/update.dtd (%chrome/browser/preferences/update.dtd)
locale/browser/sidebar/sidebar.properties (%chrome/browser/sidebar/sidebar.properties)
% locale browser-region @AB_CD@ %locale/browser-region/
locale/browser-region/region.properties (%chrome/browser-region/region.properties)
diff --git a/mozilla/toolkit/mozapps/update/content/history.js b/mozilla/toolkit/mozapps/update/content/history.js
index 86f8757561e..cbe075bc385 100644
--- a/mozilla/toolkit/mozapps/update/content/history.js
+++ b/mozilla/toolkit/mozapps/update/content/history.js
@@ -58,11 +58,11 @@ var gUpdateHistory = {
for (var i = 0; i < uc; ++i) {
var update = um.getUpdateAt(i);
+ if (!update || !update.name)
+ continue;
var element = document.createElementNS(NS_XUL, "update");
this._view.appendChild(element);
- if (!update.name)
- continue;
element.name = update.name;
element.type = bundle.getString("updateType_" + update.type);
element.installDate = this._formatDate(update.installDate);
diff --git a/mozilla/toolkit/mozapps/update/content/updates.css b/mozilla/toolkit/mozapps/update/content/updates.css
index 3a3bd12de35..73f7fbfa69b 100755
--- a/mozilla/toolkit/mozapps/update/content/updates.css
+++ b/mozilla/toolkit/mozapps/update/content/updates.css
@@ -189,3 +189,9 @@ update {
margin-bottom: 1px;
}
+.updatePrefsInfo {
+ font-size: smaller;
+ margin-left: 27px;
+ margin-bottom: 10px;
+}
+
diff --git a/mozilla/toolkit/mozapps/update/content/updates.js b/mozilla/toolkit/mozapps/update/content/updates.js
index 9da929df2ed..8b414da4d2c 100755
--- a/mozilla/toolkit/mozapps/update/content/updates.js
+++ b/mozilla/toolkit/mozapps/update/content/updates.js
@@ -247,22 +247,27 @@ var gUpdates = {
* checkForUpdates null -- foreground
*/
get startPage() {
+ dump("*** GET STARTPAGE\n");
if (window.arguments) {
var arg0 = window.arguments[0];
+ dump("*** arg0 = " + arg0 + "\n");
if (arg0 instanceof Components.interfaces.nsIUpdate) {
// If the first argument is a nsIUpdate object, we are notifying the
// user that the background checking found an update that requires
// their permission to install, and it's ready for download.
this.setUpdate(arg0);
var p = this.update.selectedPatch;
+ dump("*** P = " + p + "\n");
if (p) {
switch (p.state) {
case STATE_PENDING:
this.sourceEvent = SRCEVT_BACKGROUND;
return document.getElementById("finishedBackground");
case STATE_SUCCEEDED:
+ dump("*** :::::: goats\n");
return document.getElementById("installed");
case STATE_FAILED:
+ case STATE_APPLYING:
return document.getElementById("errors");
}
}
@@ -346,7 +351,8 @@ var gUpdates = {
* etc).
*/
notify: function(timerCallback) {
- this._prompter[methodName](this._update);
+ if (methodName in this._prompter)
+ this._prompter[methodName](null, this._update);
}
}
tm.registerTimer(timerID, (new Callback(gUpdates.update, methodName)),
@@ -596,7 +602,6 @@ var gLicensePage = {
nextButton.disabled = true;
nextButton.label = gUpdates.strings.getString("IAgreeLabel");
gUpdates.wiz.getButton("back").disabled = true;
- gUpdates.wiz.getButton("next").focus();
var cancelButton = gUpdates.wiz.getButton("cancel");
cancelButton.label = gUpdates.strings.getString("IDoNotAgreeLabel");
@@ -612,6 +617,7 @@ var gLicensePage = {
// Now that the license text is available, the user is in a position to
// agree to it, so enable the Agree button.
gUpdates.wiz.getButton("next").disabled = false;
+ gUpdates.wiz.getButton("next").focus();
},
/**
diff --git a/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl b/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
index 404a56d3e16..eb6fab5daa9 100644
--- a/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
+++ b/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
@@ -129,6 +129,11 @@ interface nsIUpdate : nsISupports
*/
attribute AString licenseURL;
+ /**
+ * The URL to the Update Service that supplied this update.
+ */
+ attribute AString serviceURL;
+
/**
* Whether or not the update being downloaded is a complete replacement of
* the user's existing installation or a patch representing the difference
@@ -151,6 +156,11 @@ interface nsIUpdate : nsISupports
*/
readonly attribute nsIUpdatePatch selectedPatch;
+ /**
+ * The state of the selected patch.
+ */
+ attribute AString state;
+
/**
* The number of patches supplied by this update.
*/
@@ -372,27 +382,25 @@ interface nsIApplicationUpdateService : nsISupports
interface nsIUpdateManager : nsISupports
{
/**
- *
+ * Gets the update at the specified index
+ * @param index
+ * The index within the updates array
+ * @returns The nsIUpdate object at the specified index
*/
nsIUpdate getUpdateAt(in long index);
/**
- *
+ * Gets the total number of updates in the history list.
*/
readonly attribute long updateCount;
/**
- *
+ * The active (current) update. The active update is not in the history list.
*/
attribute nsIUpdate activeUpdate;
/**
- *
- */
- void removeUpdateAtIndex(in long index);
-
- /**
- *
+ * Saves all updates to disk.
*/
void saveUpdates();
};
@@ -400,22 +408,22 @@ interface nsIUpdateManager : nsISupports
[scriptable, uuid(0765c92c-6145-4253-9db4-594d8023087e)]
interface nsIUpdateTimerManager : nsISupports
{
- /**
- * Register an interval with the timer manager. The timer manager
- * periodically checks to see if the interval has expired and if it has
- * calls the specified callback. This is persistent across application
- * restarts and can handle intervals of long durations.
- * @param id
- * An id that identifies the interval, used for persistence
- * @param callback
- * A nsITimerCallback object that is notified when the interval
- * expires
- * @param interval
- * The length of time, in milliseconds, of the interval
- */
- void registerTimer(in AString id,
- in nsITimerCallback callback,
- in unsigned long interval);
+ /**
+ * Register an interval with the timer manager. The timer manager
+ * periodically checks to see if the interval has expired and if it has
+ * calls the specified callback. This is persistent across application
+ * restarts and can handle intervals of long durations.
+ * @param id
+ * An id that identifies the interval, used for persistence
+ * @param callback
+ * A nsITimerCallback object that is notified when the interval
+ * expires
+ * @param interval
+ * The length of time, in milliseconds, of the interval
+ */
+ void registerTimer(in AString id,
+ in nsITimerCallback callback,
+ in unsigned long interval);
};
[scriptable, uuid(22d35700-5765-42e1-914b-a0da7c911a8c)]
diff --git a/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in b/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in
index 74d661102d1..be90a369fa4 100644
--- a/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in
+++ b/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in
@@ -37,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
+const PREF_APP_UPDATE_AUTO = "app.update.auto";
const PREF_APP_UPDATE_MODE = "app.update.mode";
const PREF_APP_UPDATE_SILENT = "app.update.silent";
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
@@ -482,6 +483,7 @@ UpdatePrompt.prototype = {
*/
_showUI: function(parent, uri, features, name, update) {
var ary = null;
+ dump("*** UUUU = " + update + "\n");
if (update) {
ary = Components.classes["@mozilla.org/supports-array;1"]
.createInstance(Components.interfaces.nsISupportsArray);
@@ -536,47 +538,6 @@ function UpdateService() {
// Observe xpcom-shutdown to unhook pref branch observers above to avoid
// shutdown leaks.
gOS.addObserver(this, "xpcom-shutdown", false);
-
- /*
- // Detect installation failures and notify
- var status = readStatusFile(getUpdatesDir());
- if (status != null) {
- // null status means the update.status file is not present, because either:
- // 1) no update was performed, and so there's no UI to show
- // 2) an update was attempted but failed during checking, transfer or
- // verification, and was cleaned up at that point, and UI notifying of
- // that error was shown at that stage.
- var um =
- Components.classes["@mozilla.org/updates/update-manager;1"].
- getService(Components.interfaces.nsIUpdateManager);
- var prompter =
- Components.classes["@mozilla.org/updates/update-prompt;1"].
- createInstance(Components.interfaces.nsIUpdatePrompt);
-
- var update = um.activeUpdate;
- if (!update)
- update = new Update(null);
- if (status == STATE_SUCCEEDED) {
- update.statusText = "Install Succeeded";
- //prompter.showUpdateInstalled(update);
- }
- else {
- // Something went wrong with the patch application process.
- update.statusText = "goats";
- // XXXben todo: synthesize the best message
- //prompter.showUpdateError(update);
- }
-
- // Move the update from the Active Update list into the Past Updates list.
- um.activeUpdate = null;
- um.saveUpdates();
-
- // Now trash the updates directory, since we're done with it
- cleanUpUpdatesDir();
- }
- */
-
- this._initLoggingPrefs();
}
UpdateService.prototype = {
@@ -584,17 +545,13 @@ UpdateService.prototype = {
observe: function(subject, topic, data) {
switch (topic) {
- case "app-startup":
- // Resume fetching...
- var um = Components.classes["@mozilla.org/updates/update-manager;1"]
- .getService(Components.interfaces.nsIUpdateManager);
- var activeUpdate = um.activeUpdate;
- if (activeUpdate)
- this.downloadUpdate(activeUpdate, true);
- break;
case "profile-after-change":
gOS.removeObserver(this, "profile-after-change");
+ this._initLoggingPrefs();
+
+ //this._postUpdateCleanup();
+
// Register a background update check timer
var tm =
Components.classes["@mozilla.org/updates/timer-manager;1"]
@@ -602,7 +559,13 @@ UpdateService.prototype = {
var interval = getPref("getIntPref", PREF_APP_UPDATE_INTERVAL, 86400000);
tm.registerTimer("background-update-timer", this, interval);
- this._initLoggingPrefs();
+ // Resume fetching...
+ var um = Components.classes["@mozilla.org/updates/update-manager;1"]
+ .getService(Components.interfaces.nsIUpdateManager);
+ var activeUpdate = um.activeUpdate;
+ if (activeUpdate)
+ this.downloadUpdate(activeUpdate, true);
+
break;
case "xpcom-shutdown":
gOS.removeObserver(this, "xpcom-shutdown");
@@ -610,6 +573,55 @@ UpdateService.prototype = {
}
},
+ /**
+ *
+ */
+ _postUpdateCleanup: function() {
+ // Detect installation failures and notify
+ var status = readStatusFile(getUpdatesDir());
+ if (status != null) {
+ // null status means the update.status file is not present, because either:
+ // 1) no update was performed, and so there's no UI to show
+ // 2) an update was attempted but failed during checking, transfer or
+ // verification, and was cleaned up at that point, and UI notifying of
+ // that error was shown at that stage.
+ var um =
+ Components.classes["@mozilla.org/updates/update-manager;1"].
+ getService(Components.interfaces.nsIUpdateManager);
+ var prompter =
+ Components.classes["@mozilla.org/updates/update-prompt;1"].
+ createInstance(Components.interfaces.nsIUpdatePrompt);
+
+ var update = um.activeUpdate;
+ if (!update)
+ update = new Update(null);
+ update.state = status;
+ if (status == STATE_SUCCEEDED) {
+ update.statusText = "Install Succeeded";
+ LOG("Downloader", "STATE = " + update.selectedPatch.state);
+ LOG("Downloader", "_postUpdateCleanup: Install Succeeded, Showing UI");
+ prompter.showUpdateInstalled(update);
+ }
+ else {
+ // Something went wrong with the patch application process.
+ update.statusText = "goats";
+ // XXXben todo: synthesize the best message
+ LOG("Downloader", "_postUpdateCleanup: Install Failed, Showing UI");
+ prompter.showUpdateError(update);
+ }
+
+ // Move the update from the Active Update list into the Past Updates list.
+ um.activeUpdate = null;
+ um.saveUpdates();
+
+ // Now trash the updates directory, since we're done with it
+ cleanUpUpdatesDir();
+ }
+ else {
+ LOG("Downloader", "_postUpdateCleanup: No Status, No Update");
+ }
+ },
+
/**
* Initialize Logging preferences, formatted like so:
* app.update.log. =
@@ -704,13 +716,11 @@ UpdateService.prototype = {
// Major 1 No Auto Install
// Major 1 Yes Notify and Confirm
// Major 2 Yes or No Notify and Confirm
- // Major 3 Yes or No Notify and Confirm
// Minor 0 Yes or No Auto Install
// Minor 1 No Auto Install
// Minor 1 Yes Notify and Confirm
// Minor 2 No Auto Install
// Minor 2 Yes Notify and Confirm
- // Minor 3 Yes or No Notify and Confirm
//
// In addition, if there is a license associated with an update, regardless
// of type it must be agreed to.
@@ -719,30 +729,49 @@ UpdateService.prototype = {
// at all, and so none of the decision making above is entered into.
//
update.QueryInterface(Components.interfaces.nsIPropertyBag);
- var licenseAccepted = update.getProperty("licenseAccepted") == "true";
- if (update.licenseURL && !licenseAccepted)
+ try {
+ var licenseAccepted = update.getProperty("licenseAccepted") == "true";
+ }
+ catch (e) {
+ licenseAccepted = false;
+ }
+ if (update.licenseURL && !licenseAccepted) {
+ LOG("Checker", "_shouldPrompt: Prompting because of an un-accepted " +
+ "license");
return true;
+ }
var updateEnabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
- if (!updateEnabled)
+ if (!updateEnabled) {
+ LOG("Checker", "_shouldPrompt: Not prompting because update is " +
+ "disabled");
return false;
-
+ }
+
+ // User has turned off automatic download and install
+ var autoEnabled = getPref("getBoolPref", PREF_APP_UPDATE_AUTO, true);
+ if (!autoEnabled) {
+ LOG("Checker", "_shouldPrompt: Prompting because auto install is disabled");
+ return true;
+ }
+
switch (getPref("getIntPref", PREF_APP_UPDATE_MODE, 1)) {
- case 0:
- // Mode 0 is do not prompt regardless of incompatibilities
- return false;
case 1:
// Mode 1 is do not prompt only if there are no incompatibilities
// releases
+ LOG("Checker", "_shouldPrompt: Prompting if there are incompatibilities");
return !isCompatible(update);
case 2:
// Mode 2 is do not prompt only if there are no incompatibilities for
// minor updates only
- if (update.type == "minor")
- return !isCompatible(update);
+ LOG("Checker", "_shouldPrompt: Prompting if major or there are " +
+ "incompatibilities");
+ return update.type == "minor" ? !isCompatible(update) : true;
}
- // Mode 3 is prompt, regardless.
- return true;
+ // Mode 0 is do not prompt regardless of incompatibilities
+ LOG("Checker", "_shouldPrompt: Not prompting the user - they choose to " +
+ "ignore incompatibilities");
+ return false;
},
/**
@@ -781,6 +810,14 @@ UpdateService.prototype = {
* An array of available updates
*/
_selectAndInstallUpdate: function(updates) {
+ // Don't prompt if there's an active update - the user is already
+ // aware and is downloading, or performed some user action to prevent
+ // notification.
+ var um = Components.classes["@mozilla.org/updates/update-manager;1"]
+ .getService(Components.interfaces.nsIUpdateManager);
+ if (um.activeUpdate)
+ return;
+
var update = this.selectUpdate(updates, updates.length);
if (!update)
return;
@@ -789,7 +826,7 @@ UpdateService.prototype = {
var prompter =
Components.classes["@mozilla.org/updates/update-prompt;1"].
createInstance(Components.interfaces.nsIUpdatePrompt);
- prompter.showUpdateAvailable(update);
+ prompter.showUpdateAvailable(null, update);
} else {
this.downloadUpdate(update, true);
}
@@ -900,6 +937,11 @@ UpdateService.prototype = {
* @constructor
*/
function UpdateManager() {
+ // Ensure the Active Update file is loaded
+ var updates = this._loadXMLFileIntoArray(getFile(KEY_APPDIR,
+ [FILE_UPDATE_ACTIVE]));
+ if (updates.length > 0)
+ this._activeUpdate = updates[0];
}
UpdateManager.prototype = {
/**
@@ -920,9 +962,11 @@ UpdateManager.prototype = {
* @returns The array of nsIUpdate items held in the file.
*/
_loadXMLFileIntoArray: function(file) {
- if (!file.exists())
+ if (!file.exists()) {
+ LOG("UpdateManager", "_loadXMLFileIntoArray: XML File does not exist");
return [];
-
+ }
+
var result = [];
var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
@@ -949,6 +993,8 @@ UpdateManager.prototype = {
}
}
catch (e) {
+ LOG("UpdateManager", "_loadXMLFileIntoArray: Error constructing update list " +
+ e);
}
fileStream.close();
return result;
@@ -961,21 +1007,8 @@ UpdateManager.prototype = {
if (!this._updates)
this._updates = this._loadXMLFileIntoArray(getFile(KEY_APPDIR,
[FILE_UPDATES_DB]));
- this._ensureActiveUpdate();
},
- /**
- * Ensure that the Active Update file is loaded.
- */
- _ensureActiveUpdate: function() {
- if (!this._activeUpdate) {
- var updates = this._loadXMLFileIntoArray(getFile(KEY_APPDIR,
- [FILE_UPDATE_ACTIVE]));
- if (updates.length > 0)
- this._activeUpdate = updates[0];
- }
- },
-
/**
* See nsIUpdateService.idl
*/
@@ -996,12 +1029,18 @@ UpdateManager.prototype = {
* See nsIUpdateService.idl
*/
get activeUpdate() {
- this._ensureActiveUpdate();
+ if (this._activeUpdate &&
+ this._activeUpdate.serviceURL != Checker.prototype.updateURL) {
+ // User switched channels, clear out any old active updates and remove
+ // partial downloads
+ this._activeUpdate = null;
+
+ // Destroy the updates directory, since we're done with it.
+ cleanUpUpdatesDir();
+ }
return this._activeUpdate;
},
set activeUpdate(activeUpdate) {
- this._ensureActiveUpdate();
- if (!activeUpdate)
this._addUpdate(this._activeUpdate);
this._activeUpdate = activeUpdate;
if (!activeUpdate) {
@@ -1015,14 +1054,6 @@ UpdateManager.prototype = {
return activeUpdate;
},
- /**
- * See nsIUpdateService.idl
- */
- removeUpdateAtIndex: function(index) {
- this._ensureUpdates();
- tihs._updates.splice(index, 1);
- },
-
/**
* Add an update to the Updates list. If the item already exists in the list,
* replace the existing value with the new value.
@@ -1041,7 +1072,8 @@ UpdateManager.prototype = {
}
}
// Otherwise add it to the front of the list.
- this._updates = [this._activeUpdate].concat(this._updates);
+ if (this._activeUpdate)
+ this._updates = [this._activeUpdate].concat(this._updates);
},
/**
@@ -1133,7 +1165,8 @@ function getPref(func, preference, defaultValue) {
*/
function UpdatePatch(patch) {
for (var i = 0; i < patch.attributes.length; ++i) {
- var attr = patch.attributes[i];
+ var attr = patch.attributes.item(i);
+ attr.QueryInterface(Components.interfaces.nsIDOMAttr);
switch (attr.name) {
case "selected":
this.selected = attr.value == "true";
@@ -1249,19 +1282,14 @@ function Update(update) {
}
for (var i = 0; i < update.attributes.length; ++i) {
- var attr = update.attributes[i];
- switch (attr.name) {
- case "installDate":
- if (attr.value)
- this.installDate = parseInt(attr.value);
- break;
- case "isCompleteUpdate":
+ var attr = update.attributes.item(i);
+ attr.QueryInterface(Components.interfaces.nsIDOMAttr);
+ if (attr.name == "installDate" && attr.value)
+ this.installDate = parseInt(attr.value);
+ else if (attr.name == "isCompleteUpdate")
this.isCompleteUpdate = attr.value == "true";
- break;
- default:
+ else
this[attr.name] = attr.value;
- break;
- };
}
// The Update Name is either the string provided by the element, or
@@ -1294,7 +1322,27 @@ Update.prototype = {
getPatchAt: function(index) {
return this._patches[index];
},
-
+
+ /**
+ * See nsIUpdateService.idl
+ */
+ _state: "",
+ set state(state) {
+ if (this.selectedPatch)
+ this.selectedPatch.state = state;
+ else
+ this._state = state;
+ return state;
+ },
+ get state() {
+ if (this.selectedPatch)
+ return this.selectedPatch.state;
+ return this._state;
+ },
+
+ /**
+ * See nsIUpdateService.idl
+ */
get selectedPatch() {
for (var i = 0; i < this.patchCount; ++i) {
if (this._patches[i].selected)
@@ -1314,6 +1362,7 @@ Update.prototype = {
update.setAttribute("extensionVersion", this.extensionVersion);
update.setAttribute("detailsURL", this.detailsURL);
update.setAttribute("licenseURL", this.licenseURL);
+ update.setAttribute("serviceURL", this.serviceURL);
update.setAttribute("installDate", this.installDate);
update.setAttribute("statusText", this.statusText);
update.setAttribute("isCompleteUpdate", this.isCompleteUpdate);
@@ -1407,7 +1456,7 @@ Checker.prototype = {
* The URL of the update service XML file to connect to that contains details
* about available updates.
*/
- get _updateURL() {
+ get updateURL() {
var url;
try {
// Use the override URL if specified.
@@ -1446,13 +1495,13 @@ Checker.prototype = {
if (!listener)
throw Components.results.NS_ERROR_NULL_POINTER;
- if (!this._updateURL || (!this.enabled && !force))
+ if (!this.updateURL || (!this.enabled && !force))
return;
this._request =
Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance(Components.interfaces.nsIXMLHttpRequest);
- this._request.open("GET", this._updateURL, true);
+ this._request.open("GET", this.updateURL, true);
this._request.overrideMimeType("text/xml");
this._request.setRequestHeader("Cache-Control", "no-cache");
@@ -1461,7 +1510,7 @@ Checker.prototype = {
this._request.onload = function(event) { self.onLoad(event); };
this._request.onprogress = function(event) { self.onProgress(event); };
- LOG("Checker", "checkForUpdates: sending request to " + this._updateURL);
+ LOG("Checker", "checkForUpdates: sending request to " + this.updateURL);
this._request.send(null);
this._callback = listener;
@@ -1500,7 +1549,10 @@ Checker.prototype = {
continue;
updateElement.QueryInterface(Components.interfaces.nsIDOMElement);
- updates.push(new Update(updateElement));
+ var update = new Update(updateElement);
+ update.serviceURL = this.updateURL;
+ LOG("Checker", "Creating service URL" + update.serviceURL);
+ updates.push(update);
}
return updates;
@@ -1856,12 +1908,16 @@ Downloader.prototype = {
},
/**
- *
+ * An array of download listeners to notify when we receive
+ * nsIRequestObserver or nsIProgressEventSink method calls.
*/
_listeners: [],
/**
- *
+ * Adds a listener to the download process
+ * @param listener
+ * A download listener, implementing nsIRequestObserver and
+ * nsIProgressEventSink
*/
addDownloadListener: function(listener) {
for (var i = 0; i < this._listeners.length; ++i) {
@@ -1872,7 +1928,9 @@ Downloader.prototype = {
},
/**
- *
+ * Removes a download listener
+ * @param listener
+ * The listener to remove.
*/
removeDownloadListener: function(listener) {
for (var i = 0; i < this._listeners.length; ++i) {
@@ -1884,7 +1942,11 @@ Downloader.prototype = {
},
/**
- *
+ * When the async request begins
+ * @param request
+ * The nsIRequest object for the transfer
+ * @param context
+ * Additional data
*/
onStartRequest: function(request, context) {
request.QueryInterface(nsIIncrementalDownload);
@@ -1895,8 +1957,16 @@ Downloader.prototype = {
this._listeners[i].onStartRequest(request, context);
},
- /**
- *
+ /**
+ * When new data has been downloaded
+ * @param request
+ * The nsIRequest object for the transfer
+ * @param context
+ * Additional data
+ * @param progress
+ * The current number of bytes transferred
+ * @param maxProgress
+ * The total number of bytes that must be transferred
*/
onProgress: function(request, context, progress, maxProgress) {
request.QueryInterface(nsIIncrementalDownload);
@@ -1910,8 +1980,16 @@ Downloader.prototype = {
}
},
- /**
- *
+ /**
+ * When we have new status text
+ * @param request
+ * The nsIRequest object for the transfer
+ * @param context
+ * Additional data
+ * @param status
+ * A status code
+ * @param statusText
+ * Human readable version of |status|
*/
onStatus: function(request, context, status, statusText) {
request.QueryInterface(nsIIncrementalDownload);
@@ -1924,8 +2002,14 @@ Downloader.prototype = {
}
},
- /**
- *
+ /**
+ * When data transfer ceases
+ * @param request
+ * The nsIRequest object for the transfer
+ * @param context
+ * Additional data
+ * @param status
+ * Status code containing the reason for the cessation.
*/
onStopRequest: function(request, context, status) {
request.QueryInterface(nsIIncrementalDownload);
@@ -1947,6 +2031,7 @@ Downloader.prototype = {
shouldShowPrompt = true;
// Tell the updater.exe we're ready to apply.
+ dump("*** WRITING STATUS = " + state);
this._writeStatusFile(getUpdatesDir(), state);
this._update.installDate = (new Date()).getTime();
this._update.statusText = "Install Pending";
@@ -1995,6 +2080,7 @@ Downloader.prototype = {
deleteActiveUpdate = true;
}
+ LOG("Downloader", "Setting state to: " + state);
this._patch.state = state;
var um =
Components.classes["@mozilla.org/updates/update-manager;1"].
@@ -2030,7 +2116,7 @@ Downloader.prototype = {
var prompter =
Components.classes["@mozilla.org/updates/update-prompt;1"].
createInstance(Components.interfaces.nsIUpdatePrompt);
- prompter.showUpdateDownloaded(this._update);
+ prompter.showUpdateDownloaded(null, this._update);
}
},
@@ -2076,6 +2162,7 @@ TimerManager.prototype = {
* The checking timer that fired.
*/
notify: function(timer) {
+dump("*** STATUS = " + readStatusFile(getUpdatesDir()) + "\n");
for (var timerID in this._timers) {
var timerData = this._timers[timerID];
var lastUpdateTime = timerData.lastUpdateTime;
@@ -2209,6 +2296,8 @@ VersionChecker.prototype = {
}
};
+var gUpdateManager = null;
+
var gModule = {
registerSelf: function(componentManager, fileSpec, location, type) {
componentManager = componentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
@@ -2259,11 +2348,6 @@ var gModule = {
className : "Update Checker",
factory : #1#(Checker)
},
- manager: { CID : Components.ID("{093C2356-4843-4C65-8709-D7DBCBBE7DFB}"),
- contractID : "@mozilla.org/updates/update-manager;1",
- className : "Update Manager",
- factory : #1#(UpdateManager)
- },
prompt: { CID : Components.ID("{27ABA825-35B5-4018-9FDD-F99250A0E722}"),
contractID : "@mozilla.org/updates/update-prompt;1",
className : "Update Prompt",
@@ -2278,7 +2362,12 @@ var gModule = {
contractID : "@mozilla.org/updates/timer-manager;1",
className : "Timer Manager",
factory : #1#(TimerManager)
- }
+ },
+ manager: { CID : Components.ID("{093C2356-4843-4C65-8709-D7DBCBBE7DFB}"),
+ contractID : "@mozilla.org/updates/update-manager;1",
+ className : "Update Manager",
+ factory : #1#(UpdateManager)
+ },
},
canUnload: function(componentManager) {