зеркало из https://github.com/mozilla/gecko-dev.git
Bug 984365 - Refactor and split out BuiltinCommands.jsm; r=mratcliffe,robcee,panos
BuiltinCommands.jsm was huge to avoid slowing things down by having many modules loading. To avoid splitting it up from slowing things down we want to delay loading commands. Create [add|remove]ItemsByModule to allow us to lazily add modules, and convert all command modules to use this. Then break up BuiltinCommands into a set of files, for each command, and do some refactoring to use JS files rather than JSMs and use "use strict". --HG-- rename : browser/devtools/commandline/Commands.jsm => browser/devtools/commandline/commands-index.js rename : browser/devtools/debugger/CmdDebugger.jsm => browser/devtools/debugger/debugger-commands.js rename : browser/devtools/inspector/CmdInspect.jsm => browser/devtools/inspector/inspector-commands.js rename : browser/devtools/responsivedesign/CmdResize.jsm => browser/devtools/responsivedesign/resize-commands.js rename : browser/devtools/scratchpad/CmdScratchpad.jsm => browser/devtools/scratchpad/scratchpad-commands.js rename : browser/devtools/styleeditor/CmdEdit.jsm => browser/devtools/styleeditor/styleeditor-commands.js rename : browser/devtools/tilt/CmdTilt.jsm => browser/devtools/tilt/tilt-commands.js
This commit is contained in:
Родитель
d90cfa210e
Коммит
6148f170d7
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,18 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
const Cu = Components.utils;
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
||||
Cu.import("resource:///modules/devtools/BuiltinCommands.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdDebugger.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdEdit.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdInspect.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdResize.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdTilt.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");
|
||||
|
||||
require("devtools/profiler/commands.js");
|
|
@ -1,9 +0,0 @@
|
|||
#
|
||||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -0,0 +1,37 @@
|
|||
/* 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 gcli = require("gcli/index");
|
||||
|
||||
const commandModules = [
|
||||
"devtools/tilt/tilt-commands",
|
||||
"gcli/commands/addon",
|
||||
"gcli/commands/appcache",
|
||||
"gcli/commands/calllog",
|
||||
"gcli/commands/cmd",
|
||||
"gcli/commands/cookie",
|
||||
"gcli/commands/jsb",
|
||||
"gcli/commands/listen",
|
||||
"gcli/commands/media",
|
||||
"gcli/commands/pagemod",
|
||||
"gcli/commands/paintflashing",
|
||||
"gcli/commands/restart",
|
||||
"gcli/commands/screenshot",
|
||||
"gcli/commands/tools",
|
||||
];
|
||||
|
||||
gcli.addItemsByModule(commandModules, { delayedLoad: true });
|
||||
|
||||
const defaultTools = require("main").defaultTools;
|
||||
for (let definition of defaultTools) {
|
||||
if (definition.commands) {
|
||||
gcli.addItemsByModule(definition.commands, { delayedLoad: true });
|
||||
}
|
||||
}
|
||||
|
||||
const { mozDirLoader } = require("gcli/commands/cmd");
|
||||
|
||||
gcli.addItemsByModule("mozcmd", { delayedLoad: true, loader: mozDirLoader });
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "gcli" ];
|
||||
Components.utils.import("resource://gre/modules/devtools/gcli.jsm");
|
|
@ -1,7 +1,11 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/commandline'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'commands-index.js'
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
|
|
@ -3,149 +3,132 @@
|
|||
|
||||
// Tests that the addon commands works as they should
|
||||
|
||||
let CmdAddonFlags = (Cu.import("resource:///modules/devtools/BuiltinCommands.jsm", {})).CmdAddonFlags;
|
||||
|
||||
let tests = {};
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar("about:blank", function(options) {
|
||||
return helpers.runTests(options, tests);
|
||||
}).then(finish, helpers.handleError);
|
||||
return Task.spawn(spawnTest).then(finish, helpers.handleError);
|
||||
}
|
||||
|
||||
tests.gatTest = function(options) {
|
||||
let deferred = promise.defer();
|
||||
function spawnTest() {
|
||||
let options = yield helpers.openTab("about:blank");
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
let onGatReady = function() {
|
||||
Services.obs.removeObserver(onGatReady, "gcli_addon_commands_ready");
|
||||
info("gcli_addon_commands_ready notification received, running tests");
|
||||
|
||||
let auditDone = helpers.audit(options, [
|
||||
{
|
||||
setup: 'addon list dictionary',
|
||||
check: {
|
||||
input: 'addon list dictionary',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: 'addon list dictionary',
|
||||
check: {
|
||||
input: 'addon list dictionary',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
{
|
||||
setup: 'addon list extension',
|
||||
check: {
|
||||
input: 'addon list extension',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Mochitest/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list locale',
|
||||
check: {
|
||||
input: 'addon list locale',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list plugin',
|
||||
check: {
|
||||
input: 'addon list plugin',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/Test Plug-in/, /Second Test Plug-in/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list theme',
|
||||
check: {
|
||||
input: 'addon list theme',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/following themes/, /Default/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list all',
|
||||
check: {
|
||||
input: 'addon list all',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Default/, /Mochitest/, /Test Plug-in/,
|
||||
/Second Test Plug-in/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 disabled.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable WRONG',
|
||||
check: {
|
||||
input: 'addon disable WRONG',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVEEEEE',
|
||||
status: 'ERROR'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
command: { name: 'addon enable' },
|
||||
name: { value: 'Test Plug-in', status: 'VALID' },
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 enabled.'
|
||||
}
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
]);
|
||||
},
|
||||
{
|
||||
setup: 'addon list extension',
|
||||
check: {
|
||||
input: 'addon list extension',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Mochitest/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list locale',
|
||||
check: {
|
||||
input: 'addon list locale',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list plugin',
|
||||
check: {
|
||||
input: 'addon list plugin',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/Test Plug-in/, /Second Test Plug-in/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list theme',
|
||||
check: {
|
||||
input: 'addon list theme',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/following themes/, /Default/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list all',
|
||||
check: {
|
||||
input: 'addon list all',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Default/, /Mochitest/, /Test Plug-in/,
|
||||
/Second Test Plug-in/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 disabled.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable WRONG',
|
||||
check: {
|
||||
input: 'addon disable WRONG',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVEEEEE',
|
||||
status: 'ERROR'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
command: { name: 'addon enable' },
|
||||
addon: {
|
||||
value: function(addon) {
|
||||
is(addon.name, 'Test Plug-in', 'test plugin name');
|
||||
},
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 enabled.'
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
auditDone.then(deferred.resolve, deferred.reject);
|
||||
};
|
||||
|
||||
Services.obs.addObserver(onGatReady, "gcli_addon_commands_ready", false);
|
||||
|
||||
if (CmdAddonFlags.addonsLoaded) {
|
||||
info("The call to AddonManager.getAllAddons in BuiltinCommands.jsm is done.");
|
||||
info("Send the gcli_addon_commands_ready notification ourselves.");
|
||||
|
||||
Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
|
||||
} else {
|
||||
info("Waiting for gcli_addon_commands_ready notification.");
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ function test() {
|
|||
}
|
||||
|
||||
function spawnTest() {
|
||||
// Setup
|
||||
let options = yield helpers.openTab(TEST_URI);
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
|
@ -31,12 +30,13 @@ function spawnTest() {
|
|||
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: 'export html',
|
||||
setup: 'export html',
|
||||
skipIf: true,
|
||||
check: {
|
||||
input: 'export html',
|
||||
hints: '',
|
||||
hints: ' [destination]',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
status: 'VALID',
|
||||
},
|
||||
exec: {
|
||||
output: ''
|
||||
|
@ -45,12 +45,32 @@ function spawnTest() {
|
|||
isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
|
||||
isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
|
||||
isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
|
||||
|
||||
options.window.open = oldOpen;
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'export html stdout',
|
||||
check: {
|
||||
input: 'export html stdout',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
destination: { value: "stdout" }
|
||||
},
|
||||
},
|
||||
exec: {
|
||||
output: [
|
||||
/<html lang="en">/,
|
||||
/<title>GCLI/,
|
||||
/<p id="someid">#/
|
||||
]
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
options.window.open = oldOpen;
|
||||
oldOpen = undefined;
|
||||
|
||||
// Test 'pagemod replace'
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
|
@ -1,23 +1,18 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
var gcli = devtools.require('gcli/index');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
/**
|
||||
* The commands and converters that are exported to GCLI
|
||||
*/
|
||||
exports.items = [];
|
||||
|
||||
/**
|
||||
* Utility to get access to the current breakpoint list.
|
||||
|
@ -56,7 +51,7 @@ function getAllBreakpoints(dbg) {
|
|||
/**
|
||||
* 'break' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break",
|
||||
description: gcli.lookup("breakDesc"),
|
||||
manual: gcli.lookup("breakManual")
|
||||
|
@ -65,7 +60,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'break list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break list",
|
||||
description: gcli.lookup("breaklistDesc"),
|
||||
returnType: "breakpoints",
|
||||
|
@ -75,7 +70,8 @@ gcli.addCommand({
|
|||
}
|
||||
});
|
||||
|
||||
gcli.addConverter({
|
||||
exports.items.push({
|
||||
item: "converter",
|
||||
from: "breakpoints",
|
||||
to: "view",
|
||||
exec: function(breakpoints, context) {
|
||||
|
@ -129,7 +125,7 @@ var MAX_LABEL_LENGTH = 20;
|
|||
/**
|
||||
* 'break add' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break add",
|
||||
description: gcli.lookup("breakaddDesc"),
|
||||
manual: gcli.lookup("breakaddManual")
|
||||
|
@ -138,7 +134,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'break add line' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break add line",
|
||||
description: gcli.lookup("breakaddlineDesc"),
|
||||
params: [
|
||||
|
@ -185,7 +181,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'break del' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break del",
|
||||
description: gcli.lookup("breakdelDesc"),
|
||||
params: [
|
||||
|
@ -231,7 +227,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg",
|
||||
description: gcli.lookup("dbgDesc"),
|
||||
manual: gcli.lookup("dbgManual")
|
||||
|
@ -240,7 +236,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg open",
|
||||
description: gcli.lookup("dbgOpen"),
|
||||
params: [],
|
||||
|
@ -253,7 +249,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg close",
|
||||
description: gcli.lookup("dbgClose"),
|
||||
params: [],
|
||||
|
@ -269,7 +265,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg interrupt' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg interrupt",
|
||||
description: gcli.lookup("dbgInterrupt"),
|
||||
params: [],
|
||||
|
@ -290,7 +286,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg continue' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg continue",
|
||||
description: gcli.lookup("dbgContinue"),
|
||||
params: [],
|
||||
|
@ -311,7 +307,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg step' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg step",
|
||||
description: gcli.lookup("dbgStepDesc"),
|
||||
manual: gcli.lookup("dbgStepManual")
|
||||
|
@ -320,7 +316,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg step over' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg step over",
|
||||
description: gcli.lookup("dbgStepOverDesc"),
|
||||
params: [],
|
||||
|
@ -341,7 +337,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg step in' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: 'dbg step in',
|
||||
description: gcli.lookup("dbgStepInDesc"),
|
||||
params: [],
|
||||
|
@ -362,7 +358,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg step over' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: 'dbg step out',
|
||||
description: gcli.lookup("dbgStepOutDesc"),
|
||||
params: [],
|
||||
|
@ -383,7 +379,7 @@ gcli.addCommand({
|
|||
/**
|
||||
* 'dbg list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg list",
|
||||
description: gcli.lookup("dbgListSourcesDesc"),
|
||||
params: [],
|
||||
|
@ -429,7 +425,7 @@ gcli.addCommand({
|
|||
return gcli.lookup(cmd.l10nPrefix + id);
|
||||
};
|
||||
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg " + cmd.name,
|
||||
description: lookup("Desc"),
|
||||
params: [
|
|
@ -6,6 +6,7 @@
|
|||
JS_MODULES_PATH = 'modules/devtools/debugger'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'debugger-commands.js',
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
|
|
@ -41,10 +41,6 @@ loader.lazyGetter(this, "toolboxStrings", () => {
|
|||
};
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "Requisition", () => {
|
||||
return require("gcli/cli").Requisition;
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "Selection", () => require("devtools/framework/selection").Selection);
|
||||
loader.lazyGetter(this, "InspectorFront", () => require("devtools/server/actors/inspector").InspectorFront);
|
||||
|
||||
|
@ -539,7 +535,7 @@ Toolbox.prototype = {
|
|||
|
||||
let spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
|
||||
let environment = CommandUtils.createEnvironment(this, '_target');
|
||||
this._requisition = new Requisition({ environment: environment });
|
||||
this._requisition = CommandUtils.createRequisition(environment);
|
||||
let buttons = CommandUtils.createButtons(spec, this._target,
|
||||
this.doc, this._requisition);
|
||||
let container = this.doc.getElementById("toolbox-buttons");
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require('gcli/index');
|
||||
|
||||
/**
|
||||
* 'inspect' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "inspect",
|
||||
description: gcli.lookup("inspectDesc"),
|
||||
manual: gcli.lookup("inspectManual"),
|
||||
params: [
|
||||
{
|
||||
name: "selector",
|
||||
type: "node",
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function Command_inspect(args, context) {
|
||||
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
|
||||
let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
return gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
toolbox.getCurrentPanel().selection.setNode(args.selector, "gcli");
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools/
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/inspector
|
|
@ -0,0 +1,29 @@
|
|||
/* 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 gcli = require("gcli/index");
|
||||
|
||||
exports.items = [{
|
||||
name: "inspect",
|
||||
description: gcli.lookup("inspectDesc"),
|
||||
manual: gcli.lookup("inspectManual"),
|
||||
params: [
|
||||
{
|
||||
name: "selector",
|
||||
type: "node",
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let gDevTools = require("resource:///modules/devtools/gDevTools.jsm").gDevTools;
|
||||
|
||||
return gDevTools.showToolbox(target, "inspector").then(toolbox => {
|
||||
toolbox.getCurrentPanel().selection.setNode(args.selector, "gcli");
|
||||
});
|
||||
}
|
||||
}];
|
|
@ -1,7 +1,14 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/inspector'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'breadcrumbs.js',
|
||||
'inspector-commands.js',
|
||||
'inspector-panel.js',
|
||||
'selector-search.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
|
|
@ -15,6 +15,7 @@ browser.jar:
|
|||
content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
* content/browser/devtools/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
content/browser/devtools/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/devtools/scratchpad-commands.js (scratchpad/scratchpad-commands.js)
|
||||
content/browser/devtools/splitview.css (shared/splitview.css)
|
||||
content/browser/devtools/theme-switching.js (shared/theme-switching.js)
|
||||
content/browser/devtools/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
|
@ -79,9 +80,11 @@ browser.jar:
|
|||
content/browser/devtools/profiler/cleopatra/images/noise.png (profiler/cleopatra/images/noise.png)
|
||||
content/browser/devtools/profiler/cleopatra/images/throbber.svg (profiler/cleopatra/images/throbber.svg)
|
||||
content/browser/devtools/profiler/cleopatra/images/treetwisty.svg (profiler/cleopatra/images/treetwisty.svg)
|
||||
content/browser/devtools/responsivedesign/resize-commands.js (responsivedesign/resize-commands.js)
|
||||
content/browser/devtools/commandline.css (commandline/commandline.css)
|
||||
content/browser/devtools/commandlineoutput.xhtml (commandline/commandlineoutput.xhtml)
|
||||
content/browser/devtools/commandlinetooltip.xhtml (commandline/commandlinetooltip.xhtml)
|
||||
content/browser/devtools/commandline/commands-index.js (commandline/commands-index.js)
|
||||
content/browser/devtools/framework/toolbox-window.xul (framework/toolbox-window.xul)
|
||||
content/browser/devtools/framework/toolbox-options.xul (framework/toolbox-options.xul)
|
||||
content/browser/devtools/framework/toolbox-options.js (framework/toolbox-options.js)
|
||||
|
|
|
@ -90,6 +90,7 @@ Tools.webConsole = {
|
|||
menuLabel: l10n("MenuWebconsole.label", webConsoleStrings),
|
||||
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/webconsole/console-commands",
|
||||
|
||||
preventClosingOnKey: true,
|
||||
onkey: function(panel, toolbox) {
|
||||
|
@ -120,6 +121,10 @@ Tools.inspector = {
|
|||
label: l10n("inspector.label", inspectorStrings),
|
||||
tooltip: l10n("inspector.tooltip", inspectorStrings),
|
||||
inMenu: true,
|
||||
commands: [
|
||||
"devtools/resize-commands",
|
||||
"devtools/inspector/inspector-commands",
|
||||
],
|
||||
|
||||
preventClosingOnKey: true,
|
||||
onkey: function(panel) {
|
||||
|
@ -149,6 +154,7 @@ Tools.jsdebugger = {
|
|||
label: l10n("ToolboxDebugger.label", debuggerStrings),
|
||||
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/debugger/debugger-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
|
@ -172,6 +178,7 @@ Tools.styleEditor = {
|
|||
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
|
||||
tooltip: l10n("ToolboxStyleEditor.tooltip2", styleEditorStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/styleeditor/styleeditor-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon;
|
||||
|
@ -236,6 +243,7 @@ Tools.jsprofiler = {
|
|||
label: l10n("profiler.label", profilerStrings),
|
||||
tooltip: l10n("profiler.tooltip2", profilerStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/profiler/commands",
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
return !target.isAddon;
|
||||
|
@ -282,6 +290,7 @@ Tools.scratchpad = {
|
|||
label: l10n("scratchpad.label", scratchpadStrings),
|
||||
tooltip: l10n("scratchpad.tooltip", scratchpadStrings),
|
||||
inMenu: false,
|
||||
commands: "devtools/scratchpad/scratchpad-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon && target.isRemote;
|
||||
|
|
|
@ -2,147 +2,115 @@
|
|||
* 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/. */
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
module.exports = [];
|
||||
"use strict";
|
||||
|
||||
var gcli = require('gcli/index');
|
||||
const gcli = require('gcli/index');
|
||||
|
||||
loader.lazyGetter(this, "gDevTools",
|
||||
() => Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools);
|
||||
|
||||
var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
/*
|
||||
* 'profiler' command. Doesn't do anything.
|
||||
*/
|
||||
gcli.addCommand({
|
||||
module.exports.items = [
|
||||
{
|
||||
name: "profiler",
|
||||
description: gcli.lookup("profilerDesc"),
|
||||
manual: gcli.lookup("profilerManual")
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler open",
|
||||
description: gcli.lookup("profilerOpenDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler close",
|
||||
description: gcli.lookup("profilerCloseDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
if (!getPanel(context, "jsprofiler"))
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel(id);
|
||||
if (panel == null)
|
||||
return;
|
||||
|
||||
return gDevTools.closeToolbox(context.environment.target)
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler start' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler start",
|
||||
description: gcli.lookup("profilerStartDesc"),
|
||||
returnType: "string",
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
function start() {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let target = context.environment.target
|
||||
return gDevTools.showToolbox(target, "jsprofiler").then(toolbox => {
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
if (panel.recordingProfile)
|
||||
throw gcli.lookup("profilerAlreadyStarted2");
|
||||
|
||||
panel.toggleRecording();
|
||||
return gcli.lookup("profilerStarted2");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(start);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler stop' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler stop",
|
||||
description: gcli.lookup("profilerStopDesc"),
|
||||
returnType: "string",
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
function stop() {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let target = context.environment.target
|
||||
return gDevTools.showToolbox(target, "jsprofiler").then(toolbox => {
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
if (!panel.recordingProfile)
|
||||
throw gcli.lookup("profilerNotStarted3");
|
||||
|
||||
panel.toggleRecording();
|
||||
return gcli.lookup("profilerStopped");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(stop);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler list",
|
||||
description: gcli.lookup("profilerListDesc"),
|
||||
returnType: "dom",
|
||||
params: [],
|
||||
|
||||
returnType: "profileList",
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel("jsprofiler");
|
||||
|
||||
if (!panel) {
|
||||
if (panel == null) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
}
|
||||
|
||||
let doc = panel.document;
|
||||
let div = createXHTMLElement(doc, "div");
|
||||
let ol = createXHTMLElement(doc, "ol");
|
||||
|
||||
for ([ uid, profile] of panel.profiles) {
|
||||
let li = createXHTMLElement(doc, "li");
|
||||
li.textContent = profile.name;
|
||||
if (profile.isStarted) {
|
||||
li.textContent += " *";
|
||||
}
|
||||
ol.appendChild(li);
|
||||
let profileList = [];
|
||||
for ([ uid, profile ] of panel.profiles) {
|
||||
profileList.push({ name: profile.name, started: profile.isStarted });
|
||||
}
|
||||
|
||||
div.appendChild(ol);
|
||||
return div;
|
||||
return profileList;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler show' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "profileList",
|
||||
to: "view",
|
||||
exec: function(profileList, context) {
|
||||
return {
|
||||
html: "<div>" +
|
||||
" <ol>" +
|
||||
" <li forEach='profile of ${profiles}'>${profile.name}</li>" +
|
||||
" ${profile.name} ${profile.started ? '*' : ''}" +
|
||||
" </li>" +
|
||||
" </ol>" +
|
||||
"</div>",
|
||||
data: { profiles: profileList.profiles },
|
||||
options: { allowEval: true }
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "profiler show",
|
||||
description: gcli.lookup("profilerShowDesc"),
|
||||
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
|
@ -152,7 +120,8 @@ gcli.addCommand({
|
|||
],
|
||||
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel(id);
|
||||
|
||||
if (!panel) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
|
@ -165,17 +134,4 @@ gcli.addCommand({
|
|||
|
||||
panel.sidebar.selectedItem = panel.sidebar.getItemByProfile(profile);
|
||||
}
|
||||
});
|
||||
|
||||
function getPanel(context, id) {
|
||||
if (context == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
return toolbox == null ? undefined : toolbox.getPanel(id);
|
||||
}
|
||||
|
||||
function createXHTMLElement(document, tagname) {
|
||||
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
|
||||
}
|
||||
}];
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://branding/locale/brand.properties").
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
|
||||
/* Responsive Mode commands */
|
||||
gcli.addCommand({
|
||||
name: 'resize',
|
||||
description: gcli.lookup('resizeModeDesc')
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize on',
|
||||
description: gcli.lookup('resizeModeOnDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize off',
|
||||
description: gcli.lookup('resizeModeOffDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize toggle',
|
||||
buttonId: "command-button-responsive",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
|
||||
description: gcli.lookup('resizeModeToggleDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
return mgr.isActiveForTab(aTarget.tab);
|
||||
},
|
||||
onChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.on("on", aChangeHandler);
|
||||
mgr.on("off", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize to',
|
||||
description: gcli.lookup('resizeModeToDesc'),
|
||||
params: [
|
||||
{
|
||||
name: 'width',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgWidthDesc"),
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgHeightDesc"),
|
||||
},
|
||||
],
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
function gcli_cmd_resize(args, context) {
|
||||
let browserDoc = context.environment.chromeDocument;
|
||||
let browserWindow = browserDoc.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.handleGcliCommand(browserWindow,
|
||||
browserWindow.gBrowser.selectedTab,
|
||||
this.name,
|
||||
args);
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
JS_MODULES_PATH = 'modules/devtools'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'resize-commands.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://branding/locale/brand.properties").
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: 'resize',
|
||||
description: gcli.lookup('resizeModeDesc')
|
||||
},
|
||||
{
|
||||
name: 'resize on',
|
||||
description: gcli.lookup('resizeModeOnDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize off',
|
||||
description: gcli.lookup('resizeModeOffDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize toggle',
|
||||
buttonId: "command-button-responsive",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
|
||||
description: gcli.lookup('resizeModeToggleDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
return mgr.isActiveForTab(aTarget.tab);
|
||||
},
|
||||
onChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.on("on", aChangeHandler);
|
||||
mgr.on("off", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize to',
|
||||
description: gcli.lookup('resizeModeToDesc'),
|
||||
params: [
|
||||
{
|
||||
name: 'width',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgWidthDesc"),
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgHeightDesc"),
|
||||
},
|
||||
],
|
||||
exec: gcli_cmd_resize
|
||||
}
|
||||
];
|
||||
|
||||
function gcli_cmd_resize(args, context) {
|
||||
let browserWindow = context.environment.chromeWindow;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.handleGcliCommand(browserWindow,
|
||||
browserWindow.gBrowser.selectedTab,
|
||||
this.name,
|
||||
args);
|
||||
}
|
|
@ -9,5 +9,6 @@ TEST_DIRS += ['test']
|
|||
JS_MODULES_PATH = 'modules/devtools/scratchpad'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'scratchpad-commands.js',
|
||||
'scratchpad-panel.js'
|
||||
]
|
||||
|
|
|
@ -2,22 +2,18 @@
|
|||
* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
"use strict";
|
||||
|
||||
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
/**
|
||||
* 'scratchpad' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [{
|
||||
name: "scratchpad",
|
||||
buttonId: "command-button-scratchpad",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("scratchpadOpenTooltip"),
|
||||
hidden: true,
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
chromeWindow.Scratchpad.ScratchpadManager.openScratchpad();
|
||||
let Scratchpad = context.environment.chromeWindow.Scratchpad;
|
||||
Scratchpad.ScratchpadManager.openScratchpad();
|
||||
}
|
||||
});
|
||||
}];
|
|
@ -12,7 +12,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/Commands.jsm");
|
||||
|
||||
const { require, TargetFactory } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
|
||||
|
@ -21,9 +20,6 @@ const Node = Ci.nsIDOMNode;
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
|
||||
"resource:///modules/devtools/BuiltinCommands.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
|
@ -43,7 +39,13 @@ XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function () {
|
|||
|
||||
const Telemetry = require("devtools/shared/telemetry");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", () => require("gcli/index"));
|
||||
// This lazy getter is needed to prevent a require loop
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", () => {
|
||||
let gcli = require("gcli/index");
|
||||
require("devtools/commandline/commands-index");
|
||||
gcli.load();
|
||||
return gcli;
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "ConsoleServiceListener", {
|
||||
get: function() {
|
||||
|
@ -59,6 +61,15 @@ const promise = Cu.import('resource://gre/modules/Promise.jsm', {}).Promise;
|
|||
* A collection of utilities to help working with commands
|
||||
*/
|
||||
let CommandUtils = {
|
||||
/**
|
||||
* Utility to ensure that things are loaded in the correct order
|
||||
*/
|
||||
createRequisition: function(environment) {
|
||||
let temp = gcli.createDisplay; // Ensure GCLI is loaded
|
||||
let Requisition = require("gcli/cli").Requisition
|
||||
return new Requisition({ environment: environment });
|
||||
},
|
||||
|
||||
/**
|
||||
* Read a toolbarSpec from preferences
|
||||
* @param pref The name of the preference to read
|
||||
|
@ -349,13 +360,6 @@ DeveloperToolbar.prototype.show = function(focus) {
|
|||
var waitPromise = this._hidePromise || promise.resolve();
|
||||
|
||||
this._showPromise = waitPromise.then(() => {
|
||||
try {
|
||||
CmdCommands.refreshAutoCommands(this._chromeWindow);
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref("devtools.toolbar.visible", true);
|
||||
|
||||
this._telemetry.toolOpened("developertoolbar");
|
||||
|
|
|
@ -2,21 +2,11 @@
|
|||
* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const gcli = devtools.require("gcli/index");
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
/**
|
||||
* 'edit' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [{
|
||||
name: "edit",
|
||||
description: gcli.lookup("editDesc"),
|
||||
manual: gcli.lookup("editManual2"),
|
||||
|
@ -42,10 +32,11 @@ gcli.addCommand({
|
|||
],
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let gDevTools = require("resource:///modules/devtools/gDevTools.jsm").gDevTools;
|
||||
return gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
|
||||
let styleEditor = toolbox.getCurrentPanel();
|
||||
styleEditor.selectStyleSheet(args.resource.element, args.line);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}];
|
|
@ -1,9 +0,0 @@
|
|||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/tilt
|
|
@ -1,8 +1,19 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
JS_MODULES_PATH = 'modules/devtools/tilt'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'tilt-commands.js',
|
||||
'tilt-gl.js',
|
||||
'tilt-math.js',
|
||||
'tilt-utils.js',
|
||||
'tilt-visualizer-style.js',
|
||||
'tilt-visualizer.js',
|
||||
'tilt.js',
|
||||
'TiltWorkerCrafter.js',
|
||||
'TiltWorkerPicker.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
|
|
@ -1,40 +1,28 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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 = [ ];
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
// Fetch TiltManager using the current loader, but don't save a
|
||||
// reference to it, because it might change with a tool reload.
|
||||
// We can clean this up once the command line is loadered.
|
||||
Object.defineProperty(this, "TiltManager", {
|
||||
get: function() {
|
||||
return devtools.require("devtools/tilt/tilt").TiltManager;
|
||||
return require("devtools/tilt/tilt").TiltManager;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
/**
|
||||
* 'tilt' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [
|
||||
{
|
||||
name: 'tilt',
|
||||
description: gcli.lookup("tiltDesc"),
|
||||
manual: gcli.lookup("tiltManual")
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt open',
|
||||
description: gcli.lookup("tiltOpenDesc"),
|
||||
manual: gcli.lookup("tiltOpenManual"),
|
||||
|
@ -45,13 +33,8 @@ gcli.addCommand({
|
|||
Tilt.toggle();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt toggle' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "tilt toggle",
|
||||
buttonId: "command-button-tilt",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
|
@ -80,13 +63,8 @@ gcli.addCommand({
|
|||
let Tilt = TiltManager.getTiltForBrowser(chromeWindow);
|
||||
Tilt.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt translate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt translate',
|
||||
description: gcli.lookup("tiltTranslateDesc"),
|
||||
manual: gcli.lookup("tiltTranslateManual"),
|
||||
|
@ -113,13 +91,8 @@ gcli.addCommand({
|
|||
Tilt.currentInstance.controller.arcball.translate([args.x, args.y]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt rotate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt rotate',
|
||||
description: gcli.lookup("tiltRotateDesc"),
|
||||
manual: gcli.lookup("tiltRotateManual"),
|
||||
|
@ -153,13 +126,8 @@ gcli.addCommand({
|
|||
Tilt.currentInstance.controller.arcball.rotate([args.x, args.y, args.z]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt zoom' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt zoom',
|
||||
description: gcli.lookup("tiltZoomDesc"),
|
||||
manual: gcli.lookup("tiltZoomManual"),
|
||||
|
@ -179,13 +147,8 @@ gcli.addCommand({
|
|||
Tilt.currentInstance.controller.arcball.zoom(-args.zoom);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt reset' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt reset',
|
||||
description: gcli.lookup("tiltResetDesc"),
|
||||
manual: gcli.lookup("tiltResetManual"),
|
||||
|
@ -197,13 +160,8 @@ gcli.addCommand({
|
|||
Tilt.currentInstance.controller.arcball.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt close',
|
||||
description: gcli.lookup("tiltCloseDesc"),
|
||||
manual: gcli.lookup("tiltCloseManual"),
|
||||
|
@ -213,4 +171,5 @@ gcli.addCommand({
|
|||
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
}
|
||||
});
|
||||
}
|
||||
];
|
|
@ -0,0 +1,99 @@
|
|||
/* 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 gcli = require("gcli/index");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const { gDevTools } = require("resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
gDevTools.on("toolbox-ready", (e, toolbox) => {
|
||||
if (!toolbox.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fireChangeForTab = () => {
|
||||
eventEmitter.emit("changed", toolbox.target.tab);
|
||||
};
|
||||
|
||||
toolbox.on("split-console", fireChangeForTab);
|
||||
toolbox.on("select", fireChangeForTab);
|
||||
|
||||
toolbox.once("destroyed", () => {
|
||||
toolbox.off("split-console", fireChangeForTab);
|
||||
toolbox.off("select", fireChangeForTab);
|
||||
});
|
||||
});
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: 'splitconsole',
|
||||
hidden: true,
|
||||
buttonId: "command-button-splitconsole",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("splitconsoleTooltip"),
|
||||
state: {
|
||||
isChecked: function(target) {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
return toolbox && toolbox.splitConsole;
|
||||
},
|
||||
onChange: function(target, changeHandler) {
|
||||
eventEmitter.on("changed", changeHandler);
|
||||
},
|
||||
offChange: function(target, changeHandler) {
|
||||
eventEmitter.off("changed", changeHandler);
|
||||
},
|
||||
},
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
if (!toolbox) {
|
||||
return gDevTools.showToolbox(target, "inspector").then((toolbox) => {
|
||||
toolbox.toggleSplitConsole();
|
||||
});
|
||||
} else {
|
||||
toolbox.toggleSplitConsole();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console",
|
||||
description: gcli.lookup("consoleDesc"),
|
||||
manual: gcli.lookup("consoleManual")
|
||||
},
|
||||
{
|
||||
name: "console clear",
|
||||
description: gcli.lookup("consoleclearDesc"),
|
||||
exec: function(args, context) {
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
if (toolbox == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let panel = toolbox.getPanel("webconsole");
|
||||
if (panel == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel.hud.jsterm.clearOutput();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console close",
|
||||
description: gcli.lookup("consolecloseDesc"),
|
||||
exec: function(args, context) {
|
||||
return gDevTools.closeToolbox(context.environment.target);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console open",
|
||||
description: gcli.lookup("consoleopenDesc"),
|
||||
exec: function(args, context) {
|
||||
return gDevTools.showToolbox(context.environment.target, "webconsole");
|
||||
}
|
||||
}
|
||||
];
|
|
@ -562,10 +562,9 @@ cmdDesc=Manipulate the commands
|
|||
# name, which is why it should be as short as possible.
|
||||
cmdRefreshDesc=Re-read mozcmd directory
|
||||
|
||||
# LOCALIZATION NOTE (cmdStatus) When the we load new commands from mozcmd
|
||||
# directory, we report on how many we loaded. %1$S is a count of the number
|
||||
# of loaded commands, and %2$S is the directory we loaded from.
|
||||
cmdStatus=Read %1$S commands from '%2$S'
|
||||
# LOCALIZATION NOTE (cmdStatus2) When the we load new commands from mozcmd
|
||||
# directory, we report where we loaded from using %1$S.
|
||||
cmdStatus2=Read commands from '%1$S'
|
||||
|
||||
# LOCALIZATION NOTE (cmdSetdirDesc)
|
||||
cmdSetdirDesc=Setup a mozcmd directory
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
# 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/.
|
||||
|
||||
gcli_commands_internal_FILES = $(wildcard $(srcdir)/commands/*)
|
||||
gcli_commands_internal_DEST = $(FINAL_TARGET)/modules/devtools/gcli/commands
|
||||
INSTALL_TARGETS += gcli_commands_internal
|
||||
|
||||
gcli_commands_FILES = $(wildcard $(srcdir)/source/lib/gcli/commands/*)
|
||||
gcli_commands_DEST = $(FINAL_TARGET)/modules/devtools/gcli/commands
|
||||
INSTALL_TARGETS += gcli_commands
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
const gcli = require("gcli/index");
|
||||
const { Promise: promise } = require("resource://gre/modules/Promise.jsm");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
/**
|
||||
* Takes a function that uses a callback as its last parameter, and returns a
|
||||
* new function that returns a promise instead.
|
||||
* This should probably live in async-util
|
||||
*/
|
||||
const promiseify = function(scope, functionWithLastParamCallback) {
|
||||
return (...args) => {
|
||||
return new Promise(resolve => {
|
||||
args.push((...results) => {
|
||||
resolve(results.length > 1 ? results : results[0]);
|
||||
});
|
||||
functionWithLastParamCallback.apply(scope, args);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Convert callback based functions to promise based ones
|
||||
const getAllAddons = promiseify(AddonManager, AddonManager.getAllAddons);
|
||||
const getAddonsByTypes = promiseify(AddonManager, AddonManager.getAddonsByTypes);
|
||||
|
||||
/**
|
||||
* Return a string array containing the pending operations on an addon
|
||||
*/
|
||||
function pendingOperations(addon) {
|
||||
let allOperations = [
|
||||
"PENDING_ENABLE", "PENDING_DISABLE", "PENDING_UNINSTALL",
|
||||
"PENDING_INSTALL", "PENDING_UPGRADE"
|
||||
];
|
||||
return allOperations.reduce(function(operations, opName) {
|
||||
return addon.pendingOperations & AddonManager[opName] ?
|
||||
operations.concat(opName) :
|
||||
operations;
|
||||
}, []);
|
||||
}
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
item: "type",
|
||||
name: "addon",
|
||||
parent: "selection",
|
||||
stringifyProperty: "name",
|
||||
cacheable: true,
|
||||
constructor: function() {
|
||||
// Tell GCLI to clear the cache of addons when one is added or removed
|
||||
let listener = {
|
||||
onInstalled: addon => { this.clearCache(); },
|
||||
onUninstalled: addon => { this.clearCache(); },
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
},
|
||||
lookup: function() {
|
||||
return getAllAddons().then(addons => {
|
||||
return addons.map(addon => {
|
||||
let name = addon.name + " " + addon.version;
|
||||
name = name.trim().replace(/\s/g, "_");
|
||||
return { name: name, value: addon };
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "addon",
|
||||
description: gcli.lookup("addonDesc")
|
||||
},
|
||||
{
|
||||
name: "addon list",
|
||||
description: gcli.lookup("addonListDesc"),
|
||||
returnType: "addonsInfo",
|
||||
params: [{
|
||||
name: "type",
|
||||
type: {
|
||||
name: "selection",
|
||||
data: [ "dictionary", "extension", "locale", "plugin", "theme", "all" ]
|
||||
},
|
||||
defaultValue: "all",
|
||||
description: gcli.lookup("addonListTypeDesc")
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
let types = (args.type === "all") ? null : [ args.type ];
|
||||
return getAddonsByTypes(types).then(addons => {
|
||||
addons = addons.map(function(addon) {
|
||||
return {
|
||||
name: addon.name,
|
||||
version: addon.version,
|
||||
isActive: addon.isActive,
|
||||
pendingOperations: pendingOperations(addon)
|
||||
};
|
||||
});
|
||||
return { addons: addons, type: args.type };
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "addonsInfo",
|
||||
to: "view",
|
||||
exec: function(addonsInfo, context) {
|
||||
if (!addonsInfo.addons.length) {
|
||||
return context.createView({
|
||||
html: "<p>${message}</p>",
|
||||
data: { message: gcli.lookup("addonNoneOfType") }
|
||||
});
|
||||
}
|
||||
|
||||
let headerLookups = {
|
||||
"dictionary": "addonListDictionaryHeading",
|
||||
"extension": "addonListExtensionHeading",
|
||||
"locale": "addonListLocaleHeading",
|
||||
"plugin": "addonListPluginHeading",
|
||||
"theme": "addonListThemeHeading",
|
||||
"all": "addonListAllHeading"
|
||||
};
|
||||
let header = gcli.lookup(headerLookups[addonsInfo.type] ||
|
||||
"addonListUnknownHeading");
|
||||
|
||||
let operationLookups = {
|
||||
"PENDING_ENABLE": "addonPendingEnable",
|
||||
"PENDING_DISABLE": "addonPendingDisable",
|
||||
"PENDING_UNINSTALL": "addonPendingUninstall",
|
||||
"PENDING_INSTALL": "addonPendingInstall",
|
||||
"PENDING_UPGRADE": "addonPendingUpgrade"
|
||||
};
|
||||
function lookupOperation(opName) {
|
||||
let lookupName = operationLookups[opName];
|
||||
return lookupName ? gcli.lookup(lookupName) : opName;
|
||||
}
|
||||
|
||||
function arrangeAddons(addons) {
|
||||
let enabledAddons = [];
|
||||
let disabledAddons = [];
|
||||
addons.forEach(function(addon) {
|
||||
if (addon.isActive) {
|
||||
enabledAddons.push(addon);
|
||||
} else {
|
||||
disabledAddons.push(addon);
|
||||
}
|
||||
});
|
||||
|
||||
function compareAddonNames(nameA, nameB) {
|
||||
return String.localeCompare(nameA.name, nameB.name);
|
||||
}
|
||||
enabledAddons.sort(compareAddonNames);
|
||||
disabledAddons.sort(compareAddonNames);
|
||||
|
||||
return enabledAddons.concat(disabledAddons);
|
||||
}
|
||||
|
||||
function isActiveForToggle(addon) {
|
||||
return (addon.isActive && ~~addon.pendingOperations.indexOf("PENDING_DISABLE"));
|
||||
}
|
||||
|
||||
return context.createView({
|
||||
html:
|
||||
"<table>" +
|
||||
" <caption>${header}</caption>" +
|
||||
" <tbody>" +
|
||||
" <tr foreach='addon in ${addons}'" +
|
||||
" class=\"gcli-addon-${addon.status}\">" +
|
||||
" <td>${addon.name} ${addon.version}</td>" +
|
||||
" <td>${addon.pendingOperations}</td>" +
|
||||
" <td>" +
|
||||
" <span class='gcli-out-shortcut'" +
|
||||
" data-command='addon ${addon.toggleActionName} ${addon.label}'" +
|
||||
" onclick='${onclick}' ondblclick='${ondblclick}'" +
|
||||
" >${addon.toggleActionMessage}</span>" +
|
||||
" </td>" +
|
||||
" </tr>" +
|
||||
" </tbody>" +
|
||||
"</table>",
|
||||
data: {
|
||||
header: header,
|
||||
addons: arrangeAddons(addonsInfo.addons).map(function(addon) {
|
||||
return {
|
||||
name: addon.name,
|
||||
label: addon.name.replace(/\s/g, "_") +
|
||||
(addon.version ? "_" + addon.version : ""),
|
||||
status: addon.isActive ? "enabled" : "disabled",
|
||||
version: addon.version,
|
||||
pendingOperations: addon.pendingOperations.length ?
|
||||
(" (" + gcli.lookup("addonPending") + ": "
|
||||
+ addon.pendingOperations.map(lookupOperation).join(", ")
|
||||
+ ")") :
|
||||
"",
|
||||
toggleActionName: isActiveForToggle(addon) ? "disable": "enable",
|
||||
toggleActionMessage: isActiveForToggle(addon) ?
|
||||
gcli.lookup("addonListOutDisable") :
|
||||
gcli.lookup("addonListOutEnable")
|
||||
};
|
||||
}),
|
||||
onclick: context.update,
|
||||
ondblclick: context.updateExec
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "addon enable",
|
||||
description: gcli.lookup("addonEnableDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "addon",
|
||||
type: "addon",
|
||||
description: gcli.lookup("addonNameDesc")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let name = (args.addon.name + " " + args.addon.version).trim();
|
||||
if (args.addon.userDisabled) {
|
||||
args.addon.userDisabled = false;
|
||||
return gcli.lookupFormat("addonEnabled", [ name ]);
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("addonAlreadyEnabled", [ name ]);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "addon disable",
|
||||
description: gcli.lookup("addonDisableDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "addon",
|
||||
type: "addon",
|
||||
description: gcli.lookup("addonNameDesc")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
// If the addon is not disabled or is set to "click to play" then
|
||||
// disable it. Otherwise display the message "Add-on is already
|
||||
// disabled."
|
||||
let name = (args.addon.name + " " + args.addon.version).trim();
|
||||
if (!args.addon.userDisabled ||
|
||||
args.addon.userDisabled === AddonManager.STATE_ASK_TO_ACTIVATE) {
|
||||
args.addon.userDisabled = true;
|
||||
return gcli.lookupFormat("addonDisabled", [ name ]);
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("addonAlreadyDisabled", [ name ]);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,177 @@
|
|||
/* 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 gcli = require("gcli/index");
|
||||
|
||||
loader.lazyImporter(this, "AppCacheUtils", "resource:///modules/devtools/AppCacheUtils.jsm");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "appcache",
|
||||
description: gcli.lookup("appCacheDesc")
|
||||
},
|
||||
{
|
||||
name: "appcache validate",
|
||||
description: gcli.lookup("appCacheValidateDesc"),
|
||||
manual: gcli.lookup("appCacheValidateManual"),
|
||||
returnType: "appcacheerrors",
|
||||
params: [{
|
||||
group: "options",
|
||||
params: [
|
||||
{
|
||||
type: "string",
|
||||
name: "uri",
|
||||
description: gcli.lookup("appCacheValidateUriDesc"),
|
||||
defaultValue: null,
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
let utils;
|
||||
let deferred = context.defer();
|
||||
|
||||
if (args.uri) {
|
||||
utils = new AppCacheUtils(args.uri);
|
||||
} else {
|
||||
utils = new AppCacheUtils(context.environment.document);
|
||||
}
|
||||
|
||||
utils.validateManifest().then(function(errors) {
|
||||
deferred.resolve([errors, utils.manifestURI || "-"]);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "appcacheerrors",
|
||||
to: "view",
|
||||
exec: function([errors, manifestURI], context) {
|
||||
if (errors.length == 0) {
|
||||
return context.createView({
|
||||
html: "<span>" + gcli.lookup("appCacheValidatedSuccessfully") + "</span>"
|
||||
});
|
||||
}
|
||||
|
||||
return context.createView({
|
||||
html:
|
||||
"<div>" +
|
||||
" <h4>Manifest URI: ${manifestURI}</h4>" +
|
||||
" <ol>" +
|
||||
" <li foreach='error in ${errors}'>${error.msg}</li>" +
|
||||
" </ol>" +
|
||||
"</div>",
|
||||
data: {
|
||||
errors: errors,
|
||||
manifestURI: manifestURI
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "appcache clear",
|
||||
description: gcli.lookup("appCacheClearDesc"),
|
||||
manual: gcli.lookup("appCacheClearManual"),
|
||||
exec: function(args, context) {
|
||||
let utils = new AppCacheUtils(args.uri);
|
||||
utils.clearAll();
|
||||
|
||||
return gcli.lookup("appCacheClearCleared");
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "appcache list",
|
||||
description: gcli.lookup("appCacheListDesc"),
|
||||
manual: gcli.lookup("appCacheListManual"),
|
||||
returnType: "appcacheentries",
|
||||
params: [{
|
||||
group: "options",
|
||||
params: [
|
||||
{
|
||||
type: "string",
|
||||
name: "search",
|
||||
description: gcli.lookup("appCacheListSearchDesc"),
|
||||
defaultValue: null,
|
||||
},
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
let utils = new AppCacheUtils();
|
||||
return utils.listEntries(args.search);
|
||||
}
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "appcacheentries",
|
||||
to: "view",
|
||||
exec: function(entries, context) {
|
||||
return context.createView({
|
||||
html: "" +
|
||||
"<ul class='gcli-appcache-list'>" +
|
||||
" <li foreach='entry in ${entries}'>" +
|
||||
" <table class='gcli-appcache-detail'>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListKey") + "</td>" +
|
||||
" <td>${entry.key}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListFetchCount") + "</td>" +
|
||||
" <td>${entry.fetchCount}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListLastFetched") + "</td>" +
|
||||
" <td>${entry.lastFetched}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListLastModified") + "</td>" +
|
||||
" <td>${entry.lastModified}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListExpirationTime") + "</td>" +
|
||||
" <td>${entry.expirationTime}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListDataSize") + "</td>" +
|
||||
" <td>${entry.dataSize}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("appCacheListDeviceID") + "</td>" +
|
||||
" <td>${entry.deviceID} <span class='gcli-out-shortcut' " +
|
||||
"onclick='${onclick}' ondblclick='${ondblclick}' " +
|
||||
"data-command='appcache viewentry ${entry.key}'" +
|
||||
">" + gcli.lookup("appCacheListViewEntry") + "</span>" +
|
||||
" </td>" +
|
||||
" </tr>" +
|
||||
" </table>" +
|
||||
" </li>" +
|
||||
"</ul>",
|
||||
data: {
|
||||
entries: entries,
|
||||
onclick: context.update,
|
||||
ondblclick: context.updateExec
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "appcache viewentry",
|
||||
description: gcli.lookup("appCacheViewEntryDesc"),
|
||||
manual: gcli.lookup("appCacheViewEntryManual"),
|
||||
params: [
|
||||
{
|
||||
type: "string",
|
||||
name: "key",
|
||||
description: gcli.lookup("appCacheViewEntryKey"),
|
||||
defaultValue: null,
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let utils = new AppCacheUtils();
|
||||
return utils.viewEntry(args.key);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,213 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const TargetFactory = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.TargetFactory;
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
loader.lazyGetter(this, "Debugger", () => {
|
||||
let global = Cu.getGlobalForObject({});
|
||||
let JsDebugger = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
|
||||
JsDebugger.addDebuggerToGlobal(global);
|
||||
return global.Debugger;
|
||||
});
|
||||
|
||||
let debuggers = [];
|
||||
let chromeDebuggers = [];
|
||||
let sandboxes = [];
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "calllog",
|
||||
description: gcli.lookup("calllogDesc")
|
||||
},
|
||||
{
|
||||
name: "calllog start",
|
||||
description: gcli.lookup("calllogStartDesc"),
|
||||
|
||||
exec: function(args, context) {
|
||||
let contentWindow = context.environment.window;
|
||||
|
||||
let dbg = new Debugger(contentWindow);
|
||||
dbg.onEnterFrame = function(frame) {
|
||||
// BUG 773652 - Make the output from the GCLI calllog command nicer
|
||||
contentWindow.console.log("Method call: " + this.callDescription(frame));
|
||||
}.bind(this);
|
||||
|
||||
debuggers.push(dbg);
|
||||
|
||||
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "webconsole");
|
||||
|
||||
return gcli.lookup("calllogStartReply");
|
||||
},
|
||||
|
||||
callDescription: function(frame) {
|
||||
let name = "<anonymous>";
|
||||
if (frame.callee.name) {
|
||||
name = frame.callee.name;
|
||||
}
|
||||
else {
|
||||
let desc = frame.callee.getOwnPropertyDescriptor("displayName");
|
||||
if (desc && desc.value && typeof desc.value == "string") {
|
||||
name = desc.value;
|
||||
}
|
||||
}
|
||||
|
||||
let args = frame.arguments.map(this.valueToString).join(", ");
|
||||
return name + "(" + args + ")";
|
||||
},
|
||||
|
||||
valueToString: function(value) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
return uneval(value);
|
||||
}
|
||||
return "[object " + value.class + "]";
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "calllog stop",
|
||||
description: gcli.lookup("calllogStopDesc"),
|
||||
|
||||
exec: function(args, context) {
|
||||
let numDebuggers = debuggers.length;
|
||||
if (numDebuggers == 0) {
|
||||
return gcli.lookup("calllogStopNoLogging");
|
||||
}
|
||||
|
||||
for (let dbg of debuggers) {
|
||||
dbg.onEnterFrame = undefined;
|
||||
}
|
||||
debuggers = [];
|
||||
|
||||
return gcli.lookupFormat("calllogStopReply", [ numDebuggers ]);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "calllog chromestart",
|
||||
description: gcli.lookup("calllogChromeStartDesc"),
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
params: [
|
||||
{
|
||||
name: "sourceType",
|
||||
type: {
|
||||
name: "selection",
|
||||
data: ["content-variable", "chrome-variable", "jsm", "javascript"]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "source",
|
||||
type: "string",
|
||||
description: gcli.lookup("calllogChromeSourceTypeDesc"),
|
||||
manual: gcli.lookup("calllogChromeSourceTypeManual"),
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let globalObj;
|
||||
let contentWindow = context.environment.window;
|
||||
|
||||
if (args.sourceType == "jsm") {
|
||||
try {
|
||||
globalObj = Cu.import(args.source);
|
||||
}
|
||||
catch (e) {
|
||||
return gcli.lookup("callLogChromeInvalidJSM");
|
||||
}
|
||||
} else if (args.sourceType == "content-variable") {
|
||||
if (args.source in contentWindow) {
|
||||
globalObj = Cu.getGlobalForObject(contentWindow[args.source]);
|
||||
} else {
|
||||
throw new Error(gcli.lookup("callLogChromeVarNotFoundContent"));
|
||||
}
|
||||
} else if (args.sourceType == "chrome-variable") {
|
||||
let chromeWin = context.environment.chromeDocument.defaultView;
|
||||
if (args.source in chromeWin) {
|
||||
globalObj = Cu.getGlobalForObject(chromeWin[args.source]);
|
||||
} else {
|
||||
return gcli.lookup("callLogChromeVarNotFoundChrome");
|
||||
}
|
||||
} else {
|
||||
let chromeWin = context.environment.chromeDocument.defaultView;
|
||||
let sandbox = new Cu.Sandbox(chromeWin,
|
||||
{
|
||||
sandboxPrototype: chromeWin,
|
||||
wantXrays: false,
|
||||
sandboxName: "gcli-cmd-calllog-chrome"
|
||||
});
|
||||
let returnVal;
|
||||
try {
|
||||
returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
|
||||
sandboxes.push(sandbox);
|
||||
} catch(e) {
|
||||
// We need to save the message before cleaning up else e contains a dead
|
||||
// object.
|
||||
let msg = gcli.lookup("callLogChromeEvalException") + ": " + e;
|
||||
Cu.nukeSandbox(sandbox);
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (typeof returnVal == "undefined") {
|
||||
return gcli.lookup("callLogChromeEvalNeedsObject");
|
||||
}
|
||||
|
||||
globalObj = Cu.getGlobalForObject(returnVal);
|
||||
}
|
||||
|
||||
let dbg = new Debugger(globalObj);
|
||||
chromeDebuggers.push(dbg);
|
||||
|
||||
dbg.onEnterFrame = function(frame) {
|
||||
// BUG 773652 - Make the output from the GCLI calllog command nicer
|
||||
contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") +
|
||||
": " + this.callDescription(frame));
|
||||
}.bind(this);
|
||||
|
||||
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "webconsole");
|
||||
|
||||
return gcli.lookup("calllogChromeStartReply");
|
||||
},
|
||||
|
||||
valueToString: function(value) {
|
||||
if (typeof value !== "object" || value === null)
|
||||
return uneval(value);
|
||||
return "[object " + value.class + "]";
|
||||
},
|
||||
|
||||
callDescription: function(frame) {
|
||||
let name = frame.callee.name || gcli.lookup("callLogChromeAnonFunction");
|
||||
let args = frame.arguments.map(this.valueToString).join(", ");
|
||||
return name + "(" + args + ")";
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "calllog chromestop",
|
||||
description: gcli.lookup("calllogChromeStopDesc"),
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
exec: function(args, context) {
|
||||
let numDebuggers = chromeDebuggers.length;
|
||||
if (numDebuggers == 0) {
|
||||
return gcli.lookup("calllogChromeStopNoLogging");
|
||||
}
|
||||
|
||||
for (let dbg of chromeDebuggers) {
|
||||
dbg.onEnterFrame = undefined;
|
||||
dbg.enabled = false;
|
||||
}
|
||||
for (let sandbox of sandboxes) {
|
||||
Cu.nukeSandbox(sandbox);
|
||||
}
|
||||
chromeDebuggers = [];
|
||||
sandboxes = [];
|
||||
|
||||
return gcli.lookupFormat("calllogChromeStopReply", [ numDebuggers ]);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,174 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
|
||||
const { Promise: promise } = require("resource://gre/modules/Promise.jsm");
|
||||
|
||||
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
|
||||
const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
loader.lazyGetter(this, "prefBranch", function() {
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
||||
return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "supportsString", function() {
|
||||
return Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
});
|
||||
|
||||
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const PREF_DIR = "devtools.commands.dir";
|
||||
|
||||
/**
|
||||
* Load all the .mozcmd files in the directory pointed to by PREF_DIR
|
||||
* @return A promise of an array of items suitable for gcli.addItems or
|
||||
* using in gcli.addItemsByModule
|
||||
*/
|
||||
function loadItemsFromMozDir() {
|
||||
let dirName = prefBranch.getComplexValue(PREF_DIR,
|
||||
Ci.nsISupportsString).data.trim();
|
||||
if (dirName == "") {
|
||||
return promise.resolve([]);
|
||||
}
|
||||
|
||||
// replaces ~ with the home directory path in unix and windows
|
||||
if (dirName.indexOf("~") == 0) {
|
||||
let dirService = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
let homeDirFile = dirService.get("Home", Ci.nsIFile);
|
||||
let homeDir = homeDirFile.path;
|
||||
dirName = dirName.substr(1);
|
||||
dirName = homeDir + dirName;
|
||||
}
|
||||
|
||||
// statPromise resolves to nothing if dirName is a directory, or it
|
||||
// rejects with an error message otherwise
|
||||
let statPromise = OS.File.stat(dirName);
|
||||
statPromise = statPromise.then(
|
||||
function onSuccess(stat) {
|
||||
if (!stat.isDir) {
|
||||
throw new Error("'" + dirName + "' is not a directory.");
|
||||
}
|
||||
},
|
||||
function onFailure(reason) {
|
||||
if (reason instanceof OS.File.Error && reason.becauseNoSuchFile) {
|
||||
throw new Error("'" + dirName + "' does not exist.");
|
||||
} else {
|
||||
throw reason;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// We need to return (a promise of) an array of items from the *.mozcmd
|
||||
// files in dirName (which we can assume to be a valid directory now)
|
||||
return statPromise.then(() => {
|
||||
let itemPromises = [];
|
||||
|
||||
let iterator = new OS.File.DirectoryIterator(dirName);
|
||||
let iterPromise = iterator.forEach(entry => {
|
||||
if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) {
|
||||
itemPromises.push(loadCommandFile(entry));
|
||||
}
|
||||
});
|
||||
|
||||
return iterPromise.then(() => {
|
||||
iterator.close();
|
||||
return promise.all(itemPromises).then((itemsArray) => {
|
||||
return itemsArray.reduce((prev, curr) => {
|
||||
return prev.concat(curr);
|
||||
}, []);
|
||||
});
|
||||
}, reason => { iterator.close(); throw reason; });
|
||||
});
|
||||
}
|
||||
|
||||
exports.mozDirLoader = function(name) {
|
||||
return loadItemsFromMozDir().then(items => {
|
||||
return { items: items };
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the commands from a single file
|
||||
* @param OS.File.DirectoryIterator.Entry entry The DirectoryIterator
|
||||
* Entry of the file containing the commands that we should read
|
||||
*/
|
||||
function loadCommandFile(entry) {
|
||||
let readPromise = OS.File.read(entry.path);
|
||||
return readPromise = readPromise.then(array => {
|
||||
let decoder = new TextDecoder();
|
||||
let source = decoder.decode(array);
|
||||
var principal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
|
||||
let sandbox = new Cu.Sandbox(principal, {
|
||||
sandboxName: entry.path
|
||||
});
|
||||
let data = Cu.evalInSandbox(source, sandbox, "1.8", entry.name, 1);
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
console.error("Command file '" + entry.name + "' does not have top level array.");
|
||||
return;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "cmd",
|
||||
get hidden() {
|
||||
return !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
description: gcli.lookup("cmdDesc")
|
||||
},
|
||||
{
|
||||
name: "cmd refresh",
|
||||
description: gcli.lookup("cmdRefreshDesc"),
|
||||
get hidden() {
|
||||
return !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
exec: function(args, context) {
|
||||
gcli.load();
|
||||
|
||||
let dirName = prefBranch.getComplexValue(PREF_DIR,
|
||||
Ci.nsISupportsString).data.trim();
|
||||
return gcli.lookupFormat("cmdStatus2", [ dirName ]);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "cmd setdir",
|
||||
description: gcli.lookup("cmdSetdirDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "directory",
|
||||
description: gcli.lookup("cmdSetdirDirectoryDesc"),
|
||||
type: {
|
||||
name: "file",
|
||||
filetype: "directory",
|
||||
existing: "yes"
|
||||
},
|
||||
defaultValue: null
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
get hidden() {
|
||||
return true; // !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
exec: function(args, context) {
|
||||
supportsString.data = args.directory;
|
||||
prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString);
|
||||
|
||||
gcli.load();
|
||||
|
||||
return gcli.lookupFormat("cmdStatus2", [ args.directory ]);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,233 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
const cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
|
||||
|
||||
/**
|
||||
* The cookie 'expires' value needs converting into something more readable
|
||||
*/
|
||||
function translateExpires(expires) {
|
||||
if (expires == 0) {
|
||||
return gcli.lookup("cookieListOutSession");
|
||||
}
|
||||
return new Date(expires).toLocaleString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given cookie matches a given host
|
||||
*/
|
||||
function isCookieAtHost(cookie, host) {
|
||||
if (cookie.host == null) {
|
||||
return host == null;
|
||||
}
|
||||
if (cookie.host.startsWith(".")) {
|
||||
return host.endsWith(cookie.host);
|
||||
}
|
||||
else {
|
||||
return cookie.host == host;
|
||||
}
|
||||
}
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "cookie",
|
||||
description: gcli.lookup("cookieDesc"),
|
||||
manual: gcli.lookup("cookieManual")
|
||||
},
|
||||
{
|
||||
name: "cookie list",
|
||||
description: gcli.lookup("cookieListDesc"),
|
||||
manual: gcli.lookup("cookieListManual"),
|
||||
returnType: "cookies",
|
||||
exec: function(args, context) {
|
||||
let host = context.environment.document.location.host;
|
||||
if (host == null || host == "") {
|
||||
throw new Error(gcli.lookup("cookieListOutNonePage"));
|
||||
}
|
||||
|
||||
let enm = cookieMgr.getCookiesFromHost(host);
|
||||
|
||||
let cookies = [];
|
||||
while (enm.hasMoreElements()) {
|
||||
let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
|
||||
if (isCookieAtHost(cookie, host)) {
|
||||
cookies.push({
|
||||
host: cookie.host,
|
||||
name: cookie.name,
|
||||
value: cookie.value,
|
||||
path: cookie.path,
|
||||
expires: cookie.expires,
|
||||
secure: cookie.secure,
|
||||
httpOnly: cookie.httpOnly,
|
||||
sameDomain: cookie.sameDomain
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return cookies;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "cookie remove",
|
||||
description: gcli.lookup("cookieRemoveDesc"),
|
||||
manual: gcli.lookup("cookieRemoveManual"),
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
description: gcli.lookup("cookieRemoveKeyDesc"),
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let host = context.environment.document.location.host;
|
||||
let enm = cookieMgr.getCookiesFromHost(host);
|
||||
|
||||
let cookies = [];
|
||||
while (enm.hasMoreElements()) {
|
||||
let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
|
||||
if (isCookieAtHost(cookie, host)) {
|
||||
if (cookie.name == args.name) {
|
||||
cookieMgr.remove(cookie.host, cookie.name, cookie.path, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "cookies",
|
||||
to: "view",
|
||||
exec: function(cookies, context) {
|
||||
if (cookies.length == 0) {
|
||||
let host = context.environment.document.location.host;
|
||||
let msg = gcli.lookupFormat("cookieListOutNoneHost", [ host ]);
|
||||
return context.createView({ html: "<span>" + msg + "</span>" });
|
||||
}
|
||||
|
||||
for (let cookie of cookies) {
|
||||
cookie.expires = translateExpires(cookie.expires);
|
||||
|
||||
let noAttrs = !cookie.secure && !cookie.httpOnly && !cookie.sameDomain;
|
||||
cookie.attrs = (cookie.secure ? "secure" : " ") +
|
||||
(cookie.httpOnly ? "httpOnly" : " ") +
|
||||
(cookie.sameDomain ? "sameDomain" : " ") +
|
||||
(noAttrs ? gcli.lookup("cookieListOutNone") : " ");
|
||||
}
|
||||
|
||||
return context.createView({
|
||||
html:
|
||||
"<ul class='gcli-cookielist-list'>" +
|
||||
" <li foreach='cookie in ${cookies}'>" +
|
||||
" <div>${cookie.name}=${cookie.value}</div>" +
|
||||
" <table class='gcli-cookielist-detail'>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("cookieListOutHost") + "</td>" +
|
||||
" <td>${cookie.host}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("cookieListOutPath") + "</td>" +
|
||||
" <td>${cookie.path}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("cookieListOutExpires") + "</td>" +
|
||||
" <td>${cookie.expires}</td>" +
|
||||
" </tr>" +
|
||||
" <tr>" +
|
||||
" <td>" + gcli.lookup("cookieListOutAttributes") + "</td>" +
|
||||
" <td>${cookie.attrs}</td>" +
|
||||
" </tr>" +
|
||||
" <tr><td colspan='2'>" +
|
||||
" <span class='gcli-out-shortcut' onclick='${onclick}'" +
|
||||
" data-command='cookie set ${cookie.name} '" +
|
||||
" >" + gcli.lookup("cookieListOutEdit") + "</span>" +
|
||||
" <span class='gcli-out-shortcut'" +
|
||||
" onclick='${onclick}' ondblclick='${ondblclick}'" +
|
||||
" data-command='cookie remove ${cookie.name}'" +
|
||||
" >" + gcli.lookup("cookieListOutRemove") + "</span>" +
|
||||
" </td></tr>" +
|
||||
" </table>" +
|
||||
" </li>" +
|
||||
"</ul>",
|
||||
data: {
|
||||
options: { allowEval: true },
|
||||
cookies: cookies,
|
||||
onclick: context.update,
|
||||
ondblclick: context.updateExec
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "cookie set",
|
||||
description: gcli.lookup("cookieSetDesc"),
|
||||
manual: gcli.lookup("cookieSetManual"),
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
description: gcli.lookup("cookieSetKeyDesc")
|
||||
},
|
||||
{
|
||||
name: "value",
|
||||
type: "string",
|
||||
description: gcli.lookup("cookieSetValueDesc")
|
||||
},
|
||||
{
|
||||
group: gcli.lookup("cookieSetOptionsDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "path",
|
||||
type: { name: "string", allowBlank: true },
|
||||
defaultValue: "/",
|
||||
description: gcli.lookup("cookieSetPathDesc")
|
||||
},
|
||||
{
|
||||
name: "domain",
|
||||
type: "string",
|
||||
defaultValue: null,
|
||||
description: gcli.lookup("cookieSetDomainDesc")
|
||||
},
|
||||
{
|
||||
name: "secure",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("cookieSetSecureDesc")
|
||||
},
|
||||
{
|
||||
name: "httpOnly",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("cookieSetHttpOnlyDesc")
|
||||
},
|
||||
{
|
||||
name: "session",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("cookieSetSessionDesc")
|
||||
},
|
||||
{
|
||||
name: "expires",
|
||||
type: "string",
|
||||
defaultValue: "Jan 17, 2038",
|
||||
description: gcli.lookup("cookieSetExpiresDesc")
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let host = context.environment.document.location.host;
|
||||
let time = Date.parse(args.expires) / 1000;
|
||||
|
||||
cookieMgr.add(args.domain ? "." + args.domain : host,
|
||||
args.path ? args.path : "/",
|
||||
args.name,
|
||||
args.value,
|
||||
args.secure,
|
||||
args.httpOnly,
|
||||
args.session,
|
||||
time);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,133 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
const XMLHttpRequest = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"];
|
||||
|
||||
loader.lazyImporter(this, "js_beautify", "resource:///modules/devtools/Jsbeautify.jsm");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "jsb",
|
||||
description: gcli.lookup("jsbDesc"),
|
||||
returnValue:"string",
|
||||
params: [
|
||||
{
|
||||
name: "url",
|
||||
type: "string",
|
||||
description: gcli.lookup("jsbUrlDesc")
|
||||
},
|
||||
{
|
||||
group: gcli.lookup("jsbOptionsDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "indentSize",
|
||||
type: "number",
|
||||
description: gcli.lookup("jsbIndentSizeDesc"),
|
||||
manual: gcli.lookup("jsbIndentSizeManual"),
|
||||
defaultValue: 2
|
||||
},
|
||||
{
|
||||
name: "indentChar",
|
||||
type: {
|
||||
name: "selection",
|
||||
lookup: [
|
||||
{ name: "space", value: " " },
|
||||
{ name: "tab", value: "\t" }
|
||||
]
|
||||
},
|
||||
description: gcli.lookup("jsbIndentCharDesc"),
|
||||
manual: gcli.lookup("jsbIndentCharManual"),
|
||||
defaultValue: " ",
|
||||
},
|
||||
{
|
||||
name: "doNotPreserveNewlines",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("jsbDoNotPreserveNewlinesDesc")
|
||||
},
|
||||
{
|
||||
name: "preserveMaxNewlines",
|
||||
type: "number",
|
||||
description: gcli.lookup("jsbPreserveMaxNewlinesDesc"),
|
||||
manual: gcli.lookup("jsbPreserveMaxNewlinesManual"),
|
||||
defaultValue: -1
|
||||
},
|
||||
{
|
||||
name: "jslintHappy",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("jsbJslintHappyDesc"),
|
||||
manual: gcli.lookup("jsbJslintHappyManual")
|
||||
},
|
||||
{
|
||||
name: "braceStyle",
|
||||
type: {
|
||||
name: "selection",
|
||||
data: ["collapse", "expand", "end-expand", "expand-strict"]
|
||||
},
|
||||
description: gcli.lookup("jsbBraceStyleDesc2"),
|
||||
manual: gcli.lookup("jsbBraceStyleManual2"),
|
||||
defaultValue: "collapse"
|
||||
},
|
||||
{
|
||||
name: "noSpaceBeforeConditional",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("jsbNoSpaceBeforeConditionalDesc")
|
||||
},
|
||||
{
|
||||
name: "unescapeStrings",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("jsbUnescapeStringsDesc"),
|
||||
manual: gcli.lookup("jsbUnescapeStringsManual")
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let opts = {
|
||||
indent_size: args.indentSize,
|
||||
indent_char: args.indentChar,
|
||||
preserve_newlines: !args.doNotPreserveNewlines,
|
||||
max_preserve_newlines: args.preserveMaxNewlines == -1 ?
|
||||
undefined : args.preserveMaxNewlines,
|
||||
jslint_happy: args.jslintHappy,
|
||||
brace_style: args.braceStyle,
|
||||
space_before_conditional: !args.noSpaceBeforeConditional,
|
||||
unescape_strings: args.unescapeStrings
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
try {
|
||||
xhr.open("GET", args.url, true);
|
||||
} catch(e) {
|
||||
return gcli.lookup("jsbInvalidURL");
|
||||
}
|
||||
|
||||
let deferred = context.defer();
|
||||
|
||||
xhr.onreadystatechange = function(aEvt) {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200 || xhr.status == 0) {
|
||||
let browserDoc = context.environment.chromeDocument;
|
||||
let browserWindow = browserDoc.defaultView;
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
let result = js_beautify(xhr.responseText, opts);
|
||||
|
||||
browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
|
||||
|
||||
deferred.resolve();
|
||||
} else {
|
||||
deferred.resolve("Unable to load page to beautify: " + args.url + " " +
|
||||
xhr.status + " " + xhr.statusText);
|
||||
}
|
||||
};
|
||||
}
|
||||
xhr.send(null);
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,49 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const gcli = require("gcli/index");
|
||||
const { DebuggerServer } = require("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "listen",
|
||||
description: gcli.lookup("listenDesc"),
|
||||
manual: gcli.lookupFormat("listenManual2", [ BRAND_SHORT_NAME ]),
|
||||
params: [
|
||||
{
|
||||
name: "port",
|
||||
type: "number",
|
||||
get defaultValue() {
|
||||
return Services.prefs.getIntPref("devtools.debugger.chrome-debugging-port");
|
||||
},
|
||||
description: gcli.lookup("listenPortDesc"),
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
var reply = DebuggerServer.openListener(args.port);
|
||||
if (!reply) {
|
||||
throw new Error(gcli.lookup("listenDisabledOutput"));
|
||||
}
|
||||
|
||||
if (DebuggerServer.initialized) {
|
||||
return gcli.lookupFormat("listenInitOutput", [ "" + args.port ]);
|
||||
}
|
||||
|
||||
return gcli.lookup("listenNoInitOutput");
|
||||
},
|
||||
}
|
||||
];
|
|
@ -0,0 +1,47 @@
|
|||
/* 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 gcli = require("gcli/index");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "media",
|
||||
description: gcli.lookup("mediaDesc")
|
||||
},
|
||||
{
|
||||
name: "media emulate",
|
||||
description: gcli.lookup("mediaEmulateDesc"),
|
||||
manual: gcli.lookup("mediaEmulateManual"),
|
||||
params: [
|
||||
{
|
||||
name: "type",
|
||||
description: gcli.lookup("mediaEmulateType"),
|
||||
type: {
|
||||
name: "selection",
|
||||
data: [
|
||||
"braille", "embossed", "handheld", "print", "projection",
|
||||
"screen", "speech", "tty", "tv"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let markupDocumentViewer = context.environment.chromeWindow
|
||||
.gBrowser.markupDocumentViewer;
|
||||
markupDocumentViewer.emulateMedium(args.type);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "media reset",
|
||||
description: gcli.lookup("mediaResetDesc"),
|
||||
manual: gcli.lookup("mediaEmulateManual"),
|
||||
exec: function(args, context) {
|
||||
let markupDocumentViewer = context.environment.chromeWindow
|
||||
.gBrowser.markupDocumentViewer;
|
||||
markupDocumentViewer.stopEmulatingMedium();
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,268 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "pagemod",
|
||||
description: gcli.lookup("pagemodDesc"),
|
||||
},
|
||||
{
|
||||
name: "pagemod replace",
|
||||
description: gcli.lookup("pagemodReplaceDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "search",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodReplaceSearchDesc"),
|
||||
},
|
||||
{
|
||||
name: "replace",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodReplaceReplaceDesc"),
|
||||
},
|
||||
{
|
||||
name: "ignoreCase",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodReplaceIgnoreCaseDesc"),
|
||||
},
|
||||
{
|
||||
name: "selector",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodReplaceSelectorDesc"),
|
||||
defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)",
|
||||
},
|
||||
{
|
||||
name: "root",
|
||||
type: "node",
|
||||
description: gcli.lookup("pagemodReplaceRootDesc"),
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "attrOnly",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodReplaceAttrOnlyDesc"),
|
||||
},
|
||||
{
|
||||
name: "contentOnly",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodReplaceContentOnlyDesc"),
|
||||
},
|
||||
{
|
||||
name: "attributes",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodReplaceAttributesDesc"),
|
||||
defaultValue: null,
|
||||
},
|
||||
],
|
||||
// Make a given string safe to use in a regular expression.
|
||||
escapeRegex: function(aString) {
|
||||
return aString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
},
|
||||
exec: function(args, context) {
|
||||
let searchTextNodes = !args.attrOnly;
|
||||
let searchAttributes = !args.contentOnly;
|
||||
let regexOptions = args.ignoreCase ? "ig" : "g";
|
||||
let search = new RegExp(this.escapeRegex(args.search), regexOptions);
|
||||
let attributeRegex = null;
|
||||
if (args.attributes) {
|
||||
attributeRegex = new RegExp(args.attributes, regexOptions);
|
||||
}
|
||||
|
||||
let root = args.root || context.environment.document;
|
||||
let elements = root.querySelectorAll(args.selector);
|
||||
elements = Array.prototype.slice.call(elements);
|
||||
|
||||
let replacedTextNodes = 0;
|
||||
let replacedAttributes = 0;
|
||||
|
||||
function replaceAttribute() {
|
||||
replacedAttributes++;
|
||||
return args.replace;
|
||||
}
|
||||
function replaceTextNode() {
|
||||
replacedTextNodes++;
|
||||
return args.replace;
|
||||
}
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let element = elements[i];
|
||||
if (searchTextNodes) {
|
||||
for (let y = 0; y < element.childNodes.length; y++) {
|
||||
let node = element.childNodes[y];
|
||||
if (node.nodeType == node.TEXT_NODE) {
|
||||
node.textContent = node.textContent.replace(search, replaceTextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchAttributes) {
|
||||
if (!element.attributes) {
|
||||
continue;
|
||||
}
|
||||
for (let y = 0; y < element.attributes.length; y++) {
|
||||
let attr = element.attributes[y];
|
||||
if (!attributeRegex || attributeRegex.test(attr.name)) {
|
||||
attr.value = attr.value.replace(search, replaceAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("pagemodReplaceResult",
|
||||
[elements.length, replacedTextNodes,
|
||||
replacedAttributes]);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "pagemod remove",
|
||||
description: gcli.lookup("pagemodRemoveDesc"),
|
||||
},
|
||||
{
|
||||
name: "pagemod remove element",
|
||||
description: gcli.lookup("pagemodRemoveElementDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "search",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodRemoveElementSearchDesc"),
|
||||
},
|
||||
{
|
||||
name: "root",
|
||||
type: "node",
|
||||
description: gcli.lookup("pagemodRemoveElementRootDesc"),
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "stripOnly",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodRemoveElementStripOnlyDesc"),
|
||||
},
|
||||
{
|
||||
name: "ifEmptyOnly",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodRemoveElementIfEmptyOnlyDesc"),
|
||||
},
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let root = args.root || context.environment.document;
|
||||
let elements = Array.prototype.slice.call(root.querySelectorAll(args.search));
|
||||
|
||||
let removed = 0;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let element = elements[i];
|
||||
let parentNode = element.parentNode;
|
||||
if (!parentNode || !element.removeChild) {
|
||||
continue;
|
||||
}
|
||||
if (args.stripOnly) {
|
||||
while (element.hasChildNodes()) {
|
||||
parentNode.insertBefore(element.childNodes[0], element);
|
||||
}
|
||||
}
|
||||
if (!args.ifEmptyOnly || !element.hasChildNodes()) {
|
||||
element.parentNode.removeChild(element);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("pagemodRemoveElementResultMatchedAndRemovedElements",
|
||||
[elements.length, removed]);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "pagemod remove attribute",
|
||||
description: gcli.lookup("pagemodRemoveAttributeDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "searchAttributes",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodRemoveAttributeSearchAttributesDesc"),
|
||||
},
|
||||
{
|
||||
name: "searchElements",
|
||||
type: "string",
|
||||
description: gcli.lookup("pagemodRemoveAttributeSearchElementsDesc"),
|
||||
},
|
||||
{
|
||||
name: "root",
|
||||
type: "node",
|
||||
description: gcli.lookup("pagemodRemoveAttributeRootDesc"),
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "ignoreCase",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("pagemodRemoveAttributeIgnoreCaseDesc"),
|
||||
},
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let root = args.root || context.environment.document;
|
||||
let regexOptions = args.ignoreCase ? "ig" : "g";
|
||||
let attributeRegex = new RegExp(args.searchAttributes, regexOptions);
|
||||
let elements = root.querySelectorAll(args.searchElements);
|
||||
elements = Array.prototype.slice.call(elements);
|
||||
|
||||
let removed = 0;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let element = elements[i];
|
||||
if (!element.attributes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var attrs = Array.prototype.slice.call(element.attributes);
|
||||
for (let y = 0; y < attrs.length; y++) {
|
||||
let attr = attrs[y];
|
||||
if (attributeRegex.test(attr.name)) {
|
||||
element.removeAttribute(attr.name);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("pagemodRemoveAttributeResult",
|
||||
[elements.length, removed]);
|
||||
}
|
||||
},
|
||||
// This command allows the user to export the page to HTML after DOM changes
|
||||
{
|
||||
name: "export",
|
||||
description: gcli.lookup("exportDesc"),
|
||||
},
|
||||
{
|
||||
name: "export html",
|
||||
description: gcli.lookup("exportHtmlDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "destination",
|
||||
type: {
|
||||
name: "selection",
|
||||
data: [ "window", "stdout", "clipboard" ]
|
||||
},
|
||||
defaultValue: "window"
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let html = context.environment.document.documentElement.outerHTML;
|
||||
if (args.destination === "stdout") {
|
||||
return html;
|
||||
}
|
||||
|
||||
if (args.desination === "clipboard") {
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
clipboard.copyString(url);
|
||||
return '';
|
||||
}
|
||||
|
||||
let url = "data:text/plain;charset=utf8," + encodeURIComponent(html);
|
||||
context.environment.window.open(url);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,129 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const TargetFactory = require("resource://gre/modules/devtools/Loader.jsm").devtools.TargetFactory;
|
||||
|
||||
const Telemetry = require("devtools/shared/telemetry");
|
||||
const telemetry = new Telemetry();
|
||||
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
function onPaintFlashingChanged(context) {
|
||||
let tab = context.environment.chromeWindow.gBrowser.selectedTab;
|
||||
eventEmitter.emit("changed", tab);
|
||||
function fireChange() {
|
||||
eventEmitter.emit("changed", tab);
|
||||
}
|
||||
let target = TargetFactory.forTab(tab);
|
||||
target.off("navigate", fireChange);
|
||||
target.once("navigate", fireChange);
|
||||
|
||||
let window = context.environment.window;
|
||||
let wUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
if (wUtils.paintFlashing) {
|
||||
telemetry.toolOpened("paintflashing");
|
||||
} else {
|
||||
telemetry.toolClosed("paintflashing");
|
||||
}
|
||||
}
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "paintflashing",
|
||||
description: gcli.lookup("paintflashingDesc")
|
||||
},
|
||||
{
|
||||
name: "paintflashing on",
|
||||
description: gcli.lookup("paintflashingOnDesc"),
|
||||
manual: gcli.lookup("paintflashingManual"),
|
||||
params: [{
|
||||
group: "options",
|
||||
params: [
|
||||
{
|
||||
type: "boolean",
|
||||
name: "chrome",
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
description: gcli.lookup("paintflashingChromeDesc"),
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
let window = args.chrome ?
|
||||
context.environment.chromeWindow :
|
||||
context.environment.window;
|
||||
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.paintFlashing = true;
|
||||
onPaintFlashingChanged(context);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "paintflashing off",
|
||||
description: gcli.lookup("paintflashingOffDesc"),
|
||||
manual: gcli.lookup("paintflashingManual"),
|
||||
params: [{
|
||||
group: "options",
|
||||
params: [
|
||||
{
|
||||
type: "boolean",
|
||||
name: "chrome",
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
description: gcli.lookup("paintflashingChromeDesc"),
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
let window = args.chrome ?
|
||||
context.environment.chromeWindow :
|
||||
context.environment.window;
|
||||
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.paintFlashing = false;
|
||||
onPaintFlashingChanged(context);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "paintflashing toggle",
|
||||
hidden: true,
|
||||
buttonId: "command-button-paintflashing",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
if (aTarget.isLocalTab) {
|
||||
let window = aTarget.tab.linkedBrowser.contentWindow;
|
||||
let wUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
return wUtils.paintFlashing;
|
||||
} else {
|
||||
throw new Error("Unsupported target");
|
||||
}
|
||||
},
|
||||
onChange: function(aTarget, aChangeHandler) {
|
||||
eventEmitter.on("changed", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
eventEmitter.off("changed", aChangeHandler);
|
||||
},
|
||||
},
|
||||
tooltipText: gcli.lookup("paintflashingTooltip"),
|
||||
description: gcli.lookup("paintflashingToggleDesc"),
|
||||
manual: gcli.lookup("paintflashingManual"),
|
||||
exec: function(args, context) {
|
||||
let window = context.environment.window;
|
||||
let wUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
wUtils.paintFlashing = !wUtils.paintFlashing;
|
||||
onPaintFlashingChanged(context);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,60 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
const Services = require("Services");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
/**
|
||||
* Restart command
|
||||
*
|
||||
* @param boolean nocache
|
||||
* Disables loading content from cache upon restart.
|
||||
*
|
||||
* Examples :
|
||||
* >> restart
|
||||
* - restarts browser immediately
|
||||
* >> restart --nocache
|
||||
* - restarts immediately and starts Firefox without using cache
|
||||
*/
|
||||
exports.items = [
|
||||
{
|
||||
name: "restart",
|
||||
description: gcli.lookupFormat("restartBrowserDesc", [ BRAND_SHORT_NAME ]),
|
||||
params: [
|
||||
{
|
||||
name: "nocache",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("restartBrowserNocacheDesc")
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
exec: function Restart(args, context) {
|
||||
let canceled = Cc["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
|
||||
if (canceled.data) {
|
||||
return gcli.lookup("restartBrowserRequestCancelled");
|
||||
}
|
||||
|
||||
// disable loading content from cache.
|
||||
if (args.nocache) {
|
||||
Services.appinfo.invalidateCachesOnRestart();
|
||||
}
|
||||
|
||||
// restart
|
||||
Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Ci.nsIAppStartup)
|
||||
.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
return gcli.lookupFormat("restartBrowserRestarting", [ BRAND_SHORT_NAME ]);
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,236 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
loader.lazyImporter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
|
||||
loader.lazyImporter(this, "LayoutHelpers", "resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
loader.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm");
|
||||
loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
// String used as an indication to generate default file name in the following
|
||||
// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
|
||||
const FILENAME_DEFAULT_VALUE = " ";
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "screenshot",
|
||||
description: gcli.lookup("screenshotDesc"),
|
||||
manual: gcli.lookup("screenshotManual"),
|
||||
returnType: "dom",
|
||||
params: [
|
||||
{
|
||||
name: "filename",
|
||||
type: "string",
|
||||
defaultValue: FILENAME_DEFAULT_VALUE,
|
||||
description: gcli.lookup("screenshotFilenameDesc"),
|
||||
manual: gcli.lookup("screenshotFilenameManual")
|
||||
},
|
||||
{
|
||||
group: gcli.lookup("screenshotGroupOptions"),
|
||||
params: [
|
||||
{
|
||||
name: "clipboard",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("screenshotClipboardDesc"),
|
||||
manual: gcli.lookup("screenshotClipboardManual")
|
||||
},
|
||||
{
|
||||
name: "chrome",
|
||||
type: "boolean",
|
||||
description: gcli.lookupFormat("screenshotChromeDesc2", [BRAND_SHORT_NAME]),
|
||||
manual: gcli.lookupFormat("screenshotChromeManual2", [BRAND_SHORT_NAME])
|
||||
},
|
||||
{
|
||||
name: "delay",
|
||||
type: { name: "number", min: 0 },
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("screenshotDelayDesc"),
|
||||
manual: gcli.lookup("screenshotDelayManual")
|
||||
},
|
||||
{
|
||||
name: "fullpage",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("screenshotFullPageDesc"),
|
||||
manual: gcli.lookup("screenshotFullPageManual")
|
||||
},
|
||||
{
|
||||
name: "selector",
|
||||
type: "node",
|
||||
defaultValue: null,
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
if (args.chrome && args.selector) {
|
||||
// Node screenshot with chrome option does not work as intended
|
||||
// Refer https://bugzilla.mozilla.org/show_bug.cgi?id=659268#c7
|
||||
// throwing for now.
|
||||
throw new Error(gcli.lookup("screenshotSelectorChromeConflict"));
|
||||
}
|
||||
var document = args.chrome? context.environment.chromeDocument
|
||||
: context.environment.document;
|
||||
if (args.delay > 0) {
|
||||
var deferred = context.defer();
|
||||
document.defaultView.setTimeout(() => {
|
||||
this.grabScreen(document, args.filename, args.clipboard,
|
||||
args.fullpage).then(deferred.resolve, deferred.reject);
|
||||
}, args.delay * 1000);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
return this.grabScreen(document, args.filename, args.clipboard,
|
||||
args.fullpage, args.selector);
|
||||
},
|
||||
grabScreen: function(document, filename, clipboard, fullpage, node) {
|
||||
return Task.spawn(function() {
|
||||
let window = document.defaultView;
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let width;
|
||||
let height;
|
||||
let div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
|
||||
|
||||
if (!fullpage) {
|
||||
if (!node) {
|
||||
left = window.scrollX;
|
||||
top = window.scrollY;
|
||||
width = window.innerWidth;
|
||||
height = window.innerHeight;
|
||||
} else {
|
||||
let lh = new LayoutHelpers(window);
|
||||
let rect = lh.getRect(node, window);
|
||||
top = rect.top;
|
||||
left = rect.left;
|
||||
width = rect.width;
|
||||
height = rect.height;
|
||||
}
|
||||
} else {
|
||||
width = window.innerWidth + window.scrollMaxX;
|
||||
height = window.innerHeight + window.scrollMaxY;
|
||||
}
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawWindow(window, left, top, width, height, "#fff");
|
||||
let data = canvas.toDataURL("image/png", "");
|
||||
|
||||
let loadContext = document.defaultView
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
|
||||
if (clipboard) {
|
||||
try {
|
||||
let io = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
let channel = io.newChannel(data, null, null);
|
||||
let input = channel.open();
|
||||
let imgTools = Cc["@mozilla.org/image/tools;1"]
|
||||
.getService(Ci.imgITools);
|
||||
|
||||
let container = {};
|
||||
imgTools.decodeImageData(input, channel.contentType, container);
|
||||
|
||||
let wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
|
||||
.createInstance(Ci.nsISupportsInterfacePointer);
|
||||
wrapped.data = container.value;
|
||||
|
||||
let trans = Cc["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Ci.nsITransferable);
|
||||
trans.init(loadContext);
|
||||
trans.addDataFlavor(channel.contentType);
|
||||
trans.setTransferData(channel.contentType, wrapped, -1);
|
||||
|
||||
let clipid = Ci.nsIClipboard;
|
||||
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
|
||||
clip.setData(trans, null, clipid.kGlobalClipboard);
|
||||
div.textContent = gcli.lookup("screenshotCopied");
|
||||
}
|
||||
catch (ex) {
|
||||
div.textContent = gcli.lookup("screenshotErrorCopying");
|
||||
}
|
||||
throw new Task.Result(div);
|
||||
}
|
||||
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
|
||||
// Create a name for the file if not present
|
||||
if (filename == FILENAME_DEFAULT_VALUE) {
|
||||
let date = new Date();
|
||||
let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
|
||||
"-" + date.getDate();
|
||||
dateString = dateString.split("-").map(function(part) {
|
||||
if (part.length == 1) {
|
||||
part = "0" + part;
|
||||
}
|
||||
return part;
|
||||
}).join("-");
|
||||
let timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
|
||||
filename = gcli.lookupFormat("screenshotGeneratedFilename",
|
||||
[dateString, timeString]) + ".png";
|
||||
}
|
||||
// Check there is a .png extension to filename
|
||||
else if (!filename.match(/.png$/i)) {
|
||||
filename += ".png";
|
||||
}
|
||||
// If the filename is relative, tack it onto the download directory
|
||||
if (!filename.match(/[\\\/]/)) {
|
||||
let preferredDir = yield Downloads.getPreferredDownloadsDirectory();
|
||||
filename = OS.Path.join(preferredDir, filename);
|
||||
}
|
||||
|
||||
try {
|
||||
file.initWithPath(filename);
|
||||
} catch (ex) {
|
||||
div.textContent = gcli.lookup("screenshotErrorSavingToFile") + " " + filename;
|
||||
throw new Task.Result(div);
|
||||
}
|
||||
|
||||
let ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
let Persist = Ci.nsIWebBrowserPersist;
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
||||
.createInstance(Persist);
|
||||
persist.persistFlags = Persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
Persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
let source = ioService.newURI(data, "UTF8", null);
|
||||
persist.saveURI(source, null, null, null, null, file, loadContext);
|
||||
|
||||
div.textContent = gcli.lookup("screenshotSavedToFile") + " \"" + filename +
|
||||
"\"";
|
||||
div.addEventListener("click", function openFile() {
|
||||
div.removeEventListener("click", openFile);
|
||||
file.reveal();
|
||||
});
|
||||
div.style.cursor = "pointer";
|
||||
let image = document.createElement("div");
|
||||
let previewHeight = parseInt(256*height/width);
|
||||
image.setAttribute("style",
|
||||
"width:256px; height:" + previewHeight + "px;" +
|
||||
"max-height: 256px;" +
|
||||
"background-image: url('" + data + "');" +
|
||||
"background-size: 256px " + previewHeight + "px;" +
|
||||
"margin: 4px; display: block");
|
||||
div.appendChild(image);
|
||||
throw new Task.Result(div);
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1,87 @@
|
|||
/* 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 { Cc, Ci, Cu } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { OS } = require("resource://gre/modules/osfile.jsm");
|
||||
const { devtools } = require("resource://gre/modules/devtools/Loader.jsm");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: "tools",
|
||||
description: gcli.lookupFormat("toolsDesc2", [ BRAND_SHORT_NAME ]),
|
||||
manual: gcli.lookupFormat("toolsManual2", [ BRAND_SHORT_NAME ]),
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
},
|
||||
{
|
||||
name: "tools srcdir",
|
||||
description: gcli.lookup("toolsSrcdirDesc"),
|
||||
manual: gcli.lookupFormat("toolsSrcdirManual2", [ BRAND_SHORT_NAME ]),
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
params: [
|
||||
{
|
||||
name: "srcdir",
|
||||
type: "string" /* {
|
||||
name: "file",
|
||||
filetype: "directory",
|
||||
existing: "yes"
|
||||
} */,
|
||||
description: gcli.lookup("toolsSrcdirDir")
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
exec: function(args, context) {
|
||||
let clobber = OS.Path.join(args.srcdir, "CLOBBER");
|
||||
return OS.File.exists(clobber).then(function(exists) {
|
||||
if (exists) {
|
||||
let str = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
str.data = args.srcdir;
|
||||
Services.prefs.setComplexValue("devtools.loader.srcdir",
|
||||
Ci.nsISupportsString, str);
|
||||
devtools.reload();
|
||||
|
||||
let msg = gcli.lookupFormat("toolsSrcdirReloaded", [ args.srcdir ]);
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
return gcli.lookupFormat("toolsSrcdirNotFound", [ args.srcdir ]);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "tools builtin",
|
||||
description: gcli.lookup("toolsBuiltinDesc"),
|
||||
manual: gcli.lookup("toolsBuiltinManual"),
|
||||
get hidden() gcli.hiddenByChromePref(),
|
||||
returnType: "string",
|
||||
exec: function(args, context) {
|
||||
Services.prefs.clearUserPref("devtools.loader.srcdir");
|
||||
devtools.reload();
|
||||
return gcli.lookup("toolsBuiltinReloaded");
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "tools reload",
|
||||
description: gcli.lookup("toolsReloadDesc"),
|
||||
get hidden() {
|
||||
return gcli.hiddenByChromePref() ||
|
||||
!Services.prefs.prefHasUserValue("devtools.loader.srcdir");
|
||||
},
|
||||
|
||||
returnType: "string",
|
||||
exec: function(args, context) {
|
||||
devtools.reload();
|
||||
return gcli.lookup("toolsReloaded2");
|
||||
}
|
||||
}
|
||||
];
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var promise = require('./util/promise');
|
||||
var centralCanon = require('./commands/commands').centralCanon;
|
||||
var connectors = require('./connectors/connectors');
|
||||
var converters = require('./converters/converters');
|
||||
|
@ -33,6 +34,114 @@ exports.getApi = function() {
|
|||
|
||||
settings.startup(types);
|
||||
|
||||
var addItem = function(item) {
|
||||
// Some items are registered using the constructor so we need to check
|
||||
// the prototype for the the type of the item
|
||||
var type = item.item;
|
||||
if (type == null && item.prototype) {
|
||||
type = item.prototype.item;
|
||||
}
|
||||
if (type === 'connector') {
|
||||
connectors.addConnector(item);
|
||||
}
|
||||
else if (type === 'converter') {
|
||||
converters.addConverter(item);
|
||||
}
|
||||
else if (type === 'field') {
|
||||
fields.addField(item);
|
||||
}
|
||||
else if (type === 'language') {
|
||||
languages.addLanguage(item);
|
||||
}
|
||||
else if (type === 'setting') {
|
||||
settings.addSetting(item);
|
||||
}
|
||||
else if (type === 'type') {
|
||||
types.addType(item);
|
||||
}
|
||||
else {
|
||||
canon.addCommand(item);
|
||||
}
|
||||
};
|
||||
|
||||
var removeItem = function(item) {
|
||||
if (item.item === 'connector') {
|
||||
connectors.removeConnector(item);
|
||||
}
|
||||
else if (item.item === 'converter') {
|
||||
converters.removeConverter(item);
|
||||
}
|
||||
else if (item.item === 'field') {
|
||||
fields.removeField(item);
|
||||
}
|
||||
else if (item.item === 'language') {
|
||||
languages.removeLanguage(item);
|
||||
}
|
||||
else if (item.item === 'settings') {
|
||||
settings.removeSetting(types, item);
|
||||
}
|
||||
else if (item.item === 'type') {
|
||||
types.removeType(item);
|
||||
}
|
||||
else {
|
||||
canon.removeCommand(item);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* loadableModules is a lookup of names to module loader functions (like
|
||||
* the venerable 'require') to which we can pass a name and get back a
|
||||
* JS object (or a promise of a JS object). This allows us to have custom
|
||||
* loaders to get stuff from the filesystem etc.
|
||||
*/
|
||||
var loadableModules = {};
|
||||
|
||||
/**
|
||||
* loadedModules is a lookup by name of the things returned by the functions
|
||||
* in loadableModules so we can track what we need to unload / reload.
|
||||
*/
|
||||
var loadedModules = {};
|
||||
|
||||
var unloadModule = function(name) {
|
||||
var existingModule = loadedModules[name];
|
||||
if (existingModule != null) {
|
||||
existingModule.items.forEach(removeItem);
|
||||
}
|
||||
delete loadedModules[name];
|
||||
};
|
||||
|
||||
var loadModule = function(name) {
|
||||
var existingModule = loadedModules[name];
|
||||
unloadModule(name);
|
||||
|
||||
// And load the new items
|
||||
try {
|
||||
var loader = loadableModules[name];
|
||||
return promise.resolve(loader(name)).then(function(newModule) {
|
||||
if (existingModule === newModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newModule == null) {
|
||||
throw 'Module \'' + name + '\' not found';
|
||||
}
|
||||
|
||||
if (newModule.items == null || typeof newModule.items.forEach !== 'function') {
|
||||
console.log('Exported properties: ' + Object.keys(newModule).join(', '));
|
||||
throw 'Module \'' + name + '\' has no \'items\' array export';
|
||||
}
|
||||
|
||||
newModule.items.forEach(addItem);
|
||||
|
||||
loadedModules[name] = newModule;
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
return promise.reject('Failure when loading \'' + name + '\'');
|
||||
}
|
||||
};
|
||||
|
||||
var api = {
|
||||
addCommand: function(item) { return canon.addCommand(item); },
|
||||
removeCommand: function(item) { return canon.removeCommand(item); },
|
||||
|
@ -46,68 +155,49 @@ exports.getApi = function() {
|
|||
removeType: function(item) { return types.removeType(item); },
|
||||
|
||||
addItems: function(items) {
|
||||
items.forEach(function(item) {
|
||||
// Some items are registered using the constructor so we need to check
|
||||
// the prototype for the the type of the item
|
||||
var type = item.item;
|
||||
if (type == null && item.prototype) {
|
||||
type = item.prototype.item;
|
||||
items.forEach(addItem);
|
||||
},
|
||||
|
||||
removeItems: function(items) {
|
||||
items.forEach(removeItem);
|
||||
},
|
||||
|
||||
addItemsByModule: function(names, options) {
|
||||
options = options || {};
|
||||
if (typeof names === 'string') {
|
||||
names = [ names ];
|
||||
}
|
||||
names.forEach(function(name) {
|
||||
if (options.loader == null) {
|
||||
options.loader = function(name) {
|
||||
return require(name);
|
||||
};
|
||||
}
|
||||
if (type === 'command') {
|
||||
canon.addCommand(item);
|
||||
}
|
||||
else if (type === 'connector') {
|
||||
connectors.addConnector(item);
|
||||
}
|
||||
else if (type === 'converter') {
|
||||
converters.addConverter(item);
|
||||
}
|
||||
else if (type === 'field') {
|
||||
fields.addField(item);
|
||||
}
|
||||
else if (type === 'language') {
|
||||
languages.addLanguage(item);
|
||||
}
|
||||
else if (type === 'setting') {
|
||||
settings.addSetting(item);
|
||||
}
|
||||
else if (type === 'type') {
|
||||
types.addType(item);
|
||||
}
|
||||
else {
|
||||
console.error('Error for: ', item);
|
||||
throw new Error('item property not found');
|
||||
loadableModules[name] = options.loader;
|
||||
|
||||
if (!options.delayedLoad) {
|
||||
loadModule(name).then(null, console.error);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeItems: function(items) {
|
||||
items.forEach(function(item) {
|
||||
if (item.item === 'command') {
|
||||
canon.removeCommand(item);
|
||||
}
|
||||
else if (item.item === 'connector') {
|
||||
connectors.removeConnector(item);
|
||||
}
|
||||
else if (item.item === 'converter') {
|
||||
converters.removeConverter(item);
|
||||
}
|
||||
else if (item.item === 'field') {
|
||||
fields.removeField(item);
|
||||
}
|
||||
else if (item.item === 'language') {
|
||||
languages.removeLanguage(item);
|
||||
}
|
||||
else if (item.item === 'settings') {
|
||||
settings.removeSetting(types, item);
|
||||
}
|
||||
else if (item.item === 'type') {
|
||||
types.removeType(item);
|
||||
}
|
||||
else {
|
||||
throw new Error('item property not found');
|
||||
}
|
||||
removeItemsByModule: function(name) {
|
||||
delete loadableModules[name];
|
||||
unloadModule(name);
|
||||
},
|
||||
|
||||
load: function() {
|
||||
// clone loadedModules, so we can remove what is left at the end
|
||||
var modules = Object.keys(loadedModules).map(function(name) {
|
||||
return loadedModules[name];
|
||||
});
|
||||
|
||||
Object.keys(loadableModules).forEach(function(name) {
|
||||
delete modules[name];
|
||||
loadModule(name).then(null, console.error);
|
||||
});
|
||||
|
||||
Object.keys(modules).forEach(unloadModule);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,3 +19,7 @@
|
|||
var Cu = require('chrome').Cu;
|
||||
module.exports = exports =
|
||||
Cu.import('resource://gre/modules/commonjs/sdk/core/promise.js', {}).Promise;
|
||||
|
||||
// When we've solved the debugger/sdk/promise/gcli/helpers/overlap problem then
|
||||
// we should use this instead:
|
||||
// module.exports = exports = require('resource://gre/modules/Promise.jsm').Promise;
|
||||
|
|
Загрузка…
Ссылка в новой задаче