Bug 788977 - [toolbox] Land the developer tools window; r=harth,jwalker,mikeratcliffe,paul,dão

This commit is contained in:
Joe Walker 2012-11-22 21:35:19 +00:00
parent b4af68ab55
commit e9233b2864
325 changed files with 10297 additions and 10105 deletions

View File

@ -1010,11 +1010,16 @@ pref("devtools.toolbar.visible", false);
pref("devtools.gcli.allowSet", false);
pref("devtools.commands.dir", "");
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500);
pref("devtools.toolbox.host", "bottom");
pref("devtools.toolbox.selectedTool", "webconsole");
pref("devtools.toolbox.toolbarSpec", '["tilt toggle","scratchpad","resize toggle"]');
pref("devtools.toolbox.sideEnabled", false);
// Enable the Inspector
pref("devtools.inspector.enabled", true);
pref("devtools.inspector.htmlHeight", 112);
pref("devtools.inspector.htmlPanelOpen", false);
pref("devtools.inspector.sidebarOpen", false);
pref("devtools.inspector.activeSidebar", "ruleview");
pref("devtools.inspector.markupPreview", false);
@ -1046,17 +1051,11 @@ pref("devtools.debugger.ui.variables-sorting-enabled", true);
pref("devtools.debugger.ui.variables-non-enum-visible", true);
pref("devtools.debugger.ui.variables-searchbox-visible", false);
// Enable the style inspector
pref("devtools.styleinspector.enabled", true);
// Enable the Tilt inspector
pref("devtools.tilt.enabled", true);
pref("devtools.tilt.intro_transition", true);
pref("devtools.tilt.outro_transition", true);
// Enable the rules view
pref("devtools.ruleview.enabled", true);
// Enable the Scratchpad tool.
pref("devtools.scratchpad.enabled", true);
@ -1081,17 +1080,6 @@ pref("devtools.gcli.eagerHelper", 2);
// Do we allow the 'pref set' command
pref("devtools.gcli.allowSet", false);
// The last Web Console height. This is initially 0 which means that the Web
// Console will use the default height next time it shows.
// Change to -1 if you do not want the Web Console to remember its last height.
pref("devtools.hud.height", 0);
// Remember the Web Console position. Possible values:
// above - above the web page,
// below - below the web page,
// window - in a separate window/popup panel.
pref("devtools.webconsole.position", "below");
// Remember the Web Console filters
pref("devtools.webconsole.filter.network", true);
pref("devtools.webconsole.filter.networkinfo", true);

View File

@ -150,20 +150,27 @@
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup">
<menuitem id="appmenu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar"/>
<menuitem id="appmenu_webConsole" observes="devtoolsMenuBroadcaster_WebConsole"/>
<menuitem id="appmenu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
<menuitem id="appmenu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect"/>
<menuitem id="appmenu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
<menuitem id="appmenu_debugger" observes="devtoolsMenuBroadcaster_Debugger"/>
<menuitem id="appmenu_remoteDebugger" observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
<menuitem id="appmenu_chromeDebugger" observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
<menuitem id="appmenu_scratchpad" observes="devtoolsMenuBroadcaster_Scratchpad"/>
<menuitem id="appmenu_styleeditor" observes="devtoolsMenuBroadcaster_StyleEditor"/>
<menuitem id="appmenu_pageSource" observes="devtoolsMenuBroadcaster_PageSource"/>
<menuitem id="appmenu_errorConsole" observes="devtoolsMenuBroadcaster_ErrorConsole"/>
<menuitem id="appmenu_devToolbox"
observes="devtoolsMenuBroadcaster_DevToolbox"/>
<menuseparator id="appmenu_devtools_separator"/>
<menuitem id="appmenu_devToolbar"
observes="devtoolsMenuBroadcaster_DevToolbar"/>
<menuitem id="appmenu_remoteWebConsole"
observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
<menuitem id="appmenu_responsiveUI"
observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
<menuitem id="appmenu_scratchpad"
observes="devtoolsMenuBroadcaster_Scratchpad"/>
<menuitem id="appmenu_pageSource"
observes="devtoolsMenuBroadcaster_PageSource"/>
<menuitem id="appmenu_errorConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"/>
<menuseparator id="appmenu_devToolsConnectSeparator"/>
<menuitem id="appmenu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="appmenu_devToolsEndSeparator"/>
<menuitem id="appmenu_getMoreDevtools" observes="devtoolsMenuBroadcaster_GetMoreTools"/>
<menuitem id="appmenu_getMoreDevtools"
observes="devtoolsMenuBroadcaster_GetMoreTools"/>
<menuseparator/>
#define ID_PREFIX appmenu_developer_
#define OMIT_ACCESSKEYS

View File

@ -19,7 +19,5 @@
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd">
%debuggerDTD;
]>

View File

@ -557,20 +557,34 @@
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup">
<menuitem id="menu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar" accesskey="&devToolbarMenu.accesskey;"/>
<menuitem id="webConsole" observes="devtoolsMenuBroadcaster_WebConsole" accesskey="&webConsoleCmd.accesskey;"/>
<menuitem id="menu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
<menuitem id="menu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect" accesskey="&inspectMenu.accesskey;"/>
<menuitem id="menu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI" accesskey="&responsiveDesignTool.accesskey;"/>
<menuitem id="menu_debugger" observes="devtoolsMenuBroadcaster_Debugger" accesskey="&debuggerMenu.accesskey;"/>
<menuitem id="menu_remoteDebugger" observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
<menuitem id="menu_chromeDebugger" observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
<menuitem id="menu_scratchpad" observes="devtoolsMenuBroadcaster_Scratchpad" accesskey="&scratchpad.accesskey;"/>
<menuitem id="menu_styleeditor" observes="devtoolsMenuBroadcaster_StyleEditor" accesskey="&styleeditor.accesskey;"/>
<menuitem id="menu_pageSource" observes="devtoolsMenuBroadcaster_PageSource" accesskey="&pageSourceCmd.accesskey;"/>
<menuitem id="javascriptConsole" observes="devtoolsMenuBroadcaster_ErrorConsole" accesskey="&errorConsoleCmd.accesskey;"/>
<menuitem id="menu_devToolbox"
observes="devtoolsMenuBroadcaster_DevToolbox"
accesskey="&devToolbox.accesskey;"/>
<menuseparator id="menu_devtools_separator"/>
<menuitem id="menu_devToolbar"
observes="devtoolsMenuBroadcaster_DevToolbar"
accesskey="&devToolbarMenu.accesskey;"/>
<menuitem id="menu_remoteWebConsole"
observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
<menuitem id="menu_responsiveUI"
observes="devtoolsMenuBroadcaster_ResponsiveUI"
accesskey="&responsiveDesignTool.accesskey;"/>
<menuitem id="menu_scratchpad"
observes="devtoolsMenuBroadcaster_Scratchpad"
accesskey="&scratchpad.accesskey;"/>
<menuitem id="menu_pageSource"
observes="devtoolsMenuBroadcaster_PageSource"
accesskey="&pageSourceCmd.accesskey;"/>
<menuitem id="javascriptConsole"
observes="devtoolsMenuBroadcaster_ErrorConsole"
accesskey="&errorConsoleCmd.accesskey;"/>
<menuseparator id="menu_devToolsConnectSeparator"/>
<menuitem id="menu_devtools_connect"
observes="devtoolsMenuBroadcaster_connect"/>
<menuseparator id="devToolsEndSeparator"/>
<menuitem id="getMoreDevtools" observes="devtoolsMenuBroadcaster_GetMoreTools" accesskey="&getMoreDevtoolsCmd.accesskey;"/>
<menuitem id="getMoreDevtools"
observes="devtoolsMenuBroadcaster_GetMoreTools"
accesskey="&getMoreDevtoolsCmd.accesskey;"/>
</menupopup>
</menu>
<menuitem id="menu_pageInfo"

View File

@ -88,19 +88,15 @@
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:DevToolbox" oncommand="gDevTools.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:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
<command id="Tools:RemoteWebConsole" oncommand="HUDConsoleUI.toggleRemoteHUD();" disabled="true" hidden="true"/>
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();"/>
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true" hidden="true"/>
<command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true" hidden="true"/>
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
<command id="Tools:StyleEditor" oncommand="StyleEditor.toggle();" disabled="true" hidden="true"/>
<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:Sanitize"
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
<command id="Tools:PrivateBrowsing"
@ -127,27 +123,6 @@
oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
</commandset>
<commandset id="inspectorCommands">
<command id="Inspector:Inspect"
oncommand="InspectorUI.toggleInspection();"/>
<command id="Inspector:Sidebar"
oncommand="InspectorUI.toggleSidebar();"/>
<command id="Inspector:Tilt"
oncommand="Tilt.initialize();"/>
<command id="Inspector:HTMLPanel"
oncommand="InspectorUI.toggleHTMLPanel();"/>
<command id="Inspector:CopyInner"
oncommand="InspectorUI.copyInnerHTML();"/>
<command id="Inspector:CopyOuter"
oncommand="InspectorUI.copyOuterHTML();"/>
<command id="Inspector:DeleteNode"
oncommand="InspectorUI.deleteNode();"/>
<command id="Inspector:ToggleVeil"
oncommand="InspectorUI.toggleVeil();"/>
<command id="Inspector:ToggleInfobar"
oncommand="InspectorUI.toggleInfobar();"/>
</commandset>
<broadcasterset id="mainBroadcasterSet">
<broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
@ -195,45 +170,23 @@
<broadcaster id="socialSidebarBroadcaster" hidden="true"/>
<!-- DevTools broadcasters -->
<broadcaster id="devtoolsMenuBroadcaster_DevToolbox"
label="&devToolbarToolsButton.label;"
type="checkbox" autocheck="false"
command="Tools:DevToolbox"/>
<broadcaster id="devtoolsMenuBroadcaster_DevToolbar"
label="&devToolbarMenu.label;"
type="checkbox" autocheck="false"
command="Tools:DevToolbar"
key="key_devToolbar"/>
<broadcaster id="devtoolsMenuBroadcaster_WebConsole"
label="&webConsoleCmd.label;"
type="checkbox" autocheck="false"
key="key_webConsole"
command="Tools:WebConsole"/>
<broadcaster id="devtoolsMenuBroadcaster_RemoteWebConsole"
label="&remoteWebConsoleCmd.label;"
type="checkbox" autocheck="false"
command="Tools:RemoteWebConsole"/>
<broadcaster id="devtoolsMenuBroadcaster_Inspect"
label="&inspectMenu.label;"
type="checkbox" autocheck="false"
command="Tools:Inspect"
key="key_inspect"/>
<broadcaster id="devtoolsMenuBroadcaster_Debugger"
label="&debuggerMenu.label2;"
type="checkbox" autocheck="false"
command="Tools:Debugger"
key="key_debugger"/>
<broadcaster id="devtoolsMenuBroadcaster_RemoteDebugger"
label="&remoteDebuggerMenu.label;"
command="Tools:RemoteDebugger"/>
<broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger"
label="&chromeDebuggerMenu.label;"
command="Tools:ChromeDebugger"/>
<broadcaster id="devtoolsMenuBroadcaster_Scratchpad"
label="&scratchpad.label;"
command="Tools:Scratchpad"
key="key_scratchpad"/>
<broadcaster id="devtoolsMenuBroadcaster_StyleEditor"
label="&styleeditor.label;"
type="checkbox" autocheck="false"
command="Tools:StyleEditor"
key="key_styleeditor"/>
<broadcaster id="devtoolsMenuBroadcaster_ResponsiveUI"
label="&responsiveDesignTool.label;"
type="checkbox" autocheck="false"
@ -250,6 +203,9 @@
<broadcaster id="devtoolsMenuBroadcaster_GetMoreTools"
label="&getMoreDevtoolsCmd.label;"
oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
<broadcaster id="devtoolsMenuBroadcaster_connect"
label="&devtoolsConnect.label;"
command="Tools:DevToolsConnect"/>
<!-- SocialAPI broadcasters -->
<broadcaster id="socialBroadcaster_userDetails"
@ -271,7 +227,7 @@
#
# Search Command Key Logic works like this:
#
#
# Unix: Ctrl+K (cross platform binding)
# Ctrl+J (in case of emacs Ctrl-K conflict)
# Mac: Cmd+K (cross platform binding)
@ -303,27 +259,6 @@
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" command="Tools:ErrorConsole" modifiers="accel,shift"/>
<key id="key_devToolbar" keycode="&devToolbar.keycode;" modifiers="shift"
keytext="&devToolbar.keytext;" command="Tools:DevToolbarFocus"/>
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_debugger" key="&debuggerMenu.commandkey;" command="Tools:Debugger"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_inspect" key="&inspectMenu.commandkey;" command="Inspector:Inspect"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_responsiveUI" key="&responsiveDesignTool.commandkey;" command="Tools:ResponsiveUI"
#ifdef XP_MACOSX
modifiers="accel,alt"
@ -333,8 +268,6 @@
/>
<key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift"
keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/>
<key id="key_styleeditor" keycode="&styleeditor.keycode;" modifiers="shift"
keytext="&styleeditor.keytext;" command="Tools:StyleEditor"/>
<key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile" modifiers="accel"/>
<key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>
<key id="printKb" key="&printCmd.commandkey;" command="cmd_print" modifiers="accel"/>

View File

