Bug 1306937 - enable inspector eyedropper when viewing images;r=pbro
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 30 Nov 2016 14:35:28 +0100
changeset 324825 f0cbd37fec30ac0a2cace54a2a87e7d6b6e34733
parent 324824 616c1cdadadee675b4e6b7ec50418506d6a7a153
child 324826 db231dc73bf45a837ea21f04a8906646cfac5c17
push id31018
push userphilringnalda@gmail.com
push dateThu, 01 Dec 2016 03:18:13 +0000
treeherdermozilla-central@a183d5c5a8f7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1306937
milestone53.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 1306937 - enable inspector eyedropper when viewing images;r=pbro MozReview-Commit-ID: BlJPMYMQb8j
devtools/client/inspector/inspector.js
devtools/client/inspector/test/browser.ini
devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-image.js
devtools/client/inspector/test/img_browser_inspector_highlighter-eyedropper-image.png
devtools/server/actors/inspector.js
devtools/shared/specs/inspector.js
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -612,29 +612,42 @@ Inspector.prototype = {
    */
   addSidebarTab: function (id, title, panel, selected) {
     this.sidebar.addTab(id, title, panel, selected);
   },
 
   /**
    * Method to check whether the document is a HTML document and
    * pickColorFromPage method is available or not.
-   * Returns a boolean value
+   *
+   * @return {Boolean} true if the eyedropper highlighter is supported by the current
+   *         document.
    */
   supportsEyeDropper: Task.async(function* () {
-    let isInHTMLDocument = this.selection.nodeFront &&
-                            this.selection.nodeFront.isInHTMLDocument;
-    let pickColorAvailable = false;
     try {
-      pickColorAvailable = yield this.target
-                                      .actorHasMethod("inspector", "pickColorFromPage");
+      let hasSupportsHighlighters =
+        yield this.target.actorHasMethod("inspector", "supportsHighlighters");
+      let hasPickColorFromPage =
+        yield this.target.actorHasMethod("inspector", "pickColorFromPage");
+
+      let supportsHighlighters;
+      if (hasSupportsHighlighters) {
+        supportsHighlighters = yield this.inspector.supportsHighlighters();
+      } else {
+        // If the actor does not provide the supportsHighlighter method, fallback to
+        // check if the selected node's document is a HTML document.
+        let { nodeFront } = this.selection;
+        supportsHighlighters = nodeFront && nodeFront.isInHTMLDocument;
+      }
+
+      return supportsHighlighters && hasPickColorFromPage;
     } catch (e) {
       console.error(e);
+      return false;
     }
-    return isInHTMLDocument && pickColorAvailable;
   }),
 
   setupToolbar: Task.async(function* () {
     this.teardownToolbar();
 
     // Setup the sidebar toggle button.
     let SidebarToggle = this.React.createFactory(this.browserRequire(
       "devtools/client/shared/components/sidebar-toggle"));
@@ -651,16 +664,23 @@ Inspector.prototype = {
 
     // Setup the add-node button.
     this.addNode = this.addNode.bind(this);
     this.addNodeButton = this.panelDoc.getElementById("inspector-element-add-button");
     this.addNodeButton.addEventListener("click", this.addNode);
 
     // Setup the eye-dropper icon if we're in an HTML document and we have actor support.
     let canShowEyeDropper = yield this.supportsEyeDropper();
+
+    // Bail out if the inspector was destroyed in the meantime and panelDoc is no longer
+    // available.
+    if (!this.panelDoc) {
+      return;
+    }
+
     if (canShowEyeDropper) {
       this.onEyeDropperDone = this.onEyeDropperDone.bind(this);
       this.onEyeDropperButtonClicked = this.onEyeDropperButtonClicked.bind(this);
       this.eyeDropperButton = this.panelDoc
                                     .getElementById("inspector-eyedropper-toggle");
       this.eyeDropperButton.disabled = false;
       this.eyeDropperButton.title = INSPECTOR_L10N.getStr("inspector.eyedropper.label");
       this.eyeDropperButton.addEventListener("click", this.onEyeDropperButtonClicked);
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -33,16 +33,17 @@ support-files =
   doc_inspector_search.html
   doc_inspector_search-reserved.html
   doc_inspector_search-suggestions.html
   doc_inspector_search-svg.html
   doc_inspector_select-last-selected-01.html
   doc_inspector_select-last-selected-02.html
   doc_inspector_svg.svg
   head.js
+  img_browser_inspector_highlighter-eyedropper-image.png
   shared-head.js
   !/devtools/client/commandline/test/helpers.js
   !/devtools/client/framework/test/shared-head.js
   !/devtools/client/shared/test/test-actor.js
   !/devtools/client/shared/test/test-actor-registry.js
 
 [browser_inspector_addNode_01.js]
 [browser_inspector_addNode_02.js]
@@ -73,16 +74,17 @@ skip-if = os == "mac" # Full keyboard na
 [browser_inspector_highlighter-cssgrid_01.js]
 [browser_inspector_highlighter-csstransform_01.js]
 [browser_inspector_highlighter-csstransform_02.js]
 [browser_inspector_highlighter-embed.js]
 [browser_inspector_highlighter-eyedropper-clipboard.js]
 subsuite = clipboard
 [browser_inspector_highlighter-eyedropper-csp.js]
 [browser_inspector_highlighter-eyedropper-events.js]
+[browser_inspector_highlighter-eyedropper-image.js]
 [browser_inspector_highlighter-eyedropper-label.js]
 [browser_inspector_highlighter-eyedropper-show-hide.js]
 [browser_inspector_highlighter-eyedropper-xul.js]
 [browser_inspector_highlighter-geometry_01.js]
 [browser_inspector_highlighter-geometry_02.js]
 [browser_inspector_highlighter-geometry_03.js]
 [browser_inspector_highlighter-geometry_04.js]
 [browser_inspector_highlighter-geometry_05.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-image.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the eyedropper icon in the toolbar is enabled when viewing an image.
+
+const TEST_URL = URL_ROOT + "img_browser_inspector_highlighter-eyedropper-image.png";
+
+add_task(function* () {
+  let {inspector} = yield openInspectorForURL(TEST_URL);
+  info("Check the inspector toolbar when viewing an image");
+  let button = inspector.panelDoc.querySelector("#inspector-eyedropper-toggle");
+  ok(!button.disabled, "The button is enabled in the toolbar");
+});
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a0aef4f93bb102939de9d78d92a8ee64e9ba3df3
GIT binary patch
literal 522
zc%17D@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrU_9^X;uum9_x7%%V1t2(^T80l
ze@8?71V4$frx^V{+`0L!?w>u<bw6|68ATcx9`Xqs;M~A?h~Wl<+k*8CMhq+p42&EB
zehmyP8sG1;4H?b}?hkpt?;m{b&AeeT1J{RBf<SKp#W@GwWfXGi?GLDxPMDn-+Xswc
P22WQ%mvv4FO$-bGi|mr%
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -79,16 +79,17 @@ const nodeFilterConstants = require("dev
 
 const {EventParsers} = require("devtools/server/event-parsers");
 const {nodeSpec, nodeListSpec, walkerSpec, inspectorSpec} = require("devtools/shared/specs/inspector");
 
 const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
 const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
 const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
 const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
+const SVG_NS = "http://www.w3.org/2000/svg";
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const IMAGE_FETCHING_TIMEOUT = 500;
 
 // The possible completions to a ':' with added score to give certain values
 // some preference.
 const PSEUDO_SELECTORS = [
   [":active", 1],
@@ -2836,16 +2837,39 @@ exports.InspectorActor = protocol.ActorC
     if (this._eyeDropper) {
       this._eyeDropper.hide();
       this._eyeDropper.off("selected", this._onColorPicked);
       this._eyeDropper.off("canceled", this._onColorPickCanceled);
       events.off(this.tabActor, "will-navigate", this.destroyEyeDropper);
     }
   },
 
+  /**
+   * Check if the current document supports highlighters using a canvasFrame anonymous
+   * content container (ie all highlighters except the SimpleOutlineHighlighter).
+   * It is impossible to detect the feature programmatically as some document types simply
+   * don't render the canvasFrame without throwing any error.
+   */
+  supportsHighlighters: function () {
+    let doc = this.tabActor.window.document;
+    let ns = doc.documentElement.namespaceURI;
+
+    // XUL documents do not support insertAnonymousContent().
+    if (ns === XUL_NS) {
+      return false;
+    }
+
+    // SVG documents do not render the canvasFrame (see Bug 1157592).
+    if (ns === SVG_NS) {
+      return false;
+    }
+
+    return true;
+  },
+
   _onColorPicked: function (e, color) {
     events.emit(this, "color-picked", color);
   },
 
   _onColorPickCanceled: function () {
     events.emit(this, "color-pick-canceled");
   }
 });
--- a/devtools/shared/specs/inspector.js
+++ b/devtools/shared/specs/inspector.js
@@ -433,13 +433,19 @@ const inspectorSpec = generateActorSpec(
     },
     pickColorFromPage: {
       request: {options: Arg(0, "nullable:json")},
       response: {}
     },
     cancelPickColorFromPage: {
       request: {},
       response: {}
+    },
+    supportsHighlighters: {
+      request: {},
+      response: {
+        value: RetVal("boolean")
+      }
     }
   }
 });
 
 exports.inspectorSpec = inspectorSpec;