Bug 1279441 - fix HTMLTooltip closing after click on inner iframe;r=bgrins
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 10 Jun 2016 11:24:04 +0200
changeset 301463 52b012fa432c0b10381dcd168a766e49d4e5ac2a
parent 301462 cd4cfadeedf2baf9feb63a2b83f2057ba5693c4a
child 301464 0cdadfe2548071a155138fa486b7ed7753f68bee
push id30335
push usercbook@mozilla.com
push dateSun, 12 Jun 2016 09:25:20 +0000
treeherdermozilla-central@9694e3713635 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1279441
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);
     }