diff --git a/mozilla/browser/app/profile/firefox.js b/mozilla/browser/app/profile/firefox.js
index 5094945e5cc..3f6c95cc059 100644
--- a/mozilla/browser/app/profile/firefox.js
+++ b/mozilla/browser/app/profile/firefox.js
@@ -71,18 +71,32 @@ pref("update.extensions.enabled", true);
pref("update.extensions.wsdl", "chrome://mozapps/locale/extensions/extensions.properties");
pref("extensions.getMoreExtensionsURL", "chrome://mozapps/locale/extensions/extensions.properties");
pref("extensions.getMoreThemesURL", "chrome://mozapps/locale/extensions/extensions.properties");
-// Automatically download and install updates to themes and extensions.
-pref("update.extensions.autoUpdate", false);
-pref("update.interval", 86400000); // every 24 hrs
-pref("update.lastUpdateDate", 0); // UTC offset when last update was performed.
-pref("update.showSlidingNotification", true); // windows-only slide-up taskbar notification
+pref("update.extensions.autoUpdate", false); // Automatically download and install
+ // updates to themes and extensions.
+ // Does nothing at present.
+pref("update.extensions.interval", 604800000); // Check for updates to Extensions and
+ // Themes every week
+pref("update.extensions.lastUpdateDate", 0); // UTC offset when last Extension/Theme
+ // update was performed.
+pref("update.extensions.severity.threshold", 5);// The number of pending Extension/Theme
+ // updates you can have before the update
+ // notifier goes from low->medium severity.
+pref("update.app.interval", 86400000); // Check for updates to Firefox every day
+pref("update.app.lastUpdateDate", 0); // UTC offset when last App update was
+ // performed.
+pref("update.interval", 3600000); // Check each of the above intervals
+ // every 60 mins
+pref("update.showSlidingNotification", true); // Windows-only slide-up taskbar
+ // notification.
// These prefs relate to the number and severity of updates available. This is a
// cache that the browser notification mechanism uses to determine if it should show
// status bar UI if updates are detected and the app is shut down before installing
// them.
-// 0 = low (extension/theme updates), 1 = medium (app minor version), 2 = high (major version)
+// 0 = low (extension/theme updates),
+// 1 = medium (numerous extension/theme updates),
+// 2 = high (new version of Firefox/Security patch)
pref("update.severity", 0);
// The number of extension/theme/etc updates available
pref("update.extensions.count", 0);
diff --git a/mozilla/toolkit/content/widgets/stringbundle.xml b/mozilla/toolkit/content/widgets/stringbundle.xml
index 0429c2f7a8a..b90107380df 100644
--- a/mozilla/toolkit/content/widgets/stringbundle.xml
+++ b/mozilla/toolkit/content/widgets/stringbundle.xml
@@ -13,7 +13,13 @@
@@ -23,7 +29,13 @@
diff --git a/mozilla/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.dtd b/mozilla/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.dtd
index 819f683802f..c69e23a95da 100755
--- a/mozilla/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.dtd
+++ b/mozilla/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.dtd
@@ -55,3 +55,9 @@
+
+
+
+
+
+
diff --git a/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.dtd b/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.dtd
index 3b7b7b25a73..a81d9ff578d 100644
--- a/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.dtd
+++ b/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.dtd
@@ -10,6 +10,11 @@
+
+
+
+
+
@@ -64,3 +69,6 @@
+
+
+
diff --git a/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.properties b/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.properties
index c42f0f0ebc7..b148691ffc5 100644
--- a/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.properties
+++ b/mozilla/toolkit/locales/en-US/chrome/mozapps/update/update.properties
@@ -5,12 +5,15 @@ mismatchDontCheckAccesskey=D
installButtonText=Install Now
installButtonTextAccesskey=I
nextButtonText=Next >
+nextButtonTextAccesskey=N
cancelButtonText=Cancel
+cancelButtonTextAccesskey=C
update.app.url=http://update.mozilla.org/update.rdf
updatesAvailableTitle=New Updates Available
updatesAvailableText=Click Here to View
+checkingPrefix=Checking for Updates to %S ...
downloadingPrefix=Downloading: %S
installingPrefix=Installing: %S
closeButton=Close
@@ -19,6 +22,8 @@ installErrorDescription=The following components could not be installed due to e
checkingErrorDescription=%S could not check for updates to the following components (either the update server(s) did not respond, or the update service(s) were not found).
installErrorItemFormat=%S (%S)
+versionUpdateComplete=Version Compatibility Update Complete
+
updatesAvailableTooltip-0=Update(s) Available
updatesAvailableTooltip-1=Update(s) Available
updatesAvailableTooltip-2=Critical Update(s) Available
diff --git a/mozilla/toolkit/mozapps/downloads/content/unknownContentType.xul b/mozilla/toolkit/mozapps/downloads/content/unknownContentType.xul
index 559c6cba763..9a946e38586 100755
--- a/mozilla/toolkit/mozapps/downloads/content/unknownContentType.xul
+++ b/mozilla/toolkit/mozapps/downloads/content/unknownContentType.xul
@@ -85,6 +85,17 @@
+
+
+
+
+#else
+ label="&chooseHandler.label;" accesskey="&chooseHandler.accesskey;"/>
+#endif
+
+
diff --git a/mozilla/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in b/mozilla/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
index c9adc5d8937..4f528bbd07c 100644
--- a/mozilla/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
+++ b/mozilla/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
@@ -85,12 +85,15 @@ nsUnknownContentTypeDialog.prototype = {
this.mLauncher = aLauncher;
this.mContext = aContext;
// Display the dialog using the Window Watcher interface.
+
+ var ir = aContext.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+ var dwi = ir.getInterface(Components.interfaces.nsIDOMWindowInternal);
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
- this.mDialog = ww.openWindow(null, // no parent
+ this.mDialog = ww.openWindow(dwi,
"chrome://mozapps/content/downloads/unknownContentType.xul",
null,
- "chrome,centerscreen,titlebar,dialog=yes",
+ "chrome,centerscreen,titlebar,dialog=yes,dependent",
null);
// Hook this object to the dialog.
this.mDialog.dialog = this;
@@ -383,7 +386,10 @@ nsUnknownContentTypeDialog.prototype = {
if (type == "application/octet-stream") {
#endif
- if (this.mLauncher.MIMEInfo.MIMEType == "application/octet-stream") {
+ var mimeType = this.mLauncher.MIMEInfo.MIMEType;
+ if (mimeType == "application/octet-stream" ||
+ mimeType == "application/x-msdownload" ||
+ this.mLauncher.targetFile.isExecutable()) {
rememberChoice.checked = false;
rememberChoice.disabled = true;
}
@@ -392,12 +398,11 @@ nsUnknownContentTypeDialog.prototype = {
}
this.toggleRememberChoice(rememberChoice);
-
// XXXben - menulist won't init properly, hack.
var openHandler = this.dialogElement("openHandler");
openHandler.parentNode.removeChild(openHandler);
- var openParent = this.dialogElement("open").parentNode;
- openParent.appendChild(openHandler);
+ var openHandlerBox = this.dialogElement("openHandlerBox");
+ openHandlerBox.appendChild(openHandler);
this.mDialog.setTimeout("dialog.postShowCallback()", 0);
},
@@ -496,6 +501,12 @@ nsUnknownContentTypeDialog.prototype = {
var defaultApp = this.dialogElement("strings").getFormattedString("defaultApp", [desc]);
this.dialogElement("defaultHandler").label = defaultApp;
}
+ else {
+ this.dialogElement("modeDeck").setAttribute("selectedIndex", "1");
+ // Hide the default handler item too, in case the user picks a
+ // custom handler at a later date which triggers the menulist to show.
+ this.dialogElement("defaultHandler").hidden = true;
+ }
},
// getPath:
@@ -515,8 +526,10 @@ nsUnknownContentTypeDialog.prototype = {
// from the browser at the moment because of security concerns.
var openWithDefaultOK = this.openWithDefaultOK();
var mimeType = this.mLauncher.MIMEInfo.MIMEType;
- if ((mimeType == "application/octet-stream" ||
- mimeType == "application/x-msdownload") && !openWithDefaultOK) {
+ if (this.mLauncher.targetFile.isExecutable() || (
+ (mimeType == "application/octet-stream" ||
+ mimeType == "application/x-msdownload") &&
+ !openWithDefaultOK)) {
this.dialogElement("open").disabled = true;
var openHandler = this.dialogElement("openHandler");
openHandler.disabled = true;
@@ -602,8 +615,11 @@ nsUnknownContentTypeDialog.prototype = {
},
openHandlerCommand: function () {
- if (this.dialogElement("openHandler").selectedItem.id == "choose")
+ var openHandler = this.dialogElement("openHandler");
+ if (openHandler.selectedItem.id == "choose")
this.chooseApp();
+ else
+ openHandler.setAttribute("lastSelectedItemID", openHandler.selectedItem.id);
},
updateOKButton: function() {
@@ -791,6 +807,10 @@ nsUnknownContentTypeDialog.prototype = {
fp.appendFilters(nsIFilePicker.filterApps);
if (fp.show() == nsIFilePicker.returnOK && fp.file) {
+ // Show the "handler" menulist since we have a (user-specified)
+ // application now.
+ this.dialogElement("modeDeck").setAttribute("selectedIndex", "0");
+
// Remember the file they chose to run.
this.chosenApp = fp.file;
// Update dialog.
@@ -799,9 +819,17 @@ nsUnknownContentTypeDialog.prototype = {
otherHandler.setAttribute("path", this.getPath(this.chosenApp));
otherHandler.label = this.chosenApp.leafName;
this.dialogElement("openHandler").selectedIndex = 1;
+ this.dialogElement("openHandler").setAttribute("lastSelectedItemID", "otherHandler");
this.dialogElement("mode").selectedItem = this.dialogElement("open");
}
+ else {
+ var openHandler = this.dialogElement("openHandler");
+ var lastSelectedID = openHandler.getAttribute("lastSelectedItemID");
+ if (!lastSelectedID)
+ lastSelectedID = "defaultHandler";
+ openHandler.selectedItem = this.dialogElement(lastSelectedID);
+ }
},
// Turn this on to get debugging messages.
diff --git a/mozilla/toolkit/mozapps/extensions/content/extensions.js b/mozilla/toolkit/mozapps/extensions/content/extensions.js
index 12e788e6629..bc2b2e9c0be 100644
--- a/mozilla/toolkit/mozapps/extensions/content/extensions.js
+++ b/mozilla/toolkit/mozapps/extensions/content/extensions.js
@@ -239,7 +239,7 @@ XPInstallDownloadManager.prototype = {
// gExtensionManager.addDownload(displayName, url, iconURL, type);
var item = Components.classes["@mozilla.org/updates/item;1"]
.createInstance(Components.interfaces.nsIUpdateItem);
- item.init(url, " ", "", "", displayName, -1, url, iconURL, "", type);
+ item.init(url, " ", "", "", displayName, -1, url, iconURL, "", "", type);
items.push(item);
// Advance the enumerator
diff --git a/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl b/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
index 35da4a13767..9bd989568a1 100644
--- a/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
+++ b/mozilla/toolkit/mozapps/extensions/public/nsIExtensionManager.idl
@@ -88,8 +88,12 @@ interface nsIExtensionManager : nsISupports
readonly attribute boolean inSafeMode;
// Updates
+ const unsigned long UPDATE_MODE_VERSION = 0x01;
+ const unsigned long UPDATE_MODE_NORMAL = 0x02;
void update([array, size_is(aItemCount)] in nsIUpdateItem aItems,
- in unsigned long aItemCount);
+ in unsigned long aItemCount,
+ in unsigned long aUpdateMode,
+ in boolean aWriteVersionUpdates);
// Management
void getItemList(in string aItemID,
@@ -107,7 +111,10 @@ interface nsIExtensionManager : nsISupports
[scriptable, uuid(c0b7517f-0b3a-41a2-bde8-ba3ac8a5af47)]
interface nsIExtensionItemUpdater : nsISupports
{
- void checkForUpdates();
+ void checkForUpdates([array, size_is(aItemCount)] in nsIUpdateItem aItems,
+ in unsigned long aItemCount,
+ in unsigned long aUpdateMode,
+ in boolean aWriteVersionUpdates);
readonly attribute unsigned short sourceEvent;
readonly attribute unsigned short updateTypes;
diff --git a/mozilla/toolkit/mozapps/extensions/service/Extension.java b/mozilla/toolkit/mozapps/extensions/service/Extension.java
deleted file mode 100644
index a1c435fdeb6..00000000000
--- a/mozilla/toolkit/mozapps/extensions/service/Extension.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.mozilla.update.extensions;
-
-public class Extension
-{
- private int row;
- private java.lang.String id;
- private java.lang.String version;
- private java.lang.String name;
- private java.lang.String xpiURL;
-
- public Extension()
- {
- }
-
- public int getRow()
- {
- return row;
- }
-
- public void setRow(int row)
- {
- this.row = row;
- }
-
- public java.lang.String getId()
- {
- return id;
- }
-
- public void setId(java.lang.String id)
- {
- this.id = id;
- }
-
- public java.lang.String getVersion()
- {
- return version;
- }
-
- public void setVersion(java.lang.String version)
- {
- this.version = version;
- }
-
- public java.lang.String getName()
- {
- return name;
- }
-
- public void setName(java.lang.String name)
- {
- this.name = name;
- }
-
- public java.lang.String getXpiURL()
- {
- return xpiURL;
- }
-
- public void setXpiURL(java.lang.String xpiURL)
- {
- this.xpiURL = xpiURL;
- }
-
-}
-
-//public class Extension
-//{
-// public Extension()
-// {
-// }
-//
-// public int row;
-// public String id;
-// public String version;
-// public String name;
-// public String xpiURL;
-//}
-
diff --git a/mozilla/toolkit/mozapps/extensions/service/UpdateItem.java b/mozilla/toolkit/mozapps/extensions/service/UpdateItem.java
index 21754b16208..2fe52c15c52 100644
--- a/mozilla/toolkit/mozapps/extensions/service/UpdateItem.java
+++ b/mozilla/toolkit/mozapps/extensions/service/UpdateItem.java
@@ -1,16 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * 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 Extension Update Service.
+ *
+ * The Initial Developer of the Original Code is Ben Goodger.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben Goodger
+ *
+ * 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 ***** */
+
package org.mozilla.update.extensions;
public class UpdateItem
{
- private int row;
private java.lang.String id;
private java.lang.String version;
private java.lang.String minAppVersion;
private java.lang.String maxAppVersion;
private java.lang.String name;
- private java.lang.String updateURL;
+ private int row;
+ private java.lang.String xpiURL;
private java.lang.String iconURL;
- private int type;
+ private int type;
public UpdateItem()
{
@@ -76,14 +113,14 @@ public class UpdateItem
this.name = name;
}
- public java.lang.String getUpdateURL()
+ public java.lang.String getXpiURL()
{
- return updateURL;
+ return xpiURL;
}
- public void setUpdateURL(java.lang.String updateURL)
+ public void setXpiURL(java.lang.String xpiURL)
{
- this.updateURL = updateURL;
+ this.xpiURL = xpiURL;
}
public java.lang.String getIconURL()
@@ -106,19 +143,3 @@ public class UpdateItem
this.type = type;
}
}
-
-//public class ExtensionType
-//{
-// public ExtensionType()
-// {
-// }
-//
-// public int row;
-// public String id;
-// public String version;
-// public String name;
-// public String updateURL;
-// public String iconURL;
-// public int type;
-//}
-
diff --git a/mozilla/toolkit/mozapps/extensions/service/VersionCheck.java b/mozilla/toolkit/mozapps/extensions/service/VersionCheck.java
index 507a36f9bef..7e9697ba64e 100644
--- a/mozilla/toolkit/mozapps/extensions/service/VersionCheck.java
+++ b/mozilla/toolkit/mozapps/extensions/service/VersionCheck.java
@@ -12,7 +12,7 @@
* for the specific language governing rights and limitations under the
* License.
*
- * The Original Code is the Extension Manager.
+ * The Original Code is the Extension Update Service.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
@@ -38,7 +38,6 @@
package org.mozilla.update.extensions;
import java.sql.*;
-import java.util.*;
public class VersionCheck
{
@@ -46,38 +45,59 @@ public class VersionCheck
{
}
- /*
- public static void main(String[] args)
- {
- VersionCheck impl = new VersionCheck();
- // int id = impl.getNewestExtension("{bb8ee064-ccb9-47fc-94ae-ec335af3fe2d}", "3.0", "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}", "0.8.0+");
- int id = impl.getNewestExtension("{93c4cb22-bf10-40a2-adff-c4c64a38df0c}", "1.5", "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}", "0.8.0+");
- System.out.println("result row = " + id + ", xpiUrl = " + impl.getProperty(id, "xpiurl"));
- }
- */
-
- public UpdateItemSet getExtensionUpdates(UpdateItem aInstalledItem,
- String aTargetApp,
- String aTargetAppVersion)
+/*
+ public static void main(String[] args)
{
- UpdateItemSet set = new UpdateItemSet();
- set.currentItem = this.getExtensionUpdates(aInstalledItem, aTargetApp, aTargetAppVersion, false);
- set.newestItem = this.getExtensionUpdates(aInstalledItem, aTargetApp, aTargetAppVersion, true);
- return set;
+ VersionCheck impl = new VersionCheck();
+
+ UpdateItem item = new UpdateItem();
+ item.setId("{1ffc34af-6d8b-45a8-9765-92887262edfe}");
+ item.setVersion("3.0");
+ item.setMinAppVersion("0.9");
+ item.setMaxAppVersion("0.10");
+ item.setName("NewExtension 5");
+ item.setRow(-1);
+ item.setXpiURL("");
+ item.setIconURL("");
+ item.setUserCookie("Goats");
+ item.setItemCookie("Goats 2");
+ UpdateItem newer = impl.getNewestExtension(item, "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}", "0.9");
+ if (newer != null) {
+ System.out.println("*** result row = " + newer.getRow() + ", xpiUrl = " + newer.getXpiURL());
+ }
+ else {
+ System.out.println("*** NADA NOTHING ZILCH");
+ }
+ }
+*/
+
+ public UpdateItem getNewestExtension(UpdateItem aInstalledItem,
+ String aTargetApp,
+ String aTargetAppVersion,
+ String aUserCookie,
+ String aSessionCookie)
+ {
+ return getExtensionUpdates(aInstalledItem, aTargetApp, aTargetAppVersion, true);
}
- public UpdateItem getExtensionUpdates(UpdateItem aInstalledItem,
- String aTargetApp,
- String aTargetAppVersion,
- boolean aNewest)
+ public UpdateItem getVersionUpdate(UpdateItem aInstalledItem,
+ String aTargetApp,
+ String aTargetAppVersion,
+ String aUserCookie,
+ String aSessionCookie)
+ {
+ return getExtensionUpdates(aInstalledItem, aTargetApp, aTargetAppVersion, false);
+ }
+
+ protected UpdateItem getExtensionUpdates(UpdateItem aInstalledItem,
+ String aTargetApp,
+ String aTargetAppVersion,
+ boolean aNewest)
{
UpdateItem remoteItem = new UpdateItem();
- int installedVersionParts = getPartCount(aInstalledItem.getVersion());
- int targetAppVersionParts = getPartCount(aTargetAppVersion);
-
- int installedVersion = parseVersion(aInstalledItem.getVersion(), installedVersionParts);
- int targetAppVersion = parseVersion(aTargetAppVersion, targetAppVersionParts);
+ Version installedVersion = new Version(aInstalledItem.getVersion());
+ Version targetAppVersion = new Version(aTargetAppVersion);
Connection c;
Statement sMain, sVersion, sApps;
@@ -95,11 +115,11 @@ public class VersionCheck
boolean temp = sMain.execute(sqlMain);
rsMain = sMain.getResultSet();
- int newestRemoteVersion = installedVersion;
+ Version newestRemoteVersion = installedVersion;
while (rsMain.next())
{
String sqlVersion = "SELECT * FROM t_version WHERE ID = '" + rsMain.getInt("ID") + "'";
-
+
sVersion = c.createStatement();
temp = sVersion.execute(sqlVersion);
rsVersion = sVersion.getResultSet();
@@ -114,29 +134,30 @@ public class VersionCheck
if (rsApps.next())
{
- int minTargetAppVersion = parseVersion(rsVersion.getString("MinAppVer"), targetAppVersionParts);
- int maxTargetAppVersion = parseVersion(rsVersion.getString("MaxAppVer"), targetAppVersionParts);
-
- int currentRemoteVersion = parseVersion(rsVersion.getString("Version"), installedVersionParts);
+ Version minTargetAppVersion = new Version(rsVersion.getString("MinAppVer"));
+ Version maxTargetAppVersion = new Version(rsVersion.getString("MaxAppVer"));
+
+ Version currentRemoteVersion = new Version(rsVersion.getString("Version"));
boolean suitable = false;
if (aNewest)
{
// If we're looking for the _newest_ version only, check to see if it's really newer
- suitable = currentRemoteVersion > installedVersion &&
- currentRemoteVersion > newestRemoteVersion &&
- minTargetAppVersion <= targetAppVersion &&
- targetAppVersion < maxTargetAppVersion;
- newestRemoteVersion = currentRemoteVersion;
+ suitable = currentRemoteVersion.compare(installedVersion) > 0 &&
+ currentRemoteVersion.compare(newestRemoteVersion) > 0 &&
+ minTargetAppVersion.compare(targetAppVersion) <= 0 &&
+ targetAppVersion.compare(maxTargetAppVersion) <= 0;
+ if (suitable)
+ newestRemoteVersion = currentRemoteVersion;
}
else
{
// ... otherwise, if the version exactly matches...
- suitable = currentRemoteVersion == installedVersion &&
- minTargetAppVersion <= targetAppVersion &&
- targetAppVersion < maxTargetAppVersion;
+ suitable = currentRemoteVersion.compare(installedVersion) == 0 &&
+ minTargetAppVersion.compare(targetAppVersion) <= 0 &&
+ targetAppVersion.compare(maxTargetAppVersion) <= 0;
}
-
+
if (suitable)
{
remoteItem.setRow(rsMain.getInt("ID"));
@@ -145,7 +166,7 @@ public class VersionCheck
remoteItem.setVersion(rsVersion.getString("Version"));
remoteItem.setMinAppVersion(rsVersion.getString("MinAppVer"));
remoteItem.setMaxAppVersion(rsVersion.getString("MaxAppVer"));
- remoteItem.setUpdateURL(rsMain.getString("URI"));
+ remoteItem.setXpiURL(rsVersion.getString("URI"));
remoteItem.setIconURL("");
}
}
@@ -166,39 +187,10 @@ public class VersionCheck
return remoteItem;
}
- protected int parseVersion(String aVersionString, int aPower)
- {
- int version = 0;
- StringTokenizer tokenizer = new StringTokenizer(aVersionString, ".");
-
- if (aPower == 0)
- aPower = tokenizer.countTokens();
-
- for (int i = 0; tokenizer.hasMoreTokens(); ++i)
- {
- String token = tokenizer.nextToken();
- if (token.endsWith("+"))
- {
- token = token.substring(0, token.lastIndexOf("+"));
- version += 1;
- if (token.length() == 0)
- continue;
- }
-
- version += Integer.parseInt(token) * Math.pow(10, aPower - i);
- }
- return version;
- }
-
- protected int getPartCount(String aVersionString)
- {
- return (new StringTokenizer(aVersionString, ".")).countTokens();
- }
-
protected Connection getConnection() throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
- return DriverManager.getConnection("jdbc:mysql://localhost/umo_extensions", "root", "");
+ return DriverManager.getConnection("jdbc:mysql://localhost/update", "root", "");
}
}
diff --git a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
index 04b4a948931..c5890816729 100644
--- a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+++ b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
@@ -77,6 +77,9 @@ const KEY_APPDIR = "XCurProcD";
const KEY_DEFAULTS = "ProfDefNoLoc";
const KEY_DEFAULT_THEME = "classic/1.0";
+const ERROR_INVALID_VERSION = -1;
+const ERROR_PHONED_HOME = -2;
+
///////////////////////////////////////////////////////////////////////////////
//
// Utility Functions
@@ -1285,7 +1288,6 @@ nsThemeInstaller.prototype = {
zipReader.extract(FILE_CHROME_MANIFEST, tempChromeManifest);
var rdfs = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
- dumpFile(zipReader.file);
showOldThemeError(rdfs.GetDataSourceBlocking(getURLSpecFromFile(tempChromeManifest)));
tempChromeManifest.remove(false);
}
@@ -2091,7 +2093,7 @@ nsExtensionManager.prototype = {
return getDirNoCreate(getDirKey(aIsProfile),
[DIR_EXTENSIONS, aExtensionID, DIR_COMPONENTS]);
},
-
+
_getPreferencesDir: function nsExtensionManager__getPreferencesDir (aIsProfile, aExtensionID)
{
return getDirNoCreate(getDirKey(aIsProfile),
@@ -2173,19 +2175,26 @@ nsExtensionManager.prototype = {
// components/
// defaults/
// prefs/
+ var installProfile = aFlags & nsIExtensionManager.FLAG_INSTALL_PROFILE;
+
+ var tempDir = getDir(getDirKey(installProfile), [DIR_EXTENSIONS, DIR_TEMP]);
+ var fileName = getRandomFileName("temp", "xpi");
+ aXPIFile.copyTo(tempDir, fileName);
+ var xpiFile = tempDir.clone();
+ xpiFile.append(fileName);
+
var zipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Components.interfaces.nsIZipReader);
- zipReader.init(aXPIFile);
+ zipReader.init(xpiFile);
zipReader.open();
- var installProfile = aFlags & nsIExtensionManager.FLAG_INSTALL_PROFILE;
var tempManifest = getFile(getDirKey(installProfile),
[DIR_EXTENSIONS, DIR_TEMP, getRandomFileName("install", "rdf")]);
if (!tempManifest.exists())
tempManifest.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
zipReader.extract(FILE_INSTALL_MANIFEST, tempManifest);
- var extensionID = this.installExtensionInternal(tempManifest, installProfile);
+ var extensionID = this.installExtensionInternal(xpiFile, tempManifest, installProfile);
if (extensionID) {
// Then we stage the extension's XPI into a temporary directory so we
// can extract them after the next restart.
@@ -2193,11 +2202,15 @@ nsExtensionManager.prototype = {
this._writeComponentManifest(installProfile);
}
+
zipReader.close();
tempManifest.remove(false);
+
+ if (extensionID != ERROR_PHONED_HOME)
+ xpiFile.remove(false);
},
- installExtensionInternal: function nsExtensionManager_installExtensionInternal (aManifest, aIsProfile)
+ installExtensionInternal: function nsExtensionManager_installExtensionInternal (aXPIFile, aManifest, aIsProfile)
{
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
@@ -2209,36 +2222,174 @@ nsExtensionManager.prototype = {
this._ensureDS();
var extensionID = this.canInstallItem(ds);
// |extensionID| must be a GUID string, not a number - a number means failure.
- if (isNaN(parseInt(extensionID))) {
- // Clear any "disabled" flags that may have been set by the mismatch
- // checking code at startup.
- var props = { toBeDisabled : null,
- disabled : null,
- toBeInstalled : this._ds._emL("true"),
- name : this.getManifestProperty(ds, "name"),
- version : this.getManifestProperty(ds, "version") };
- for (var p in props) {
- this._ds.setItemProperty(extensionID, this._ds._emR(p),
- props[p], aIsProfile,
- nsIUpdateItem.TYPE_EXTENSION);
+ if (isNaN(parseInt(extensionID)))
+ this._configureForthcomingItem(ds, extensionID, aIsProfile);
+ else if (extensionID == 0) {
+ var io = new this.IncompatibleObserver(this);
+ var isChecking = io.checkForUpdates(ds, nsIUpdateItem.TYPE_EXTENSION,
+ aXPIFile, aIsProfile);
+ if (!isChecking)
+ showIncompatibleError(ds);
+ else {
+ extensionID = ERROR_PHONED_HOME; // caller uses this to distinguish
+ // phone-home attempt.
}
-
- // Insert it into the child list NOW rather than later because:
- // - extensions installed using the command line need to be a member
- // of a container during the install phase for the code to be able
- // to identify profile vs. global
- // - extensions installed through the UI should show some kind of
- // feedback to indicate their presence is forthcoming (i.e. they
- // will be available after a restart).
- this._ds.insertForthcomingItem(extensionID, nsIUpdateItem.TYPE_EXTENSION,
- aIsProfile);
}
- else if (extensionID == 0)
- showIncompatibleError(ds);
return extensionID;
},
+ IncompatibleObserver: function nsExtensionManager_IncompatibleObserver (aEM)
+ {
+ this._item = null;
+ this._em = aEM;
+ this._ds = null;
+ this._xpi = null;
+ this._extensionID = 0;
+ this._isProfile = true;
+
+ this.checkForUpdates = function nsExtensionManager__iOcheckForUpdates (aDataSource, aType,
+ aXPIFile, aIsProfile)
+ {
+ // Construct a nsIUpdateItem for this extension...
+ var item = this._em._getItemForIncompatibleID(aDataSource, aType);
+ if (item) {
+ this._item = item;
+ this._ds = aDataSource;
+ this._xpi = aXPIFile;
+ this._isProfile = true;
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.addObserver(this, "Version:Extension:Started", false);
+ os.addObserver(this, "Version:Extension:Item-Ended", false);
+ os.addObserver(this, "Version:Extension:Item-Error", false);
+ os.addObserver(this, "Version:Extension:Ended", false);
+
+ this._em.update([item], 1, nsIExtensionManager.UPDATE_MODE_VERSION, false);
+
+ return true;
+ }
+ return false;
+ }
+
+ this.observe = function nsExtensionManager__iOobserve (aSubject, aTopic, aData)
+ {
+ switch (aTopic) {
+ case "Version:Extension:Started":
+ break;
+ case "Version:Extension:Item-Ended":
+ if (aSubject) {
+ var item = aSubject.QueryInterface(Components.interfaces.nsIUpdateItem);
+ this._em._ds.setTargetApplicationInfo(item.id,
+ item.minAppVersion,
+ item.maxAppVersion,
+ this._ds,
+ this._item.type);
+ this._extensionID = this._em.canInstallItem(this._ds);
+ }
+ break;
+ case "Version:Extension:Item-Error":
+ break;
+ case "Version:Extension:Ended":
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ os.removeObserver(this, "Version:Extension:Started");
+ os.removeObserver(this, "Version:Extension:Item-Ended");
+ os.removeObserver(this, "Version:Extension:Item-Error");
+ os.removeObserver(this, "Version:Extension:Ended");
+
+ if (isNaN(this._extensionID)) {
+ var zipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"]
+ .createInstance(Components.interfaces.nsIZipReader);
+ zipReader.init(this._xpi);
+ zipReader.open();
+
+ // Add the item after all
+ this._em._configureForthcomingItem(this._ds, this._extensionID,
+ this._isProfile);
+ this._em._stageExtensionXPI(zipReader, this._extensionID, this._isProfile);
+ this._em._writeComponentManifest(this._isProfile);
+
+ zipReader.close();
+ }
+ else
+ showIncompatibleError(this._ds);
+
+ // Now really delete the temporary XPI file
+ this._xpi.remove(false);
+ break;
+ }
+ }
+ },
+
+ _configureForthcomingItem: function nsExtensionManager__configureForthcomingItem (aDataSource,
+ aExtensionID,
+ aIsProfile)
+ {
+ // Clear any "disabled" flags that may have been set by the mismatch
+ // checking code at startup.
+ var props = { toBeDisabled : null,
+ disabled : null,
+ toBeInstalled : this._ds._emL("true"),
+ name : this.getManifestProperty(aDataSource, "name"),
+ version : this.getManifestProperty(aDataSource, "version") };
+ for (var p in props) {
+ this._ds.setItemProperty(aExtensionID, this._ds._emR(p),
+ props[p], aIsProfile,
+ nsIUpdateItem.TYPE_EXTENSION);
+ }
+
+ // Insert it into the child list NOW rather than later because:
+ // - extensions installed using the command line need to be a member
+ // of a container during the install phase for the code to be able
+ // to identify profile vs. global
+ // - extensions installed through the UI should show some kind of
+ // feedback to indicate their presence is forthcoming (i.e. they
+ // will be available after a restart).
+ this._ds.insertForthcomingItem(aExtensionID, nsIUpdateItem.TYPE_EXTENSION,
+ aIsProfile);
+ },
+
+ _getItemForIncompatibleID: function nsExtensionManager__getItemForID (aDataSource, aType)
+ {
+ var newItem = null;
+ var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
+ .getService(Components.interfaces.nsIRDFService);
+ var id, version, targetAppInfo, name;
+ var manifestRoot = rdf.GetResource("urn:mozilla:install-manifest");
+ try {
+ function getProperty (aDataSource, aSourceResource, aProperty)
+ {
+ var rv;
+ try {
+ var property = rdf.GetResource(EM_NS(aProperty));
+ rv = stringData(aDataSource.GetTarget(aSourceResource, property, true));
+ if (rv == "--")
+ throw Components.results.NS_ERROR_FAILURE;
+ }
+ catch (e) { }
+ return rv;
+ }
+
+ var root = rdf.GetResource("urn:mozilla:install-manifest");
+ id = getProperty(aDataSource, root, "id");
+ version = getProperty(aDataSource, root, "version");
+ targetAppInfo = this._ds.getTargetApplicationInfo(id, aDataSource, aType);
+ name = getProperty(aDataSource, root, "name");
+
+ newItem = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ newItem.init(id, version, targetAppInfo.minAppVersion,
+ targetAppInfo.maxAppVersion,
+ name, -1, "", "", "", "", aType);
+ }
+ catch (e) {
+ return null;
+ }
+ return newItem;
+ },
+
canInstallItem: function nsExtensionManager_canInstallItem (aDataSource)
{
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
@@ -2253,7 +2404,7 @@ nsExtensionManager.prototype = {
var name = rdf.GetResource(EM_NS("name"));
var nameLiteral = stringData(aDataSource.GetTarget(manifestRoot, name, true));
showInvalidVersionError(nameLiteral, versionLiteral);
- return -1;
+ return ERROR_INVALID_VERSION;
}
// Check the target application range specified by the extension metadata.
@@ -2384,8 +2535,10 @@ nsExtensionManager.prototype = {
// Update the Defaults Manifest
this._writeDefaults(isProfile);
},
-
- update: function nsExtensionManager_update (aItems, aItemCount)
+
+ update: function nsExtensionManager_update (aItems, aItemCount,
+ aUpdateMode,
+ aWriteVersionUpdates)
{
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
@@ -2396,8 +2549,9 @@ nsExtensionManager.prototype = {
var addonType = nsIUpdateItem.TYPE_ADDON;
aItems = this.getItemList(null, addonType, { });
}
- var updater = new nsExtensionItemUpdater(aItems, appID, appVersion, this);
- updater.checkForUpdates();
+ var updater = new nsExtensionItemUpdater(appID, appVersion, this);
+ updater.checkForUpdates(aItems, aItems.length, aUpdateMode,
+ aWriteVersionUpdates);
},
getItemList: function nsExtensionManager_getItemList (aItemID, aType, aCountRef)
@@ -2457,7 +2611,7 @@ nsExtensionManager.prototype = {
for (var i = 0; i < aItemCount; ++i) {
var currItem = aItems[i];
var txnID = Math.round(Math.random() * 100);
- txn.addDownload(currItem.name, currItem.updateURL, currItem.iconURL,
+ txn.addDownload(currItem.name, currItem.xpiURL, currItem.iconURL,
currItem.type, txnID);
this._transactions.push(txn);
}
@@ -2702,10 +2856,8 @@ nsItemDownloadTransaction.prototype = {
//
// nsExtensionItemUpdater
//
-function nsExtensionItemUpdater(aItems, aTargetAppID, aTargetAppVersion, aEM)
+function nsExtensionItemUpdater(aTargetAppID, aTargetAppVersion, aEM)
{
- this._items = aItems;
- this._count = aItems.length;
this._appID = aTargetAppID;
this._appVersion = aTargetAppVersion;
this._emDS = aEM._ds;
@@ -2714,96 +2866,337 @@ function nsExtensionItemUpdater(aItems, aTargetAppID, aTargetAppVersion, aEM)
this._os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
- // This is the number of extensions/themes/etc that we found updates for.
- this._updateCount = 0;
+ this._versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
+ .getService(Components.interfaces.nsIVersionChecker);
+ this._goat = Math.round(Math.random() * 100000);
}
nsExtensionItemUpdater.prototype = {
+ _appID : "",
+ _appVersion : "",
+ _emDS : null,
+ _em : null,
+ _os : null,
+ _versionChecker : null,
+ _prefix : "",
+ _updateMode : 0,
+ _items : [],
+
+ _getMessage: function nsExtensionItemUpdater_getMessage(aMessage)
+ {
+ return this._prefix + ":Extension:" + aMessage;
+ },
+
/////////////////////////////////////////////////////////////////////////////
// nsIExtensionItemUpdater
- checkForUpdates: function nsExtensionItemUpdater_checkForUpdates ()
+ checkForUpdates: function nsExtensionItemUpdater_checkForUpdates (aItems, aItemCount,
+ aUpdateMode,
+ aWriteVersionUpdates)
{
- this._os.notifyObservers(null, "Update:Extension:Started", "");
- var wspFactory = Components.classes["@mozilla.org/xmlextras/proxy/webserviceproxyfactory;1"]
- .getService(Components.interfaces.nsIWebServiceProxyFactory);
- var pref = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- var wsdlURI = pref.getComplexValue(PREF_UPDATE_EXT_WSDL_URI,
- Components.interfaces.nsIPrefLocalizedString).data;
- wspFactory.createProxyAsync(wsdlURI, "VersionCheck", "", true, this);
+ this._prefix = (aUpdateMode == nsIExtensionManager.UPDATE_MODE_NORMAL) ? "Update" : "Version";
+ this._os.notifyObservers(null, this._getMessage("Started"), "");
+ this._updateMode = aUpdateMode;
+ this._items = aItems;
+ this._responseCount = aItemCount;
- for (var i = 0; i < this._items.length; ++i) {
+ // Install-time updates are not written to the DS because there is no
+ // entry yet, EM just uses the notifications to ascertain (by hand)
+ // whether or not there is a remote maxVersion tweak that makes the
+ // item being installed compatible.
+ this._writeVersionUpdates = aWriteVersionUpdates;
+
+ // This is the number of extensions/themes/etc that we found updates for.
+ this._updateCount = 0;
+
+ var pref = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+
+ var defaultRequest = false;
+ for (var i = 0; i < aItemCount; ++i) {
var e = this._items[i];
- if (e.updateRDF) {
- var dsURI = e.updateRDF;
- dsURI = dsURI.replace(/%ITEM_ID%/g, e.id);
- dsURI = dsURI.replace(/%ITEM_VERSION%/g, e.version);
- dsURI = dsURI.replace(/%APP_ID%/g, this._appID);
- dsURI = dsURI.replace(/%APP_VERSION%/g, this._appVersion);
- var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
- .getService(Components.interfaces.nsIRDFService);
- var ds = rdf.GetDataSource(dsURI);
- var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource)
- if (rds.loaded)
- this.onDatasourceLoaded(ds, e);
- else {
- var sink = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
- sink.addXMLSinkObserver(new nsExtensionUpdateXMLRDFDSObserver(this, e));
- }
+ this._os.notifyObservers(e, this._getMessage("Item-Started"), "");
+ if (e.updateRDF)
+ (new nsRDFItemUpdater(this)).checkForUpdates(e, this._updateMode);
+ else {
+ // Invoke a custom web service proxy, if the extension specifies one.
+ if (e.updateService)
+ this._checkForUpdatesAtServiceURI(e.updateService);
+ else
+ defaultRequest = true;
}
}
+
+ if (defaultRequest) {
+ var wsdlURI = pref.getComplexValue(PREF_UPDATE_EXT_WSDL_URI,
+ Components.interfaces.nsIPrefLocalizedString).data;
+ this._checkForUpdatesAtServiceURI(wsdlURI);
+ }
+ },
+
+ _checkForUpdatesAtServiceURI: function nsExtensionItemUpdater__checkForUpdatesAtServiceURI (aServiceURI)
+ {
+ var proxy = new WSProxy(this, aServiceURI);
+ var wspFactory = Components.classes["@mozilla.org/xmlextras/proxy/webserviceproxyfactory;1"]
+ .getService(Components.interfaces.nsIWebServiceProxyFactory);
+ wspFactory.createProxyAsync(aServiceURI, "VersionCheck", "", true, proxy);
},
/////////////////////////////////////////////////////////////////////////////
// nsExtensionItemUpdater
- _proxy: null,
-
- _checkForUpdates: function nsExtensionItemUpdater__checkForUpdates ()
+ _applyVersionUpdates: function nsExtensionItemUpdater__applyVersionUpdates (aLocalItem, aRemoteItem)
{
- for (var i = 0; i < this._items.length; ++i) {
- var e = this._items[i];
+ var r = this._emDS._getResourceForItem(aLocalItem.id);
+ if (!r) return;
+ var targetAppInfo = this._emDS.getTargetApplicationInfo(aLocalItem.id, this._emDS,
+ getItemType(r.Value));
+ if (this._versionChecker.compare(targetAppInfo.maxVersion, aRemoteItem.maxAppVersion) < 0) {
+ // Remotely specified maxVersion is newer than the maxVersion
+ // for the installed Extension. Apply that change to the datasource.
+ this._emDS.setTargetApplicationInfo(aLocalItem.id,
+ aRemoteItem.minAppVersion,
+ aRemoteItem.maxAppVersion,
+ null, aLocalItem.type);
+
+ // If we got here through |checkForMismatches|, this extension has
+ // already been disabled, re-enable it.
+ if (this._emDS.getItemProperty(aLocalItem.id, "disabled") == "true")
+ this._em.enableExtension(aLocalItem.id);
+ }
+ },
+
+ _isValidUpdate: function nsExtensionItemUpdater__isValidUpdate (aLocalItem, aRemoteItem)
+ {
+ var pref = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ var appExtensionsVersion = pref.getCharPref(PREF_EM_APP_EXTENSIONS_VERSION);
+
+ // Check if the update will only run on a newer version of Firefox.
+ if (aRemoteItem.minAppVersion &&
+ this._versionChecker.compare(appExtensionsVersion, aRemoteItem.minAppVersion) < 0)
+ return false;
+
+ // Check if the update will only run on an older version of Firefox.
+ if (aRemoteItem.maxAppVersion &&
+ this._versionChecker.compare(appExtensionsVersion, aRemoteItem.maxAppVersion) > 0)
+ return false;
+
+ return true;
+ },
+
+ _checkForDone: function nsExtensionItemUpdater__checkForDone (aServiceURI)
+ {
+ if (--this._responseCount == 0) {
+ if (this._updateMode == nsIExtensionManager.UPDATE_MODE_NORMAL) {
+ var pref = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ pref.setIntPref(PREF_UPDATE_COUNT, this._updateCount);
+ }
+
+ this._os.notifyObservers(null, this._getMessage("Ended"), "");
+ }
+ },
+
+ /////////////////////////////////////////////////////////////////////////////
+ // nsISupports
+ QueryInterface: function nsExtensionItemUpdater_QueryInterface (aIID)
+ {
+ if (!aIID.equals(Components.interfaces.nsIExtensionItemUpdater) &&
+ !aIID.equals(Components.interfaces.nsISupports))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ return this;
+ }
+};
+
+function WSProxy(aUpdater, aServiceURI)
+{
+ this._updater = aUpdater;
+ this._serviceURI = aServiceURI;
+
+ this._os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+}
+
+WSProxy.prototype = {
+ _updater : null,
+ _serviceURI : "",
+ _proxy : null,
+ _pendingTransactions : [],
+ _os : null,
+
+ checkForUpdates: function nsExtensionItemUpdater__checkForUpdates (aUpdateMode)
+ {
+ if (!this._proxy) {
+ this._pendingTransactions.push(aUpdateMode);
+ return;
+ }
+
+ for (var i = 0; i < this._updater._items.length; ++i) {
+ var e = this._updater._items[i];
if (!e.updateRDF) {
- this._os.notifyObservers(null, "Update:Extension:Item-Started", e.name + " " + e.version);
- this._proxy.getNewestExtension(eval(e.objectSource), this._appID, this._appVersion);
+ if (e.updateService && e.updateService != this._serviceURI)
+ continue;
+ if (aUpdateMode == nsIExtensionManager.UPDATE_MODE_NORMAL) {
+ this._proxy.getNewestExtension(eval(e.objectSource),
+ this._updater._appID,
+ this._updater._appVersion,
+ "", "");
+ }
+ else {
+ this._proxy.getVersionUpdate(eval(e.objectSource),
+ this._updater._appID,
+ this._updater._appVersion,
+ "", "");
+ }
}
}
},
+ getNewestExtensionCallback: function nsExtensionItemUpdater_getNewestExtensionCallback (aResult)
+ {
+ var remoteItem = null;
+ try {
+ aResult.name.toString(); // XXXben This is a lame hack to cause an exception to be
+ // thrown for null values when there is no newer extension
+ // or something else bad happens on the server that we
+ // don't recognize.
+ remoteItem = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ remoteItem.init(aResult.id, aResult.version, aResult.minAppVersion,
+ aResult.maxAppVersion, aResult.name, -1,
+ aResult.xpiURL, aResult.iconURL, "", "",
+ aResult.type);
+ var localItem = this._updater._emDS.getItemForID(remoteItem.id);
+ if (!this._updater._isValidUpdate(localItem, remoteItem))
+ return;
+ else
+ ++this._updater._updateCount;
+ }
+ catch (e) { }
+
+ this._os.notifyObservers(remoteItem,
+ "Update:Extension:Item-Ended",
+ "");
+
+ this._updater._checkForDone(this._serviceURI);
+ },
+
+ getVersionUpdateCallback: function nsExtensionItemUpdater_getVersionUpdateCallback (aResult)
+ {
+ var remoteItem = null;
+ try {
+ aResult.name.toString(); // XXXben see above for excuse-making.
+ remoteItem = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ remoteItem.init(aResult.id, aResult.version, aResult.minAppVersion,
+ aResult.maxAppVersion, aResult.name, -1,
+ aResult.xpiURL, aResult.iconURL, "", "",
+ aResult.type);
+ var localItem = this._updater._emDS.getItemForID(remoteItem.id);
+ if (this._updater._writeVersionUpdates)
+ this._updater._applyVersionUpdates(localItem, remoteItem);
+ }
+ catch (e) { }
+
+ this._os.notifyObservers(remoteItem,
+ "Version:Extension:Item-Ended",
+ "");
+
+ this._updater._checkForDone(this._serviceURI);
+ },
+
/////////////////////////////////////////////////////////////////////////////
// nsIWSDLLoadListener
onLoad: function nsExtensionItemUpdater_onLoad (aProxy)
{
this._proxy = aProxy;
this._proxy.setListener(this);
- this._checkForUpdates();
+ this.checkForUpdates(this._updater._updateMode);
+
+ // Also perform any queued operations that were waiting on the WSDL
+ // proxy to load
+ for (var i = 0; i < this._pendingTransactions.length; ++i)
+ this.checkForUpdates(this._pendingTransactions);
},
onError: function nsExtensionItemUpdater_onError (aStatus, aMessage)
{
- this._os.notifyObservers(null, "Update:Extension:Item-Error", aStatus.toString());
+ dump("*** status = " + aStatus + ", message = " + aMessage + "\n");
+ this._os.notifyObservers(null,
+ this._updater._getMessage("Item-Error"),
+ aStatus.toString());
- for (var i = 0; i < this._items.length; ++i) {
- if (!this._items[i].updateRDF)
- this._checkForDone();
+ for (var i = 0; i < this._updater._items.length; ++i) {
+ var item = this._updater._items[i];
+ if ((!item.updateRDF && !item.updateService) ||
+ (item.updateService == this._serviceURI)) {
+ this._updater._checkForDone(this._serviceURI);
+ }
+ }
+ }
+};
+
+function nsRDFItemUpdater(aUpdater)
+{
+ this._rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
+ .getService(Components.interfaces.nsIRDFService);
+ this._os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ this._updater = aUpdater;
+}
+
+nsRDFItemUpdater.prototype = {
+ _rdf : null,
+ _os : null,
+ _updater : null,
+ _updateMode : 0,
+
+ checkForUpdates: function (aItem, aUpdateMode)
+ {
+ this._updateMode = aUpdateMode;
+
+ var dsURI = aItem.updateRDF;
+ dsURI = dsURI.replace(/%ITEM_ID%/g, aItem.id);
+ dsURI = dsURI.replace(/%ITEM_VERSION%/g, aItem.version);
+ dsURI = dsURI.replace(/%APP_ID%/g, this._updater._appID);
+ dsURI = dsURI.replace(/%APP_VERSION%/g, this._updater._appVersion);
+ var ds = this._rdf.GetDataSource(dsURI);
+ var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource)
+ if (rds.loaded)
+ this.onDatasourceLoaded(ds, aItem);
+ else {
+ var sink = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
+ sink.addXMLSinkObserver(new nsExtensionUpdateXMLRDFDSObserver(this, aItem));
}
},
-
+
onDatasourceLoaded: function nsExtensionItemUpdater_onDatasourceLoaded (aDatasource, aLocalItem)
{
///////////////////////////////////////////////////////////////////////////
// The extension update RDF file looks something like this:
- //
- // 5.0
- //
- //
- //
- // {GUID}
- // 0.8
- // 1.0
- //
- //
- //
- //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // 5.0
+ // http://www.mysite.com/myext-50.xpi
+ //
+ //
+ //
+ // 4.9
+ //
+ //
+ // {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+ // 0.9
+ // 1.0
+ // http://www.mysite.com/myext-49.xpi
+ //
+ //
+ //
//
// If we get here because the following happened:
// 1) User was using Firefox 0.9 with ExtensionX 0.5 (minVersion 0.8,
@@ -2820,212 +3213,183 @@ nsExtensionItemUpdater.prototype = {
// installed ExtensionX (0.5) is freshened with the new maxVersion,
// and we advance to the next item WITHOUT any download/install
// updates.
- // TODO: write logic to do this for the custom RDF case and for the
- // version check service case.
// Parse the response RDF
- var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
- .getService(Components.interfaces.nsIRDFService);
- var versionArc = rdf.GetResource(EM_NS("version"));
- var updateLinkArc = rdf.GetResource(EM_NS("updateLink"));
- var targetAppArc = rdf.GetResource(EM_NS("targetApplication"));
- var minVersionArc = rdf.GetResource(EM_NS("minVersion"));
- var maxVersionArc = rdf.GetResource(EM_NS("maxVersion"));
- var idArc = rdf.GetResource(EM_NS("id"));
- var extensionRes = rdf.GetResource(getItemPrefix(aLocalItem.type) + aLocalItem.id);
+ function UpdateData() {};
+ UpdateData.prototype = { version: "0.0", updateLink: null,
+ minVersion: "0.0", maxVersion: "0.0" };
- var version;
+ var versionUpdate = new UpdateData();
+ var newestUpdate = new UpdateData();
+
+ // Firefox 1.0RC1+ update.rdf format
+ if (this._updateMode == nsIExtensionManager.UPDATE_MODE_NORMAL) {
+ // Look for newer versions too
+ this._parseV20UpdateInfo(aDatasource, aLocalItem, newestUpdate, false);
+ if (!newestUpdate.updateLink) {
+ // Firefox 0.9 update.rdf format - does not contain any metadata
+ // that can be used for version updates, so performed in the "all updates"
+ // mode only.
+ this._parseV10UpdateInfo(aDatasource, aLocalItem, newestUpdate);
+ }
+ }
+ else
+ this._parseV20UpdateInfo(aDatasource, aLocalItem, versionUpdate, true);
+
+ if (this._updateMode == nsIExtensionManager.UPDATE_MODE_VERSION) {
+ var remoteItem = null;
+ var result = this._updater._versionChecker.compare(versionUpdate.version,
+ aLocalItem.version);
+ if (result == 0) {
+ // Local version exactly matches the "Version Update" remote version,
+ // Apply changes into local datasource.
+ remoteItem = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ remoteItem.init(aLocalItem.id,
+ versionUpdate.version,
+ versionUpdate.minVersion,
+ versionUpdate.maxVersion,
+ aLocalItem.name,
+ -1, "", "", "", "",
+ aLocalItem.type);
+ if (this._updater._isValidUpdate(aLocalItem, remoteItem) &&
+ this._updater._writeVersionUpdates) {
+ this._updater._applyVersionUpdates(aLocalItem, remoteItem);
+ remoteItem = null;
+ }
+ }
+ }
+ else {
+ remoteItem = Components.classes["@mozilla.org/updates/item;1"]
+ .createInstance(Components.interfaces.nsIUpdateItem);
+ remoteItem.init(aLocalItem.id,
+ newestUpdate.version,
+ newestUpdate.minVersion,
+ newestUpdate.maxVersion,
+ aLocalItem.name,
+ -1, newestUpdate.updateLink, "", "", "",
+ aLocalItem.type);
+ if (this._updater._isValidUpdate(aLocalItem, remoteItem))
+ ++this._updater._updateCount;
+ else
+ remoteItem = null;
+ }
+
+ this._os.notifyObservers(remoteItem, this._updater._getMessage("Item-Ended"), "");
+
+ // Only one call of this._updater._checkForDone is needed for RDF
+ // responses, since there is only one response per item.
+ this._updater._checkForDone(null);
+ },
+
+ // Parses Firefox 0.9 update.rdf format
+ _parseV10UpdateInfo: function nsExtensionItemUpdater__parseV10UpdateInfo (aDataSource, aLocalItem, aUpdateData)
+ {
+ var extensionRes = this._rdf.GetResource(getItemPrefix(aLocalItem.type) + aLocalItem.id);
+
+ aUpdateData.version = this._getPropertyFromResource(aDataSource, extensionRes,
+ "version", aLocalItem);
+ aUpdateData.updateLink = this._getPropertyFromResource(aDataSource, extensionRes,
+ "updateLink", aLocalItem);
+ },
+
+ // Get a compulsory property from a resource. Reports an error if the
+ // property was not present.
+ _getPropertyFromResource: function nsExtensionItemUpdater__getPropertyFromResource (aDataSource,
+ aSourceResource,
+ aProperty,
+ aLocalItem)
+ {
+ var rv;
try {
- version = stringData(aDatasource.GetTarget(extensionRes, versionArc, true));
- if (version == "--")
+ var property = this._rdf.GetResource(EM_NS(aProperty));
+ rv = stringData(aDataSource.GetTarget(aSourceResource, property, true));
+ if (rv == "--")
throw Components.results.NS_ERROR_FAILURE;
}
catch (e) {
// Report an error if the update manifest is incomplete
this.onDatasourceError(aLocalItem, "malformed-rdf");
- // XXXben show console message
- return;
+ // XXXben show console message "aProperty" not found on aSourceResource.
+ return null;
}
+ return rv;
+ },
+
+ // Parses Firefox 1.0RC1+ update.rdf format
+ _parseV20UpdateInfo: function nsExtensionItemUpdater__parseV20UpdateInfo (aDataSource,
+ aLocalItem,
+ aUpdateData,
+ aVersionUpdatesOnly)
+ {
+ var extensionRes = this._rdf.GetResource(getItemPrefix(aLocalItem.type) + aLocalItem.id);
- var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
- .getService(Components.interfaces.nsIVersionChecker);
- var pref = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- var appID = pref.getCharPref(PREF_EM_APP_ID);
- var updateLink = null;
+ var updatesArc = this._rdf.GetResource(EM_NS("updates"));
+ var updates = aDataSource.GetTarget(extensionRes, updatesArc, true);
+
try {
- var targetApps = aDatasource.GetTargets(extensionRes, targetAppArc, true);
- while (targetApps.hasMoreElements()) {
- var targetApp = targetApps.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
- if (targetApp) {
- var id = stringData(aDatasource.GetTarget(targetApp, idArc, true));
- if (id != appID) // Different target application
- continue;
-
- var minVersion = "";
- var maxVersion = "";
- try {
- minVersion = stringData(aDatasource.GetTarget(targetApp, minVersionArc, true));
- }
- catch (e) { }
- try {
- maxVersion = stringData(aDatasource.GetTarget(targetApp, maxVersionArc, true));
- }
- catch (e) { };
+ updates = updates.QueryInterface(Components.interfaces.nsIRDFResource);
+ }
+ catch (e) { return; }
+
+ var cu = Components.classes["@mozilla.org/rdf/container-utils;1"]
+ .getService(Components.interfaces.nsIRDFContainerUtils);
+ if (cu.IsContainer(aDataSource, updates)) {
+ var c = Components.classes["@mozilla.org/rdf/container;1"]
+ .getService(Components.interfaces.nsIRDFContainer);
+ c.Init(aDataSource, updates);
- // Either the new version wasn't compatible with the installed version of
- // Firefox, or the version is the same and includes only a maxVersion rev.
- var remoteItem = Components.classes["@mozilla.org/updates/item;1"]
- .createInstance(Components.interfaces.nsIUpdateItem);
- remoteItem.init(aLocalItem.id, version, minVersion, maxVersion, aLocalItem.name,
- -1, "", "", "", aLocalItem.type);
- if (!this._needsUpdate(aLocalItem, remoteItem)) {
- return;
- }
- else {
- // Get the update link for this target application...
- updateLink = stringData(aDatasource.GetTarget(targetApp, updateLinkArc, true));
- }
- }
- }
- }
- catch (e) {
- dump("*** eee! " + e + "\n");
- dump("*** nsExtensionItemUpdater::onDatasourceLoaded - falling back to 0.9 compatible update.rdf format...\n");
- updateLink = null;
- }
-
- if (!updateLink) {
- try {
- updateLink = stringData(aDatasource.GetTarget(extensionRes, updateLinkArc, true));
- if (updateLink == "--")
- throw Components.results.NS_ERROR_FAILURE;
- }
- catch (e) {
- // Report an error if the update manifest is incomplete
- this.onDatasourceError(aItem, "malformed-rdf");
- // XXXben show console message
- return;
+ // In "all update types" mode, we look for newer versions, starting with the
+ // current installed version.
+ if (!aVersionUpdatesOnly)
+ aUpdateData.version = aLocalItem.version;
+
+ var versions = c.GetElements();
+ while (versions.hasMoreElements()) {
+ // There are two different methodologies for collecting version
+ // information depending on whether or not we've bene invoked in
+ // "version updates only" mode or "version+newest" mode.
+ var version = versions.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
+ this._parseV20Update(aDataSource, version, aLocalItem, aUpdateData, aVersionUpdatesOnly);
+ if (aVersionUpdatesOnly && aUpdateData.updateLink)
+ break;
}
}
-
- // Check to see if this is a newer version.
- var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
- .getService(Components.interfaces.nsIVersionChecker);
- if (versionChecker.compare(aLocalItem.version, version) < 0) {
- // Construct an update item and pass it to observers.
- var remoteItem = Components.classes["@mozilla.org/updates/item;1"]
- .createInstance(Components.interfaces.nsIUpdateItem);
- remoteItem.init(aLocalItem.id, version, "", "", aLocalItem.name,
- -1, updateLink, "", "", aLocalItem.type);
- this._os.notifyObservers(remoteItem, "Update:Extension:Item-Ended", "");
- ++this._updateCount;
+ },
+
+ _parseV20Update: function nsExtensionItemUpdater__parseV20Update (aDataSource,
+ aUpdateResource,
+ aLocalItem,
+ aUpdateData,
+ aVersionUpdatesOnly)
+ {
+ var version = this._getPropertyFromResource(aDataSource, aUpdateResource,
+ "version", aLocalItem);
+ var taArc = this._rdf.GetResource(EM_NS("targetApplication"));
+ var targetApps = aDataSource.GetTargets(aUpdateResource, taArc, true);
+ while (targetApps.hasMoreElements()) {
+ var targetApp = targetApps.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
+ var id = this._getPropertyFromResource(aDataSource, targetApp, "id", aLocalItem);
+ if (id != this._updater._appID)
+ continue;
+
+ var result = this._updater._versionChecker.compare(version, aLocalItem.version);
+ if (aVersionUpdatesOnly ? result == 0 : result > 0) {
+ aUpdateData.version = version;
+ aUpdateData.updateLink = this._getPropertyFromResource(aDataSource, targetApp, "updateLink", aLocalItem);
+ aUpdateData.minVersion = this._getPropertyFromResource(aDataSource, targetApp, "minVersion", aLocalItem);
+ aUpdateData.maxVersion = this._getPropertyFromResource(aDataSource, targetApp, "maxVersion", aLocalItem);
+ }
}
-
- this._checkForDone();
},
onDatasourceError: function nsExtensionItemUpdater_onDatasourceError (aItem, aError)
{
- this._os.notifyObservers(aItem, "Update:Extension:Item-Error", aError);
-
- this._checkForDone();
- },
-
- _needsUpdate: function nsExtensionItemUpdater__needsUpdate (aLocalItem, aRemoteItem)
- {
- var versionChecker = Components.classes["@mozilla.org/updates/version-checker;1"]
- .getService(Components.interfaces.nsIVersionChecker);
- var pref = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- var appID = pref.getCharPref(PREF_EM_APP_ID);
- var appExtensionsVersion = pref.getCharPref(PREF_EM_APP_EXTENSIONS_VERSION);
-
- // Check if the update will only run on a newer version of Firefox.
- if (aRemoteItem.minAppVersion &&
- versionChecker.compare(appExtensionsVersion, aRemoteItem.minAppVersion) < 0)
- return false;
-
- // Check if the update will only run on an older version of Firefox.
- if (aRemoteItem.maxAppVersion &&
- versionChecker.compare(appExtensionsVersion, aRemoteItem.maxAppVersion) > 0)
- return false;
-
- // Locally installed Extension version matches remote extension
- // version, and new maxVersion remotely specified
- if (aRemoteItem.maxAppVersion &&
- versionChecker.compare(aLocalItem.version, aRemoteItem.version) == 0) {
- var targetAppInfo = this._emDS.getTargetApplicationInfo(aLocalItem.id);
- if (versionChecker.compare(targetAppInfo.maxVersion, aRemoteItem.maxAppVersion) < 0) {
- // Remotely specified maxVersion is newer than the maxVersion
- // for the installed Extension. Apply that change to the datasource.
- this._emDS.setTargetApplicationInfo(aLocalItem.id,
- aRemoteItem.minAppVersion,
- aRemoteItem.maxAppVersion);
-
- // If we got here through |checkForMismatches|, this extension has
- // already been disabled, re-enable it.
- if (this._emDS.getItemProperty(aLocalItem.id, "disabled") == "true")
- this._em.enableExtension(aLocalItem.id);
-
- // Notify that update is complete for this item, pass "" as the update
- // link as there is no downloading to be done.
- this._os.notifyObservers(aRemoteItem, "Update:Extension:Item-Ended", "");
- ++this._updateCount;
- return false;
- }
- }
- return true;
- },
-
- getNewestExtensionCallback: function nsExtensionItemUpdater_getNewestExtensionCallback (aResult)
- {
- try {
- aResult.name.toString(); // XXXben This is a lame hack to cause an exception to be
- // thrown for null values when there is no newer extension
- // or something else bad happens on the server that we
- // don't recognize.
- var remoteItem = Components.classes["@mozilla.org/updates/item;1"]
- .createInstance(Components.interfaces.nsIUpdateItem);
- remoteItem.init(aResult.id, aResult.version, aResult.minAppVersion,
- aResult.maxAppVersion, aResult.name, -1,
- aResult.updateURL, aResult.iconURL, "",
- aResult.type);
- var localItem = this._emDS.getItemForID(remoteItem.id);
- if (!this._needsUpdate(localItem, remoteItem)) {
- return;
- }
- else {
- this._os.notifyObservers(remoteItem, "Update:Extension:Item-Ended", "");
- ++this._updateCount;
- }
- }
- catch (e) {
- }
-
- this._checkForDone();
- },
-
- _checkForDone: function nsExtensionItemUpdater__checkForDone ()
- {
- if (--this._count == 0) {
- var pref = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- pref.setIntPref(PREF_UPDATE_COUNT, this._updateCount);
-
- this._os.notifyObservers(null, "Update:Extension:Ended", "");
- }
- },
-
- /////////////////////////////////////////////////////////////////////////////
- // nsISupports
- QueryInterface: function nsExtensionItemUpdater_QueryInterface (aIID)
- {
- if (!aIID.equals(Components.interfaces.nsIExtensionItemUpdater) &&
- !aIID.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
+ this._os.notifyObservers(aItem,
+ this._updater._getMessage("Item-Error"),
+ aError);
+ this._updater._checkForDone(null);
+ }
};
@@ -3106,7 +3470,7 @@ nsExtensionsDataSource.prototype = {
.getService(Components.interfaces.nsIPrefBranch);
var appVersion = pref.getCharPref(PREF_EM_APP_EXTENSIONS_VERSION);
var appID = pref.getCharPref(PREF_EM_APP_ID);
-
+
var targets = aDS.GetTargets(aSource, this._emR("targetApplication"), true);
var idRes = this._emR("id");
var minVersionRes = this._emR("minVersion");
@@ -3126,7 +3490,7 @@ nsExtensionsDataSource.prototype = {
}
return false;
},
-
+
getIncompatibleItemList: function nsExtensionsDataSource_getIncompatibleItemList (aAppID, aAppVersion, aItemType)
{
var items = [];
@@ -3146,7 +3510,7 @@ nsExtensionsDataSource.prototype = {
.createInstance(Components.interfaces.nsIUpdateItem);
item.init(id, this._getItemProperty(e, "version"), "", "",
this._getItemProperty(e, "name"),
- -1, "", "", this._getItemProperty(e, "updateURL"),
+ -1, "", "", this._getItemProperty(e, "updateURL"), "",
itemType);
items.push(item);
}
@@ -3164,7 +3528,7 @@ nsExtensionsDataSource.prototype = {
item.init(aItemID, this.getItemProperty(aItemID, "version"), "", "",
this.getItemProperty(aItemID, "name"),
-1, "", "", this.getItemProperty(aItemID, "updateURL"),
- aType); // XXXben - potential bug! discover real type!
+ "", aType); // XXXben - potential bug! discover real type!
items.push(item);
}
else {
@@ -3183,8 +3547,8 @@ nsExtensionsDataSource.prototype = {
.createInstance(Components.interfaces.nsIUpdateItem);
item.init(id, this.getItemProperty(id, "version"), "", "",
this.getItemProperty(id, "name"),
- -1, "", "",
- this.getItemProperty(id, "updateURL"), getItemType(roots[i]));
+ -1, "", "", this.getItemProperty(id, "updateURL"),
+ "", getItemType(roots[i]));
items.push(item);
}
}
@@ -3233,18 +3597,22 @@ nsExtensionsDataSource.prototype = {
{
var item = Components.classes["@mozilla.org/updates/item;1"]
.createInstance(Components.interfaces.nsIUpdateItem);
- var targetAppInfo = this.getTargetApplicationInfo(aItemID);
+
var r = this._getResourceForItem(aItemID);
+ if (!r)
+ return null;
+
+ var targetAppInfo = this.getTargetApplicationInfo(aItemID, this, getItemType(r.Value));
item.init(aItemID,
- this.getItemProperty(id, "version"),
+ this.getItemProperty(aItemID, "version"),
targetAppInfo.minVersion,
targetAppInfo.maxVersion,
- this.getItemProperty(id, "name"),
+ this.getItemProperty(aItemID, "name"),
-1,
"", /* XPI Update URL */
- this.getItemProperty(id, "iconURL"),
- this.getItemProperty(id, "updateURL"),
- getItemType(r.Value));
+ this.getItemProperty(aItemID, "iconURL"),
+ this.getItemProperty(aItemID, "updateURL"),
+ "", getItemType(r.Value));
return item;
},
@@ -3290,46 +3658,68 @@ nsExtensionsDataSource.prototype = {
return null;
},
- getTargetApplicationInfo: function nsExtensionsDataSource_getTargetApplicationInfo (aExtensionID)
+ getTargetApplicationInfo: function nsExtensionsDataSource_getTargetApplicationInfo (aExtensionID, aDataSource, aType)
{
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var appID = pref.getCharPref(PREF_EM_APP_ID);
- var r = this._getResourceForItem(aExtensionID);
- var targetApps = this.GetTargets(r, this._emR("targetApplication"), true);
+ var r = this._rdf.GetResource(getItemPrefix(aType) + aExtensionID);
+ var targetApps = aDataSource.GetTargets(r, this._emR("targetApplication"), true);
+ if (!targetApps.hasMoreElements()) {
+ r = this._rdf.GetResource("urn:mozilla:install-manifest");
+ targetApps = aDataSource.GetTargets(r, this._emR("targetApplication"), true);
+ }
while (targetApps.hasMoreElements()) {
var targetApp = targetApps.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
if (targetApp) {
- var id = stringData(this.GetTarget(targetApp, this._emR("id"), true));
- if (id != appID) // Different target application
+ try {
+ var id = stringData(aDataSource.GetTarget(targetApp, this._emR("id"), true));
+ if (id != appID) // Different target application
+ continue;
+
+ return { minVersion: stringData(aDataSource.GetTarget(targetApp, this._emR("minVersion"), true)),
+ maxVersion: stringData(aDataSource.GetTarget(targetApp, this._emR("maxVersion"), true)) };
+ }
+ catch (e) {
continue;
-
- return { minVersion: stringData(this.GetTarget(targetApp, this._emR("minVersion"), true)),
- maxVersion: stringData(this.GetTarget(targetApp, this._emR("maxVersion"), true)) };
+ }
}
}
return null;
},
- setTargetApplicationInfo: function nsExtensionsDataSource_setTargetApplicationInfo(aExtensionID, aMinVersion, aMaxVersion)
+ setTargetApplicationInfo: function nsExtensionsDataSource_setTargetApplicationInfo(aExtensionID, aMinVersion,
+ aMaxVersion, aDataSource, aType)
{
+ var targetDataSource = aDataSource;
+ if (!targetDataSource)
+ targetDataSource = this;
+
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var appID = pref.getCharPref(PREF_EM_APP_ID);
- var r = this._getResourceForItem(aExtensionID);
- var targetApps = this.GetTargets(r, this._emR("targetApplication"), true);
+ var r = this._rdf.GetResource(getItemPrefix(aType) + aExtensionID);
+ var targetApps = targetDataSource.GetTargets(r, this._emR("targetApplication"), true);
+ if (!targetApps.hasMoreElements()) {
+ r = this._rdf.GetResource("urn:mozilla:install-manifest");
+ targetApps = aDataSource.GetTargets(r, this._emR("targetApplication"), true);
+ }
while (targetApps.hasMoreElements()) {
var targetApp = targetApps.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
if (targetApp) {
- var id = stringData(this.GetTarget(targetApp, this._emR("id"), true));
+ var id = stringData(targetDataSource.GetTarget(targetApp, this._emR("id"), true));
if (id != appID) // Different target application
continue;
- var isProfile = this.isProfileItem(aExtensionID);
- var ds = isProfile ? this._profileExtensions : this._appExtensions;
- this._setProperty(ds, targetApp, this._emR("minVersion"), this._emL(aMinVersion));
- this._setProperty(ds, targetApp, this._emR("maxVersion"), this._emL(aMaxVersion));
- this._flush(isProfile);
+ if (!aDataSource) {
+ var isProfile = this.isProfileItem(aExtensionID);
+ targetDataSource = isProfile ? this._profileExtensions : this._appExtensions;
+ }
+ this._setProperty(targetDataSource, targetApp, this._emR("minVersion"), this._emL(aMinVersion));
+ this._setProperty(targetDataSource, targetApp, this._emR("maxVersion"), this._emL(aMaxVersion));
+
+ if (!aDataSource)
+ this._flush(isProfile);
}
}
},
@@ -3412,8 +3802,8 @@ nsExtensionsDataSource.prototype = {
// Assert properties with single values
var singleProps = ["version", "name", "description", "creator", "homepageURL",
- "updateURL", "optionsURL", "aboutURL", "iconURL",
- "internalName"];
+ "updateURL", "updateService", "optionsURL", "aboutURL",
+ "iconURL", "internalName"];
// Global extensions and themes can also be locked (can't be removed or disabled).
if (!aIsProfile)
diff --git a/mozilla/toolkit/mozapps/update/content/errors.xul b/mozilla/toolkit/mozapps/update/content/errors.xul
index a56ce059c7e..4b3cc241545 100644
--- a/mozilla/toolkit/mozapps/update/content/errors.xul
+++ b/mozilla/toolkit/mozapps/update/content/errors.xul
@@ -64,9 +64,12 @@
for (var i = 0; i < items.length; ++i) {
if (items[i].error) {
var listitem = document.createElement("listitem");
- var errorString = xpinstallStrings.getString("error" + items[i].error);
- var label = updateStrings.getFormattedString("installErrorItemFormat",
- [items[i].name, errorString]);
+ try {
+ var errorString = xpinstallStrings.getString("error" + items[i].error);
+ var label = updateStrings.getFormattedString("installErrorItemFormat",
+ [items[i].name, errorString]);
+ }
+ catch (e) { label = items[i].name; }
listitem.setAttribute("label", label);
listbox.appendChild(listitem);
}
diff --git a/mozilla/toolkit/mozapps/update/content/update.js b/mozilla/toolkit/mozapps/update/content/update.js
index 847f4a3299f..fb97af3b144 100644
--- a/mozilla/toolkit/mozapps/update/content/update.js
+++ b/mozilla/toolkit/mozapps/update/content/update.js
@@ -83,14 +83,22 @@ var gUpdateWizard = {
this.shouldSuggestAutoChecking = (gSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) &&
!pref.getBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED);
- if (gSourceEvent == nsIUpdateService.SOURCE_EVENT_USER) {
- document.getElementById("mismatch").setAttribute("next", "checking");
- document.documentElement.advance();
+ if (gSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) {
+ var version = document.getElementById("version")
+ version.setAttribute("next", "mismatch");
}
gMismatchPage.init();
},
+ uninit: function ()
+ {
+ // Ensure all observers are unhooked, just in case something goes wrong or the
+ // user aborts.
+ gVersionPage.uninit();
+ gUpdatePage.uninit();
+ },
+
onWizardFinish: function ()
{
if (this.shouldSuggestAutoChecking) {
@@ -123,24 +131,8 @@ var gUpdateWizard = {
url.data = updates.appUpdateURL;
ary.AppendElement(url);
- function obs(aWindow)
- {
- this._win = aWindow;
- }
- obs.prototype = {
- _win: null,
- notify: function (aTimer)
- {
- this._win.focus();
- }
- };
-
- var win = ww.openWindow(null, "chrome://browser/content/browser.xul",
- "_blank", "chrome,all,dialog=no", ary);
- var timer = Components.classes["@mozilla.org/timer;1"]
- .createInstance(Components.interfaces.nsITimer);
- timer.initWithCallback(new obs(win), 100,
- Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ ww.openWindow(null, "chrome://browser/content/browser.xul",
+ "_blank", "chrome,all,dialog=no", ary);
#endif
// Clear the "app update available" pref as an interim amnesty assuming
@@ -257,6 +249,129 @@ var gUpdateWizard = {
}
};
+var gVersionPage = {
+ _completeCount: 0,
+ _messages: ["Version:Extension:Started",
+ "Version:Extension:Ended",
+ "Version:Extension:Item-Started",
+ "Version:Extension:Item-Ended",
+ "Version:Extension:Item-Error"],
+
+ onPageShow: function ()
+ {
+ gUpdateWizard.setButtonLabels(null, true,
+ "nextButtonText", true,
+ "cancelButtonText", true);
+ document.documentElement.getButton("next").focus();
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ for (var i = 0; i < this._messages.length; ++i)
+ os.addObserver(this, this._messages[i], false);
+
+ var em = Components.classes["@mozilla.org/extensions/manager;1"]
+ .getService(Components.interfaces.nsIExtensionManager);
+ em.update(gUpdateWizard.items, gUpdateWizard.items.length,
+ nsIExtensionManager.UPDATE_MODE_VERSION, true);
+ },
+
+ _destroyed: false,
+ uninit: function ()
+ {
+ if (this._destroyed)
+ return;
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+ for (var i = 0; i < this._messages.length; ++i)
+ os.removeObserver(this, this._messages[i]);
+
+ this._destroyed = true;
+ },
+
+ _totalCount: 0,
+ get totalCount()
+ {
+ if (!this._totalCount) {
+ this._totalCount = gUpdateWizard.items.length;
+ if (this._totalCount == 0) {
+ var em = Components.classes["@mozilla.org/extensions/manager;1"]
+ .getService(Components.interfaces.nsIExtensionManager);
+ var extensionCount = em.getItemList(null, nsIUpdateItem.TYPE_EXTENSION, {}).length;
+ var themeCount = em.getItemList(null, nsIUpdateItem.TYPE_THEME, {}).length;
+
+ this._totalCount = extensionCount + themeCount;
+ }
+ }
+ return this._totalCount;
+ },
+
+ observe: function (aSubject, aTopic, aData)
+ {
+ var canFinish = false;
+ switch (aTopic) {
+ case "Version:Extension:Started":
+ break;
+ case "Version:Extension:Item-Started":
+ break;
+ case "Version:Extension:Item-Ended":
+ if (aSubject) {
+ var item = aSubject.QueryInterface(Components.interfaces.nsIUpdateItem);
+ var updateStrings = document.getElementById("updateStrings");
+ var status = document.getElementById("checking.status");
+ var statusString = updateStrings.getFormattedString("checkingPrefix", [item.name]);
+ status.setAttribute("value", statusString);
+
+ if (gSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) {
+ // In mismatch mode it is sufficient to perform a version update
+ // on Extensions and Themes - a proper update check can occur later.
+ var ary = [];
+ for (var i = 0; i < gUpdateWizard.items.length; ++i) {
+ if (gUpdateWizard.items[i].id != item.id)
+ ary.push(gUpdateWizard.items[i]);
+ }
+ gUpdateWizard.items = ary;
+ }
+ }
+ ++this._completeCount;
+
+ // Update the Progress Bar
+ var progress = document.getElementById("checking.progress");
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
+
+ break;
+ case "Version:Extension:Item-Error":
+ ++this._completeCount;
+ var progress = document.getElementById("checking.progress");
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
+
+ break;
+ case "Version:Extension:Ended":
+ gVersionPage.uninit();
+
+ if (gUpdateWizard.items.length == 0) {
+ // We've resolved all compatibilities in this Version Update, so
+ // close up.
+ var updateStrings = document.getElementById("updateStrings");
+ var status = document.getElementById("checking.status");
+ status.setAttribute("value", updateStrings.getString("versionUpdateComplete"));
+
+ var closeTimer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ closeTimer.initWithCallback(this, 2000,
+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
+ break;
+ }
+ document.documentElement.advance();
+ break;
+ }
+ },
+
+ notify: function (aTimer)
+ {
+ window.close();
+ }
+};
var gMismatchPage = {
init: function ()
@@ -308,14 +423,37 @@ var gUpdatePage = {
updates.checkForUpdatesInternal(gUpdateWizard.items, gUpdateWizard.items.length,
gUpdateTypes, gSourceEvent);
},
-
+
+ _destroyed: false,
uninit: function ()
{
+ if (this._destroyed)
+ return;
+
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
for (var i = 0; i < this._messages.length; ++i)
os.removeObserver(this, this._messages[i]);
+
+ this._destroyed = true;
},
+
+ _totalCount: 0,
+ get totalCount()
+ {
+ if (!this._totalCount) {
+ this._totalCount = gUpdateWizard.items.length;
+ if (this._totalCount == 0) {
+ var em = Components.classes["@mozilla.org/extensions/manager;1"]
+ .getService(Components.interfaces.nsIExtensionManager);
+ var extensionCount = em.getItemList(null, nsIUpdateItem.TYPE_EXTENSION, {}).length;
+ var themeCount = em.getItemList(null, nsIUpdateItem.TYPE_THEME, {}).length;
+
+ this._totalCount = extensionCount + themeCount + 1;
+ }
+ }
+ return this._totalCount;
+ },
observe: function (aSubject, aTopic, aData)
{
@@ -326,13 +464,20 @@ var gUpdatePage = {
case "Update:Extension:Item-Started":
break;
case "Update:Extension:Item-Ended":
- var item = aSubject.QueryInterface(Components.interfaces.nsIUpdateItem);
- gUpdateWizard.itemsToUpdate.push(item);
+ if (aSubject) {
+ var item = aSubject.QueryInterface(Components.interfaces.nsIUpdateItem);
+ gUpdateWizard.itemsToUpdate.push(item);
+ var updateStrings = document.getElementById("updateStrings");
+ var status = document.getElementById("checking.status");
+ var statusString = updateStrings.getFormattedString("checkingPrefix", [item.name]);
+ status.setAttribute("value", statusString);
+ }
++this._completeCount;
-
+
+ // Update the Progress Bar
var progress = document.getElementById("checking.progress");
- progress.value = Math.ceil(this._completeCount / gUpdateWizard.itemsToUpdate.length) * 100;
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
break;
case "Update:Extension:Item-Error":
@@ -346,6 +491,10 @@ var gUpdatePage = {
gUpdateWizard.errorItems.push(gUpdateWizard.items[i]);
}
}
+ ++this._completeCount;
+ var progress = document.getElementById("checking.progress");
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
+
break;
case "Update:Extension:Ended":
// If we were passed a set of extensions/themes/other to update, this
@@ -362,6 +511,9 @@ var gUpdatePage = {
break;
case "Update:App:Error":
gUpdateWizard.errorOnApp = true;
+ ++this._completeCount;
+ var progress = document.getElementById("checking.progress");
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
break;
case "Update:App:Ended":
// The "Updates Found" page of the update wizard needs to know if it there are app
@@ -383,9 +535,13 @@ var gUpdatePage = {
"", "",
brandShortName, -1, updates.appUpdateURL,
"chrome://mozapps/skin/update/icon32.png",
- "", nsIUpdateItem.TYPE_APP);
+ "", "", nsIUpdateItem.TYPE_APP);
gUpdateWizard.itemsToUpdate.splice(0, 0, item);
}
+
+ ++this._completeCount;
+ var progress = document.getElementById("checking.progress");
+ progress.value = Math.ceil((this._completeCount / this.totalCount) * 100);
break;
}
@@ -417,7 +573,7 @@ var gFoundPage = {
var item = gUpdateWizard.itemsToUpdate[i];
updateitem.name = item.name + " " + item.version;
- updateitem.url = item.updateURL;
+ updateitem.url = item.xpiURL;
// If we have an App entry in the list, check it and uncheck
// the others since the two are mutually exclusive installs.
diff --git a/mozilla/toolkit/mozapps/update/content/update.xul b/mozilla/toolkit/mozapps/update/content/update.xul
index 3cdd621333d..4f12439e2d9 100644
--- a/mozilla/toolkit/mozapps/update/content/update.xul
+++ b/mozilla/toolkit/mozapps/update/content/update.xul
@@ -50,7 +50,8 @@
@@ -62,6 +63,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -87,9 +104,13 @@
-
+
+
+
+
+
diff --git a/mozilla/toolkit/mozapps/update/content/updates.xml b/mozilla/toolkit/mozapps/update/content/updates.xml
index 39d6fda97ad..8e18409fc4d 100644
--- a/mozilla/toolkit/mozapps/update/content/updates.xml
+++ b/mozilla/toolkit/mozapps/update/content/updates.xml
@@ -24,6 +24,8 @@
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "Update:Ended");
+ os.removeObserver(this, "Update:Extension:Item-Ended");
+ os.removeObserver(this, "Update:App:Ended");
]]>
@@ -33,6 +35,8 @@
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "Update:Ended", false);
+ os.addObserver(this, "Update:Extension:Item-Ended", false);
+ os.addObserver(this, "Update:App:Ended", false);
this.refreshData();
]]>
@@ -45,8 +49,12 @@
diff --git a/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl b/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
index 4353413a7fd..41bb57992d2 100644
--- a/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
+++ b/mozilla/toolkit/mozapps/update/public/nsIUpdateService.idl
@@ -50,9 +50,10 @@ interface nsIUpdateItem : nsISupports
readonly attribute string maxAppVersion;
readonly attribute wstring name;
readonly attribute long row;
- readonly attribute wstring updateURL;
+ readonly attribute wstring xpiURL;
readonly attribute wstring iconURL;
readonly attribute wstring updateRDF;
+ readonly attribute wstring updateService;
const unsigned short TYPE_ANY = 0x01;
const unsigned short TYPE_APP = 0x02;
@@ -67,7 +68,8 @@ interface nsIUpdateItem : nsISupports
void init(in string aID, in string aVersion, in string aMinAppVersion,
in string aMaxAppVersion, in wstring aName,
in long aRow, in wstring aUpdateURL, in wstring aIconURL,
- in wstring aUpdateRDF, in long aType);
+ in wstring aUpdateRDF, in wstring aUpdateService,
+ in long aType);
readonly attribute wstring objectSource;
};
diff --git a/mozilla/toolkit/mozapps/update/src/nsBackgroundUpdateService.js b/mozilla/toolkit/mozapps/update/src/nsBackgroundUpdateService.js
index a600bb462ee..1557b387b8f 100644
--- a/mozilla/toolkit/mozapps/update/src/nsBackgroundUpdateService.js
+++ b/mozilla/toolkit/mozapps/update/src/nsBackgroundUpdateService.js
@@ -43,22 +43,31 @@ const PREF_UPDATE_APP_UPDATESAVAILABLE = "update.app.updatesAvailable";
const PREF_UPDATE_APP_UPDATEVERSION = "update.app.updateVersion";
const PREF_UPDATE_APP_UPDATEDESCRIPTION = "update.app.updateDescription";
const PREF_UPDATE_APP_UPDATEURL = "update.app.updateURL";
+const PREF_UPDATE_APP_INTERVAL = "update.app.interval";
+const PREF_UPDATE_APP_LASTUPDATEDATE = "update.app.lastUpdateDate";
const PREF_UPDATE_SHOW_SLIDING_NOTIFICATION = "update.showSlidingNotification";
const PREF_UPDATE_EXTENSIONS_ENABLED = "update.extensions.enabled";
const PREF_UPDATE_EXTENSIONS_AUTOUPDATE = "update.extensions.autoUpdate";
const PREF_UPDATE_EXTENSIONS_COUNT = "update.extensions.count";
+const PREF_UPDATE_EXTENSIONS_INTERVAL = "update.extensions.interval";
+const PREF_UPDATE_EXTENSIONS_LASTUPDATEDATE = "update.extensions.lastUpdateDate";
+const PREF_UPDATE_EXTENSIONS_SEVERITY_THRESHOLD = "update.extensions.severity.threshold";
const PREF_UPDATE_INTERVAL = "update.interval";
-const PREF_UPDATE_LASTUPDATEDATE = "update.lastUpdateDate";
const PREF_UPDATE_SEVERITY = "update.severity";
-const nsIUpdateService = Components.interfaces.nsIUpdateService;
-const nsIUpdateItem = Components.interfaces.nsIUpdateItem;
+const nsIExtensionManager = Components.interfaces.nsIExtensionManager;
+const nsIUpdateService = Components.interfaces.nsIUpdateService;
+const nsIUpdateItem = Components.interfaces.nsIUpdateItem;
const UPDATED_EXTENSIONS = 0x01;
const UPDATED_APP = 0x02;
+const SEVERITY_HIGH = 2;
+const SEVERITY_MEDIUM = 1;
+const SEVERITY_LOW = 0;
+
function nsUpdateService()
{
this._pref = Components.classes["@mozilla.org/preferences-service;1"]
@@ -69,6 +78,8 @@ function nsUpdateService()
pbi.addObserver(PREF_UPDATE_APP_ENABLED, this, false);
pbi.addObserver(PREF_UPDATE_EXTENSIONS_ENABLED, this, false);
pbi.addObserver(PREF_UPDATE_INTERVAL, this, false);
+ pbi.addObserver(PREF_UPDATE_APP_INTERVAL, this, false);
+ pbi.addObserver(PREF_UPDATE_EXTENSIONS_INTERVAL, this, false);
// Observe xpcom-shutdown to unhook pref branch observers above to avoid
// shutdown leaks.
@@ -78,7 +89,6 @@ function nsUpdateService()
}
nsUpdateService.prototype = {
- _timer: null,
_pref: null,
_updateObserver: null,
_appUpdatesEnabled: true,
@@ -95,16 +105,8 @@ nsUpdateService.prototype = {
this._extUpdatesEnabled = this._pref.getBoolPref(PREF_UPDATE_EXTENSIONS_ENABLED);
if (!this._appUpdatesEnabled && !this._extUpdatesEnabled)
return;
-
- var interval = this._pref.getIntPref(PREF_UPDATE_INTERVAL);
- var lastUpdateTime = this._pref.getIntPref(PREF_UPDATE_LASTUPDATEDATE);
- var timeSinceLastCheck = lastUpdateTime ? this._nowInMilliseconds - lastUpdateTime : 0;
- if (timeSinceLastCheck > interval) {
- this.checkForUpdatesInternal([], 0, nsIUpdateItem.TYPE_ANY,
- nsIUpdateService.SOURCE_EVENT_BACKGROUND);
- }
- else
- this._makeTimer(interval - timeSinceLastCheck);
+
+ this._makeTimer(this._pref.getIntPref(PREF_UPDATE_INTERVAL));
},
checkForUpdates: function nsUpdateService_checkForUpdates (aItems, aItemCount, aUpdateTypes, aSourceEvent, aParentWindow)
@@ -127,10 +129,15 @@ nsUpdateService.prototype = {
for (var i = 0; i < aItems.length; ++i)
ary.AppendElement(aItems[i]);
+ var features = "chrome,centerscreen";
+ if (aSourceEvent == nsIUpdateService.SOURCE_EVENT_MISMATCH) {
+ features += ",modal"; // Must block in mismatch mode since there's
+ // no main evt loop yet.
+ }
// This *must* be modal so as not to break startup! This code is invoked before
// the main event loop is initiated (via checkForMismatches).
ww.openWindow(aParentWindow, "chrome://mozapps/content/update/update.xul",
- "", "chrome,modal,centerscreen", ary);
+ "", features, ary);
break;
case nsIUpdateService.SOURCE_EVENT_BACKGROUND:
// Rather than show a UI, call the checkForUpdates function directly here.
@@ -173,6 +180,7 @@ nsUpdateService.prototype = {
var dsURI = this._pref.getComplexValue(PREF_UPDATE_APP_URI,
Components.interfaces.nsIPrefLocalizedString).data;
+
var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
var ds = rdf.GetDataSource(dsURI);
@@ -187,21 +195,29 @@ nsUpdateService.prototype = {
}
if (!(aUpdateTypes & nsIUpdateItem.TYPE_APP)) { // TYPE_EXTENSION, TYPE_ANY, etc.
if (this._canUpdate(this._extUpdatesEnabled, aSourceEvent)) {
+ os.addObserver(this._updateObserver, "Update:Extension:Started", false);
os.addObserver(this._updateObserver, "Update:Extension:Item-Ended", false);
os.addObserver(this._updateObserver, "Update:Extension:Ended", false);
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
- em.update(aItems, aItems.length);
+ // We have to explicitly perform the Version update here in background
+ // mode because there is no update UI to kick it off.
+ if (aSourceEvent == nsIUpdateService.SOURCE_EVENT_BACKGROUND) {
+ em.update(aItems, aItems.length,
+ nsIExtensionManager.UPDATE_MODE_VERSION, true);
+ }
+ em.update(aItems, aItems.length,
+ nsIExtensionManager.UPDATE_MODE_NORMAL, false);
}
}
if (aSourceEvent == nsIUpdateService.SOURCE_EVENT_BACKGROUND &&
(this._appUpdatesEnabled || this._extUpdatesEnabled)) {
- this._pref.setIntPref(PREF_UPDATE_LASTUPDATEDATE, this._nowInMilliseconds);
-
- // If this was a background update, reset timer.
- this._makeTimer(this._pref.getIntPref(PREF_UPDATE_INTERVAL));
+ if (aUpdateTypes & nsIUpdateItem.TYPE_ADDON)
+ this._pref.setIntPref(PREF_UPDATE_EXTENSIONS_LASTUPDATEDATE, this._nowInMilliseconds / 1000);
+ if (aUpdateTypes & nsIUpdateItem.TYPE_APP)
+ this._pref.setIntPref(PREF_UPDATE_APP_LASTUPDATEDATE, this._nowInMilliseconds / 1000);
}
},
@@ -266,8 +282,18 @@ nsUpdateService.prototype = {
Components.interfaces.nsISupportsString,
descStr);
}
- else
+ else {
this._clearAppUpdatePrefs();
+
+ // Lower the severity to reflect the fact that there are now only Extension/
+ // Theme updates available
+ var newCount = this._pref.getIntPref(PREF_UPDATE_EXTENSIONS_COUNT);
+ var threshold = this._pref.getIntPref(PREF_UPDATE_EXTENSIONS_SEVERITY_THRESHOLD);
+ if (newCount >= threshold)
+ this._pref.setIntPref(PREF_UPDATE_SEVERITY, SEVERITY_MEDIUM);
+ else
+ this._pref.setIntPref(PREF_UPDATE_SEVERITY, SEVERITY_LOW);
+ }
// The Update Wizard uses this notification to determine that the application
// update process is now complete.
@@ -347,12 +373,29 @@ nsUpdateService.prototype = {
/////////////////////////////////////////////////////////////////////////////
// nsITimerCallback
- notify: function nsUpdateService_notify (aTimer)
+ _shouldUpdate: function nsUpdateService__shouldUpdate (aIntervalPref, aLastCheckPref)
{
- this.checkForUpdatesInternal([], 0, nsIUpdateItem.TYPE_ANY,
- nsIUpdateService.SOURCE_EVENT_BACKGROUND);
+ var interval = this._pref.getIntPref(aIntervalPref);
+ var lastUpdateTime = this._pref.getIntPref(aLastCheckPref);
+ return ((Math.round(this._nowInMilliseconds/1000) - lastUpdateTime) > interval);
},
+ notify: function nsUpdateService_notify (aTimer)
+ {
+ var types = 0;
+ if (this._shouldUpdate(PREF_UPDATE_EXTENSIONS_INTERVAL,
+ PREF_UPDATE_EXTENSIONS_LASTUPDATEDATE)) {
+ types |= nsIUpdateItem.TYPE_ADDON;
+ }
+ if (this._shouldUpdate(PREF_UPDATE_APP_INTERVAL,
+ PREF_UPDATE_APP_LASTUPDATEDATE)) {
+ types |= nsIUpdateItem.TYPE_APP;
+ }
+ if (types)
+ this.checkForUpdatesInternal([], 0, types,
+ nsIUpdateService.SOURCE_EVENT_BACKGROUND);
+ },
+
/////////////////////////////////////////////////////////////////////////////
// nsIObserver
observe: function nsUpdateService_observe (aSubject, aTopic, aData)
@@ -390,6 +433,8 @@ nsUpdateService.prototype = {
}
break;
case PREF_UPDATE_INTERVAL:
+ case PREF_UPDATE_APP_INTERVAL:
+ case PREF_UPDATE_EXTENSIONS_INTERVAL:
this._makeTimer(this._pref.getIntPref(PREF_UPDATE_INTERVAL));
break;
}
@@ -407,6 +452,7 @@ nsUpdateService.prototype = {
pbi.removeObserver(PREF_UPDATE_APP_ENABLED, this);
pbi.removeObserver(PREF_UPDATE_EXTENSIONS_ENABLED, this);
pbi.removeObserver(PREF_UPDATE_INTERVAL, this);
+ pbi.removeObserver(PREF_UPDATE_EXTENSIONS_INTERVAL, this);
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
@@ -417,15 +463,15 @@ nsUpdateService.prototype = {
/////////////////////////////////////////////////////////////////////////////
// nsUpdateService
+ _timer: null,
_makeTimer: function nsUpdateService__makeTimer (aDelay)
{
- if (this._timer)
- this._timer.cancel();
-
- this._timer = Components.classes["@mozilla.org/timer;1"]
- .createInstance(Components.interfaces.nsITimer);
+ if (!this._timer)
+ this._timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ this._timer.cancel();
this._timer.initWithCallback(this, aDelay,
- Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
},
get _nowInMilliseconds ()
@@ -510,8 +556,15 @@ nsUpdateObserver.prototype = {
this._pref.setIntPref(PREF_UPDATE_EXTENSIONS_COUNT, 0);
break;
case "Update:Extension:Item-Ended":
- this._pref.setIntPref(PREF_UPDATE_EXTENSIONS_COUNT,
- this._pref.getIntPref(PREF_UPDATE_EXTENSIONS_COUNT) + 1);
+ var newCount = this._pref.getIntPref(PREF_UPDATE_EXTENSIONS_COUNT) + 1;
+ this._pref.setIntPref(PREF_UPDATE_EXTENSIONS_COUNT, newCount);
+ var threshold = this._pref.getIntPref(PREF_UPDATE_EXTENSIONS_SEVERITY_THRESHOLD);
+ if (this._service.updateSeverity < SEVERITY_HIGH) {
+ if (newCount > threshold)
+ this._pref.setIntPref(PREF_UPDATE_SEVERITY, SEVERITY_MEDIUM);
+ else
+ this._pref.setIntPref(PREF_UPDATE_SEVERITY, SEVERITY_LOW);
+ }
break;
case "Update:Extension:Ended":
this._updateState |= UPDATED_EXTENSIONS;
@@ -578,6 +631,7 @@ nsUpdateObserver.prototype = {
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
+ try { os.removeObserver(this, "Update:Extension:Started"); } catch (e) { }
try { os.removeObserver(this, "Update:Extension:Item-Ended"); } catch (e) { }
try { os.removeObserver(this, "Update:Extension:Ended"); } catch (e) { }
try { os.removeObserver(this, "Update:App:Ended"); } catch (e) { }
@@ -652,7 +706,17 @@ function UpdateItem ()
}
UpdateItem.prototype = {
- init: function UpdateItem_init (aID, aVersion, aMinAppVersion, aMaxAppVersion, aName, aRow, aUpdateURL, aIconURL, aUpdateRDF, aType)
+ init: function UpdateItem_init (aID,
+ aVersion,
+ aMinAppVersion,
+ aMaxAppVersion,
+ aName,
+ aRow,
+ aXPIURL,
+ aIconURL,
+ aUpdateRDF,
+ aUpdateService,
+ aType)
{
this._id = aID;
this._version = aVersion;
@@ -660,9 +724,10 @@ UpdateItem.prototype = {
this._maxAppVersion = aMaxAppVersion;
this._name = aName;
this._row = aRow;
- this._updateURL = aUpdateURL;
+ this._xpiURL = aXPIURL;
this._iconURL = aIconURL;
this._updateRDF = aUpdateRDF;
+ this._updateService = aUpdateService;
this._type = aType;
},
@@ -672,9 +737,10 @@ UpdateItem.prototype = {
get maxAppVersion() { return this._maxAppVersion; },
get name() { return this._name; },
get row() { return this._row; },
- get updateURL() { return this._updateURL; },
+ get xpiURL() { return this._xpiURL; },
get iconURL() { return this._iconURL },
get updateRDF() { return this._updateRDF; },
+ get updateService() { return this._updateService; },
get type() { return this._type; },
get objectSource()
@@ -685,8 +751,10 @@ UpdateItem.prototype = {
maxAppVersion : this._maxAppVersion,
name : this._name,
row : this._row,
- updateURL : this._updateURL,
+ xpiURL : this._xpiURL,
iconURL : this._iconURL,
+ updateRDF : this._updateRDF,
+ updateService : this._updateService,
type : this._type
}.toSource();
},
@@ -702,6 +770,36 @@ UpdateItem.prototype = {
}
};
+function Version(aMajor, aMinor, aRelease, aBuild, aPlus)
+{
+ this.major = aMajor || 0;
+ this.minor = aMinor || 0;
+ this.release = aRelease || 0;
+ this.build = aBuild || 0;
+ this.plus = aPlus || 0;
+}
+
+Version.prototype = {
+ toString: function Version_toString()
+ {
+ return this.major + "." + this.minor + "." + this.subminor + "." + this.release + (this.plus ? "+" : "");
+ },
+
+ compare: function (aVersion)
+ {
+ var fields = ["major", "minor", "release", "build", "plus"];
+
+ for (var i = 0; i < fields.length; ++i) {
+ var field = fields[i];
+ if (aVersion[field] > this[field])
+ return -1;
+ else if (aVersion[field] < this[field])
+ return 1;
+ }
+ return 0;
+ }
+}
+
function nsVersionChecker()
{
}
@@ -717,28 +815,25 @@ nsVersionChecker.prototype = {
{
var a = this._decomposeVersion(aVersionA);
var b = this._decomposeVersion(aVersionB);
- return a - b;
+
+ return a.compare(b);
},
- // Version strings get translated into a "score" that indicates how new
- // the product is.
- //
- // a.b.c+ -> a*1000 + b*100 + c*10 + 1*[+]
- // i.e 0.6.1+ = 6 * 100 + 1 * 10 = 611.
_decomposeVersion: function nsVersionChecker__decomposeVersion (aVersion)
{
- var result = 0;
+ var plus = 0;
if (aVersion.charAt(aVersion.length-1) == "+") {
aVersion = aVersion.substr(0, aVersion.length-1);
- result += 1;
+ plus = 1;
}
-
+
var parts = aVersion.split(".");
- result += this._getValidInt(parts[0]) * 1000;
- result += this._getValidInt(parts[1]) * 100;
- result += this._getValidInt(parts[2]) * 10;
- return result;
+ return new Version(this._getValidInt(parts[0]),
+ this._getValidInt(parts[1]),
+ this._getValidInt(parts[2]),
+ this._getValidInt(parts[3]),
+ plus);
},
_getValidInt: function nsVersionChecker__getValidInt (aPartString)
diff --git a/mozilla/toolkit/themes/winstripe/global/jar.mn b/mozilla/toolkit/themes/winstripe/global/jar.mn
index 92ef4b81061..a13983fa1a7 100644
--- a/mozilla/toolkit/themes/winstripe/global/jar.mn
+++ b/mozilla/toolkit/themes/winstripe/global/jar.mn
@@ -95,3 +95,4 @@ classic.jar:
skin/classic/global/tree/sort-dsc.gif (tree/sort-dsc.gif)
skin/classic/global/tree/twisty-clsd.png (tree/twisty-clsd.png)
skin/classic/global/tree/twisty-open.png (tree/twisty-open.png)
+ skin/classic/global/throbber/Throbber-small.gif (throbber/Throbber-small.gif)
diff --git a/mozilla/toolkit/themes/winstripe/mozapps/update/update.css b/mozilla/toolkit/themes/winstripe/mozapps/update/update.css
index b7f89a65528..46080ece28f 100644
--- a/mozilla/toolkit/themes/winstripe/mozapps/update/update.css
+++ b/mozilla/toolkit/themes/winstripe/mozapps/update/update.css
@@ -79,3 +79,19 @@ updateitem {
.updateIcon[severity="2"] {
-moz-image-region: rect(0px 48px 16px 32px);
}
+
+.throbber {
+ list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif");
+ width: 16px;
+ height: 16px;
+ margin: 5px 2px 5px 5px;
+}
+
+#incompatibleAlert {
+ background-color: InfoBackground;
+ color: InfoText;
+ border: 1px outset InfoBackground;
+ margin-left: 3px;
+ margin-right: 3px;
+ padding: 5px;
+}