зеркало из https://github.com/mozilla/pjs.git
Bug 474988: Mismatched adds and removes of install listeners will fail. r=robstrong
This commit is contained in:
Родитель
8e0ff851fb
Коммит
097e0f4e5d
|
@ -4089,10 +4089,8 @@ ExtensionManager.prototype = {
|
||||||
|
|
||||||
// If there are no compatibility checks running and no downloads in
|
// If there are no compatibility checks running and no downloads in
|
||||||
// progress then the install operations are complete.
|
// progress then the install operations are complete.
|
||||||
if (this._compatibilityCheckCount == 0 && this._transactions.length == 0) {
|
if (this._compatibilityCheckCount == 0 && this._transactions.length == 0)
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallsCompleted");
|
||||||
this._installListeners[i].onInstallsCompleted();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4300,8 +4298,7 @@ ExtensionManager.prototype = {
|
||||||
this._xpi = xpiFile;
|
this._xpi = xpiFile;
|
||||||
this._installManifest = installManifest;
|
this._installManifest = installManifest;
|
||||||
|
|
||||||
for (var i = 0; i < em._installListeners.length; ++i)
|
em._callInstallListeners("onCompatibilityCheckStarted", item);
|
||||||
em._installListeners[i].onCompatibilityCheckStarted(item);
|
|
||||||
em._compatibilityCheckCount++;
|
em._compatibilityCheckCount++;
|
||||||
em.update([item], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, this);
|
em.update([item], 1, Ci.nsIExtensionManager.UPDATE_CHECK_COMPATIBILITY, this);
|
||||||
},
|
},
|
||||||
|
@ -4343,8 +4340,7 @@ ExtensionManager.prototype = {
|
||||||
em.datasource.removeDownload(this._xpi.path);
|
em.datasource.removeDownload(this._xpi.path);
|
||||||
LOG("Version Check Phone Home Completed");
|
LOG("Version Check Phone Home Completed");
|
||||||
|
|
||||||
for (var i = 0; i < em._installListeners.length; ++i)
|
em._callInstallListeners("onCompatibilityCheckEnded", addon, status);
|
||||||
em._installListeners[i].onCompatibilityCheckEnded(addon, status);
|
|
||||||
|
|
||||||
// Only compatibility updates (e.g. STATUS_VERSIONINFO) are currently
|
// Only compatibility updates (e.g. STATUS_VERSIONINFO) are currently
|
||||||
// supported
|
// supported
|
||||||
|
@ -4389,9 +4385,8 @@ ExtensionManager.prototype = {
|
||||||
BundleManager.appName + " " + gApp.version + ", Toolkit " +
|
BundleManager.appName + " " + gApp.version + ", Toolkit " +
|
||||||
gApp.platformVersion + ". Remote compatibility check did not " +
|
gApp.platformVersion + ". Remote compatibility check did not " +
|
||||||
"resolve this.");
|
"resolve this.");
|
||||||
|
|
||||||
for (var i = 0; i < em._installListeners.length; ++i)
|
em._callInstallListeners("onInstallEnded", addon, INSTALLERROR_INCOMPATIBLE_VERSION);
|
||||||
em._installListeners[i].onInstallEnded(addon, INSTALLERROR_INCOMPATIBLE_VERSION);
|
|
||||||
|
|
||||||
// We are responsible for cleaning up this file!
|
// We are responsible for cleaning up this file!
|
||||||
InstallLocations.get(aInstallLocationKey).removeFile(this._xpi);
|
InstallLocations.get(aInstallLocationKey).removeFile(this._xpi);
|
||||||
|
@ -4400,10 +4395,8 @@ ExtensionManager.prototype = {
|
||||||
em._compatibilityCheckCount--;
|
em._compatibilityCheckCount--;
|
||||||
// If there are no more compatibility checks running and no downloads in
|
// If there are no more compatibility checks running and no downloads in
|
||||||
// progress then the install operations are complete.
|
// progress then the install operations are complete.
|
||||||
if (em._compatibilityCheckCount == 0 && em._transactions.length == 0) {
|
if (em._compatibilityCheckCount == 0 && em._transactions.length == 0)
|
||||||
for (var i = 0; i < em._installListeners.length; ++i)
|
em._callInstallListeners("onInstallsCompleted");
|
||||||
em._installListeners[i].onInstallsCompleted();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonUpdateCheckListener])
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonUpdateCheckListener])
|
||||||
|
@ -4420,8 +4413,7 @@ ExtensionManager.prototype = {
|
||||||
aInstallLocationKey, "", "", "",
|
aInstallLocationKey, "", "", "",
|
||||||
getURIFromFile(aXPIFile).spec,
|
getURIFromFile(aXPIFile).spec,
|
||||||
"", "", "", "", 0, gApp.id);
|
"", "", "", "", 0, gApp.id);
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallStarted", addon);
|
||||||
this._installListeners[i].onInstallStarted(addon);
|
|
||||||
|
|
||||||
shouldPhoneHomeIfNecessary = true;
|
shouldPhoneHomeIfNecessary = true;
|
||||||
var installManifest = null;
|
var installManifest = null;
|
||||||
|
@ -4435,8 +4427,7 @@ ExtensionManager.prototype = {
|
||||||
if (!installManifest) {
|
if (!installManifest) {
|
||||||
LOG("The Install Manifest supplied by this item is not well-formed. " +
|
LOG("The Install Manifest supplied by this item is not well-formed. " +
|
||||||
"Installation will not proceed.");
|
"Installation will not proceed.");
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallEnded", addon, INSTALLERROR_INVALID_MANIFEST);
|
||||||
this._installListeners[i].onInstallEnded(addon, INSTALLERROR_INVALID_MANIFEST);
|
|
||||||
return INSTALLERROR_INVALID_MANIFEST;
|
return INSTALLERROR_INVALID_MANIFEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4504,8 +4495,7 @@ ExtensionManager.prototype = {
|
||||||
// this function, BEFORE staging takes place... technically speaking
|
// this function, BEFORE staging takes place... technically speaking
|
||||||
// a location could become readonly during the phone home process,
|
// a location could become readonly during the phone home process,
|
||||||
// but that's an edge case I don't care about.
|
// but that's an edge case I don't care about.
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallEnded", addon, INSTALLERROR_RESTRICTED);
|
||||||
this._installListeners[i].onInstallEnded(addon, INSTALLERROR_RESTRICTED);
|
|
||||||
return INSTALLERROR_RESTRICTED;
|
return INSTALLERROR_RESTRICTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4601,9 +4591,7 @@ ExtensionManager.prototype = {
|
||||||
stageXPIForOtherApps(aXPIFile, installData);
|
stageXPIForOtherApps(aXPIFile, installData);
|
||||||
|
|
||||||
// The install of this item is complete, notify observers
|
// The install of this item is complete, notify observers
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallEnded", addon, installData.error);
|
||||||
this._installListeners[i].onInstallEnded(addon, installData.error);
|
|
||||||
|
|
||||||
return installData.error;
|
return installData.error;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -5651,12 +5639,10 @@ ExtensionManager.prototype = {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case nsIXPIProgressDialog.DOWNLOAD_START:
|
case nsIXPIProgressDialog.DOWNLOAD_START:
|
||||||
ds.updateDownloadState(id, "downloading");
|
ds.updateDownloadState(id, "downloading");
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onDownloadStarted", addon);
|
||||||
this._installListeners[i].onDownloadStarted(addon);
|
|
||||||
break;
|
break;
|
||||||
case nsIXPIProgressDialog.DOWNLOAD_DONE:
|
case nsIXPIProgressDialog.DOWNLOAD_DONE:
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onDownloadEnded", addon);
|
||||||
this._installListeners[i].onDownloadEnded(addon);
|
|
||||||
break;
|
break;
|
||||||
case nsIXPIProgressDialog.INSTALL_START:
|
case nsIXPIProgressDialog.INSTALL_START:
|
||||||
ds.updateDownloadState(id, "finishing");
|
ds.updateDownloadState(id, "finishing");
|
||||||
|
@ -5673,10 +5659,8 @@ ExtensionManager.prototype = {
|
||||||
}
|
}
|
||||||
transaction.removeDownload(addon.xpiURL);
|
transaction.removeDownload(addon.xpiURL);
|
||||||
// A successful install will be passing notifications via installItemFromFile
|
// A successful install will be passing notifications via installItemFromFile
|
||||||
if (value != 0) {
|
if (value != 0)
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallEnded", addon, value);
|
||||||
this._installListeners[i].onInstallEnded(addon, value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case nsIXPIProgressDialog.DIALOG_CLOSE:
|
case nsIXPIProgressDialog.DIALOG_CLOSE:
|
||||||
for (var i = 0; i < this._transactions.length; ++i) {
|
for (var i = 0; i < this._transactions.length; ++i) {
|
||||||
|
@ -5689,10 +5673,8 @@ ExtensionManager.prototype = {
|
||||||
|
|
||||||
// If there are no compatibility checks running then the install
|
// If there are no compatibility checks running then the install
|
||||||
// operations are complete.
|
// operations are complete.
|
||||||
if (this._compatibilityCheckCount == 0) {
|
if (this._compatibilityCheckCount == 0)
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onInstallsCompleted");
|
||||||
this._installListeners[i].onInstallsCompleted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5704,8 +5686,7 @@ ExtensionManager.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
onProgress: function EM_onProgress(addon, value, maxValue) {
|
onProgress: function EM_onProgress(addon, value, maxValue) {
|
||||||
for (var i = 0; i < this._installListeners.length; ++i)
|
this._callInstallListeners("onDownloadProgress", addon, value, maxValue);
|
||||||
this._installListeners[i].onDownloadProgress(addon, value, maxValue);
|
|
||||||
|
|
||||||
var id = addon.id != addon.xpiURL ? PREFIX_ITEM_URI + addon.id : addon.xpiURL;
|
var id = addon.id != addon.xpiURL ? PREFIX_ITEM_URI + addon.id : addon.xpiURL;
|
||||||
var progress = Math.round((value / maxValue) * 100);
|
var progress = Math.round((value / maxValue) * 100);
|
||||||
|
@ -5723,7 +5704,25 @@ ExtensionManager.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
removeInstallListenerAt: function EM_removeInstallListenerAt(index) {
|
removeInstallListenerAt: function EM_removeInstallListenerAt(index) {
|
||||||
this._installListeners.splice(index, 1);
|
if (index < 0 || index >= this._installListeners.length)
|
||||||
|
throw Cr.NS_ERROR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
this._installListeners[index] = null;
|
||||||
|
while (this._installListeners[this._installListeners.length - 1] === null)
|
||||||
|
this._installListeners.splice(this._installListeners.length - 1, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
_callInstallListeners: function EM__callInstallListeners(method) {
|
||||||
|
for (var i = 0; i < this._installListeners.length; ++i) {
|
||||||
|
try {
|
||||||
|
if (this._installListeners[i])
|
||||||
|
this._installListeners[i][method].apply(this._installListeners[i],
|
||||||
|
Array.slice(arguments, 1));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
LOG("Failure in install listener's " + method + ": " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* ***** 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 *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
var installListenerA = {};
|
||||||
|
var installListenerB = {};
|
||||||
|
var installListenerC = {};
|
||||||
|
var installListenerD = {};
|
||||||
|
var installListenerE = {};
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9");
|
||||||
|
startupEM();
|
||||||
|
|
||||||
|
// Add some listeners
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerA), 0);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerB), 1);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerC), 2);
|
||||||
|
// Now stack is ABC
|
||||||
|
|
||||||
|
// Should get back the same id if adding the same listener twice
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerA), 0);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerB), 1);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerC), 2);
|
||||||
|
// Stack is still ABC
|
||||||
|
|
||||||
|
// Removing a listener shouldn't affect the id of the others
|
||||||
|
gEM.removeInstallListenerAt(0);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerB), 1);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerC), 2);
|
||||||
|
// Stack is .BC
|
||||||
|
|
||||||
|
// Adding a new listener should still give a higher id than previously
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerD), 3);
|
||||||
|
// Stack is .BCD
|
||||||
|
|
||||||
|
// Removing and re-adding the highest listener should give the same result.
|
||||||
|
gEM.removeInstallListenerAt(3);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerE), 3);
|
||||||
|
// Stack is .BCE
|
||||||
|
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerD), 4);
|
||||||
|
gEM.removeInstallListenerAt(3);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerE), 5);
|
||||||
|
// Stack is .BC.DE
|
||||||
|
|
||||||
|
// Stack should shorten down to the last listener
|
||||||
|
gEM.removeInstallListenerAt(4);
|
||||||
|
gEM.removeInstallListenerAt(5);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerD), 3);
|
||||||
|
// Stack is .BCD
|
||||||
|
|
||||||
|
// Stack should get down to 0
|
||||||
|
gEM.removeInstallListenerAt(1);
|
||||||
|
gEM.removeInstallListenerAt(2);
|
||||||
|
gEM.removeInstallListenerAt(3);
|
||||||
|
do_check_eq(gEM.addInstallListener(installListenerE), 0);
|
||||||
|
gEM.removeInstallListenerAt(0);
|
||||||
|
// Stack is empty
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче