Bug 392180: updateURL should have variable indicating the context of the check. r=robstrong, sr=bsmedberg

This commit is contained in:
Dave Townsend 2009-09-10 19:50:41 +01:00
parent 752fb7fae5
commit 562091c5d0
10 changed files with 253 additions and 14 deletions

View File

@ -157,7 +157,7 @@ pref("app.update.incompatible.mode", 0);
// .. etc ..
//
pref("extensions.update.enabled", true);
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%");
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%");
pref("extensions.update.interval", 86400); // Check for updates to Extensions and
// Themes every day
// Non-symmetric (not shared by extensions) extension-specific [update] preferences

View File

@ -2295,7 +2295,8 @@ function checkUpdatesAll() {
var listener = new UpdateCheckListener();
gExtensionManager.update(items, items.length,
nsIExtensionManager.UPDATE_CHECK_NEWVERSION,
listener);
listener,
nsIExtensionMananger.UPDATE_WHEN_USER_REQUESTED);
}
if (gExtensionsView.selectedItem)
gExtensionsView.selectedItem.focus();
@ -2666,7 +2667,8 @@ var gExtensionsViewController = {
var listener = new UpdateCheckListener();
gExtensionManager.update(items, items.length,
nsIExtensionManager.UPDATE_CHECK_NEWVERSION,
listener);
listener,
nsIExtensionManager.UPDATE_WHEN_USER_REQUESTED);
},
cmd_installUpdate: function (aSelectedItem)

View File

@ -191,7 +191,8 @@ var gVersionInfoPage = {
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(nsIExtensionManager);
// Synchronize the app compatibility info for all items.
em.update([], 0, nsIExtensionManager.UPDATE_SYNC_COMPATIBILITY, this);
em.update([], 0, nsIExtensionManager.UPDATE_SYNC_COMPATIBILITY, this,
Ci.nsIExtensionManager.UPDATE_WHEN_NEW_APP_INSTALLED);
},
/////////////////////////////////////////////////////////////////////////////
@ -304,7 +305,8 @@ var gUpdatePage = {
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(nsIExtensionManager);
em.update(gUpdateWizard.items, this._totalCount,
nsIExtensionManager.UPDATE_CHECK_NEWVERSION, this);
nsIExtensionManager.UPDATE_CHECK_NEWVERSION, this,
Ci.nsIExtensionManager.UPDATE_WHEN_NEW_APP_INSTALLED);
},
/////////////////////////////////////////////////////////////////////////////

View File

