Bug 591663: "You don't have any add-ons of this type installed" doesn't disappear as it should. r=dtownsend, a=blocks-betaN

This commit is contained in:
Dave Townsend 2010-12-10 13:01:08 -08:00
parent e4cc8609c6
commit 1060fa2af5
4 changed files with 218 additions and 52 deletions

View File

@ -1237,23 +1237,16 @@ function sortList(aList, aSortBy, aAscending) {
}
function getAddonsAndInstalls(aType, aCallback) {
var addonTypes = null, installTypes = null;
if (aType != null) {
addonTypes = [aType];
installTypes = [aType];
if (aType == "extension")
installTypes = addonTypes.concat("");
}
let addons = null, installs = null;
let types = (aType != null) ? [aType] : null;
var addons = null, installs = null;
AddonManager.getAddonsByTypes(addonTypes, function(aAddonsList) {
AddonManager.getAddonsByTypes(types, function(aAddonsList) {
addons = aAddonsList;
if (installs != null)
aCallback(addons, installs);
});
AddonManager.getInstallsByTypes(installTypes, function(aInstallsList) {
AddonManager.getInstallsByTypes(types, function(aInstallsList) {
// skip over upgrade installs and non-active installs
installs = aInstallsList.filter(function(aInstall) {
return !(aInstall.existingAddon ||
@ -1263,8 +1256,6 @@ function getAddonsAndInstalls(aType, aCallback) {
if (addons != null)
aCallback(addons, installs)
});
return {addon: addonTypes, install: installTypes};
}
@ -1892,8 +1883,7 @@ var gListView = {
_listBox: null,
_emptyNotice: null,
_sorters: null,
_types: [],
_installTypes: [],
_type: null,
initialize: function() {
this.node = document.getElementById("list-view");
@ -1914,6 +1904,7 @@ var gListView = {
},
show: function(aType, aRequest) {
this._type = aType;
this.node.setAttribute("type", aType);
this.showEmptyNotice(false);
@ -1921,7 +1912,7 @@ var gListView = {
this._listBox.removeItemAt(0);
var self = this;
var types = getAddonsAndInstalls(aType, function(aAddonsList, aInstallsList) {
getAddonsAndInstalls(aType, function(aAddonsList, aInstallsList) {
if (gViewController && aRequest != gViewController.currentViewRequest)
return;
@ -1933,22 +1924,18 @@ var gListView = {
for (let i = 0; i < aInstallsList.length; i++)
elements.push(createItem(aInstallsList[i], true));
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
sortElements(elements, self._sorters.sortBy, self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
} else {
self.showEmptyNotice(true);
}
gEventManager.registerInstallListener(self);
gViewController.updateCommands();
gViewController.notifyViewChanged();
});
this._types = types.addon;
this._installTypes = types.install;
},
hide: function() {
@ -1976,47 +1963,61 @@ var gListView = {
sortList(this._listBox, aSortBy, aAscending);
},
onNewInstall: function(aInstall) {
// Ignore any upgrade installs
if (aInstall.existingAddon)
return;
var item = createItem(aInstall, true);
this._listBox.insertBefore(item, this._listBox.firstChild);
},
onExternalInstall: function(aAddon, aExistingAddon, aRequiresRestart) {
if (this._types.indexOf(aAddon.type) == -1)
return;
// The existing list item will take care of upgrade installs
if (aExistingAddon)
return;
var item = createItem(aAddon, false);
this._listBox.insertBefore(item, this._listBox.firstChild);
this.addItem(aAddon);
},
onDownloadStarted: function(aInstall) {
this.addItem(aInstall, true);
},
onInstallStarted: function(aInstall) {
this.addItem(aInstall, true);
},
onDownloadCancelled: function(aInstall) {
this.removeInstall(aInstall);
this.removeItem(aInstall, true);
},
onInstallCancelled: function(aInstall) {
this.removeInstall(aInstall);
this.removeItem(aInstall, true);
},
onInstallEnded: function(aInstall) {
// Remove any install entries for upgrades, their status will appear against
// the existing item
if (aInstall.existingAddon)
this.removeInstall(aInstall);
this.removeItem(aInstall, true);
},
removeInstall: function(aInstall) {
for (let i = 0; i < this._listBox.childNodes.length; i++) {
addItem: function(aObj, aIsInstall) {
if (aObj.type != this._type)
return;
let prop = aIsInstall ? "mInstall" : "mAddon";
for (let i = 0; i < this._listBox.itemCount; i++) {
let item = this._listBox.childNodes[i];
if (item.mInstall == aInstall) {
if (item[prop] == aObj)
return;
}
let item = createItem(aObj, aIsInstall);
this._listBox.insertBefore(item, this._listBox.firstChild);
this.showEmptyNotice(false);
},
removeItem: function(aObj, aIsInstall) {
let prop = aIsInstall ? "mInstall" : "mAddon";
for (let i = 0; i < this._listBox.itemCount; i++) {
let item = this._listBox.childNodes[i];
if (item[prop] == aObj) {
this._listBox.removeChild(item);
this.showEmptyNotice(this._listBox.itemCount == 0);
return;
}
}
@ -2472,13 +2473,12 @@ var gUpdatesView = {
elements.push(createItem(aAddon));
});
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
sortElements(elements, self._sorters.sortBy, self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
} else {
self.showEmptyNotice(true);
}
gViewController.notifyViewChanged();
@ -2519,14 +2519,13 @@ var gUpdatesView = {
elements.push(item);
});
self.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
self._updateSelected.hidden = false;
sortElements(elements, self._sorters.sortBy, self._sorters.ascending);
elements.forEach(function(aElement) {
self._listBox.appendChild(aElement);
});
} else {
self.showEmptyNotice(true);
}
// ensure badge count is in sync

View File

@ -59,6 +59,7 @@ _MAIN_TEST_FILES = \
browser_bug581076.js \
browser_bug587970.js \
browser_bug591465.js \
browser_bug591663.js \
browser_bug596336.js \
browser_bug608316.js \
browser_bug610764.js \

View File

@ -0,0 +1,156 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Test that the empty notice in the list view disappears as it should
// Don't use a standard list view (e.g. "extension") to ensure that the list is
// initially empty. Don't need to worry about the list of categories displayed
// since only the list view itself is tested.
let VIEW_ID = "addons://list/mock-addon";
let LIST_ID = "addon-list";
let EMPTY_ID = "addon-list-empty";
let gManagerWindow;
let gProvider;
let gItem;
let gInstallProperties = {
name: "Bug 591663 Mock Install",
type: "mock-addon"
};
let gAddonProperties = {
id: "test1@tests.mozilla.org",
name: "Bug 591663 Mock Add-on",
type: "mock-addon"
};
let gExtensionProperties = {
name: "Bug 591663 Extension Install",
type: "extension"
};
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
open_manager(VIEW_ID, function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, finish);
}
/**
* Check that the list view is as expected
*
* @param aItem
* The expected item in the list, or null if list should be empty
*/
function check_list(aItem) {
// Check state of the empty notice
let emptyNotice = gManagerWindow.document.getElementById(EMPTY_ID);
ok(emptyNotice != null, "Should have found the empty notice");
is(!emptyNotice.hidden, (aItem == null), "Empty notice should be showing if list empty");
// Check the children of the list
let list = gManagerWindow.document.getElementById(LIST_ID);
is(list.itemCount, aItem ? 1 : 0, "Should get expected number of items in list");
if (aItem != null) {
let itemName = list.firstChild.getAttribute("name");
is(itemName, aItem.name, "List item should have correct name");
}
}
// Test that the empty notice is showing and no items are showing in list
add_test(function() {
check_list(null);
run_next_test();
});
// Test that a new, non-active, install does not affect the list view
add_test(function() {
gItem = gProvider.createInstalls([gInstallProperties])[0];
check_list(null);
run_next_test();
});
// Test that onInstallStarted properly hides empty notice and adds install to list
add_test(function() {
gItem.addTestListener({
onDownloadStarted: function() {
// Install type unknown until download complete
check_list(null);
},
onInstallStarted: function() {
check_list(gItem);
},
onInstallEnded: function() {
check_list(gItem);
run_next_test();
}
});
gItem.install();
});
// Test that restarting the manager does not change list
add_test(function() {
restart_manager(gManagerWindow, VIEW_ID, function(aManagerWindow) {
gManagerWindow = aManagerWindow;
check_list(gItem);
run_next_test();
});
});
// Test that onInstallCancelled removes install and shows empty notice
add_test(function() {
gItem.cancel();
gItem = null;
check_list(null);
run_next_test();
});
// Test that add-ons of a different type do not show up in the list view
add_test(function() {
let extension = gProvider.createInstalls([gExtensionProperties])[0];
check_list(null);
extension.addTestListener({
onDownloadStarted: function() {
check_list(null);
},
onInstallStarted: function() {
check_list(null);
},
onInstallEnded: function() {
check_list(null);
extension.cancel();
run_next_test();
}
});
extension.install();
});
// Test that onExternalInstall properly hides empty notice and adds install to list
add_test(function() {
gItem = gProvider.createAddons([gAddonProperties])[0];
check_list(gItem);
run_next_test();
});
// Test that restarting the manager does not change list
add_test(function() {
restart_manager(gManagerWindow, VIEW_ID, function(aManagerWindow) {
gManagerWindow = aManagerWindow;
check_list(gItem);
run_next_test();
});
});

View File

@ -597,14 +597,20 @@ MockProvider.prototype = {
createInstalls: function MP_createInstalls(aInstallProperties) {
var newInstalls = [];
aInstallProperties.forEach(function(aInstallProp) {
var install = new MockInstall();
var install = new MockInstall(aInstallProp.name || null,
aInstallProp.type || null,
null);
for (var prop in aInstallProp) {
if (prop == "sourceURI") {
install[prop] = NetUtil.newURI(aInstallProp[prop]);
continue;
switch (prop) {
case "name":
case "type":
break;
case "sourceURI":
install[prop] = NetUtil.newURI(aInstallProp[prop]);
break;
default:
install[prop] = aInstallProp[prop];
}
install[prop] = aInstallProp[prop];
}
this.addInstall(install);
newInstalls.push(install);
@ -971,7 +977,9 @@ MockAddon.prototype = {
function MockInstall(aName, aType, aAddonToInstall) {
this.name = aName || "";
this.type = aType || "extension";
// Don't expose type until download completed
this._type = aType || "extension";
this.type = null;
this.version = "1.0";
this.iconURL = "";
this.infoURL = "";
@ -1004,6 +1012,8 @@ MockInstall.prototype = {
return;
}
this.type = this._type;
// Adding addon to MockProvider to be implemented when needed
if (this._addonToInstall)
this.addon = this._addonToInstall;