Bug 1326753 - Fix inspect node from browser context menu against elements in iframes. r=pbro draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 18 Jan 2017 22:08:10 +0100
changeset 463324 76bd6c00287a2f6f2dbcae0e41f100de5af92302
parent 457899 8f3b24109e3412b36f97277e31ad66856dc609d6
child 542637 06c3183de3ad83530448eb593074c11a58b1e3ae
push id42021
push userbmo:poirot.alex@gmail.com
push dateWed, 18 Jan 2017 21:09:09 +0000
reviewerspbro
bugs1326753
milestone53.0a1
Bug 1326753 - Fix inspect node from browser context menu against elements in iframes. r=pbro MozReview-Commit-ID: C4dvnISlneS
devtools/client/framework/devtools-browser.js
devtools/client/inspector/test/browser.ini
devtools/client/inspector/test/browser_inspector_inspect_node_contextmenu.js
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -235,30 +235,53 @@ var gDevToolsBrowser = exports.gDevTools
       win.focus();
     } else {
       Services.ww.openWindow(null, "chrome://webide/content/", "webide", "chrome,centerscreen,resizable", null);
     }
   },
 
   inspectNode: function (tab, node) {
     let target = TargetFactory.forTab(tab);
-    let selector = findCssSelector(node);
+
+    // Generate a cross iframes query selector
+    let selectors = [];
+    while(node) {
+      selectors.push(findCssSelector(node));
+      node = node.ownerDocument.defaultView.frameElement;
+    }
 
     return gDevTools.showToolbox(target, "inspector").then(toolbox => {
       let inspector = toolbox.getCurrentPanel();
 
       // new-node-front tells us when the node has been selected, whether the
       // browser is remote or not.
       let onNewNode = inspector.selection.once("new-node-front");
 
-      inspector.walker.getRootNode().then(rootNode => {
-        return inspector.walker.querySelector(rootNode, selector);
-      }).then(node => {
-        inspector.selection.setNodeFront(node, "browser-context-menu");
-      });
+      // Evaluate the cross iframes query selectors
+      function querySelectors(nodeFront) {
+        let selector = selectors.pop();
+        if (!selector) {
+          return Promise.resolve(nodeFront);
+        }
+        return inspector.walker.querySelector(nodeFront, selector)
+          .then(node => {
+            if (selectors.length > 0) {
+              return inspector.walker.children(node).then(({ nodes }) => {
+                return nodes[0]; // This is the NodeFront for the document node inside the iframe
+              });
+            }
+            return node;
+          }).then(querySelectors);
+      }
+      inspector.walker.getRootNode()
+        .then(querySelectors)
+        .then(node =>  {
+          // Select the final node
+          inspector.selection.setNodeFront(node, "browser-context-menu");
+        });
 
       return onNewNode.then(() => {
         // Now that the node has been selected, wait until the inspector is
         // fully updated.
         return inspector.once("inspector-updated");
       });
     });
   },
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -114,16 +114,17 @@ subsuite = clipboard
 [browser_inspector_iframe-navigation.js]
 [browser_inspector_infobar_01.js]
 [browser_inspector_infobar_02.js]
 [browser_inspector_infobar_03.js]
 [browser_inspector_infobar_textnode.js]
 [browser_inspector_initialization.js]
 skip-if = (e10s && debug) # Bug 1250058 - Docshell leak on debug e10s
 [browser_inspector_inspect-object-element.js]
+[browser_inspector_inspect_node_contextmenu.js]
 [browser_inspector_invalidate.js]
 [browser_inspector_keyboard-shortcuts-copy-outerhtml.js]
 subsuite = clipboard
 [browser_inspector_keyboard-shortcuts.js]
 [browser_inspector_menu-01-sensitivity.js]
 subsuite = clipboard
 [browser_inspector_menu-02-copy-items.js]
 subsuite = clipboard
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_inspect_node_contextmenu.js
@@ -0,0 +1,38 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* globals getTestActorWithoutToolbox */
+"use strict";
+
+// Tests for inspect node in browser context menu
+
+const FRAME_URI = "data:text/html;charset=utf-8," +
+  encodeURI(`<div id="in-frame">div in the iframe</div>`);
+const HTML = `
+  <div id="salutation">Salution in top document</div>
+  <iframe src="${FRAME_URI}"></iframe>
+`;
+
+const TEST_URI = "data:text/html;charset=utf-8," + encodeURI(HTML);
+
+add_task(function* () {
+  let tab = yield addTab(TEST_URI);
+  let testActor = yield getTestActorWithoutToolbox(tab);
+
+  yield testContextMenuWithinIframe(testActor);
+});
+
+function* testContextMenuWithinIframe(testActor) {
+  info("Opening inspector via 'Inspect Element' context menu item within an iframe");
+  let selector = ["iframe", "#in-frame"];
+  yield clickOnInspectMenuItem(testActor, selector);
+
+  info("Checking inspector state.");
+  let inspector = getActiveInspector();
+  let nodeFront = yield getNodeFrontInFrame("#in-frame", "iframe", inspector);
+
+  is(inspector.selection.nodeFront, nodeFront,
+     "Right node is selected in the markup view");
+}