Bug 941862 - UITour: Support a callback to notify when the menu panel opens while the menu button is an info panel target. r=Unfocused a=Sylvestre
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Sat, 29 Mar 2014 18:41:29 -0700
changeset 191395 a051669b62ea522fc90c3c88f7671a8943f6c166
parent 191394 629760276aaaa702df856bd514a276c13a43f1b7
child 191396 74d94bd2db30e2d38120e8e15c2ba5ec190b3427
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersUnfocused, Sylvestre
bugs941862
milestone30.0a2
Bug 941862 - UITour: Support a callback to notify when the menu panel opens while the menu button is an info panel target. r=Unfocused a=Sylvestre
browser/modules/UITour.jsm
browser/modules/test/browser_UITour3.js
browser/modules/test/uitour.html
browser/modules/test/uitour.js
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -66,17 +66,27 @@ this.UITour = {
         let statusButton = aDocument.getElementById("PanelUI-fxa-status");
         return aDocument.getAnonymousElementByAttribute(statusButton,
                                                         "class",
                                                         "toolbarbutton-icon");
       },
       widgetName: "PanelUI-fxa-status",
     }],
     ["addons",      {query: "#add-ons-button"}],
-    ["appMenu",     {query: "#PanelUI-button"}],
+    ["appMenu",     {
+      addTargetListener: (aDocument, aCallback) => {
+        let panelPopup = aDocument.getElementById("PanelUI-popup");
+        panelPopup.addEventListener("popupshown", aCallback);
+      },
+      query: "#PanelUI-button",
+      removeTargetListener: (aDocument, aCallback) => {
+        let panelPopup = aDocument.getElementById("PanelUI-popup");
+        panelPopup.removeEventListener("popupshown", aCallback);
+      },
+    }],
     ["backForward", {
       query: "#back-button",
       widgetName: "urlbar-container",
     }],
     ["bookmarks",   {query: "#bookmarks-menu-button"}],
     ["customize",   {
       query: (aDocument) => {
         let customizeButton = aDocument.getElementById("PanelUI-customize");
@@ -324,16 +334,18 @@ this.UITour = {
               }
             }
           }
 
           let infoOptions = {};
 
           if (typeof data.closeButtonCallbackID == "string")
             infoOptions.closeButtonCallbackID = data.closeButtonCallbackID;
+          if (typeof data.targetCallbackID == "string")
+            infoOptions.targetCallbackID = data.targetCallbackID;
 
           this.showInfo(contentDocument, target, data.title, data.text, iconURL, buttons, infoOptions);
         }).then(null, Cu.reportError);
         break;
       }
 
       case "hideInfo": {
         this.hideInfo(window);
@@ -668,26 +680,30 @@ this.UITour = {
       deferred.reject("The specified target name is not in the allowed set");
       return deferred.promise;
     }
 
     let targetQuery = targetObject.query;
     aWindow.PanelUI.ensureReady().then(() => {
       if (typeof targetQuery == "function") {
         deferred.resolve({
+          addTargetListener: targetObject.addTargetListener,
+          node: targetQuery(aWindow.document),
+          removeTargetListener: targetObject.removeTargetListener,
           targetName: aTargetName,
-          node: targetQuery(aWindow.document),
           widgetName: targetObject.widgetName,
         });
         return;
       }
 
       deferred.resolve({
+        addTargetListener: targetObject.addTargetListener,
+        node: aWindow.document.querySelector(targetQuery),
+        removeTargetListener: targetObject.removeTargetListener,
         targetName: aTargetName,
-        node: aWindow.document.querySelector(targetQuery),
         widgetName: targetObject.widgetName,
       });
     }).then(null, Cu.reportError);
     return deferred.promise;
   },
 
   targetIsInAppMenu: function(aTarget) {
     let placement = CustomizableUI.getPlacementOfWidget(aTarget.widgetName || aTarget.node.id);
@@ -931,19 +947,34 @@ this.UITour = {
 
       let tooltipClose = document.getElementById("UITourTooltipClose");
       let closeButtonCallback = (event) => {
         this.hideInfo(document.defaultView);
         if (aOptions && aOptions.closeButtonCallbackID)
           this.sendPageCallback(aContentDocument, aOptions.closeButtonCallbackID);
       };
       tooltipClose.addEventListener("command", closeButtonCallback);
+
+      let targetCallback = (event) => {
+        let details = {
+          target: aAnchor.targetName,
+          type: event.type,
+        };
+        this.sendPageCallback(aContentDocument, aOptions.targetCallbackID, details);
+      };
+      if (aOptions.targetCallbackID && aAnchor.addTargetListener) {
+        aAnchor.addTargetListener(document, targetCallback);
+      }
+
       tooltip.addEventListener("popuphiding", function tooltipHiding(event) {
         tooltip.removeEventListener("popuphiding", tooltipHiding);
         tooltipClose.removeEventListener("command", closeButtonCallback);
+        if (aOptions.targetCallbackID && aAnchor.removeTargetListener) {
+          aAnchor.removeTargetListener(document, targetCallback);
+        }
       });
 
       tooltip.setAttribute("targetName", aAnchor.targetName);
       tooltip.hidden = false;
       let alignment = "bottomcenter topright";
       this._addAnnotationPanelMutationObserver(tooltip);
       tooltip.openPopup(aAnchorEl, alignment);
     }
--- a/browser/modules/test/browser_UITour3.js
+++ b/browser/modules/test/browser_UITour3.js
@@ -133,10 +133,26 @@ let tests = [
       executeSoon(function() {
         is(gContentWindow.callbackResult, "closeButton", "Close button callback called");
         done();
       });
     });
 
     let infoOptions = gContentWindow.makeInfoOptions();
     gContentAPI.showInfo("urlbar", "Close me", "X marks the spot", null, null, infoOptions);