@ -198,7 +198,7 @@ interface nsIInstallLocation : nsISupports
* XXXben - Some of this stuff should go into a management-ey interface,
* some into an app-startup-ey interface.
*/
[scriptable, uuid(d514dd0c-5797-4f75-bea2-47612b49e243)]
[scriptable, uuid(494e8302-8689-4a8a-a08d-0da17c649c7d)]
interface nsIExtensionManager : nsISupports
{
/**
@ -209,6 +209,24 @@ interface nsIExtensionManager : nsISupports
const unsigned long UPDATE_SYNC_COMPATIBILITY = 2;
const unsigned long UPDATE_NOTIFY_NEWVERSION = 3;
/**
* Constants that callers can use to indicate the reason for an add-on update
* check. Internal code uses other constants in nsExtensionManager.js.in.
*
* The update check is being performed at the request of the user.
*/
const unsigned long UPDATE_WHEN_USER_REQUESTED = 1;
/**
* The update check is being performed after a new version of the application
* has been detected.
*/
const unsigned long UPDATE_WHEN_NEW_APP_DETECTED = 2;
/**
* The update check is being performed after a new version of the application
* has been installed.
*/
const unsigned long UPDATE_WHEN_NEW_APP_INSTALLED = 3;
/**
* Starts the Extension Manager, checking for item changes, additions and
* removals, and finishing pending operations.
@ -299,6 +317,9 @@ interface nsIExtensionManager : nsISupports
* during the update check process. If not null, the object's
* onUpdateStarted() and onUpdateEnded() methods will be called even
* if there are no items to update.
* @param updateType (optional)
* The type of the update check. Should be one of the UPDATE_WHEN
* values.
* @param appVersion (optional)
* The version of the application to check for compatible updates.
* This param is only honored when updateCheckType is equal to
@ -316,6 +337,7 @@ interface nsIExtensionManager : nsISupports
in unsigned long itemCount,
in unsigned long updateCheckType,
in nsIAddonUpdateCheckListener listener,
[optional] in unsigned long updateType,
[optional] in AString appVersion,
[optional] in AString platformVersion);

View File

@ -139,6 +139,20 @@ const URI_DOWNLOADS_PROPERTIES = "chrome://mozapps/locale/downloads/downl
const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
const URI_EXTENSION_LIST_DIALOG = "chrome://mozapps/content/extensions/list.xul";
/**
* Constants that internal code can use to indicate the reason for an add-on
* update check. external code uses other constants in nsIExtensionManager.idl.
*/
const MAX_PUBLIC_UPDATE_WHEN = 15;
const UPDATE_WHEN_PERIODIC_UPDATE = 16;
const UPDATE_WHEN_ADDON_INSTALLED = 17;
/**
* Bitmask of the different types of update check.
*/
const UPDATE_TYPE_COMPATIBILITY = 32;
const UPDATE_TYPE_NEWVERSION = 64;
const INSTALLERROR_SUCCESS = 0;
const INSTALLERROR_INVALID_VERSION = -1;
const INSTALLERROR_INVALID_GUID = -2;
@ -2554,7 +2568,7 @@ ExtensionManager.prototype = {
updater.checkForUpdates(items, items.length,
Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION,
new BackgroundUpdateCheckListener(this.datasource),
null, null);
UPDATE_WHEN_PERIODIC_UPDATE);
},
/**
@ -3896,7 +3910,10 @@ ExtensionManager.prototype = {
em._callInstallListeners("onCompatibilityCheckStarted", item);
em._compatibilityCheckCount++;
em.update([item], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, this);
var updater = new ExtensionItemUpdater(em);
updater.checkForUpdates([item], 1,
Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY,
this, UPDATE_WHEN_ADDON_INSTALLED);
},
/**
@ -4893,7 +4910,13 @@ ExtensionManager.prototype = {
* See nsIExtensionManager.idl
*/
update: function EM_update(items, itemCount, updateCheckType, listener,
appVersion, platformVersion) {
updateType, appVersion, platformVersion) {
// Callers through the API are only allowed to use update types declared
// in nsIExtensionManager.idl
if (updateType > MAX_PUBLIC_UPDATE_WHEN)
throw Cr.NS_ERROR_ILLEGAL_VALUE;
for (i = 0; i < itemCount; ++i) {
var currItem = items[i];
if (!currItem)
@ -4905,7 +4928,7 @@ ExtensionManager.prototype = {
var updater = new ExtensionItemUpdater(this);
updater.checkForUpdates(items, items.length, updateCheckType, listener,
appVersion, platformVersion);
updateType, appVersion, platformVersion);
},
/**
@ -5593,6 +5616,7 @@ ExtensionItemUpdater.prototype = {
_emDS : null,
_em : null,
_updateCheckType : 0,
_updateType : 0,
_items : [],
_listener : null,
@ -5628,6 +5652,7 @@ ExtensionItemUpdater.prototype = {
aItemCount,
aUpdateCheckType,
aListener,
aUpdateType,
aAppVersion,
aPlatformVersion) {
if (aUpdateCheckType == Ci.nsIExtensionManager.UPDATE_NOTIFY_NEWVERSION) {
@ -5648,6 +5673,14 @@ ExtensionItemUpdater.prototype = {
this._items = aItems;
this._responseCount = aItemCount;
this._updateType = aUpdateType;
// All update check types look for compatibility currently
this._updateType |= UPDATE_TYPE_COMPATIBILITY;
// Only two types also look for new versions
if (aUpdateCheckType == Ci.nsIExtensionManager.UPDATE_NOTIFY_NEWVERSION ||
aUpdateCheckType == Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION)
this._updateType |= UPDATE_TYPE_NEWVERSION;
// This is the number of extensions/themes/etc that we found updates for.
this._updateCount = 0;
@ -5772,6 +5805,10 @@ ExtensionItemUpdater.prototype = {
* appropriate values.
* @param aItem
* The nsIUpdateItem representing the item
* @param aAppVersion
* The application version to check for updates for
* @param aUpdateType
* The type of the update (see nsIExtensionManager)
* @param aURI
* The uri to escape
* @param aDS
@ -5779,7 +5816,7 @@ ExtensionItemUpdater.prototype = {
*
* @returns the appropriately escaped uri.
*/
function escapeAddonURI(aItem, aAppVersion, aURI, aDS)
function escapeAddonURI(aItem, aAppVersion, aUpdateType, aURI, aDS)
{
var itemStatus = "userEnabled";
if (aDS.getItemProperty(aItem.id, "userDisabled") == "true" ||
@ -5809,6 +5846,8 @@ function escapeAddonURI(aItem, aAppVersion, aURI, aDS)
aURI = aURI.replace(/%APP_ABI%/g, gXPCOMABI);
aURI = aURI.replace(/%APP_LOCALE%/g, gLocale);
aURI = aURI.replace(/%CURRENT_APP_VERSION%/g, gApp.version);
if (aUpdateType)
aURI = aURI.replace(/%UPDATE_TYPE%/g, aUpdateType);
// Replace custom parameters (names of custom parameters must have at
// least 3 characters to prevent lookups for something like %D0%C8)
@ -5904,7 +5943,8 @@ RDFItemUpdater.prototype = {
if (!dsURI)
dsURI = gPref.getCharPref(PREF_UPDATE_DEFAULT_URL);
dsURI = escapeAddonURI(aItem, this._updater._appVersion, dsURI, emDS);
dsURI = escapeAddonURI(aItem, this._updater._appVersion,
this._updater._updateType, dsURI, emDS);
// Verify that the URI provided is valid
try {
@ -7953,7 +7993,7 @@ ExtensionsDataSource.prototype = {
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
var uri = stringData(this._inner.GetTarget(item, EM_R("availableUpdateInfo"), true));
if (uri) {
uri = escapeAddonURI(this.getItemForID(id), null, uri, this);
uri = escapeAddonURI(this.getItemForID(id), null, null, uri, this);
return EM_L(uri);
}
return null;

View File

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>bug392180@tests.mozilla.org</em:id>
<em:version>1.0</em:version>
<em:targetApplication>
<Description>
<em:id>xpcshell@tests.mozilla.org</em:id>
<em:minVersion>1</em:minVersion>
<em:maxVersion>5</em:maxVersion>
</Description>
</em:targetApplication>
<em:name>Bug 392180</em:name>
<em:updateURL>http://localhost:4444/update.rdf?%UPDATE_TYPE%</em:updateURL>
</Description>
</RDF>

View File

@ -177,7 +177,8 @@ function run_test() {
}
gEM.update(items, items.length, Ci.nsIExtensionManager.UPDATE_NOTIFY_NEWVERSION,
updateListener, "3", "3");
updateListener, Ci.nsIExtensionManager.UPDATE_WHEN_USER_REQUESTED,
"3", "3");
do_test_pending();
}

View File

@ -0,0 +1,148 @@
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Dave Townsend <dtownsend@oxymoronical.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 *****
*/
// Disables security checking our updates which haven't been signed
gPrefs.setBoolPref("extensions.checkUpdateSecurity", false);
do_load_httpd_js();
var server;
var updateListener = {
onUpdateStarted: function() {
},
onUpdateEnded: function() {
gNext();
},
onAddonUpdateStarted: function(addon) {
},
onAddonUpdateEnded: function(addon, status) {
// No update rdf will get found so this should be a failure.
do_check_eq(status, Ci.nsIAddonUpdateCheckListener.STATUS_FAILURE);
}
}
var requestHandler = {
handle: function(metadata, response) {
var updateType = metadata.queryString;
do_check_eq(updateType, gType);
response.setStatusLine(metadata.httpVersion, 404, "Not Found");
}
}
var gAddon;
var gNext;
var gType;
function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
startupEM();
gEM.installItemFromFile(do_get_addon("test_bug392180"), NS_INSTALL_LOCATION_APPPROFILE);
restartEM();
gAddon = gEM.getItemForID("bug392180@tests.mozilla.org");
do_check_neq(gAddon, null);
server = new nsHttpServer();
server.registerPathHandler("/update.rdf", requestHandler);
server.start(4444);
do_test_pending();
run_test_1();
}
function end_test() {
server.stop(do_test_finished);
}
function run_test_1() {
// UPDATE_TYPE_COMPATIBILITY | UPDATE_TYPE_NEWVERSION;
gType = 96;
gNext = run_test_2;
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION, updateListener);
}
function run_test_2() {
// UPDATE_TYPE_COMPATIBILITY;
gType = 32;
gNext = run_test_3;
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, updateListener);
}
function run_test_3() {
// UPDATE_TYPE_COMPATIBILITY | UPDATE_TYPE_NEWVERSION | UPDATE_WHEN_USER_REQUESTED;
gType = 97;
gNext = run_test_4;
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION, updateListener,
Ci.nsIExtensionManager.UPDATE_WHEN_USER_REQUESTED);
}
function run_test_4() {
// UPDATE_TYPE_COMPATIBILITY | UPDATE_TYPE_NEWVERSION | UPDATE_WHEN_NEW_APP_DETECTED;
gType = 98;
gNext = run_test_5;
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION, updateListener,
Ci.nsIExtensionManager.UPDATE_WHEN_NEW_APP_DETECTED);
}
function run_test_5() {
// UPDATE_TYPE_COMPATIBILITY | UPDATE_WHEN_NEW_APP_INSTALLED;
gType = 35;
gNext = run_test_6;
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, updateListener,
Ci.nsIExtensionManager.UPDATE_WHEN_NEW_APP_INSTALLED);
}
function run_test_6() {
// UPDATE_TYPE_COMPATIBILITY;
gType = 35;
gNext = end_test;
try {
gEM.update([gAddon], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, updateListener,
16);
do_throw("Should have thrown an exception");
}
catch (e) {
do_check_eq(e.result, Components.results.NS_ERROR_ILLEGAL_VALUE);
end_test();
}
}

View File

@ -640,6 +640,7 @@ var gIncompatibleCheckPage = {
getService(CoI.nsIExtensionManager);
em.update(this.addons, this.addons.length,
CoI.nsIExtensionManager.UPDATE_NOTIFY_NEWVERSION, this,
CoI.nsIExtensionManager.UPDATE_WHEN_NEW_APP_DETECTED,
gUpdates.update.extensionVersion, gUpdates.update.platformVersion);
},

View File

@ -1579,6 +1579,7 @@ UpdateService.prototype = {
var mode = (updateIncompatMode == 1) ? Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY :
Ci.nsIExtensionManager.UPDATE_NOTIFY_NEWVERSION;
em.update(currentAddons, currentAddons.length, mode, this,
Ci.nsIExtensionManager.UPDATE_WHEN_NEW_APP_DETECTED,
this._update.extensionVersion, this._update.platformVersion);
}
else {