Bug 562854: Double-click goes through buttons in the new add-ons manager. r+a=dtownsend
authorGeoff Lankow <geoff@darktrojan.net>
Tue, 11 Jan 2011 09:49:50 -0800
changeset 60307 fc1817a3d7a4cba01542acb0f949af292cbc0617
parent 60306 d48eb4e9d90301b0a684047109ef4b9cc1e6a2a8
child 60308 00893dfbaedb0462a7f1e251bf64bbb0bb042b61
push idunknown
push userunknown
push dateunknown
bugs562854
milestone2.0b10pre
Bug 562854: Double-click goes through buttons in the new add-ons manager. r+a=dtownsend
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/test/browser/Makefile.in
toolkit/mozapps/extensions/test/browser/browser_bug562797.js
toolkit/mozapps/extensions/test/browser/browser_bug562854.js
toolkit/mozapps/extensions/test/browser/browser_details.js
toolkit/mozapps/extensions/test/browser/browser_purchase.js
toolkit/mozapps/extensions/test/browser/browser_searching.js
toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -1622,18 +1622,30 @@
       <method name="onInstallCancelled">
         <body><![CDATA[
             this._updateState();
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
-      <handler event="click" button="0" clickcount="2"><![CDATA[
-        this.showInDetailView();
+      <handler event="click" button="0"><![CDATA[
+        switch (event.detail) {
+        case 1:
+          // Prevent double-click where the UI changes on the first click
+          this._lastClickTarget = event.originalTarget;
+          break;
+        case 2:
+          if (event.originalTarget.localName != 'button' &&
+              !event.originalTarget.classList.contains('text-link') &&
+              event.originalTarget == this._lastClickTarget) {
+            this.showInDetailView();
+          }
+          break;
+        }
       ]]></handler>
     </handlers>
   </binding>
 
 
   <!-- Addon - uninstalled - An uninstalled addon that can be re-installed. -->
   <binding id="addon-uninstalled"
            extends="chrome://mozapps/content/extensions/extensions.xml#addon-base">
--- a/toolkit/mozapps/extensions/test/browser/Makefile.in
+++ b/toolkit/mozapps/extensions/test/browser/Makefile.in
@@ -45,16 +45,17 @@ TESTXPI = $(CURDIR)/$(DEPTH)/_tests/test
 
 include $(DEPTH)/config/autoconf.mk
 
 _MAIN_TEST_FILES = \
   head.js \
   browser_about.js \
   browser_bug557943.js \
   browser_bug562797.js \
+  browser_bug562854.js \
   browser_bug562890.js \
   browser_bug562899.js \
   browser_bug562992.js \
   browser_bug567127.js \
   browser_bug567137.js \
   browser_bug572561.js \
   browser_bug577990.js \
   browser_bug581076.js \
--- a/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug562797.js
@@ -94,16 +94,17 @@ function is_in_detail(aManager, view, ca
   is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view");
 
   check_state(aManager, canGoBack, canGoForward);
 }
 
 function double_click_addon_element(aManager, aId) {
   var addon = get_addon_element(aManager, aId);
   addon.parentNode.ensureElementIsVisible(addon);
+  EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager);
   EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager);
 }
 
 // Tests simple forward and back navigation and that the right heading and
 // category is selected
 add_test(function() {
   open_manager("addons://list/extension", function(aManager) {
     info("Part 1");
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js
@@ -0,0 +1,129 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Tests that double-click does not go to detail view if the target is a link or button.
+ */
+
+function test() {
+  requestLongerTimeout(2);
+
+  waitForExplicitFinish();
+
+  var gProvider = new MockProvider();
+  gProvider.createAddons([{
+    id: "test1@tests.mozilla.org",
+    name: "Test add-on 1",
+    description: "foo",
+    operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
+  }]);
+
+  run_next_test();
+}
+
+function end_test() {
+  finish();
+}
+
+function is_in_list(aManager, view) {
+  var doc = aManager.document;
+
+  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
+  is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view");
+}
+
+function is_in_detail(aManager, view) {
+  var doc = aManager.document;
+
+  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
+  is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view");
+}
+
+// Check that double-click does something.
+add_test(function() {
+  open_manager("addons://list/extension", function(aManager) {
+    info("Part 1");
+    is_in_list(aManager, "addons://list/extension");
+
+    var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+    addon.parentNode.ensureElementIsVisible(addon);
+    EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager);
+    EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager);
+
+    wait_for_view_load(aManager, function(aManager) {
+      info("Part 2");
+      is_in_detail(aManager, "addons://list/extension");
+
+      close_manager(aManager, run_next_test);
+    });
+  });
+});
+
+// Check that double-click does nothing when over the disable button.
+add_test(function() {
+  open_manager("addons://list/extension", function(aManager) {
+    info("Part 1");
+    is_in_list(aManager, "addons://list/extension");
+
+    var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+    addon.parentNode.ensureElementIsVisible(addon);
+    EventUtils.synthesizeMouseAtCenter(
+      aManager.document.getAnonymousElementByAttribute(addon, "anonid", "disable-btn"),
+      { clickCount: 1 },
+      aManager
+    );
+    // The disable button is replaced by the enable button when clicked on.
+    EventUtils.synthesizeMouseAtCenter(
+      aManager.document.getAnonymousElementByAttribute(addon, "anonid", "enable-btn"),
+      { clickCount: 2 },
+      aManager
+    );
+
+    wait_for_view_load(aManager, function(aManager) {
+      info("Part 2");
+      is_in_list(aManager, "addons://list/extension");
+
+      close_manager(aManager, run_next_test);
+    });
+  });
+});
+
+// Check that double-click does nothing when over the undo button.
+add_test(function() {
+  open_manager("addons://list/extension", function(aManager) {
+    info("Part 1");
+    is_in_list(aManager, "addons://list/extension");
+
+    var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+    addon.parentNode.ensureElementIsVisible(addon);
+    EventUtils.synthesizeMouseAtCenter(
+      aManager.document.getAnonymousElementByAttribute(addon, "anonid", "remove-btn"),
+      { clickCount: 1 },
+      aManager
+    );
+
+    // The undo button is removed when clicked on.
+    // We need to wait for the UI to catch up.
+    setTimeout(function() {
+      var target = aManager.document.getAnonymousElementByAttribute(addon, "anonid", "undo-btn");
+      var rect = target.getBoundingClientRect();
+      var addonRect = addon.getBoundingClientRect();
+
+      EventUtils.synthesizeMouse(target, rect.width / 2, rect.height / 2, { clickCount: 1 }, aManager);
+      EventUtils.synthesizeMouse(addon,
+        rect.left - addonRect.left + rect.width / 2,
+        rect.top - addonRect.top + rect.height / 2,
+        { clickCount: 2 },
+        aManager
+      );
+
+      wait_for_view_load(aManager, function(aManager) {
+        info("Part 2");
+        is_in_list(aManager, "addons://list/extension");
+
+        close_manager(aManager, run_next_test);
+      });
+    }, 0);
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_details.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_details.js
@@ -22,16 +22,17 @@ function open_details(aId, aType, aCallb
   requestLongerTimeout(2);
 
   gCategoryUtilities.openType(aType, function() {
     var list = gManagerWindow.document.getElementById("addon-list");
     var item = list.firstChild;
     while (item) {
       if ("mAddon" in item && item.mAddon.id == aId) {
         list.ensureElementIsVisible(item);
+        EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
         EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
         wait_for_view_load(gManagerWindow, aCallback);
         return;
       }
       item = item.nextSibling;
     }
     ok(false, "Should have found the add-on in the list");
   });
--- a/toolkit/mozapps/extensions/test/browser/browser_purchase.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_purchase.js
@@ -176,16 +176,17 @@ add_test(function() {
     else {
       waitForFocus(run_next_test, gManagerWindow);
     }
   }, true);
 
   var list = gManagerWindow.document.getElementById("search-list");
   var item = list.firstChild.nextSibling;
   list.ensureElementIsVisible(item);
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
   EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
 
   wait_for_view_load(gManagerWindow, function() {
     var btn = gManagerWindow.document.getElementById("detail-purchase-btn");
     is_element_visible(btn, "Purchase button should be visible");
 
     EventUtils.synthesizeMouseAtCenter(btn, { }, gManagerWindow);
   });
--- a/toolkit/mozapps/extensions/test/browser/browser_searching.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js
@@ -442,16 +442,17 @@ add_test(function() {
       var result = results[currentIndex];
       if (result.name.indexOf("install") == 0) {
         run_next_double_click_test();
         return;
       }
 
       var item = result.item;
       list.ensureElementIsVisible(item);
+      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
       EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
       wait_for_view_load(gManagerWindow, function() {
         var name = gManagerWindow.document.getElementById("detail-name").textContent;
         is(name, item.mAddon.name, "Name in detail view should be correct");
         var version = gManagerWindow.document.getElementById("detail-version").value;
         is(version, item.mAddon.version, "Version in detail view should be correct");
 
         EventUtils.synthesizeMouseAtCenter(gManagerWindow.document.getElementById("category-search"),
--- a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
@@ -444,16 +444,17 @@ add_test(function() {
 
     AddonManager.getAddonByID(ID, function(aAddon) {
       ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
       ok(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL, "Add-on should require a restart to uninstall");
 
       var item = get_item_in_list(ID, list);
       isnot(item, null, "Should have found the add-on in the list");
 
+      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
       EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
       wait_for_view_load(gManagerWindow, function() {
         is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view");
 
         var button = gDocument.getElementById("detail-uninstall-btn");
         isnot(button, null, "Should have a remove button");
         ok(!button.disabled, "Button should not be disabled");
 
@@ -507,16 +508,17 @@ add_test(function() {
     AddonManager.getAddonByID(ID, function(aAddon) {
       ok(aAddon.isActive, "Add-on should be active");
       ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
       ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
       var item = get_item_in_list(ID, list);
       isnot(item, null, "Should have found the add-on in the list");
 
+      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
       EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
       wait_for_view_load(gManagerWindow, function() {
         is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view");
 
         var button = gDocument.getElementById("detail-uninstall-btn");
         isnot(button, null, "Should have a remove button");
         ok(!button.disabled, "Button should not be disabled");
 
@@ -573,16 +575,17 @@ add_test(function() {
 
       ok(!aAddon.isActive, "Add-on should be inactive");
       ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
       ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
       var item = get_item_in_list(ID, list);
       isnot(item, null, "Should have found the add-on in the list");
 
+      EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
       EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
       wait_for_view_load(gManagerWindow, function() {
         is(gDocument.getElementById("view-port").selectedPanel.id, "detail-view", "Should be in the detail view");
 
         var button = gDocument.getElementById("detail-uninstall-btn");
         isnot(button, null, "Should have a remove button");
         ok(!button.disabled, "Button should not be disabled");