Bug 1341304 - Emit "selection-changed" event on the DevTools toolbox object. draft
authorLuca Greco <lgreco@mozilla.com>
Thu, 06 Jul 2017 19:47:21 +0200
changeset 609730 bfa143d099fde404ba0f3c11d5c14bee6f294665
parent 609596 aff336ac161daa3ea350e59a288963edbd58ed39
child 609731 fbe427893523f6184de1c890a999bb55fe848a3a
push id68668
push userluca.greco@alcacoop.it
push dateMon, 17 Jul 2017 11:47:51 +0000
bugs1341304
milestone56.0a1
Bug 1341304 - Emit "selection-changed" event on the DevTools toolbox object. MozReview-Commit-ID: G2jRxqDH9wx
devtools/client/framework/test/browser.ini
devtools/client/framework/test/browser_toolbox_selectionchanged_event.js
devtools/client/framework/toolbox.js
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -86,16 +86,17 @@ skip-if = true # Bug 1177463 - Temporari
 # skip-if = os == "win"
 [browser_toolbox_races.js]
 [browser_toolbox_ready.js]
 [browser_toolbox_remoteness_change.js]
 run-if = e10s
 [browser_toolbox_select_event.js]
 skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
 [browser_toolbox_selected_tool_unavailable.js]
+[browser_toolbox_selectionchanged_event.js]
 [browser_toolbox_sidebar.js]
 [browser_toolbox_sidebar_events.js]
 [browser_toolbox_sidebar_existing_tabs.js]
 [browser_toolbox_sidebar_overflow_menu.js]
 [browser_toolbox_split_console.js]
 [browser_toolbox_target.js]
 [browser_toolbox_tabsswitch_shortcuts.js]
 [browser_toolbox_textbox_context_menu.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/browser_toolbox_selectionchanged_event.js
@@ -0,0 +1,41 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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";
+
+const PAGE_URL = "data:text/html;charset=utf-8,<body><div></div></body>";
+
+add_task(function* () {
+  let tab = yield addTab(PAGE_URL);
+  let toolbox = yield openToolboxForTab(tab, "inspector", "bottom");
+  let inspector = toolbox.getCurrentPanel();
+
+  let root = yield inspector.walker.getRootNode();
+  let body = yield inspector.walker.querySelector(root, "body");
+  let node = yield inspector.walker.querySelector(root, "div");
+
+  is(inspector.selection.nodeFront, body, "Body is selected by default");
+
+  // Listen to selection changed
+  let onSelectionChanged = toolbox.once("selection-changed");
+
+  info("Select the div and wait for the selection-changed event to be fired.");
+  inspector.selection.setNodeFront(node, "browser-context-menu");
+
+  yield onSelectionChanged;
+
+  is(inspector.selection.nodeFront, node, "Div is now selected");
+
+  // Listen to cleared selection changed
+  let onClearSelectionChanged = toolbox.once("selection-changed");
+
+  info("Clear the selection and wait for the selection-changed event to be fired.");
+  inspector.selection.setNodeFront(undefined, "browser-context-menu");
+
+  yield onClearSelectionChanged;
+
+  is(inspector.selection.nodeFront, undefined, "The selection is undefined as expected");
+});
+
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -132,16 +132,17 @@ function Toolbox(target, selectedTool, h
   this._toggleMinimizeMode = this._toggleMinimizeMode.bind(this);
   this._onToolbarFocus = this._onToolbarFocus.bind(this);
   this._onToolbarArrowKeypress = this._onToolbarArrowKeypress.bind(this);
   this._onPickerClick = this._onPickerClick.bind(this);
   this._onPickerKeypress = this._onPickerKeypress.bind(this);
   this._onPickerStarted = this._onPickerStarted.bind(this);
   this._onPickerStopped = this._onPickerStopped.bind(this);
   this._onInspectObject = this._onInspectObject.bind(this);
+  this._onNewSelectedNodeFront = this._onNewSelectedNodeFront.bind(this);
   this.selectTool = this.selectTool.bind(this);
 
   this._target.on("close", this.destroy);
 
   if (!selectedTool) {
     selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
   }
   this._defaultToolId = selectedTool;
@@ -2214,29 +2215,37 @@ Toolbox.prototype = {
   initInspector: function () {
     if (!this._initInspector) {
       this._initInspector = Task.spawn(function* () {
         this._inspector = InspectorFront(this._target.client, this._target.form);
         let pref = "devtools.inspector.showAllAnonymousContent";
         let showAllAnonymousContent = Services.prefs.getBoolPref(pref);
         this._walker = yield this._inspector.getWalker({ showAllAnonymousContent });
         this._selection = new Selection(this._walker);
+        this._selection.on("new-node-front", this._onNewSelectedNodeFront);
 
         if (this.highlighterUtils.isRemoteHighlightable()) {
           this.walker.on("highlighter-ready", this._highlighterReady);
           this.walker.on("highlighter-hide", this._highlighterHidden);
 
           let autohide = !flags.testing;
           this._highlighter = yield this._inspector.getHighlighter(autohide);
         }
       }.bind(this));
     }
     return this._initInspector;
   },
 
+  _onNewSelectedNodeFront: function (evt) {
+    // Emit a "selection-changed" event when the toolbox.selection has been set
+    // to a new node (or cleared). Currently used in the WebExtensions APIs (to
+    // provide the `devtools.panels.elements.onSelectionChanged` event).
+    this.emit("selection-changed");
+  },
+
   _onInspectObject: function (evt, packet) {
     this.inspectObjectActor(packet.objectActor, packet.inspectFromAnnotation);
   },
 
   inspectObjectActor: async function (objectActor, inspectFromAnnotation) {
     if (objectActor.preview &&
         objectActor.preview.nodeType === domNodeConstants.ELEMENT_NODE) {
       // Open the inspector and select the DOM Element.
@@ -2298,16 +2307,17 @@ Toolbox.prototype = {
         // proceed with the rest of destruction if it fails.
         // FF42+ now does the cleanup from the actor.
         if (!this.highlighter.traits.autoHideOnDestroy) {
           this.highlighterUtils.unhighlight();
         }
         yield this._highlighter.destroy();
       }
       if (this._selection) {
+        this._selection.off("new-node-front", this._onNewSelectedNodeFront);
         this._selection.destroy();
       }
 
       if (this.walker) {
         this.walker.off("highlighter-ready", this._highlighterReady);
         this.walker.off("highlighter-hide", this._highlighterHidden);
       }