Bug 1306937 - enable inspector eyedropper when viewing images;r=pbro draft
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 30 Nov 2016 14:35:28 +0100
changeset 445856 c13bbb8d680fb48d6dccf3e0f8e83a0201f9738b
parent 445311 3b322d58be091eb4aab2e6e8fb86cb45fd8948a3
child 445857 1d0e4130febaa0a0e775f1b16c4cc468c804fbda
push id37644
push userjdescottes@mozilla.com
push dateWed, 30 Nov 2016 13:36:27 +0000
reviewerspbro
bugs1306937
milestone53.0a1
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 0000000000000000000000000000000000000000..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;
 const RX_FUNC_NAME =
   /((var|const|let)\s+)?([\w$.]+\s*[:=]\s*)*(function)?\s*\*?\s*([\w$]+)?\s*$/;
 
 // The possible completions to a ':' with added score to give certain values
 // some preference.
@@ -2802,16 +2803,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;