@ -562,10 +562,6 @@ statuspanel[inactive][previoustype=overLink] {
-moz-box-align: end;
}
.styleInspector {
min-width: 350px;
}
.panel-inner-arrowcontentfooter[footertype="promobox"] {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#promobox");
}
@ -593,22 +589,16 @@ html|*#gcli-output-frame,
direction: ltr;
}
#developer-toolbar-webconsole[error-count] > .toolbarbutton-icon {
#developer-toolbar-toolbox-button[error-count] > .toolbarbutton-icon {
display: none;
}
#developer-toolbar-webconsole[error-count]:before {
#developer-toolbar-toolbox-button[error-count]:before {
content: attr(error-count);
display: -moz-box;
-moz-box-pack: center;
}
/* We don't show the Style Editor button in the developer toolbar for now.
See bug 771203 */
#developer-toolbar-styleeditor {
display: none;
}
/* Responsive Mode */
.browserContainer[responsivemode] {

View File

@ -118,24 +118,6 @@ XPCOMUtils.defineLazyGetter(this, "DeveloperToolbar", function() {
return new tmp.DeveloperToolbar(window, document.getElementById("developer-toolbar"));
});
XPCOMUtils.defineLazyGetter(this, "InspectorUI", function() {
let tmp = {};
Cu.import("resource:///modules/inspector.jsm", tmp);
return new tmp.InspectorUI(window);
});
XPCOMUtils.defineLazyGetter(this, "DebuggerUI", function() {
let tmp = {};
Cu.import("resource:///modules/devtools/DebuggerUI.jsm", tmp);
return new tmp.DebuggerUI(window);
});
XPCOMUtils.defineLazyGetter(this, "Tilt", function() {
let tmp = {};
Cu.import("resource:///modules/devtools/Tilt.jsm", tmp);
return new tmp.Tilt(window);
});
XPCOMUtils.defineLazyGetter(this, "Social", function() {
let tmp = {};
Cu.import("resource:///modules/Social.jsm", tmp);
@ -1436,36 +1418,6 @@ var gBrowserInit = {
}
}
// Enable Debugger?
let enabled = gPrefService.getBoolPref("devtools.debugger.enabled");
if (enabled) {
let cmd = document.getElementById("Tools:Debugger");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
// Enable Remote Debugger?
let enabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
if (enabled) {
let cmd = document.getElementById("Tools:RemoteDebugger");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
cmd = document.getElementById("Tools:RemoteWebConsole");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
// Enable Chrome Debugger?
let enabled = gPrefService.getBoolPref("devtools.chrome.enabled") &&
gPrefService.getBoolPref("devtools.debugger.chrome-enabled") &&
gPrefService.getBoolPref("devtools.debugger.remote-enabled");
if (enabled) {
let cmd = document.getElementById("Tools:ChromeDebugger");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
// Enable Error Console?
// Temporarily enabled. See bug 798925.
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled") ||
@ -1484,14 +1436,6 @@ var gBrowserInit = {
cmd.removeAttribute("hidden");
}
// Enable Style Editor?
let styleEditorEnabled = gPrefService.getBoolPref(StyleEditor.prefEnabledName);
if (styleEditorEnabled) {
let cmd = document.getElementById("Tools:StyleEditor");
cmd.removeAttribute("disabled");
cmd.removeAttribute("hidden");
}
#ifdef MENUBAR_CAN_AUTOHIDE
// If the user (or the locale) hasn't enabled the top-level "Character
// Encoding" menu via the "browser.menu.showCharacterEncoding" preference,
@ -1509,6 +1453,9 @@ var gBrowserInit = {
cmd.removeAttribute("hidden");
}
// Add Devtools menuitems and listeners
gDevTools.registerBrowserWindow(window);
let appMenuButton = document.getElementById("appmenu-button");
let appMenuPopup = document.getElementById("appmenu-popup");
if (appMenuButton && appMenuPopup) {
@ -1551,8 +1498,7 @@ var gBrowserInit = {
if (!gStartupRan)
return;
if (!__lookupGetter__("InspectorUI"))
InspectorUI.destroy();
gDevTools.forgetBrowserWindow(window);
// First clean up services initialized in gBrowserInit.onLoad (or those whose
// uninit methods don't depend on the services having been initialized).
@ -1650,7 +1596,7 @@ var gBrowserInit = {
'viewToolbarsMenu', 'viewSidebarMenuMenu', 'Browser:Reload',
'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
'viewHistorySidebar', 'Browser:AddBookmarkAs', 'Browser:BookmarkAllTabs',
'View:PageInfo', 'Tasks:InspectPage', 'Browser:ToggleTabView', 'Browser:ToggleAddonBar'];
'View:PageInfo', 'Browser:ToggleTabView', 'Browser:ToggleAddonBar'];
var element;
for (let disabledItem of disabledItems) {
@ -7456,6 +7402,12 @@ var TabContextMenu = {
}
};
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsXULCommands",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
let tempScope = {};
Cu.import("resource:///modules/HUDService.jsm", tempScope);
@ -7551,41 +7503,6 @@ XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() {
return tmp.ResponsiveUIManager;
});
var StyleEditor = {
prefEnabledName: "devtools.styleeditor.enabled",
/**
* Opens the style editor. If the UI is already open, it will be focused.
*
* @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
* @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
* @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
*/
openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
{
let contentWindow = gBrowser.selectedBrowser.contentWindow;
let win = this.StyleEditorManager.getEditorForWindow(contentWindow);
if (win) {
this.StyleEditorManager.selectEditor(win);
return win;
} else {
return this.StyleEditorManager.newEditor(contentWindow, window,
aSelectedStyleSheet, aLine, aCol);
}
},
toggle: function SE_toggle()
{
this.StyleEditorManager.toggleEditor(gBrowser.contentWindow, window);
}
};
XPCOMUtils.defineLazyGetter(StyleEditor, "StyleEditorManager", function() {
let tmp = {};
Cu.import("resource:///modules/devtools/StyleEditor.jsm", tmp);
return new tmp.StyleEditorManager(window);
});
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN
// Only show resizers on Windows 2000 and XP

View File

@ -278,22 +278,6 @@
noautofocus="true"
position="topcenter topright"/>
<menupopup id="inspector-node-popup">
<menuitem id="inspectorHTMLCopyInner"
label="&inspectorHTMLCopyInner.label;"
accesskey="&inspectorHTMLCopyInner.accesskey;"
command="Inspector:CopyInner"/>
<menuitem id="inspectorHTMLCopyOuter"
label="&inspectorHTMLCopyOuter.label;"
accesskey="&inspectorHTMLCopyOuter.accesskey;"
command="Inspector:CopyOuter"/>
<menuseparator/>
<menuitem id="inspectorHTMLDelete"
label="&inspectorHTMLDelete.label;"
accesskey="&inspectorHTMLDelete.accesskey;"
command="Inspector:DeleteNode"/>
</menupopup>
<menupopup id="toolbar-context-menu"
onpopupshowing="onViewToolbarsPopupShowing(event);">
<menuseparator/>
@ -1064,19 +1048,6 @@
<chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
<statuspanel id="statusbar-display" inactive="true"/>
</vbox>
<splitter id="devtools-side-splitter" hidden="true"/>
<vbox id="devtools-sidebar-box" hidden="true"
style="min-width: 18em; width: 22em; max-width: 42em;" persist="width">
<toolbar id="devtools-sidebar-toolbar"
class="devtools-toolbar"
nowindowdrag="true">
<spacer flex="1"/>
<toolbarbutton tooltiptext="&inspectSidebarCloseButton.tooltiptext;"
class="devtools-closebutton"
command="Inspector:Sidebar"/>
</toolbar>
<deck id="devtools-sidebar-deck" flex="1"/>
</vbox>
<splitter id="social-sidebar-splitter"
class="chromeclass-extrachrome sidebar-splitter"
observes="socialSidebarBroadcaster"/>
@ -1115,52 +1086,6 @@
</hbox>
<vbox id="browser-bottombox" layer="true">
<toolbar id="inspector-toolbar"
class="devtools-toolbar"
nowindowdrag="true"
hidden="true">
#ifdef XP_MACOSX
<toolbarbutton id="highlighter-closebutton"
class="devtools-closebutton"
oncommand="InspectorUI.closeInspectorUI(false);"
tooltiptext="&inspectCloseButton.tooltiptext;"/>
#endif
<toolbarbutton id="inspector-inspect-toolbutton"
class="devtools-toolbarbutton"
command="Inspector:Inspect"/>
<toolbarbutton id="inspector-treepanel-toolbutton"
class="devtools-toolbarbutton"
tabindex="0"
aria-label="&markupButton.arialabel;"
accesskey="&markupButton.accesskey;"
command="Inspector:HTMLPanel"/>
<arrowscrollbox id="inspector-breadcrumbs"
flex="1" orient="horizontal"
clicktoscroll="true"/>
<hbox id="inspector-tools">
<toolbarbutton id="inspector-3D-button"
class="devtools-toolbarbutton"
hidden="true"
label="&inspect3DViewButton.label;"
accesskey="&inspect3DViewButton.accesskey;"
tabindex="0"
command="Inspector:Tilt"/>
<toolbarbutton id="inspector-style-button"
class="devtools-toolbarbutton"
label="&inspectStyleButton.label;"
accesskey="&inspectStyleButton.accesskey;"
tabindex="0"
command="Inspector:Sidebar"/>
<!-- registered tools go here -->
</hbox>
#ifndef XP_MACOSX
<toolbarbutton id="highlighter-closebutton"
class="devtools-closebutton"
oncommand="InspectorUI.closeInspectorUI(false);"
tooltiptext="&inspectCloseButton.tooltiptext;"/>
#endif
</toolbar>
<toolbar id="developer-toolbar"
class="devtools-toolbar"
hidden="true">
@ -1177,36 +1102,9 @@
<hbox class="gclitoolbar-complete-node"/>
<textbox class="gclitoolbar-input-node" rows="1"/>
</stack>
<toolbarbutton id="developer-toolbar-webconsole"
<toolbarbutton id="developer-toolbar-toolbox-button"
class="developer-toolbar-button"
observes="devtoolsMenuBroadcaster_WebConsole"/>
<toolbarbutton id="developer-toolbar-inspector"
class="developer-toolbar-button"
observes="devtoolsMenuBroadcaster_Inspect"/>
<toolbarbutton id="developer-toolbar-styleeditor"
class="developer-toolbar-button"
observes="devtoolsMenuBroadcaster_StyleEditor"/>
<toolbarbutton id="developer-toolbar-debugger"
class="developer-toolbar-button"
observes="devtoolsMenuBroadcaster_Debugger"/>
<toolbarbutton id="developer-toolbar-other-tools"
type="menu"
class="developer-toolbar-button"
label="&devToolbarOtherToolsButton.label;">
<menupopup position="before_end">
<menuitem observes="devtoolsMenuBroadcaster_DevToolbar"/>
<menuitem observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
<menuitem observes="devtoolsMenuBroadcaster_RemoteDebugger"/>
<menuitem observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
<menuitem observes="devtoolsMenuBroadcaster_Scratchpad"/>
<menuitem observes="devtoolsMenuBroadcaster_StyleEditor"/>
<menuitem observes="devtoolsMenuBroadcaster_PageSource"/>
<menuitem observes="devtoolsMenuBroadcaster_ErrorConsole"/>
<menuseparator/>
<menuitem observes="devtoolsMenuBroadcaster_GetMoreTools"/>
</menupopup>
</toolbarbutton>
observes="devtoolsMenuBroadcaster_DevToolbox"/>
#ifndef XP_MACOSX
<toolbarbutton id="developer-toolbar-closebutton"
class="devtools-closebutton"

View File

@ -2,64 +2,60 @@
* 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/. */
#highlighter-container {
.highlighter-container {
pointer-events: none;
}
#highlighter-controls {
.highlighter-controls {
position: absolute;
top: 0;
left: 0;
}
#highlighter-outline-container {
.highlighter-outline-container {
overflow: hidden;
position: relative;
}
#highlighter-outline {
.highlighter-outline {
position: absolute;
}
#highlighter-outline[hidden] {
.highlighter-outline[hidden] {
opacity: 0;
pointer-events: none;
display: -moz-box;
}
#highlighter-outline:not([disable-transitions]) {
.highlighter-outline:not([disable-transitions]) {
transition-property: opacity, top, left, width, height;
transition-duration: 0.1s;
transition-timing-function: linear;
}
.inspector-breadcrumbs-button {
direction: ltr;
}
/*
* Node Infobar
*/
#highlighter-nodeinfobar-container {
.highlighter-nodeinfobar-container {
position: absolute;
max-width: 95%;
}
#highlighter-nodeinfobar-container[hidden] {
.highlighter-nodeinfobar-container[hidden] {
opacity: 0;
pointer-events: none;
display: -moz-box;
}
#highlighter-nodeinfobar-container:not([disable-transitions]),
#highlighter-nodeinfobar-container[disable-transitions][force-transitions] {
.highlighter-nodeinfobar-container:not([disable-transitions]),
.highlighter-nodeinfobar-container[disable-transitions][force-transitions] {
transition-property: transform, opacity, top, left;
transition-duration: 0.1s;
transition-timing-function: linear;
}
#highlighter-nodeinfobar-text {
.highlighter-nodeinfobar-text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@ -70,19 +66,19 @@
display: none;
}
#highlighter-nodeinfobar-container:not([locked]):not(:hover) > #highlighter-nodeinfobar > .highlighter-nodeinfobar-button {
.highlighter-nodeinfobar-container:not([locked]):not(:hover) > .highlighter-nodeinfobar > .highlighter-nodeinfobar-button {
visibility: hidden;
}
#highlighter-nodeinfobar-container[locked] > #highlighter-nodeinfobar,
#highlighter-nodeinfobar-container:not([locked]):hover > #highlighter-nodeinfobar {
.highlighter-nodeinfobar-container[locked] > .highlighter-nodeinfobar,
.highlighter-nodeinfobar-container:not([locked]):hover > .highlighter-nodeinfobar {
pointer-events: auto;
}
html|*#highlighter-nodeinfobar-id,
html|*#highlighter-nodeinfobar-classes,
html|*#highlighter-nodeinfobar-pseudo-classes,
html|*#highlighter-nodeinfobar-tagname {
html|*.highlighter-nodeinfobar-id,
html|*.highlighter-nodeinfobar-classes,
html|*.highlighter-nodeinfobar-pseudo-classes,
html|*.highlighter-nodeinfobar-tagname {
-moz-user-select: text;
cursor: text;
}
@ -91,41 +87,18 @@ html|*#highlighter-nodeinfobar-tagname {
display: none;
}
#highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > #highlighter-nodeinfobar-arrow-bottom {
.highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-bottom {
display: block;
}
#highlighter-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > #highlighter-nodeinfobar-arrow-top {
.highlighter-nodeinfobar-container[position="bottom"]:not([hide-arrow]) > .highlighter-nodeinfobar-arrow-top {
display: block;
}
#highlighter-nodeinfobar-container[disabled] {
.highlighter-nodeinfobar-container[disabled] {
visibility: hidden;
}
html|*#highlighter-nodeinfobar-tagname {
html|*.highlighter-nodeinfobar-tagname {
text-transform: lowercase;
}
.devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
display: none;
}
#inspector-option-toolbarbutton > .toolbarbutton-menu-dropmarker {
display: none;
}
#inspector-layoutview-container > iframe {
/* header size */
height: 28px;
}
#inspector-layoutview-container:not([disable-transitions]) > iframe {
transition-property: height;
transition-duration: 0.2s;
}
#inspector-layoutview-container > iframe[open] {
/* header size + layout view size: 28px + 145px */
height: 173px;
}

