Bug 558134: Cancelling add-on installs for already installed add-ons does not clean up the install from the list. r=Unfocused, a=blocks-final
authorDave Townsend <dtownsend@oxymoronical.com>
Wed, 06 Oct 2010 10:14:46 -0700
changeset 54984 5ba23deb185657838b087e8dbed87157217c86e2
parent 54983 c619eb7a24d0878ea7576bd5ae5b276d74f1c9bb
child 54985 a8bf9ed4846ddccd2e4a4c86bdc9f3960cb59c92
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersUnfocused, blocks-final
bugs558134
milestone2.0b8pre
Bug 558134: Cancelling add-on installs for already installed add-ons does not clean up the install from the list. r=Unfocused, a=blocks-final
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/test/browser/Makefile.in
toolkit/mozapps/extensions/test/browser/addons/browser_install/install.rdf
toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf
toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf
toolkit/mozapps/extensions/test/browser/browser_install.js
toolkit/mozapps/extensions/test/browser/browser_install.rdf
toolkit/mozapps/extensions/test/browser/browser_install.xml
toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -4296,23 +4296,23 @@ AddonInstall.prototype = {
         if (stagedAddon.exists())
           stagedAddon.remove(false);
       }
       if (stagedJSON.exists())
         stagedJSON.remove(true);
       this.state = AddonManager.STATE_CANCELLED;
       XPIProvider.removeActiveInstall(this);
 
-      AddonManagerPrivate.callAddonListeners("onOperationCancelled", createWrapper(this.addon));
-
       if (this.existingAddon) {
         delete this.existingAddon.pendingUpgrade;
         this.existingAddon.pendingUpgrade = null;
       }
 
