diff --git a/devtools/client/accessibility/accessibility-panel.js b/devtools/client/accessibility/accessibility-panel.js index e38d97141976..fb7da3956d04 100644 --- a/devtools/client/accessibility/accessibility-panel.js +++ b/devtools/client/accessibility/accessibility-panel.js @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -const { AccessibilityFront } = require("devtools/shared/fronts/accessibility"); const EventEmitter = require("devtools/shared/event-emitter"); const Telemetry = require("devtools/client/shared/telemetry"); @@ -28,9 +27,10 @@ const EVENTS = { * render Accessibility Tree of the current debugger target and the sidebar that * displays current relevant accessible details. */ -function AccessibilityPanel(iframeWindow, toolbox) { +function AccessibilityPanel(iframeWindow, toolbox, startup) { this.panelWin = iframeWindow; this._toolbox = toolbox; + this.startup = startup; this.onTabNavigated = this.onTabNavigated.bind(this); this.onPanelVisibilityChange = this.onPanelVisibilityChange.bind(this); @@ -40,7 +40,6 @@ function AccessibilityPanel(iframeWindow, toolbox) { this.onAccessibilityInspectorUpdated.bind(this); this.updateA11YServiceDurationTimer = this.updateA11YServiceDurationTimer.bind(this); this.updatePickerButton = this.updatePickerButton.bind(this); - this.updateToolboxButtons = this.updateToolboxButtons.bind(this); EventEmitter.decorate(this); } @@ -82,19 +81,14 @@ AccessibilityPanel.prototype = { this.panelWin.gToolbox = this._toolbox; await this._toolbox.initInspector(); - this._front = new AccessibilityFront(this.target.client, - this.target.form); - this._walker = await this._front.getWalker(); - - this._isOldVersion = !(await this.target.actorHasMethod("accessibility", "enable")); - if (!this._isOldVersion) { - await this._front.bootstrap(); + await this.startup.initAccessibility(); + if (this.supportsLatestAccessibility) { this.picker = new Picker(this); } this.updateA11YServiceDurationTimer(); - this._front.on("init", this.updateA11YServiceDurationTimer); - this._front.on("shutdown", this.updateA11YServiceDurationTimer); + this.front.on("init", this.updateA11YServiceDurationTimer); + this.front.on("shutdown", this.updateA11YServiceDurationTimer); this.isReady = true; this.emit("ready"); @@ -130,12 +124,7 @@ AccessibilityPanel.prototype = { refresh() { this.cancelPicker(); - if (this.isVisible) { - this._front.on("init", this.updateToolboxButtons); - this._front.on("shutdown", this.updateToolboxButtons); - } else { - this._front.off("init", this.updateToolboxButtons); - this._front.off("shutdown", this.updateToolboxButtons); + if (!this.isVisible) { // Do not refresh if the panel isn't visible. return; } @@ -146,11 +135,13 @@ AccessibilityPanel.prototype = { } // Alright reset the flag we are about to refresh the panel. this.shouldRefresh = false; - this.postContentMessage("initialize", this._front, this._walker, this._isOldVersion); + this.postContentMessage("initialize", this.front, + this.walker, + this.supportsLatestAccessibility); }, updateA11YServiceDurationTimer() { - if (this._front.enabled) { + if (this.front.enabled) { this._telemetry.start(A11Y_SERVICE_DURATION, this, true); } else { this._telemetry.finish(A11Y_SERVICE_DURATION, this, true); @@ -158,7 +149,7 @@ AccessibilityPanel.prototype = { }, selectAccessible(accessibleFront) { - this.postContentMessage("selectAccessible", this._walker, accessibleFront); + this.postContentMessage("selectAccessible", this.walker, accessibleFront); }, selectAccessibleForNode(nodeFront, reason) { @@ -167,11 +158,11 @@ AccessibilityPanel.prototype = { "devtools.accessibility.select_accessible_for_node", reason, 1); } - this.postContentMessage("selectNodeAccessible", this._walker, nodeFront); + this.postContentMessage("selectNodeAccessible", this.walker, nodeFront); }, highlightAccessible(accessibleFront) { - this.postContentMessage("highlightAccessible", this._walker, accessibleFront); + this.postContentMessage("highlightAccessible", this.walker, accessibleFront); }, postContentMessage(type, ...args) { @@ -184,10 +175,6 @@ AccessibilityPanel.prototype = { this.panelWin.dispatchEvent(event); }, - updateToolboxButtons() { - this._toolbox.updatePickerButton(); - }, - updatePickerButton() { this.picker && this.picker.updateButton(); }, @@ -204,8 +191,16 @@ AccessibilityPanel.prototype = { this.picker && this.picker.stop(); }, + get front() { + return this.startup.accessibility; + }, + get walker() { - return this._walker; + return this.startup.walker; + }, + + get supportsLatestAccessibility() { + return this.startup._supportsLatestAccessibility; }, /** @@ -241,13 +236,11 @@ AccessibilityPanel.prototype = { this.picker.release(); this.picker = null; - if (this._front) { - this._front.off("init", this.updateA11YServiceDurationTimer); - this._front.off("shutdown", this.updateA11YServiceDurationTimer); - await this._front.destroy(); + if (this.front) { + this.front.off("init", this.updateA11YServiceDurationTimer); + this.front.off("shutdown", this.updateA11YServiceDurationTimer); } - this._front = null; this._telemetry = null; this.panelWin.gToolbox = null; this.panelWin.gTelemetry = null; diff --git a/devtools/client/accessibility/accessibility-startup.js b/devtools/client/accessibility/accessibility-startup.js new file mode 100644 index 000000000000..94f126bb842c --- /dev/null +++ b/devtools/client/accessibility/accessibility-startup.js @@ -0,0 +1,138 @@ +/* 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"; + +const { AccessibilityFront } = require("devtools/shared/fronts/accessibility"); + +/** + * Component responsible for all accessibility panel startup steps before the panel is + * actually opened. + */ +class AccessibilityStartup { + constructor(toolbox) { + this.toolbox = toolbox; + + this._updateAccessibilityState = this._updateAccessibilityState.bind(this); + + // Creates accessibility front. + this.initAccessibility(); + } + + get target() { + return this.toolbox.target; + } + + /** + * Get the accessibility front for the toolbox. + */ + get accessibility() { + return this._accessibility; + } + + get walker() { + return this._walker; + } + + /** + * Fully initialize accessibility front. Also add listeners for accessibility + * service lifecycle events that affect picker state and the state of the tool tab + * highlight. + * @return {Promise} + * A promise for when accessibility front is fully initialized. + */ + initAccessibility() { + if (!this._initAccessibility) { + this._initAccessibility = (async function() { + this._accessibility = new AccessibilityFront(this.target.client, + this.target.form); + // We must call a method on an accessibility front here (such as getWalker), in + // oreder to be able to check actor's backward compatibility via actorHasMethod. + // See targe.js@getActorDescription for more information. + this._walker = await this._accessibility.getWalker(); + // Only works with FF61+ targets + this._supportsLatestAccessibility = + await this.target.actorHasMethod("accessibility", "enable"); + + if (this._supportsLatestAccessibility) { + await this._accessibility.bootstrap(); + } + + this._updateAccessibilityState(); + this._accessibility.on("init", this._updateAccessibilityState); + this._accessibility.on("shutdown", this._updateAccessibilityState); + }.bind(this))(); + } + + return this._initAccessibility; + } + + /** + * Destroy accessibility front. Also remove listeners for accessibility service + * lifecycle events. + * @return {Promise} + * A promise for when accessibility front is fully destroyed. + */ + destroyAccessibility() { + if (this._destroyingAccessibility) { + return this._destroyingAccessibility; + } + + this._destroyingAccessibility = (async function() { + if (!this._accessibility) { + return; + } + + // Ensure that the accessibility isn't still being initiated, otherwise race + // conditions in the initialization process can throw errors. + await this._initAccessibility; + + this._accessibility.off("init", this._updateAccessibilityState); + this._accessibility.off("shutdown", this._updateAccessibilityState); + + await this._walker.destroy(); + await this._accessibility.destroy(); + this._accessibility = null; + this._walker = null; + }.bind(this))(); + return this._destroyingAccessibility; + } + + /** + * Update states of the accessibility picker and accessibility tab highlight. + * @return {[type]} [description] + */ + _updateAccessibilityState() { + this._updateAccessibilityToolHighlight(); + this._updatePickerButton(); + } + + /** + * Update picker button state and ensure toolbar is re-rendered correctly. + */ + _updatePickerButton() { + this.toolbox.updatePickerButton(); + // Calling setToolboxButtons to make sure toolbar is re-rendered correctly. + this.toolbox.component.setToolboxButtons(this.toolbox.toolbarButtons); + } + + /** + * Set the state of the accessibility tab highlight depending on whether the + * accessibility service is initialized or shutdown. + */ + _updateAccessibilityToolHighlight() { + if (this._accessibility.enabled) { + this.toolbox.highlightTool("accessibility"); + } else { + this.toolbox.unhighlightTool("accessibility"); + } + } + + async destroy() { + await this.destroyAccessibility(); + this.toolbox = null; + } +} + +exports.AccessibilityStartup = AccessibilityStartup; diff --git a/devtools/client/accessibility/accessibility-view.js b/devtools/client/accessibility/accessibility-view.js index 811c1f1509fb..1eb28452f549 100644 --- a/devtools/client/accessibility/accessibility-view.js +++ b/devtools/client/accessibility/accessibility-view.js @@ -48,12 +48,12 @@ AccessibilityView.prototype = { * walker and enable/disable accessibility * services. */ - async initialize(accessibility, walker, isOldVersion) { + async initialize(accessibility, walker, supportsLatestAccessibility) { // Make sure state is reset every time accessibility panel is initialized. await this.store.dispatch(reset(accessibility)); const container = document.getElementById("content"); - if (isOldVersion) { + if (!supportsLatestAccessibility) { ReactDOM.render(OldVersionDescription(), container); return; } diff --git a/devtools/client/accessibility/moz.build b/devtools/client/accessibility/moz.build index 0c7b1b162914..cefe61cbcba2 100644 --- a/devtools/client/accessibility/moz.build +++ b/devtools/client/accessibility/moz.build @@ -14,6 +14,7 @@ DIRS += [ DevToolsModules( 'accessibility-panel.js', + 'accessibility-startup.js', 'accessibility-view.js', 'accessibility.css', 'constants.js', diff --git a/devtools/client/accessibility/picker.js b/devtools/client/accessibility/picker.js index dfadc6ff6b38..291560e4ce8f 100644 --- a/devtools/client/accessibility/picker.js +++ b/devtools/client/accessibility/picker.js @@ -23,7 +23,7 @@ class Picker { } get walker() { - return this._panel._walker; + return this._panel.walker; } get pickerButton() { @@ -71,8 +71,8 @@ class Picker { updateButton() { this.pickerButton.description = this.getStr("accessibility.pick"); this.pickerButton.className = "accessibility"; - this.pickerButton.disabled = !this._panel._front.enabled; - if (!this._panel._front.enabled && this.isPicking) { + this.pickerButton.disabled = !this._panel.front.enabled; + if (!this._panel.front.enabled && this.isPicking) { this.cancel(); } } diff --git a/devtools/client/accessibility/reducers/ui.js b/devtools/client/accessibility/reducers/ui.js index 8e311d52d253..5b0e8f10f885 100644 --- a/devtools/client/accessibility/reducers/ui.js +++ b/devtools/client/accessibility/reducers/ui.js @@ -3,8 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -/* global gToolbox */ - const { ENABLE, DISABLE, @@ -136,7 +134,6 @@ function onCanBeEnabledChange(state, { canBeEnabled }) { */ function onReset(state, { accessibility }) { const { enabled, canBeDisabled, canBeEnabled } = accessibility; - toggleHighlightTool(enabled); return Object.assign({}, state, { enabled, canBeDisabled, canBeEnabled }); } @@ -153,16 +150,7 @@ function onToggle(state, { error }, enabled) { return state; } - toggleHighlightTool(enabled); return Object.assign({}, state, { enabled }); } -function toggleHighlightTool(enabled) { - if (enabled) { - gToolbox.highlightTool("accessibility"); - } else { - gToolbox.unhighlightTool("accessibility"); - } -} - exports.ui = ui; diff --git a/devtools/client/accessibility/test/browser/browser.ini b/devtools/client/accessibility/test/browser/browser.ini index af6529b5acf6..2b7459fe3115 100644 --- a/devtools/client/accessibility/test/browser/browser.ini +++ b/devtools/client/accessibility/test/browser/browser.ini @@ -11,6 +11,8 @@ support-files = [browser_accessibility_context_menu_browser.js] [browser_accessibility_context_menu_inspector.js] [browser_accessibility_mutations.js] +[browser_accessibility_panel_highlighter.js] +[browser_accessibility_panel_highlighter_multi_tab.js] [browser_accessibility_reload.js] [browser_accessibility_sidebar.js] [browser_accessibility_tree.js] diff --git a/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter.js b/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter.js new file mode 100644 index 000000000000..fd1a56340e49 --- /dev/null +++ b/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_URI = "

header

paragraph

"; + +add_task(async function tabNotHighlighted() { + await addTab(buildURL(TEST_URI)); + const { toolbox } = await openInspector(); + const isHighlighted = await toolbox.isToolHighlighted("accessibility"); + + ok(!isHighlighted, "When accessibility service is not running, accessibility panel " + + "should not be highlighted when toolbox opens"); + + gBrowser.removeCurrentTab(); +}); + +add_task(async function tabHighlighted() { + let a11yService = await initA11y(); + ok(a11yService, "Accessibility service was started"); + await addTab(buildURL(TEST_URI)); + const { toolbox } = await openInspector(); + const isHighlighted = await toolbox.isToolHighlighted("accessibility"); + + ok(isHighlighted, "When accessibility service is running, accessibility panel should" + + "be highlighted when toolbox opens"); + + a11yService = null; + gBrowser.removeCurrentTab(); +}); diff --git a/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter_multi_tab.js b/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter_multi_tab.js new file mode 100644 index 000000000000..f27339c9258f --- /dev/null +++ b/devtools/client/accessibility/test/browser/browser_accessibility_panel_highlighter_multi_tab.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_URI = "

header

paragraph

"; + +add_task(async function() { + const { toolbox: toolbox1 } = await addTestTab(buildURL(TEST_URI)); + const { toolbox: toolbox2 } = await addTestTab(buildURL(TEST_URI)); + const options = await openOptions(toolbox2); + + info("Check that initially both accessibility panels are highlighted."); + await checkHighlighted(toolbox1, true); + await checkHighlighted(toolbox2, true); + + info("Toggle accessibility panel off an on."); + await toggleAccessibility(options); + await toggleAccessibility(options); + + await checkHighlighted(toolbox1, true); + await checkHighlighted(toolbox2, true); + + info("Toggle accessibility panel off an on again."); + await toggleAccessibility(options); + await toggleAccessibility(options); + + const panel = await toolbox2.selectTool("accessibility"); + await disableAccessibilityInspector( + { panel, win: panel.panelWin, doc: panel.panelWin.document }); + + await checkHighlighted(toolbox1, false); + await checkHighlighted(toolbox2, false); +}); + +async function checkHighlighted(toolbox, expected) { + await BrowserTestUtils.waitForCondition(async function() { + const isHighlighted = await toolbox.isToolHighlighted("accessibility"); + return isHighlighted === expected; + }); +} + +async function openOptions(toolbox) { + const panel = await toolbox.selectTool("options"); + return { + panelWin: panel.panelWin, + // This is a getter becuse toolbox tools list gets re-setup every time there + // is a tool-registered or tool-undregistered event. + get checkbox() { + return panel.panelDoc.getElementById("accessibility"); + } + }; +} + +async function toggleAccessibility({ panelWin, checkbox }) { + const prevChecked = checkbox.checked; + const onToggleTool = gDevTools.once( + `tool-${prevChecked ? "unregistered" : "registered"}`); + EventUtils.sendMouseEvent({ type: "click" }, checkbox, panelWin); + const id = await onToggleTool; + is(id, "accessibility", "Correct event was fired"); +} diff --git a/devtools/client/accessibility/test/browser/head.js b/devtools/client/accessibility/test/browser/head.js index 26a0f7a06a49..d160843cf4fc 100644 --- a/devtools/client/accessibility/test/browser/head.js +++ b/devtools/client/accessibility/test/browser/head.js @@ -30,6 +30,30 @@ const { ORDERED_PROPS } = require("devtools/client/accessibility/constants"); // Enable the Accessibility panel Services.prefs.setBoolPref("devtools.accessibility.enabled", true); +/** + * Enable accessibility service and wait for a11y init event. + * @return {Object} instance of accessibility service. + */ +async function initA11y() { + if (Services.appinfo.accessibilityEnabled) { + return Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService); + } + + const initPromise = new Promise(resolve => { + const observe = () => { + Services.obs.removeObserver(observe, "a11y-init-or-shutdown"); + resolve(); + }; + Services.obs.addObserver(observe, "a11y-init-or-shutdown"); + }); + + const a11yService = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService); + await initPromise; + return a11yService; +} + /** * Wait for accessibility service to shut down. We consider it shut down when * an "a11y-init-or-shutdown" event is received with a value of "0". @@ -83,8 +107,11 @@ async function addTestTab(url) { const doc = win.document; const store = win.view.store; - EventUtils.sendMouseEvent({ type: "click" }, - doc.getElementById("accessibility-enable-button"), win); + const enableButton = doc.getElementById("accessibility-enable-button"); + // If enable button is not found, asume the tool is already enabled. + if (enableButton) { + EventUtils.sendMouseEvent({ type: "click" }, enableButton, win); + } await waitUntilState(store, state => state.accessibles.size === 1 && state.details.accessible && @@ -113,9 +140,10 @@ async function disableAccessibilityInspector(env) { const { doc, win, panel } = env; // Disable accessibility service through the panel and wait for the shutdown // event. - const shutdown = panel._front.once("shutdown"); - EventUtils.sendMouseEvent({ type: "click" }, - doc.getElementById("accessibility-disable-button"), win); + const shutdown = panel.front.once("shutdown"); + const disableButton = await BrowserTestUtils.waitForCondition(() => + doc.getElementById("accessibility-disable-button"), "Wait for the disable button."); + EventUtils.sendMouseEvent({ type: "click" }, disableButton, win); await shutdown; } diff --git a/devtools/client/definitions.js b/devtools/client/definitions.js index 83b644f6fa97..75dd62686eb6 100644 --- a/devtools/client/definitions.js +++ b/devtools/client/definitions.js @@ -28,6 +28,7 @@ loader.lazyGetter(this, "AccessibilityPanel", () => require("devtools/client/acc loader.lazyGetter(this, "ApplicationPanel", () => require("devtools/client/application/panel").ApplicationPanel); // Other dependencies +loader.lazyRequireGetter(this, "AccessibilityStartup", "devtools/client/accessibility/accessibility-startup", true); loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true); loader.lazyRequireGetter(this, "CommandState", "devtools/shared/gcli/command-state", true); loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true); @@ -452,7 +453,12 @@ Tools.accessibility = { }, build(iframeWindow, toolbox) { - return new AccessibilityPanel(iframeWindow, toolbox); + const startup = toolbox.getToolStartup("accessibility"); + return new AccessibilityPanel(iframeWindow, toolbox, startup); + }, + + buildToolStartup(toolbox) { + return new AccessibilityStartup(toolbox); } }; diff --git a/devtools/client/framework/components/ToolboxController.js b/devtools/client/framework/components/ToolboxController.js index 9fb1485ae79c..73e882d53ff7 100644 --- a/devtools/client/framework/components/ToolboxController.js +++ b/devtools/client/framework/components/ToolboxController.js @@ -118,6 +118,10 @@ class ToolboxController extends Component { this.setState({ canRender: true }, this.updateButtonIds); } + isToolHighlighted(toolID) { + return this.state.highlightedTools.has(toolID); + } + highlightTool(highlightedTool) { const { highlightedTools } = this.state; highlightedTools.add(highlightedTool); diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js index e4564f8604bd..11c713039889 100644 --- a/devtools/client/framework/toolbox.js +++ b/devtools/client/framework/toolbox.js @@ -112,6 +112,8 @@ function Toolbox(target, selectedTool, hostType, contentWindow, frameId) { this._webExtensions = new Map(); this._toolPanels = new Map(); + // Map of tool startup components for given tool id. + this._toolStartups = new Map(); this._inspectorExtensionSidebars = new Map(); this._initInspector = null; @@ -1438,6 +1440,10 @@ Toolbox.prototype = { deck.appendChild(panel); + if (toolDefinition.buildToolStartup && !this._toolStartups.has(id)) { + this._toolStartups.set(id, toolDefinition.buildToolStartup(this)); + } + this._addKeysToWindow(); }, @@ -2080,6 +2086,19 @@ Toolbox.prototype = { return this.selectTool(definition.id, "select_prev_key"); }, + /** + * Check if the tool's tab is highlighted. + * + * @param {string} id + * The id of the tool to be checked + */ + async isToolHighlighted(id) { + if (!this.component) { + await this.isOpen; + } + return this.component.isToolHighlighted(id); + }, + /** * Highlights the tool's tab if it is not the currently selected tool. * @@ -2589,6 +2608,25 @@ Toolbox.prototype = { } }, + /** + * Get a startup component for a given tool. + * @param {string} toolId + * Id of the tool to get the startup component for. + */ + getToolStartup: function(toolId) { + return this._toolStartups.get(toolId); + }, + + _unloadToolStartup: async function(toolId) { + const startup = this.getToolStartup(toolId); + if (!startup) { + return; + } + + this._toolStartups.delete(toolId); + await startup.destroy(); + }, + /** * Handler for the tool-registered event. * @param {string} toolId @@ -2626,6 +2664,8 @@ Toolbox.prototype = { */ _toolUnregistered: function(toolId) { this.unloadTool(toolId); + this._unloadToolStartup(toolId); + // Emit the event so tools can listen to it from the toolbox level // instead of gDevTools this.emit("tool-unregistered", toolId); @@ -2838,6 +2878,10 @@ Toolbox.prototype = { } } + for (const id of this._toolStartups.keys()) { + outstanding.push(this._unloadToolStartup(id)); + } + this.browserRequire = null; // Now that we are closing the toolbox we can re-enable the cache settings diff --git a/devtools/client/inspector/test/head.js b/devtools/client/inspector/test/head.js index 0936e3c370e0..fc7e2d344d65 100644 --- a/devtools/client/inspector/test/head.js +++ b/devtools/client/inspector/test/head.js @@ -4,7 +4,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* eslint no-unused-vars: [2, {"vars": "local"}] */ /* import-globals-from ../../shared/test/shared-head.js */ -/* import-globals-from ../../shared/test/test-actor-registry.js */ /* import-globals-from ../../inspector/test/shared-head.js */ "use strict"; @@ -18,11 +17,6 @@ Services.scriptloader.loadSubScript( // Services.prefs.clearUserPref("devtools.debugger.log"); // }); -// Import helpers registering the test-actor in remote targets -Services.scriptloader.loadSubScript( - "chrome://mochitests/content/browser/devtools/client/shared/test/test-actor-registry.js", - this); - // Import helpers for the inspector that are also shared with others Services.scriptloader.loadSubScript( "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js", diff --git a/devtools/client/inspector/test/shared-head.js b/devtools/client/inspector/test/shared-head.js index 993a6b976580..9372ecbe4e2c 100644 --- a/devtools/client/inspector/test/shared-head.js +++ b/devtools/client/inspector/test/shared-head.js @@ -7,6 +7,12 @@ /* eslint no-unused-vars: [2, {"vars": "local"}] */ /* globals registerTestActor, getTestActor, openToolboxForTab, gBrowser */ /* import-globals-from ../../shared/test/shared-head.js */ +/* import-globals-from ../../shared/test/test-actor-registry.js */ + +// Import helpers registering the test-actor in remote targets +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/shared/test/test-actor-registry.js", + this); var {getInplaceEditorForSpan: inplaceEditor} = require("devtools/client/shared/inplace-editor");