Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-12-14 16:52:20 +00:00
commit 911cab351a
117 changed files with 2682 additions and 1143 deletions

View File

@ -6,8 +6,8 @@
"filename": "gonk.tar.xz"
},
{
"size": 8859648,
"digest": "05d4a99e0f36cd91d1b10a2b558979ea776e9a7e03b8a921af3b0bfc62e2d96cf4faa20586c39885b6f8b25089fe07726794620a3b18c4826a2f71e29d90a8ef",
"size": 8622080,
"digest": "7a2bbf0c76f7b7d5e4b89f758f69b5d8bcf08ec579374877de8939ad69883ab8cd842f04fdaa03a4ef9cdf8170f242e0381dd437e969d5212ead6cdd6f79ab50",
"algorithm": "sha512",
"filename": "boot.img"
}

View File

@ -47,6 +47,7 @@ MOZ_EXTENSION_MANAGER=1
MOZ_SYS_MSG=1
MOZ_TIME_MANAGER=1
MOZ_B2G_CERTDATA=1
MOZ_PAY=1
MOZ_TOOLKIT_SEARCH=
MOZ_PLACES=

View File

@ -89,7 +89,7 @@
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:DevToolbox" oncommand="gDevTools.toggleToolboxCommand(gBrowser);"/>
<command id="Tools:DevToolbox" oncommand="gDevToolsBrowser.toggleToolboxCommand(gBrowser);"/>
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
@ -97,7 +97,7 @@
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
<command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
<command id="Tools:DevToolsConnect" oncommand="DevToolsXULCommands.openConnectScreen(gBrowser)"/>
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)"/>
<command id="Tools:Sanitize"
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
<command id="Tools:PrivateBrowsing"

View File

@ -1462,7 +1462,7 @@ var gBrowserInit = {
}
// Add Devtools menuitems and listeners
gDevTools.registerBrowserWindow(window);
gDevToolsBrowser.registerBrowserWindow(window);
let appMenuButton = document.getElementById("appmenu-button");
let appMenuPopup = document.getElementById("appmenu-popup");
@ -1506,7 +1506,7 @@ var gBrowserInit = {
if (!this._loadHandled)
return;
gDevTools.forgetBrowserWindow(window);
gDevToolsBrowser.forgetBrowserWindow(window);
// First clean up services initialized in gBrowserInit.onLoad (or those whose
// uninit methods don't depend on the services having been initialized).
@ -7297,7 +7297,7 @@ var TabContextMenu = {
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsXULCommands",
XPCOMUtils.defineLazyModuleGetter(this, "gDevToolsBrowser",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {

View File

@ -421,17 +421,11 @@ nsContextMenu.prototype = {
let gBrowser = this.browser.ownerDocument.defaultView.gBrowser;
let imported = {};
Cu.import("resource:///modules/devtools/Target.jsm", imported);
var target = imported.TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
inspector.selection.setNode(this.target);
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
inspector.selection.setNode(this.target, "browser-context-menu");
}.bind(this));
}
let tt = imported.TargetFactory.forTab(gBrowser.selectedTab);
return gDevTools.showToolbox(tt, "inspector").then(function(toolbox) {
let inspector = toolbox.getCurrentPanel();
inspector.selection.setNode(this.target, "browser-context-menu");
}.bind(this));
},
// Set various context menu attributes based on the state of the world.

View File

@ -135,11 +135,13 @@ gcli.addCommand({
}
// Map and sort the add-ons, and create an HTML list.
this.resolve(header +
"<ol>" +
enabledAddons.sort(compareAddonNames).map(representEnabledAddon).join("") +
disabledAddons.sort(compareAddonNames).map(representDisabledAddon).join("") +
"</ol>");
let message = header +
"<ol>" +
enabledAddons.sort(compareAddonNames).map(representEnabledAddon).join("") +
disabledAddons.sort(compareAddonNames).map(representDisabledAddon).join("") +
"</ol>";
this.resolve(context.createView({ html: message }));
}
// Create the promise that will be resolved when the add-on listing has
@ -231,16 +233,15 @@ AddonManager.getAllAddons(function addonAsync(aAddons) {
});
let name = representAddon(addon);
let message = "";
if (!addon.userDisabled) {
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonAlreadyEnabled", [name]) + "]]>");
message = gcli.lookupFormat("addonAlreadyEnabled", [name]);
} else {
addon.userDisabled = false;
// nl-nl: {$1} is ingeschakeld.
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonEnabled", [name]) + "]]>");
message = gcli.lookupFormat("addonEnabled", [name]);
}
this.resolve(message);
}
let promise = context.createPromise();
@ -274,16 +275,15 @@ AddonManager.getAllAddons(function addonAsync(aAddons) {
});
let name = representAddon(addon);
let message = "";
if (addon.userDisabled) {
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonAlreadyDisabled", [name]) + "]]>");
message = gcli.lookupFormat("addonAlreadyDisabled", [name]);
} else {
addon.userDisabled = true;
// nl-nl: {$1} is uitgeschakeld.
this.resolve("<![CDATA[" +
gcli.lookupFormat("addonDisabled", [name]) + "]]>");
message = gcli.lookupFormat("addonDisabled", [name]);
}
this.resolve(message);
}
let promise = context.createPromise();

View File

