Bug 1159109 - The MDN tooltip should be controlled by a pref. r=pbrosset
authorWill Bamberg <wbamberg@mozilla.com>
Wed, 06 May 2015 20:59:00 +0200
changeset 274490 14b2376c96fa8cd9e4c07394ae09a83ef406d722
parent 274489 77dd978b8ef378943d846f745683cee4bca363e7
child 274491 732d6616d93972a4e4900a03e01cea323dfbdcd3
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbrosset
bugs1159109
milestone40.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 1159109 - The MDN tooltip should be controlled by a pref. r=pbrosset
browser/app/profile/firefox.js
browser/devtools/styleinspector/rule-view.js
browser/devtools/styleinspector/test/browser.ini
browser/devtools/styleinspector/test/browser_ruleview_context-menu-show-mdn-docs-03.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1391,16 +1391,18 @@ pref("devtools.inspector.remote", false)
 // Expand pseudo-elements by default in the rule-view
 pref("devtools.inspector.show_pseudo_elements", true);
 // The default size for image preview tooltips in the rule-view/computed-view/markup-view
 pref("devtools.inspector.imagePreviewTooltipSize", 300);
 // Enable user agent style inspection in rule-view
 pref("devtools.inspector.showUserAgentStyles", false);
 // Show all native anonymous content (like controls in <video> tags)
 pref("devtools.inspector.showAllAnonymousContent", false);
