Bug 1316797 - Refactor HighlightersOverlay and TooltipsOverlay into separate modules r=jdescottes
authorGabriel Luong <gabriel.luong@gmail.com>
Sat, 12 Nov 2016 00:58:09 +0900
changeset 348860 3530eb420c7f2ec8510304e7e30aee8fe07c23e7
parent 348859 720a160f4c0c2707b1c0eacd5b652a0763655ec1
child 348861 d243b2d5c128035af74a15d5ee1069066b7df89f
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1316797
milestone52.0a1
Bug 1316797 - Refactor HighlightersOverlay and TooltipsOverlay into separate modules r=jdescottes
devtools/client/inspector/computed/computed.js
devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js
devtools/client/inspector/rules/rules.js
devtools/client/inspector/shared/highlighters-overlay.js
devtools/client/inspector/shared/moz.build
devtools/client/inspector/shared/node-types.js
devtools/client/inspector/shared/style-inspector-menu.js
devtools/client/inspector/shared/style-inspector-overlays.js
devtools/client/inspector/shared/tooltips-overlay.js
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -12,19 +12,25 @@ const {ELEMENT_STYLE} = require("devtool
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const Services = require("Services");
 const {OutputParser} = require("devtools/client/shared/output-parser");
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {createChild} = require("devtools/client/inspector/shared/utils");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-
-const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
+const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
+const {
+  VIEW_NODE_SELECTOR_TYPE,
+  VIEW_NODE_PROPERTY_TYPE,
+  VIEW_NODE_VALUE_TYPE,
+  VIEW_NODE_IMAGE_URL_TYPE,
+} = require("devtools/client/inspector/shared/node-types");
 const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
+const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
 const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 const {BoxModelView} = require("devtools/client/inspector/components/box-model");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
@@ -202,20 +208,20 @@ function CssComputedView(inspector, docu
   // The element that we're inspecting, and the document that it comes from.
   this._viewedElement = null;
 
   this.createStyleViews();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
 
   // Add the tooltips and highlightersoverlay
-  this.tooltips = new overlays.TooltipsOverlay(this);
+  this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
 
-  this.highlighters = new overlays.HighlightersOverlay(this);
+  this.highlighters = new HighlightersOverlay(this);
   this.highlighters.addToView();
 }
 
 /**
  * Lookup a l10n string in the shared styleinspector string bundle.
  *
  * @param {String} name
  *        The key to lookup.
@@ -296,17 +302,17 @@ CssComputedView.prototype = {
 
   /**
    * Get the type of a given node in the computed-view
    *
    * @param {DOMNode} node
    *        The node which we want information about
    * @return {Object} The type information object contains the following props:
    * - type {String} One of the VIEW_NODE_XXX_TYPE const in
-   *   style-inspector-overlays
+   *   client/inspector/shared/node-types
    * - value {Object} Depends on the type of the node
    * returns null if the node isn't anything we care about
    */
   getNodeInfo: function (node) {
     if (!node) {
       return null;
     }
 
@@ -319,17 +325,17 @@ CssComputedView.prototype = {
         classes.contains("parentmatch")) {
       let selectorText = "";
       for (let child of node.childNodes) {
         if (child.nodeType === node.TEXT_NODE) {
           selectorText += child.textContent;
         }
       }
       return {
-        type: overlays.VIEW_NODE_SELECTOR_TYPE,
+        type: VIEW_NODE_SELECTOR_TYPE,
         value: selectorText.trim()
       };
     }
 
     // Walk up the nodes to find out where node is
     let propertyView;
     let propertyContent;
     let parent = node;
@@ -366,22 +372,22 @@ CssComputedView.prototype = {
       value = {
         property: view.querySelector(".property-name").textContent,
         value: node.textContent
       };
     }
 
     // Get the type
     if (classes.contains("property-name")) {
-      type = overlays.VIEW_NODE_PROPERTY_TYPE;
+      type = VIEW_NODE_PROPERTY_TYPE;
     } else if (classes.contains("property-value") ||
                classes.contains("other-property-value")) {
-      type = overlays.VIEW_NODE_VALUE_TYPE;
+      type = VIEW_NODE_VALUE_TYPE;
     } else if (isHref) {
-      type = overlays.VIEW_NODE_IMAGE_URL_TYPE;
+      type = VIEW_NODE_IMAGE_URL_TYPE;
       value.url = node.href;
     } else {
       return null;
     }
 
     return {type, value};
   },
 
--- a/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js
+++ b/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js
@@ -1,31 +1,32 @@
 /* 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/ */
 
 "use strict";
 
 // Tests various output of the computed-view's getNodeInfo method.
-// This method is used by the style-inspector-overlay on mouseover to decide
-// which tooltip or highlighter to show when hovering over a
-// value/name/selector if any.
+// This method is used by the HighlightersOverlay and TooltipsOverlay on mouseover to
+// decide which highlighter or tooltip to show when hovering over a value/name/selector
+// if any.
+//
 // For instance, browser_ruleview_selector-highlighter_01.js and
 // browser_ruleview_selector-highlighter_02.js test that the selector
 // highlighter appear when hovering over a selector in the rule-view.
 // Since the code to make this work for the computed-view is 90% the same,
 // there is no need for testing it again here.
 // This test however serves as a unit test for getNodeInfo.
 
 const {
   VIEW_NODE_SELECTOR_TYPE,
   VIEW_NODE_PROPERTY_TYPE,
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_IMAGE_URL_TYPE
-} = require("devtools/client/inspector/shared/style-inspector-overlays");
+} = require("devtools/client/inspector/shared/node-types");
 
 const TEST_URI = `
   <style type="text/css">
     body {
       background: red;
       color: white;
     }
     div {
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -12,26 +12,32 @@ const {Task} = require("devtools/shared/
 const {Tools} = require("devtools/client/definitions");
 const {l10n} = require("devtools/shared/inspector/css-logic");
 const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
 const {OutputParser} = require("devtools/client/shared/output-parser");
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {ElementStyle} = require("devtools/client/inspector/rules/models/element-style");
 const {Rule} = require("devtools/client/inspector/rules/models/rule");
 const {RuleEditor} = require("devtools/client/inspector/rules/views/rule-editor");
-const {createChild, promiseWarn, throttle} = require("devtools/client/inspector/shared/utils");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-
-const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
+const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
+const {
+  VIEW_NODE_SELECTOR_TYPE,
+  VIEW_NODE_PROPERTY_TYPE,
+  VIEW_NODE_VALUE_TYPE,
+  VIEW_NODE_IMAGE_URL_TYPE,
+  VIEW_NODE_LOCATION_TYPE,
+} = require("devtools/client/inspector/shared/node-types");
+const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
+const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
+const {createChild, promiseWarn, throttle} = require("devtools/client/inspector/shared/utils");
 const EventEmitter = require("devtools/shared/event-emitter");
-const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
 const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
-
 const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 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 FILTER_CHANGED_TIMEOUT = 150;
@@ -164,19 +170,19 @@ function CssRuleView(inspector, document
     theme: "auto"
   });
 
   this._showEmpty();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: true });
 
   // Add the tooltips and highlighters to the view
-  this.tooltips = new overlays.TooltipsOverlay(this);
+  this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
-  this.highlighters = new overlays.HighlightersOverlay(this);
+  this.highlighters = new HighlightersOverlay(this);
   this.highlighters.addToView();
 
   EventEmitter.decorate(this);
 }
 
 CssRuleView.prototype = {
   // The element that we're inspecting.
   _viewedElement: null,
@@ -289,54 +295,54 @@ CssRuleView.prototype = {
 
   /**
    * Get the type of a given node in the rule-view
    *
    * @param {DOMNode} node
    *        The node which we want information about
    * @return {Object} The type information object contains the following props:
    * - type {String} One of the VIEW_NODE_XXX_TYPE const in
-   *   style-inspector-overlays
+   *   client/inspector/shared/node-types
    * - value {Object} Depends on the type of the node
    * returns null of the node isn't anything we care about
    */
   getNodeInfo: function (node) {
     if (!node) {
       return null;
     }
 
     let type, value;
     let classes = node.classList;
     let prop = getParentTextProperty(node);
 
     if (classes.contains("ruleview-propertyname") && prop) {
-      type = overlays.VIEW_NODE_PROPERTY_TYPE;
+      type = VIEW_NODE_PROPERTY_TYPE;
       value = {
         property: node.textContent,
         value: getPropertyNameAndValue(node).value,
         enabled: prop.enabled,
         overridden: prop.overridden,
         pseudoElement: prop.rule.pseudoElement,
         sheetHref: prop.rule.domRule.href,
         textProperty: prop
       };
     } else if (classes.contains("ruleview-propertyvalue") && prop) {
-      type = overlays.VIEW_NODE_VALUE_TYPE;
+      type = VIEW_NODE_VALUE_TYPE;
       value = {
         property: getPropertyNameAndValue(node).name,
         value: node.textContent,
         enabled: prop.enabled,
         overridden: prop.overridden,
         pseudoElement: prop.rule.pseudoElement,
         sheetHref: prop.rule.domRule.href,
         textProperty: prop
       };
     } else if (classes.contains("theme-link") &&
                !classes.contains("ruleview-rule-source") && prop) {
-      type = overlays.VIEW_NODE_IMAGE_URL_TYPE;
+      type = VIEW_NODE_IMAGE_URL_TYPE;
       value = {
         property: getPropertyNameAndValue(node).name,
         value: node.parentNode.textContent,
         url: node.href,
         enabled: prop.enabled,
         overridden: prop.overridden,
         pseudoElement: prop.rule.pseudoElement,
         sheetHref: prop.rule.domRule.href,
@@ -344,21 +350,21 @@ CssRuleView.prototype = {
       };
     } else if (classes.contains("ruleview-selector-unmatched") ||
                classes.contains("ruleview-selector-matched") ||
                classes.contains("ruleview-selectorcontainer") ||
                classes.contains("ruleview-selector") ||
                classes.contains("ruleview-selector-attribute") ||
                classes.contains("ruleview-selector-pseudo-class") ||
                classes.contains("ruleview-selector-pseudo-class-lock")) {
-      type = overlays.VIEW_NODE_SELECTOR_TYPE;
+      type = VIEW_NODE_SELECTOR_TYPE;
       value = this._getRuleEditorForNode(node).selectorText.textContent;
     } else if (classes.contains("ruleview-rule-source") ||
                classes.contains("ruleview-rule-source-label")) {
-      type = overlays.VIEW_NODE_LOCATION_TYPE;
+      type = VIEW_NODE_LOCATION_TYPE;
       let rule = this._getRuleEditorForNode(node).rule;
       value = (rule.sheet && rule.sheet.href) ? rule.sheet.href : rule.title;
     } else {
       return null;
     }
 
     return {type, value};
   },
rename from devtools/client/inspector/shared/style-inspector-overlays.js
rename to devtools/client/inspector/shared/highlighters-overlay.js
--- a/devtools/client/inspector/shared/style-inspector-overlays.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -1,62 +1,30 @@
 /* -*- 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/. */
 
 "use strict";
 
-// The style-inspector overlays are:
-// - tooltips that appear when hovering over property values
-// - editor tooltips that appear when clicking color swatches, etc.
-// - in-content highlighters that appear when hovering over property values
-// - etc.
+/**
+ * The highlighter overlays are in-content highlighters that appear when hovering over
+ * property values.
+ */
 
-const {getColor} = require("devtools/client/shared/theme");
-const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
-const {
-  getImageDimensions,
-  setImageTooltip,
-  setBrokenImageTooltip,
-} = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper");
-const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
-const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
-const SwatchCubicBezierTooltip = require("devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip");
-const SwatchFilterTooltip = require("devtools/client/shared/widgets/tooltip/SwatchFilterTooltip");
-const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
-const {Task} = require("devtools/shared/task");
-const Services = require("Services");
-const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-
-const PREF_IMAGE_TOOLTIP_SIZE = "devtools.inspector.imagePreviewTooltipSize";
-
-// Types of existing tooltips
-const TOOLTIP_IMAGE_TYPE = "image";
-const TOOLTIP_FONTFAMILY_TYPE = "font-family";
-
-// Types of nodes in the rule/computed-view
-const VIEW_NODE_SELECTOR_TYPE = 1;
-exports.VIEW_NODE_SELECTOR_TYPE = VIEW_NODE_SELECTOR_TYPE;
-const VIEW_NODE_PROPERTY_TYPE = 2;
-exports.VIEW_NODE_PROPERTY_TYPE = VIEW_NODE_PROPERTY_TYPE;
-const VIEW_NODE_VALUE_TYPE = 3;
-exports.VIEW_NODE_VALUE_TYPE = VIEW_NODE_VALUE_TYPE;
-const VIEW_NODE_IMAGE_URL_TYPE = 4;
-exports.VIEW_NODE_IMAGE_URL_TYPE = VIEW_NODE_IMAGE_URL_TYPE;
-const VIEW_NODE_LOCATION_TYPE = 5;
-exports.VIEW_NODE_LOCATION_TYPE = VIEW_NODE_LOCATION_TYPE;
+const EventEmitter = require("devtools/shared/event-emitter");
+const { VIEW_NODE_VALUE_TYPE } = require("devtools/client/inspector/shared/node-types");
 
 /**
  * Manages all highlighters in the style-inspector.
  *
- * @param {CssRuleView|CssComputedView} view
- *        Either the rule-view or computed-view panel
+ * @param  {CssRuleView|CssComputedView} view
+ *         Either the rule-view or computed-view panel
  */
 function HighlightersOverlay(view) {
   this.view = view;
 
   let {CssRuleView} = require("devtools/client/inspector/rules/rules");
   this.isRuleView = view instanceof CssRuleView;
 
   this.highlighterUtils = this.view.inspector.toolbox.highlighterUtils;
@@ -69,18 +37,16 @@ function HighlightersOverlay(view) {
   // Only initialize the overlay if at least one of the highlighter types is
   // supported
   this.supportsHighlighters =
     this.highlighterUtils.supportsCustomHighlighters();
 
   EventEmitter.decorate(this);
 }
 
-exports.HighlightersOverlay = HighlightersOverlay;
-
 HighlightersOverlay.prototype = {
   /**
    * Add the highlighters overlay to the view. This will start tracking mouse
    * movements and display highlighters when needed
    */
   addToView: function () {
     if (!this.supportsHighlighters || this._isStarted || this._isDestroyed) {
       return;
@@ -158,33 +124,33 @@ HighlightersOverlay.prototype = {
     // Otherwise, hide the highlighter.
     this._lastHovered = null;
     this._hideCurrent();
   },
 
   /**
    * Is the current hovered node a css transform property value in the rule-view
    *
-   * @param {Object} nodeInfo
+   * @param  {Object} nodeInfo
    * @return {Boolean}
    */
   _isRuleViewTransform: function (nodeInfo) {
     let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
                       nodeInfo.value.property === "transform";
     let isEnabled = nodeInfo.value.enabled &&
                     !nodeInfo.value.overridden &&
                     !nodeInfo.value.pseudoElement;
     return this.isRuleView && isTransform && isEnabled;
   },
 
   /**
    * Is the current hovered node a css transform property value in the
    * computed-view
    *
-   * @param {Object} nodeInfo
+   * @param  {Object} nodeInfo
    * @return {Boolean}
    */
   _isComputedViewTransform: function (nodeInfo) {
     let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
                       nodeInfo.value.property === "transform";
     return !this.isRuleView && isTransform;
   },
 
@@ -206,18 +172,19 @@ HighlightersOverlay.prototype = {
     }
 
     this.highlighterShown = null;
     this.emit("highlighter-hidden");
   },
 
   /**
    * Get a highlighter front given a type. It will only be initialized once
-   * @param {String} type The highlighter type. One of this.highlighters
-   * @return a promise that resolves to the highlighter
+   *
+   * @param  {String} type The highlighter type. One of this.highlighters
+   * @return {Promise} that resolves to the highlighter
    */
   _getHighlighter: function (type) {
     let utils = this.highlighterUtils;
 
     if (this.highlighters[type]) {
       return promise.resolve(this.highlighters[type]);
     }
 
@@ -243,289 +210,9 @@ HighlightersOverlay.prototype = {
 
     this.view = null;
     this.highlighterUtils = null;
 
     this._isDestroyed = true;
   }
 };
 
-/**
- * Manages all tooltips in the style-inspector.
- *
- * @param {CssRuleView|CssComputedView} view
- *        Either the rule-view or computed-view panel
- */
-function TooltipsOverlay(view) {
-  this.view = view;
-
-  let {CssRuleView} = require("devtools/client/inspector/rules/rules");
-  this.isRuleView = view instanceof CssRuleView;
-  this._cssProperties = getCssProperties(this.view.inspector.toolbox);
-
-  this._onNewSelection = this._onNewSelection.bind(this);
-  this.view.inspector.selection.on("new-node-front", this._onNewSelection);
-}
-
-exports.TooltipsOverlay = TooltipsOverlay;
-
-TooltipsOverlay.prototype = {
-  get isEditing() {
-    return this.colorPicker.tooltip.isVisible() ||
-           this.colorPicker.eyedropperOpen ||
-           this.cubicBezier.tooltip.isVisible() ||
-           this.filterEditor.tooltip.isVisible();
-  },
-
-  /**
-   * Add the tooltips overlay to the view. This will start tracking mouse
-   * movements and display tooltips when needed
-   */
-  addToView: function () {
-    if (this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    let { toolbox } = this.view.inspector;
-
-    // Initializing the different tooltips that are used in the inspector.
-    // These tooltips are attached to the toolbox document if they require a popup panel.
-    // Otherwise, it is attached to the inspector panel document if it is an inline
-    // editor.
-    this.previewTooltip = new HTMLTooltip(toolbox.doc, {
-      type: "arrow",
-      useXulWrapper: true
-    });
-    this.previewTooltip.startTogglingOnHover(this.view.element,
-      this._onPreviewTooltipTargetHover.bind(this));
-
-    // MDN CSS help tooltip
-    this.cssDocs = new CssDocsTooltip(toolbox.doc);
-
-    if (this.isRuleView) {
-      // Color picker tooltip
-      this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc, this.view.inspector);
-      // Cubic bezier tooltip
-      this.cubicBezier = new SwatchCubicBezierTooltip(toolbox.doc);
-      // Filter editor tooltip
-      this.filterEditor = new SwatchFilterTooltip(toolbox.doc,
-        this._cssProperties.getValidityChecker(this.view.inspector.panelDoc));
-    }
-
-    this._isStarted = true;
-  },
-
-  /**
-   * Remove the tooltips overlay from the view. This will stop tracking mouse
-   * movements and displaying tooltips
-   */
-  removeFromView: function () {
-    if (!this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    this.previewTooltip.stopTogglingOnHover(this.view.element);
-    this.previewTooltip.destroy();
-
-    if (this.colorPicker) {
-      this.colorPicker.destroy();
-    }
-
-    if (this.cubicBezier) {
-      this.cubicBezier.destroy();
-    }
-
-    if (this.cssDocs) {
-      this.cssDocs.destroy();
-    }
-
-    if (this.filterEditor) {
-      this.filterEditor.destroy();
-    }
-
-    this._isStarted = false;
-  },
-
-  /**
-   * Given a hovered node info, find out which type of tooltip should be shown,
-   * if any
-   *
-   * @param {Object} nodeInfo
-   * @return {String} The tooltip type to be shown, or null
-   */
-  _getTooltipType: function ({type, value: prop}) {
-    let tooltipType = null;
-    let inspector = this.view.inspector;
-
-    // Image preview tooltip
-    if (type === VIEW_NODE_IMAGE_URL_TYPE &&
-        inspector.hasUrlToImageDataResolver) {
-      tooltipType = TOOLTIP_IMAGE_TYPE;
-    }
-
-    // Font preview tooltip
-    if (type === VIEW_NODE_VALUE_TYPE && prop.property === "font-family") {
-      let value = prop.value.toLowerCase();
-      if (value !== "inherit" && value !== "unset" && value !== "initial") {
-        tooltipType = TOOLTIP_FONTFAMILY_TYPE;
-      }
-    }
-
-    return tooltipType;
-  },
-
-  /**
-   * Executed by the tooltip when the pointer hovers over an element of the
-   * view. Used to decide whether the tooltip should be shown or not and to
-   * actually put content in it.
-   * Checks if the hovered target is a css value we support tooltips for.
-   *
-   * @param {DOMNode} target The currently hovered node
-   * @return {Promise}
-   */
-  _onPreviewTooltipTargetHover: Task.async(function* (target) {
-    let nodeInfo = this.view.getNodeInfo(target);
-    if (!nodeInfo) {
-      // The hovered node isn't something we care about
-      return false;
-    }
-
-    let type = this._getTooltipType(nodeInfo);
-    if (!type) {
-      // There is no tooltip type defined for the hovered node
-      return false;
-    }
-
-    if (this.isRuleView && this.colorPicker.tooltip.isVisible()) {
-      this.colorPicker.revert();
-      this.colorPicker.hide();
-    }
-
-    if (this.isRuleView && this.cubicBezier.tooltip.isVisible()) {
-      this.cubicBezier.revert();
-      this.cubicBezier.hide();
-    }
-
-    if (this.isRuleView && this.cssDocs.tooltip.isVisible()) {
-      this.cssDocs.hide();
-    }
-
-    if (this.isRuleView && this.filterEditor.tooltip.isVisible()) {
-      this.filterEditor.revert();
-      this.filterEdtior.hide();
-    }
-
-    let inspector = this.view.inspector;
-
-    if (type === TOOLTIP_IMAGE_TYPE) {
-      try {
-        yield this._setImagePreviewTooltip(nodeInfo.value.url);
-      } catch (e) {
-        yield setBrokenImageTooltip(this.previewTooltip, this.view.inspector.panelDoc);
-      }
-      return true;
-    }
-
-    if (type === TOOLTIP_FONTFAMILY_TYPE) {
-      let font = nodeInfo.value.value;
-      let nodeFront = inspector.selection.nodeFront;
-      yield this._setFontPreviewTooltip(font, nodeFront);
-      return true;
-    }
-
-    return false;
-  }),
-
-  /**
-   * Set the content of the preview tooltip to display an image preview. The image URL can
-   * be relative, a call will be made to the debuggee to retrieve the image content as an
-   * imageData URI.
-   *
-   * @param {String} imageUrl
-   *        The image url value (may be relative or absolute).
-   * @return {Promise} A promise that resolves when the preview tooltip content is ready
-   */
-  _setImagePreviewTooltip: Task.async(function* (imageUrl) {
-    let doc = this.view.inspector.panelDoc;
-    let maxDim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE);
-
-    let naturalWidth, naturalHeight;
-    if (imageUrl.startsWith("data:")) {
-      // If the imageUrl already is a data-url, save ourselves a round-trip
-      let size = yield getImageDimensions(doc, imageUrl);
-      naturalWidth = size.naturalWidth;
-      naturalHeight = size.naturalHeight;
-    } else {
-      let inspectorFront = this.view.inspector.inspector;
-      let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl, maxDim);
-      imageUrl = yield data.string();
-      naturalWidth = size.naturalWidth;
-      naturalHeight = size.naturalHeight;
-    }
-
-    yield setImageTooltip(this.previewTooltip, doc, imageUrl,
-      {maxDim, naturalWidth, naturalHeight});
-  }),
-
-  /**
-   * Set the content of the preview tooltip to display a font family preview.
-   *
-   * @param {String} font
-   *        The font family value.
-   * @param {object} nodeFront
-   *        The NodeActor that will used to retrieve the dataURL for the font
-   *        family tooltip contents.
-   * @return {Promise} A promise that resolves when the preview tooltip content is ready
-   */
-  _setFontPreviewTooltip: Task.async(function* (font, nodeFront) {
-    if (!font || !nodeFront || typeof nodeFront.getFontFamilyDataURL !== "function") {
-      throw new Error("Unable to create font preview tooltip content.");
-    }
-
-    font = font.replace(/"/g, "'");
-    font = font.replace("!important", "");
-    font = font.trim();
-
-    let fillStyle = getColor("body-color");
-    let {data, size: maxDim} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
-
-    let imageUrl = yield data.string();
-    let doc = this.view.inspector.panelDoc;
-    let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl);
-
-    yield setImageTooltip(this.previewTooltip, doc, imageUrl,
-      {hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight});
-  }),
-
-  _onNewSelection: function () {
-    if (this.previewTooltip) {
-      this.previewTooltip.hide();
-    }
-
-    if (this.colorPicker) {
-      this.colorPicker.hide();
-    }
-
-    if (this.cubicBezier) {
-      this.cubicBezier.hide();
-    }
-
-    if (this.cssDocs) {
-      this.cssDocs.hide();
-    }
-
-    if (this.filterEditor) {
-      this.filterEditor.hide();
-    }
-  },
-
-  /**
-   * Destroy this overlay instance, removing it from the view
-   */
-  destroy: function () {
-    this.removeFromView();
-
-    this.view.inspector.selection.off("new-node-front", this._onNewSelection);
-    this.view = null;
-
-    this._isDestroyed = true;
-  }
-};
+module.exports = HighlightersOverlay;
--- a/devtools/client/inspector/shared/moz.build
+++ b/devtools/client/inspector/shared/moz.build
@@ -1,14 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
     'dom-node-preview.js',
+    'highlighters-overlay.js',
+    'node-types.js',
     'style-inspector-menu.js',
-    'style-inspector-overlays.js',
+    'tooltips-overlay.js',
     'utils.js'
 )
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
copy from devtools/client/inspector/shared/style-inspector-overlays.js
copy to devtools/client/inspector/shared/node-types.js
--- a/devtools/client/inspector/shared/style-inspector-overlays.js
+++ b/devtools/client/inspector/shared/node-types.js
@@ -1,531 +1,17 @@
 /* -*- 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/. */
 
 "use strict";
 
-// The style-inspector overlays are:
-// - tooltips that appear when hovering over property values
-// - editor tooltips that appear when clicking color swatches, etc.
-// - in-content highlighters that appear when hovering over property values
-// - etc.
-
-const {getColor} = require("devtools/client/shared/theme");
-const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
-const {
-  getImageDimensions,
-  setImageTooltip,
-  setBrokenImageTooltip,
-} = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper");
-const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
-const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
-const SwatchCubicBezierTooltip = require("devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip");
-const SwatchFilterTooltip = require("devtools/client/shared/widgets/tooltip/SwatchFilterTooltip");
-const EventEmitter = require("devtools/shared/event-emitter");
-const promise = require("promise");
-const {Task} = require("devtools/shared/task");
-const Services = require("Services");
-const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-
-const PREF_IMAGE_TOOLTIP_SIZE = "devtools.inspector.imagePreviewTooltipSize";
-
-// Types of existing tooltips
-const TOOLTIP_IMAGE_TYPE = "image";
-const TOOLTIP_FONTFAMILY_TYPE = "font-family";
-
-// Types of nodes in the rule/computed-view
-const VIEW_NODE_SELECTOR_TYPE = 1;
-exports.VIEW_NODE_SELECTOR_TYPE = VIEW_NODE_SELECTOR_TYPE;
-const VIEW_NODE_PROPERTY_TYPE = 2;
-exports.VIEW_NODE_PROPERTY_TYPE = VIEW_NODE_PROPERTY_TYPE;
-const VIEW_NODE_VALUE_TYPE = 3;
-exports.VIEW_NODE_VALUE_TYPE = VIEW_NODE_VALUE_TYPE;
-const VIEW_NODE_IMAGE_URL_TYPE = 4;
-exports.VIEW_NODE_IMAGE_URL_TYPE = VIEW_NODE_IMAGE_URL_TYPE;
-const VIEW_NODE_LOCATION_TYPE = 5;
-exports.VIEW_NODE_LOCATION_TYPE = VIEW_NODE_LOCATION_TYPE;
-
 /**
- * Manages all highlighters in the style-inspector.
- *
- * @param {CssRuleView|CssComputedView} view
- *        Either the rule-view or computed-view panel
+ * Types of nodes used in the rule and omputed view.
  */
-function HighlightersOverlay(view) {
-  this.view = view;
-
-  let {CssRuleView} = require("devtools/client/inspector/rules/rules");
-  this.isRuleView = view instanceof CssRuleView;
-
-  this.highlighterUtils = this.view.inspector.toolbox.highlighterUtils;
-
-  this._onMouseMove = this._onMouseMove.bind(this);
-  this._onMouseOut = this._onMouseOut.bind(this);
-
-  this.highlighters = {};
-
-  // Only initialize the overlay if at least one of the highlighter types is
-  // supported
-  this.supportsHighlighters =
-    this.highlighterUtils.supportsCustomHighlighters();
-
-  EventEmitter.decorate(this);
-}
-
-exports.HighlightersOverlay = HighlightersOverlay;
-
-HighlightersOverlay.prototype = {
-  /**
-   * Add the highlighters overlay to the view. This will start tracking mouse
-   * movements and display highlighters when needed
-   */
-  addToView: function () {
-    if (!this.supportsHighlighters || this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    let el = this.view.element;
-    el.addEventListener("mousemove", this._onMouseMove, false);
-    el.addEventListener("mouseout", this._onMouseOut, false);
-    el.ownerDocument.defaultView.addEventListener("mouseout", this._onMouseOut, false);
-
-    this._isStarted = true;
-  },
-
-  /**
-   * Remove the overlay from the current view. This will stop tracking mouse
-   * movement and showing highlighters
-   */
-  removeFromView: function () {
-    if (!this.supportsHighlighters || !this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    this._hideCurrent();
-
-    let el = this.view.element;
-    el.removeEventListener("mousemove", this._onMouseMove, false);
-    el.removeEventListener("mouseout", this._onMouseOut, false);
-
-    this._isStarted = false;
-  },
-
-  _onMouseMove: function (event) {
-    // Bail out if the target is the same as for the last mousemove
-    if (event.target === this._lastHovered) {
-      return;
-    }
-
-    // Only one highlighter can be displayed at a time, hide the currently shown
-    this._hideCurrent();
-
-    this._lastHovered = event.target;
-
-    let nodeInfo = this.view.getNodeInfo(event.target);
-    if (!nodeInfo) {
-      return;
-    }
-
-    // Choose the type of highlighter required for the hovered node
-    let type;
-    if (this._isRuleViewTransform(nodeInfo) ||
-        this._isComputedViewTransform(nodeInfo)) {
-      type = "CssTransformHighlighter";
-    }
-
-    if (type) {
-      this.highlighterShown = type;
-      let node = this.view.inspector.selection.nodeFront;
-      this._getHighlighter(type)
-          .then(highlighter => highlighter.show(node))
-          .then(shown => {
-            if (shown) {
-              this.emit("highlighter-shown");
-            }
-          });
-    }
-  },
-
-  _onMouseOut: function (event) {
-    // Only hide the highlighter if the mouse leaves the currently hovered node.
-    if (!this._lastHovered ||
-        (event && this._lastHovered.contains(event.relatedTarget))) {
-      return;
-    }
-
-    // Otherwise, hide the highlighter.
-    this._lastHovered = null;
-    this._hideCurrent();
-  },
-
-  /**
-   * Is the current hovered node a css transform property value in the rule-view
-   *
-   * @param {Object} nodeInfo
-   * @return {Boolean}
-   */
-  _isRuleViewTransform: function (nodeInfo) {
-    let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
-                      nodeInfo.value.property === "transform";
-    let isEnabled = nodeInfo.value.enabled &&
-                    !nodeInfo.value.overridden &&
-                    !nodeInfo.value.pseudoElement;
-    return this.isRuleView && isTransform && isEnabled;
-  },
-
-  /**
-   * Is the current hovered node a css transform property value in the
-   * computed-view
-   *
-   * @param {Object} nodeInfo
-   * @return {Boolean}
-   */
-  _isComputedViewTransform: function (nodeInfo) {
-    let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
-                      nodeInfo.value.property === "transform";
-    return !this.isRuleView && isTransform;
-  },
-
-  /**
-   * Hide the currently shown highlighter
-   */
-  _hideCurrent: function () {
-    if (!this.highlighterShown || !this.highlighters[this.highlighterShown]) {
-      return;
-    }
-
-    // For some reason, the call to highlighter.hide doesn't always return a
-    // promise. This causes some tests to fail when trying to install a
-    // rejection handler on the result of the call. To avoid this, check
-    // whether the result is truthy before installing the handler.
-    let onHidden = this.highlighters[this.highlighterShown].hide();
-    if (onHidden) {
-      onHidden.then(null, e => console.error(e));
-    }
-
-    this.highlighterShown = null;
-    this.emit("highlighter-hidden");
-  },
-
-  /**
-   * Get a highlighter front given a type. It will only be initialized once
-   * @param {String} type The highlighter type. One of this.highlighters
-   * @return a promise that resolves to the highlighter
-   */
-  _getHighlighter: function (type) {
-    let utils = this.highlighterUtils;
-
-    if (this.highlighters[type]) {
-      return promise.resolve(this.highlighters[type]);
-    }
-
-    return utils.getHighlighterByType(type).then(highlighter => {
-      this.highlighters[type] = highlighter;
-      return highlighter;
-    });
-  },
-
-  /**
-   * Destroy this overlay instance, removing it from the view and destroying
-   * all initialized highlighters
-   */
-  destroy: function () {
-    this.removeFromView();
-
-    for (let type in this.highlighters) {
-      if (this.highlighters[type]) {
-        this.highlighters[type].finalize();
-        this.highlighters[type] = null;
-      }
-    }
-
-    this.view = null;
-    this.highlighterUtils = null;
-
-    this._isDestroyed = true;
-  }
-};
-
-/**
- * Manages all tooltips in the style-inspector.
- *
- * @param {CssRuleView|CssComputedView} view
- *        Either the rule-view or computed-view panel
- */
-function TooltipsOverlay(view) {
-  this.view = view;
-
-  let {CssRuleView} = require("devtools/client/inspector/rules/rules");
-  this.isRuleView = view instanceof CssRuleView;
-  this._cssProperties = getCssProperties(this.view.inspector.toolbox);
-
-  this._onNewSelection = this._onNewSelection.bind(this);
-  this.view.inspector.selection.on("new-node-front", this._onNewSelection);
-}
-
-exports.TooltipsOverlay = TooltipsOverlay;
 
-TooltipsOverlay.prototype = {
-  get isEditing() {
-    return this.colorPicker.tooltip.isVisible() ||
-           this.colorPicker.eyedropperOpen ||
-           this.cubicBezier.tooltip.isVisible() ||
-           this.filterEditor.tooltip.isVisible();
-  },
-
-  /**
-   * Add the tooltips overlay to the view. This will start tracking mouse
-   * movements and display tooltips when needed
-   */
-  addToView: function () {
-    if (this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    let { toolbox } = this.view.inspector;
-
-    // Initializing the different tooltips that are used in the inspector.
-    // These tooltips are attached to the toolbox document if they require a popup panel.
-    // Otherwise, it is attached to the inspector panel document if it is an inline
-    // editor.
-    this.previewTooltip = new HTMLTooltip(toolbox.doc, {
-      type: "arrow",
-      useXulWrapper: true
-    });
-    this.previewTooltip.startTogglingOnHover(this.view.element,
-      this._onPreviewTooltipTargetHover.bind(this));
-
-    // MDN CSS help tooltip
-    this.cssDocs = new CssDocsTooltip(toolbox.doc);
-
-    if (this.isRuleView) {
-      // Color picker tooltip
-      this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc, this.view.inspector);
-      // Cubic bezier tooltip
-      this.cubicBezier = new SwatchCubicBezierTooltip(toolbox.doc);
-      // Filter editor tooltip
-      this.filterEditor = new SwatchFilterTooltip(toolbox.doc,
-        this._cssProperties.getValidityChecker(this.view.inspector.panelDoc));
-    }
-
-    this._isStarted = true;
-  },
-
-  /**
-   * Remove the tooltips overlay from the view. This will stop tracking mouse
-   * movements and displaying tooltips
-   */
-  removeFromView: function () {
-    if (!this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    this.previewTooltip.stopTogglingOnHover(this.view.element);
-    this.previewTooltip.destroy();
-
-    if (this.colorPicker) {
-      this.colorPicker.destroy();
-    }
-
-    if (this.cubicBezier) {
-      this.cubicBezier.destroy();
-    }
-
-    if (this.cssDocs) {
-      this.cssDocs.destroy();
-    }
-
-    if (this.filterEditor) {
-      this.filterEditor.destroy();
-    }
-
-    this._isStarted = false;
-  },
-
-  /**
-   * Given a hovered node info, find out which type of tooltip should be shown,
-   * if any
-   *
-   * @param {Object} nodeInfo
-   * @return {String} The tooltip type to be shown, or null
-   */
-  _getTooltipType: function ({type, value: prop}) {
-    let tooltipType = null;
-    let inspector = this.view.inspector;
-
-    // Image preview tooltip
-    if (type === VIEW_NODE_IMAGE_URL_TYPE &&
-        inspector.hasUrlToImageDataResolver) {
-      tooltipType = TOOLTIP_IMAGE_TYPE;
-    }
-
-    // Font preview tooltip
-    if (type === VIEW_NODE_VALUE_TYPE && prop.property === "font-family") {
-      let value = prop.value.toLowerCase();
-      if (value !== "inherit" && value !== "unset" && value !== "initial") {
-        tooltipType = TOOLTIP_FONTFAMILY_TYPE;
-      }
-    }
-
-    return tooltipType;
-  },
-
-  /**
-   * Executed by the tooltip when the pointer hovers over an element of the
-   * view. Used to decide whether the tooltip should be shown or not and to
-   * actually put content in it.
-   * Checks if the hovered target is a css value we support tooltips for.
-   *
-   * @param {DOMNode} target The currently hovered node
-   * @return {Promise}
-   */
-  _onPreviewTooltipTargetHover: Task.async(function* (target) {
-    let nodeInfo = this.view.getNodeInfo(target);
-    if (!nodeInfo) {
-      // The hovered node isn't something we care about
-      return false;
-    }
-
-    let type = this._getTooltipType(nodeInfo);
-    if (!type) {
-      // There is no tooltip type defined for the hovered node
-      return false;
-    }
-
-    if (this.isRuleView && this.colorPicker.tooltip.isVisible()) {
-      this.colorPicker.revert();
-      this.colorPicker.hide();
-    }
-
-    if (this.isRuleView && this.cubicBezier.tooltip.isVisible()) {
-      this.cubicBezier.revert();
-      this.cubicBezier.hide();
-    }
-
-    if (this.isRuleView && this.cssDocs.tooltip.isVisible()) {
-      this.cssDocs.hide();
-    }
-
-    if (this.isRuleView && this.filterEditor.tooltip.isVisible()) {
-      this.filterEditor.revert();
-      this.filterEdtior.hide();
-    }
-
-    let inspector = this.view.inspector;
-
-    if (type === TOOLTIP_IMAGE_TYPE) {
-      try {
-        yield this._setImagePreviewTooltip(nodeInfo.value.url);
-      } catch (e) {
-        yield setBrokenImageTooltip(this.previewTooltip, this.view.inspector.panelDoc);
-      }
-      return true;
-    }
-
-    if (type === TOOLTIP_FONTFAMILY_TYPE) {
-      let font = nodeInfo.value.value;
-      let nodeFront = inspector.selection.nodeFront;
-      yield this._setFontPreviewTooltip(font, nodeFront);
-      return true;
-    }
-
-    return false;
-  }),
-
-  /**
-   * Set the content of the preview tooltip to display an image preview. The image URL can
-   * be relative, a call will be made to the debuggee to retrieve the image content as an
-   * imageData URI.
-   *
-   * @param {String} imageUrl
-   *        The image url value (may be relative or absolute).
-   * @return {Promise} A promise that resolves when the preview tooltip content is ready
-   */
-  _setImagePreviewTooltip: Task.async(function* (imageUrl) {
-    let doc = this.view.inspector.panelDoc;
-    let maxDim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE);
-
-    let naturalWidth, naturalHeight;
-    if (imageUrl.startsWith("data:")) {
-      // If the imageUrl already is a data-url, save ourselves a round-trip
-      let size = yield getImageDimensions(doc, imageUrl);
-      naturalWidth = size.naturalWidth;
-      naturalHeight = size.naturalHeight;
-    } else {
-      let inspectorFront = this.view.inspector.inspector;
-      let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl, maxDim);
-      imageUrl = yield data.string();
-      naturalWidth = size.naturalWidth;
-      naturalHeight = size.naturalHeight;
-    }
-
-    yield setImageTooltip(this.previewTooltip, doc, imageUrl,
-      {maxDim, naturalWidth, naturalHeight});
-  }),
-
-  /**
-   * Set the content of the preview tooltip to display a font family preview.
-   *
-   * @param {String} font
-   *        The font family value.
-   * @param {object} nodeFront
-   *        The NodeActor that will used to retrieve the dataURL for the font
-   *        family tooltip contents.
-   * @return {Promise} A promise that resolves when the preview tooltip content is ready
-   */
-  _setFontPreviewTooltip: Task.async(function* (font, nodeFront) {
-    if (!font || !nodeFront || typeof nodeFront.getFontFamilyDataURL !== "function") {
-      throw new Error("Unable to create font preview tooltip content.");
-    }
-
-    font = font.replace(/"/g, "'");
-    font = font.replace("!important", "");
-    font = font.trim();
-
-    let fillStyle = getColor("body-color");
-    let {data, size: maxDim} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
-
-    let imageUrl = yield data.string();
-    let doc = this.view.inspector.panelDoc;
-    let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl);
-
-    yield setImageTooltip(this.previewTooltip, doc, imageUrl,
-      {hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight});
-  }),
-
-  _onNewSelection: function () {
-    if (this.previewTooltip) {
-      this.previewTooltip.hide();
-    }
-
-    if (this.colorPicker) {
-      this.colorPicker.hide();
-    }
-
-    if (this.cubicBezier) {
-      this.cubicBezier.hide();
-    }
-
-    if (this.cssDocs) {
-      this.cssDocs.hide();
-    }
-
-    if (this.filterEditor) {
-      this.filterEditor.hide();
-    }
-  },
-
-  /**
-   * Destroy this overlay instance, removing it from the view
-   */
-  destroy: function () {
-    this.removeFromView();
-
-    this.view.inspector.selection.off("new-node-front", this._onNewSelection);
-    this.view = null;
-
-    this._isDestroyed = true;
-  }
-};
+exports.VIEW_NODE_SELECTOR_TYPE = 1;
+exports.VIEW_NODE_PROPERTY_TYPE = 2;
+exports.VIEW_NODE_VALUE_TYPE = 3;
+exports.VIEW_NODE_IMAGE_URL_TYPE = 4;
+exports.VIEW_NODE_LOCATION_TYPE = 5;
--- a/devtools/client/inspector/shared/style-inspector-menu.js
+++ b/devtools/client/inspector/shared/style-inspector-menu.js
@@ -8,17 +8,23 @@
 
 const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const Services = require("Services");
 const {Task} = require("devtools/shared/task");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
-const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
+const {
+  VIEW_NODE_SELECTOR_TYPE,
+  VIEW_NODE_PROPERTY_TYPE,
+  VIEW_NODE_VALUE_TYPE,
+  VIEW_NODE_IMAGE_URL_TYPE,
+  VIEW_NODE_LOCATION_TYPE,
+} = require("devtools/client/inspector/shared/node-types");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
 const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
 
 const PREF_ENABLE_MDN_DOCS_TOOLTIP =
   "devtools.inspector.mdnDocsTooltip.enabled";
@@ -158,28 +164,28 @@ StyleInspectorMenu.prototype = {
         this._onCopySelector();
       },
       visible: false,
     });
 
     this._clickedNodeInfo = this._getClickedNodeInfo();
     if (this.isRuleView && this._clickedNodeInfo) {
       switch (this._clickedNodeInfo.type) {
-        case overlays.VIEW_NODE_PROPERTY_TYPE :
+        case VIEW_NODE_PROPERTY_TYPE :
           menuitemCopyPropertyDeclaration.visible = true;
           menuitemCopyPropertyName.visible = true;
           break;
-        case overlays.VIEW_NODE_VALUE_TYPE :
+        case VIEW_NODE_VALUE_TYPE :
           menuitemCopyPropertyDeclaration.visible = true;
           menuitemCopyPropertyValue.visible = true;
           break;
-        case overlays.VIEW_NODE_SELECTOR_TYPE :
+        case VIEW_NODE_SELECTOR_TYPE :
           menuitemCopySelector.visible = true;
           break;
-        case overlays.VIEW_NODE_LOCATION_TYPE :
+        case VIEW_NODE_LOCATION_TYPE :
           menuitemCopyLocation.visible = true;
           break;
       }
     }
 
     menu.append(menuitemCopy);
     menu.append(menuitemCopyLocation);
     menu.append(menuitemCopyRule);
@@ -306,30 +312,30 @@ StyleInspectorMenu.prototype = {
     return true;
   },
 
   _isPropertyName: function () {
     let nodeInfo = this._getClickedNodeInfo();
     if (!nodeInfo) {
       return false;
     }
-    return nodeInfo.type == overlays.VIEW_NODE_PROPERTY_TYPE;
+    return nodeInfo.type == VIEW_NODE_PROPERTY_TYPE;
   },
 
   /**
    * Check if the current node (clicked node) is an image URL
    *
    * @return {Boolean} true if the node is an image url
    */
   _isImageUrl: function () {
     let nodeInfo = this._getClickedNodeInfo();
     if (!nodeInfo) {
       return false;
     }
-    return nodeInfo.type == overlays.VIEW_NODE_IMAGE_URL_TYPE;
+    return nodeInfo.type == VIEW_NODE_IMAGE_URL_TYPE;
   },
 
   /**
    * Get the DOM Node container for the current popupNode.
    * If popupNode is a textNode, return the parent node, otherwise return
    * popupNode itself.
    *
    * @return {DOMNode}
copy from devtools/client/inspector/shared/style-inspector-overlays.js
copy to devtools/client/inspector/shared/tooltips-overlay.js
--- a/devtools/client/inspector/shared/style-inspector-overlays.js
+++ b/devtools/client/inspector/shared/tooltips-overlay.js
@@ -1,258 +1,46 @@
 /* -*- 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/. */
 
 "use strict";
 
-// The style-inspector overlays are:
-// - tooltips that appear when hovering over property values
-// - editor tooltips that appear when clicking color swatches, etc.
-// - in-content highlighters that appear when hovering over property values
-// - etc.
+/**
+ * The tooltip overlays are tooltips that appear when hovering over property values and
+ * editor tooltips that appear when clicking swatch based editors.
+ */
 
-const {getColor} = require("devtools/client/shared/theme");
-const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
+const { Task } = require("devtools/shared/task");
+const Services = require("Services");
+const {
+  VIEW_NODE_VALUE_TYPE,
+  VIEW_NODE_IMAGE_URL_TYPE,
+} = require("devtools/client/inspector/shared/node-types");
+const { getColor } = require("devtools/client/shared/theme");
+const { getCssProperties } = require("devtools/shared/fronts/css-properties");
+const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
+const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
 const {
   getImageDimensions,
   setImageTooltip,
   setBrokenImageTooltip,
 } = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper");
-const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
 const SwatchColorPickerTooltip = require("devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
 const SwatchCubicBezierTooltip = require("devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip");
 const SwatchFilterTooltip = require("devtools/client/shared/widgets/tooltip/SwatchFilterTooltip");
-const EventEmitter = require("devtools/shared/event-emitter");
-const promise = require("promise");
-const {Task} = require("devtools/shared/task");
-const Services = require("Services");
-const {getCssProperties} = require("devtools/shared/fronts/css-properties");
 
 const PREF_IMAGE_TOOLTIP_SIZE = "devtools.inspector.imagePreviewTooltipSize";
 
 // Types of existing tooltips
 const TOOLTIP_IMAGE_TYPE = "image";
 const TOOLTIP_FONTFAMILY_TYPE = "font-family";
 
-// Types of nodes in the rule/computed-view
-const VIEW_NODE_SELECTOR_TYPE = 1;
-exports.VIEW_NODE_SELECTOR_TYPE = VIEW_NODE_SELECTOR_TYPE;
-const VIEW_NODE_PROPERTY_TYPE = 2;
-exports.VIEW_NODE_PROPERTY_TYPE = VIEW_NODE_PROPERTY_TYPE;
-const VIEW_NODE_VALUE_TYPE = 3;
-exports.VIEW_NODE_VALUE_TYPE = VIEW_NODE_VALUE_TYPE;
-const VIEW_NODE_IMAGE_URL_TYPE = 4;
-exports.VIEW_NODE_IMAGE_URL_TYPE = VIEW_NODE_IMAGE_URL_TYPE;
-const VIEW_NODE_LOCATION_TYPE = 5;
-exports.VIEW_NODE_LOCATION_TYPE = VIEW_NODE_LOCATION_TYPE;
-
-/**
- * Manages all highlighters in the style-inspector.
- *
- * @param {CssRuleView|CssComputedView} view
- *        Either the rule-view or computed-view panel
- */
-function HighlightersOverlay(view) {
-  this.view = view;
-
-  let {CssRuleView} = require("devtools/client/inspector/rules/rules");
-  this.isRuleView = view instanceof CssRuleView;
-
-  this.highlighterUtils = this.view.inspector.toolbox.highlighterUtils;
-
-  this._onMouseMove = this._onMouseMove.bind(this);
-  this._onMouseOut = this._onMouseOut.bind(this);
-
-  this.highlighters = {};
-
-  // Only initialize the overlay if at least one of the highlighter types is
-  // supported
-  this.supportsHighlighters =
-    this.highlighterUtils.supportsCustomHighlighters();
-
-  EventEmitter.decorate(this);
-}
-
-exports.HighlightersOverlay = HighlightersOverlay;
-
-HighlightersOverlay.prototype = {
-  /**
-   * Add the highlighters overlay to the view. This will start tracking mouse
-   * movements and display highlighters when needed
-   */
-  addToView: function () {
-    if (!this.supportsHighlighters || this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    let el = this.view.element;
-    el.addEventListener("mousemove", this._onMouseMove, false);
-    el.addEventListener("mouseout", this._onMouseOut, false);
-    el.ownerDocument.defaultView.addEventListener("mouseout", this._onMouseOut, false);
-
-    this._isStarted = true;
-  },
-
-  /**
-   * Remove the overlay from the current view. This will stop tracking mouse
-   * movement and showing highlighters
-   */
-  removeFromView: function () {
-    if (!this.supportsHighlighters || !this._isStarted || this._isDestroyed) {
-      return;
-    }
-
-    this._hideCurrent();
-
-    let el = this.view.element;
-    el.removeEventListener("mousemove", this._onMouseMove, false);
-    el.removeEventListener("mouseout", this._onMouseOut, false);
-
-    this._isStarted = false;
-  },
-
-  _onMouseMove: function (event) {
-    // Bail out if the target is the same as for the last mousemove
-    if (event.target === this._lastHovered) {
-      return;
-    }
-
-    // Only one highlighter can be displayed at a time, hide the currently shown
-    this._hideCurrent();
-
-    this._lastHovered = event.target;
-
-    let nodeInfo = this.view.getNodeInfo(event.target);
-    if (!nodeInfo) {
-      return;
-    }
-
-    // Choose the type of highlighter required for the hovered node
-    let type;
-    if (this._isRuleViewTransform(nodeInfo) ||
-        this._isComputedViewTransform(nodeInfo)) {
-      type = "CssTransformHighlighter";
-    }
-
-    if (type) {
-      this.highlighterShown = type;
-      let node = this.view.inspector.selection.nodeFront;
-      this._getHighlighter(type)
-          .then(highlighter => highlighter.show(node))
-          .then(shown => {
-            if (shown) {
-              this.emit("highlighter-shown");
-            }
-          });
-    }
-  },
-
-  _onMouseOut: function (event) {
-    // Only hide the highlighter if the mouse leaves the currently hovered node.
-    if (!this._lastHovered ||
-        (event && this._lastHovered.contains(event.relatedTarget))) {
-      return;
-    }
-
-    // Otherwise, hide the highlighter.
-    this._lastHovered = null;
-    this._hideCurrent();
-  },
-
-  /**
-   * Is the current hovered node a css transform property value in the rule-view
-   *
-   * @param {Object} nodeInfo
-   * @return {Boolean}
-   */
-  _isRuleViewTransform: function (nodeInfo) {
-    let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
-                      nodeInfo.value.property === "transform";
-    let isEnabled = nodeInfo.value.enabled &&
-                    !nodeInfo.value.overridden &&
-                    !nodeInfo.value.pseudoElement;
-    return this.isRuleView && isTransform && isEnabled;
-  },
-
-  /**
-   * Is the current hovered node a css transform property value in the
-   * computed-view
-   *
-   * @param {Object} nodeInfo
-   * @return {Boolean}
-   */
-  _isComputedViewTransform: function (nodeInfo) {
-    let isTransform = nodeInfo.type === VIEW_NODE_VALUE_TYPE &&
-                      nodeInfo.value.property === "transform";
-    return !this.isRuleView && isTransform;
-  },
-
-  /**
-   * Hide the currently shown highlighter
-   */
-  _hideCurrent: function () {
-    if (!this.highlighterShown || !this.highlighters[this.highlighterShown]) {
-      return;
-    }
-
-    // For some reason, the call to highlighter.hide doesn't always return a
-    // promise. This causes some tests to fail when trying to install a
-    // rejection handler on the result of the call. To avoid this, check
-    // whether the result is truthy before installing the handler.
-    let onHidden = this.highlighters[this.highlighterShown].hide();
-    if (onHidden) {
-      onHidden.then(null, e => console.error(e));
-    }
-
-    this.highlighterShown = null;
-    this.emit("highlighter-hidden");
-  },
-
-  /**
-   * Get a highlighter front given a type. It will only be initialized once
-   * @param {String} type The highlighter type. One of this.highlighters
-   * @return a promise that resolves to the highlighter
-   */
-  _getHighlighter: function (type) {
-    let utils = this.highlighterUtils;
-
-    if (this.highlighters[type]) {
-      return promise.resolve(this.highlighters[type]);
-    }
-
-    return utils.getHighlighterByType(type).then(highlighter => {
-      this.highlighters[type] = highlighter;
-      return highlighter;
-    });
-  },
-
-  /**
-   * Destroy this overlay instance, removing it from the view and destroying
-   * all initialized highlighters
-   */
-  destroy: function () {
-    this.removeFromView();
-
-    for (let type in this.highlighters) {
-      if (this.highlighters[type]) {
-        this.highlighters[type].finalize();
-        this.highlighters[type] = null;
-      }
-    }
-
-    this.view = null;
-    this.highlighterUtils = null;
-
-    this._isDestroyed = true;
-  }
-};
-
 /**
  * Manages all tooltips in the style-inspector.
  *
  * @param {CssRuleView|CssComputedView} view
  *        Either the rule-view or computed-view panel
  */
 function TooltipsOverlay(view) {
   this.view = view;
@@ -260,18 +48,16 @@ function TooltipsOverlay(view) {
   let {CssRuleView} = require("devtools/client/inspector/rules/rules");
   this.isRuleView = view instanceof CssRuleView;
   this._cssProperties = getCssProperties(this.view.inspector.toolbox);
 
   this._onNewSelection = this._onNewSelection.bind(this);
   this.view.inspector.selection.on("new-node-front", this._onNewSelection);
 }
 
-exports.TooltipsOverlay = TooltipsOverlay;
-
 TooltipsOverlay.prototype = {
   get isEditing() {
     return this.colorPicker.tooltip.isVisible() ||
            this.colorPicker.eyedropperOpen ||
            this.cubicBezier.tooltip.isVisible() ||
            this.filterEditor.tooltip.isVisible();
   },
 
@@ -524,8 +310,10 @@ TooltipsOverlay.prototype = {
     this.removeFromView();
 
     this.view.inspector.selection.off("new-node-front", this._onNewSelection);
     this.view = null;
 
     this._isDestroyed = true;
   }
 };
+
+module.exports = TooltipsOverlay;