-  }
+  },
+
+  function test_info_target_callback(done) {
+    let popup = document.getElementById("UITourTooltip");
+    popup.addEventListener("popupshown", function onPopupShown() {
+      popup.removeEventListener("popupshown", onPopupShown);
+      PanelUI.show().then(() => {
+        is(gContentWindow.callbackResult, "target", "target callback called");
+        is(gContentWindow.callbackData.target, "appMenu", "target callback was from the appMenu");
+        is(gContentWindow.callbackData.type, "popupshown", "target callback was from the mousedown");
+        done();
+      });
+    });
+
+    let infoOptions = gContentWindow.makeInfoOptions();
+    gContentAPI.showInfo("appMenu", "I want to know when the target is clicked", "*click*", null, null, infoOptions);
+  },
 ];
--- a/browser/modules/test/uitour.html
+++ b/browser/modules/test/uitour.html
@@ -1,34 +1,36 @@
 <!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8" />
     <title>UITour test</title>
     <script type="application/javascript" src="uitour.js">
     </script>
     <script type="application/javascript">
-      var callbackResult;
+      var callbackResult, callbackData;
       function makeCallback(name) {
-        return (function() {
+        return (function(data) {
           callbackResult = name;
+          callbackData = data;
         });
       }
 
       // Defined in content to avoid weird issues when crossing between chrome/content.
       function makeButtons() {
         return [
           {label: "Button 1", callback: makeCallback("button1")},
           {label: "Button 2", callback: makeCallback("button2"), icon: "image.png"}
         ];
       }
 
       function makeInfoOptions() {
         return {
-          closeButtonCallback: makeCallback("closeButton")
+          closeButtonCallback: makeCallback("closeButton"),
+          targetCallback: makeCallback("target"),
         };
       }
     </script>
   </head>
   <body>
     <h1>UITour tests</h1>
     <p>Because Firefox is...</p>
     <p>Never gonna let you down</p>
--- a/browser/modules/test/uitour.js
+++ b/browser/modules/test/uitour.js
@@ -85,27 +85,30 @@ if (typeof Mozilla == 'undefined') {
 					label: buttons[i].label,
 					icon: buttons[i].icon,
 					style: buttons[i].style,
 					callbackID: _waitForCallback(buttons[i].callback)
 			});
 			}
 		}
 
-		var closeButtonCallbackID;
+		var closeButtonCallbackID, targetCallbackID;
 		if (options && options.closeButtonCallback)
 			closeButtonCallbackID = _waitForCallback(options.closeButtonCallback);
+		if (options && options.targetCallback)
+			targetCallbackID = _waitForCallback(options.targetCallback);
 
 		_sendEvent('showInfo', {
 			target: target,
 			title: title,
 			text: text,
 			icon: icon,
 			buttons: buttonData,
-			closeButtonCallbackID: closeButtonCallbackID
+			closeButtonCallbackID: closeButtonCallbackID,
+			targetCallbackID: targetCallbackID
 		});
 	};
 
 	Mozilla.UITour.hideInfo = function() {
 		_sendEvent('hideInfo');
 	};
 
 	Mozilla.UITour.previewTheme = function(theme) {