Bug 1279441 - fix HTMLTooltip closing after click on inner iframe;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 10 Jun 2016 11:24:04 +0200
changeset 377459 4c0c08694226c29bd8fcdd8f61093f5a9d53afbe
parent 377458 bf436e92bff8b6369f1fff4bd308f10206834515
child 523355 07231f7719b6c5fa29dfa92cf79c9ce4c249dc9a
push id20798
push userjdescottes@mozilla.com
push dateFri, 10 Jun 2016 11:50:41 +0000
reviewersbgrins
bugs1279441
milestone50.0a1
Bug 1279441 - fix HTMLTooltip closing after click on inner iframe;r=bgrins MozReview-Commit-ID: EggheTpU2y3
devtools/client/shared/test/browser_html_tooltip-02.js
devtools/client/shared/widgets/HTMLTooltip.js
--- a/devtools/client/shared/test/browser_html_tooltip-02.js
+++ b/devtools/client/shared/test/browser_html_tooltip-02.js
@@ -1,12 +1,11 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* import-globals-from helper_html_tooltip.js */
-
 "use strict";
 
 /**
  * Test the HTMLTooltip is closed when clicking outside of its container.
  */
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const TEST_URI = `data:text/xml;charset=UTF-8,<?xml version="1.0"?>
@@ -27,23 +26,24 @@ const TEST_URI = `data:text/xml;charset=
 
 const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
 loadHelperScript("helper_html_tooltip.js");
 
 add_task(function* () {
   yield addTab("about:blank");
   let [,, doc] = yield createHost("bottom", TEST_URI);
 
-  yield testTooltipNotClosingOnInsideClick(doc);
+  yield testClickInTooltipContent(doc);
   yield testConsumeOutsideClicksFalse(doc);
   yield testConsumeOutsideClicksTrue(doc);
-  yield testClickInsideIframe(doc);
+  yield testClickInOuterIframe(doc);
+  yield testClickInInnerIframe(doc);
 });
 
-function* testTooltipNotClosingOnInsideClick(doc) {
+function* testClickInTooltipContent(doc) {
   info("Test a tooltip is not closed when clicking inside itself");
 
   let tooltip = new HTMLTooltip({doc}, {});
   yield tooltip.setContent(getTooltipContent(doc), 100, 50);
   yield showTooltip(tooltip, doc.getElementById("box1"));
 
   let onTooltipContainerClick = once(tooltip.container, "click");
   EventUtils.synthesizeMouseAtCenter(tooltip.container, {}, doc.defaultView);
@@ -89,31 +89,51 @@ function* testConsumeOutsideClicksTrue(d
   yield onHidden;
 
   is(box4clicks, 0, "box4 catched no click event");
   is(tooltip.isVisible(), false, "Tooltip is hidden");
 
   tooltip.destroy();
 }
 
-function* testClickInsideIframe(doc) {
-  info("Test closing a tooltip via click inside an iframe");
+function* testClickInOuterIframe(doc) {
+  info("Test clicking an iframe outside of the tooltip closes the tooltip");
   let frame = doc.getElementById("frame");
 
   let tooltip = new HTMLTooltip({doc});
   yield tooltip.setContent(getTooltipContent(doc), 100, 50);
   yield showTooltip(tooltip, doc.getElementById("box1"));
 
   let onHidden = once(tooltip, "hidden");
   EventUtils.synthesizeMouseAtCenter(frame, {}, doc.defaultView);
   yield onHidden;
 
   is(tooltip.isVisible(), false, "Tooltip is hidden");
   tooltip.destroy();
 }
 
+function* testClickInInnerIframe(doc) {
+  info("Test clicking an iframe inside the tooltip content does not close the tooltip");
+
+  let tooltip = new HTMLTooltip({doc}, {consumeOutsideClicks: false});
+
+  let iframe = doc.createElementNS(HTML_NS, "iframe");
+  iframe.style.width = "100px";
+  iframe.style.height = "50px";
+  yield tooltip.setContent(iframe, 100, 50);
+  yield showTooltip(tooltip, doc.getElementById("box1"));
+
+  let onTooltipContainerClick = once(tooltip.container, "click");
+  EventUtils.synthesizeMouseAtCenter(tooltip.container, {}, doc.defaultView);
+  yield onTooltipContainerClick;
+
+  is(tooltip.isVisible(), true, "Tooltip is still visible");
+
+  tooltip.destroy();
+}
+
 function getTooltipContent(doc) {
   let div = doc.createElementNS(HTML_NS, "div");
   div.style.height = "50px";
   div.style.boxSizing = "border-box";
   div.textContent = "tooltip";
   return div;
 }
--- a/devtools/client/shared/widgets/HTMLTooltip.js
+++ b/devtools/client/shared/widgets/HTMLTooltip.js
@@ -245,20 +245,22 @@ HTMLTooltip.prototype = {
 
     // Check if the tooltip panel contains the node if they live in the same document.
     if (win === tooltipWindow) {
       return this.panel.contains(node);
     }
 
     // Check if the node window is in the tooltip container.
     while (win.parent && win.parent != win) {
-      win = win.parent;
-      if (win === tooltipWindow) {
+      if (win.parent === tooltipWindow) {
+        // If the parent window is the tooltip window, check if the tooltip contains
+        // the current frame element.
         return this.panel.contains(win.frameElement);
       }
+      win = win.parent;
     }
 
     return false;
   },
 
   /**
    * Calculates the best possible position to display the tooltip near the
    * provided anchor. An optional position can be provided, but will be
@@ -318,17 +320,17 @@ HTMLTooltip.prototype = {
     // Arrow style tooltips may need to be shifted to the left
     if (this.type === TYPE.ARROW) {
       let arrowCenter = left + ARROW_OFFSET + ARROW_WIDTH / 2;
       let anchorCenter = anchorLeft + anchorWidth / 2;
       // If the anchor is too narrow, align the arrow and the anchor center.
       if (arrowCenter > anchorCenter) {
         left = Math.max(0, left - (arrowCenter - anchorCenter));
       }
-      // Arrow's feft offset relative to the anchor.
+      // Arrow's left offset relative to the anchor.
       arrowLeft = Math.min(ARROW_OFFSET, (anchorWidth - ARROW_WIDTH) / 2) | 0;
       // Translate the coordinate to tooltip container
       arrowLeft += anchorLeft - left;
       // Make sure the arrow remains in the tooltip container.
       arrowLeft = Math.min(arrowLeft, width - ARROW_WIDTH);
       arrowLeft = Math.max(arrowLeft, 0);
     }