Backed out 2 changesets (bug 1307481) for mass dt bustage a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 07 Oct 2016 11:54:38 -0700
changeset 422569 5ddd619ca0c5410faca3fc1e0ae52ad14de898a2
parent 422568 91c6a72e5d0d7779aae8fd514c1e18d5e083c8e4
child 422570 76bab3177db2432347164850b953c3bea269bb08
child 422574 a7c9eaef19cccfc35a34dc406b5bac1fb1727cac
child 422637 efa3b654aa77bcb9b3dd7fc5a52efb6b5afc34d6
push id31744
push usermwein@mozilla.com
push dateFri, 07 Oct 2016 21:14:49 +0000
reviewersbackout
bugs1307481
milestone52.0a1
backs out91c6a72e5d0d7779aae8fd514c1e18d5e083c8e4
a9f9f561127275de84173d0f536e6d74a6000730
Backed out 2 changesets (bug 1307481) for mass dt bustage a=backout Backed out changeset 91c6a72e5d0d (bug 1307481) Backed out changeset a9f9f5611272 (bug 1307481)
devtools/client/inspector/inspector-search.js
devtools/client/inspector/markup/markup.js
devtools/client/inspector/rules/rules.js
devtools/client/inspector/shared/style-inspector-overlays.js
devtools/client/shared/autocomplete-popup.js
devtools/client/shared/widgets/tooltip/CssDocsTooltip.js
devtools/client/shared/widgets/tooltip/HTMLTooltip.js
devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip.js
devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
devtools/client/shared/widgets/tooltip/Tooltip.js
devtools/client/webconsole/jsterm.js
--- a/devtools/client/inspector/inspector-search.js
+++ b/devtools/client/inspector/inspector-search.js
@@ -170,18 +170,17 @@ function SelectorAutocompleter(inspector
   let options = {
     listId: "searchbox-panel-listbox",
     autoSelect: true,
     position: "top",
     theme: "auto",
     onClick: this._onSearchPopupClick,
   };
 
-  // The popup will be attached to the toolbox document.
-  this.searchPopup = new AutocompletePopup(inspector._toolbox.doc, options);
+  this.searchPopup = new AutocompletePopup(inspector._toolbox, options);
 
   this.searchBox.addEventListener("input", this.showSuggestions, true);
   this.searchBox.addEventListener("keypress", this._onSearchKeypress, true);
   this.inspector.on("markupmutation", this._onMarkupMutation);
 
   // For testing, we need to be able to wait for the most recent node request
   // to finish.  Tests can watch this promise for that.
   this._lastQuery = promise.resolve(null);
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -99,21 +99,22 @@ function MarkupView(inspector, frame, co
   }
 
   this.collapseAttributes =
     Services.prefs.getBoolPref(ATTR_COLLAPSE_ENABLED_PREF);
   this.collapseAttributeLength =
     Services.prefs.getIntPref(ATTR_COLLAPSE_LENGTH_PREF);
 
   // Creating the popup to be used to show CSS suggestions.
-  // The popup will be attached to the toolbox document.
-  this.popup = new AutocompletePopup(inspector.toolbox.doc, {
+  let options = {
     autoSelect: true,
     theme: "auto",
-  });
+  };
+
+  this.popup = new AutocompletePopup(inspector.toolbox, options);
 
   this.undo = new UndoStack();
   this.undo.installController(controllerWindow);
 
   this._containers = new Map();
 
   // Binding functions that need to be called in scope.
   this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
@@ -179,20 +180,19 @@ MarkupView.prototype = {
    */
   _handleRejectionIfNotDestroyed: function (e) {
     if (!this._destroyer) {
       console.error(e);
     }
   },
 
   _initTooltips: function () {
-    // The tooltips will be attached to the toolbox document.
-    this.eventDetailsTooltip = new HTMLTooltip(this.toolbox.doc,
+    this.eventDetailsTooltip = new HTMLTooltip(this.toolbox,
       {type: "arrow"});
-    this.imagePreviewTooltip = new HTMLTooltip(this.toolbox.doc,
+    this.imagePreviewTooltip = new HTMLTooltip(this.toolbox,
       {type: "arrow", useXulWrapper: "true"});
     this._enableImagePreviewTooltip();
   },
 
   _enableImagePreviewTooltip: function () {
     this.imagePreviewTooltip.startTogglingOnHover(this._elt,
       this._isImagePreviewTarget);
   },
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -154,21 +154,21 @@ function CssRuleView(inspector, document
   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);
 
-  // The popup will be attached to the toolbox document.
-  this.popup = new AutocompletePopup(inspector._toolbox.doc, {
+  let options = {
     autoSelect: true,
     theme: "auto"
-  });
+  };
+  this.popup = new AutocompletePopup(inspector._toolbox, options);
 
   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.addToView();
--- a/devtools/client/inspector/shared/style-inspector-overlays.js
+++ b/devtools/client/inspector/shared/style-inspector-overlays.js
@@ -281,37 +281,34 @@ TooltipsOverlay.prototype = {
    */
   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, {
+    // Image, fonts, ... preview tooltip
+    this.previewTooltip = new HTMLTooltip(toolbox, {
       type: "arrow",
       useXulWrapper: true
     });
     this.previewTooltip.startTogglingOnHover(this.view.element,
       this._onPreviewTooltipTargetHover.bind(this));
 
     // MDN CSS help tooltip
-    this.cssDocs = new CssDocsTooltip(toolbox.doc);
+    this.cssDocs = new CssDocsTooltip(toolbox);
 
     if (this.isRuleView) {
       // Color picker tooltip
-      this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc, this.view.inspector);
+      this.colorPicker = new SwatchColorPickerTooltip(toolbox, this.view.inspector);
       // Cubic bezier tooltip
-      this.cubicBezier = new SwatchCubicBezierTooltip(toolbox.doc);
+      this.cubicBezier = new SwatchCubicBezierTooltip(toolbox);
       // Filter editor tooltip
-      this.filterEditor = new SwatchFilterTooltip(toolbox.doc,
+      this.filterEditor = new SwatchFilterTooltip(toolbox,
         this._cssProperties.getValidityChecker(this.view.inspector.panelDoc));
     }
 
     this._isStarted = true;
   },
 
   /**
    * Remove the tooltips overlay from the view. This will stop tracking mouse
--- a/devtools/client/shared/autocomplete-popup.js
+++ b/devtools/client/shared/autocomplete-popup.js
@@ -11,33 +11,33 @@ const {gDevTools} = require("devtools/cl
 const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
 const EventEmitter = require("devtools/shared/event-emitter");
 
 let itemIdCounter = 0;
 /**
  * Autocomplete popup UI implementation.
  *
  * @constructor
- * @param {Document} toolboxDoc
- *        The toolbox document to attach the autocomplete popup panel.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox required to instanciate the HTMLTooltip.
  * @param {Object} options
  *        An object consiting any of the following options:
  *        - listId {String} The id for the list <LI> element.
  *        - position {String} The position for the tooltip ("top" or "bottom").
  *        - theme {String} String related to the theme of the popup
  *        - autoSelect {Boolean} Boolean to allow the first entry of the popup
  *          panel to be automatically selected when the popup shows.
  *        - onSelect {String} Callback called when the selected index is updated.
  *        - onClick {String} Callback called when the autocomplete popup receives a click
  *          event. The selectedIndex will already be updated if need be.
  */
-function AutocompletePopup(toolboxDoc, options = {}) {
+function AutocompletePopup(toolbox, options = {}) {
   EventEmitter.decorate(this);
 
-  this._document = toolboxDoc;
+  this._document = toolbox.doc;
 
   this.autoSelect = options.autoSelect || false;
   this.position = options.position || "bottom";
   let theme = options.theme || "dark";
 
   this.onSelectCallback = options.onSelect;
   this.onClickCallback = options.onClick;
 
@@ -46,17 +46,17 @@ function AutocompletePopup(toolboxDoc, o
     theme = Services.prefs.getCharPref("devtools.theme");
     this.autoThemeEnabled = true;
     // Setup theme change listener.
     this._handleThemeChange = this._handleThemeChange.bind(this);
     gDevTools.on("pref-changed", this._handleThemeChange);
   }
 
   // Create HTMLTooltip instance
-  this._tooltip = new HTMLTooltip(this._document);
+  this._tooltip = new HTMLTooltip(toolbox);
   this._tooltip.panel.classList.add(
     "devtools-autocomplete-popup",
     "devtools-monospace",
     theme + "-theme");
   // Stop this appearing as an alert to accessibility.
   this._tooltip.panel.setAttribute("role", "presentation");
 
   this._list = this._document.createElementNS(HTML_NS, "ul");
--- a/devtools/client/shared/widgets/tooltip/CssDocsTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/CssDocsTooltip.js
@@ -10,33 +10,33 @@ const {KeyShortcuts} = require("devtools
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 
 const TOOLTIP_WIDTH = 418;
 const TOOLTIP_HEIGHT = 308;
 
 /**
  * Tooltip for displaying docs for CSS properties from MDN.
  *
- * @param {Document} toolboxDoc
- *        The toolbox document to attach the CSS docs tooltip.
+ * @param {Toolbox} toolbox
+ *        Toolbox used to create the tooltip.
  */
-function CssDocsTooltip(toolboxDoc) {
-  this.tooltip = new HTMLTooltip(toolboxDoc, {
+function CssDocsTooltip(toolbox) {
+  this.tooltip = new HTMLTooltip(toolbox, {
     type: "arrow",
     consumeOutsideClicks: true,
     autofocus: true,
     useXulWrapper: true,
     stylesheet: "chrome://devtools/content/shared/widgets/mdn-docs.css",
   });
   this.widget = this.setMdnDocsContent();
   this._onVisitLink = this._onVisitLink.bind(this);
   this.widget.on("visitlink", this._onVisitLink);
 
   // Initialize keyboard shortcuts
-  this.shortcuts = new KeyShortcuts({ window: this.tooltip.topWindow });
+  this.shortcuts = new KeyShortcuts({ window: toolbox.win });
   this._onShortcut = this._onShortcut.bind(this);
 
   this.shortcuts.on("Escape", this._onShortcut);
 }
 
 CssDocsTooltip.prototype = {
   /**
    * Load CSS docs for the given property,
--- a/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/HTMLTooltip.js
@@ -186,42 +186,42 @@ const getRelativeRect = function (node, 
   let bottom = top + height;
 
   return {top, right, bottom, left, width, height};
 };
 
 /**
  * The HTMLTooltip can display HTML content in a tooltip popup.
  *
- * @param {Document} toolboxDoc
- *        The toolbox document to attach the HTMLTooltip popup.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox, needed to get the devtools main window.
  * @param {Object}
  *        - {String} type
  *          Display type of the tooltip. Possible values: "normal", "arrow"
  *        - {Boolean} autofocus
  *          Defaults to false. Should the tooltip be focused when opening it.
  *        - {Boolean} consumeOutsideClicks
  *          Defaults to true. The tooltip is closed when clicking outside.
  *          Should this event be stopped and consumed or not.
  *        - {Boolean} useXulWrapper
  *          Defaults to false. If the tooltip is hosted in a XUL document, use a XUL panel
  *          in order to use all the screen viewport available.
  *        - {String} stylesheet
  *          Style sheet URL to apply to the tooltip content.
  */
-function HTMLTooltip(toolboxDoc, {
+function HTMLTooltip(toolbox, {
     type = "normal",
     autofocus = false,
     consumeOutsideClicks = true,
     useXulWrapper = false,
     stylesheet = "",
   } = {}) {
   EventEmitter.decorate(this);
 
-  this.doc = toolboxDoc;
+  this.doc = toolbox.doc;
   this.type = type;
   this.autofocus = autofocus;
   this.consumeOutsideClicks = consumeOutsideClicks;
   this.useXulWrapper = this._isXUL() && useXulWrapper;
 
   // The top window is used to attach click event listeners to close the tooltip if the
   // user clicks on the content page.
   this.topWindow = this._getTopWindow();
--- a/devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchBasedEditorTooltip.js
@@ -7,28 +7,26 @@
 const EventEmitter = require("devtools/shared/event-emitter");
 const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
 
 /**
  * Base class for all (color, gradient, ...)-swatch based value editors inside
  * tooltips
  *
- * @param {Document} document
- *        The document to attach the SwatchBasedEditorTooltip. This is either the toolbox
- *        document if the tooltip is a popup tooltip or the panel's document if it is an
- *        inline editor.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox, needed to get the devtools main window.
  */
-function SwatchBasedEditorTooltip(document, stylesheet) {
+function SwatchBasedEditorTooltip(toolbox, stylesheet) {
   EventEmitter.decorate(this);
   // Creating a tooltip instance
   // This one will consume outside clicks as it makes more sense to let the user
   // close the tooltip by clicking out
   // It will also close on <escape> and <enter>
-  this.tooltip = new HTMLTooltip(document, {
+  this.tooltip = new HTMLTooltip(toolbox, {
     type: "arrow",
     consumeOutsideClicks: true,
     useXulWrapper: true,
     stylesheet
   });
 
   // By default, swatch-based editor tooltips revert value change on <esc> and
   // commit value change on <enter>
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -15,26 +15,24 @@ const XHTML_NS = "http://www.w3.org/1999
 
 /**
  * The swatch color picker tooltip class is a specific class meant to be used
  * along with output-parser's generated color swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
  * It just wraps a standard Tooltip and sets its content with an instance of a
  * color picker.
  *
- * @param {Document} document
- *        The document to attach the SwatchColorPickerTooltip. This is either the toolbox
- *        document if the tooltip is a popup tooltip or the panel's document if it is an
- *        inline editor.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox, needed to get the devtools main window.
  * @param {InspectorPanel} inspector
  *        The inspector panel, needed for the eyedropper.
  */
-function SwatchColorPickerTooltip(document, inspector) {
+function SwatchColorPickerTooltip(toolbox, inspector) {
   let stylesheet = "chrome://devtools/content/shared/widgets/spectrum.css";
-  SwatchBasedEditorTooltip.call(this, document, stylesheet);
+  SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
 
   this.inspector = inspector;
 
   // Creating a spectrum instance. this.spectrum will always be a promise that
   // resolves to the spectrum instance
   this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
   this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
   this._openEyeDropper = this._openEyeDropper.bind(this);
--- a/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchCubicBezierTooltip.js
@@ -15,24 +15,22 @@ const XHTML_NS = "http://www.w3.org/1999
 
 /**
  * The swatch cubic-bezier tooltip class is a specific class meant to be used
  * along with rule-view's generated cubic-bezier swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
  * It just wraps a standard Tooltip and sets its content with an instance of a
  * CubicBezierWidget.
  *
- * @param {Document} document
- *        The document to attach the SwatchCubicBezierTooltip. This is either the toolbox
- *        document if the tooltip is a popup tooltip or the panel's document if it is an
- *        inline editor.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox, needed to get the devtools main window.
  */
-function SwatchCubicBezierTooltip(document) {
+function SwatchCubicBezierTooltip(toolbox) {
   let stylesheet = "chrome://devtools/content/shared/widgets/cubic-bezier.css";
-  SwatchBasedEditorTooltip.call(this, document, stylesheet);
+  SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
 
   // Creating a cubic-bezier instance.
   // this.widget will always be a promise that resolves to the widget instance
   this.widget = this.setCubicBezierContent([0, 0, 1, 1]);
   this._onUpdate = this._onUpdate.bind(this);
 }
 
 SwatchCubicBezierTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
--- a/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchFilterTooltip.js
@@ -14,27 +14,25 @@ const XHTML_NS = "http://www.w3.org/1999
 
 /**
  * The swatch-based css filter tooltip class is a specific class meant to be
  * used along with rule-view's generated css filter swatches.
  * It extends the parent SwatchBasedEditorTooltip class.
  * It just wraps a standard Tooltip and sets its content with an instance of a
  * CSSFilterEditorWidget.
  *
- * @param {Document} document
- *        The document to attach the SwatchFilterTooltip. This is either the toolbox
- *        document if the tooltip is a popup tooltip or the panel's document if it is an
- *        inline editor.
+ * @param {Toolbox} toolbox
+ *        The devtools toolbox, needed to get the devtools main window.
  * @param {function} cssIsValid
  *        A function to check that css declaration's name and values are valid together.
  *        This can be obtained from "shared/fronts/css-properties.js".
  */
-function SwatchFilterTooltip(document, cssIsValid) {
+function SwatchFilterTooltip(toolbox, cssIsValid) {
   let stylesheet = "chrome://devtools/content/shared/widgets/filter-widget.css";
-  SwatchBasedEditorTooltip.call(this, document, stylesheet);
+  SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
   this._cssIsValid = cssIsValid;
 
   // Creating a filter editor instance.
   this.widget = this.setFilterContent("none");
   this._onUpdate = this._onUpdate.bind(this);
 }
 
 SwatchFilterTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.prototype, {
--- a/devtools/client/shared/widgets/tooltip/Tooltip.js
+++ b/devtools/client/shared/widgets/tooltip/Tooltip.js
@@ -29,16 +29,75 @@ const POPUP_EVENTS = ["shown", "hidden",
  * attaching some content in it, or using one of the ready-made content types.
  *
  * A convenient `startTogglingOnHover` method may avoid having to register event
  * handlers yourself if the tooltip has to be shown when hovering over a
  * specific element or group of elements (which is usually the most common case)
  */
 
 /**
+ * Container used for dealing with optional parameters.
+ *
+ * @param {Object} defaults
+ *        An object with all default options {p1: v1, p2: v2, ...}
+ * @param {Object} options
+ *        The actual values.
+ */
+function OptionsStore(defaults, options) {
+  this.defaults = defaults || {};
+  this.options = options || {};
+}
+
+OptionsStore.prototype = {
+  /**
+   * Get the value for a given option name.
+   * @return {Object} Returns the value for that option, coming either for the
+   *         actual values that have been set in the constructor, or from the
+   *         defaults if that options was not specified.
+   */
+  get: function (name) {
+    if (typeof this.options[name] !== "undefined") {
+      return this.options[name];
+    }
+    return this.defaults[name];
+  }
+};
+
+/**
+ * The low level structure of a tooltip is a XUL element (a <panel>).
+ */
+var PanelFactory = {
+  /**
+   * Get a new XUL panel instance.
+   * @param {XULDocument} doc
+   *        The XUL document to put that panel into
+   * @param {OptionsStore} options
+   *        An options store to get some configuration from
+   */
+  get: function (doc, options) {
+    // Create the tooltip
+    let panel = doc.createElement("panel");
+    panel.setAttribute("hidden", true);
+    panel.setAttribute("ignorekeys", true);
+    panel.setAttribute("animate", false);
+
+    panel.setAttribute("consumeoutsideclicks",
+                       options.get("consumeOutsideClick"));
+    panel.setAttribute("noautofocus", options.get("noAutoFocus"));
+    panel.setAttribute("type", "arrow");
+    panel.setAttribute("level", "top");
+
+    panel.setAttribute("class", "devtools-tooltip theme-tooltip-panel");
+    doc.querySelector("window").appendChild(panel);
+
+    return panel;
+  }
+};
+
+/**
  * Tooltip class.
  *
  * Basic usage:
  *   let t = new Tooltip(xulDoc);
  *   t.content = someXulContent;
  *   t.show();
  *   t.hide();
  *   t.destroy();
@@ -82,31 +141,27 @@ const POPUP_EVENTS = ["shown", "hidden",
  *
  * Fires these events:
  * - showing : just before the tooltip shows
  * - shown : when the tooltip is shown
  * - hiding : just before the tooltip closes
  * - hidden : when the tooltip gets hidden
  * - keypress : when any key gets pressed, with keyCode
  */
-function Tooltip(doc, {
-  consumeOutsideClick = false,
-  closeOnKeys = [ESCAPE_KEYCODE],
-  noAutoFocus = true,
-  closeOnEvents = [],
-  } = {}) {
+function Tooltip(doc, options) {
   EventEmitter.decorate(this);
 
   this.doc = doc;
-  this.consumeOutsideClick = consumeOutsideClick;
-  this.closeOnKeys = closeOnKeys;
-  this.noAutoFocus = noAutoFocus;
-  this.closeOnEvents = closeOnEvents;
-
-  this.panel = this._createPanel();
+  this.options = new OptionsStore({
+    consumeOutsideClick: false,
+    closeOnKeys: [ESCAPE_KEYCODE],
+    noAutoFocus: true,
+    closeOnEvents: []
+  }, options);
+  this.panel = PanelFactory.get(doc, this.options);
 
   // Create tooltip toggle helper and decorate the Tooltip instance with
   // shortcut methods.
   this._toggle = new TooltipToggle(this);
   this.startTogglingOnHover = this._toggle.start.bind(this._toggle);
   this.stopTogglingOnHover = this._toggle.stop.bind(this._toggle);
 
   // Emit show/hide events when the panel does.
@@ -125,27 +180,28 @@ function Tooltip(doc, {
   // Listen to keypress events to close the tooltip if configured to do so
   let win = this.doc.querySelector("window");
   this._onKeyPress = event => {
     if (this.panel.hidden) {
       return;
     }
 
     this.emit("keypress", event.keyCode);
-    if (this.closeOnKeys.indexOf(event.keyCode) !== -1 &&
+    if (this.options.get("closeOnKeys").indexOf(event.keyCode) !== -1 &&
         this.isShown()) {
       event.stopPropagation();
       this.hide();
     }
   };
   win.addEventListener("keypress", this._onKeyPress, false);
 
   // Listen to custom emitters' events to close the tooltip
   this.hide = this.hide.bind(this);
-  for (let {emitter, event, useCapture} of this.closeOnEvents) {
+  let closeOnEvents = this.options.get("closeOnEvents");
+  for (let {emitter, event, useCapture} of closeOnEvents) {
     for (let add of ["addEventListener", "on"]) {
       if (add in emitter) {
         emitter[add](event, this.hide, useCapture);
         break;
       }
     }
   }
 }
@@ -230,17 +286,18 @@ Tooltip.prototype = {
     for (let eventName of POPUP_EVENTS) {
       this.panel.removeEventListener("popup" + eventName,
         this["_onPopup" + eventName], false);
     }
 
     let win = this.doc.querySelector("window");
     win.removeEventListener("keypress", this._onKeyPress, false);
 
-    for (let {emitter, event, useCapture} of this.closeOnEvents) {
+    let closeOnEvents = this.options.get("closeOnEvents");
+    for (let {emitter, event, useCapture} of closeOnEvents) {
       for (let remove of ["removeEventListener", "off"]) {
         if (remove in emitter) {
           emitter[remove](event, this.hide, useCapture);
           break;
         }
       }
     }
 
@@ -378,33 +435,12 @@ Tooltip.prototype = {
 
     // load the document from url into the iframe
     iframe.setAttribute("src", url);
 
     // Put the iframe in the tooltip
     this.content = iframe;
 
     return def.promise;
-  },
-
-  /**
-   * Create the tooltip panel
-   */
-  _createPanel() {
-    let panel = this.doc.createElement("panel");
-    panel.setAttribute("hidden", true);
-    panel.setAttribute("ignorekeys", true);
-    panel.setAttribute("animate", false);
-
-    panel.setAttribute("consumeoutsideclicks",
-                       this.consumeOutsideClick);
-    panel.setAttribute("noautofocus", this.noAutoFocus);
-    panel.setAttribute("type", "arrow");
-    panel.setAttribute("level", "top");
-
-    panel.setAttribute("class", "devtools-tooltip theme-tooltip-panel");
-    this.doc.querySelector("window").appendChild(panel);
-
-    return panel;
   }
 };
 
 module.exports = Tooltip;
--- a/devtools/client/webconsole/jsterm.js
+++ b/devtools/client/webconsole/jsterm.js
@@ -247,21 +247,23 @@ JSTerm.prototype = {
       onClick: this.acceptProposedCompletion.bind(this),
       listId: "webConsole_autocompletePopupListBox",
       position: "top",
       theme: "auto",
       autoSelect: true
     };
 
     let doc = this.hud.document;
+
     let toolbox = gDevTools.getToolbox(this.hud.owner.target);
-    let tooltipDoc = toolbox ? toolbox.doc : doc;
-    // The popup will be attached to the toolbox document or HUD document in the case
-    // such as the browser console which doesn't have a toolbox.
-    this.autocompletePopup = new AutocompletePopup(tooltipDoc, autocompleteOptions);
+    if (!toolbox) {
+      // In some cases (e.g. Browser Console), there is no toolbox.
+      toolbox = { doc };
+    }
+    this.autocompletePopup = new AutocompletePopup(toolbox, autocompleteOptions);
 
     let inputContainer = doc.querySelector(".jsterm-input-container");
     this.completeNode = doc.querySelector(".jsterm-complete-node");
     this.inputNode = doc.querySelector(".jsterm-input-node");
 
     if (this.hud.isBrowserConsole &&
         !Services.prefs.getBoolPref("devtools.chrome.enabled")) {
       inputContainer.style.display = "none";