View File

@ -412,11 +412,19 @@ nsContextMenu.prototype = {
},
inspectNode: function CM_inspectNode() {
if (InspectorUI.isTreePanelOpen) {
InspectorUI.inspectNode(this.target);
InspectorUI.stopInspecting();
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 {
InspectorUI.openInspectorUI(this.target);
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));
}
},

View File

@ -13,7 +13,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/config.mk
DIRS = \
highlighter \
inspector \
markupview \
webconsole \
commandline \
@ -26,6 +26,7 @@ DIRS = \
layoutview \
shared \
responsivedesign \
framework \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -12,6 +12,12 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
/**
* 'break' command
*/
@ -30,12 +36,15 @@ gcli.addCommand({
description: gcli.lookup("breaklistDesc"),
returnType: "html",
exec: function(args, context) {
let win = HUDService.currentContext();
let dbg = win.DebuggerUI.getDebugger();
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");
}
let breakpoints = dbg.breakpoints;
let breakpoints = dbg.getAllBreakpoints();
if (Object.keys(breakpoints).length === 0) {
return gcli.lookup("breaklistNone");
@ -76,11 +85,13 @@ gcli.addCommand({
type: {
name: "selection",
data: function() {
let win = HUDService.currentContext();
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = HUDService.currentContext().gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
let files = [];
if (dbg) {
let sourcesView = dbg.contentWindow.DebuggerView.Sources;
let sourcesView = dbg.panelWin.DebuggerView.Sources;
for (let item in sourcesView) {
files.push(item.value);
}
@ -99,8 +110,11 @@ gcli.addCommand({
returnType: "html",
exec: function(args, context) {
args.type = "line";
let win = HUDService.currentContext();
let dbg = win.DebuggerUI.getDebugger();
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");
}
@ -131,12 +145,14 @@ gcli.addCommand({
name: "number",
min: 0,
max: function() {
let win = HUDService.currentContext();
let dbg = win.DebuggerUI.getDebugger();
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.breakpoints).length - 1;
return Object.keys(dbg.getAllBreakpoints()).length - 1;
},
},
description: gcli.lookup("breakdelBreakidDesc")
@ -144,14 +160,16 @@ gcli.addCommand({
],
returnType: "html",
exec: function(args, context) {
let win = HUDService.currentContext();
let dbg = win.DebuggerUI.getDebugger();
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");
}
let breakpoints = dbg.breakpoints;
let id = Object.keys(dbg.breakpoints)[args.breakid];
let breakpoints = dbg.getAllBreakpoints();
let id = Object.keys(breakpoints)[args.breakid];
if (!id || !(id in breakpoints)) {
return gcli.lookup("breakNotFound");
}

View File

@ -9,8 +9,8 @@ this.EXPORTED_SYMBOLS = [ ];
Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
let JsDebugger = {};
@ -22,6 +22,9 @@ XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
return global.Debugger;
});
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
let debuggers = [];
/**
@ -50,8 +53,9 @@ gcli.addCommand({
debuggers.push(dbg);
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab;
HUDService.activateHUDForContext(tab);
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
return gcli.lookup("calllogStartReply");
},

View File

@ -10,8 +10,10 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
XPCOMUtils.defineLazyGetter(this, "Debugger", function() {
let JsDebugger = {};
@ -108,8 +110,9 @@ gcli.addCommand({
": " + this.callDescription(frame));
}.bind(this);
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab;
HUDService.activateHUDForContext(tab);
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
return gcli.lookup("calllogChromeStartReply");
},

View File

@ -11,6 +11,10 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
/**
* 'console' command
@ -44,8 +48,9 @@ gcli.addCommand({
name: "console close",
description: gcli.lookup("consolecloseDesc"),
exec: function Command_consoleClose(args, context) {
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
HUDService.deactivateHUDForContext(tab);
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
}
});
@ -56,7 +61,8 @@ gcli.addCommand({
name: "console open",
description: gcli.lookup("consoleopenDesc"),
exec: function Command_consoleOpen(args, context) {
let tab = context.environment.chromeDocument.defaultView.gBrowser.selectedTab
HUDService.activateHUDForContext(tab);
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "webconsole");
}
});

View File

@ -9,6 +9,11 @@ this.EXPORTED_SYMBOLS = [ ];
Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
/**
* 'dbg' command
*/
@ -26,19 +31,9 @@ gcli.addCommand({
description: gcli.lookup("dbgOpen"),
params: [],
exec: function (args, context) {
let win = context.environment.chromeDocument.defaultView;
let tab = win.gBrowser.selectedTab;
let dbg = win.DebuggerUI.findDebugger();
if (dbg) {
if (dbg.ownerTab !== tab) {
win.DebuggerUI.toggleDebugger();
}
return;
}
win.DebuggerUI.toggleDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.openToolboxForTab(target, "jsdebugger");
}
});
@ -50,12 +45,12 @@ gcli.addCommand({
description: gcli.lookup("dbgClose"),
params: [],
exec: function (args, context) {
let win = context.environment.chromeDocument.defaultView;
let tab = win.gBrowser.selectedTab;
let dbg = win.DebuggerUI.findDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
dbg.close();
if (dbg /* FIXME: and debugger panel is currently active */) {
gDevTools.closeToolbox(target);
}
}
});
@ -68,11 +63,12 @@ gcli.addCommand({
description: gcli.lookup("dbgInterrupt"),
params: [],
exec: function(args, context) {
let win = context.environment.chromeDocument.defaultView;
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
let controller = dbg.contentWindow.DebuggerController;
let controller = dbg._controller;
let thread = controller.activeThread;
if (!thread.paused) {
thread.interrupt();
@ -89,11 +85,12 @@ gcli.addCommand({
description: gcli.lookup("dbgContinue"),
params: [],
exec: function(args, context) {
let win = context.environment.chromeDocument.defaultView;
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
let controller = dbg.contentWindow.DebuggerController;
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.resume();
@ -121,11 +118,12 @@ gcli.addCommand({
description: gcli.lookup("dbgStepOverDesc"),
params: [],
exec: function(args, context) {
let win = context.environment.chromeDocument.defaultView;
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
let controller = dbg.contentWindow.DebuggerController;
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOver();
@ -142,11 +140,12 @@ gcli.addCommand({
description: gcli.lookup("dbgStepInDesc"),
params: [],
exec: function(args, context) {
let win = context.environment.chromeDocument.defaultView;
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
let controller = dbg.contentWindow.DebuggerController;
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepIn();
@ -163,11 +162,12 @@ gcli.addCommand({
description: gcli.lookup("dbgStepOutDesc"),
params: [],
exec: function(args, context) {
let win = context.environment.chromeDocument.defaultView;
let dbg = win.DebuggerUI.getDebugger();
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
if (dbg) {
let controller = dbg.contentWindow.DebuggerController;
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOut();

View File

@ -24,3 +24,4 @@ Cu.import("resource:///modules/devtools/CmdResize.jsm");
Cu.import("resource:///modules/devtools/CmdRestart.jsm");
Cu.import("resource:///modules/devtools/CmdScreenshot.jsm");
Cu.import("resource:///modules/devtools/CmdTilt.jsm");
Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");

View File

@ -1,3 +1,11 @@
/* 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 tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
function test() {
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_dbg_cmd.html";
@ -7,54 +15,40 @@ function test() {
});
}
function testDbgCmd() {
DeveloperToolbarTest.exec({
typed: "dbg open",
blankOutput: true
});
function testCommands(dbg, cmd) {
// Wait for the initial resume...
dbg._controller.activeThread.addOneTimeListener("resumed", function () {
info("Starting tests.");
let pane = DebuggerUI.findDebugger();
ok(pane, "Debugger was opened.");
let frame = pane._frame;
let contentDoc = content.window.document;
let output = contentDoc.querySelector("input[type=text]");
let btnDoit = contentDoc.querySelector("input[type=button]");
frame.addEventListener("Debugger:Connected", function dbgConnected(aEvent) {
frame.removeEventListener("Debugger:Connected", dbgConnected, true);
// Wait for the initial resume...
aEvent.target.ownerDocument.defaultView.gClient
.addOneTimeListener("resumed", function() {
info("Starting tests.");
let contentDoc = content.window.document;
let output = contentDoc.querySelector("input[type=text]");
let btnDoit = contentDoc.querySelector("input[type=button]");
cmd("dbg interrupt", function() {
ok(true, "debugger is paused");
pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
ok(true, "debugger continued");
pane.contentWindow.gClient.addOneTimeListener("paused", function() {
cmd("dbg interrupt", function() {
ok(true, "debugger is paused");
dbg._controller.activeThread.addOneTimeListener("resumed", function () {
ok(true, "debugger continued");
dbg._controller.activeThread.addOneTimeListener("paused", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
is(output.value, "step in", "debugger stepped in");
cmd("dbg step over", function() {
is(output.value, "step over", "debugger stepped over");
cmd("dbg step out", function() {
is(output.value, "step out", "debugger stepped out");
is(output.value, "step in", "debugger stepped in");
cmd("dbg step over", function() {
is(output.value, "step over", "debugger stepped over");
cmd("dbg step out", function() {
is(output.value, "step out", "debugger stepped out");
cmd("dbg continue", function() {
cmd("dbg continue", function() {
cmd("dbg continue", function() {
is(output.value, "dbg continue", "debugger continued");
DeveloperToolbarTest.exec({
typed: "dbg close",
blankOutput: true
});
let dbg = DebuggerUI.findDebugger();
ok(!dbg, "Debugger was closed.");
finish();
is(output.value, "dbg continue", "debugger continued");
DeveloperToolbarTest.exec({
typed: "dbg close",
blankOutput: true
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
ok(!gDevTools.getToolboxForTarget(target),
"Debugger was closed.");
finish();
});
});
});
@ -62,21 +56,42 @@ function testDbgCmd() {
});
});
});
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
});
DeveloperToolbarTest.exec({
typed: "dbg continue",
blankOutput: true
});
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
});
DeveloperToolbarTest.exec({
typed: "dbg continue",
blankOutput: true
});
});
});
}
function testDbgCmd() {
DeveloperToolbarTest.exec({
typed: "dbg open",
blankOutput: true
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolboxForTarget(target);
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
ok(dbg, "DebuggerPanel exists");
function cmd(aTyped, aCallback) {
pane.contentWindow.gClient.addOneTimeListener("paused", aCallback);
dbg._controller.activeThread.addOneTimeListener("paused", aCallback);
DeveloperToolbarTest.exec({
typed: aTyped,
blankOutput: true
});
}
if (dbg._controller.activeThread) {
testCommands(dbg, cmd);
} else {
dbg.once("connected", testCommands.bind(null, dbg, cmd));
}
});
}

View File

@ -6,6 +6,10 @@
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_dbg_cmd_break.html";
let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testBreakCommands ]);
}
@ -35,86 +39,84 @@ function testBreakCommands() {
status: 'ERROR'
});
let pane = DebuggerUI.toggleDebugger();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
ok(dbg, "DebuggerPanel exists");
dbg.once("connected", function() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
dbg._view.Variables.lazyEmpty = false;
var dbgConnected = DeveloperToolbarTest.checkCalled(function() {
pane._frame.removeEventListener("Debugger:Connected", dbgConnected, true);
// Wait for the initial resume.
let client = pane.contentWindow.gClient;
var resumed = DeveloperToolbarTest.checkCalled(function() {
var framesAdded = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break add line ' + TEST_URI + ' ' + content.wrappedJSObject.line0);
helpers.check({
hints: '',
status: 'VALID',
args: {
file: { value: TEST_URI },
line: { value: content.wrappedJSObject.line0 },
}
});
DeveloperToolbarTest.exec({
args: {
type: 'line',
file: TEST_URI,
line: content.wrappedJSObject.line0
},
completed: false
});
helpers.setInput('break list');
helpers.check({
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
var cleanup = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break del 9');
var client = dbg.panelWin.gClient;
var framesAdded = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break add line ' + TEST_URI + ' ' + content.wrappedJSObject.line0);
helpers.check({
input: 'break del 9',
hints: '',
markup: 'VVVVVVVVVVE',
status: 'ERROR',
args: {
breakid: { status: 'ERROR', message: '9 is greater than maximum allowed: 0.' },
}
});
helpers.setInput('break del 0');
helpers.check({
input: 'break del 0',
hints: '',
markup: 'VVVVVVVVVVV',
hints: '',
status: 'VALID',
args: {
breakid: { value: 0 },
file: { value: TEST_URI },
line: { value: content.wrappedJSObject.line0 },
}
});
DeveloperToolbarTest.exec({
args: { breakid: 0 },
args: {
type: 'line',
file: TEST_URI,
line: content.wrappedJSObject.line0
},
completed: false
});
helpers.setInput('break list');
helpers.check({
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
var cleanup = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break del 9');
helpers.check({
input: 'break del 9',
hints: '',
markup: 'VVVVVVVVVVE',
status: 'ERROR',
args: {
breakid: { status: 'ERROR', message: '9 is greater than maximum allowed: 0.' },
}
});
helpers.setInput('break del 0');
helpers.check({
input: 'break del 0',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID',
args: {
breakid: { value: 0 },
}
});
DeveloperToolbarTest.exec({
args: { breakid: 0 },
completed: false
});
});
client.activeThread.resume(cleanup);
});
client.activeThread.resume(cleanup);
client.activeThread.addOneTimeListener("framesadded", framesAdded);
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
client.activeThread.addOneTimeListener("framesadded", framesAdded);
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
client.addOneTimeListener("resumed", resumed);
});
pane._frame.addEventListener("Debugger:Connected", dbgConnected, true);
}

View File

@ -0,0 +1,144 @@
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
this.EXPORTED_SYMBOLS = ["DebuggerDefinition"];
const STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
"resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
"resource://gre/modules/devtools/dbg-server.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyGetter(this, "_strings",
function() Services.strings.createBundle(STRINGS_URI));
XPCOMUtils.defineLazyGetter(this, "osString", function() {
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
});
this.DebuggerDefinition = {
id: "jsdebugger",
key: l10n("open.commandkey"),
accesskey: l10n("debuggerMenu.accesskey"),
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 1,
killswitch: "devtools.debugger.enabled",
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
url: "chrome://browser/content/debugger.xul",
label: l10n("ToolboxDebugger.label"),
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new DebuggerPanel(iframeWindow, toolbox);
}
};
function DebuggerPanel(iframeWindow, toolbox) {
this._toolbox = toolbox;
this._controller = iframeWindow.DebuggerController;
this._view = iframeWindow.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 = {
// DevToolPanel API
get target() this._toolbox.target,
get isReady() this._isReady,
setReady: function() {
this._isReady = true;
this.emit("ready");
},
destroy: function() {
delete this._toolbox;
delete this._target;
delete this._controller;
delete this._view;
delete this._bkp;
delete this.panelWin;
},
// DebuggerPanel API
addBreakpoint: function() {
this._bkp.addBreakpoint.apply(this._bkp, arguments);
},
removeBreakpoint: function() {
this._bkp.removeBreakpoint.apply(this._bkp, arguments);
},
getBreakpoint: function() {
return this._bkp.getBreakpoint.apply(this._bkp, arguments);
},
getAllBreakpoints: function() {
return this._bkp.store;
},
// Private
_ensureOnlyOneRunningDebugger: function() {
// FIXME
},
};
/**
* Lookup l10n string from a string bundle.
* @param {string} aName The key to lookup.
* @returns A localized version of the given key.
*/
function l10n(aName)
{
try {
return _strings.GetStringFromName(aName);
} catch (ex) {
Services.console.logStringMessage("Error reading '" + aName + "'");
throw new Error("l10n error with " + aName);
}
}

View File

@ -48,6 +48,7 @@ let DebuggerController = {
return;
}
this._isInitialized = true;
window.removeEventListener("load", this._startupDebugger, true);
DebuggerView.initialize(function() {
@ -145,14 +146,32 @@ let DebuggerController = {
* wiring event handlers as necessary.
*/
_connect: function DC__connect() {
if (window._isRemoteDebugger && !this._prepareConnection()) {
function callback() {
window.dispatchEvent("Debugger:Connected");
}
let client;
// Remote debugging gets the debuggee from a RemoteTarget object.
if (this._target.isRemote) {
client = this.client = this._target.client;
this._target.on("close", this._onTabDetached);
this._target.on("navigate", this._onTabNavigated);
if (this._target.chrome) {
let dbg = this._target.form.chromeDebugger;
this._startChromeDebugging(client, dbg, callback);
} else {
this._startDebuggingTab(client, this._target.form, callback);
}
return;
}
let transport = (window._isChromeDebugger || window._isRemoteDebugger)
? debuggerSocketConnect(Prefs.remoteHost, Prefs.remotePort)
: DebuggerServer.connectPipe();
let client = this.client = new DebuggerClient(transport);
// Content debugging can connect directly to the page.
// TODO: convert this to use a TabTarget.
let transport = DebuggerServer.connectPipe();
client = this.client = new DebuggerClient(transport);
client.addListener("tabNavigated", this._onTabNavigated);
client.addListener("tabDetached", this._onTabDetached);
@ -160,12 +179,11 @@ let DebuggerController = {
client.listTabs(function(aResponse) {
if (window._isChromeDebugger) {
let dbg = aResponse.chromeDebugger;
this._startChromeDebugging(client, dbg);
this._startChromeDebugging(client, dbg, callback);
} else {
let tab = aResponse.tabs[aResponse.selected];
this._startDebuggingTab(client, tab);
this._startDebuggingTab(client, tab, callback);
}
window.dispatchEvent("Debugger:Connected");
}.bind(this));
}.bind(this));
},
@ -180,9 +198,12 @@ let DebuggerController = {
}
this.client.removeListener("tabNavigated", this._onTabNavigated);
this.client.removeListener("tabDetached", this._onTabDetached);
this.client.close();
this.client = null;
if (!this._target.isRemote) {
this.client.close();
this.client = null;
}
this.tabClient = null;
this.activeThread = null;
},
@ -212,7 +233,8 @@ let DebuggerController = {
* @param object aTabGrip
* The remote protocol grip of the tab.
*/
_startDebuggingTab: function DC__startDebuggingTab(aClient, aTabGrip) {
_startDebuggingTab: function DC__startDebuggingTab
(aClient, aTabGrip, aCallback=function(){}) {
if (!aClient) {
Cu.reportError("No client found!");
return;
@ -238,6 +260,7 @@ let DebuggerController = {
this.SourceScripts.connect();
aThreadClient.resume();
aCallback();
}.bind(this));
}.bind(this));
},
@ -250,7 +273,8 @@ let DebuggerController = {
* @param object aChromeDebugger
* The remote protocol grip of the chrome debugger.
*/
_startChromeDebugging: function DC__startChromeDebugging(aClient, aChromeDebugger) {
_startChromeDebugging: function DC__startChromeDebugging
(aClient, aChromeDebugger, aCallback=function(){}) {
if (!aClient) {
Cu.reportError("No client found!");
return;
@ -269,6 +293,7 @@ let DebuggerController = {
this.SourceScripts.connect();
aThreadClient.resume();
aCallback();
}.bind(this));
},

View File

@ -25,7 +25,6 @@ ToolbarView.prototype = {
*/
initialize: function DVT_initialize() {
dumpn("Initializing the ToolbarView");
this._closeButton = document.getElementById("close");
this._togglePanesButton = document.getElementById("toggle-panes");
this._resumeButton = document.getElementById("resume");
this._stepOverButton = document.getElementById("step-over");
@ -44,7 +43,6 @@ ToolbarView.prototype = {
this._stepInTooltip = L10N.getFormatStr("stepInTooltip", [stepInKey]);
this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", [stepOutKey]);
this._closeButton.addEventListener("click", this._onCloseClick, false);
this._togglePanesButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.addEventListener("mousedown", this._onStepOverPressed, false);
@ -55,7 +53,6 @@ ToolbarView.prototype = {
this._stepInButton.setAttribute("tooltiptext", this._stepInTooltip);
this._stepOutButton.setAttribute("tooltiptext", this._stepOutTooltip);
this.toggleCloseButton(!window._isRemoteDebugger && !window._isChromeDebugger);
// TODO: bug 806775
// this.toggleChromeGlobalsContainer(window._isChromeDebugger);
},
@ -65,7 +62,6 @@ ToolbarView.prototype = {
*/
destroy: function DVT_destroy() {
dumpn("Destroying the ToolbarView");
this._closeButton.removeEventListener("click", this._onCloseClick, false);
this._togglePanesButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
this._resumeButton.removeEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.removeEventListener("mousedown", this._onStepOverPressed, false);
@ -73,16 +69,6 @@ ToolbarView.prototype = {
this._stepOutButton.removeEventListener("mousedown", this._onStepOutPressed, false);
},
/**
* Sets the close button hidden or visible. It's hidden by default.
*
* @param boolean aVisibleFlag
* Specifies the intended visibility.
*/
toggleCloseButton: function DVT_toggleCloseButton(aVisibleFlag) {
this._closeButton.setAttribute("hidden", !aVisibleFlag);
},
/**
* Sets the resume button state based on the debugger active thread.
*
@ -177,7 +163,6 @@ ToolbarView.prototype = {
}
},
_closeButton: null,
_togglePanesButton: null,
_resumeButton: null,
_stepOverButton: null,

View File

@ -153,11 +153,6 @@
<vbox id="body" flex="1">
<toolbar id="dbg-toolbar" class="devtools-toolbar">
#ifdef XP_MACOSX
<toolbarbutton id="close"
class="devtools-closebutton"
tooltiptext="&debuggerUI.closeButton.tooltip;"/>
#endif
<hbox id="debugger-controls">
<toolbarbutton id="resume"
class="devtools-toolbarbutton"
@ -186,11 +181,6 @@
class="devtools-option-toolbarbutton"
tooltiptext="&debuggerUI.optsButton.tooltip;"
popup="debuggerPrefsContextMenu"/>
#ifndef XP_MACOSX
<toolbarbutton id="close"
class="devtools-closebutton"
tooltiptext="&debuggerUI.closeButton.tooltip;"/>
#endif
</toolbar>
<panel id="searchbox-panel"

View File

@ -12,9 +12,9 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_TESTS = \
browser_dbg_leaktest.js \
browser_dbg_createChrome.js \
browser_dbg_debugger-tab-switch.js \
browser_dbg_debugger-tab-switch-window.js \
$(warning browser_dbg_createChrome.js disabled until issue 156 is fixed) \
$(browser_dbg_debugger-tab-switch.js disabled until issues 106, 40 are fixed) \
$(browser_dbg_debugger-tab-switch-window.js disabled until issues 106, 40 are fixed) \
browser_dbg_debuggerstatement.js \
browser_dbg_listtabs.js \
browser_dbg_tabactor-01.js \
@ -45,7 +45,6 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_propertyview-reexpand.js \
browser_dbg_reload-same-script.js \
browser_dbg_pane-collapse.js \
browser_dbg_panesize.js \
browser_dbg_panesize-inner.js \
browser_dbg_stack-01.js \
browser_dbg_stack-02.js \
@ -82,7 +81,6 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_iframes.js \
browser_dbg_pause-exceptions.js \
browser_dbg_multiple-windows.js \
browser_dbg_menustatus.js \
browser_dbg_bfcache.js \
browser_dbg_breakpoint-new-script.js \
browser_dbg_bug737803_editor_actual_location.js \

View File

@ -20,7 +20,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testInitialLoad();
});

View File

@ -17,7 +17,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
testAddBreakpoint();

View File

@ -31,9 +31,11 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
@ -50,12 +52,10 @@ function test()
executeSoon(startTest);
}
window.addEventListener("Debugger:SourceShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
@ -77,7 +77,7 @@ function test()
isnot(gScripts.selectedValue, gScripts.values[0],
"the correct script is selected");
gBreakpoints = gPane.breakpoints;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints), 0, "no breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
@ -127,7 +127,7 @@ function test()
is(Object.keys(gBreakpoints).length, 1,
"the list of debugger breakpoints holds only one breakpoint");
is(gPane.getBreakpoint(gScripts.selectedValue, 6), aBreakpointClient,
"getBreakpoint(selectedScript, 2) returns the correct breakpoint");
"getBreakpoint returns the correct breakpoint");
info("remove the first breakpoint");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,

View File

@ -29,9 +29,11 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
@ -48,12 +50,10 @@ function test()
executeSoon(startTest);
}
window.addEventListener("Debugger:SourceShown", onScriptShown);
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
@ -79,7 +79,7 @@ function test()
isnot(gScripts.selectedValue, gScripts.values[0],
"the correct script is selected");
gBreakpoints = gPane.breakpoints;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints), 0, "no breakpoints");
ok(!gPane.getBreakpoint("chocolate", 3), "getBreakpoint('chocolate', 3) returns falsey");

View File

@ -19,7 +19,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gWatch = gDebugger.DebuggerView.WatchExpressions;
gDebugger.DebuggerView.togglePanes({ visible: true, animated: false });

View File

@ -20,7 +20,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gWatch = gDebugger.DebuggerView.WatchExpressions;
gVars = gDebugger.DebuggerView.Variables;

View File

@ -28,7 +28,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -30,9 +30,11 @@ function test() {
gTab = aTab;
gPane = aPane;
gDebuggee = aDebuggee;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function () {
framesAdded = true;
executeSoon(startTest);
@ -48,11 +50,9 @@ function test() {
executeSoon(startTest);
}
window.addEventListener("Debugger:SourceShown", onScriptShown);
function startTest() {
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
@ -61,7 +61,7 @@ function test() {
function performTest() {
gScripts = gDebugger.DebuggerView.Sources;
gEditor = gDebugger.editor;
gBreakpoints = gPane.breakpoints;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints), 0, "There are no breakpoints");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,

View File

@ -29,7 +29,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
@ -79,7 +79,7 @@ function test()
is(gScripts.selectedValue, gScripts.values[0],
"The correct script is selected");
gBreakpoints = gPane.breakpoints;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints).length, 13, "thirteen breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");

View File

@ -33,7 +33,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsPane = gDebugger.DebuggerView.Breakpoints;
@ -83,7 +83,7 @@ function test()
is(gScripts.selectedValue, gScripts.values[0],
"The correct script is selected");
gBreakpoints = gPane.breakpoints;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints), 0, "no breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testNonEnumProperties();
});

View File

@ -15,7 +15,7 @@ function test() {
debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testCleanExit();
});

View File

@ -18,7 +18,7 @@ function test() {
debug_remote(TEST_URL, function(aTab, aDebuggee, aWindow) {
gTab = aTab;
gWindow = aWindow;
let gDebugger = gWindow.contentWindow;
let gDebugger = gWindow.panelWin;
info("Current remote window x: " +
Services.prefs.getIntPref("devtools.debugger.ui.win-x"));

View File

@ -18,7 +18,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testAnonCall();
});

View File

@ -14,10 +14,7 @@ function test() {
debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
let gDebugger = gPane.contentWindow;
is(gDebugger.document.getElementById("close").getAttribute("hidden"), "false",
"The close button should be visible in a normal content debugger.");
let gDebugger = gPane.panelWin;
is(gDebugger.DebuggerController.activeThread.paused, false,
"Should be running after debug_tab_pane.");

View File

@ -24,7 +24,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -20,7 +20,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;

View File

@ -20,7 +20,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;

View File

@ -17,7 +17,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -16,7 +16,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gView = gDebugger.DebuggerView;
testPanesState();

View File

@ -7,65 +7,70 @@
function test() {
var tab1 = addTab(TAB1_URL, function() {
gBrowser.selectedTab = tab1;
let target1 = TargetFactory.forTab(tab1);
ok(!DebuggerUI.getDebugger(),
"Shouldn't have a debugger pane for this tab yet.");
ok(!gDevTools.getPanelForTarget("jsdebugger", target1),
"Shouldn't have a debugger panel for this tab yet.");
let pane = DebuggerUI.toggleDebugger();
ok(pane, "toggleDebugger() should return a pane.");
let toolbox = gDevTools.openToolboxForTab(target1, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target1);
ok(dbg, "We should have a debugger panel.");
let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
let preferredBpw = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
let someWidth1, someWidth2;
let preferredSfw = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
let preferredBpw = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
let someWidth1, someWidth2;
do {
someWidth1 = parseInt(Math.random() * 200) + 100;
someWidth2 = parseInt(Math.random() * 200) + 100;
} while (someWidth1 == preferredSfw ||
someWidth2 == preferredBpw)
do {
someWidth1 = parseInt(Math.random() * 200) + 100;
someWidth2 = parseInt(Math.random() * 200) + 100;
} while (someWidth1 == preferredSfw ||
someWidth2 == preferredBpw)
info("Preferred stackframes width: " + preferredSfw);
info("Preferred variables width: " + preferredBpw);
info("Generated stackframes width: " + someWidth1);
info("Generated variables width: " + someWidth2);
let someWidth1 = parseInt(Math.random() * 200) + 100;
let someWidth2 = parseInt(Math.random() * 200) + 100;
is(DebuggerUI.getDebugger(), pane,
"getDebugger() should return the same pane as toggleDebugger().");
info("Preferred stackframes width: " + preferredSfw);
info("Preferred variables width: " + preferredBpw);
info("Generated stackframes width: " + someWidth1);
info("Generated variables width: " + someWidth2);
let content = pane.contentWindow;
let stackframes;
let variables;
let content = dbg.panelWin;
let stackframes;
let variables;
wait_for_connect_and_resume(function() {
ok(content.Prefs.stackframesWidth,
"The debugger preferences should have a saved stackframesWidth value.");
ok(content.Prefs.variablesWidth,
"The debugger preferences should have a saved variablesWidth value.");
wait_for_connect_and_resume(function() {
ok(content.Prefs.stackframesWidth,
"The debugger preferences should have a saved stackframesWidth value.");
ok(content.Prefs.variablesWidth,
"The debugger preferences should have a saved variablesWidth value.");
stackframes = content.document.getElementById("stackframes+breakpoints");
variables = content.document.getElementById("variables+expressions");
stackframes = content.document.getElementById("stackframes+breakpoints");
variables = content.document.getElementById("variables+expressions");
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
"The stackframes pane width should be the same as the preferred value.");
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
"The variables pane width should be the same as the preferred value.");
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
"The stackframes pane width should be the same as the preferred value.");
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
"The variables pane width should be the same as the preferred value.");
stackframes.setAttribute("width", someWidth1);
variables.setAttribute("width", someWidth2);
stackframes.setAttribute("width", someWidth1);
variables.setAttribute("width", someWidth2);
removeTab(tab1);
removeTab(tab1);
}, tab1);
window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
"The stackframes pane width should have been saved by now.");
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
"The variables pane width should have been saved by now.");
finish();
}, true);
});
window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
"The stackframes pane width should have been saved by now.");
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
"The variables pane width should have been saved by now.");
finish();
}, true);
});
}

View File

@ -1,55 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function test() {
var tab1 = addTab(TAB1_URL, function() {
gBrowser.selectedTab = tab1;
ok(!DebuggerUI.getDebugger(),
"Shouldn't have a debugger pane for this tab yet.");
let pane = DebuggerUI.toggleDebugger();
ok(pane, "toggleDebugger() should return a pane.");
let preferredHeight = Services.prefs.getIntPref("devtools.debugger.ui.height");
let someHeight;
do {
someHeight = parseInt(Math.random() * 200) + 200;
} while (someHeight == preferredHeight)
info("Preferred pane height: " + preferredHeight);
info("Generated pane height: " + someHeight);
is(DebuggerUI.getDebugger(), pane,
"getDebugger() should return the same pane as toggleDebugger().");
ok(DebuggerUI.preferences.height,
"The debugger preferences should have a saved height value.");
is(DebuggerUI.preferences.height, pane._frame.height,
"The debugger pane height should be the same as the preferred value.");
pane._frame.height = someHeight;
ok(DebuggerUI.preferences.height !== someHeight,
"Height preferences shouldn't have been updated yet.");
wait_for_connect_and_resume(function() {
removeTab(tab1);
});
window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
is(DebuggerUI.preferences.height, someHeight,
"Height preferences should have been updated by now.");
finish();
}, true);
});
}

View File

@ -20,7 +20,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
gDebugger.DebuggerView.Variables.nonEnumVisible = false;
@ -30,7 +30,7 @@ function test()
function testWithFrame()
{
gPane.contentWindow.gClient.addOneTimeListener("paused", function() {
gPane.panelWin.gClient.addOneTimeListener("paused", function() {
gDebugger.addEventListener("Debugger:FetchedVariables", function testA() {
// We expect 2 Debugger:FetchedVariables events, one from the global object
// scope and the regular one.
@ -48,7 +48,7 @@ function testWithFrame()
gDebugger.DebuggerView.Options._togglePauseOnExceptions();
gCount = 0;
gPane.contentWindow.gClient.addOneTimeListener("resumed", function() {
gPane.panelWin.gClient.addOneTimeListener("resumed", function() {
gDebugger.addEventListener("Debugger:FetchedVariables", function testB() {
// We expect 2 Debugger:FetchedVariables events, one from the global object
// scope and the regular one.
@ -96,7 +96,7 @@ function testWithFrame()
}
function resumeAndFinish() {
gPane.contentWindow.gClient.addOneTimeListener("resumed", function() {
gPane.panelWin.gClient.addOneTimeListener("resumed", function() {
Services.tm.currentThread.dispatch({ run: function() {
closeDebuggerAndFinish(false);

View File

@ -15,7 +15,7 @@ function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gView = gDebugger.DebuggerView;
gLH = gDebugger.LayoutHelpers;
gL10N = gDebugger.L10N;

View File

@ -18,7 +18,7 @@ function test() {
debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
let gDebugger = gPane.contentWindow;
let gDebugger = gPane.panelWin;
is(gDebugger.DebuggerController._isInitialized, true,
"Controller should be initialized after debug_tab_pane.");

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -17,7 +17,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testFrameParameters();
});

View File

@ -17,7 +17,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testFrameParameters();
});

View File

@ -19,7 +19,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
gDebugger.DebuggerView.Variables.nonEnumVisible = false;

View File

@ -19,7 +19,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
gDebugger.DebuggerView.Variables.nonEnumVisible = false;

View File

@ -18,7 +18,7 @@ function test()
debug_tab_pane(TAB1_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gVariablesView = gDebugger.DebuggerView.Variables;
testVariablesView();

View File

@ -18,7 +18,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;
gDebugger.DebuggerView.Variables.nonEnumVisible = false;

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;

View File

@ -24,7 +24,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
testSearchbox();

View File

@ -24,7 +24,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
testSearchbox();

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = false;

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;

View File

@ -21,7 +21,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gDebugger.DebuggerController.StackFrames.autoScopeExpand = true;

View File

@ -20,7 +20,7 @@ function test()
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
addBreakpoint();

View File

@ -28,7 +28,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gView = gDebugger.DebuggerView;
resumed = true;

View File

@ -25,7 +25,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -24,7 +24,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -26,7 +26,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -27,7 +27,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -27,7 +27,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -27,7 +27,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -27,7 +27,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -28,7 +28,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -27,7 +27,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.SourceResults.prototype.alwaysExpand = false;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {

View File

@ -18,7 +18,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
runTest();

View File

@ -13,7 +13,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -24,7 +24,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSelectLine();
});

View File

@ -14,7 +14,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testSimpleCall();
});

View File

@ -14,7 +14,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testEvalCall();
});

View File

@ -14,7 +14,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testRecurse();
});

View File

@ -14,7 +14,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
testEvalCallResume();
});

View File

@ -22,7 +22,7 @@ function test() {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;

View File

@ -29,7 +29,7 @@ function test()
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebugger = gPane.panelWin;
gScripts = gDebugger.DebuggerView.Sources._container;
resumed = true;

View File

@ -14,6 +14,10 @@ let DebuggerServer = tempScope.DebuggerServer;
let DebuggerTransport = tempScope.DebuggerTransport;
let DebuggerClient = tempScope.DebuggerClient;
let Services = tempScope.Services;
Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
let gDevTools = tempScope.gDevTools;
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html";
@ -86,11 +90,25 @@ function removeTab(aTab, aWindow) {
}
function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
let targetWindow = aWindow || window;
let debuggerUI = targetWindow.DebuggerUI;
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() {
debuggerClosed = true;
_maybeFinish();
});
toolbox.destroy();
function _maybeFinish() {
if (debuggerClosed && debuggerDisconnected) {
@ -100,20 +118,15 @@ function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
}
}
debuggerUI.chromeWindow.addEventListener("Debugger:Shutdown", function cleanup() {
debuggerUI.chromeWindow.removeEventListener("Debugger:Shutdown", cleanup, false);
debuggerDisconnected = true;
_maybeFinish();
}, false);
if (!aRemoteFlag) {
debuggerUI.getDebugger().close(function() {
debuggerClosed = true;
_maybeFinish();
});
} else {
debuggerClosed = true;
debuggerUI.getRemoteDebugger().close();
}
// if (!aRemoteFlag) {
// dbg.getDebugger().close(function() {
// debuggerClosed = true;
// _maybeFinish();
// });
// } else {
// debuggerClosed = true;
// dbg.getRemoteDebugger().close();
// }
}
function get_tab_actor_for_url(aClient, aURL, aCallback) {
@ -129,7 +142,7 @@ function get_tab_actor_for_url(aClient, aURL, aCallback) {
function attach_tab_actor_for_url(aClient, aURL, aCallback) {
get_tab_actor_for_url(aClient, aURL, function(actor) {
aClient.request({ to: actor.actor, type: "attach" }, function(aResponse) {
aClient.attachTab(actor.actor, function(aResponse) {
aCallback(actor, aResponse);
});
});
@ -137,45 +150,44 @@ function attach_tab_actor_for_url(aClient, aURL, aCallback) {
function attach_thread_actor_for_url(aClient, aURL, aCallback) {
attach_tab_actor_for_url(aClient, aURL, function(aTabActor, aResponse) {
aClient.request({ "to": actor.threadActor, "type": "attach" }, function(aResponse) {
aClient.attachThread(actor.threadActor, function(aResponse, aThreadClient) {
// We don't care about the pause right now (use
// get_actor_for_url() if you do), so resume it.
aClient.request({ to: actor.threadActor, type: "resume" }, function(aResponse) {
aThreadClient.resume(function(aResponse) {
aCallback(actor);
});
});
});
}
function wait_for_connect_and_resume(aOnDebugging, aWindow) {
let targetWindow = aWindow || window;
let targetDocument = targetWindow.document;
targetDocument.addEventListener("Debugger:Connected", function dbgConnected(aEvent) {
targetDocument.removeEventListener("Debugger:Connected", dbgConnected, true);
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...
aEvent.target.ownerDocument.defaultView.gClient.addOneTimeListener("resumed", function() {
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
aOnDebugging();
});
}, true);
});
}
function debug_tab_pane(aURL, aOnDebugging) {
let tab = addTab(aURL, function() {
gBrowser.selectedTab = gTab;
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
let pane = DebuggerUI.toggleDebugger();
pane._frame.addEventListener("Debugger:Connected", function dbgConnected() {
pane._frame.removeEventListener("Debugger:Connected", dbgConnected, true);
// Wait for the initial resume...
pane.contentWindow.gClient.addOneTimeListener("resumed", function() {
pane.contentWindow.DebuggerView.Variables.lazyEmpty = false;
aOnDebugging(tab, debuggee, pane);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.openToolboxForTab(target, "jsdebugger");
toolbox.once("jsdebugger-ready", function dbgReady() {
let dbg = gDevTools.getPanelForTarget("jsdebugger", target);
dbg.once("connected", function() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
dbg._view.Variables.lazyEmpty = false;
aOnDebugging(tab, debuggee, dbg);
});
});
}, true);
});
});
}
@ -192,7 +204,7 @@ function debug_remote(aURL, aOnDebugging, aBeforeTabAdded) {
win._dbgwin.removeEventListener("Debugger:Connected", dbgConnected, true);
// Wait for the initial resume...
win.contentWindow.gClient.addOneTimeListener("resumed", function() {
win.panelWin.gClient.addOneTimeListener("resumed", function() {
win._dbgwin.DebuggerView.Variables.lazyEmpty = false;
aOnDebugging(tab, debuggee, win);
});

View File

@ -10,17 +10,9 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXTRA_JS_MODULES = \
highlighter.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = \
inspector.jsm \
$(NULL)
TEST_DIRS += test
include $(topsrcdir)/config/rules.mk
libs::
$(NSINSTALL) $(srcdir)/CmdInspect.jsm $(FINAL_TARGET)/modules/devtools
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools

View File

@ -0,0 +1,191 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cc = Components.classes;
const Cu = Components.utils;
const Ci = Components.interfaces;
this.EXPORTED_SYMBOLS = ["ToolSidebar"];
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* ToolSidebar provides methods to register tabs in the sidebar.
* It's assumed that the sidebar contains a xul:tabbox.
*
* @param {Node} tabbox
* <tabbox> node;
* @param {ToolPanel} panel
* Related ToolPanel instance;
* @param {Boolean} showTabstripe
* Show the tabs.
*/
this.ToolSidebar = function ToolSidebar(tabbox, panel, showTabstripe=true)
{
new EventEmitter(this);
this._tabbox = tabbox;
this._panelDoc = this._tabbox.ownerDocument;
this._toolPanel = panel;
this._tabbox.tabpanels.addEventListener("select", this, true);
this._tabs = new Map();
if (!showTabstripe) {
this._tabbox.setAttribute("hidetabs", "true");
}
}
ToolSidebar.prototype = {
/**
* Register a tab. A tab is a document.
* The document must have a title, which will be used as the name of the tab.
*
* @param {string} tab uniq id
* @param {string} url
*/
addTab: function ToolSidebar_addTab(id, url, selected=false) {
let iframe = this._panelDoc.createElementNS(XULNS, "iframe");
iframe.className = "iframe-" + id;
iframe.setAttribute("flex", "1");
iframe.setAttribute("src", url);
let tab = this._tabbox.tabs.appendItem();
let onIFrameLoaded = function() {
tab.setAttribute("label", iframe.contentDocument.title);
iframe.removeEventListener("DOMContentLoaded", onIFrameLoaded, true);
if ("setPanel" in iframe.contentWindow) {
iframe.contentWindow.setPanel(this._toolPanel, iframe);
}
this.emit(id + "-ready");
}.bind(this);
iframe.addEventListener("DOMContentLoaded", onIFrameLoaded, true);
let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
tabpanel.setAttribute("id", "sidebar-panel-" + id);
tabpanel.appendChild(iframe);
this._tabbox.tabpanels.appendChild(tabpanel);
tab.linkedPanel = "sidebar-panel-" + id;
// We store the index of this tab.
this._tabs.set(id, tab);
if (selected) {
// For some reason I don't understand, if we call this.select in this
// event loop (after inserting the tab), the tab will never get the
// the "selected" attribute set to true.
this._panelDoc.defaultView.setTimeout(function() {
this.select(id);
}.bind(this), 0);
}
this.emit("new-tab-registered", id);
},
/**
* Select a specific tab.
*/
select: function ToolSidebar_select(id) {
let tab = this._tabs.get(id);
if (tab) {
this._tabbox.selectedTab = tab;
}
},
/**
* Return the id of the selected tab.
*/
getCurrentTabID: function ToolSidebar_getCurrentTabID() {
let currentID = null;
for (let [id, tab] of this._tabs) {
if (this._tabbox.tabs.selectedItem == tab) {
currentID = id;
break;
}
}
return currentID;
},
/**
* Event handler.
*/
handleEvent: function ToolSidebar_eventHandler(event) {
if (event.type == "select") {
let previousTool = this._currentTool;
this._currentTool = this.getCurrentTabID();
if (previousTool) {
this.emit(previousTool + "-unselected");
}
this.emit(this._currentTool + "-selected");
this.emit("select", this._currentTool);
}
},
/**
* Toggle sidebar's visibility state.
*/
toggle: function ToolSidebar_toggle() {
if (this._tabbox.hasAttribute("hidden")) {
this.show();
} else {
this.hide();
}
},
/**
* Show the sidebar.
*/
show: function ToolSidebar_show() {
this._tabbox.removeAttribute("hidden");
},
/**
* Show the sidebar.
*/
hide: function ToolSidebar_hide() {
this._tabbox.setAttribute("hidden", "true");
},
/**
* Return the window containing the tab content.
*/
getWindowForTab: function ToolSidebar_getWindowForTab(id) {
if (!this._tabs.has(id)) {
return null;
}
let panel = this._panelDoc.getElementById(this._tabs.get(id).linkedPanel);
return panel.firstChild.contentWindow;
},
/**
* Clean-up.
*/
destroy: function ToolSidebar_destroy() {
this._tabbox.removeEventListener("select", this, true);
while (this._tabbox.tabpanels.hasChildNodes()) {
this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);
}
while (this._tabbox.tabs.hasChildNodes()) {
this._tabbox.tabs.removeChild(this._tabbox.tabs.firstChild);
}
this._tabs = null;
this._tabbox = null;
this._panelDoc = null;
this._toolPanel = null;
},
}

View File

@ -0,0 +1,385 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = [ "TargetFactory" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const targets = new WeakMap();
/**
* Functions for creating Targets
*/
this.TargetFactory = {
/**
* Construct a Target
* @param {XULTab} tab
* The tab to use in creating a new target
* @return A target object
*/
forTab: function TF_forTab(tab) {
let target = targets.get(tab);
if (target == null) {
target = new TabTarget(tab);
targets.set(tab, target);
}
return target;
},
/**
* Creating a target for a tab that is being closed is a problem because it
* allows a leak as a result of coming after the close event which normally
* clears things up. This function allows us to ask if there is a known
* target for a tab without creating a target
* @return true/false
*/
isKnownTab: function TF_isKnownTab(tab) {
return targets.has(tab);
},
/**
* Construct a Target
* @param {nsIDOMWindow} window
* The chromeWindow to use in creating a new target
* @return A target object
*/
forWindow: function TF_forWindow(window) {
let target = targets.get(window);
if (target == null) {
target = new WindowTarget(window);
targets.set(window, target);
}
return target;
},
/**
* Construct a Target for a remote global
* @param {Object} form
* The serialized form of a debugging protocol actor.
* @param {DebuggerClient} client
* The debuger client instance to communicate with the server.
* @param {boolean} chrome
* A flag denoting that the debugging target is the remote process as a
* whole and not a single tab.
* @return A target object
*/
forRemote: function TF_forRemote(form, client, chrome) {
let target = targets.get(form);
if (target == null) {
target = new RemoteTarget(form, client, chrome);
targets.set(form, target);
}
return target;
},
/**
* Get all of the targets known to some browser instance (local if null)
* @return An array of target objects
*/
allTargets: function TF_allTargets() {
let windows = [];
let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
let en = wm.getXULWindowEnumerator(null);
while (en.hasMoreElements()) {
windows.push(en.getNext());
}
return windows.map(function(window) {
return TargetFactory.forWindow(window);
});
},
};
/**
* The 'version' property allows the developer tools equivalent of browser
* detection. Browser detection is evil, however while we don't know what we
* will need to detect in the future, it is an easy way to postpone work.
* We should be looking to use 'supports()' in place of version where
* possible.
*/
function getVersion() {
// FIXME: return something better
return 20;
}
/**
* A better way to support feature detection, but we're not yet at a place
* where we have the features well enough defined for this to make lots of
* sense.
*/
function supports(feature) {
// FIXME: return something better
return false;
};
/**
* A Target represents something that we can debug. Targets are generally
* read-only. Any changes that you wish to make to a target should be done via
* a Tool that attaches to the target. i.e. a Target is just a pointer saying
* "the thing to debug is over there".
*
* Providing a generalized abstraction of a web-page or web-browser (available
* either locally or remotely) is beyond the scope of this class (and maybe
* also beyond the scope of this universe) However Target does attempt to
* abstract some common events and read-only properties common to many Tools.
*
* Supported read-only properties:
* - name, isRemote, url
*
* Target extends EventEmitter and provides support for the following events:
* - close: The target window has been closed. All tools attached to this
* target should close. This event is not currently cancelable.
* - navigate: The target window has navigated to a different URL
*
* Optional events:
* - will-navigate: The target window will navigate to a different URL
* - hidden: The target is not visible anymore (for TargetTab, another tab is selected)
* - visible: The target is visible (for TargetTab, tab is selected)
*
* Target also supports 2 functions to help allow 2 different versions of
* Firefox debug each other. The 'version' property is the equivalent of
* browser detection - simple and easy to implement but gets fragile when things
* are not quite what they seem. The 'supports' property is the equivalent of
* feature detection - harder to setup, but more robust long-term.
*
* Comparing Targets: 2 instances of a Target object can point at the same
* thing, so t1 !== t2 and t1 != t2 even when they represent the same object.
* To compare to targets use 't1.equals(t2)'.
*/
function Target() {
throw new Error("Use TargetFactory.newXXX or Target.getXXX to create a Target in place of 'new Target()'");
}
Object.defineProperty(Target.prototype, "version", {
get: getVersion,
enumerable: true
});
/**
* A TabTarget represents a page living in a browser tab. Generally these will
* be web pages served over http(s), but they don't have to be.
*/
function TabTarget(tab) {
new EventEmitter(this);
this._tab = tab;
this._setupListeners();
}
TabTarget.prototype = {
_webProgressListener: null,
supports: supports,
get version() { return getVersion(); },
get tab() {
return this._tab;
},
get name() {
return this._tab.linkedBrowser.contentDocument.title;
},
get url() {
return this._tab.linkedBrowser.contentDocument.location.href;
},
get isRemote() {
return false;
},
/**
* Listen to the different tabs events.
*/
_setupListeners: function TabTarget__setupListeners() {
this._webProgressListener = new TabWebProgressListener(this);
this.tab.linkedBrowser.addProgressListener(this._webProgressListener);
this.tab.addEventListener("TabClose", this);
this.tab.parentNode.addEventListener("TabSelect", this);
},
/**
* Handle tabs events.
*/
handleEvent: function (event) {
switch (event.type) {
case "TabClose":
this.destroy();
break;
case "TabSelect":
if (this.tab.selected) {
this.emit("visible", event);
} else {
this.emit("hidden", event);
}
break;
}
},
/**
* 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");
targets.delete(this._tab);
this._tab = null;
},
toString: function() {
return 'TabTarget:' + this.tab;
},
};
/**
* WebProgressListener for TabTarget.
*
* @param object aTarget
* The TabTarget instance to work with.
*/
function TabWebProgressListener(aTarget) {
this.target = aTarget;
}
TabWebProgressListener.prototype = {
target: null,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
onStateChange: function TWPL_onStateChange(progress, request, flag, status) {
let isStart = flag & Ci.nsIWebProgressListener.STATE_START;
let isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
let isNetwork = flag & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
let isRequest = flag & Ci.nsIWebProgressListener.STATE_IS_REQUEST;
// Skip non-interesting states.
if (!isStart || !isDocument || !isRequest || !isNetwork) {
return;
}
if (this.target) {
this.target.emit("will-navigate", request);
}
},
onProgressChange: function() {},
onSecurityChange: function() {},
onStatusChange: function() {},
onLocationChange: function TwPL_onLocationChange(webProgress) {
let window = webProgress.DOMWindow;
if (this.target) {
this.target.emit("navigate", window);
}
},
};
/**
* A WindowTarget represents a page living in a xul window or panel. Generally
* these will have a chrome: URL
*/
function WindowTarget(window) {
new EventEmitter(this);
this._window = window;
}
WindowTarget.prototype = {
supports: supports,
get version() { return getVersion(); },
get window() {
return this._window;
},
get name() {
return this._window.document.title;
},
get url() {
return this._window.document.location.href;
},
get isRemote() {
return false;
},
toString: function() {
return 'WindowTarget:' + this.window;
},
};
/**
* A RemoteTarget represents a page living in a remote Firefox instance.
*/
function RemoteTarget(form, client, chrome) {
new EventEmitter(this);
this._client = client;
this._form = form;
this._chrome = chrome;
this.destroy = this.destroy.bind(this);
this.client.addListener("tabDetached", this.destroy);
this._onTabNavigated = function onRemoteTabNavigated() {
this.emit("navigate");
}.bind(this);
this.client.addListener("tabNavigated", this._onTabNavigated);
}
RemoteTarget.prototype = {
supports: supports,
get version() getVersion(),
get isRemote() true,
get chrome() this._chrome,
get name() this._form._title,
get url() this._form._url,
get client() this._client,
get form() this._form,
/**
* Target is not alive anymore.
*/
destroy: function RT_destroy() {
if (this._destroyed) {
return;
}
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");
}.bind(this));
},
toString: function() {
return 'RemoteTarget:' + this.form.actor;
},
};

View File

@ -0,0 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = [ "defaultTools" ];
Components.utils.import("resource:///modules/WebConsolePanel.jsm");
Components.utils.import("resource:///modules/devtools/DebuggerPanel.jsm");
Components.utils.import("resource:///modules/devtools/StyleEditorDefinition.jsm");
Components.utils.import("resource:///modules/devtools/InspectorDefinition.jsm");
this.defaultTools = [
StyleEditorDefinition,
WebConsoleDefinition,
DebuggerDefinition,
InspectorDefinition,
];

View File

@ -0,0 +1,523 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource:///modules/devtools/ToolboxHosts.jsm");
Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
"resource:///modules/devtools/DeveloperToolbar.jsm");
Components.utils.import("resource://gre/modules/devtools/Require.jsm");
let Requisition = require('gcli/cli').Requisition;
let CommandOutputManager = require('gcli/canon').CommandOutputManager;
this.EXPORTED_SYMBOLS = [ "Toolbox" ];
/**
* 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
* the iframes where the tool panels will be living in.
*
* @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
*/
this.Toolbox = function Toolbox(target, hostType, selectedTool) {
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);
this._target.once("close", this.destroy);
if (!hostType) {
hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
}
if (!selectedTool) {
selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
}
let definitions = gDevTools.getToolDefinitions();
if (!definitions.get(selectedTool)) {
selectedTool = "webconsole";
}
this._defaultToolId = selectedTool;
this._host = this._createHost(hostType);
new EventEmitter(this);
gDevTools.on("tool-registered", this._toolRegistered);
gDevTools.on("tool-unregistered", this._toolUnregistered);
}
/**
* The toolbox can be 'hosted' either embedded in a browser window
* or in a separate window.
*/
Toolbox.HostType = {
BOTTOM: "bottom",
SIDE: "side",
WINDOW: "window"
}
Toolbox.prototype = {
_URL: "chrome://browser/content/devtools/framework/toolbox.xul",
_prefs: {
LAST_HOST: "devtools.toolbox.host",
LAST_TOOL: "devtools.toolbox.selectedTool",
SIDE_ENABLED: "devtools.toolbox.sideEnabled"
},
HostType: Toolbox.HostType,
/**
* Returns a *copy* of the _toolPanels collection.
*
* @return {Map} panels
* All the running panels in the toolbox
*/
getToolPanels: function TB_getToolPanels() {
let panels = new Map();
for (let [key, value] of this._toolPanels) {
panels.set(key, value);
}
return panels;
},
/**
* Get/alter the target of a Toolbox so we're debugging something different.
* See Target.jsm for more details.
* TODO: Do we allow |toolbox.target = null;| ?
*/
get target() {
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.
*/
get hostType() {
return this._host.type;
},
set hostType(value) {
this._switchToHost(value);
},
/**
* Get/alter the currently displayed tool.
*/
get currentToolId() {
return this._currentToolId;
},
set currentToolId(value) {
this._currentToolId = value;
},
/**
* Get the iframe containing the toolbox UI.
*/
get frame() {
return this._host.frame;
},
/**
* Shortcut to the document containing the toolbox UI
*/
get doc() {
return this.frame.contentDocument;
},
/**
* Open the toolbox
*/
open: function TBOX_open() {
this._host.once("ready", function(event, iframe) {
iframe.addEventListener("DOMContentLoaded", this._onLoad, true);
iframe.setAttribute("src", this._URL);
}.bind(this));
this._host.open();
},
/**
* Build the buttons for changing hosts. Called every time
* the host changes.
*/
_buildDockButtons: function TBOX_createDockButtons() {
let dockBox = this.doc.getElementById("toolbox-dock-buttons");
while (dockBox.firstChild) {
dockBox.removeChild(dockBox.firstChild);
}
let sideEnabled = Services.prefs.getBoolPref(this._prefs.SIDE_ENABLED);
for each (let position in this.HostType) {
if (position == this.hostType ||
(!sideEnabled && position == this.HostType.SIDE)) {
continue;
}
let button = this.doc.createElement("toolbarbutton");
button.id = "toolbox-dock-" + position;
button.className = "toolbox-dock-button";
button.addEventListener("command", function(position) {
this.hostType = 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
*/
_buildTabs: function TBOX_buildTabs() {
for (let [id, definition] of gDevTools.getToolDefinitions()) {
this._buildTabForTool(definition);
}
},
/**
* Add buttons to the UI as specified in the devtools.window.toolbarSpec pref
*
* @param {iframe} frame
* The iframe to contain the buttons
*/
_buildButtons: function TBOX_buildButtons(frame) {
let toolbarSpec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
let environment = { chromeDocument: frame.ownerDocument };
let requisition = new Requisition(environment);
requisition.commandOutputManager = new CommandOutputManager();
let buttons = CommandUtils.createButtons(toolbarSpec, this.doc, requisition);
let container = this.doc.getElementById("toolbox-buttons");
buttons.forEach(function(button) {
container.appendChild(button);
}.bind(this));
},
/**
* Build a tab for one tool definition and add to the toolbox
*
* @param {string} toolDefinition
* Tool definition of the tool to build a tab for.
*/
_buildTabForTool: function TBOX_buildTabForTool(toolDefinition) {
const MAX_ORDINAL = 99;
if (!toolDefinition.isTargetSupported(this._target)) {
return;
}
let tabs = this.doc.getElementById("toolbox-tabs");
let deck = this.doc.getElementById("toolbox-deck");
let id = toolDefinition.id;
let radio = this.doc.createElement("radio");
radio.setAttribute("label", toolDefinition.label);
radio.className = "toolbox-tab devtools-tab";
radio.id = "toolbox-tab-" + id;
radio.setAttribute("toolid", id);
let ordinal = (typeof toolDefinition.ordinal == "number") ?
toolDefinition.ordinal : MAX_ORDINAL;
radio.setAttribute("ordinal", ordinal);
radio.addEventListener("command", function(id) {
this.selectTool(id);
}.bind(this, id));
let vbox = this.doc.createElement("vbox");
vbox.className = "toolbox-panel";
vbox.id = "toolbox-panel-" + id;
tabs.appendChild(radio);
deck.appendChild(vbox);
},
/**
* Switch to the tool with the given id
*
* @param {string} id
* The id of the tool to switch to
*/
selectTool: function TBOX_selectTool(id) {
if (!this.isReady) {
throw new Error("Can't select tool, wait for toolbox 'ready' event");
}
let tab = this.doc.getElementById("toolbox-tab-" + id);
if (!tab) {
throw new Error("No tool found");
}
let tabstrip = this.doc.getElementById("toolbox-tabs");
// select the right tab
let index = -1;
let tabs = tabstrip.childNodes;
for (let i = 0; i < tabs.length; i++) {
if (tabs[i] === tab) {
index = i;
break;
}
}
tabstrip.selectedIndex = index;
// and select the right iframe
let deck = this.doc.getElementById("toolbox-deck");
deck.selectedIndex = index;
let definition = gDevTools.getToolDefinitions().get(id);
let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
if (!iframe) {
iframe = this.doc.createElement("iframe");
iframe.className = "toolbox-panel-iframe";
iframe.id = "toolbox-panel-iframe-" + id;
iframe.setAttribute("flex", 1);
let vbox = this.doc.getElementById("toolbox-panel-" + id);
vbox.appendChild(iframe);
let boundLoad = function() {
iframe.removeEventListener("DOMContentLoaded", boundLoad, true);
let panel = definition.build(iframe.contentWindow, this);
this._toolPanels.set(id, panel);
let panelReady = function() {
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);
}
}.bind(this);
iframe.addEventListener("DOMContentLoaded", boundLoad, true);
iframe.setAttribute("src", definition.url);
} else {
let panel = this._toolPanels.get(id);
// only emit 'select' event if the iframe has been loaded
if (panel) {
this.emit("select", id);
this.emit(id + "-selected", panel);
}
}
Services.prefs.setCharPref(this._prefs.LAST_TOOL, id);
this._currentToolId = id;
},
/**
* Create a host object based on the given host type.
*
* @param {string} hostType
* The host type of the new host object
*
* @return {Host} host
* The created host object
*/
_createHost: function TBOX_createHost(hostType) {
let hostTab = this._getHostTab();
if (!Hosts[hostType]) {
throw new Error('Unknown hostType: '+ hostType);
}
let newHost = new Hosts[hostType](hostTab);
// clean up the toolbox if its window is closed
newHost.on("window-closed", this.destroy);
return newHost;
},
/**
* Switch to a new host for the toolbox UI. E.g.
* bottom, sidebar, separate window.
*
* @param {string} hostType
* The host type of the new host object
*/
_switchToHost: function TBOX_switchToHost(hostType) {
if (hostType == this._host.type) {
return;
}
let newHost = this._createHost(hostType);
newHost.once("ready", function(event, iframe) {
// change toolbox document's parent to the new host
iframe.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
iframe.swapFrameLoaders(this.frame);
this._host.off("window-closed", this.destroy);
this._host.destroy();
this._host = newHost;
Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
this._buildDockButtons();
this.emit("host-changed");
}.bind(this));
newHost.open();
},
/**
* Get the most appropriate host tab, either the target or the current tab
*/
_getHostTab: function TBOX_getHostTab() {
if (!this._target.isRemote && !this._target.isChrome) {
return this._target.tab;
} else {
let win = Services.wm.getMostRecentWindow("navigator:browser");
return win.gBrowser.selectedTab;
}
},
/**
* Handler for the tool-registered event.
* @param {string} event
* Name of the event ("tool-registered")
* @param {string} toolId
* Id of the tool that was registered
*/
_toolRegistered: function TBOX_toolRegistered(event, toolId) {
let defs = gDevTools.getToolDefinitions();
let tool = defs.get(toolId);
this._buildTabForTool(tool);
},
/**
* Handler for the tool-unregistered event.
* @param {string} event
* Name of the event ("tool-unregistered")
* @param {string} toolId
* Id of the tool that was unregistered
*/
_toolUnregistered: function TBOX_toolUnregistered(event, toolId) {
let radio = this.doc.getElementById("toolbox-tab-" + toolId);
let panel = this.doc.getElementById("toolbox-panel-" + toolId);
if (this._currentToolId == toolId) {
let nextToolName = null;
if (radio.nextSibling) {
nextToolName = radio.nextSibling.getAttribute("toolid");
}
if (radio.previousSibling) {
nextToolName = radio.previousSibling.getAttribute("toolid");
}
if (nextToolName) {
this.selectTool(nextToolName);
}
}
if (radio) {
radio.parentNode.removeChild(radio);
}
if (panel) {
panel.parentNode.removeChild(panel);
}
if (this._toolPanels.has(toolId)) {
let instance = this._toolPanels.get(toolId);
instance.destroy();
this._toolPanels.delete(toolId);
}
},
/**
* Get the toolbox's notification box
*
* @return The notification box element.
*/
getNotificationBox: function TBOX_getNotificationBox() {
return this.doc.getElementById("toolbox-notificationbox");
},
/**
* Remove all UI elements, detach from target and clear up
*/
destroy: function TBOX_destroy() {
if (this._destroyed) {
return;
}
// Remote targets need to be notified that the toolbox is being torn down.
if (this._target && this._target.isRemote) {
this._target.destroy();
}
this._target = null;
for (let [id, panel] of this._toolPanels) {
panel.destroy();
}
this._host.destroy();
gDevTools.off("tool-registered", this._toolRegistered);
gDevTools.off("tool-unregistered", this._toolUnregistered);
this._destroyed = true;
this.emit("destroyed");
}
};

View File

@ -0,0 +1,208 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
this.EXPORTED_SYMBOLS = [ "Hosts" ];
/**
* A toolbox host represents an object that contains a toolbox (e.g. the
* sidebar or a separate window). Any host object should implement the
* following functions:
*
* open() - create the UI and emit a 'ready' event when the UI is ready to use
* destroy() - destroy the host's UI
*/
this.Hosts = {
"bottom": BottomHost,
"side": SidebarHost,
"window": WindowHost
}
/**
* Host object for the dock on the bottom of the browser
*/
function BottomHost(hostTab) {
this.hostTab = hostTab;
new EventEmitter(this);
}
BottomHost.prototype = {
type: "bottom",
heightPref: "devtools.toolbox.footer.height",
/**
* Create a box at the bottom of the host tab.
*/
open: function BH_open() {
let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
let ownerDocument = gBrowser.ownerDocument;
this._splitter = ownerDocument.createElement("splitter");
this._splitter.setAttribute("class", "devtools-horizontal-splitter");
this.frame = ownerDocument.createElement("iframe");
this.frame.id = "devtools-toolbox-bottom-iframe";
this.frame.height = Services.prefs.getIntPref(this.heightPref);
this._nbox = gBrowser.getNotificationBox(this.hostTab.linkedBrowser);
this._nbox.appendChild(this._splitter);
this._nbox.appendChild(this.frame);
let frameLoad = function() {
this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
this.emit("ready", this.frame);
}.bind(this);
this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
// we have to load something so we can switch documents if we have to
this.frame.setAttribute("src", "about:blank");
focusTab(this.hostTab);
},
/**
* Destroy the bottom dock.
*/
destroy: function BH_destroy() {
if (this._destroyed) {
return;
}
this._destroyed = true;
Services.prefs.setIntPref(this.heightPref, this.frame.height);
this._nbox.removeChild(this._splitter);
this._nbox.removeChild(this.frame);
}
}
/**
* Host object for the in-browser sidebar
*/
function SidebarHost(hostTab) {
this.hostTab = hostTab;
new EventEmitter(this);
}
SidebarHost.prototype = {
type: "side",
widthPref: "devtools.toolbox.sidebar.width",
/**
* Create a box in the sidebar of the host tab.
*/
open: function RH_open() {
let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser;
let ownerDocument = gBrowser.ownerDocument;
this._splitter = ownerDocument.createElement("splitter");
this._splitter.setAttribute("class", "devtools-side-splitter");
this.frame = ownerDocument.createElement("iframe");
this.frame.id = "devtools-toolbox-side-iframe";
this.frame.width = Services.prefs.getIntPref(this.widthPref);
this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
this._sidebar.appendChild(this._splitter);
this._sidebar.appendChild(this.frame);
let frameLoad = function() {
this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
this.emit("ready", this.frame);
}.bind(this);
this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
this.frame.setAttribute("src", "about:blank");
focusTab(this.hostTab);
},
/**
* Destroy the sidebar.
*/
destroy: function RH_destroy() {
Services.prefs.setIntPref(this.widthPref, this.frame.width);
this._sidebar.removeChild(this._splitter);
this._sidebar.removeChild(this.frame);
}
}
/**
* Host object for the toolbox in a separate window
*/
function WindowHost() {
this._boundUnload = this._boundUnload.bind(this);
new EventEmitter(this);
}
WindowHost.prototype = {
type: "window",
WINDOW_URL: "chrome://browser/content/devtools/framework/toolbox-window.xul",
/**
* Create a new xul window to contain the toolbox.
*/
open: function WH_open() {
let flags = "chrome,centerscreen,resizable,dialog=no";
let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
flags, null);
let frameLoad = function(event) {
win.removeEventListener("load", frameLoad, true);
this.frame = win.document.getElementById("toolbox-iframe");
this.emit("ready", this.frame);
}.bind(this);
win.addEventListener("load", frameLoad, true);
win.addEventListener("unload", this._boundUnload);
win.focus();
this._window = win;
},
/**
* Catch the user closing the window.
*/
_boundUnload: function(event) {
if (event.target.location != this.WINDOW_URL) {
return;
}
this._window.removeEventListener("unload", this._boundUnload);
this.emit("window-closed");
},
/**
* Destroy the window.
*/
destroy: function WH_destroy() {
this._window.removeEventListener("unload", this._boundUnload);
this._window.close();
}
}
/**
* Switch to the given tab in a browser and focus the browser window
*/
function focusTab(tab) {
let browserWindow = tab.ownerDocument.defaultView;
browserWindow.focus();
browserWindow.gBrowser.selectedTab = tab;
}

View File

@ -0,0 +1,87 @@
html {
background: url("chrome://browser/skin/newtab/noise.png");
}
body {
font-family: Arial;
padding: 20px;
border-radius: 3px;
max-width: 600px;
min-height: 400px;
margin: 10px auto 0;
}
label {
display: block;
margin: 10px;
font-size: 0;
}
label > span {
display: inline-block;
min-width: 150px;
font-size: 0.8rem;
text-align: right;
margin-right: 10px;
}
#submit {
margin-left: 160px;
}
#actors, #connection-form {
margin: 20px;
}
input {
border: 1px solid grey;
}
#connection-form,
#connecting,
#actors-list {
display: none;
}
body:not(.actors-mode):not(.connecting) > #connection-form {
display: block;
}
body.actors-mode > #actors-list {
display: block;
}
body.connecting > #connecting {
display: block;
}
#connecting {
text-align: center;
}
#throbber {
height: 7px; width: 7px;
border-radius: 50%;
background: black;
display: inline-block;
animation-duration: 0.6s;
animation-name: anim;
animation-direction: alternate;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes anim {to {
transform: scale(0.5) rotate(0.1deg);
}}
#actors {
padding-left: 0;
font-size: 0.9rem;
}
#actors > a {
display: block;
margin: 5px;
padding: 5px;
}

View File

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/Target.jsm");
Cu.import("resource:///modules/devtools/Toolbox.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
let gClient;
function submit() {
document.body.classList.add("connecting");
let host = document.getElementById("host").value;
let port = document.getElementById("port").value;
if (!host) {
host = Services.prefs.getCharPref("devtools.debugger.remote-host");
} else {
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
}
if (!port) {
port = Services.prefs.getIntPref("devtools.debugger.remote-port");
} else {
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
}
let transport = debuggerSocketConnect(host, port);
let client = gClient = new DebuggerClient(transport);
client.connect(function(aType, aTraits) {
client.listTabs(function(aResponse) {
document.body.classList.remove("connecting");
document.body.classList.add("actors-mode");
let parent = document.getElementById("actors");
let focusSet = false;
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will always
// be there).
if (Object.keys(globals).length > 1) {
let a = document.createElement("a");
a.onclick = function() {
connect(globals, true);
}
a.title = a.textContent = "Remote process";
a.href = "#";
parent.appendChild(a);
}
// Add one entry for each open tab.
if (aResponse.tabs.length > 0) {
let header = document.createElement("div");
header.innerHTML = "Tabs:";
parent.appendChild(header);
}
for (let i = 0; i < aResponse.tabs.length; i++) {
let tab = aResponse.tabs[i];
let a = document.createElement("a");
a.onclick = function() {
connect(tab);
}
a.title = a.textContent = tab.title;
a.href = "#";
if (i == aResponse.selected) {
a.title += " [*]";
a.textContent = a.title;
}
parent.appendChild(a);
if (!focusSet) {
a.focus();
focusSet = true;
}
}
});
});
}
function connect(form, chrome=false) {
let target = TargetFactory.forRemote(form, gClient, chrome);
gDevTools.openToolbox(target, Toolbox.HostType.WINDOW, "webconsole");
window.close();
}

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html [
<!ENTITY % connectionDTD SYSTEM "chrome://browser/locale/devtools/connection-screen.dtd" >
%connectionDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<head>
<title>&title;</title>
<link rel="stylesheet" href="chrome://browser/content/devtools/connect.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="connect.js"></script>
</head>
<body>
<p>
</p>
<section id="connection-form">
<form onsubmit="window.submit()" action="#">
<label>
<span>&host;</span>
<input id="host" type="text" placeholder="localhost"></input>
</label>
<label>
<span>&port;</span>
<input id="port" type="number" placeholder="6000"></input>
</label>
<label>
<input id="submit" type="submit" value="&connect;"></input>
</label>
</form>
</section>
<section id="actors-list">
<p>&availability;</p>
<ul id="actors"></ul>
</section>
<section id="connecting">
<p>&connecting;</p>
<div id="throbber"></div>
</section>
</body>
</html>

View File

@ -0,0 +1,543 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = [ "gDevTools", "DevTools", "DevToolsXULCommands" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource:///modules/devtools/ToolDefinitions.jsm");
Cu.import("resource:///modules/devtools/Toolbox.jsm");
Cu.import("resource:///modules/devtools/Target.jsm");
const FORBIDDEN_IDS = new Set("toolbox", "");
/**
* DevTools is a class that represents a set of developer tools, it holds a
* set of tools and keeps track of open toolboxes in the browser.
*/
this.DevTools = function DevTools() {
this._tools = new Map();
this._toolboxes = new Map();
// 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
*/
for (let definition of defaultTools) {
this.registerTool(definition);
}
}
DevTools.prototype = {
/**
* Register a new developer tool.
*
* A definition is a light object that holds different information about a
* developer tool. This object is not supposed to have any operational code.
* See it as a "manifest".
* The only actual code lives in the build() function, which will be used to
* start an instance of this tool.
*
* Each toolDefinition has the following properties:
* - id: Unique identifier for this tool (string|required)
* - killswitch: Property name to allow us to turn this tool on/off globally
* (string|required) (TODO: default to devtools.{id}.enabled?)
* - icon: URL pointing to a graphic which will be used as the src for an
* 16x16 img tag (string|required)
* - url: URL pointing to a XUL/XHTML document containing the user interface
* (string|required)
* - label: Localized name for the tool to be displayed to the user
* (string|required)
* - build: Function that takes an iframe, which has been populated with the
* markup from |url|, and also the toolbox containing the panel.
* And returns an instance of ToolPanel (function|required)
*/
registerTool: function DT_registerTool(toolDefinition) {
let toolId = toolDefinition.id;
if (!toolId || FORBIDDEN_IDS.has(toolId)) {
throw new Error("Invalid definition.id");
}
toolDefinition.killswitch = toolDefinition.killswitch ||
"devtools." + toolId + ".enabled";
this._tools.set(toolId, toolDefinition);
this._addToolToWindows(toolDefinition);
this.emit("tool-registered", toolId);
},
/**
* Removes all tools that match the given |toolId|
* Needed so that add-ons can remove themselves when they are deactivated
*
* @param {string} toolId
* id of the tool to unregister
*/
unregisterTool: function DT_unregisterTool(toolId) {
this._tools.delete(toolId);
this._removeToolFromWindows(toolId);
this.emit("tool-unregistered", toolId);
},
/**
* Allow ToolBoxes to get at the list of tools that they should populate
* themselves with.
*
* @return {Map} tools
* A map of the the tool definitions registered in this instance
*/
getToolDefinitions: function DT_getToolDefinitions() {
let tools = new Map();
for (let [key, value] of this._tools) {
let enabled;
try {
enabled = Services.prefs.getBoolPref(value.killswitch);
} catch(e) {
enabled = true;
}
if (enabled) {
tools.set(key, value);
}
}
return tools;
},
/**
* Create a toolbox to debug |target| using a window displayed in |hostType|
* (optionally with |defaultToolId| opened)
*
* @param {Target} target
* The target the toolbox will debug
* @param {Toolbox.HostType} hostType
* The type of host (bottom, top, side)
* @param {string} defaultToolId
* The id of the initial tool to show
*
* @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);
}
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;
}
toolbox.destroy();
},
/**
* 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);
if (tb) {
tb.selectTool(toolId);
} else {
tb = this.openToolbox(target, null, toolId);
}
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 the toolbox for a given target.
*
* @param {object} target
* Target value e.g. the target that owns this toolbox
*
* @return {Toolbox} toolbox
* The toobox that is debugging the given target
*/
getToolboxForTarget: function DT_getToolboxForTarget(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
*/
getPanelForTarget: function DT_getPanelForTarget(toolId, target) {
let toolbox = this.getToolboxForTarget(target);
if (!toolbox) {
return undefined;
}
return toolbox.getToolPanels().get(toolId);
},
/**
* 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
*/
registerBrowserWindow: function DT_registerBrowserWindow(win) {
this._trackedBrowserWindows.add(win);
this._addAllToolsToMenu(win.document);
let tabContainer = win.document.getElementById("tabbrowser-tabs")
tabContainer.addEventListener("TabSelect", this._updateMenuCheckbox, false);
},
/**
* Add the menuitem for a tool to all open browser windows.
*
* @param {object} toolDefinition
* properties of the tool to add
*/
_addToolToWindows: function DT_addToolToWindows(toolDefinition) {
for (let win of this._trackedBrowserWindows) {
this._addToolToMenu(toolDefinition, win.document);
}
},
/**
* Add all tools to the developer tools menu of a window.
*
* @param {XULDocument} doc
* The document to which the tool items are to be added.
*/
_addAllToolsToMenu: function DT_addAllToolsToMenu(doc) {
let fragCommands = doc.createDocumentFragment();
let fragKeys = doc.createDocumentFragment();
let fragBroadcasters = doc.createDocumentFragment();
let fragAppMenuItems = doc.createDocumentFragment();
let fragMenuItems = doc.createDocumentFragment();
for (let [key, toolDefinition] of this._tools) {
let frags = this._addToolToMenu(toolDefinition, doc, true);
if (!frags) {
return;
}
let [cmd, key, bc, appmenuitem, menuitem] = frags;
fragCommands.appendChild(cmd);
if (key) {
fragKeys.appendChild(key);
}
fragBroadcasters.appendChild(bc);
fragAppMenuItems.appendChild(appmenuitem);
fragMenuItems.appendChild(menuitem);
}
let mcs = doc.getElementById("mainCommandSet");
mcs.appendChild(fragCommands);
let mks = doc.getElementById("mainKeyset");
mks.appendChild(fragKeys);
let mbs = doc.getElementById("mainBroadcasterSet");
mbs.appendChild(fragBroadcasters);
let amp = doc.getElementById("appmenu_webDeveloper_popup");
if (amp) {
let amps = doc.getElementById("appmenu_devtools_separator");
amp.insertBefore(fragAppMenuItems, amps);
}
let mp = doc.getElementById("menuWebDeveloperPopup");
let mps = doc.getElementById("menu_devtools_separator");
mp.insertBefore(fragMenuItems, mps);
},
/**
* Add a menu entry for a tool definition
*
* @param {string} toolDefinition
* Tool definition of the tool to add a menu entry.
* @param {XULDocument} doc
* The document to which the tool menu item is to be added.
* @param {Boolean} [noAppend]
* Return an array of elements instead of appending them to the
* document. Default is false.
*/
_addToolToMenu: function DT_addToolToMenu(toolDefinition, doc, noAppend) {
let id = toolDefinition.id;
// Prevent multiple entries for the same tool.
if (doc.getElementById("Tools:" + id)) {
return;
}
let cmd = doc.createElement("command");
cmd.id = "Tools:" + id;
cmd.setAttribute("oncommand",
'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
let key = null;
if (toolDefinition.key) {
key = doc.createElement("key");
key.id = "key_" + id;
if (toolDefinition.key.startsWith("VK_")) {
key.setAttribute("keycode", toolDefinition.key);
} else {
key.setAttribute("key", toolDefinition.key);
}
key.setAttribute("oncommand",
'gDevTools.toggleToolboxCommand(gBrowser, "' + id + '");');
key.setAttribute("modifiers", toolDefinition.modifiers);
}
let bc = doc.createElement("broadcaster");
bc.id = "devtoolsMenuBroadcaster_" + id;
bc.setAttribute("label", toolDefinition.label);
bc.setAttribute("command", "Tools:" + id);
if (key) {
bc.setAttribute("key", "key_" + id);
}
let appmenuitem = doc.createElement("menuitem");
appmenuitem.id = "appmenuitem_" + id;
appmenuitem.setAttribute("observes", "devtoolsMenuBroadcaster_" + id);
let menuitem = doc.createElement("menuitem");
menuitem.id = "menuitem_" + id;
menuitem.setAttribute("observes", "devtoolsMenuBroadcaster_" + id);
if (toolDefinition.accesskey) {
menuitem.setAttribute("accesskey", toolDefinition.accesskey);
}
if (noAppend) {
return [cmd, key, bc, appmenuitem, menuitem];
} else {
let mcs = doc.getElementById("mainCommandSet");
mcs.appendChild(cmd);
if (key) {
let mks = doc.getElementById("mainKeyset");
mks.appendChild(key);
}
let mbs = doc.getElementById("mainBroadcasterSet");
mbs.appendChild(bc);
let amp = doc.getElementById("appmenu_webDeveloper_popup");
if (amp) {
let amps = doc.getElementById("appmenu_devtools_separator");
amp.insertBefore(appmenuitem, amps);
}
let mp = doc.getElementById("menuWebDeveloperPopup");
let mps = doc.getElementById("menu_devtools_separator");
mp.insertBefore(menuitem, mps);
}
},
/**
* Update the "Toggle Toolbox" checkbox in the developer tools menu. This is
* called when a toolbox is created or destroyed.
*/
_updateMenuCheckbox: function DT_updateMenuCheckbox() {
for (let win of this._trackedBrowserWindows) {
let hasToolbox = false;
if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) {
let target = TargetFactory.forTab(win.gBrowser.selectedTab);
if (this._toolboxes.has(target)) {
hasToolbox = true;
}
}
let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox");
if (hasToolbox) {
broadcaster.setAttribute("checked", "true");
} else {
broadcaster.removeAttribute("checked");
}
}
},
/**
* Remove the menuitem for a tool to all open browser windows.
*
* @param {object} toolId
* id of the tool to remove
*/
_removeToolFromWindows: function DT_removeToolFromWindows(toolId) {
for (let win of this._trackedBrowserWindows) {
this._removeToolFromMenu(toolId, win.document);
}
},
/**
* Remove a tool's menuitem from a window
*
* @param {string} toolId
* Id of the tool to add a menu entry for
* @param {XULDocument} doc
* The document to which the tool menu item is to be removed from
*/
_removeToolFromMenu: function DT_removeToolFromMenu(toolId, doc) {
let command = doc.getElementById("Tools:" + toolId);
command.parentNode.removeChild(command);
let key = doc.getElementById("key_" + toolId);
if (key) {
key.parentNode.removeChild(key);
}
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);
*/
},
/**
* Called on browser unload to remove menu entries, toolboxes and event
* listeners from the closed browser window.
*
* @param {XULWindow} win
* The window containing the menu entry
*/
forgetBrowserWindow: function DT_forgetBrowserWindow(win) {
if (!this._tools) {
return;
}
this._trackedBrowserWindows.delete(win);
// Destroy toolboxes for closed window
for (let [target, toolbox] of this._toolboxes) {
if (toolbox.frame.ownerDocument.defaultView == win) {
toolbox.destroy();
}
}
let tabContainer = win.document.getElementById("tabbrowser-tabs")
tabContainer.removeEventListener("TabSelect",
this._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");
},
}

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