Bug 1341304 - Emit "selection-changed" event on the DevTools toolbox object.
MozReview-Commit-ID: G2jRxqDH9wx
--- 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);
}