зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1356244 - devtools-addon: create low-level DevTools shim for mozilla-central;r=ochameau
MozReview-Commit-ID: KdfomLHgdLY --HG-- extra : rebase_source : 5fff97798bfe3eeac98c8be12cbcfe6e6177afa8 extra : source : 2d422bec07d3a5bab5d83b4c949f27c6e49be261
This commit is contained in:
Родитель
0ce286101c
Коммит
52acc63ebc
|
@ -622,6 +622,10 @@
|
||||||
@RESPATH@/browser/chrome/webide.manifest
|
@RESPATH@/browser/chrome/webide.manifest
|
||||||
@RESPATH@/browser/@PREF_DIR@/webide-prefs.js
|
@RESPATH@/browser/@PREF_DIR@/webide-prefs.js
|
||||||
|
|
||||||
|
; [DevTools Shim Files]
|
||||||
|
@RESPATH@/browser/chrome/devtools-shim@JAREXT@
|
||||||
|
@RESPATH@/browser/chrome/devtools-shim.manifest
|
||||||
|
|
||||||
; DevTools
|
; DevTools
|
||||||
@RESPATH@/browser/chrome/devtools@JAREXT@
|
@RESPATH@/browser/chrome/devtools@JAREXT@
|
||||||
@RESPATH@/browser/chrome/devtools.manifest
|
@RESPATH@/browser/chrome/devtools.manifest
|
||||||
|
|
|
@ -8,6 +8,7 @@ const {Cu} = require("chrome");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
|
|
||||||
// Load gDevToolsBrowser toolbox lazily as they need gDevTools to be fully initialized
|
// Load gDevToolsBrowser toolbox lazily as they need gDevTools to be fully initialized
|
||||||
|
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
|
||||||
loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
|
loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
|
||||||
loader.lazyRequireGetter(this, "ToolboxHostManager", "devtools/client/framework/toolbox-host-manager", true);
|
loader.lazyRequireGetter(this, "ToolboxHostManager", "devtools/client/framework/toolbox-host-manager", true);
|
||||||
loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
|
loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
|
||||||
|
@ -468,6 +469,18 @@ DevTools.prototype = {
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper on TargetFactory.forTab, constructs a Target for the provided tab.
|
||||||
|
*
|
||||||
|
* @param {XULTab} tab
|
||||||
|
* The tab to use in creating a new target.
|
||||||
|
*
|
||||||
|
* @return {TabTarget} A target object
|
||||||
|
*/
|
||||||
|
getTargetForTab: function (tab) {
|
||||||
|
return TargetFactory.forTab(tab);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either the SDK Loader has been destroyed by the add-on contribution
|
* Either the SDK Loader has been destroyed by the add-on contribution
|
||||||
* workflow, or firefox is shutting down.
|
* workflow, or firefox is shutting down.
|
||||||
|
|
|
@ -15,6 +15,7 @@ if CONFIG['MOZ_DEVTOOLS'] == 'all':
|
||||||
DIRS += [
|
DIRS += [
|
||||||
'server',
|
'server',
|
||||||
'shared',
|
'shared',
|
||||||
|
'shim',
|
||||||
]
|
]
|
||||||
|
|
||||||
# /browser uses DIST_SUBDIR. We opt-in to this treatment when building
|
# /browser uses DIST_SUBDIR. We opt-in to this treatment when building
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/* 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";
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = [
|
||||||
|
"DevToolsShim",
|
||||||
|
];
|
||||||
|
|
||||||
|
function removeItem(array, callback) {
|
||||||
|
let index = array.findIndex(callback);
|
||||||
|
if (index >= 0) {
|
||||||
|
array.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DevToolsShim is a part of the DevTools go faster project, which moves the Firefox
|
||||||
|
* DevTools outside of mozilla-central to an add-on. It aims to bridge the gap for
|
||||||
|
* existing mozilla-central code that still needs to interact with DevTools (such as
|
||||||
|
* web-extensions).
|
||||||
|
*
|
||||||
|
* DevToolsShim is a singleton that provides a set of helpers to interact with DevTools,
|
||||||
|
* that work whether the DevTools addon is installed or not. It can be used to start
|
||||||
|
* listening to events, register tools, themes. As soon as a DevTools addon is installed
|
||||||
|
* the DevToolsShim will forward all the requests received until then to the real DevTools
|
||||||
|
* instance.
|
||||||
|
*
|
||||||
|
* DevToolsShim.isInstalled() can also be used to know if DevTools are currently
|
||||||
|
* installed.
|
||||||
|
*/
|
||||||
|
this.DevToolsShim = {
|
||||||
|
gDevTools: null,
|
||||||
|
listeners: [],
|
||||||
|
tools: [],
|
||||||
|
themes: [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if DevTools are currently installed and available.
|
||||||
|
*
|
||||||
|
* @return {Boolean} true if DevTools are installed.
|
||||||
|
*/
|
||||||
|
isInstalled: function () {
|
||||||
|
return !!this.gDevTools;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an instance of gDevTools. Should be called by DevTools during startup.
|
||||||
|
*
|
||||||
|
* @param {DevTools} a devtools instance (from client/framework/devtools)
|
||||||
|
*/
|
||||||
|
register: function (gDevTools) {
|
||||||
|
this.gDevTools = gDevTools;
|
||||||
|
this._onDevToolsRegistered();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister the current instance of gDevTools. Should be called by DevTools during
|
||||||
|
* shutdown.
|
||||||
|
*/
|
||||||
|
unregister: function () {
|
||||||
|
this.gDevTools = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following methods can be called before DevTools are installed:
|
||||||
|
* - on
|
||||||
|
* - off
|
||||||
|
* - registerTool
|
||||||
|
* - unregisterTool
|
||||||
|
* - registerTheme
|
||||||
|
* - unregisterTheme
|
||||||
|
*
|
||||||
|
* If DevTools are not installed when calling the method, DevToolsShim will call the
|
||||||
|
* appropriate method as soon as a gDevTools instance is registered.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used by browser/components/extensions/ext-devtools.js for the events:
|
||||||
|
* - toolbox-created
|
||||||
|
* - toolbox-destroyed
|
||||||
|
*/
|
||||||
|
on: function (event, listener) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.on(event, listener);
|
||||||
|
} else {
|
||||||
|
this.listeners.push([event, listener]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is currently only used by devtools code, but is kept here for consistency
|
||||||
|
* with on().
|
||||||
|
*/
|
||||||
|
off: function (event, listener) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.off(event, listener);
|
||||||
|
} else {
|
||||||
|
removeItem(this.listeners, ([e, l]) => e === event && l === listener);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
|
||||||
|
* no longer supported.
|
||||||
|
*/
|
||||||
|
registerTool: function (tool) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.registerTool(tool);
|
||||||
|
} else {
|
||||||
|
this.tools.push(tool);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
|
||||||
|
* no longer supported.
|
||||||
|
*/
|
||||||
|
unregisterTool: function (tool) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.unregisterTool(tool);
|
||||||
|
} else {
|
||||||
|
removeItem(this.tools, t => t === tool);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
|
||||||
|
* no longer supported.
|
||||||
|
*/
|
||||||
|
registerTheme: function (theme) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.registerTheme(theme);
|
||||||
|
} else {
|
||||||
|
this.themes.push(theme);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is only used by the addon-sdk and should be removed when Firefox 56 is
|
||||||
|
* no longer supported.
|
||||||
|
*/
|
||||||
|
unregisterTheme: function (theme) {
|
||||||
|
if (this.isInstalled()) {
|
||||||
|
this.gDevTools.unregisterTheme(theme);
|
||||||
|
} else {
|
||||||
|
removeItem(this.themes, t => t === theme);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDevToolsRegistered: function () {
|
||||||
|
// Register all pending event listeners on the real gDevTools object.
|
||||||
|
for (let [event, listener] of this.listeners) {
|
||||||
|
this.gDevTools.on(event, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let tool of this.tools) {
|
||||||
|
this.gDevTools.registerTool(tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let theme of this.themes) {
|
||||||
|
this.gDevTools.registerTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listeners = [];
|
||||||
|
this.tools = [];
|
||||||
|
this.themes = [];
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
devtools-shim.jar:
|
||||||
|
% content devtools-shim %content/
|
||||||
|
content/DevToolsShim.jsm (DevToolsShim.jsm)
|
|
@ -0,0 +1,3 @@
|
||||||
|
JAR_MANIFESTS += ['jar.mn']
|
||||||
|
|
||||||
|
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
|
@ -0,0 +1,21 @@
|
||||||
|
// This file was copied from the .eslintrc.xpcshell.js
|
||||||
|
// This new xpcshell test folder should stay in mozilla-central while devtools move to a
|
||||||
|
// GitHub repository, hence the duplication.
|
||||||
|
module.exports = {
|
||||||
|
"extends": [
|
||||||
|
"plugin:mozilla/xpcshell-test"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
// Allow non-camelcase so that run_test doesn't produce a warning.
|
||||||
|
"camelcase": "off",
|
||||||
|
// Allow using undefined variables so that tests can refer to functions
|
||||||
|
// and variables defined in head.js files, without having to maintain a
|
||||||
|
// list of globals in each .eslintrc file.
|
||||||
|
// Note that bug 1168340 will eventually help auto-registering globals
|
||||||
|
// from head.js files.
|
||||||
|
"no-undef": "off",
|
||||||
|
"block-scoped-var": "off",
|
||||||
|
// Tests can always import anything.
|
||||||
|
"mozilla/reject-some-requires": "off",
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { DevToolsShim } =
|
||||||
|
Components.utils.import("chrome://devtools-shim/content/DevToolsShim.jsm", {});
|
||||||
|
|
||||||
|
// Test the DevToolsShim
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a mocked version of DevTools that records all calls made to methods expected
|
||||||
|
* to be called by DevToolsShim.
|
||||||
|
*/
|
||||||
|
function createMockDevTools() {
|
||||||
|
let methods = [
|
||||||
|
"on",
|
||||||
|
"off",
|
||||||
|
"registerTool",
|
||||||
|
"registerTheme",
|
||||||
|
"unregisterTool",
|
||||||
|
"unregisterTheme",
|
||||||
|
];
|
||||||
|
|
||||||
|
let mock = {
|
||||||
|
callLog: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let method of methods) {
|
||||||
|
// Create a stub for method, that only pushes its arguments in the inner callLog
|
||||||
|
mock[method] = function (...args) {
|
||||||
|
mock.callLog[method].push(args);
|
||||||
|
};
|
||||||
|
mock.callLog[method] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given method was called an expected number of times, and finally check the
|
||||||
|
* arguments provided to the last call, if appropriate.
|
||||||
|
*/
|
||||||
|
function checkCalls(mock, method, length, lastArgs) {
|
||||||
|
ok(mock.callLog[method].length === length,
|
||||||
|
"Devtools.on was called the expected number of times");
|
||||||
|
|
||||||
|
// If we don't want to check the last call or if the method was never called, bail out.
|
||||||
|
if (!lastArgs || length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < lastArgs.length; i++) {
|
||||||
|
let expectedArg = lastArgs[i];
|
||||||
|
ok(mock.callLog[method][length - 1][i] === expectedArg,
|
||||||
|
`Devtools.${method} was called with the expected argument (index ${i})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_register_unregister() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
DevToolsShim.register(createMockDevTools());
|
||||||
|
ok(DevToolsShim.isInstalled(), "DevTools are installed");
|
||||||
|
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_on_is_forwarded_to_devtools() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
function cb1() {}
|
||||||
|
function cb2() {}
|
||||||
|
let mock = createMockDevTools();
|
||||||
|
|
||||||
|
DevToolsShim.on("test_event", cb1);
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "on", 1, ["test_event", cb1]);
|
||||||
|
|
||||||
|
DevToolsShim.on("other_event", cb2);
|
||||||
|
checkCalls(mock, "on", 2, ["other_event", cb2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_off_called_before_registering_devtools() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
function cb1() {}
|
||||||
|
let mock = createMockDevTools();
|
||||||
|
|
||||||
|
DevToolsShim.on("test_event", cb1);
|
||||||
|
DevToolsShim.off("test_event", cb1);
|
||||||
|
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "on", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_off_called_before_with_bad_callback() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
function cb1() {}
|
||||||
|
function cb2() {}
|
||||||
|
let mock = createMockDevTools();
|
||||||
|
|
||||||
|
DevToolsShim.on("test_event", cb1);
|
||||||
|
DevToolsShim.off("test_event", cb2);
|
||||||
|
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
// on should still be called
|
||||||
|
checkCalls(mock, "on", 1, ["test_event", cb1]);
|
||||||
|
// Calls to off should not be held and forwarded.
|
||||||
|
checkCalls(mock, "off", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_registering_tool() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
let tool1 = {};
|
||||||
|
let tool2 = {};
|
||||||
|
let tool3 = {};
|
||||||
|
let mock = createMockDevTools();
|
||||||
|
|
||||||
|
// Pre-register tool1
|
||||||
|
DevToolsShim.registerTool(tool1);
|
||||||
|
|
||||||
|
// Pre-register tool3, but unregister right after
|
||||||
|
DevToolsShim.registerTool(tool3);
|
||||||
|
DevToolsShim.unregisterTool(tool3);
|
||||||
|
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "registerTool", 1, [tool1]);
|
||||||
|
|
||||||
|
DevToolsShim.registerTool(tool2);
|
||||||
|
checkCalls(mock, "registerTool", 2, [tool2]);
|
||||||
|
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
// Create a new mock and check the tools are not added once again.
|
||||||
|
mock = createMockDevTools();
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "registerTool", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_registering_theme() {
|
||||||
|
ok(!DevToolsShim.isInstalled(), "DevTools are not installed");
|
||||||
|
|
||||||
|
let theme1 = {};
|
||||||
|
let theme2 = {};
|
||||||
|
let theme3 = {};
|
||||||
|
let mock = createMockDevTools();
|
||||||
|
|
||||||
|
// Pre-register theme1
|
||||||
|
DevToolsShim.registerTheme(theme1);
|
||||||
|
|
||||||
|
// Pre-register theme3, but unregister right after
|
||||||
|
DevToolsShim.registerTheme(theme3);
|
||||||
|
DevToolsShim.unregisterTheme(theme3);
|
||||||
|
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "registerTheme", 1, [theme1]);
|
||||||
|
|
||||||
|
DevToolsShim.registerTheme(theme2);
|
||||||
|
checkCalls(mock, "registerTheme", 2, [theme2]);
|
||||||
|
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
// Create a new mock and check the themes are not added once again.
|
||||||
|
mock = createMockDevTools();
|
||||||
|
DevToolsShim.register(mock);
|
||||||
|
checkCalls(mock, "registerTheme", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
test_register_unregister();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
test_on_is_forwarded_to_devtools();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
test_off_called_before_registering_devtools();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
test_off_called_before_with_bad_callback();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
test_registering_tool();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
|
||||||
|
test_registering_theme();
|
||||||
|
DevToolsShim.unregister();
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[DEFAULT]
|
||||||
|
tags = devtools
|
||||||
|
firefox-appdir = browser
|
||||||
|
skip-if = toolkit == 'android'
|
||||||
|
|
||||||
|
[test_devtools_shim.js]
|
Загрузка…
Ссылка в новой задаче