+// Enable the MDN docs tooltip
+pref("devtools.inspector.mdnDocsTooltip.enabled", true);
 
 // DevTools default color unit
 pref("devtools.defaultColorUnit", "hex");
 
 // Enable the Responsive UI tool
 pref("devtools.responsiveUI.no-reload-notification", false);
 
 // Enable the Debugger
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -20,16 +20,17 @@ const EventEmitter = require("devtools/t
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
 const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
+const PREF_ENABLE_MDN_DOCS_TOOLTIP = "devtools.inspector.mdnDocsTooltip.enabled";
 const PROPERTY_NAME_CLASS = "ruleview-propertyname";
 const FILTER_CHANGED_TIMEOUT = 150;
 
 /**
  * These regular expressions are adapted from firebug's css.js, and are
  * used to parse CSSStyleDeclaration's cssText attribute.
  */
 
@@ -1148,18 +1149,20 @@ function CssRuleView(aInspector, aDoc, a
 
   this._handlePrefChange = this._handlePrefChange.bind(this);
   this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
 
   this._prefObserver = new PrefObserver("devtools.");
   this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
   this._prefObserver.on(PREF_UA_STYLES, this._handlePrefChange);
   this._prefObserver.on(PREF_DEFAULT_COLOR_UNIT, this._handlePrefChange);
+  this._prefObserver.on(PREF_ENABLE_MDN_DOCS_TOOLTIP, this._handlePrefChange);
 
   this.showUserAgentStyles = Services.prefs.getBoolPref(PREF_UA_STYLES);
+  this.enableMdnDocsTooltip = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
 
   let options = {
     autoSelect: true,
     theme: "auto"
   };
   this.popup = new AutocompletePopup(aDoc.defaultView.parent.document, options);
 
   this._buildContextMenu();
@@ -1347,17 +1350,18 @@ CssRuleView.prototype = {
     }
 
     this.menuitemCopyColor.hidden = !this._isColorPopup();
     this.menuitemCopy.disabled = !copy;
 
     var showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES);
     this.menuitemSources.setAttribute("checked", showOrig);
 
-    this.menuitemShowMdnDocs.hidden = !this.doc.popupNode.parentNode
+    this.menuitemShowMdnDocs.hidden = !this.enableMdnDocsTooltip ||
+                                      !this.doc.popupNode.parentNode
                                       .classList.contains(PROPERTY_NAME_CLASS);
 
     this.menuitemAddRule.disabled = this.inspector.selection.isAnonymousNode();
   },
 
   /**
    * Get the type of a given node in the rule-view
    * @param {DOMNode} node The node which we want information about
@@ -1590,16 +1594,20 @@ CssRuleView.prototype = {
       || this.tooltips.isEditing;
   },
 
   _handlePrefChange: function(pref) {
     if (pref === PREF_UA_STYLES) {
       this.showUserAgentStyles = Services.prefs.getBoolPref(pref);
     }
 
+    if (pref === PREF_ENABLE_MDN_DOCS_TOOLTIP) {
+      this.enableMdnDocsTooltip = Services.prefs.getBoolPref(pref);
+    }
+
     // Reselect the currently selected element
     let refreshOnPrefs = [PREF_UA_STYLES, PREF_DEFAULT_COLOR_UNIT];
     if (refreshOnPrefs.indexOf(pref) > -1) {
       let element = this._viewedElement;
       this._viewedElement = null;
       this.selectElement(element);
     }
   },
@@ -1694,16 +1702,17 @@ CssRuleView.prototype = {
     this.isDestroyed = true;
     this.clear();
 
     gDummyPromise = null;
 
     this._prefObserver.off(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
     this._prefObserver.off(PREF_UA_STYLES, this._handlePrefChange);
     this._prefObserver.off(PREF_DEFAULT_COLOR_UNIT, this._handlePrefChange);
+    this._prefObserver.off(PREF_ENABLE_MDN_DOCS_TOOLTIP, this._handlePrefChange);
     this._prefObserver.destroy();
 
     this._outputParser = null;
     this._editorsExpandedForFilter = null;
 
     // Remove context menu
     if (this._contextmenu) {
       // Destroy the Add Rule menuitem.
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -69,16 +69,17 @@ support-files =
 [browser_ruleview_completion-existing-property_02.js]
 [browser_ruleview_completion-new-property_01.js]
 [browser_ruleview_completion-new-property_02.js]
 [browser_ruleview_content_01.js]
 [browser_ruleview_content_02.js]
 skip-if = e10s # Bug 1039528: "inspect element" contextual-menu doesn't work with e10s
 [browser_ruleview_context-menu-show-mdn-docs-01.js]
 [browser_ruleview_context-menu-show-mdn-docs-02.js]
+[browser_ruleview_context-menu-show-mdn-docs-03.js]
 [browser_ruleview_cubicbezier-appears-on-swatch-click.js]
 [browser_ruleview_cubicbezier-commit-on-ENTER.js]
 [browser_ruleview_cubicbezier-revert-on-ESC.js]
 [browser_ruleview_edit-property-commit.js]
 [browser_ruleview_edit-property-increments.js]
 [browser_ruleview_edit-property-order.js]
 [browser_ruleview_edit-property_01.js]
 [browser_ruleview_edit-property_02.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_context-menu-show-mdn-docs-03.js
@@ -0,0 +1,116 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * This file tests the "devtools.inspector.mdnDocsTooltip.enabled" preference,
+ * that we use to enable/disable the MDN tooltip in the Inspector.
+ *
+ * The desired behavior is:
+ * - if the preference is true, show the "Show MDN Docs" context menu item
+ * - if the preference is false, don't show the item
+ * - listen for changes to the pref, so we can show/hide the item dynamically
+ */
+
+"use strict";
+
+const { PrefObserver } = devtools.require("devtools/styleeditor/utils");
+const PREF_ENABLE_MDN_DOCS_TOOLTIP = "devtools.inspector.mdnDocsTooltip.enabled";
+const PROPERTY_NAME_CLASS = "ruleview-propertyname";
+
+const TEST_DOC = `
+<html>
+  <body>
+    <div style="color: red">
+      Test the pref to enable/disable the "Show MDN Docs" context menu option
+    </div>
+  </body>
+</html>`;
+
+add_task(function* () {
+  info("Ensure the pref is true to begin with");
+  let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
+  if (initial != true) {
+    setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
+  }
+
+  yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
+
+  let {inspector, view} = yield openRuleView();
+  yield selectNode("div", inspector);
+  yield testMdnContextMenuItemVisibility(view, true);
+
+  yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, false);
+  yield testMdnContextMenuItemVisibility(view, false);
+
+  info("Close the Inspector");
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  yield gDevTools.closeToolbox(target);
+
+  ({inspector, view} = yield openRuleView());
+  yield selectNode("div", inspector);
+  yield testMdnContextMenuItemVisibility(view, false);
+
+  yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
+  yield testMdnContextMenuItemVisibility(view, true);
+
+  info("Ensure the pref is reset to its initial value");
+  let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
+  if (eventual != initial) {
+    setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial);
+  }
+});
+
+/**
+ * Set a boolean pref, and wait for the pref observer to
+ * trigger, so that code listening for the pref change
+ * has had a chance to update itself.
+ *
+ * @param pref {string} Name of the pref to change
+ * @param state {boolean} Desired value of the pref.
+ *
+ * Note that if the pref already has the value in `state`,
+ * then the prefObserver will not trigger. So you should only
+ * call this function if you know the pref's current value is
+ * not `state`.
+ */
+function* setBooleanPref(pref, state) {
+  let oncePrefChanged = promise.defer();
+  let prefObserver = new PrefObserver("devtools.");
+  prefObserver.on(pref, oncePrefChanged.resolve);
+
+  info("Set the pref " + pref + " to: " + state);
+  Services.prefs.setBoolPref(pref, state);
+
+  info("Wait for prefObserver to call back so the UI can update");
+  yield oncePrefChanged.promise;
+  prefObserver.off(pref, oncePrefChanged.resolve);
+}
+
+/**
+ * Test whether the MDN tooltip context menu item is visible when it should be.
+ *
+ * @param view The rule view
+ * @param shouldBeVisible {boolean} Whether we expect the context
+ * menu item to be visible or not.
+ */
+function* testMdnContextMenuItemVisibility(view, shouldBeVisible) {
+  let message = shouldBeVisible? "shown": "hidden";
+  info("Test that MDN context menu item is " + message);
+
+  info("Set a CSS property name as popupNode");
+  let root = rootElement(view);
+  let node = root.querySelector("." + PROPERTY_NAME_CLASS).firstChild;
+  view.doc.popupNode = node;
+
+  info("Update context menu state");
+  view._contextMenuUpdate();
+  let isVisible = !view.menuitemShowMdnDocs.hidden;
+  is(isVisible, shouldBeVisible,
+     "The MDN context menu item is " + message);
+}
+
+/**
+ * Returns the root element for the rule view.
+ */
+let rootElement = view => (view.element) ? view.element : view.styleDocument;