+      AddonManagerPrivate.callAddonListeners("onOperationCancelled", createWrapper(this.addon));
+
       AddonManagerPrivate.callInstallListeners("onInstallCancelled",
                                                this.listeners, this.wrapper);
       break;
     default:
       throw new Error("Cannot cancel from this state");
     }
   },
 
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -247,23 +247,18 @@ var gEventManager = {
   },
 
   delegateInstallEvent: function(aEvent, aParams) {
     var install = aParams[0];
     if (install.existingAddon) {
       // install is an update
       let addon = install.existingAddon;
       this.delegateAddonEvent(aEvent, [addon].concat(aParams));
-      return;
     }
 
-    this.delegateNewInstallEvent(aEvent, aParams);
-  },
-
-  delegateNewInstallEvent: function(aEvent, aParams) {
     for (let i = 0; i < this._installListeners.length; i++) {
       let listener = this._installListeners[i];
       if (!(aEvent in listener))
         continue;
       try {
         listener[aEvent].apply(listener, aParams);
       } catch(e) {
         // this shouldn't be fatal
@@ -906,18 +901,17 @@ var gViewController = {
         if (!aAddon)
           return false;
         return aAddon.pendingOperations != AddonManager.PENDING_NONE;
       },
       doCommand: function(aAddon) {
         if (isPending(aAddon, "install")) {
           aAddon.install.cancel();
         } else if (isPending(aAddon, "upgrade")) {
-          this.mAddon.pendingUpgrade.install.cancel();
-          this._updateState();
+          aAddon.pendingUpgrade.install.cancel();
         } else if (isPending(aAddon, "uninstall")) {
           aAddon.cancelUninstall();
         } else if (isPending(aAddon, "enable")) {
           aAddon.userDisabled = true;
         } else if (isPending(aAddon, "disable")) {
           aAddon.userDisabled = false;
         }
       }
@@ -1061,20 +1055,18 @@ function createItem(aObj, aIsInstall, aI
   return item;
 }
 
 function getAddonsAndInstalls(aType, aCallback) {
   var addonTypes = null, installTypes = null;
   if (aType != null) {
     addonTypes = [aType];
     installTypes = [aType];
-    if (aType == "extension") {
-      addonTypes.push("bootstrapped");
+    if (aType == "extension")
       installTypes = addonTypes.concat("");
-    }
   }
 
   var addons = null, installs = null;
 
   AddonManager.getAddonsByTypes(addonTypes, function(aAddonsList) {
     addons = aAddonsList;
     if (installs != null)
       aCallback(addons, installs);
@@ -1736,17 +1728,20 @@ var gListView = {
       hints += " integer";
 
     var sortService = Cc["@mozilla.org/xul/xul-sort-service;1"].
                       getService(Ci.nsIXULSortService);
     sortService.sort(this._listBox, aSortBy, hints);
   },
 
   onNewInstall: function(aInstall) {
-    // the event manager ensures that upgrades are filtered out
+    // 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;
 
@@ -1757,16 +1752,23 @@ var gListView = {
   onDownloadCancelled: function(aInstall) {
     this.removeInstall(aInstall);
   },
 
   onInstallCancelled: function(aInstall) {
     this.removeInstall(aInstall);
   },
 
+  onInstallEnded: function(aInstall) {
+    // Remove any install entries for upgrades, their status will appear against
+    // the existing item
+    if (aInstall.existingAddon)
+      this.removeInstall(aInstall);
+  },
+
   removeInstall: function(aInstall) {
     for (let i = 0; i < this._listBox.childNodes.length; i++) {
       let item = this._listBox.childNodes[i];
       if (item.mInstall == aInstall) {
         this._listBox.removeChild(item);
         return;
       }
     }
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -656,17 +656,18 @@
         <body><![CDATA[
           this.refreshState();
         ]]></body>
       </method>
 
       <method name="onInstallEnded">
         <body><![CDATA[
           this.refreshState();
-          this.mControl.onInstallCompleted();
+          if ("onInstallCompleted" in this.mControl)
+            this.mControl.onInstallCompleted();
         ]]></body>
       </method>
 
       <method name="onInstallFailed">
         <body><![CDATA[
           this.refreshState();
         ]]></body>
       </method>
--- a/toolkit/mozapps/extensions/test/browser/Makefile.in
+++ b/toolkit/mozapps/extensions/test/browser/Makefile.in
@@ -71,17 +71,19 @@ include $(DEPTH)/config/autoconf.mk
   browser_searching.js \
   browser_searching.xml \
   browser_searching_empty.xml \
   browser_sorting.js \
   browser_uninstalling.js \
   browser_updatessl.js \
   browser_updatessl.rdf \
   browser_install.js \
+  browser_install.rdf \
   browser_install.xml \
+  browser_install1_3.xpi \
   browser_installssl.js \
   browser_recentupdates.js \
   browser_manualupdates.js \
   browser_globalwarnings.js \
   redirect.sjs \
   releaseNotes.xhtml \
   $(NULL)
 
rename from toolkit/mozapps/extensions/test/browser/addons/browser_install/install.rdf
rename to toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf
--- a/toolkit/mozapps/extensions/test/browser/addons/browser_install/install.rdf
+++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_1/install.rdf
@@ -1,16 +1,18 @@
 <?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>addon1@tests.mozilla.org</em:id>
     <em:version>1.0</em:version>
+    <em:bootstrap>true</em:bootstrap>
+    <em:updateURL>http://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install.rdf</em:updateURL>
 
     <em:targetApplication>
       <Description>
         <em:id>toolkit@mozilla.org</em:id>
         <em:minVersion>0</em:minVersion>
         <em:maxVersion>*</em:maxVersion>
       </Description>
     </em:targetApplication>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2/install.rdf
@@ -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>addon1@tests.mozilla.org</em:id>
+    <em:version>2.0</em:version>
+
+    <em:targetApplication>
+      <Description>
+        <em:id>toolkit@mozilla.org</em:id>
+        <em:minVersion>0</em:minVersion>
+        <em:maxVersion>*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <em:name>Install Tests</em:name>
+
+  </Description>
+</RDF>
--- a/toolkit/mozapps/extensions/test/browser/browser_install.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_install.js
@@ -11,46 +11,87 @@ var gApp = document.getElementById("bund
 var gSearchCount = 0;
 
 function test() {
   waitForExplicitFinish();
 
   // Turn on searching for this test
   Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
   Services.prefs.setCharPref("extensions.getAddons.search.url", TESTROOT + "browser_install.xml");
+  // Allow http update checks
+  Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
 
   open_manager(null, function(aWindow) {
     gManagerWindow = aWindow;
     gCategoryUtilities = new CategoryUtilities(gManagerWindow);
     run_next_test();
   });
 }
 
 function end_test() {
   close_manager(gManagerWindow, function() {
+    Services.prefs.clearUserPref("extensions.getAddons.search.url");
+    Services.prefs.clearUserPref("extensions.checkUpdateSecurity");
+
+    AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) {
+      aAddon.uninstall();
+    });
     finish();
   });
 }
 
 function get_node(parent, anonid) {
   return parent.ownerDocument.getAnonymousElementByAttribute(parent, "anonid", anonid);
 }
 
 function installAddon(aCallback) {
-  AddonManager.getInstallForURL(TESTROOT + "addons/browser_install.xpi",
+  AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_2.xpi",
                                 function(aInstall) {
     aInstall.addListener({
       onInstallEnded: function() {
         executeSoon(aCallback);
       }
     });
     aInstall.install();
   }, "application/x-xpinstall");
 }
 
+function installUpgrade(aCallback) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) {
+    aAddon.findUpdates({
+      onUpdateAvailable: function(aAddon, aInstall) {
+        is(get_list_item_count(), 1, "Should be only one item in the list");
+
+        aInstall.addListener({
+          onInstallEnded: function() {
+            executeSoon(aCallback);
+          }
+        });
+        aInstall.install();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+function cancelInstall(aCallback) {
+  AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_2.xpi",
+                                function(aInstall) {
+    aInstall.addListener({
+      onDownloadEnded: function(aInstall) {
+        executeSoon(function() {
+          aInstall.cancel();
+          aCallback();
+        });
+        return false;
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
 function installSearchResult(aCallback) {
   var searchBox = gManagerWindow.document.getElementById("header-search");
   // Search for something different each time
   searchBox.value = "foo" + gSearchCount;
   gSearchCount++;
 
   EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
   EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
@@ -68,29 +109,65 @@ function installSearchResult(aCallback) 
     item.mInstall.addListener({
       onInstallEnded: function() {
         executeSoon(aCallback);
       }
     });
   });
 }
 
+function get_list_item_count() {
+  let view = gManagerWindow.document.getElementById("view-port").selectedPanel;
+  let listid = view.id == "search-view" ? "search-list" : "addon-list";
+  let list = gManagerWindow.document.getElementById(listid);
+  let count = list.childNodes.length;
+  // Remove the show all results item
+  if (view.id == "search-view")
+    count--;
+
+  return count;
+}
+
 function check_undo_install() {
+  is(get_list_item_count(), 1, "Should be only one item in the list");
+
   let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
   ok(!!item, "Should see the pending install in the list");
   // Force XBL to apply
   item.clientTop;
   is_element_visible(get_node(item, "pending"), "Pending message should be visible");
   is(get_node(item, "pending").textContent, "Install Tests will be installed after you restart " + gApp + ".", "Pending message should be correct");
 
   EventUtils.synthesizeMouse(get_node(item, "undo"), 2, 2, {}, gManagerWindow);
+
+  is(get_list_item_count(), 0, "Should be no items in the list");
+
   item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
   ok(!item, "Should no longer see the pending install");
 }
 
+function check_undo_upgrade() {
+  is(get_list_item_count(), 1, "Should be only one item in the list");
+
+  let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+  ok(!!item, "Should see the pending upgrade in the list");
+  // Force XBL to apply
+  item.clientTop;
+  is_element_visible(get_node(item, "pending"), "Pending message should be visible");
+  is(get_node(item, "pending").textContent, "Install Tests will be updated after you restart " + gApp + ".", "Pending message should be correct");
+
+  EventUtils.synthesizeMouse(get_node(item, "undo"), 2, 2, {}, gManagerWindow);
+
+  is(get_list_item_count(), 1, "Should be only one item in the list");
+
+  item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+  ok(!!item, "Should still see installed item in the list");
+  is_element_hidden(get_node(item, "pending"), "Pending message should be hidden");
+}
+
 // Install an add-on through the API with the manager open
 add_test(function() {
   gCategoryUtilities.openType("extension", function() {
     installAddon(function() {
       check_undo_install();
       run_next_test();
     });
   });
@@ -138,8 +215,105 @@ add_test(function() {
         gManagerWindow = aWindow;
         gCategoryUtilities = new CategoryUtilities(gManagerWindow);
         check_undo_install();
         run_next_test();
       });
     });
   });
 });
+
+// Cancel an install after download with the manager open
+add_test(function() {
+  cancelInstall(function() {
+    is(get_list_item_count(), 0, "Should be no items in the list");
+
+    run_next_test();
+  });
+});
+
+// Cancel an install after download with the manager closed
+add_test(function() {
+  close_manager(gManagerWindow, function() {
+    cancelInstall(function() {
+      open_manager(null, function(aWindow) {
+        gManagerWindow = aWindow;
+        gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+        is(get_list_item_count(), 0, "Should be no items in the list");
+
+        run_next_test();
+      });
+    });
+  });
+});
+
+// Install an existing add-on for the subsequent tests
+add_test(function() {
+  AddonManager.getInstallForURL(TESTROOT + "addons/browser_install1_1.xpi",
+                                function(aInstall) {
+    aInstall.addListener({
+      onInstallEnded: function() {
+        executeSoon(run_next_test);
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+});
+
+// Install an upgrade through the API with the manager open
+add_test(function() {
+  installAddon(function() {
+    check_undo_upgrade();
+    run_next_test();
+  });
+});
+
+// Install an upgrade through the API with the manager open
+add_test(function() {
+  installUpgrade(function() {
+    check_undo_upgrade();
+    run_next_test();
+  });
+});
+
+// Install an upgrade through the API with the manager closed
+add_test(function() {
+  close_manager(gManagerWindow, function() {
+    installAddon(function() {
+      open_manager(null, function(aWindow) {
+        gManagerWindow = aWindow;
+        gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+        check_undo_upgrade();
+        run_next_test();
+      });
+    });
+  });
+});
+
+// Cancel an upgrade after download with the manager open
+add_test(function() {
+  cancelInstall(function() {
+    is(get_list_item_count(), 1, "Should be no items in the list");
+    let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+    ok(!!item, "Should still see installed item in the list");
+    is_element_hidden(get_node(item, "pending"), "Pending message should be hidden");
+
+    run_next_test();
+  });
+});
+
+// Cancel an upgrade after download with the manager closed
+add_test(function() {
+  close_manager(gManagerWindow, function() {
+    cancelInstall(function() {
+      open_manager(null, function(aWindow) {
+        gManagerWindow = aWindow;
+        gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+        is(get_list_item_count(), 1, "Should be no items in the list");
+        let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
+        ok(!!item, "Should still see installed item in the list");
+        is_element_hidden(get_node(item, "pending"), "Pending message should be hidden");
+
+        run_next_test();
+      });
+    });
+  });
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_install.rdf
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<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:extension:addon1@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>toolkit@mozilla.org</em:id>
+                <em:minVersion>0</em:minVersion>
+                <em:maxVersion>*</em:maxVersion>
+                <em:updateLink>https://example.com/browser/toolkit/mozapps/extensions/test/browser/browser_install1_3.xpi</em:updateLink>
+                <em:updateHash>sha1:6760e51269941245105a17076afeb5f45621de0e</em:updateHash>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+
+</RDF>
--- a/toolkit/mozapps/extensions/test/browser/browser_install.xml
+++ b/toolkit/mozapps/extensions/test/browser/browser_install.xml
@@ -24,11 +24,11 @@
       <application>
         <name>SeaMonkey</name>
         <appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
         <min_version>0</min_version>
         <max_version>*</max_version>
       </application>
     </compatible_applications>
     <compatible_os>ALL</compatible_os>
-    <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_install.xpi</install>
+    <install size="2">http://example.com/browser/toolkit/mozapps/extensions/test/browser/addons/browser_install1_2.xpi</install>
   </addon>
 </searchresults>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..31bb4b2a6c6cdccfcd3d40bf4cf0e5fb70f97080
GIT binary patch
literal 463
zc$^FHW@Zs#U}E54_?u~GyIZ};UYU`B!Ig=Dftx{wAv3SIBrzvPuP7xgG=!6Z`QQ5`
zJ|J9L!Og(P@)f8OsF{JGG$_`;*+8WBdH9ugXO~PdjCX4|o1*vepm=i4{=Pi3Z_QiE
zjsAXhYRq+cEB$=&^E=+3uX<{K(wsB>nn;P9dP%5T;J-aLCrvZlx8Qw8>9NYoCWV_j
z)>?n~S+w(s=c&t6c4nRbGu_d`@Nv3{(p}DDJ})}MZ|AQRY2m)4vh%T1`8&zn#~dfk
z551qWX5(7N2WRCrE^trZba1NYW5Fp&QayLL``51aKGk|ICDbW2(l|cZ`^W1AbH4wH
zwC0J@d!$nExV$7xVMp_U-@C$!*d=xtTwe09V=niCt*@LP{o4N~aMjXES*71h;RixE
zmJ9BG+bW)*bEMvs>y*9Pi<8pFPF#y@esVD6iKjviL!&|2&3;DRQ^)JBKUo@`zQgFi
zLvvr_;(Plh8~tJo@MdI^W5yNI5)2>!<T5O21hG)UofQ)9Xki}U&B_MR#K;f`q%%Oe
F82}+?y6*r0