@ -27,7 +27,6 @@ gcli.addCommand({
manual: gcli.lookup("breakManual")
});
/**
* 'break list' command
*/
@ -36,12 +35,9 @@ gcli.addCommand({
description: gcli.lookup("breaklistDesc"),
returnType: "html",
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("breakaddDebuggerStopped");
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
@ -63,7 +59,6 @@ gcli.addCommand({
}
});
/**
* 'break add' command
*/
@ -84,12 +79,9 @@ gcli.addCommand({
name: "file",
type: {
name: "selection",
data: function() {
let gBrowser = HUDService.currentContext().gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
data: function(args, context) {
let files = [];
let dbg = getPanel(context, "jsdebugger");
if (dbg) {
let sourcesView = dbg.panelWin.DebuggerView.Sources;
for (let item in sourcesView) {
@ -111,23 +103,20 @@ gcli.addCommand({
exec: function(args, context) {
args.type = "line";
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("breakaddDebuggerStopped");
return gcli.lookup("debuggerStopped");
}
var promise = context.createPromise();
var deferred = context.defer();
let position = { url: args.file, line: args.line };
dbg.addBreakpoint(position, function(aBreakpoint, aError) {
if (aError) {
promise.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
return;
}
promise.resolve(gcli.lookup("breakaddAdded"));
deferred.resolve(gcli.lookup("breakaddAdded"));
});
return promise;
return deferred.promise;
}
});
@ -144,15 +133,11 @@ gcli.addCommand({
type: {
name: "number",
min: 0,
max: function() {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (!dbg) {
return gcli.lookup("breakaddDebuggerStopped");
}
return Object.keys(dbg.getAllBreakpoints()).length - 1;
max: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
return dbg == null ?
null :
Object.keys(dbg.getAllBreakpoints()).length - 1;
},
},
description: gcli.lookup("breakdelBreakidDesc")
@ -160,12 +145,9 @@ gcli.addCommand({
],
returnType: "html",
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("breakaddDebuggerStopped");
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
@ -174,15 +156,29 @@ gcli.addCommand({
return gcli.lookup("breakNotFound");
}
let promise = context.createPromise();
let deferred = context.defer();
try {
dbg.removeBreakpoint(breakpoints[id], function() {
promise.resolve(gcli.lookup("breakdelRemoved"));
deferred.resolve(gcli.lookup("breakdelRemoved"));
});
} catch (ex) {
// If the debugger has been closed already, don't scare the user.
promise.resolve(gcli.lookup("breakdelRemoved"));
deferred.resolve(gcli.lookup("breakdelRemoved"));
}
return promise;
return deferred.promise;
}
});
/**
* A helper to go from a command context to a debugger panel
*/
function getPanel(context, id) {
if (context == null) {
return undefined;
}
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox == null ? undefined : toolbox.getPanel(id);
}

View File

@ -55,7 +55,7 @@ gcli.addCommand({
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
gDevTools.showToolbox(target, "webconsole");
return gcli.lookup("calllogStartReply");
},

View File

@ -112,7 +112,7 @@ gcli.addCommand({
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
gDevTools.showToolbox(target, "webconsole");
return gcli.lookup("calllogChromeStartReply");
},

View File

@ -124,6 +124,6 @@ gcli.addCommand({
get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
exec: function Command_cmdRefresh(args, context) {
let chromeWindow = context.environment.chromeDocument.defaultView;
GcliCommands.refreshAutoCommands(chromeWindow);
CmdCommands.refreshAutoCommands(chromeWindow);
}
});

View File

@ -50,7 +50,7 @@ gcli.addCommand({
exec: function Command_consoleClose(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
return gDevTools.closeToolbox(target);
}
});
@ -63,6 +63,6 @@ gcli.addCommand({
exec: function Command_consoleOpen(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
return gDevTools.showToolbox(target, "webconsole");
}
});

View File

@ -33,7 +33,7 @@ gcli.addCommand({
exec: function (args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "jsdebugger");
return gDevTools.showToolbox(target, "jsdebugger");
}
});
@ -47,11 +47,7 @@ gcli.addCommand({
exec: function (args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg /* FIXME: and debugger panel is currently active */) {
gDevTools.closeToolbox(target);
}
return gDevTools.closeToolbox(target);
}
});
@ -63,16 +59,15 @@ gcli.addCommand({
description: gcli.lookup("dbgInterrupt"),
params: [],
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
if (dbg) {
let controller = dbg._controller;
let thread = controller.activeThread;
if (!thread.paused) {
thread.interrupt();
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (!thread.paused) {
thread.interrupt();
}
}
});
@ -85,21 +80,19 @@ gcli.addCommand({
description: gcli.lookup("dbgContinue"),
params: [],
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
if (dbg) {
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.resume();
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.resume();
}
}
});
/**
* 'dbg step' command
*/
@ -109,7 +102,6 @@ gcli.addCommand({
manual: gcli.lookup("dbgStepManual")
});
/**
* 'dbg step over' command
*/
@ -118,16 +110,15 @@ gcli.addCommand({
description: gcli.lookup("dbgStepOverDesc"),
params: [],
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
if (dbg) {
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOver();
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOver();
}
}
});
@ -140,16 +131,15 @@ gcli.addCommand({
description: gcli.lookup("dbgStepInDesc"),
params: [],
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
if (dbg) {
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepIn();
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepIn();
}
}
});
@ -162,16 +152,25 @@ gcli.addCommand({
description: gcli.lookup("dbgStepOutDesc"),
params: [],
exec: function(args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
if (dbg) {
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOut();
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOut();
}
}
});
/**
* A helper to go from a command context to a debugger panel
*/
function getPanel(context, id) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox == null ? undefined : toolbox.getPanel(id);
}

View File

@ -72,6 +72,7 @@ function testCallLogExec() {
typed: "console close",
args: {},
blankOutput: true,
completed: false,
});
});

View File

@ -98,6 +98,7 @@ function testCallLogExec() {
typed: "console close",
args: {},
blankOutput: true,
completed: false,
});
executeSoon(finish);
@ -107,5 +108,6 @@ function testCallLogExec() {
DeveloperToolbarTest.exec({
typed: "calllog chromestart javascript \"({a1: function() {this.a2()},a2: function() {}});\"",
outputMatch: /Call logging started/,
completed: false,
});
}

View File

@ -38,6 +38,7 @@ function testConsole(browser, tab) {
typed: "console open",
args: {},
blankOutput: true,
completed: false,
});
function onExecute() {

View File

@ -46,7 +46,7 @@ function testCommands(dbg, cmd) {
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
ok(!gDevTools.getToolboxForTarget(target),
ok(!gDevTools.getToolbox(target),
"Debugger was closed.");
finish();
});
@ -68,16 +68,22 @@ function testCommands(dbg, cmd) {
}
function testDbgCmd() {
DeveloperToolbarTest.exec({
let output = DeveloperToolbarTest.exec({
typed: "dbg open",
blankOutput: true
blankOutput: true,
completed: false,
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
output.onChange.add(onOpenComplete);
}
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
function onOpenComplete(ev) {
let output = ev.output;
output.onChange.remove(onOpenComplete);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
function cmd(aTyped, aCallback) {

View File

@ -40,9 +40,8 @@ function testBreakCommands() {
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
dbg.once("connected", function() {
// Wait for the initial resume...

View File

@ -11,6 +11,18 @@ let console = (function() {
return tempScope.console;
})();
let TargetFactory = (function() {
let tempScope = {};
Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
return tempScope.TargetFactory;
})();
let Promise = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/commonjs/promise/core.js", tempScope);
return tempScope.Promise;
})();
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
@ -26,17 +38,28 @@ function addTab(aURL, aCallback)
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = aURL;
if (aURL != null) {
content.location = aURL;
}
let deferred = Promise.defer();
let tab = gBrowser.selectedTab;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
aCallback(browser, tab, browser.contentDocument);
if (aCallback != null) {
aCallback(browser, tab, browser.contentDocument);
}
deferred.resolve({ browser: browser, tab: tab, target: target });
}
browser.addEventListener("load", onTabLoad, true);
return deferred.promise;
}
registerCleanupFunction(function tearDown() {

View File

@ -335,10 +335,9 @@ DeveloperToolbarTest.exec = function DTT_exec(tests) {
if (tests.outputMatch) {
var doTest = function(match, against) {
if (!match.test(against)) {
ok(false, "html output for " + typed + " against " + match.source +
info("Actual textContent: '" + against + "'");
ok(false, "mismatched output for " + typed + " against " + match.source +
" (textContent sent to info)");
info("Actual textContent");
info(against);
}
}
if (Array.isArray(tests.outputMatch)) {
@ -353,11 +352,12 @@ DeveloperToolbarTest.exec = function DTT_exec(tests) {
if (tests.blankOutput != null) {
if (!/^$/.test(displayed)) {
ok(false, "html output for " + typed + " (textContent sent to info)");
info("Actual textContent");
info(displayed);
info("Actual textContent: '" + displayed + "'");
ok(false, "non-blank output for " + typed + " (textContent sent to info)");
}
}
return output;
};
/**
@ -446,6 +446,7 @@ DeveloperToolbarTest.test = function DTT_test(uri, target, isGcli) {
target(browser, tab);
}
catch (ex) {
console.error(ex.stack);
ok(false, "" + ex);
DeveloperToolbarTest._finish();
throw ex;

View File

@ -5,62 +5,73 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cu = Components.utils;
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
this.EXPORTED_SYMBOLS = ["DebuggerPanel"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
"resource://gre/modules/devtools/dbg-server.jsm");
function DebuggerPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;
this._toolbox = toolbox;
this._controller = iframeWindow.DebuggerController;
this._view = iframeWindow.DebuggerView;
this._controller = this.panelWin.DebuggerController;
this._view = this.panelWin.DebuggerView;
this._controller._target = this.target;
this._bkp = this._controller.Breakpoints;
this.panelWin = iframeWindow;
this._ensureOnlyOneRunningDebugger();
if (!this.target.isRemote) {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
}
let onDebuggerLoaded = function () {
iframeWindow.removeEventListener("Debugger:Loaded", onDebuggerLoaded, true);
this.setReady();
}.bind(this);
let onDebuggerConnected = function () {
iframeWindow.removeEventListener("Debugger:Connected",
onDebuggerConnected, true);
this.emit("connected");
}.bind(this);
iframeWindow.addEventListener("Debugger:Loaded", onDebuggerLoaded, true);
iframeWindow.addEventListener("Debugger:Connected",
onDebuggerConnected, true);
new EventEmitter(this);
}
DebuggerPanel.prototype = {
/**
* open is effectively an asynchronous constructor
*/
open: function DebuggerPanel_open() {
let deferred = Promise.defer();
this._ensureOnlyOneRunningDebugger();
if (!this.target.isRemote) {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
}
let onDebuggerLoaded = function () {
this.panelWin.removeEventListener("Debugger:Loaded",
onDebuggerLoaded, true);
this._isReady = true;
this.emit("ready");
deferred.resolve(this);
}.bind(this);
let onDebuggerConnected = function () {
this.panelWin.removeEventListener("Debugger:Connected",
onDebuggerConnected, true);
this.emit("connected");
}.bind(this);
this.panelWin.addEventListener("Debugger:Loaded", onDebuggerLoaded, true);
this.panelWin.addEventListener("Debugger:Connected",
onDebuggerConnected, true);
return deferred.promise;
},
// DevToolPanel API
get target() this._toolbox.target,
get isReady() this._isReady,
setReady: function() {
this._isReady = true;
this.emit("ready");
},
destroy: function() {
return Promise.resolve(null);
},
// DebuggerPanel API

View File

@ -637,6 +637,7 @@ StackFrames.prototype = {
let arrow = L10N.getStr("watchExpressionsSeparatorLabel");
let scope = DebuggerView.Variables.addScope(label);
scope.separator = arrow;
scope.showDescriptorTooltip = false;
scope.allowNameInput = true;
scope.allowDeletion = true;
scope.contextMenu = "debuggerWatchExpressionsContextMenu";

View File

@ -1455,8 +1455,12 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
* Called when all the sources have been fetched.
*/
_onFetchSourcesFinished: function DVGS__onFetchSourcesFinished() {
if (!this._sourcesCount) {
return;
}
// All sources are fetched and stored in the cache, we can start searching.
this._performGlobalSearch();
this._sourcesCount = 0;
},
/**

View File

@ -713,7 +713,7 @@ FilterView.prototype = {
*/
clearSearch: function DVF_clearSearch() {
this._searchbox.value = "";
this._onSearch();
this._searchboxPanel.hidePopup();
},
/**
@ -754,6 +754,7 @@ FilterView.prototype = {
if (!found) {
found = true;
view.selectedItem = item;
view.refresh();
}
}
// Item not matched, hide the corresponding node.
@ -766,6 +767,9 @@ FilterView.prototype = {
view.setUnavailable();
}
}
// Synchronize with the view's filtered sources container.
DebuggerView.FilteredSources.syncFileSearch();
this._prevSearchedFile = aFile;
},
@ -778,9 +782,13 @@ FilterView.prototype = {
*/
_performLineSearch: function DVF__performLineSearch(aLine) {
// Don't search for lines if the input hasn't changed.
if (this._prevSearchedLine != aLine && aLine > 0) {
if (this._prevSearchedLine != aLine && aLine) {
DebuggerView.editor.setCaretPosition(aLine - 1);
}
// Can't search for lines and tokens at the same time.
if (this._prevSearchedToken && !aLine) {
this._target.refresh();
}
this._prevSearchedLine = aLine;
},
@ -793,13 +801,17 @@ FilterView.prototype = {
*/
_performTokenSearch: function DVF__performTokenSearch(aToken) {
// Don't search for tokens if the input hasn't changed.
if (this._prevSearchedToken != aToken && aToken.length > 0) {
if (this._prevSearchedToken != aToken && aToken) {
let editor = DebuggerView.editor;
let offset = editor.find(aToken, { ignoreCase: true });
if (offset > -1) {
editor.setSelection(offset, offset + aToken.length)
}
}
// Can't search for tokens and lines at the same time.
if (this._prevSearchedLine && !aToken) {
this._target.refresh();
}
this._prevSearchedToken = aToken;
},
@ -821,6 +833,7 @@ FilterView.prototype = {
// or hide the corresponding pane otherwise.
if (isGlobal) {
DebuggerView.GlobalSearch.scheduleSearch(token);
this._prevSearchedToken = token;
return;
}
@ -828,6 +841,7 @@ FilterView.prototype = {
// variables view instance.
if (isVariable) {
DebuggerView.Variables.scheduleSearch(token);
this._prevSearchedToken = token;
return;
}
@ -845,8 +859,15 @@ FilterView.prototype = {
e.char = String.fromCharCode(e.charCode);
let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
let isDifferentToken, isReturnKey, action = -1;
let isFileSearch, isLineSearch, isDifferentToken, isReturnKey;
let action = -1;
if (file && !line && !token) {
isFileSearch = true;
}
if (line && !token) {
isLineSearch = true;
}
if (this._prevSearchedToken != token) {
isDifferentToken = true;
}
@ -881,13 +902,27 @@ FilterView.prototype = {
DebuggerView.editor.focus();
return;
}
if (action == -1 || (token.length == 0 && line == 0)) {
if (action == -1 || (!file && !line && !token)) {
DebuggerView.FilteredSources.hidden = true;
return;
}
e.preventDefault();
e.stopPropagation();
// Select the next or previous file search entry.
if (isFileSearch) {
if (isReturnKey) {
DebuggerView.FilteredSources.hidden = true;
DebuggerView.editor.focus();
this.clearSearch();
} else {
DebuggerView.FilteredSources[["focusNext", "focusPrev"][action]]();
}
this._prevSearchedFile = file;
return;
}
// Perform a global search based on the specified operator.
if (isGlobal) {
if (isReturnKey && (isDifferentToken || DebuggerView.GlobalSearch.hidden)) {
@ -903,6 +938,7 @@ FilterView.prototype = {
if (isVariable) {
if (isReturnKey && isDifferentToken) {
DebuggerView.Variables.performSearch(token);
} else {
DebuggerView.Variables.expandFirstSearchResults();
}
this._prevSearchedToken = token;
@ -910,7 +946,7 @@ FilterView.prototype = {
}
// Increment or decrement the specified line.
if (!isReturnKey && token.length == 0 && line > 0) {
if (isLineSearch && !isReturnKey) {
line += action == 0 ? 1 : -1;
let lineCount = DebuggerView.editor.getLineCount();
let lineTarget = line < 1 ? 1 : line > lineCount ? lineCount : line;
@ -1010,6 +1046,168 @@ FilterView.prototype = {
_prevSearchedToken: ""
};
/**
* Functions handling the filtered sources UI.
*/
function FilteredSourcesView() {
MenuContainer.call(this);
this._onClick = this._onClick.bind(this);
}
create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
/**
* Initialization function, called when the debugger is started.
*/
initialize: function DVFS_initialize() {
dumpn("Initializing the FilteredSourcesView");
let panel = this._panel = document.createElement("panel");
panel.id = "filtered-sources-panel";
panel.setAttribute("noautofocus", "true");
panel.setAttribute("position", FILTERED_SOURCES_POPUP_POSITION);
document.documentElement.appendChild(panel);
this._searchbox = document.getElementById("searchbox");
this._container = new StackList(panel);
this._container.itemFactory = this._createItemView;
this._container.itemType = "vbox";
this._container.addEventListener("click", this._onClick, false);
},
/**
* Destruction function, called when the debugger is closed.
*/
destroy: function DVFS_destroy() {
dumpn("Destroying the FilteredSourcesView");
document.documentElement.removeChild(this._panel);
this._container.removeEventListener("click", this._onClick, false);
},
/**
* Sets the files container hidden or visible. It's hidden by default.
* @param boolean aFlag
*/
set hidden(aFlag) {
if (aFlag) {
this._container._parent.hidePopup();
} else {
this._container._parent.openPopup(this._searchbox);
}
},
/**
* Updates the list of sources displayed in this container.
*/
syncFileSearch: function DVFS_syncFileSearch() {
this.empty();
// If there's no currently searched file, or there are no matches found,
// hide the popup.
if (!DebuggerView.Filtering.searchedFile ||
!DebuggerView.Sources.visibleItems.length) {
this.hidden = true;
return;
}
// Get the currently visible items in the sources container.
let visibleItems = DebuggerView.Sources.visibleItems;
let displayedItems = visibleItems.slice(0, FILTERED_SOURCES_MAX_RESULTS);
for (let item of displayedItems) {
// Append a location item item to this container.
let trimmedLabel = SourceUtils.trimUrlLength(item.label);
let trimmedValue = SourceUtils.trimUrlLength(item.value);
let locationItem = this.push(trimmedLabel, trimmedValue, {
forced: true,
relaxed: true,
unsorted: true,
attachment: {
fullLabel: item.label,
fullValue: item.value
}
});
let element = locationItem.target;
element.className = "dbg-source-item list-item";
element.labelNode.className = "dbg-source-item-name plain";
element.valueNode.className = "dbg-source-item-details plain";
}
this._updateSelection(this.getItemAtIndex(0));
this.hidden = false;
},
/**
* Focuses the next found match in this container.
*/
focusNext: function DVFS_focusNext() {
let nextIndex = this.selectedIndex + 1;
if (nextIndex >= this.totalItems) {
nextIndex = 0;
}
this._updateSelection(this.getItemAtIndex(nextIndex));
},
/**
* Focuses the previously found match in this container.
*/
focusPrev: function DVFS_focusPrev() {
let prevIndex = this.selectedIndex - 1;
if (prevIndex < 0) {
prevIndex = this.totalItems - 1;
}
this._updateSelection(this.getItemAtIndex(prevIndex));
},
/**
* The click listener for this container.
*/
_onClick: function DVFS__onClick(e) {
let locationItem = this.getItemForElement(e.target);
if (locationItem) {
this._updateSelection(locationItem);
}
},
/**
* Updates the selected item in this container and other views.
*
* @param MenuItem aItem
* The item associated with the element to select.
*/
_updateSelection: function DVFS__updateSelection(aItem) {
this.selectedItem = aItem;
DebuggerView.Filtering._target.selectedValue = aItem.attachment.fullValue;
},
/**
* Customization function for creating an item's UI.
*
* @param string aLabel
* The item's label.
* @param string aValue
* The item's value.
*/
_createItemView: function DVFS__createItemView(aElementNode, aLabel, aValue) {
let labelNode = document.createElement("label");
let valueNode = document.createElement("label");
labelNode.setAttribute("value", aLabel);
valueNode.setAttribute("value", aValue);
aElementNode.appendChild(labelNode);
aElementNode.appendChild(valueNode);
aElementNode.labelNode = labelNode;
aElementNode.valueNode = valueNode;
},
_panel: null,
_searchbox: null
});
/**
* Preliminary setup for the DebuggerView object.
*/
@ -1018,3 +1216,4 @@ DebuggerView.Options = new OptionsView();
DebuggerView.ChromeGlobals = new ChromeGlobalsView();
DebuggerView.Sources = new SourcesView();
DebuggerView.Filtering = new FilterView();
DebuggerView.FilteredSources = new FilteredSourcesView();

View File

@ -11,8 +11,10 @@ const PANES_APPEARANCE_DELAY = 50; // ms
const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "after_start";
const BREAKPOINT_CONDITIONAL_POPUP_OFFSET = 50; // px
const GLOBAL_SEARCH_LINE_MAX_LENGTH = 300; // chars
const FILTERED_SOURCES_POPUP_POSITION = "before_start";
const FILTERED_SOURCES_MAX_RESULTS = 10;
const GLOBAL_SEARCH_EXPAND_MAX_RESULTS = 50;
const GLOBAL_SEARCH_LINE_MAX_LENGTH = 300; // chars
const GLOBAL_SEARCH_ACTION_MAX_DELAY = 1500; // ms
const SEARCH_GLOBAL_FLAG = "!";
const SEARCH_TOKEN_FLAG = "#";
@ -40,6 +42,7 @@ let DebuggerView = {
this.ChromeGlobals.initialize();
this.Sources.initialize();
this.Filtering.initialize();
this.FilteredSources.initialize();
this.StackFrames.initialize();
this.Breakpoints.initialize();
this.WatchExpressions.initialize();
@ -70,6 +73,7 @@ let DebuggerView = {
this.ChromeGlobals.destroy();
this.Sources.destroy();
this.Filtering.destroy();
this.FilteredSources.destroy();
this.StackFrames.destroy();
this.Breakpoints.destroy();
this.WatchExpressions.destroy();
@ -470,6 +474,7 @@ let DebuggerView = {
if (this.editor) {
this.editor.setText("");
this.editor.focus();
this._editorSource = null;
}
},
@ -936,7 +941,7 @@ MenuContainer.prototype = {
},
/**
* Gets the total items in this container.
* Gets the total number of items in this container.
* @return number
*/
get totalItems() {
@ -944,15 +949,17 @@ MenuContainer.prototype = {
},
/**
* Gets the total visible (non-hidden) items in this container.
* @return number
* Returns a list of all the visible (non-hidden) items in this container.
* @return array
*/
get visibleItems() {
let count = 0;
for (let [element] of this._itemsByElement) {
count += element.hidden ? 0 : 1;
let items = [];
for (let [element, item] of this._itemsByElement) {
if (!element.hidden) {
items.push(item);
}
}
return count;
return items;
},
/**
@ -1134,8 +1141,6 @@ MenuContainer.prototype = {
* set itemType(aType:string)
* set itemFactory(aCallback:function)
*
* TODO: Use this in #796135 - "Provide some obvious UI for scripts filtering".
*
* @param nsIDOMNode aAssociatedNode
* The element associated with the displayed container.
*/

View File

@ -219,9 +219,11 @@
tabindex="0"/>
</hbox>
<menulist id="chrome-globals"
class="devtools-menulist" hidden="true"/>
class="devtools-menulist"
sizetopopup="none" hidden="true"/>
<menulist id="sources"
class="devtools-menulist"/>
class="devtools-menulist"
sizetopopup="none"/>
<textbox id="searchbox"
class="devtools-searchinput" type="search"/>
<spacer flex="1"/>

View File

@ -66,6 +66,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_scripts-searching-06.js \
browser_dbg_scripts-searching-07.js \
browser_dbg_scripts-searching-08.js \
browser_dbg_scripts-searching-files_ui.js \
browser_dbg_scripts-searching-popup.js \
browser_dbg_pause-resume.js \
browser_dbg_update-editor-mode.js \

View File

@ -143,9 +143,9 @@ function test()
is(gBreakpointsPane._popupShown, false,
"The breakpoint conditional expression popup should not be shown.");
is(gDebugger.DebuggerView.StackFrames.visibleItems, 0,
is(gDebugger.DebuggerView.StackFrames.visibleItems.length, 0,
"There should be no visible stackframes.");
is(gDebugger.DebuggerView.Breakpoints.visibleItems, 13,
is(gDebugger.DebuggerView.Breakpoints.visibleItems.length, 13,
"There should be thirteen visible breakpoints.");
testReload();
@ -341,7 +341,7 @@ function test()
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gBreakpointsPane.visibleItems != total) {
if (gBreakpointsPane.visibleItems.length != total) {
return;
}
// We got all the breakpoints, it's safe to callback.

View File

@ -9,12 +9,11 @@ function test() {
gBrowser.selectedTab = tab1;
let target1 = TargetFactory.forTab(tab1);
ok(!gDevTools.getPanelForTarget("jsdebugger", target1),
ok(!gDevTools.getToolbox(target1),
"Shouldn't have a debugger panel for this tab yet.");
let toolbox = gDevTools.openToolboxForTab(target1, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target1);
gDevTools.showToolbox(target1, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "We should have a debugger panel.");
let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");

View File

@ -35,27 +35,31 @@ function testSearchbox()
{
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should be hidden at this point.");
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should be found.");
gDebugger.DebuggerView.Variables.disableSearch();
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There shouldn't be a searchbox available after disabling.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should be hidden at this point.");
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should be found.");
let placeholder = "freshly squeezed mango juice";
@ -67,14 +71,16 @@ function testSearchbox()
gDebugger.DebuggerView.Variables.disableSearch();
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There shouldn't be a searchbox available after disabling again.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling again.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should be hidden at this point.");
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"),
placeholder, "There correct placeholder should be applied to the searchbox again.");
@ -83,14 +89,16 @@ function testSearchbox()
gDebugger.DebuggerView.Variables.searchEnabled = false;
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There shouldn't be a searchbox available after disabling again.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should not be found.");
gDebugger.DebuggerView.Variables.searchEnabled = true;
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling again.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should be hidden at this point.");
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"),
placeholder, "There correct placeholder should be applied to the searchbox again.");
@ -98,6 +106,9 @@ function testSearchbox()
function testVariablesFiltering()
{
ok(!gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should not be hidden at this point.");
function test1()
{
write("location");

View File

@ -35,18 +35,23 @@ function testSearchbox()
{
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"The searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should be hidden at this point.");
}
function testVariablesFiltering()
{
ok(!gDebugger.DebuggerView.Variables._searchboxContainer.hidden,
"The searchbox container should not be hidden at this point.");
function test1()
{
write("htmldocument");

View File

@ -36,7 +36,7 @@ function testSearchbox()
{
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should not be found.");
}
@ -53,7 +53,7 @@ function testPref()
executeSoon(function() {
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, true,
"The debugger searchbox should now be preffed as visible.");
@ -66,7 +66,7 @@ function testPref()
executeSoon(function() {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should not be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, false,
"The debugger searchbox should now be preffed as hidden.");

View File

@ -36,7 +36,7 @@ function testSearchbox()
{
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should initially be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should be found.");
}
@ -53,7 +53,7 @@ function testPref()
executeSoon(function() {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(!gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should not be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, false,
"The debugger searchbox should now be preffed as hidden.");
@ -66,7 +66,7 @@ function testPref()
executeSoon(function() {
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
ok(gDebugger.DebuggerView.Variables._parent.parentNode.querySelector(".variables-searchinput.devtools-searchinput"),
"There searchbox element should be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, true,
"The debugger searchbox should now be preffed as visible.");

View File

@ -25,7 +25,6 @@ function test()
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
@ -50,6 +49,7 @@ function test()
}
function testScriptSearching() {
let noMatchingScripts = gDebugger.L10N.getStr("noMatchingScriptsText");
var token;
gDebugger.DebuggerController.activeThread.resume(function() {
@ -135,37 +135,87 @@ function testScriptSearching() {
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (6)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write(":13#" + token);
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (7)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write(":#" + token);
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (8)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("::#" + token);
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (9)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write(":::#" + token);
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (10)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#" + token + ":bogus");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (6)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#" + token + ":13");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (7)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#" + token + ":");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (8)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#" + token + "::");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (9)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#" + token + ":::");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't jump to the correct token. (10)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write(":i am not a number");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't remain at the correct token. (11)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write("#__i do not exist__");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
"The editor didn't remain at the correct token. (12)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
token = "debugger";
@ -173,17 +223,23 @@ function testScriptSearching() {
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44 + token.length,
"The editor didn't jump to the correct token. (12.1)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
clear();
EventUtils.sendKey("RETURN");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44 + token.length,
"The editor shouldn't jump to another token. (12.2)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
EventUtils.sendKey("ENTER");
ok(gEditor.getCaretPosition().line == 2 &&
gEditor.getCaretPosition().col == 44 + token.length,
"The editor shouldn't jump to another token. (12.3)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
write(":1:2:3:a:b:c:::12");
@ -196,7 +252,6 @@ function testScriptSearching() {
gEditor.getCaretPosition().col == 44 + token.length,
"The editor didn't jump to the correct token. (14)");
EventUtils.sendKey("DOWN");
ok(gEditor.getCaretPosition().line == 8 &&
gEditor.getCaretPosition().col == 2 + token.length,
@ -227,8 +282,10 @@ function testScriptSearching() {
ok(gEditor.getCaretPosition().line == 19 &&
gEditor.getCaretPosition().col == 4 + token.length,
"The editor didn't remain at the correct token. (19)");
is(gScripts.visibleItems, 1,
is(gScripts.visibleItems.length, 1,
"Not all the scripts are shown after the search. (20)");
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice that matches are found.");
closeDebuggerAndFinish();
});

View File

@ -27,7 +27,6 @@ function test()
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
@ -79,7 +78,7 @@ function firstSearch() {
ok(gEditor.getCaretPosition().line == 4 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line. (1)");
is(gScripts.visibleItems, 1,
is(gScripts.visibleItems.length, 1,
"Not all the correct scripts are shown after the search. (1)");
secondSearch();
@ -107,7 +106,7 @@ function secondSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 8 + token.length,
"The editor didn't jump to the correct line. (2)");
is(gScripts.visibleItems, 1,
is(gScripts.visibleItems.length, 1,
"Not all the correct scripts are shown after the search. (2)");
waitForFirstScript();
@ -150,7 +149,7 @@ function thirdSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 8 + token.length,
"The editor didn't jump to the correct line. (3)");
is(gScripts.visibleItems, 1,
is(gScripts.visibleItems.length, 1,
"Not all the correct scripts are shown after the search. (3)");
fourthSearch(0, "ugger;", token);
@ -181,7 +180,7 @@ function fourthSearch(i, string, token) {
executeSoon(function() {
let noMatchingScripts = gDebugger.L10N.getStr("noMatchingScriptsText");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the searchbox was emptied.");
is(gMenulist.selectedIndex, 1,
"The menulist should have retained its selected index after the searchbox was emptied.");
@ -193,7 +192,7 @@ function fourthSearch(i, string, token) {
is(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should display a notice that no scripts match the searched token.");
is(gScripts.visibleItems, 0,
is(gScripts.visibleItems.length, 0,
"No scripts should be displayed in the menulist after a bogus search.");
is(gMenulist.selectedIndex, 1,
"The menulist should retain its selected index after a bogus search.");
@ -205,7 +204,7 @@ function fourthSearch(i, string, token) {
isnot(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should not display a notice after the searchbox was emptied.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the searchbox was emptied.");
is(gMenulist.selectedIndex, 1,
"The menulist should have retained its selected index after the searchbox was emptied of a bogus search.");
@ -224,7 +223,7 @@ function noMatchingScriptsSingleCharCheck(token, i) {
is(gMenulist.getAttribute("label"), noMatchingScripts,
"The menulist should display a notice after no matches are found.");
is(gScripts.visibleItems, 0,
is(gScripts.visibleItems.length, 0,
"No scripts should be shown after no matches are found.");
is(gMenulist.selectedIndex, 1,
"The menulist should have retained its selected index after no matches are found.");

View File

@ -86,7 +86,7 @@ function firstSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor shouldn't have jumped to a matching line yet.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the global search.");
let scriptResults = gDebugger.document.querySelectorAll(".dbg-source-results");
@ -202,7 +202,7 @@ function secondSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor shouldn't have jumped to a matching line yet.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the global search.");
let scriptResults = gDebugger.document.querySelectorAll(".dbg-source-results");

View File

@ -86,7 +86,7 @@ function doSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor shouldn't have jumped to a matching line yet.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the global search.");
isnot(gSearchView._container._list.childNodes.length, 0,
@ -120,7 +120,7 @@ function doFirstJump() {
ok(gEditor.getCaretPosition().line == 4 &&
gEditor.getCaretPosition().col == 6,
"The editor didn't jump to the correct line. (1)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (1)");
doSecondJump();
@ -147,7 +147,7 @@ function doSecondJump() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 6,
"The editor didn't jump to the correct line. (2)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (2)");
doWrapAroundJump();
@ -174,7 +174,7 @@ function doWrapAroundJump() {
ok(gEditor.getCaretPosition().line == 4 &&
gEditor.getCaretPosition().col == 6,
"The editor didn't jump to the correct line. (3)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (3)");
doBackwardsWrapAroundJump();
@ -201,7 +201,7 @@ function doBackwardsWrapAroundJump() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 6,
"The editor didn't jump to the correct line. (4)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (4)");
testSearchTokenEmpty();
@ -228,7 +228,7 @@ function testSearchTokenEmpty() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 6,
"The editor didn't remain at the correct line. (5)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (5)");
is(gSearchView._container._list.childNodes.length, 0,

View File

@ -86,7 +86,7 @@ function doSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor shouldn't have jumped to a matching line yet.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the global search.");
isnot(gSearchView._container._list.childNodes.length, 0,

View File

@ -79,7 +79,7 @@ function doSearch() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor shouldn't have jumped to a matching line yet.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the scripts are shown after the global search.");
testSearchMatchNotFound();
@ -106,7 +106,7 @@ function testSearchMatchNotFound() {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't remain at the correct line.");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search.");
closeDebuggerAndFinish();

View File

@ -182,7 +182,7 @@ function testClickLineToJump(scriptResults, callbacks) {
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 4,
"The editor didn't jump to the correct line. (1)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (1)");
callbacks[0](scriptResults, callbacks.slice(1));
@ -217,7 +217,7 @@ function testClickMatchToJump(scriptResults, callbacks) {
ok(gEditor.getCaretPosition().line == 5 &&
gEditor.getCaretPosition().col == 5,
"The editor didn't jump to the correct line. (1)");
is(gScripts.visibleItems, 2,
is(gScripts.visibleItems.length, 2,
"Not all the correct scripts are shown after the search. (1)");
callbacks[0]();

View File

@ -0,0 +1,604 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TAB_URL = EXAMPLE_URL + "browser_dbg_update-editor-mode.html";
/**
* Tests basic functionality of scripts filtering (file search) helper UI.
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gEditor = null;
var gScripts = null;
var gSearchBox = null;
var gFilteredSources = null;
var gMenulist = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
});
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
});
}
function testScriptSearching() {
gEditor = gDebugger.DebuggerView.editor;
gScripts = gDebugger.DebuggerView.Sources;
gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
gFilteredSources = gDebugger.DebuggerView.FilteredSources;
gMenulist = gScripts._container;
firstSearch();
}
function firstSearch() {
window.addEventListener("popupshown", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
for (let i = 0; i < gFilteredSources.totalItems; i++) {
is(gFilteredSources.labels[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.labels[i]),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.values[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.values[i]),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].label,
gDebugger.SourceUtils.trimUrlLength(gScripts.labels[i]),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].value,
gDebugger.SourceUtils.trimUrlLength(gScripts.values[i]),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gScripts.labels[i],
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].attachment.fullValue, gScripts.values[i],
"The filtered sources view should have the correct values.");
}
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("update-editor-mode.html") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
secondSearch();
});
} else {
ok(false, "How did you get here?");
}
});
write(".");
}
function secondSearch() {
let sourceshown = false;
let popupshown = false;
let proceeded = false;
window.addEventListener("Debugger:SourceShown", function _onEvent1(aEvent) {
window.removeEventListener(aEvent.type, _onEvent1);
sourceshown = true;
executeSoon(proceed);
});
window.addEventListener("popupshown", function _onEvent2(aEvent) {
window.removeEventListener(aEvent.type, _onEvent2);
popupshown = true;
executeSoon(proceed);
});
function proceed() {
if (!sourceshown || !popupshown || proceeded) {
return;
}
proceeded = true;
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 1,
"The filtered sources view should have 1 items available.");
is(gFilteredSources.visibleItems.length, 1,
"The filtered sources view should have 1 items visible.");
for (let i = 0; i < gFilteredSources.totalItems; i++) {
is(gFilteredSources.labels[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].label),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.values[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].value),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].label,
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].label),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].value,
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].value),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gScripts.visibleItems[i].label,
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].attachment.fullValue, gScripts.visibleItems[i].value,
"The filtered sources view should have the correct values.");
}
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 1,
"Not all the correct scripts are shown after the search.");
thirdSearch();
});
} else {
ok(false, "How did you get here?");
}
}
append("-0")
}
function thirdSearch() {
let sourceshown = false;
let popupshown = false;
let proceeded = false;
window.addEventListener("Debugger:SourceShown", function _onEvent1(aEvent) {
window.removeEventListener(aEvent.type, _onEvent1);
sourceshown = true;
executeSoon(proceed);
});
window.addEventListener("popupshown", function _onEvent2(aEvent) {
window.removeEventListener(aEvent.type, _onEvent2);
popupshown = true;
executeSoon(proceed);
});
function proceed() {
if (!sourceshown || !popupshown || proceeded) {
return;
}
proceeded = true;
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
for (let i = 0; i < gFilteredSources.totalItems; i++) {
is(gFilteredSources.labels[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].label),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.values[i],
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].value),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].label,
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].label),
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].value,
gDebugger.SourceUtils.trimUrlLength(gScripts.visibleItems[i].value),
"The filtered sources view should have the correct values.");
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gScripts.visibleItems[i].label,
"The filtered sources view should have the correct labels.");
is(gFilteredSources.visibleItems[i].attachment.fullValue, gScripts.visibleItems[i].value,
"The filtered sources view should have the correct values.");
}
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("update-editor-mode.html") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
goDown();
});
} else {
ok(false, "How did you get here?");
}
}
backspace(1)
}
function goDown() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("test-editor-mode") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
goDownAgain();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendKey("DOWN");
}
function goDownAgain() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
goDownAndWrap();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.synthesizeKey("g", { metaKey: true });
}
function goDownAndWrap() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("update-editor-mode.html") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
goUpAndWrap();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.synthesizeKey("n", { ctrlKey: true });
}
function goUpAndWrap() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
clickAndSwitch();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendKey("UP");
}
function clickAndSwitch() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("update-editor-mode.html") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
clickAndSwitchAgain();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendMouseEvent({ type: "click" }, gFilteredSources.visibleItems[0].target);
}
function clickAndSwitchAgain() {
window.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
is(gFilteredSources.totalItems, 3,
"The filtered sources view should have 3 items available.");
is(gFilteredSources.visibleItems.length, 3,
"The filtered sources view should have 3 items visible.");
is(gFilteredSources.selectedValue,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedValue),
"The correct item should be selected in the filtered sources view");
is(gFilteredSources.selectedLabel,
gDebugger.SourceUtils.trimUrlLength(gScripts.selectedLabel),
"The correct item should be selected in the filtered sources view");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
window.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
switchFocusWithEscape();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendMouseEvent({ type: "click" }, gFilteredSources.visibleItems[2].target);
}
function switchFocusWithEscape() {
window.addEventListener("popuphidden", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
focusAgainAfterEscape();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendKey("ESCAPE");
}
function focusAgainAfterEscape() {
window.addEventListener("popupshown", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 1,
"Not all the correct scripts are shown after the search.");
switchFocusWithReturn();
});
} else {
ok(false, "How did you get here?");
}
});
append("0");
}
function switchFocusWithReturn() {
window.addEventListener("popuphidden", function _onEvent(aEvent) {
window.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gScripts.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
let url = gScripts.selectedValue;
if (url.indexOf("test-script-switching-01.js") != -1) {
executeSoon(function() {
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
ok(gEditor.getCaretPosition().line == 0 &&
gEditor.getCaretPosition().col == 0,
"The editor didn't jump to the correct line.");
is(gScripts.visibleItems.length, 3,
"Not all the correct scripts are shown after the search.");
closeDebuggerAndFinish();
});
} else {
ok(false, "How did you get here?");
}
});
EventUtils.sendKey("RETURN");
}
function clear() {
gSearchBox.focus();
gSearchBox.value = "";
}
function write(text) {
clear();
append(text);
}
function backspace(times) {
for (let i = 0; i < times; i++) {
EventUtils.sendKey("BACK_SPACE")
}
}
function append(text) {
gSearchBox.focus();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i]);
}
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gScripts = null;
gSearchBox = null;
gFilteredSources = null;
gMenulist = null;
});

View File

@ -92,23 +92,20 @@ function removeTab(aTab, aWindow) {
function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
let debuggerClosed = false;
let debuggerDisconnected = false;
// let targetWindow = aWindow || window;
ok(gTab, "There is a gTab to use for getting a toolbox reference");
let target = TargetFactory.forTab(gTab);
// let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
window.addEventListener("Debugger:Shutdown", function cleanup() {
window.removeEventListener("Debugger:Shutdown", cleanup, false);
debuggerDisconnected = true;
_maybeFinish();
}, false);
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("destroyed", function() {
let toolbox = gDevTools.getToolbox(target);
toolbox.destroy().then(function() {
debuggerClosed = true;
_maybeFinish();
});
toolbox.destroy();
function _maybeFinish() {
if (debuggerClosed && debuggerDisconnected) {
@ -162,11 +159,13 @@ function attach_thread_actor_for_url(aClient, aURL, aCallback) {
function wait_for_connect_and_resume(aOnDebugging, aTab) {
let target = TargetFactory.forTab(aTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
dbg.once("connected", function dbgConnected() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
aOnDebugging();
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
dbg.once("connected", function dbgConnected() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
aOnDebugging();
});
});
});
}
@ -177,9 +176,9 @@ function debug_tab_pane(aURL, aOnDebugging) {
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
dbg.once("connected", function() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {

View File

@ -4,12 +4,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 Cc = Components.classes;
const Cu = Components.utils;
const Ci = Components.interfaces;
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
this.EXPORTED_SYMBOLS = ["ToolSidebar"];
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -131,7 +130,6 @@ ToolSidebar.prototype = {
}
},
/**
* Toggle sidebar's visibility state.
*/
@ -173,6 +171,11 @@ ToolSidebar.prototype = {
* Clean-up.
*/
destroy: function ToolSidebar_destroy() {
if (this._destroyed) {
return Promise.resolve(null);
}
this._destroyed = true;
this._tabbox.removeEventListener("select", this, true);
while (this._tabbox.tabpanels.hasChildNodes()) {
@ -187,5 +190,7 @@ ToolSidebar.prototype = {
this._tabbox = null;
this._panelDoc = null;
this._toolPanel = null;
return Promise.resolve(null);
},
}

View File

@ -6,10 +6,11 @@
this.EXPORTED_SYMBOLS = [ "TargetFactory" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
const targets = new WeakMap();
@ -184,6 +185,10 @@ TabTarget.prototype = {
return this._tab;
},
get window() {
return this._tab.linkedBrowser.contentWindow;
},
get name() {
return this._tab.linkedBrowser.contentDocument.title;
},
@ -224,24 +229,25 @@ TabTarget.prototype = {
}
},
/**
* Target is not alive anymore.
*/
destroy: function() {
if (this._destroyed) {
return;
}
this.tab.linkedBrowser.removeProgressListener(this._webProgressListener)
this._webProgressListener.target = null;
this._webProgressListener = null;
this.tab.removeEventListener("TabClose", this);
this.tab.parentNode.removeEventListener("TabSelect", this);
this._destroyed = true;
this.emit("close");
if (!this._destroyed) {
this._destroyed = true;
targets.delete(this._tab);
this._tab = null;
this.tab.linkedBrowser.removeProgressListener(this._webProgressListener)
this._webProgressListener.target = null;
this._webProgressListener = null;
this.tab.removeEventListener("TabClose", this);
this.tab.parentNode.removeEventListener("TabSelect", this);
this.emit("close");
targets.delete(this._tab);
this._tab = null;
}
return Promise.resolve(null);
},
toString: function() {
@ -323,6 +329,22 @@ WindowTarget.prototype = {
return false;
},
/**
* Target is not alive anymore.
*/
destroy: function() {
if (!this._destroyed) {
this._destroyed = true;
this.emit("close");
targets.delete(this._window);
this._window = null;
}
return Promise.resolve(null);
},
toString: function() {
return 'WindowTarget:' + this.window;
},
@ -366,17 +388,25 @@ RemoteTarget.prototype = {
* Target is not alive anymore.
*/
destroy: function RT_destroy() {
if (this._destroyed) {
return;
// If several things call destroy then we give them all the same
// destruction promise so we're sure to destroy only once
if (this._destroyer) {
return this._destroyer.promise;
}
this._destroyer = Promise.defer();
this.client.removeListener("tabNavigated", this._onTabNavigated);
this.client.removeListener("tabDetached", this.destroy);
this._client.close(function onClosed() {
this._client = null;
this._destroyed = true;
this.emit("close");
this._destroyer.resolve(null);
}.bind(this));
return this._destroyer.promise;
},
toString: function() {

View File

@ -66,7 +66,8 @@ let webConsoleDefinition = {
return true;
},
build: function(iframeWindow, toolbox) {
return new WebConsolePanel(iframeWindow, toolbox);
let panel = new WebConsolePanel(iframeWindow, toolbox);
return panel.open();
}
};
@ -86,7 +87,8 @@ let debuggerDefinition = {
},
build: function(iframeWindow, toolbox) {
return new DebuggerPanel(iframeWindow, toolbox);
let panel = new DebuggerPanel(iframeWindow, toolbox);
return panel.open();
}
};
@ -105,7 +107,8 @@ let inspectorDefinition = {
},
build: function(iframeWindow, toolbox) {
return new InspectorPanel(iframeWindow, toolbox);
let panel = new InspectorPanel(iframeWindow, toolbox);
return panel.open();
}
};
@ -123,7 +126,8 @@ let styleEditorDefinition = {
},
build: function(iframeWindow, toolbox) {
return new StyleEditorPanel(iframeWindow, toolbox);
let panel = new StyleEditorPanel(iframeWindow, toolbox);
return panel.open();
}
};

View File

@ -8,6 +8,7 @@ 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://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
@ -26,6 +27,70 @@ let CommandOutputManager = require('gcli/canon').CommandOutputManager;
this.EXPORTED_SYMBOLS = [ "Toolbox" ];
// This isn't the best place for this, but I don't know what is right now
/**
* Implementation of 'promised', while we wait for bug 790195 to be fixed.
* @see Consuming promises in https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/api-utils/promise.html
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=790195
* @see https://github.com/mozilla/addon-sdk/blob/master/packages/api-utils/lib/promise.js#L179
*/
Promise.promised = (function() {
// Note: Define shortcuts and utility functions here in order to avoid
// slower property accesses and unnecessary closure creations on each
// call of this popular function.
var call = Function.call;
var concat = Array.prototype.concat;
// Utility function that does following:
// execute([ f, self, args...]) => f.apply(self, args)
function execute(args) { return call.apply(call, args); }
// Utility function that takes promise of `a` array and maybe promise `b`
// as arguments and returns promise for `a.concat(b)`.
function promisedConcat(promises, unknown) {
return promises.then(function(values) {
return Promise.resolve(unknown).then(function(value) {
return values.concat([ value ]);
});
});
}
return function promised(f, prototype) {
/**
Returns a wrapped `f`, which when called returns a promise that resolves to
`f(...)` passing all the given arguments to it, which by the way may be
promises. Optionally second `prototype` argument may be provided to be used
a prototype for a returned promise.
## Example
var promise = promised(Array)(1, promise(2), promise(3))
promise.then(console.log) // => [ 1, 2, 3 ]
**/
return function promised() {
// create array of [ f, this, args... ]
return concat.apply([ f, this ], arguments).
// reduce it via `promisedConcat` to get promised array of fulfillments
reduce(promisedConcat, Promise.resolve([], prototype)).
// finally map that to promise of `f.apply(this, args...)`
then(execute);
};
};
})();
/**
* Convert an array of promises to a single promise, which is resolved (with an
* array containing resolved values) only when all the component promises are
* resolved.
*/
Promise.all = Promise.promised(Array);
/**
* A "Toolbox" is the component that holds all the tools for one specific
* target. Visually, it's a document that includes the tools tabs and all
@ -33,16 +98,15 @@ this.EXPORTED_SYMBOLS = [ "Toolbox" ];
*
* @param {object} target
* The object the toolbox is debugging.
* @param {Toolbox.HostType} hostType
* Type of host that will host the toolbox (e.g. sidebar, window)
* @param {string} selectedTool
* Tool to select initially
* @param {Toolbox.HostType} hostType
* Type of host that will host the toolbox (e.g. sidebar, window)
*/
this.Toolbox = function Toolbox(target, hostType, selectedTool) {
this.Toolbox = function Toolbox(target, selectedTool, hostType) {
this._target = target;
this._toolPanels = new Map();
this._onLoad = this._onLoad.bind(this);
this._toolRegistered = this._toolRegistered.bind(this);
this._toolUnregistered = this._toolUnregistered.bind(this);
this.destroy = this.destroy.bind(this);
@ -105,6 +169,22 @@ Toolbox.prototype = {
return panels;
},
/**
* Access the panel for a given tool
*/
getPanel: function TBOX_getPanel(id) {
return this.getToolPanels().get(id);
},
/**
* This is a shortcut for getPanel(currentToolId) because it is much more
* likely that we're going to want to get the panel that we've just made
* visible
*/
getCurrentPanel: function TBOX_getCurrentPanel() {
return this.getToolPanels().get(this.currentToolId);
},
/**
* Get/alter the target of a Toolbox so we're debugging something different.
* See Target.jsm for more details.
@ -114,10 +194,6 @@ Toolbox.prototype = {
return this._target;
},
set target(value) {
this._target = value;
},
/**
* Get/alter the host of a Toolbox, i.e. is it in browser or in a separate
* tab. See HostType for more details.
@ -126,10 +202,6 @@ Toolbox.prototype = {
return this._host.type;
},
set hostType(value) {
this._switchToHost(value);
},
/**
* Get/alter the currently displayed tool.
*/
@ -159,12 +231,32 @@ Toolbox.prototype = {
* Open the toolbox
*/
open: function TBOX_open() {
this._host.once("ready", function(event, iframe) {
iframe.addEventListener("DOMContentLoaded", this._onLoad, true);
let deferred = Promise.defer();
this._host.open().then(function(iframe) {
let onload = function() {
iframe.removeEventListener("DOMContentLoaded", onload, true);
this.isReady = true;
let closeButton = this.doc.getElementById("toolbox-close");
closeButton.addEventListener("command", this.destroy, true);
this._buildDockButtons();
this._buildTabs();
this._buildButtons(this.frame);
this.selectTool(this._defaultToolId).then(function(panel) {
this.emit("ready");
deferred.resolve();
}.bind(this));
}.bind(this);
iframe.addEventListener("DOMContentLoaded", onload, true);
iframe.setAttribute("src", this._URL);
}.bind(this));
this._host.open();
return deferred.promise;
},
/**
@ -190,33 +282,13 @@ Toolbox.prototype = {
button.id = "toolbox-dock-" + position;
button.className = "toolbox-dock-button";
button.addEventListener("command", function(position) {
this.hostType = position;
this.switchHost(position);
}.bind(this, position));
dockBox.appendChild(button);
}
},
/**
* Onload handler for the toolbox's iframe
*/
_onLoad: function TBOX_onLoad() {
this.frame.removeEventListener("DOMContentLoaded", this._onLoad, true);
this.isReady = true;
let closeButton = this.doc.getElementById("toolbox-close");
closeButton.addEventListener("command", this.destroy, true);
this._buildDockButtons();
this._buildTabs();
this._buildButtons(this.frame);
this.selectTool(this._defaultToolId);
this.emit("ready");
},
/**
* Add tabs to the toolbox UI for registered tools
*/
@ -233,6 +305,10 @@ Toolbox.prototype = {
* The iframe to contain the buttons
*/
_buildButtons: function TBOX_buildButtons(frame) {
if (this.target.isRemote) {
return;
}
let toolbarSpec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
let environment = { chromeDocument: frame.ownerDocument };
let requisition = new Requisition(environment);
@ -292,6 +368,8 @@ Toolbox.prototype = {
* The id of the tool to switch to
*/
selectTool: function TBOX_selectTool(id) {
let deferred = Promise.defer();
if (!this.isReady) {
throw new Error("Can't select tool, wait for toolbox 'ready' event");
}
@ -332,21 +410,17 @@ Toolbox.prototype = {
let boundLoad = function() {
iframe.removeEventListener("DOMContentLoaded", boundLoad, true);
let panel = definition.build(iframe.contentWindow, this);
this._toolPanels.set(id, panel);
let panelReady = function() {
definition.build(iframe.contentWindow, this).then(function(panel) {
this._toolPanels.set(id, panel);
this.emit(id + "-ready", panel);
this.emit("select", id);
this.emit(id + "-selected", panel);
gDevTools.emit(id + "-ready", this, panel);
}.bind(this);
if (panel.isReady) {
panelReady();
} else {
panel.once("ready", panelReady);
}
deferred.resolve(panel);
}.bind(this));
}.bind(this);
iframe.addEventListener("DOMContentLoaded", boundLoad, true);
@ -357,12 +431,15 @@ Toolbox.prototype = {
if (panel) {
this.emit("select", id);
this.emit(id + "-selected", panel);
deferred.resolve(panel);
}
}
Services.prefs.setCharPref(this._prefs.LAST_TOOL, id);
this._currentToolId = id;
return deferred.promise;
},
/**
@ -394,16 +471,15 @@ Toolbox.prototype = {
* @param {string} hostType
* The host type of the new host object
*/
_switchToHost: function TBOX_switchToHost(hostType) {
switchHost: function TBOX_switchHost(hostType) {
if (hostType == this._host.type) {
return;
}
let newHost = this._createHost(hostType);
newHost.once("ready", function(event, iframe) {
return newHost.open().then(function(iframe) {
// change toolbox document's parent to the new host
iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
iframe.swapFrameLoaders(this.frame);
this._host.off("window-closed", this.destroy);
@ -417,8 +493,6 @@ Toolbox.prototype = {
this.emit("host-changed");
}.bind(this));
newHost.open();
},
/**
@ -500,26 +574,38 @@ Toolbox.prototype = {
* Remove all UI elements, detach from target and clear up
*/
destroy: function TBOX_destroy() {
if (this._destroyed) {
return;
// If several things call destroy then we give them all the same
// destruction promise so we're sure to destroy only once
if (this._destroyer) {
return this._destroyer;
}
let outstanding = [];
// Remote targets need to be notified that the toolbox is being torn down.
if (this._target && this._target.isRemote) {
this._target.destroy();
outstanding.push(this._target.destroy());
}
this._target = null;
for (let [id, panel] of this._toolPanels) {
panel.destroy();
outstanding.push(panel.destroy());
}
this._host.destroy();
outstanding.push(this._host.destroy());
gDevTools.off("tool-registered", this._toolRegistered);
gDevTools.off("tool-unregistered", this._toolUnregistered);
this._destroyed = true;
this.emit("destroyed");
this._destroyer = Promise.all(outstanding);
this._destroyer.then(function() {
this.emit("destroyed");
}.bind(this));
return this._destroyer.then(function() {
// Ensure that the promise resolves to nothing, rather than an array of
// several nothings, which is what we get from Promise.all
return undefined;
});
}
};

View File

@ -7,6 +7,7 @@
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
this.EXPORTED_SYMBOLS = [ "Hosts" ];
@ -44,6 +45,8 @@ BottomHost.prototype = {
* Create a box at the bottom of the host tab.
*/
open: function BH_open() {
let deferred = Promise.defer();
let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
let ownerDocument = gBrowser.ownerDocument;
@ -61,6 +64,8 @@ BottomHost.prototype = {
let frameLoad = function() {
this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
@ -69,20 +74,23 @@ BottomHost.prototype = {
this.frame.setAttribute("src", "about:blank");
focusTab(this.hostTab);
return deferred.promise;
},
/**
* Destroy the bottom dock.
*/
destroy: function BH_destroy() {
if (this._destroyed) {
return;
}
this._destroyed = true;
Services.prefs.setIntPref(this.heightPref, this.frame.height);
if (!this._destroyed) {
this._destroyed = true;
this._nbox.removeChild(this._splitter);
this._nbox.removeChild(this.frame);
Services.prefs.setIntPref(this.heightPref, this.frame.height);
this._nbox.removeChild(this._splitter);
this._nbox.removeChild(this.frame);
}
return Promise.resolve(null);
}
}
@ -105,6 +113,8 @@ SidebarHost.prototype = {
* Create a box in the sidebar of the host tab.
*/
open: function RH_open() {
let deferred = Promise.defer();
let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
let ownerDocument = gBrowser.ownerDocument;
@ -122,22 +132,31 @@ SidebarHost.prototype = {
let frameLoad = function() {
this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
this.frame.setAttribute("src", "about:blank");
focusTab(this.hostTab);
return deferred.promise;
},
/**
* Destroy the sidebar.
*/
destroy: function RH_destroy() {
Services.prefs.setIntPref(this.widthPref, this.frame.width);
if (!this._destroyed) {
this._destroyed = true;
this._sidebar.removeChild(this._splitter);
this._sidebar.removeChild(this.frame);
Services.prefs.setIntPref(this.widthPref, this.frame.width);
this._sidebar.removeChild(this._splitter);
this._sidebar.removeChild(this.frame);
}
return Promise.resolve(null);
}
}
@ -159,6 +178,8 @@ WindowHost.prototype = {
* Create a new xul window to contain the toolbox.
*/
open: function WH_open() {
let deferred = Promise.defer();
let flags = "chrome,centerscreen,resizable,dialog=no";
let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
flags, null);
@ -167,6 +188,8 @@ WindowHost.prototype = {
win.removeEventListener("load", frameLoad, true);
this.frame = win.document.getElementById("toolbox-iframe");
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
win.addEventListener("load", frameLoad, true);
@ -175,6 +198,8 @@ WindowHost.prototype = {
win.focus();
this._window = win;
return deferred.promise;
},
/**
@ -193,8 +218,14 @@ WindowHost.prototype = {
* Destroy the window.
*/
destroy: function WH_destroy() {
this._window.removeEventListener("unload", this._boundUnload);
this._window.close();
if (!this._destroyed) {
this._destroyed = true;
this._window.removeEventListener("unload", this._boundUnload);
this._window.close();
}
return Promise.resolve(null);
}
}

View File

@ -95,6 +95,6 @@ function submit() {
function connect(form, chrome=false) {
let target = TargetFactory.forRemote(form, gClient, chrome);
gDevTools.openToolbox(target, Toolbox.HostType.WINDOW, "webconsole");
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
window.close();
}

View File

@ -4,13 +4,13 @@
"use strict";
this.EXPORTED_SYMBOLS = [ "gDevTools", "DevTools", "DevToolsXULCommands" ];
this.EXPORTED_SYMBOLS = [ "gDevTools", "DevTools", "gDevToolsBrowser" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
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://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource:///modules/devtools/ToolDefinitions.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Toolbox",
@ -31,18 +31,11 @@ this.DevTools = function DevTools() {
// destroy() is an observer's handler so we need to preserve context.
this.destroy = this.destroy.bind(this);
this._trackedBrowserWindows = new Set();
// Bind _updateMenuCheckbox() to preserve context.
this._updateMenuCheckbox = this._updateMenuCheckbox.bind(this);
new EventEmitter(this);
Services.obs.addObserver(this.destroy, "quit-application", false);
/**
* Register the set of default tools
*/
// Register the set of default tools
for (let definition of defaultTools) {
this.registerTool(definition);
}
@ -80,11 +73,9 @@ DevTools.prototype = {
}
toolDefinition.killswitch = toolDefinition.killswitch ||
"devtools." + toolId + ".enabled";
"devtools." + toolId + ".enabled";
this._tools.set(toolId, toolDefinition);
this._addToolToWindows(toolDefinition);
this.emit("tool-registered", toolId);
},
@ -98,8 +89,6 @@ DevTools.prototype = {
unregisterTool: function DT_unregisterTool(toolId) {
this._tools.delete(toolId);
this._removeToolFromWindows(toolId);
this.emit("tool-unregistered", toolId);
},
@ -130,104 +119,72 @@ DevTools.prototype = {
},
/**
* Create a toolbox to debug |target| using a window displayed in |hostType|
* (optionally with |defaultToolId| opened)
* Show a Toolbox for a target (either by creating a new one, or if a toolbox
* already exists for the target, by bring to the front the existing one)
* If |toolId| is specified then the displayed toolbox will have the
* specified tool selected.
* If |hostType| is specified then the toolbox will be displayed using the
* specified HostType.
*
* @param {Target} target
* The target the toolbox will debug
* @param {string} toolId
* The id of the tool to show
* @param {Toolbox.HostType} hostType
* The type of host (bottom, top, side)
* @param {string} defaultToolId
* The id of the initial tool to show
* The type of host (bottom, window, side)
*
* @return {Toolbox} toolbox
* The toolbox that was opened
*/
openToolbox: function DT_openToolbox(target, hostType, defaultToolId) {
if (this._toolboxes.has(target)) {
// only allow one toolbox per target
return this._toolboxes.get(target);
}
showToolbox: function(target, toolId, hostType) {
let deferred = Promise.defer();
let tb = new Toolbox(target, hostType, defaultToolId);
this._toolboxes.set(target, tb);
tb.once("destroyed", function() {
this._toolboxes.delete(target);
this._updateMenuCheckbox();
this.emit("toolbox-destroyed", target);
}.bind(this));
tb.once("ready", function() {
this.emit("toolbox-ready", tb);
this._updateMenuCheckbox();
}.bind(this));
tb.open();
return tb;
},
/**
* Close the toolbox for a given target
*/
closeToolbox: function DT_closeToolbox(target) {
let toolbox = this._toolboxes.get(target);
if (toolbox == null) {
return;
if (toolbox) {
let promise = (hostType != null && toolbox.hostType != hostType) ?
toolbox.switchHost(hostType) :
Promise.resolve(null);
if (toolId != null && toolbox.currentToolId != toolId) {
promise = promise.then(function() {
return toolbox.selectTool(toolId);
});
}
return promise.then(function() {
return toolbox;
});
}
toolbox.destroy();
},
else {
// No toolbox for target, create one
toolbox = new Toolbox(target, toolId, hostType);
/**
* Open the toolbox for a specific target (not tab).
* FIXME: We should probably merge this function and openToolbox
*
* @param {Target} target
* The target that the toolbox should be debugging
* @param {String} toolId
* The id of the tool to open
*
* @return {Toolbox} toolbox
* The toolbox that has been opened
*/
openToolboxForTab: function DT_openToolboxForTab(target, toolId) {
let tb = this.getToolboxForTarget(target);
this._toolboxes.set(target, toolbox);
if (tb) {
tb.selectTool(toolId);
} else {
tb = this.openToolbox(target, null, toolId);
toolbox.once("destroyed", function() {
this._toolboxes.delete(target);
this.emit("toolbox-destroyed", target);
}.bind(this));
// If we were asked for a specific tool then we need to wait for the
// tool to be ready, otherwise we can just wait for toolbox open
if (toolId != null) {
toolbox.once(toolId + "-ready", function(event, panel) {
this.emit("toolbox-ready", toolbox);
deferred.resolve(toolbox);
}.bind(this));
toolbox.open();
}
else {
toolbox.open().then(function() {
deferred.resolve(toolbox);
this.emit("toolbox-ready", toolbox);
}.bind(this));
}
}
return tb;
},
/**
* This function is for the benefit of command#Tools:DevToolbox in
* browser/base/content/browser-sets.inc and should not be used outside
* of there
*/
toggleToolboxCommand: function(gBrowser, toolId=null) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
this.toggleToolboxForTarget(target, toolId);
},
/**
* Toggle a toolbox for the given target.
*
* @param {Target} target
* The target the toolbox is debugging
* @param {string} toolId
* The id of the tool to show in the toolbox, if it's to be opened.
*/
toggleToolboxForTarget: function DT_toggleToolboxForTarget(target, toolId) {
let tb = this.getToolboxForTarget(target);
if (tb /* FIXME: && tool is showing */ ) {
tb.destroy();
} else {
this.openToolboxForTab(target, toolId);
}
return deferred.promise;
},
/**
@ -239,41 +196,86 @@ DevTools.prototype = {
* @return {Toolbox} toolbox
* The toobox that is debugging the given target
*/
getToolboxForTarget: function DT_getToolboxForTarget(target) {
getToolbox: function DT_getToolbox(target) {
return this._toolboxes.get(target);
},
/**
* Return a tool panel for a given tool and target.
*
* @param {String} toolId
* The id of the tool to open.
* @param {object} target
* The toolbox's target.
*
* @return {ToolPanel} panel
* Panel for the tool with the toolid
* Close the toolbox for a given target
*/
getPanelForTarget: function DT_getPanelForTarget(toolId, target) {
let toolbox = this.getToolboxForTarget(target);
if (!toolbox) {
return undefined;
closeToolbox: function DT_closeToolbox(target) {
let toolbox = this._toolboxes.get(target);
if (toolbox == null) {
return;
}
return toolbox.getToolPanels().get(toolId);
return toolbox.destroy();
},
/**
* All browser windows have been closed, tidy up remaining objects.
*/
destroy: function() {
Services.obs.removeObserver(this.destroy, "quit-application");
delete this._trackedBrowserWindows;
delete this._toolboxes;
},
};
/**
* gDevTools is a singleton that controls the Firefox Developer Tools.
*
* It is an instance of a DevTools class that holds a set of tools. It has the
* same lifetime as the browser.
*/
let gDevTools = new DevTools();
this.gDevTools = gDevTools;
/**
* gDevToolsBrowser exposes functions to connect the gDevTools instance with a
* Firefox instance.
*/
let gDevToolsBrowser = {
/**
* A record of the windows whose menus we altered, so we can undo the changes
* as the window is closed
*/
_trackedBrowserWindows: new Set(),
/**
* This function is for the benefit of command#Tools:DevToolbox in
* browser/base/content/browser-sets.inc and should not be used outside
* of there
*/
toggleToolboxCommand: function(gBrowser, toolId=null) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox && (toolId == null || toolId == toolbox.currentToolId) ?
toolbox.destroy() :
gDevTools.showToolbox(target, toolId);
},
/**
* Open a tab to allow connects to a remote browser
*/
openConnectScreen: function(gBrowser) {
gBrowser.selectedTab = gBrowser.addTab("chrome://browser/content/devtools/connect.xhtml");
},
/**
* Add this DevTools's presence to a browser window's document
*
* @param {XULDocument} doc
* The document to which menuitems and handlers are to be added
* @param {XULDocument} doc
* The document to which menuitems and handlers are to be added
*/
registerBrowserWindow: function DT_registerBrowserWindow(win) {
this._trackedBrowserWindows.add(win);
this._addAllToolsToMenu(win.document);
gDevToolsBrowser._trackedBrowserWindows.add(win);
gDevToolsBrowser._addAllToolsToMenu(win.document);
let tabContainer = win.document.getElementById("tabbrowser-tabs")
tabContainer.addEventListener("TabSelect", this._updateMenuCheckbox, false);
tabContainer.addEventListener("TabSelect",
gDevToolsBrowser._updateMenuCheckbox, false);
},
/**
@ -283,8 +285,8 @@ DevTools.prototype = {
* properties of the tool to add
*/
_addToolToWindows: function DT_addToolToWindows(toolDefinition) {
for (let win of this._trackedBrowserWindows) {
this._addToolToMenu(toolDefinition, win.document);
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
gDevToolsBrowser._addToolToMenu(toolDefinition, win.document);
}
},
@ -301,8 +303,8 @@ DevTools.prototype = {
let fragAppMenuItems = doc.createDocumentFragment();
let fragMenuItems = doc.createDocumentFragment();
for (let [key, toolDefinition] of this._tools) {
let frags = this._addToolToMenu(toolDefinition, doc, true);
for (let [key, toolDefinition] of gDevTools._tools) {
let frags = gDevToolsBrowser._addToolToMenu(toolDefinition, doc, true);
if (!frags) {
return;
@ -361,7 +363,7 @@ DevTools.prototype = {
let cmd = doc.createElement("command");
cmd.id = "Tools:" + id;
cmd.setAttribute("oncommand",
'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
'gDevToolsBrowser.toggleToolboxCommand(gBrowser, "' + id + '");');
let key = null;
if (toolDefinition.key) {
@ -375,7 +377,7 @@ DevTools.prototype = {
}
key.setAttribute("oncommand",
'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
'gDevToolsBrowser.toggleToolboxCommand(gBrowser, "' + id + '");');
key.setAttribute("modifiers", toolDefinition.modifiers);
}
@ -431,12 +433,12 @@ DevTools.prototype = {
* called when a toolbox is created or destroyed.
*/
_updateMenuCheckbox: function DT_updateMenuCheckbox() {
for (let win of this._trackedBrowserWindows) {
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
let hasToolbox = false;
if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) {
let target = TargetFactory.forTab(win.gBrowser.selectedTab);
if (this._toolboxes.has(target)) {
if (gDevTools._toolboxes.has(target)) {
hasToolbox = true;
}
}
@ -457,8 +459,8 @@ DevTools.prototype = {
* id of the tool to remove
*/
_removeToolFromWindows: function DT_removeToolFromWindows(toolId) {
for (let win of this._trackedBrowserWindows) {
this._removeToolFromMenu(toolId, win.document);
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
gDevToolsBrowser._removeToolFromMenu(toolId, win.document);
}
},
@ -481,13 +483,6 @@ DevTools.prototype = {
let bc = doc.getElementById("devtoolsMenuBroadcaster_" + toolId);
bc.parentNode.removeChild(bc);
/*
// FIXME: item is null in testing. This is the only place to use
// "appmenu_devToolbar" + toolId, so it seems clear that this is wrong
let item = doc.getElementById("appmenu_devToolbar" + toolId);
item.parentNode.removeChild(item);
*/
},
/**
@ -498,14 +493,14 @@ DevTools.prototype = {
* The window containing the menu entry
*/
forgetBrowserWindow: function DT_forgetBrowserWindow(win) {
if (!this._tools) {
if (!gDevToolsBrowser._trackedBrowserWindows) {
return;
}
this._trackedBrowserWindows.delete(win);
gDevToolsBrowser._trackedBrowserWindows.delete(win);
// Destroy toolboxes for closed window
for (let [target, toolbox] of this._toolboxes) {
for (let [target, toolbox] of gDevTools._toolboxes) {
if (toolbox.frame.ownerDocument.defaultView == win) {
toolbox.destroy();
}
@ -513,34 +508,29 @@ DevTools.prototype = {
let tabContainer = win.document.getElementById("tabbrowser-tabs")
tabContainer.removeEventListener("TabSelect",
this._updateMenuCheckbox, false);
gDevToolsBrowser._updateMenuCheckbox, false);
},
/**
* All browser windows have been closed, tidy up remaining objects.
*/
destroy: function() {
Services.obs.removeObserver(this.destroy, "quit-application");
delete this._trackedBrowserWindows;
delete this._tools;
delete this._toolboxes;
},
};
/**
* gDevTools is a singleton that controls the Firefox Developer Tools.
*
* It is an instance of a DevTools class that holds a set of tools. It has the
* same lifetime as the browser.
*/
this.gDevTools = new DevTools();
/**
* DevToolsXULCommands exposes methods used by browser's <command>s.
*/
this.DevToolsXULCommands = {
openConnectScreen: function(gBrowser) {
gBrowser.selectedTab = gBrowser.addTab("chrome://browser/content/devtools/connect.xhtml");
Services.obs.removeObserver(gDevToolsBrowser.destroy, "quit-application");
delete gDevToolsBrowser._trackedBrowserWindows;
},
}
this.gDevToolsBrowser = gDevToolsBrowser;
gDevTools.on("tool-registered", function(ev, toolId) {
let toolDefinition = gDevTools._tools.get(toolId);
gDevToolsBrowser._addToolToWindows(toolDefinition);
});
gDevTools.on("tool-unregistered", function(ev, toolId) {
gDevToolsBrowser._removeToolFromWindows(toolId);
});
gDevTools.on("toolbox-ready", gDevToolsBrowser._updateMenuCheckbox);
gDevTools.on("toolbox-destroyed", gDevToolsBrowser._updateMenuCheckbox);
Services.obs.addObserver(gDevToolsBrowser.destroy, "quit-application", false);

View File

@ -27,7 +27,7 @@ function runTests(aTab) {
label: "someLabel",
build: function(iframeWindow, toolbox) {
let panel = new DevToolPanel(iframeWindow, toolbox);
return panel;
return panel.open();
},
};
@ -40,36 +40,15 @@ function runTests(aTab) {
"The tool is registered");
let target = TargetFactory.forTab(gBrowser.selectedTab);
function onNewToolbox(event, toolboxFromEvent) {
let toolBoxes = gDevTools._toolboxes;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let tb = toolBoxes.get(target);
is(toolboxFromEvent, tb, "'toolbox-ready' event fired. Correct toolbox value.");
is(tb.target, target, "toolbox target is correct");
is(tb._host.hostTab, gBrowser.selectedTab, "toolbox host is correct");
gDevTools.once(toolId + "-ready", continueTests);
}
function onToolboxClosed(event, targetFromEvent) {
is(targetFromEvent, target, "'toolbox-destroyed' event fired. Correct tab value.");
finishUp();
}
gDevTools.once("toolbox-ready", onNewToolbox);
gDevTools.once("toolbox-destroyed", onToolboxClosed);
executeSoon(function() {
gDevTools.openToolbox(target, "bottom", toolId);
});
gDevTools.showToolbox(target, toolId).then(function(toolbox) {
is(toolbox.target, target, "toolbox target is correct");
is(toolbox._host.hostTab, gBrowser.selectedTab, "toolbox host is correct");
continueTests(toolbox);
}).then(null, console.error);
}
function continueTests(event, toolbox, panel) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
is(toolbox, gDevTools._toolboxes.get(target), "{toolId}-ready event received, with correct toolbox value");
is(panel, toolbox.getToolPanels().get(toolId), "panel value is correct");
function continueTests(toolbox, panel) {
ok(toolbox.getCurrentPanel(), "panel value is correct");
is(toolbox.currentToolId, toolId, "toolbox _currentToolId is correct");
let toolDefinitions = gDevTools.getToolDefinitions();
@ -82,7 +61,13 @@ function continueTests(event, toolbox, panel) {
is(gDevTools.getToolDefinitions().has(toolId), false,
"The tool is no longer registered");
toolbox.destroy();
toolbox.destroy().then(function() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
ok(gDevTools._toolboxes.get(target) == null, "gDevTools doesn't know about target");
ok(toolbox._target == null, "toolbox doesn't know about target.");
finishUp();
}).then(null, console.error);
}
function finishUp() {
@ -110,13 +95,21 @@ function DevToolPanel(iframeWindow, toolbox) {
label.appendChild(textNode);
doc.body.appendChild(label);*/
executeSoon(function() {
this.setReady();
}.bind(this));
}
DevToolPanel.prototype = {
open: function() {
let deferred = Promise.defer();
executeSoon(function() {
this._isReady = true;
this.emit("ready");
deferred.resolve(this);
}.bind(this));
return deferred.promise;
},
get target() this._toolbox.target,
get toolbox() this._toolbox,
@ -125,13 +118,7 @@ DevToolPanel.prototype = {
_isReady: false,
setReady: function() {
this._isReady = true;
this.emit("ready");
},
destroy: function DTI_destroy()
{
destroy: function DTI_destroy() {
return Promise.defer(null);
},
};

View File

@ -5,7 +5,7 @@
const Cu = Components.utils;
let toolbox;
let toolbox, target;
let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
@ -13,52 +13,57 @@ let TargetFactory = tempScope.TargetFactory;
function test() {
addTab("about:blank", function(aBrowser, aTab) {
loadWebConsole(aTab);
target = TargetFactory.forTab(gBrowser.selectedTab);
loadWebConsole(aTab).then(function() {
console.log('loaded');
}, console.error);
});
}
function loadWebConsole(aTab) {
ok(gDevTools, "gDevTools exists");
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.openToolbox(target, "bottom", "webconsole");
toolbox.once("webconsole-ready", checkToolLoading);
return gDevTools.showToolbox(target, "webconsole").then(function(aToolbox) {
toolbox = aToolbox;
checkToolLoading();
}, console.error);
}
function checkToolLoading() {
is(toolbox.currentToolId, "webconsole", "The web console is selected");
selectAndCheckById("jsdebugger");
selectAndCheckById("styleeditor");
testToggle();
ok(toolbox.isReady, "toolbox is ready")
selectAndCheckById("jsdebugger").then(function() {
selectAndCheckById("styleeditor").then(function() {
testToggle();
});
}, console.error);
}
function selectAndCheckById(id) {
let doc = toolbox.frame.contentDocument;
toolbox.selectTool(id);
let tab = doc.getElementById("toolbox-tab-" + id);
is(tab.selected, true, "The " + id + " tab is selected");
return toolbox.selectTool(id).then(function() {
let tab = doc.getElementById("toolbox-tab-" + id);
is(tab.selected, true, "The " + id + " tab is selected");
});
}
function testToggle() {
toolbox.once("destroyed", function() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.openToolbox(target, "bottom", "styleeditor");
toolbox.once("styleeditor-ready", checkStyleEditorLoaded);
gDevTools.showToolbox(target, "styleeditor").then(function() {
is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
finishUp();
});
}.bind(this));
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.toggleToolboxForTarget(target);
}
function checkStyleEditorLoaded() {
is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
finishUp();
toolbox.destroy();
}
function finishUp() {
toolbox.destroy();
toolbox = null;
target = null;
gBrowser.removeCurrentTab();
finish();
}

View File

@ -13,25 +13,19 @@ function test()
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
openToolbox();
gDevTools.showToolbox(target).then(testRegister);
}, true);
content.location = "data:text/html,test for dynamically registering and unregistering tools";
}
function openToolbox()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.openToolbox(target);
toolbox.once("ready", testRegister);
}
function testRegister()
function testRegister(aToolbox)
{
toolbox = aToolbox
gDevTools.once("tool-registered", toolRegistered);
gDevTools.registerTool({

View File

@ -12,32 +12,29 @@ let Toolbox = temp.Toolbox;
Cu.import("resource:///modules/devtools/Target.jsm", temp);
let TargetFactory = temp.TargetFactory;
let toolbox;
let toolbox, target;
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
openToolbox(testBottomHost);
gDevTools.showToolbox(target)
.then(testBottomHost, console.error)
.then(null, console.error);
}, true);
content.location = "data:text/html,test for opening toolbox in different hosts";
}
function openToolbox(callback)
function testBottomHost(aToolbox)
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.toggleToolboxForTarget(target);
toolbox = aToolbox;
toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("ready", callback);
}
function testBottomHost()
{
checkHostType(Toolbox.HostType.BOTTOM);
// test UI presence
@ -46,8 +43,7 @@ function testBottomHost()
checkToolboxLoaded(iframe);
toolbox.once("host-changed", testSidebarHost);
toolbox.hostType = Toolbox.HostType.SIDE;
toolbox.switchHost(Toolbox.HostType.SIDE).then(testSidebarHost);
}
function testSidebarHost()
@ -63,8 +59,7 @@ function testSidebarHost()
checkToolboxLoaded(iframe);
toolbox.once("host-changed", testWindowHost);
toolbox.hostType = Toolbox.HostType.WINDOW;
toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost);
}
function testWindowHost()
@ -86,17 +81,14 @@ function testWindowHost()
function testToolSelect()
{
// make sure we can load a tool after switching hosts
toolbox.once("inspector-ready", testDestroy);
toolbox.selectTool("inspector");
toolbox.selectTool("inspector").then(testDestroy);
}
function testDestroy()
{
toolbox.once("destroyed", function() {
openToolbox(testRememberHost);
toolbox.destroy().then(function() {
gDevTools.showToolbox(target).then(testRememberHost);
});
toolbox.destroy();
}
function testRememberHost()
@ -129,7 +121,7 @@ function cleanup()
Services.prefs.setCharPref("devtools.toolbox.host", Toolbox.HostType.BOTTOM);
toolbox.destroy();
DevTools = Toolbox = toolbox = null;
DevTools = Toolbox = toolbox = target = null;
gBrowser.removeCurrentTab();
finish();
}

View File

@ -6,51 +6,42 @@ let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
let toolbox;
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
openToolbox();
gDevTools.showToolbox(target).then(testReady);
}, true);
content.location = "data:text/html,test for dynamically registering and unregistering tools";
}
function openToolbox()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.toggleToolboxForTarget(target);
toolbox = gDevTools.getToolboxForTarget(target);
ok(!toolbox.isReady, "toolbox isReady isn't set yet");
try {
toolbox.selectTool("webconsole");
ok(false, "Should throw when selectTool() called before toolbox is ready");
}
catch(error) {
is(error.message, "Can't select tool, wait for toolbox 'ready' event")
}
toolbox.once("ready", testReady);
}
function testReady()
function testReady(toolbox)
{
ok(toolbox.isReady, "toolbox isReady is set");
cleanup();
testDouble(toolbox);
}
function cleanup()
function testDouble(toolbox)
{
toolbox.destroy();
toolbox = null;
gBrowser.removeCurrentTab();
finish();
let target = toolbox.target;
let toolId = toolbox.currentToolId;
gDevTools.showToolbox(target, toolId).then(function(toolbox2) {
is(toolbox2, toolbox, "same toolbox");
cleanup(toolbox);
});
}
function cleanup(toolbox)
{
toolbox.destroy().then(function() {
gBrowser.removeCurrentTab();
finish();
});
}

View File

@ -6,8 +6,7 @@ let toolbox;
function test() {
addTab("about:blank", function() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.openToolbox(target, "bottom", "webconsole");
toolbox.once("ready", testSelect);
gDevTools.showToolbox(target, "webconsole").then(testSelect);
});
}
@ -18,7 +17,9 @@ let called = {
//jsdebugger: false,
}
function testSelect() {
function testSelect(aToolbox) {
toolbox = aToolbox;
info("Toolbox fired a `ready` event");
toolbox.on("select", selectCB);

View File

@ -33,14 +33,17 @@ function test() {
label: "FAKE TOOL!!!",
isTargetSupported: function() true,
build: function(iframeWindow, toolbox) {
let panel = {
target: toolbox.target,
toolbox: toolbox,
isReady: true,
destroy: function(){},
panelDoc: iframeWindow.document,
}
return panel;
let deferred = Promise.defer();
executeSoon(function() {
deferred.resolve({
target: toolbox.target,
toolbox: toolbox,
isReady: true,
destroy: function(){},
panelDoc: iframeWindow.document,
});
}.bind(this));
return deferred.promise;
},
};
@ -48,8 +51,8 @@ function test() {
addTab("about:blank", function(aBrowser, aTab) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolbox(target, "bottom", "fakeTool4242");
toolbox.once("fakeTool4242-ready", function(event, panel) {
gDevTools.showToolbox(target, toolDefinition.id).then(function(toolbox) {
let panel = toolbox.getPanel(toolDefinition.id);
ok(true, "Tool open");
let tabbox = panel.panelDoc.getElementById("sidebar");
@ -85,7 +88,7 @@ function test() {
panel.sidebar.addTab("tab3", tab3URL);
panel.sidebar.show();
});
}).then(null, console.error);
});
function allTabsReady(panel) {

View File

@ -1,72 +1,29 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let temp = [];
Cu.import("resource:///modules/devtools/Target.jsm", temp);
let TargetFactory = temp.TargetFactory;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
openAllTools();
}, true);
addTab().then(function(data) {
let toolIds = [ "jsdebugger", "styleeditor", "webconsole", "inspector" ];
function openAllTools() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let open = function(index) {
let toolId = toolIds[index];
let tools = gDevTools.getToolDefinitions();
let expectedCallbacksCount = tools.size;
info("About to open " + index + "/" + toolId);
gDevTools.showToolbox(data.target, toolId).then(function(toolbox) {
ok(toolbox, "toolbox exists for " + toolId);
is(toolbox.currentToolId, toolId, "currentToolId should be " + toolId);
let firstTool = null;
// we transform the map to a [id, eventHasBeenFiredYet] map
for (let [id] of tools) {
if (!firstTool)
firstTool = id;
tools.set(id, false);
}
let toolbox = gDevTools.openToolbox(target, undefined, firstTool);
// We add the event listeners
for (let [toolId] of tools) {
let id = toolId;
info("Registering listener for " + id);
tools.set(id, false);
toolbox.on(id + "-ready", function(event, panel) {
expectedCallbacksCount--;
info("Got event " + event);
is(toolbox.getToolPanels().get(id), panel, "Got the right tool panel for " + id);
tools.set(id, true);
if (expectedCallbacksCount == 0) {
// "executeSoon" because we want to let a chance
// to falsy code to fire unexpected ready events.
executeSoon(theEnd);
let nextIndex = index + 1;
if (nextIndex >= toolIds.length) {
toolbox.destroy();
finish();
}
if (expectedCallbacksCount < 0) {
ok(false, "we are receiving too many events");
else {
open(nextIndex);
}
});
}
}, console.error);
};
toolbox.once("ready", function() {
// We open all the
for (let [id] of tools) {
if (id != firstTool) {
toolbox.selectTool(id);
}
}
});
function theEnd() {
for (let [id, called] of tools) {
ok(called, "Tool " + id + " has fired its ready event");
}
toolbox.destroy();
gBrowser.removeCurrentTab();
finish();
}
}
open(0);
}).then(null, console.error);
}

View File

@ -7,6 +7,8 @@ Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
Components.utils.import("resource://gre/modules/commonjs/promise/core.js", tempScope);
let Promise = tempScope.Promise;
/**
* Open a new tab at a URL and call a callback on load
@ -16,17 +18,28 @@ function addTab(aURL, aCallback)
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = aURL;
if (aURL != null) {
content.location = aURL;
}
let deferred = Promise.defer();
let tab = gBrowser.selectedTab;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
aCallback(browser, tab, browser.contentDocument);
if (aCallback != null) {
aCallback(browser, tab, browser.contentDocument);
}
deferred.resolve({ browser: browser, tab: tab, target: target });
}
browser.addEventListener("load", onTabLoad, true);
return deferred.promise;
}
registerCleanupFunction(function tearDown() {

View File

@ -32,17 +32,8 @@ gcli.addCommand({
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let node = args.selector;
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
inspector.selection.setNode(node, "gcli");
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
inspector.selection.setNode(node, "gcli");
}.bind(this));
}
return gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
toolbox.getCurrentPanel().selection.setNode(args.selector, "gcli");
}.bind(this));
}
});

View File

@ -10,6 +10,7 @@ this.EXPORTED_SYMBOLS = ["InspectorPanel"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MarkupView",
@ -34,85 +35,90 @@ const LAYOUT_CHANGE_TIMER = 250;
this.InspectorPanel = function InspectorPanel(iframeWindow, toolbox) {
this._toolbox = toolbox;
this._target = toolbox._target;
if (this.target.isRemote) {
throw "Unsupported target";
}
this.panelDoc = iframeWindow.document;
this.panelWin = iframeWindow;
this.panelWin.inspector = this;
this.tabTarget = (this.target.tab != null);
this.winTarget = (this.target.window != null);
new EventEmitter(this);
this.preventNavigateAway = this.preventNavigateAway.bind(this);
this.onNavigatedAway = this.onNavigatedAway.bind(this);
this.target.on("will-navigate", this.preventNavigateAway);
this.target.on("navigate", this.onNavigatedAway);
this.panelDoc = iframeWindow.document;
this.panelWin = iframeWindow;
this.panelWin.inspector = this;
this.nodemenu = this.panelDoc.getElementById("inspector-node-popup");
this.lastNodemenuItem = this.nodemenu.lastChild;
this._setupNodeMenu = this._setupNodeMenu.bind(this);
this._resetNodeMenu = this._resetNodeMenu.bind(this);
this.nodemenu.addEventListener("popupshowing", this._setupNodeMenu, true);
this.nodemenu.addEventListener("popuphiding", this._resetNodeMenu, true);
// Create an empty selection
this._selection = new Selection();
this.onNewSelection = this.onNewSelection.bind(this);
this.selection.on("new-node", this.onNewSelection);
this.breadcrumbs = new HTMLBreadcrumbs(this);
if (this.tabTarget) {
this.browser = this.target.tab.linkedBrowser;
this.scheduleLayoutChange = this.scheduleLayoutChange.bind(this);
this.browser.addEventListener("resize", this.scheduleLayoutChange, true);
this.highlighter = new Highlighter(this.target, this, this._toolbox);
let button = this.panelDoc.getElementById("inspector-inspect-toolbutton");
button.hidden = false;
this.updateInspectorButton = function() {
if (this.highlighter.locked) {
button.removeAttribute("checked");
} else {
button.setAttribute("checked", "true");
}
}.bind(this);
this.highlighter.on("locked", this.updateInspectorButton);
this.highlighter.on("unlocked", this.updateInspectorButton);
}
this._initMarkup();
this.isReady = false;
this.once("markuploaded", function() {
this.isReady = true;
// All the components are initialized. Let's select a node.
if (this.tabTarget) {
let root = this.browser.contentDocument.documentElement;
this._selection.setNode(root);
}
if (this.winTarget) {
let root = this.target.window.document.documentElement;
this._selection.setNode(root);
}
if (this.highlighter) {
this.highlighter.unlock();
}
this.emit("ready");
}.bind(this));
this.setupSidebar();
}
InspectorPanel.prototype = {
/**
* open is effectively an asynchronous constructor
*/
open: function InspectorPanel_open() {
let deferred = Promise.defer();
this.preventNavigateAway = this.preventNavigateAway.bind(this);
this.onNavigatedAway = this.onNavigatedAway.bind(this);
this.target.on("will-navigate", this.preventNavigateAway);
this.target.on("navigate", this.onNavigatedAway);
this.nodemenu = this.panelDoc.getElementById("inspector-node-popup");
this.lastNodemenuItem = this.nodemenu.lastChild;
this._setupNodeMenu = this._setupNodeMenu.bind(this);
this._resetNodeMenu = this._resetNodeMenu.bind(this);
this.nodemenu.addEventListener("popupshowing", this._setupNodeMenu, true);
this.nodemenu.addEventListener("popuphiding", this._resetNodeMenu, true);
// Create an empty selection
this._selection = new Selection();
this.onNewSelection = this.onNewSelection.bind(this);
this.selection.on("new-node", this.onNewSelection);
this.breadcrumbs = new HTMLBreadcrumbs(this);
if (this.tabTarget) {
this.browser = this.target.tab.linkedBrowser;
this.scheduleLayoutChange = this.scheduleLayoutChange.bind(this);
this.browser.addEventListener("resize", this.scheduleLayoutChange, true);
this.highlighter = new Highlighter(this.target, this, this._toolbox);
let button = this.panelDoc.getElementById("inspector-inspect-toolbutton");
button.hidden = false;
this.updateInspectorButton = function() {
if (this.highlighter.locked) {
button.removeAttribute("checked");
} else {
button.setAttribute("checked", "true");
}
}.bind(this);
this.highlighter.on("locked", this.updateInspectorButton);
this.highlighter.on("unlocked", this.updateInspectorButton);
}
this._initMarkup();
this.isReady = false;
this.once("markuploaded", function() {
this.isReady = true;
// All the components are initialized. Let's select a node.
if (this.tabTarget) {
let root = this.browser.contentDocument.documentElement;
this._selection.setNode(root);
}
if (this.winTarget) {
let root = this.target.window.document.documentElement;
this._selection.setNode(root);
}
if (this.highlighter) {
this.highlighter.unlock();
}
this.emit("ready");
deferred.resolve(this);
}.bind(this));
this.setupSidebar();
return deferred.promise;
},
/**
* Selection object (read only)
*/
@ -274,11 +280,12 @@ InspectorPanel.prototype = {
*/
destroy: function InspectorPanel__destroy() {
if (this._destroyed) {
return;
return Promise.resolve(null);
}
this.cancelLayoutChange();
this._destroyed = true;
this.cancelLayoutChange();
this._toolbox = null;
if (this.browser) {
@ -314,6 +321,8 @@ InspectorPanel.prototype = {
this.lastNodemenuItem = null;
this.nodemenu = null;
this.highlighter = null;
return Promise.resolve(null);
},
/**

View File

@ -68,7 +68,7 @@ function test()
function performTest()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
let panel = gDevTools.getPanelForTarget("inspector", target);
let panel = gDevTools.getToolbox(target).getPanel("inspector");
let container = panel.panelDoc.getElementById("inspector-breadcrumbs");
let buttonsLabelIds = nodes[cursor].result.split(" ");

View File

@ -24,7 +24,7 @@ function test() {
inspector.markDirty();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
notificationBox = toolbox.getNotificationBox();
notificationBox.addEventListener("AlertActive", alertActive1, false);
@ -59,7 +59,7 @@ function test() {
is(para.textContent, "init", "paragraph content is correct");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
let inspector = gDevTools.getToolbox(target).getPanel("inspector");
ok(inspector, "Inspector still alive");
notificationBox.addEventListener("AlertActive", alertActive2, false);

View File

@ -25,17 +25,17 @@ function createDocument()
'</div>';
doc.title = "Inspector Initialization Test";
openInspector(startInspectorTests);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
startInspectorTests(toolbox);
}).then(null, console.error);
}
function startInspectorTests()
function startInspectorTests(toolbox)
{
let inspector = toolbox.getCurrentPanel();
ok(true, "Inspector started, and notification received.");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
ok(inspector, "Inspector instance is accessible");
ok(inspector.isReady, "Inspector instance is ready");
is(inspector.target.tab, gBrowser.selectedTab, "Valid target");
@ -58,11 +58,10 @@ function startInspectorTests()
testMarkupView(span);
testBreadcrumbs(span);
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("destroyed", function() {
ok("true", "'destroyed' notification received.");
let toolbox = gDevTools.getToolboxForTarget(target);
ok(!toolbox, "Toolbox destroyed.");
let target = TargetFactory.forTab(gBrowser.selectedTab);
ok(!gDevTools.getToolbox(target), "Toolbox destroyed.");
executeSoon(runContextMenuTest);
});
toolbox.destroy();
@ -94,14 +93,13 @@ function _clickOnInspectMenuItem(node) {
document.popupNode = node;
var contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
var contextMenu = new nsContextMenu(contentAreaContextMenu, gBrowser);
contextMenu.inspectNode();
return contextMenu.inspectNode();
}
function runContextMenuTest()
{
salutation = doc.getElementById("salutation");
_clickOnInspectMenuItem(salutation);
gDevTools.once("inspector-ready", testInitialNodeIsSelected);
_clickOnInspectMenuItem(salutation).then(testInitialNodeIsSelected);
}
function testInitialNodeIsSelected() {

View File

@ -130,6 +130,6 @@ function finishUp()
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
toolbox.destroy();
}

View File

@ -29,7 +29,7 @@ function inspectorRuleViewOpened()
gDevTools.once("toolbox-destroyed", inspectorClosed);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
executeSoon(function() {
toolbox.destroy();
});

View File

@ -8,6 +8,8 @@ Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
let LayoutHelpers = tempScope.LayoutHelpers;
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
@ -16,23 +18,15 @@ Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
function openInspector(callback)
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
callback(inspector);
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
callback(inspector);
});
}
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
callback(toolbox.getCurrentPanel());
}).then(null, console.error);
}
function getActiveInspector()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
return gDevTools.getPanelForTarget("inspector", target);
return gDevTools.getToolbox(target).getPanel("inspector");
}
function isHighlighting()

View File

@ -67,10 +67,8 @@ function test() {
ok(node, "node found");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
openLayoutView(inspector);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
openLayoutView(toolbox.getCurrentPanel());
});
}

View File

@ -205,9 +205,8 @@ function test() {
function setupTest() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
runTests();
});
}

View File

@ -146,9 +146,8 @@ function test() {
function setupTest() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function BIMMT_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
startTests();
});
}

View File

@ -74,9 +74,8 @@ function test() {
function setupTest() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function BIMNT_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
startNavigation();
});
}

View File

@ -32,6 +32,7 @@ gcli.addCommand({
name: 'resize toggle',
buttonId: "command-button-responsive",
buttonClass: "command-button devtools-toolbarbutton",
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
description: gcli.lookup('resizeModeToggleDesc'),
manual: gcli.lookup('resizeModeManual'),
exec: gcli_cmd_resize

View File

@ -164,7 +164,7 @@ function ResponsiveUI(aWindow, aTab)
this.checkMenus();
let target = TargetFactory.forTab(this.tab);
this.toolboxWasOpen = !!gDevTools.getToolboxForTarget(target);
this.toolboxWasOpen = !!gDevTools.getToolbox(target);
try {
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
@ -249,7 +249,7 @@ ResponsiveUI.prototype = {
// We let the toolbox close first.
let target = TargetFactory.forTab(this.tab);
let isToolboxOpen = !!gDevTools.getToolboxForTarget(target);
let isToolboxOpen = !!gDevTools.getToolbox(target);
if (this.toolboxWasOpen || !isToolboxOpen) {
aEvent.preventDefault();
aEvent.stopPropagation();
@ -608,8 +608,8 @@ ResponsiveUI.prototype = {
this._resizing = true;
this.stack.setAttribute("notransition", "true");
this.lastClientX = aEvent.clientX;
this.lastClientY = aEvent.clientY;
this.lastScreenX = aEvent.screenX;
this.lastScreenY = aEvent.screenY;
this.ignoreY = (aEvent.target === this.resizeBar);
@ -622,8 +622,8 @@ ResponsiveUI.prototype = {
* @param aEvent
*/
onDrag: function RUI_onDrag(aEvent) {
let deltaX = aEvent.clientX - this.lastClientX;
let deltaY = aEvent.clientY - this.lastClientY;
let deltaX = aEvent.screenX - this.lastScreenX;
let deltaY = aEvent.screenY - this.lastScreenY;
if (this.ignoreY)
deltaY = 0;
@ -634,13 +634,13 @@ ResponsiveUI.prototype = {
if (width < MIN_WIDTH) {
width = MIN_WIDTH;
} else {
this.lastClientX = aEvent.clientX;
this.lastScreenX = aEvent.screenX;
}
if (height < MIN_HEIGHT) {
height = MIN_HEIGHT;
} else {
this.lastClientY = aEvent.clientY;
this.lastScreenY = aEvent.screenY;
}
this.setSize(width, height);

View File

@ -14,16 +14,8 @@ Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
function openInspector(callback)
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
callback(inspector);
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
callback(inspector);
});
}
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
callback(toolbox.getCurrentPanel());
});
}

View File

@ -13,6 +13,7 @@ gcli.addCommand({
name: "scratchpad",
buttonId: "command-button-scratchpad",
buttonClass: "command-button devtools-toolbarbutton",
tooltipText: gcli.lookup("scratchpadOpenTooltip"),
hidden: true,
exec: function(args, context) {
let chromeWindow = context.environment.chromeDocument.defaultView;

View File

@ -1056,7 +1056,7 @@ var Scratchpad = {
openWebConsole: function SP_openWebConsole()
{
let target = TargetFactory.forTab(this.gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
gDevTools.showToolbox(target, "webconsole");
this.browserWindow.focus();
},

View File

@ -81,6 +81,12 @@ this.CommandUtils = {
if (command.buttonClass != null) {
button.className = command.buttonClass;
}
if (command.tooltipText != null) {
button.setAttribute("tooltiptext", command.tooltipText);
}
else if (command.description != null) {
button.setAttribute("tooltiptext", command.description);
}
button.addEventListener("click", function() {
requisition.update(buttonSpec.typed);

View File

@ -92,7 +92,15 @@ EventEmitter.prototype = {
// event handler we're going to fire wasn't removed.
if (originalListeners === this._eventEmitterListeners.get(aEvent) ||
this._eventEmitterListeners.get(aEvent).some(function(l) l === listener)) {
listener.apply(null, arguments);
try {
listener.apply(null, arguments);
}
catch (ex) {
// Prevent a bad listener from interfering with the others.
let msg = ex + ": " + ex.stack;
Components.utils.reportError(msg);
dump(msg + "\n");
}
}
}
},

View File

@ -65,6 +65,7 @@ VariablesView.prototype = {
*/
addScope: function VV_addScope(aName = "") {
this._removeEmptyNotice();
this._toggleSearch(true);
let scope = new Scope(this, aName);
this._store.set(scope.id, scope);
@ -100,6 +101,7 @@ VariablesView.prototype = {
this._store = new Map();
this._appendEmptyNotice();
this._toggleSearch(false);
},
/**
@ -133,6 +135,7 @@ VariablesView.prototype = {
if (!this._store.size) {
this._appendEmptyNotice();
this._toggleSearch(false);
}
}.bind(this), aTimeout);
},
@ -187,13 +190,14 @@ VariablesView.prototype = {
return;
}
let document = this.document;
let parent = this._parent;
let ownerView = this._parent.parentNode;
let container = this._searchboxContainer = document.createElement("hbox");
container.className = "devtools-toolbar";
container.hidden = !this._store.size;
let searchbox = this._searchboxNode = document.createElement("textbox");
searchbox.className = "devtools-searchinput";
searchbox.className = "variables-searchinput devtools-searchinput";
searchbox.setAttribute("placeholder", this._searchboxPlaceholder);
searchbox.setAttribute("type", "search");
searchbox.setAttribute("flex", "1");
@ -201,7 +205,7 @@ VariablesView.prototype = {
searchbox.addEventListener("keypress", this._onSearchboxKeyPress, false);
container.appendChild(searchbox);
parent.insertBefore(container, parent.firstChild);
ownerView.insertBefore(container, this._parent);
},
/**
@ -212,7 +216,7 @@ VariablesView.prototype = {
if (!this._searchboxContainer) {
return;
}
this._parent.removeChild(this._searchboxContainer);
this._searchboxContainer.parentNode.removeChild(this._searchboxContainer);
this._searchboxNode.addEventListener("input", this._onSearchboxInput, false);
this._searchboxNode.addEventListener("keypress", this._onSearchboxKeyPress, false);
@ -220,6 +224,20 @@ VariablesView.prototype = {
this._searchboxNode = null;
},
/**
* Sets the variables searchbox hidden or visible. It's hidden by default.
*
* @param boolean aVisibleFlag
* Specifies the intended visibility.
*/
_toggleSearch: function VV__toggleSearch(aVisibleFlag) {
// If searching was already disabled, there's no need to hide it.
if (!this._searchboxContainer) {
return;
}
this._searchboxContainer.hidden = !aVisibleFlag;
},
/**
* Sets if the variable and property searching is enabled.
*/
@ -660,6 +678,13 @@ Scope.prototype = {
*/
set twisty(aFlag) aFlag ? this.showArrow() : this.hideArrow(),
/**
* Specifies if the configurable/enumerable/writable tooltip should be shown
* whenever a variable or property descriptor is available.
* This flag applies non-recursively to the current scope.
*/
showDescriptorTooltip: true,
/**
* Specifies if editing variable or property names is allowed.
* This flag applies non-recursively to the current scope.
@ -1256,26 +1281,27 @@ create({ constructor: Variable, proto: Scope.prototype }, {
this._target.removeEventListener("mouseover", this._displayTooltip, false);
let document = this.document;
let tooltip = document.createElement("tooltip");
tooltip.id = "tooltip-" + this.id;
if (this.ownerView.showDescriptorTooltip) {
let tooltip = document.createElement("tooltip");
tooltip.id = "tooltip-" + this.id;
let configurableLabel = document.createElement("label");
configurableLabel.setAttribute("value", "configurable");
let configurableLabel = document.createElement("label");
configurableLabel.setAttribute("value", "configurable");
let enumerableLabel = document.createElement("label");
enumerableLabel.setAttribute("value", "enumerable");
let enumerableLabel = document.createElement("label");
enumerableLabel.setAttribute("value", "enumerable");
let writableLabel = document.createElement("label");
writableLabel.setAttribute("value", "writable");
let writableLabel = document.createElement("label");
writableLabel.setAttribute("value", "writable");
tooltip.setAttribute("orient", "horizontal")
tooltip.appendChild(configurableLabel);
tooltip.appendChild(enumerableLabel);
tooltip.appendChild(writableLabel);
this._target.appendChild(tooltip);
this._target.setAttribute("tooltip", tooltip.id);
tooltip.setAttribute("orient", "horizontal")
tooltip.appendChild(configurableLabel);
tooltip.appendChild(enumerableLabel);
tooltip.appendChild(writableLabel);
this._target.appendChild(tooltip);
this._target.setAttribute("tooltip", tooltip.id);
}
if (this.ownerView.allowNameInput) {
this._name.setAttribute("tooltiptext", L10N.getStr("variablesEditableNameTooltip"));
}

View File

@ -39,8 +39,7 @@ function checkOpen() {
ok(!isChecked(toggleToolbox), "toggle toolbox button is not checked");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "webconsole");
toolbox.once("webconsole-selected", function BTBT_selected(id, aInspector) {
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
ok(isChecked(toggleToolbox), "toggle toolbox button is checked");
addTab("about:blank", function(browser, tab) {

View File

@ -112,7 +112,7 @@ function test() {
oneTimeObserve("web-console-created", _onWebConsoleOpen);
let target = TargetFactory.forTab(tab);
gDevTools.openToolboxForTab(target, "webconsole");
gDevTools.showToolbox(target, "webconsole");
}
function onWebConsoleOpen(hud) {

View File

@ -660,7 +660,7 @@ StyleEditor.prototype = {
// Use a ref count to make sure we do not add it multiple times.. and remove
// it only when all pending StyleEditor-generated transitions ended.
if (!this._transitionRefCount) {
this._styleSheet.insertRule(TRANSITION_RULE, 0);
this.styleSheet.insertRule(TRANSITION_RULE, this.styleSheet.cssRules.length);
content.documentElement.classList.add(TRANSITION_CLASS);
}
@ -682,7 +682,7 @@ StyleEditor.prototype = {
{
if (--this._transitionRefCount == 0) {
this.contentDocument.documentElement.classList.remove(TRANSITION_CLASS);
this.styleSheet.deleteRule(0);
this.styleSheet.deleteRule(this.styleSheet.cssRules.length - 1);
}
this._triggerAction("Commit");
@ -809,8 +809,8 @@ StyleEditor.prototype = {
}
}
if (sheet.ownerNode) {
// step 3: see <link charset="…">
// step 3: charset attribute of <link> or <style> element, if it exists
if (sheet.ownerNode && sheet.ownerNode.getAttribute) {
let linkCharset = sheet.ownerNode.getAttribute("charset");
if (linkCharset != null) {
return this._convertToUnicode(aString, linkCharset);
@ -952,7 +952,7 @@ StyleEditor.prototype = {
{
let document = this.contentDocument;
let parent = document.documentElement;
let style = document.createElement("style");
let style = document.createElementNS("http://www.w3.org/1999/xhtml", "style");
style.setAttribute("type", "text/css");
if (aText) {
style.appendChild(document.createTextNode(aText));

View File

@ -4,15 +4,16 @@
* 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 = Components.utils;
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
this.EXPORTED_SYMBOLS = ["StyleEditorPanel"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "StyleEditorChrome",
"resource:///modules/devtools/StyleEditorChrome.jsm");
"resource:///modules/devtools/StyleEditorChrome.jsm");
this.StyleEditorPanel = function StyleEditorPanel(panelWin, toolbox) {
new EventEmitter(this);
@ -30,20 +31,24 @@ this.StyleEditorPanel = function StyleEditorPanel(panelWin, toolbox) {
this._panelWin = panelWin;
this._panelDoc = panelWin.document;
let contentWin = toolbox.target.tab.linkedBrowser.contentWindow;
this.setPage(contentWin);
this.isReady = true;
}
StyleEditorPanel.prototype = {
/**
* open is effectively an asynchronous constructor
*/
open: function StyleEditor_open() {
let contentWin = this._toolbox.target.window;
this.setPage(contentWin);
this.isReady = true;
return Promise.resolve(this);
},
/**
* Target getter.
*/
get target() {
return this._target;
},
get target() this._target,
/**
* Panel window getter.
@ -94,17 +99,18 @@ StyleEditorPanel.prototype = {
* Destroy StyleEditor
*/
destroy: function StyleEditor_destroy() {
if (this._destroyed) {
return;
}
this._destroyed = true;
if (!this._destroyed) {
this._destroyed = true;
this._target.off("will-navigate", this.reset);
this._target.off("navigate", this.newPage);
this._target.off("close", this.destroy);
this._target = null;
this._toolbox = null;
this._panelWin = null;
this._panelDoc = null;
this._target.off("will-navigate", this.reset);
this._target.off("navigate", this.newPage);
this._target.off("close", this.destroy);
this._target = null;
this._toolbox = null;
this._panelWin = null;
this._panelDoc = null;
}
return Promise.resolve(null);
},
}

View File

@ -24,7 +24,7 @@ function test() {
addTabAndLaunchStyleEditorChromeWhenLoaded(function (aChrome) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.getToolboxForTarget(target);
toolbox = gDevTools.getToolbox(target);
aChrome.addChromeListener({
onEditorAdded: function (aChrome, aEditor) {

View File

@ -9,6 +9,8 @@ const TEST_HOST = 'mochi.test:8888';
let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
let gChromeWindow; //StyleEditorChrome window
let cache = Cc["@mozilla.org/network/cache-service;1"]
@ -35,26 +37,15 @@ function launchStyleEditorChrome(aCallback, aSheet, aLine, aCol)
function launchStyleEditorChromeFromWindow(aWindow, aCallback, aSheet, aLine, aCol)
{
let target = TargetFactory.forTab(aWindow.gBrowser.selectedTab);
let panel = aWindow.gDevTools.getPanelForTarget("styleeditor", target);
if (panel && panel.isReady) {
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
let panel = toolbox.getCurrentPanel();
gChromeWindow = panel._panelWin;
gChromeWindow.styleEditorChrome._alwaysDisableAnimations = true;
if (aSheet) {
panel.selectStyleSheet(aSheet, aLine, aCol);
}
aCallback(gChromeWindow.styleEditorChrome);
} else {
let toolbox = aWindow.gDevTools.openToolboxForTab(target, "styleeditor");
toolbox.once("styleeditor-ready", function(event, panel) {
gChromeWindow = panel._panelWin;
gChromeWindow.styleEditorChrome._alwaysDisableAnimations = true;
if (aSheet) {
panel.selectStyleSheet(aSheet, aLine, aCol);
}
aCallback(gChromeWindow.styleEditorChrome);
});
}
});
}
function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback, aSheet, aLine, aCol)

View File

@ -736,7 +736,7 @@ this.PropertyView = function PropertyView(aTree, aName)
this.name = aName;
this.getRTLAttr = aTree.getRTLAttr;
this.link = "https://developer.mozilla.org/en/CSS/" + aName;
this.link = "https://developer.mozilla.org/CSS/" + aName;
this.templateMatchedSelectors = aTree.styleDocument.getElementById("templateMatchedSelectors");
}
@ -1257,12 +1257,9 @@ SelectorView.prototype = {
let target = inspector.target;
if (styleEditorDefinition.isTargetSupported(target)) {
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("styleeditor-selected", function SE_selected(id, styleEditor) {
styleEditor.selectStyleSheet(styleSheet, line);
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
toolbox.getCurrentPanel().selectStyleSheet(styleSheet, line);
});
toolbox.selectTool("styleeditor");
}
} else {
let href = styleSheet ? styleSheet.href : "";

View File

@ -62,12 +62,9 @@ this.RuleViewTool = function RVT_RuleViewTool(aInspector, aWindow, aIFrame)
let target = this.inspector.target;
if (styleEditorDefinition.isTargetSupported(target)) {
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("styleeditor-selected", function SE_selected(id, styleEditor) {
styleEditor.selectStyleSheet(styleSheet, line);
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
toolbox.getCurrentPanel().selectStyleSheet(styleSheet, line);
});
toolbox.selectTool("styleeditor");
}
} else {
let href = styleSheet ? styleSheet.href : "";

View File

@ -82,9 +82,8 @@ function testInlineStyleSheet()
info("clicking an inline stylesheet");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "styleeditor");
toolbox.once("styleeditor-ready", function(event, panel) {
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
let panel = toolbox.getCurrentPanel();
let win = panel._panelWin;
win.styleEditorChrome.addChromeListener({

View File

@ -34,9 +34,9 @@ function createDocument()
doc.title = "Rule view style editor link test";
let target = TargetFactory.forTab(gBrowser.selectedTab);
toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(aToolbox) {
toolbox = aToolbox;
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
highlightNode();
});

View File

@ -35,9 +35,8 @@ function createDocument()
doc.title = "Rule view context menu test";
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
win = inspector.sidebar.getWindowForTab("ruleview");
highlightNode();

View File

@ -15,9 +15,8 @@ let stylePanel;
function openRuleView()
{
var target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
inspector = aInspector;
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
// Highlight a node.

View File

@ -13,6 +13,8 @@ let CssHtmlTree = tempScope.CssHtmlTree;
let gDevTools = tempScope.gDevTools;
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
let browser, hudId, hud, hudBox, filterBox, outputNode, cs;
@ -26,16 +28,9 @@ function addTab(aURL)
function openInspector(callback)
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
callback(inspector);
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function(event, panel) {
let inspector = gDevTools.getPanelForTarget("inspector", target);
callback(inspector);
});
}
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
callback(toolbox.getCurrentPanel());
});
}
function addStyle(aDocument, aString)

View File

@ -44,6 +44,7 @@ gcli.addCommand({
name: "tilt toggle",
buttonId: "command-button-tilt",
buttonClass: "command-button devtools-toolbarbutton",
tooltipText: gcli.lookup("tiltToggleTooltip"),
hidden: true,
exec: function(args, context) {
let chromeWindow = context.environment.chromeDocument.defaultView;

View File

@ -175,9 +175,9 @@ TiltVisualizer.prototype = {
false);
let target = TargetFactory.forTab(aTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector) {
this.inspector = inspector;
let toolbox = gDevTools.getToolbox(target);
if (toolbox) {
this.inspector = toolbox.getPanel("inspector");
this.inspector.selection.on("new-node", this.onNewNodeFromInspector);
this.inspector.selection.on("detached", this.onNewNodeFromInspector);
this.onNewNodeFromInspector();

View File

@ -535,12 +535,9 @@ WebConsole.prototype = {
if (style.href == aSourceURL) {
let target = TargetFactory.forTab(this.tab);
let gDevTools = this.chromeWindow.gDevTools;
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("styleeditor-selected",
function _onStyleEditorReady(aEvent, aPanel) {
aPanel.selectStyleSheet(style, aSourceLine);
});
toolbox.selectTool("styleeditor");
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
toolbox.getCurrentPanel().selectStyleSheet(style, aSourceLine);
});
return;
}
}
@ -602,7 +599,11 @@ var HeadsUpDisplayUICommands = {
{
var window = HUDService.currentContext();
let target = TargetFactory.forTab(window.gBrowser.selectedTab);
gDevTools.toggleToolboxForTarget(target, "webconsole");
let toolbox = gDevTools.getToolbox(target);
return toolbox && toolbox.currentToolId == "webconsole" ?
toolbox.destroy() :
gDevTools.showToolbox(target, "webconsole");
},
toggleRemoteHUD: function UIC_toggleRemoteHUD()

View File

@ -6,15 +6,15 @@
this.EXPORTED_SYMBOLS = [ "WebConsolePanel" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
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://gre/modules/commonjs/promise/core.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
"resource:///modules/HUDService.jsm");
/**
* A DevToolPanel that controls the Web Console.
@ -23,26 +23,37 @@ function WebConsolePanel(iframeWindow, toolbox) {
this._frameWindow = iframeWindow;
this._toolbox = toolbox;
new EventEmitter(this);
let tab = this._toolbox._getHostTab();
let parentDoc = iframeWindow.document.defaultView.parent.document;
let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
this.hud = HUDService.activateHUDForContext(tab, iframe, toolbox.target);
let hudId = this.hud.hudId;
let onOpen = function _onWebConsoleOpen(aSubject)
{
aSubject.QueryInterface(Ci.nsISupportsString);
if (hudId == aSubject.data) {
Services.obs.removeObserver(onOpen, "web-console-created");
this.setReady();
}
}.bind(this);
Services.obs.addObserver(onOpen, "web-console-created", false);
}
WebConsolePanel.prototype = {
/**
* open is effectively an asynchronous constructor
*/
open: function StyleEditor_open() {
let tab = this._toolbox._getHostTab();
let parentDoc = this._frameWindow.document.defaultView.parent.document;
let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
this.hud = HUDService.activateHUDForContext(tab, iframe, this._toolbox.target);
let deferred = Promise.defer();
let hudId = this.hud.hudId;
let onOpen = function _onWebConsoleOpen(aSubject) {
aSubject.QueryInterface(Ci.nsISupportsString);
if (hudId == aSubject.data) {
Services.obs.removeObserver(onOpen, "web-console-created");
this._isReady = true;
this.emit("ready");
deferred.resolve(this);
}
}.bind(this);
Services.obs.addObserver(onOpen, "web-console-created", false);
return deferred.promise;
},
get target() this._toolbox.target,
_isReady: false,
@ -50,6 +61,12 @@ WebConsolePanel.prototype = {
destroy: function WCP_destroy()
{
if (this.destroyer) {
return this.destroyer.promise;
}
this.destroyer = Promise.defer();
let hudId = this.hud.hudId;
let onClose = function _onWebConsoleClose(aSubject)
@ -57,17 +74,15 @@ WebConsolePanel.prototype = {
aSubject.QueryInterface(Ci.nsISupportsString);
if (hudId == aSubject.data) {
Services.obs.removeObserver(onClose, "web-console-destroyed");
this.emit("destroyed");
this.destroyer.resolve(null);
}
}.bind(this);
Services.obs.addObserver(onClose, "web-console-destroyed", false);
HUDService.deactivateHUDForContext(this.hud.tab, false);
},
setReady: function WCP_setReady()
{
this._isReady = true;
this.emit("ready");
return this.destroyer.promise;
},
};

View File

@ -45,19 +45,19 @@ function tab2Loaded(aEvent) {
function openConsoles() {
try {
let target1 = TargetFactory.forTab(tab1);
gDevTools.openToolboxForTab(target1, "webconsole");
gDevTools.showToolbox(target1, "webconsole");
}
catch (ex) {
ok(false, "gDevTools.openToolboxForTab(target1) exception: " + ex);
ok(false, "gDevTools.showToolbox(target1) exception: " + ex);
noErrors = false;
}
try {
let target2 = TargetFactory.forTab(tab2);
gDevTools.openToolboxForTab(target2, "webconsole");
gDevTools.showToolbox(target2, "webconsole");
}
catch (ex) {
ok(false, "gDevTools.openToolboxForTab(target2) exception: " + ex);
ok(false, "gDevTools.showToolbox(target2) exception: " + ex);
noErrors = false;
}
}

View File

@ -16,7 +16,11 @@ function test() {
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, consoleOpened);
openConsole(null, function(hud) {
executeSoon(function() {
consoleOpened(hud);
});
});
}, true);
}

View File

@ -63,7 +63,7 @@ function runSelectionTests(aInspector)
function performTestComparisons()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
let inspector = gDevTools.getToolbox(target).getPanel("inspector");
inspector.highlighter.lock();
let isHighlighting =
@ -116,7 +116,7 @@ function performWebConsoleTests(hud)
let node = outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("bug653531"), -1,
"correct output for $0.textContent");
let inspector = gDevTools.getPanelForTarget("inspector", target);
let inspector = gDevTools.getToolbox(target).getPanel("inspector");
is(inspector.selection.node.textContent, "bug653531",
"node successfully updated");

View File

@ -40,7 +40,7 @@ function testViewSource(aHud)
is(nodes.length, 2, "correct number of css messages");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
toolbox.once("styleeditor-selected", onStyleEditorReady);
EventUtils.sendMouseEvent({ type: "click" }, nodes[0]);
@ -81,17 +81,17 @@ function onStyleEditorReady(aEvent, aPanel)
info("first check done");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
let sheet = sheetForNode(nodes[1]);
ok(sheet, "sheet found");
let line = nodes[1].sourceLine;
ok(line, "found source line");
toolbox.once("webconsole-selected", function(aEvent) {
info(aEvent + " event fired");
toolbox.selectTool("webconsole").then(function() {
info("webconsole selected");
toolbox.once("styleeditor-selected", function() {
toolbox.once("styleeditor-selected", function(aEvent) {
info(aEvent + " event fired");
checkStyleEditorForSheetAndLine(sheet, line - 1, function() {
@ -102,8 +102,6 @@ function onStyleEditorReady(aEvent, aPanel)
EventUtils.sendMouseEvent({ type: "click" }, nodes[1]);
});
toolbox.selectTool("webconsole");
});
}, win);
}

View File

@ -10,7 +10,11 @@ function test() {
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, testViewSource);
openConsole(null, function(hud) {
executeSoon(function() {
testViewSource(hud);
});
});
}, true);
}

View File

@ -12,6 +12,8 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
let gDevTools = tempScope.gDevTools;
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
@ -139,22 +141,10 @@ function findLogEntry(aString)
*/
function openConsole(aTab, aCallback = function() { })
{
function onWebConsoleOpen(aEvent, aPanel)
{
executeSoon(aCallback.bind(null, aPanel.hud));
}
let target = TargetFactory.forTab(aTab || tab);
let toolbox = gDevTools.getToolboxForTarget(target);
if (toolbox) {
toolbox.once("webconsole-selected", onWebConsoleOpen);
toolbox.selectTool("webconsole");
}
else {
let target = TargetFactory.forTab(aTab || tab);
toolbox = gDevTools.openToolboxForTab(target, "webconsole");
toolbox.once("webconsole-selected", onWebConsoleOpen);
}
gDevTools.showToolbox(target, "webconsole").then(function(toolbox) {
aCallback(toolbox.getCurrentPanel().hud);
});
}
/**
@ -170,20 +160,18 @@ function openConsole(aTab, aCallback = function() { })
function closeConsole(aTab, aCallback = function() { })
{
let target = TargetFactory.forTab(aTab || tab);
let toolbox = gDevTools.getToolboxForTarget(target);
let toolbox = gDevTools.getToolbox(target);
if (toolbox) {
let panel = gDevTools.getPanelForTarget("webconsole", target);
let panel = toolbox.getPanel("webconsole");
if (panel) {
let hudId = panel.hud.hudId;
panel.once("destroyed", function() {
toolbox.destroy().then(function() {
executeSoon(aCallback.bind(null, hudId));
});
}).then(null, console.error);
}
else {
toolbox.once("destroyed", aCallback.bind(null, null));
toolbox.destroy().then(aCallback.bind(null));
}
toolbox.destroy();
}
else {
aCallback();
@ -321,13 +309,7 @@ function waitForSuccess(aOptions)
function openInspector(aCallback, aTab = gBrowser.selectedTab)
{
let target = TargetFactory.forTab(aTab);
let inspector = gDevTools.getPanelForTarget("inspector", target);
if (inspector && inspector.isReady) {
aCallback(inspector);
} else {
let toolbox = gDevTools.openToolboxForTab(target, "inspector");
toolbox.once("inspector-ready", function _onSelect(aEvent, aPanel) {
aCallback(aPanel);
});
}
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
aCallback(toolbox.getCurrentPanel());
});
}

Some files were not shown because too many files have changed in this diff Show More