mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team
This commit is contained in:
commit
867d635d7f
@ -1035,7 +1035,6 @@ pref("devtools.debugger.remote-connection-retries", 3);
|
||||
pref("devtools.debugger.remote-timeout", 20000);
|
||||
|
||||
// The default Debugger UI settings
|
||||
pref("devtools.debugger.ui.height", 250);
|
||||
pref("devtools.debugger.ui.win-x", 0);
|
||||
pref("devtools.debugger.ui.win-y", 0);
|
||||
pref("devtools.debugger.ui.win-width", 900);
|
||||
|
@ -147,8 +147,9 @@
|
||||
</menupopup>
|
||||
</splitmenu>
|
||||
<menuseparator class="appmenu-menuseparator"/>
|
||||
<menu id="appmenu_webDeveloper"
|
||||
label="&appMenuWebDeveloper.label;">
|
||||
<splitmenu id="appmenu_webDeveloper"
|
||||
command="Tools:DevToolbox"
|
||||
label="&appMenuWebDeveloper.label;">
|
||||
<menupopup id="appmenu_webDeveloper_popup">
|
||||
<menuitem id="appmenu_devToolbox"
|
||||
observes="devtoolsMenuBroadcaster_DevToolbox"/>
|
||||
@ -165,7 +166,6 @@
|
||||
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"/>
|
||||
@ -182,7 +182,7 @@
|
||||
observes="workOfflineMenuitemState"
|
||||
oncommand="BrowserOffline.toggleOfflineStatus();"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</splitmenu>
|
||||
<menuseparator class="appmenu-menuseparator"/>
|
||||
#define ID_PREFIX appmenu_
|
||||
#define OMIT_ACCESSKEYS
|
||||
|
@ -584,7 +584,6 @@
|
||||
<menuitem id="javascriptConsole"
|
||||
observes="devtoolsMenuBroadcaster_ErrorConsole"
|
||||
accesskey="&errorConsoleCmd.accesskey;"/>
|
||||
<menuseparator id="menu_devToolsConnectSeparator"/>
|
||||
<menuitem id="menu_devtools_connect"
|
||||
observes="devtoolsMenuBroadcaster_connect"/>
|
||||
<menuseparator id="devToolsEndSeparator"/>
|
||||
|
@ -97,7 +97,7 @@
|
||||
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
|
||||
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
|
||||
<command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
|
||||
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)"/>
|
||||
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
|
||||
<command id="Tools:Sanitize"
|
||||
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
|
||||
<command id="Tools:PrivateBrowsing"
|
||||
|
@ -1444,6 +1444,14 @@ var gBrowserInit = {
|
||||
cmd.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
// Enable DevTools connection screen, if the preference allows this.
|
||||
let devtoolsRemoteEnabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
|
||||
if (devtoolsRemoteEnabled) {
|
||||
let cmd = document.getElementById("Tools:DevToolsConnect");
|
||||
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,
|
||||
|
@ -173,12 +173,6 @@ DebuggerUI.prototype = {
|
||||
return '_chromeDebugger' in this ? this._chromeDebugger : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the preferences associated with the debugger frontend.
|
||||
* @return object
|
||||
*/
|
||||
get preferences() Prefs,
|
||||
|
||||
/**
|
||||
* Currently, there can only be one debugger per tab.
|
||||
* Show an asynchronous notification which asks the user to switch the
|
||||
@ -279,7 +273,6 @@ DebuggerPane.prototype = {
|
||||
this._splitter.setAttribute("class", "devtools-horizontal-splitter");
|
||||
|
||||
this._frame = ownerDocument.createElement("iframe");
|
||||
this._frame.height = Prefs.height;
|
||||
|
||||
this._nbox = gBrowser.getNotificationBox(this._tab.linkedBrowser);
|
||||
this._nbox.appendChild(this._splitter);
|
||||
@ -326,7 +319,6 @@ DebuggerPane.prototype = {
|
||||
}, true)
|
||||
}
|
||||
|
||||
Prefs.height = this._frame.height;
|
||||
this._frame.removeEventListener("Debugger:Unloaded", this.close, true);
|
||||
this._nbox.removeChild(this._splitter);
|
||||
this._nbox.removeChild(this._frame);
|
||||
@ -599,21 +591,7 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
|
||||
/**
|
||||
* Shortcuts for accessing various debugger preferences.
|
||||
*/
|
||||
let Prefs = {
|
||||
/**
|
||||
* Gets the preferred height of the debugger pane.
|
||||
* @return number
|
||||
*/
|
||||
get height()
|
||||
Services.prefs.getIntPref("devtools.debugger.ui.height"),
|
||||
|
||||
/**
|
||||
* Sets the preferred height of the debugger pane.
|
||||
* @param number aValue
|
||||
*/
|
||||
set height(aValue)
|
||||
Services.prefs.setIntPref("devtools.debugger.ui.height", aValue)
|
||||
};
|
||||
let Prefs = {};
|
||||
|
||||
/**
|
||||
* Gets the preferred default remote debugging host.
|
||||
|
@ -11,6 +11,7 @@ const Cu = Components.utils;
|
||||
|
||||
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const NEW_SCRIPT_DISPLAY_DELAY = 200; // ms
|
||||
const FETCH_SOURCE_RESPONSE_DELAY = 50; // ms
|
||||
const FRAME_STEP_CLEAR_DELAY = 100; // ms
|
||||
const CALL_STACK_PAGE_SIZE = 25; // frames
|
||||
|
||||
@ -1166,6 +1167,7 @@ SourceScripts.prototype = {
|
||||
|
||||
DebuggerView.Sources.push(label, url, {
|
||||
forced: aOptions.forced,
|
||||
tooltip: url,
|
||||
attachment: aSource
|
||||
});
|
||||
},
|
||||
@ -1177,18 +1179,29 @@ SourceScripts.prototype = {
|
||||
* The source object coming from the active thread.
|
||||
* @param function aCallback
|
||||
* Function called after the source text has been loaded.
|
||||
* @param function aOnTimeout
|
||||
* Function called when the source text takes too long to fetch.
|
||||
*/
|
||||
getText: function SS_getText(aSource, aCallback) {
|
||||
getText: function SS_getText(aSource, aCallback, aOnTimeout) {
|
||||
// If already loaded, return the source text immediately.
|
||||
if (aSource.loaded) {
|
||||
aCallback(aSource.url, aSource.text);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the source text takes too long to fetch, invoke a timeout to
|
||||
// avoid blocking any operations.
|
||||
if (aOnTimeout) {
|
||||
var fetchTimeout = window.setTimeout(aOnTimeout, FETCH_SOURCE_RESPONSE_DELAY);
|
||||
}
|
||||
|
||||
// Get the source text from the active thread.
|
||||
this.activeThread.source(aSource.source).source(function(aResponse) {
|
||||
window.clearTimeout(fetchTimeout);
|
||||
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("Error loading " + aUrl);
|
||||
Cu.reportError("Error loading " + aSource.url + "\n" + aResponse.error);
|
||||
aCallback(aSource.url, "");
|
||||
return;
|
||||
}
|
||||
aSource.loaded = true;
|
||||
@ -1609,7 +1622,6 @@ let Prefs = {
|
||||
}
|
||||
};
|
||||
|
||||
Prefs.map("Int", "height", "devtools.debugger.ui.height");
|
||||
Prefs.map("Int", "windowX", "devtools.debugger.ui.win-x");
|
||||
Prefs.map("Int", "windowY", "devtools.debugger.ui.win-y");
|
||||
Prefs.map("Int", "windowWidth", "devtools.debugger.ui.win-width");
|
||||
|
@ -1260,6 +1260,7 @@ function GlobalSearchView() {
|
||||
MenuContainer.call(this);
|
||||
this._startSearch = this._startSearch.bind(this);
|
||||
this._onFetchSourceFinished = this._onFetchSourceFinished.bind(this);
|
||||
this._onFetchSourceTimeout = this._onFetchSourceTimeout.bind(this);
|
||||
this._onFetchSourcesFinished = this._onFetchSourcesFinished.bind(this);
|
||||
this._createItemView = this._createItemView.bind(this);
|
||||
this._onScroll = this._onScroll.bind(this);
|
||||
@ -1402,25 +1403,29 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
this._sourcesCount = locations.length;
|
||||
this._searchedToken = aQuery;
|
||||
|
||||
this._fetchSources(
|
||||
this._onFetchSourceFinished,
|
||||
this._onFetchSourcesFinished, locations);
|
||||
this._fetchSources(locations, {
|
||||
onFetch: this._onFetchSourceFinished,
|
||||
onTimeout: this._onFetchSourceTimeout,
|
||||
onFinished: this._onFetchSourcesFinished
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts fetching all the sources, silently.
|
||||
*
|
||||
* @param function aFetchCallback
|
||||
* Called after each source is fetched.
|
||||
* @param function aFetchedCallback
|
||||
* Called if all the sources were already fetched.
|
||||
* @param array aLocations
|
||||
* The locations for the sources to fetch.
|
||||
* @param object aCallbacks
|
||||
* An object containing the callback functions to invoke:
|
||||
* - onFetch: called after each source is fetched
|
||||
* - onTimeout: called when a source's text takes too long to fetch
|
||||
* - onFinished: called if all the sources were already fetched
|
||||
*/
|
||||
_fetchSources: function DVGS__fetchSources(aFetchCallback, aFetchedCallback, aLocations) {
|
||||
_fetchSources:
|
||||
function DVGS__fetchSources(aLocations, { onFetch, onTimeout, onFinished }) {
|
||||
// If all the sources were already fetched, then don't do anything.
|
||||
if (this._cache.size == aLocations.length) {
|
||||
aFetchedCallback();
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1430,7 +1435,8 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
continue;
|
||||
}
|
||||
let sourceItem = DebuggerView.Sources.getItemByValue(location);
|
||||
DebuggerController.SourceScripts.getText(sourceItem.attachment, aFetchCallback);
|
||||
let sourceObject = sourceItem.attachment;
|
||||
DebuggerController.SourceScripts.getText(sourceObject, onFetch, onTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1452,10 +1458,24 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a source's text takes too long to fetch.
|
||||
*/
|
||||
_onFetchSourceTimeout: function DVGS__onFetchSourceTimeout() {
|
||||
// Remove the source from the load queue.
|
||||
this._sourcesCount--;
|
||||
|
||||
// Check if the remaining sources were fetched and stored in the cache.
|
||||
if (this._cache.size == this._sourcesCount) {
|
||||
this._onFetchSourcesFinished();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all the sources have been fetched.
|
||||
*/
|
||||
_onFetchSourcesFinished: function DVGS__onFetchSourcesFinished() {
|
||||
// At least one source needs to be present to perform a global search.
|
||||
if (!this._sourcesCount) {
|
||||
return;
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
*/
|
||||
function ToolbarView() {
|
||||
dumpn("ToolbarView was instantiated");
|
||||
this._onCloseClick = this._onCloseClick.bind(this);
|
||||
this._onTogglePanesPressed = this._onTogglePanesPressed.bind(this);
|
||||
this._onResumePressed = this._onResumePressed.bind(this);
|
||||
this._onStepOverPressed = this._onStepOverPressed.bind(this);
|
||||
@ -108,13 +107,6 @@ ToolbarView.prototype = {
|
||||
this._sources.setAttribute("hidden", !aVisibleFlag);
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener handling the close button click event.
|
||||
*/
|
||||
_onCloseClick: function DVT__onCloseClick() {
|
||||
DebuggerController._shutdownDebugger();
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener handling the toggle button click event.
|
||||
*/
|
||||
|
@ -618,6 +618,7 @@ MenuContainer.prototype = {
|
||||
* - unsorted: true if the items should not always remain sorted
|
||||
* - relaxed: true if this container should allow dupes & degenerates
|
||||
* - description: an optional description of the item
|
||||
* - tooltip: an optional tooltip for the item
|
||||
* - attachment: some attached primitive/object
|
||||
* @return MenuItem
|
||||
* The item associated with the displayed element if a forced push,
|
||||
@ -629,7 +630,7 @@ MenuContainer.prototype = {
|
||||
|
||||
// Batch the item to be added later.
|
||||
if (!aOptions.forced) {
|
||||
this._stagedItems.push(item);
|
||||
this._stagedItems.push({ item: item, options: aOptions });
|
||||
}
|
||||
// Immediately insert the item at the specified index.
|
||||
else if (aOptions.forced && aOptions.forced.atIndex !== undefined) {
|
||||
@ -657,11 +658,12 @@ MenuContainer.prototype = {
|
||||
|
||||
// By default, sort the items before adding them to this container.
|
||||
if (!aOptions.unsorted) {
|
||||
stagedItems.sort(function(a, b) a.label.toLowerCase() > b.label.toLowerCase());
|
||||
stagedItems.sort(function(a, b) a.item.label.toLowerCase() >
|
||||
b.item.label.toLowerCase());
|
||||
}
|
||||
// Append the prepared items to this container.
|
||||
for (let item of stagedItems) {
|
||||
this._appendItem(item, aOptions);
|
||||
for (let { item, options } of stagedItems) {
|
||||
this._appendItem(item, options);
|
||||
}
|
||||
// Recreate the temporary items list for ulterior pushes.
|
||||
this._stagedItems = [];
|
||||
@ -750,7 +752,7 @@ MenuContainer.prototype = {
|
||||
*/
|
||||
containsLabel: function DVMC_containsLabel(aLabel) {
|
||||
return this._itemsByLabel.has(aLabel) ||
|
||||
this._stagedItems.some(function(o) o.label == aLabel);
|
||||
this._stagedItems.some(function({item}) item.label == aLabel);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -764,7 +766,7 @@ MenuContainer.prototype = {
|
||||
*/
|
||||
containsValue: function DVMC_containsValue(aValue) {
|
||||
return this._itemsByValue.has(aValue) ||
|
||||
this._stagedItems.some(function(o) o.value == aValue);
|
||||
this._stagedItems.some(function({item}) item.value == aValue);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -788,7 +790,7 @@ MenuContainer.prototype = {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return this._stagedItems.some(function(o) aTrim(o.value) == trimmedValue);
|
||||
return this._stagedItems.some(function({item}) aTrim(item.value) == trimmedValue);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1046,8 +1048,15 @@ MenuContainer.prototype = {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._entangleItem(aItem, this._container.appendItem(
|
||||
this._entangleItem(aItem, this._container.appendItem(
|
||||
aItem.label, aItem.value, "", aOptions.attachment));
|
||||
|
||||
// Handle any additional options after entangling the item.
|
||||
if (aOptions.tooltip) {
|
||||
aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
|
||||
}
|
||||
|
||||
return aItem;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1068,8 +1077,15 @@ MenuContainer.prototype = {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._entangleItem(aItem, this._container.insertItemAt(
|
||||
this._entangleItem(aItem, this._container.insertItemAt(
|
||||
aIndex, aItem.label, aItem.value, "", aOptions.attachment));
|
||||
|
||||
// Handle any additional options after entangling the item.
|
||||
if (aOptions.tooltip) {
|
||||
aItem._target.setAttribute("tooltiptext", aOptions.tooltip);
|
||||
}
|
||||
|
||||
return aItem;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -114,6 +114,16 @@ ToolSidebar.prototype = {
|
||||
return currentID;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the requested tab based on the id.
|
||||
*
|
||||
* @param String id
|
||||
* unique id of the requested tab.
|
||||
*/
|
||||
getTab: function ToolSidebar_getTab(id) {
|
||||
return this._tabbox.tabpanels.querySelector("#sidebar-panel-" + id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler.
|
||||
*/
|
||||
@ -176,7 +186,7 @@ ToolSidebar.prototype = {
|
||||
}
|
||||
this._destroyed = true;
|
||||
|
||||
this._tabbox.removeEventListener("select", this, true);
|
||||
this._tabbox.tabpanels.removeEventListener("select", this, true);
|
||||
|
||||
while (this._tabbox.tabpanels.hasChildNodes()) {
|
||||
this._tabbox.tabpanels.removeChild(this._tabbox.tabpanels.firstChild);
|
||||
|
@ -295,9 +295,10 @@ TabWebProgressListener.prototype = {
|
||||
onSecurityChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
|
||||
onLocationChange: function TwPL_onLocationChange(webProgress) {
|
||||
let window = webProgress.DOMWindow;
|
||||
if (this.target) {
|
||||
onLocationChange: function TwPL_onLocationChange(webProgress, request, URI, flags) {
|
||||
if (this.target &&
|
||||
!(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)) {
|
||||
let window = webProgress.DOMWindow;
|
||||
this.target.emit("navigate", window);
|
||||
}
|
||||
},
|
||||
|
@ -69,6 +69,8 @@ let webConsoleDefinition = {
|
||||
icon: "chrome://browser/skin/devtools/webconsole-tool-icon.png",
|
||||
url: "chrome://browser/content/devtools/webconsole.xul",
|
||||
label: l10n("ToolboxWebconsole.label", webConsoleStrings),
|
||||
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
},
|
||||
@ -88,6 +90,7 @@ let debuggerDefinition = {
|
||||
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
|
||||
url: "chrome://browser/content/debugger.xul",
|
||||
label: l10n("ToolboxDebugger.label", debuggerStrings),
|
||||
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
@ -108,6 +111,7 @@ let inspectorDefinition = {
|
||||
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
|
||||
url: "chrome://browser/content/devtools/inspector/inspector.xul",
|
||||
label: l10n("inspector.label", inspectorStrings),
|
||||
tooltip: l10n("inspector.tooltip", inspectorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isRemote;
|
||||
@ -127,6 +131,7 @@ let styleEditorDefinition = {
|
||||
modifiers: "shift",
|
||||
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
|
||||
url: "chrome://browser/content/styleeditor.xul",
|
||||
tooltip: l10n("ToolboxStyleEditor.tooltip", styleEditorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isRemote && !target.isChrome;
|
||||
@ -144,6 +149,7 @@ let profilerDefinition = {
|
||||
icon: "chrome://browser/skin/devtools/tools-icons-small.png",
|
||||
url: "chrome://browser/content/profiler.xul",
|
||||
label: l10n("profiler.label", profilerStrings),
|
||||
tooltip: l10n("profiler.tooltip", profilerStrings),
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
if (target.isRemote || target.isChrome) {
|
||||
|
@ -16,6 +16,17 @@ XPCOMUtils.defineLazyModuleGetter(this, "Hosts",
|
||||
"resource:///modules/devtools/ToolboxHosts.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
|
||||
"resource:///modules/devtools/DeveloperToolbar.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function() {
|
||||
let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
|
||||
let l10n = function(name) {
|
||||
try {
|
||||
return bundle.GetStringFromName(name);
|
||||
} catch (ex) {
|
||||
Services.console.logStringMessage("Error reading '" + name + "'");
|
||||
}
|
||||
};
|
||||
return l10n;
|
||||
});
|
||||
|
||||
// DO NOT put Require.jsm or gcli.jsm into lazy getters as this breaks the
|
||||
// requisition import a few lines down.
|
||||
@ -285,6 +296,8 @@ Toolbox.prototype = {
|
||||
let button = this.doc.createElement("toolbarbutton");
|
||||
button.id = "toolbox-dock-" + position;
|
||||
button.className = "toolbox-dock-button";
|
||||
button.setAttribute("tooltiptext", toolboxStrings("toolboxDockButtons." +
|
||||
position + ".tooltip"));
|
||||
button.addEventListener("command", function(position) {
|
||||
this.switchHost(position);
|
||||
}.bind(this, position));
|
||||
@ -348,6 +361,7 @@ Toolbox.prototype = {
|
||||
radio.className = "toolbox-tab devtools-tab";
|
||||
radio.id = "toolbox-tab-" + id;
|
||||
radio.setAttribute("toolid", id);
|
||||
radio.setAttribute("tooltiptext", toolDefinition.tooltip);
|
||||
|
||||
let ordinal = (typeof toolDefinition.ordinal == "number") ?
|
||||
toolDefinition.ordinal : MAX_ORDINAL;
|
||||
|
@ -1,14 +1,25 @@
|
||||
html {
|
||||
background: url("chrome://browser/skin/newtab/noise.png");
|
||||
background-color: #111;
|
||||
background-image: url("chrome://browser/skin/newtab/noise.png");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial;
|
||||
padding: 20px;
|
||||
border-radius: 3px;
|
||||
font-family: Arial, sans-serif;
|
||||
color: white;
|
||||
max-width: 600px;
|
||||
min-height: 400px;
|
||||
margin: 10px auto 0;
|
||||
margin: 30px auto 0;
|
||||
box-shadow: 0 2px 3px black;
|
||||
background-color: #3C3E40;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: rgba(0,0,0,0.12);
|
||||
background-image: radial-gradient(ellipse farthest-corner at center top , rgb(159, 223, 255), rgba(101, 203, 255, 0.3)), radial-gradient(ellipse farthest-side at center top , rgba(101, 203, 255, 0.4), rgba(101, 203, 255, 0));
|
||||
background-size: 100% 2px, 100% 5px;
|
||||
background-repeat: no-repeat;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
label {
|
||||
@ -29,18 +40,21 @@ label > span {
|
||||
margin-left: 160px;
|
||||
}
|
||||
|
||||
|
||||
#actors, #connection-form {
|
||||
margin: 20px;
|
||||
input:invalid {
|
||||
box-shadow: 0 0 2px 2px #F06;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid grey;
|
||||
section {
|
||||
min-height: 160px;
|
||||
margin: 60px 20px;
|
||||
display: none; /* By default, hidden */
|
||||
}
|
||||
|
||||
#connection-form,
|
||||
#connecting,
|
||||
#actors-list {
|
||||
.error-message {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.error-message:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -60,20 +74,9 @@ body.connecting > #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;
|
||||
#connecting > p > img {
|
||||
vertical-align: top;
|
||||
}
|
||||
@keyframes anim {to {
|
||||
transform: scale(0.5) rotate(0.1deg);
|
||||
}}
|
||||
|
||||
#actors {
|
||||
padding-left: 0;
|
||||
@ -84,4 +87,22 @@ body.connecting > #connecting {
|
||||
display: block;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.remote-process {
|
||||
font-style: italic;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 10px;
|
||||
background-color: rgba(0,0,0,0.12);
|
||||
border-top: 1px solid rgba(0,0,0,0.1);
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
footer > a,
|
||||
footer > a:visited {
|
||||
color: white;
|
||||
}
|
||||
|
@ -10,91 +10,158 @@ 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/XPCOMUtils.jsm');
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
let gClient;
|
||||
let gConnectionTimeout;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(window, 'l10n', function () {
|
||||
return Services.strings.createBundle('chrome://browser/locale/devtools/connection-screen.properties');
|
||||
});
|
||||
|
||||
/**
|
||||
* Once DOM is ready, we prefil the host/port inputs with
|
||||
* pref-stored values.
|
||||
*/
|
||||
window.addEventListener("DOMContentLoaded", function onDOMReady() {
|
||||
window.removeEventListener("DOMContentLoaded", onDOMReady, true);
|
||||
let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
|
||||
let port = Services.prefs.getIntPref("devtools.debugger.remote-port");
|
||||
|
||||
if (host) {
|
||||
document.getElementById("host").value = host;
|
||||
}
|
||||
|
||||
if (port) {
|
||||
document.getElementById("port").value = port;
|
||||
}
|
||||
|
||||
}, true);
|
||||
|
||||
/**
|
||||
* Called when the "connect" button is clicked.
|
||||
*/
|
||||
function submit() {
|
||||
// Show the "connecting" screen
|
||||
document.body.classList.add("connecting");
|
||||
|
||||
// Save the host/port values
|
||||
let host = document.getElementById("host").value;
|
||||
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
|
||||
|
||||
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);
|
||||
}
|
||||
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
|
||||
|
||||
// Initiate the connection
|
||||
let transport = debuggerSocketConnect(host, port);
|
||||
let client = gClient = new DebuggerClient(transport);
|
||||
gClient = new DebuggerClient(transport);
|
||||
let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
|
||||
gConnectionTimeout = setTimeout(handleConnectionTimeout, delay);
|
||||
gClient.connect(onConnectionReady);
|
||||
}
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(function(aResponse) {
|
||||
document.body.classList.remove("connecting");
|
||||
document.body.classList.add("actors-mode");
|
||||
/**
|
||||
* Connection is ready. List actors and build buttons.
|
||||
*/
|
||||
function onConnectionReady(aType, aTraits) {
|
||||
clearTimeout(gConnectionTimeout);
|
||||
gClient.listTabs(function(aResponse) {
|
||||
document.body.classList.remove("connecting");
|
||||
document.body.classList.add("actors-mode");
|
||||
|
||||
let parent = document.getElementById("actors");
|
||||
let focusSet = false;
|
||||
let parent = document.getElementById("actors");
|
||||
|
||||
// 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);
|
||||
}
|
||||
// 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).
|
||||
|
||||
a.title = a.textContent = "Remote process";
|
||||
a.href = "#";
|
||||
// Add one entry for each open tab.
|
||||
for (let i = 0; i < aResponse.tabs.length; i++) {
|
||||
buildLink(aResponse.tabs[i], parent, i == aResponse.selected);
|
||||
}
|
||||
|
||||
// Build the Remote Process button
|
||||
if (Object.keys(globals).length > 1) {
|
||||
let a = document.createElement("a");
|
||||
a.onclick = function() {
|
||||
openToolbox(globals, true);
|
||||
|
||||
parent.appendChild(a);
|
||||
}
|
||||
a.title = a.textContent = window.l10n.GetStringFromName("remoteProcess");
|
||||
a.className = "remote-process";
|
||||
a.href = "#";
|
||||
parent.appendChild(a);
|
||||
}
|
||||
// Move the selected tab on top
|
||||
let selectedLink = parent.querySelector("a.selected");
|
||||
if (selectedLink) {
|
||||
parent.insertBefore(selectedLink, parent.firstChild);
|
||||
}
|
||||
|
||||
// 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];
|
||||
// Ensure the first link is focused
|
||||
let firstLink = parent.querySelector("a:first-of-type");
|
||||
if (firstLink) {
|
||||
firstLink.focus();
|
||||
}
|
||||
|
||||
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) {
|
||||
/**
|
||||
* Build one button for an actor.
|
||||
*/
|
||||
function buildLink(tab, parent, selected) {
|
||||
let a = document.createElement("a");
|
||||
a.onclick = function() {
|
||||
openToolbox(tab);
|
||||
}
|
||||
|
||||
a.textContent = tab.title;
|
||||
a.title = tab.url;
|
||||
if (!a.textContent) {
|
||||
a.textContent = tab.url;
|
||||
}
|
||||
a.href = "#";
|
||||
|
||||
if (selected) {
|
||||
a.classList.add("selected");
|
||||
}
|
||||
|
||||
parent.appendChild(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* An error occured. Let's show it and return to the first screen.
|
||||
*/
|
||||
function showError(type) {
|
||||
document.body.className = "error";
|
||||
let activeError = document.querySelector(".error-message.active");
|
||||
if (activeError) {
|
||||
activeError.classList.remove("active");
|
||||
}
|
||||
activeError = document.querySelector(".error-" + type);
|
||||
if (activeError) {
|
||||
activeError.classList.add("active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection timeout.
|
||||
*/
|
||||
function handleConnectionTimeout() {
|
||||
showError("timeout");
|
||||
}
|
||||
|
||||
/**
|
||||
* The user clicked on one of the buttons.
|
||||
* Opens the toolbox.
|
||||
*/
|
||||
function openToolbox(form, chrome=false) {
|
||||
let target = TargetFactory.forRemote(form, gClient, chrome);
|
||||
gDevTools.showToolbox(target, "webconsole", Toolbox.HostType.WINDOW);
|
||||
window.close();
|
||||
}
|
||||
|
@ -12,34 +12,37 @@
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<head>
|
||||
<title>&title;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
|
||||
<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>
|
||||
<h1>&header;</h1>
|
||||
<section id="connection-form">
|
||||
<form onsubmit="window.submit()" action="#">
|
||||
<form validate="validate" onsubmit="window.submit()" action="#">
|
||||
<label>
|
||||
<span>&host;</span>
|
||||
<input id="host" type="text" placeholder="localhost"></input>
|
||||
<input required="required" class="devtools-textinput" id="host" type="text"></input>
|
||||
</label>
|
||||
<label>
|
||||
<span>&port;</span>
|
||||
<input id="port" type="number" placeholder="6000"></input>
|
||||
<input required="required" class="devtools-textinput" id="port" type="number" pattern="\d+"></input>
|
||||
</label>
|
||||
<label>
|
||||
<input id="submit" type="submit" value="&connect;"></input>
|
||||
<input class="devtools-toolbarbutton" id="submit" type="submit" value="&connect;"></input>
|
||||
</label>
|
||||
</form>
|
||||
<p class="error-message error-timeout">&errorTimeout;</p>
|
||||
<p class="error-message error-refused">&errorRefused;</p>
|
||||
<p class="error-message error-unexpected">&errorUnexpected;</p>
|
||||
</section>
|
||||
<section id="actors-list">
|
||||
<p>&availability;</p>
|
||||
<ul id="actors"></ul>
|
||||
</section>
|
||||
<section id="connecting">
|
||||
<p>&connecting;</p>
|
||||
<div id="throbber"></div>
|
||||
<p><img src="chrome://browser/skin/tabbrowser/loading.png"></img> &connecting;</p>
|
||||
</section>
|
||||
<footer>&help;</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,6 +2,10 @@
|
||||
<!-- 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 window [
|
||||
<!ENTITY % toolboxDTD SYSTEM "chrome://browser/locale/devtools/toolbox.dtd" >
|
||||
%toolboxDTD;
|
||||
]>
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/shared/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/framework/toolbox.css" type="text/css"?>
|
||||
@ -15,7 +19,9 @@
|
||||
<toolbar class="devtools-tabbar">
|
||||
#ifdef XP_MACOSX
|
||||
<hbox id="toolbox-controls">
|
||||
<toolbarbutton id="toolbox-close" class="devtools-closebutton"></toolbarbutton>
|
||||
<toolbarbutton id="toolbox-close"
|
||||
class="devtools-closebutton"
|
||||
tooltiptext="&toolboxCloseButton.tooltip;"/>
|
||||
<hbox id="toolbox-dock-buttons"/>
|
||||
</hbox>
|
||||
#endif
|
||||
@ -25,7 +31,9 @@
|
||||
#ifndef XP_MACOSX
|
||||
<hbox id="toolbox-controls">
|
||||
<hbox id="toolbox-dock-buttons"/>
|
||||
<toolbarbutton id="toolbox-close" class="devtools-closebutton"></toolbarbutton>
|
||||
<toolbarbutton id="toolbox-close"
|
||||
class="devtools-closebutton"
|
||||
tooltiptext="&toolboxCloseButton.tooltip;"/>
|
||||
</hbox>
|
||||
#endif
|
||||
</toolbar>
|
||||
|
@ -83,7 +83,6 @@ HTMLBreadcrumbs.prototype = {
|
||||
this.update = this.update.bind(this);
|
||||
this.updateSelectors = this.updateSelectors.bind(this);
|
||||
this.selection.on("new-node", this.update);
|
||||
this.selection.on("detached", this.update);
|
||||
this.selection.on("pseudoclass", this.updateSelectors);
|
||||
this.selection.on("attribute-changed", this.updateSelectors);
|
||||
this.update();
|
||||
@ -296,7 +295,6 @@ HTMLBreadcrumbs.prototype = {
|
||||
});
|
||||
|
||||
this.selection.off("new-node", this.update);
|
||||
this.selection.off("detached", this.update);
|
||||
this.selection.off("pseudoclass", this.updateSelectors);
|
||||
this.selection.off("attribute-changed", this.updateSelectors);
|
||||
|
||||
|
@ -133,7 +133,6 @@ Highlighter.prototype = {
|
||||
|
||||
this.selection.on("new-node", this.highlight);
|
||||
this.selection.on("new-node", this.updateInfobar);
|
||||
this.selection.on("detached", this.highlight);
|
||||
this.selection.on("pseudoclass", this.updateInfobar);
|
||||
this.selection.on("attribute-changed", this.updateInfobar);
|
||||
|
||||
@ -168,7 +167,6 @@ Highlighter.prototype = {
|
||||
|
||||
this.selection.off("new-node", this.highlight);
|
||||
this.selection.off("new-node", this.updateInfobar);
|
||||
this.selection.off("detached", this.highlight);
|
||||
this.selection.off("pseudoclass", this.updateInfobar);
|
||||
this.selection.off("attribute-changed", this.updateInfobar);
|
||||
|
||||
|
@ -68,6 +68,8 @@ InspectorPanel.prototype = {
|
||||
this._selection = new Selection();
|
||||
this.onNewSelection = this.onNewSelection.bind(this);
|
||||
this.selection.on("new-node", this.onNewSelection);
|
||||
this.onDetached = this.onDetached.bind(this);
|
||||
this.selection.on("detached", this.onDetached);
|
||||
|
||||
this.breadcrumbs = new HTMLBreadcrumbs(this);
|
||||
|
||||
@ -170,6 +172,7 @@ InspectorPanel.prototype = {
|
||||
}.bind(this);
|
||||
|
||||
this.sidebar.on("select", this._setDefaultSidebar);
|
||||
this.toggleHighlighter = this.toggleHighlighter.bind(this);
|
||||
|
||||
this.sidebar.addTab("ruleview",
|
||||
"chrome://browser/content/devtools/cssruleview.xul",
|
||||
@ -183,6 +186,10 @@ InspectorPanel.prototype = {
|
||||
"chrome://browser/content/devtools/layoutview/view.xhtml",
|
||||
"layoutview" == defaultTab);
|
||||
|
||||
let ruleViewTab = this.sidebar.getTab("ruleview");
|
||||
ruleViewTab.addEventListener("mouseover", this.toggleHighlighter, false);
|
||||
ruleViewTab.addEventListener("mouseout", this.toggleHighlighter, false);
|
||||
|
||||
this.sidebar.show();
|
||||
},
|
||||
|
||||
@ -275,6 +282,15 @@ InspectorPanel.prototype = {
|
||||
this.cancelLayoutChange();
|
||||
},
|
||||
|
||||
/**
|
||||
* When a node is deleted, select its parent node.
|
||||
*/
|
||||
onDetached: function InspectorPanel_onDetached(event, parentNode) {
|
||||
this.cancelLayoutChange();
|
||||
this.breadcrumbs.cutAfter(this.breadcrumbs.indexOf(parentNode));
|
||||
this.selection.setNode(parentNode, "detached");
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the inspector.
|
||||
*/
|
||||
@ -310,6 +326,7 @@ InspectorPanel.prototype = {
|
||||
this.nodemenu.removeEventListener("popuphiding", this._resetNodeMenu, true);
|
||||
this.breadcrumbs.destroy();
|
||||
this.selection.off("new-node", this.onNewSelection);
|
||||
this.selection.off("detached", this.onDetached);
|
||||
this._destroyMarkup();
|
||||
this._selection.destroy();
|
||||
this._selection = null;
|
||||
@ -447,6 +464,19 @@ InspectorPanel.prototype = {
|
||||
this.selection.emit("pseudoclass");
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the highlighter when ruleview is hovered.
|
||||
*/
|
||||
toggleHighlighter: function InspectorPanel_toggleHighlighter(event)
|
||||
{
|
||||
if (event.type == "mouseover") {
|
||||
this.highlighter.hide();
|
||||
}
|
||||
else if (event.type == "mouseout") {
|
||||
this.highlighter.show();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the innerHTML of the selected Node to the clipboard.
|
||||
*/
|
||||
|
@ -70,12 +70,14 @@ Selection.prototype = {
|
||||
_onMutations: function(mutations) {
|
||||
let attributeChange = false;
|
||||
let detached = false;
|
||||
let parentNode = null;
|
||||
for (let m of mutations) {
|
||||
if (!attributeChange && m.type == "attributes") {
|
||||
attributeChange = true;
|
||||
}
|
||||
if (m.type == "childList") {
|
||||
if (!detached && !this.isConnected()) {
|
||||
parentNode = m.target;
|
||||
detached = true;
|
||||
}
|
||||
}
|
||||
@ -84,7 +86,7 @@ Selection.prototype = {
|
||||
if (attributeChange)
|
||||
this.emit("attribute-changed");
|
||||
if (detached)
|
||||
this.emit("detached");
|
||||
this.emit("detached", parentNode);
|
||||
},
|
||||
|
||||
_attachEvents: function SN__attachEvents() {
|
||||
|
@ -35,6 +35,7 @@ _BROWSER_FILES = \
|
||||
browser_inspector_highlighter_autohide.js \
|
||||
browser_inspector_changes.js \
|
||||
browser_inspector_bug_674871.js \
|
||||
browser_inspector_bug_817558_delete_node.js \
|
||||
head.js \
|
||||
helpers.js \
|
||||
$(NULL)
|
||||
|
@ -104,7 +104,7 @@ function test() {
|
||||
is(para.textContent, "test2", "paragraph content is correct");
|
||||
|
||||
let root = content.document.documentElement;
|
||||
ok(inspector.selection.node, root, "Selection is the root of the new page.");
|
||||
is(inspector.selection.node, root, "Selection is the root of the new page.");
|
||||
|
||||
ok(alertActive1_called, "first notification box has been showed");
|
||||
ok(alertActive2_called, "second notification box has been showed");
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
//ignoreAllUncaughtExceptions();
|
||||
|
||||
let node, iframe, inspector;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(setupTest, content);
|
||||
}, true);
|
||||
|
||||
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_destroyselection.html";
|
||||
|
||||
function setupTest()
|
||||
{
|
||||
iframe = content.document.querySelector("iframe");
|
||||
node = iframe.contentDocument.querySelector("span");
|
||||
openInspector(runTests);
|
||||
}
|
||||
|
||||
function runTests(aInspector)
|
||||
{
|
||||
inspector = aInspector;
|
||||
inspector.selection.setNode(node);
|
||||
|
||||
let parentNode = node.parentNode;
|
||||
parentNode.removeChild(node);
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
|
||||
executeSoon(function() {
|
||||
is(inspector.selection.node, parentNode, "parent of selection got selected");
|
||||
|
||||
finishUp();
|
||||
});
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
node = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ LayoutView.prototype = {
|
||||
this.update = this.update.bind(this);
|
||||
this.onNewNode = this.onNewNode.bind(this);
|
||||
this.onHighlighterLocked = this.onHighlighterLocked.bind(this);
|
||||
this.inspector.selection.on("detached", this.onNewNode);
|
||||
this.inspector.selection.on("new-node", this.onNewNode);
|
||||
this.inspector.sidebar.on("layoutview-selected", this.onNewNode);
|
||||
if (this.inspector.highlighter) {
|
||||
@ -101,7 +100,6 @@ LayoutView.prototype = {
|
||||
destroy: function LV_destroy() {
|
||||
this.inspector.sidebar.off("layoutview-selected", this.onNewNode);
|
||||
this.inspector.selection.off("new-node", this.onNewNode);
|
||||
this.inspector.selection.off("detached", this.onNewNode);
|
||||
if (this.browser) {
|
||||
this.browser.removeEventListener("MozAfterPaint", this.update, true);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ const Ci = Components.interfaces;
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
const PREVIEW_AREA = 700;
|
||||
const DEFAULT_MAX_CHILDREN = 100;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MarkupView"];
|
||||
|
||||
@ -20,6 +21,7 @@ Cu.import("resource:///modules/devtools/CssRuleView.jsm");
|
||||
Cu.import("resource:///modules/devtools/Templater.jsm");
|
||||
Cu.import("resource:///modules/devtools/Undo.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
/**
|
||||
* Vocabulary for the purposes of this file:
|
||||
@ -46,6 +48,12 @@ this.MarkupView = function MarkupView(aInspector, aFrame, aControllerWindow)
|
||||
this.doc = this._frame.contentDocument;
|
||||
this._elt = this.doc.querySelector("#root");
|
||||
|
||||
try {
|
||||
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
|
||||
} catch(ex) {
|
||||
this.maxChildren = DEFAULT_MAX_CHILDREN;
|
||||
}
|
||||
|
||||
this.undo = new UndoStack();
|
||||
this.undo.installController(aControllerWindow);
|
||||
|
||||
@ -69,7 +77,7 @@ this.MarkupView = function MarkupView(aInspector, aFrame, aControllerWindow)
|
||||
MarkupView.prototype = {
|
||||
_selectedContainer: null,
|
||||
|
||||
template: function MT_template(aName, aDest, aOptions)
|
||||
template: function MT_template(aName, aDest, aOptions={stack: "markup-view.xhtml"})
|
||||
{
|
||||
let node = this.doc.getElementById("template-" + aName).cloneNode(true);
|
||||
node.removeAttribute("id");
|
||||
@ -288,7 +296,6 @@ MarkupView.prototype = {
|
||||
let walker = documentWalker(aNode);
|
||||
let parent = walker.parentNode();
|
||||
if (parent) {
|
||||
// Make sure parents of this node are imported too.
|
||||
var container = new MarkupContainer(this, aNode);
|
||||
} else {
|
||||
var container = new RootContainer(this, aNode);
|
||||
@ -298,12 +305,15 @@ MarkupView.prototype = {
|
||||
// Fake a childList mutation here.
|
||||
this._mutationObserver([{target: aEvent.target, type: "childList"}]);
|
||||
}.bind(this), true);
|
||||
|
||||
}
|
||||
|
||||
this._containers.set(aNode, container);
|
||||
// FIXME: set an expando to prevent the the wrapper from disappearing
|
||||
// See bug 819131 for details.
|
||||
aNode.__preserveHack = true;
|
||||
container.expanded = aExpand;
|
||||
|
||||
container.childrenDirty = true;
|
||||
this._updateChildren(container);
|
||||
|
||||
if (parent) {
|
||||
@ -327,6 +337,7 @@ MarkupView.prototype = {
|
||||
if (mutation.type === "attributes" || mutation.type === "characterData") {
|
||||
container.update();
|
||||
} else if (mutation.type === "childList") {
|
||||
container.childrenDirty = true;
|
||||
this._updateChildren(container);
|
||||
}
|
||||
}
|
||||
@ -339,10 +350,12 @@ MarkupView.prototype = {
|
||||
*/
|
||||
showNode: function MT_showNode(aNode, centered)
|
||||
{
|
||||
this.importNode(aNode);
|
||||
let container = this.importNode(aNode);
|
||||
this._updateChildren(container);
|
||||
let walker = documentWalker(aNode);
|
||||
let parent;
|
||||
while (parent = walker.parentNode()) {
|
||||
this._updateChildren(this.getContainer(parent));
|
||||
this.expandNode(parent);
|
||||
}
|
||||
LayoutHelpers.scrollIntoViewIfNeeded(this._containers.get(aNode).editor.elt, centered);
|
||||
@ -421,9 +434,32 @@ MarkupView.prototype = {
|
||||
this._selectedContainer.selected = true;
|
||||
}
|
||||
|
||||
this._ensureSelectionVisible();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Make sure that every ancestor of the selection are updated
|
||||
* and included in the list of visible children.
|
||||
*/
|
||||
_ensureSelectionVisible: function MT_ensureSelectionVisible()
|
||||
{
|
||||
let node = this._selectedContainer.node;
|
||||
let walker = documentWalker(node);
|
||||
while (node) {
|
||||
let container = this._containers.get(node);
|
||||
let parent = walker.parentNode();
|
||||
if (!container.elt.parentNode) {
|
||||
let parentContainer = this._containers.get(parent);
|
||||
parentContainer.childrenDirty = true;
|
||||
this._updateChildren(parentContainer, node);
|
||||
}
|
||||
|
||||
node = parent;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unmark selected node (no node selected).
|
||||
*/
|
||||
@ -448,29 +484,139 @@ MarkupView.prototype = {
|
||||
/**
|
||||
* Make sure all children of the given container's node are
|
||||
* imported and attached to the container in the right order.
|
||||
* @param aCentered If provided, this child will be included
|
||||
* in the visible subset, and will be roughly centered
|
||||
* in that list.
|
||||
*/
|
||||
_updateChildren: function MT__updateChildren(aContainer)
|
||||
_updateChildren: function MT__updateChildren(aContainer, aCentered)
|
||||
{
|
||||
if (!aContainer.childrenDirty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a tree walker pointing at the first child of the node.
|
||||
let treeWalker = documentWalker(aContainer.node);
|
||||
let child = treeWalker.firstChild();
|
||||
aContainer.hasChildren = !!child;
|
||||
if (aContainer.expanded) {
|
||||
let lastContainer = null;
|
||||
while (child) {
|
||||
let container = this.importNode(child, false);
|
||||
|
||||
// Make sure children are in the right order.
|
||||
let before = lastContainer ? lastContainer.nextSibling : aContainer.children.firstChild;
|
||||
aContainer.children.insertBefore(container.elt, before);
|
||||
lastContainer = container.elt;
|
||||
child = treeWalker.nextSibling();
|
||||
if (!aContainer.expanded) {
|
||||
return;
|
||||
}
|
||||
|
||||
aContainer.childrenDirty = false;
|
||||
|
||||
let children = this._getVisibleChildren(aContainer, aCentered);
|
||||
let fragment = this.doc.createDocumentFragment();
|
||||
|
||||
for (child of children.children) {
|
||||
let container = this.importNode(child, false);
|
||||
fragment.appendChild(container.elt);
|
||||
}
|
||||
|
||||
while (aContainer.children.firstChild) {
|
||||
aContainer.children.removeChild(aContainer.children.firstChild);
|
||||
}
|
||||
|
||||
if (!(children.hasFirst && children.hasLast)) {
|
||||
let data = {
|
||||
showing: this.strings.GetStringFromName("markupView.more.showing"),
|
||||
showAll: this.strings.formatStringFromName(
|
||||
"markupView.more.showAll",
|
||||
[aContainer.node.children.length.toString()], 1),
|
||||
allButtonClick: function() {
|
||||
aContainer.maxChildren = -1;
|
||||
aContainer.childrenDirty = true;
|
||||
this._updateChildren(aContainer);
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
if (!children.hasFirst) {
|
||||
let span = this.template("more-nodes", data);
|
||||
fragment.insertBefore(span, fragment.firstChild);
|
||||
}
|
||||
|
||||
while (aContainer.children.lastChild != lastContainer) {
|
||||
aContainer.children.removeChild(aContainer.children.lastChild);
|
||||
if (!children.hasLast) {
|
||||
let span = this.template("more-nodes", data);
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
aContainer.children.appendChild(fragment);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a list of the children to display for this container.
|
||||
*/
|
||||
_getVisibleChildren: function MV__getVisibleChildren(aContainer, aCentered)
|
||||
{
|
||||
let maxChildren = aContainer.maxChildren || this.maxChildren;
|
||||
if (maxChildren == -1) {
|
||||
maxChildren = Number.MAX_VALUE;
|
||||
}
|
||||
let firstChild = documentWalker(aContainer.node).firstChild();
|
||||
let lastChild = documentWalker(aContainer.node).lastChild();
|
||||
|
||||
if (!firstChild) {
|
||||
// No children, we're done.
|
||||
return { hasFirst: true, hasLast: true, children: [] };
|
||||
}
|
||||
|
||||
// By default try to put the selected child in the middle of the list.
|
||||
let start = aCentered || firstChild;
|
||||
|
||||
// Start by reading backward from the starting point....
|
||||
let nodes = [];
|
||||
let backwardWalker = documentWalker(start);
|
||||
if (backwardWalker.previousSibling()) {
|
||||
let backwardCount = Math.floor(maxChildren / 2);
|
||||
let backwardNodes = this._readBackward(backwardWalker, backwardCount);
|
||||
nodes = backwardNodes;
|
||||
}
|
||||
|
||||
// Then read forward by any slack left in the max children...
|
||||
let forwardWalker = documentWalker(start);
|
||||
let forwardCount = maxChildren - nodes.length;
|
||||
nodes = nodes.concat(this._readForward(forwardWalker, forwardCount));
|
||||
|
||||
// If there's any room left, it means we've run all the way to the end.
|
||||
// In that case, there might still be more items at the front.
|
||||
let remaining = maxChildren - nodes.length;
|
||||
if (remaining > 0 && nodes[0] != firstChild) {
|
||||
let firstNodes = this._readBackward(backwardWalker, remaining);
|
||||
|
||||
// Then put it all back together.
|
||||
nodes = firstNodes.concat(nodes);
|
||||
}
|
||||
|
||||
return {
|
||||
hasFirst: nodes[0] == firstChild,
|
||||
hasLast: nodes[nodes.length - 1] == lastChild,
|
||||
children: nodes
|
||||
};
|
||||
},
|
||||
|
||||
_readForward: function MV__readForward(aWalker, aCount)
|
||||
{
|
||||
let ret = [];
|
||||
let node = aWalker.currentNode;
|
||||
do {
|
||||
ret.push(node);
|
||||
node = aWalker.nextSibling();
|
||||
} while (node && --aCount);
|
||||
return ret;
|
||||
},
|
||||
|
||||
_readBackward: function MV__readBackward(aWalker, aCount)
|
||||
{
|
||||
let ret = [];
|
||||
let node = aWalker.currentNode;
|
||||
do {
|
||||
ret.push(node);
|
||||
node = aWalker.previousSibling();
|
||||
} while(node && --aCount);
|
||||
ret.reverse();
|
||||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -618,9 +764,7 @@ function MarkupContainer(aMarkupView, aNode)
|
||||
this.expander = null;
|
||||
this.codeBox = null;
|
||||
this.children = null;
|
||||
let options = { stack: "markup-view.xhtml" };
|
||||
this.markup.template("container", this, options);
|
||||
|
||||
this.markup.template("container", this);
|
||||
this.elt.container = this;
|
||||
|
||||
this.expander.addEventListener("click", function() {
|
||||
@ -734,7 +878,7 @@ MarkupContainer.prototype = {
|
||||
if (focusable) {
|
||||
focusable.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
@ -841,13 +985,12 @@ function ElementEditor(aContainer, aNode)
|
||||
this.attrList = null;
|
||||
this.newAttr = null;
|
||||
this.closeElt = null;
|
||||
let options = { stack: "markup-view.xhtml" };
|
||||
|
||||
// Create the main editor
|
||||
this.template("element", this, options);
|
||||
this.template("element", this);
|
||||
|
||||
// Create the closing tag
|
||||
this.template("elementClose", this, options);
|
||||
this.template("elementClose", this);
|
||||
|
||||
// Make the tag name editable (unless this is a document element)
|
||||
if (aNode != aNode.ownerDocument.documentElement) {
|
||||
@ -927,8 +1070,7 @@ ElementEditor.prototype = {
|
||||
let data = {
|
||||
attrName: aAttr.name,
|
||||
};
|
||||
let options = { stack: "markup-view.xhtml" };
|
||||
this.template("attribute", data, options);
|
||||
this.template("attribute", data);
|
||||
var {attr, inner, name, val} = data;
|
||||
|
||||
// Figure out where we should place the attribute.
|
||||
@ -1260,3 +1402,8 @@ function whitespaceTextFilter(aNode)
|
||||
return Ci.nsIDOMNodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(MarkupView.prototype, "strings", function () {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/inspector.properties");
|
||||
});
|
||||
|
@ -16,6 +16,8 @@
|
||||
<div id="templates" style="display:none">
|
||||
<ul>
|
||||
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
|
||||
|
||||
<li id="template-more-nodes" class="more-nodes devtools-class-comment" save="${elt}"><span>${showing}</span> <button href="#" onclick="${allButtonClick}">${showAll}</button></li>
|
||||
</ul>
|
||||
|
||||
<span id="template-element" save="${elt}" class="editor"><span><</span><span save="${tag}" class="tagname devtools-theme-tagname"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>></span>
|
||||
|
@ -17,7 +17,9 @@ _BROWSER_FILES = \
|
||||
browser_inspector_markup_mutation.html \
|
||||
browser_inspector_markup_mutation.js \
|
||||
browser_inspector_markup_edit.html \
|
||||
browser_inspector_markup_edit.js \
|
||||
browser_inspector_markup_edit.js \
|
||||
browser_inspector_markup_subset.html \
|
||||
browser_inspector_markup_subset.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="html">
|
||||
<body class="body">
|
||||
<div id="a"></div>
|
||||
<div id="b"></div>
|
||||
<div id="c"></div>
|
||||
<div id="d"></div>
|
||||
<div id="e"></div>
|
||||
<div id="f"></div>
|
||||
<div id="g"></div>
|
||||
<div id="h"></div>
|
||||
<div id="i"></div>
|
||||
<div id="j"></div>
|
||||
<div id="k"></div>
|
||||
<div id="l"></div>
|
||||
<div id="m"></div>
|
||||
<div id="n"></div>
|
||||
<div id="o"></div>
|
||||
<div id="p"></div>
|
||||
<div id="q"></div>
|
||||
<div id="r"></div>
|
||||
<div id="s"></div>
|
||||
<div id="t"></div>
|
||||
<div id="u"></div>
|
||||
<div id="v"></div>
|
||||
<div id="w"></div>
|
||||
<div id="x"></div>
|
||||
<div id="y"></div>
|
||||
<div id="z"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,146 @@
|
||||
/* Any copyright", " is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the markup view loads only as many nodes as specified
|
||||
* by the devtools.markup.pagesize preference.
|
||||
*/
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("devtools.markup.pagesize");
|
||||
});
|
||||
Services.prefs.setIntPref("devtools.markup.pagesize", 5);
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Will hold the doc we're viewing
|
||||
let doc;
|
||||
|
||||
let inspector;
|
||||
|
||||
// Holds the MarkupTool object we're testing.
|
||||
let markup;
|
||||
|
||||
function assertChildren(expected)
|
||||
{
|
||||
let container = markup.getContainer(doc.querySelector("body"));
|
||||
let found = [];
|
||||
for (let child of container.children.children) {
|
||||
if (child.classList.contains("more-nodes")) {
|
||||
found += "*more*";
|
||||
} else {
|
||||
found += child.container.node.getAttribute("id");
|
||||
}
|
||||
}
|
||||
is(expected, found, "Got the expected children.");
|
||||
}
|
||||
|
||||
function forceReload()
|
||||
{
|
||||
let container = markup.getContainer(doc.querySelector("body"));
|
||||
container.childrenDirty = true;
|
||||
}
|
||||
|
||||
let selections = [
|
||||
{
|
||||
desc: "Select the first item",
|
||||
selector: "#a",
|
||||
before: function() {
|
||||
},
|
||||
after: function() {
|
||||
assertChildren("abcde*more*");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Select the last item",
|
||||
selector: "#z",
|
||||
before: function() {},
|
||||
after: function() {
|
||||
assertChildren("*more*vwxyz");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Select an already-visible item",
|
||||
selector: "#v",
|
||||
before: function() {},
|
||||
after: function() {
|
||||
// Because "v" was already visible, we shouldn't have loaded
|
||||
// a different page.
|
||||
assertChildren("*more*vwxyz");
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Verify childrenDirty reloads the page",
|
||||
selector: "#w",
|
||||
before: function() {
|
||||
forceReload();
|
||||
},
|
||||
after: function() {
|
||||
// But now that we don't already have a loaded page, selecting
|
||||
// w should center around w.
|
||||
assertChildren("*more*uvwxy*more*");
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// Create the helper tab for parsing...
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
doc = content.document;
|
||||
waitForFocus(setupTest, content);
|
||||
}, true);
|
||||
content.location = "http://mochi.test:8888/browser/browser/devtools/markupview/test/browser_inspector_markup_subset.html";
|
||||
|
||||
function setupTest() {
|
||||
var target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
toolbox.once("inspector-selected", function SE_selected(id, aInspector) {
|
||||
inspector = aInspector;
|
||||
markup = inspector.markup;
|
||||
runNextSelection();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
inspector.selection.once("new-node", startTests);
|
||||
executeSoon(function() {
|
||||
inspector.selection.setNode(doc.body);
|
||||
});
|
||||
}
|
||||
|
||||
function runNextSelection() {
|
||||
let selection = selections.shift();
|
||||
if (!selection) {
|
||||
clickMore();
|
||||
return;
|
||||
}
|
||||
|
||||
info(selection.desc);
|
||||
selection.before();
|
||||
inspector.selection.once("new-node", function() {
|
||||
selection.after();
|
||||
runNextSelection();
|
||||
});
|
||||
inspector.selection.setNode(doc.querySelector(selection.selector));
|
||||
}
|
||||
|
||||
function clickMore() {
|
||||
info("Check that clicking more loads the whole thing.");
|
||||
// Make sure that clicking the "more" button loads all the nodes.
|
||||
let container = markup.getContainer(doc.querySelector("body"));
|
||||
let button = container.elt.querySelector("button");
|
||||
button.click();
|
||||
assertChildren("abcdefghijklmnopqrstuvwxyz");
|
||||
finishUp();
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
doc = inspector = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
@ -158,9 +158,6 @@ function ResponsiveUI(aWindow, aTab)
|
||||
this.buildUI();
|
||||
this.checkMenus();
|
||||
|
||||
let target = TargetFactory.forTab(this.tab);
|
||||
this.toolboxWasOpen = !!gDevTools.getToolbox(target);
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
|
||||
this.rotate();
|
||||
@ -239,17 +236,9 @@ ResponsiveUI.prototype = {
|
||||
if (aEvent.keyCode == this.mainWindow.KeyEvent.DOM_VK_ESCAPE &&
|
||||
this.mainWindow.gBrowser.selectedBrowser == this.browser) {
|
||||
|
||||
// If the toolbox wasn't open at first but is open now,
|
||||
// we don't want to close the Responsive Mode on Escape.
|
||||
// We let the toolbox close first.
|
||||
|
||||
let target = TargetFactory.forTab(this.tab);
|
||||
let isToolboxOpen = !!gDevTools.getToolbox(target);
|
||||
if (this.toolboxWasOpen || !isToolboxOpen) {
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
this.close();
|
||||
}
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,11 +69,29 @@ this.ScratchpadManager = {
|
||||
saveOpenWindows: function SPM_saveOpenWindows() {
|
||||
this._scratchpads = [];
|
||||
|
||||
function clone(src) {
|
||||
let dest = {};
|
||||
|
||||
for (let key in src) {
|
||||
if (src.hasOwnProperty(key)) {
|
||||
dest[key] = src[key];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
// We need to clone objects we get from Scratchpad instances
|
||||
// because such (cross-window) objects have a property 'parent'
|
||||
// that holds on to a ChromeWindow instance. This means that
|
||||
// such objects are not primitive-values-only anymore so they
|
||||
// can leak.
|
||||
|
||||
let enumerator = Services.wm.getEnumerator("devtools:scratchpad");
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let win = enumerator.getNext();
|
||||
if (!win.closed && win.Scratchpad.initialized) {
|
||||
this._scratchpads.push(win.Scratchpad.getState());
|
||||
this._scratchpads.push(clone(win.Scratchpad.getState()));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -106,6 +124,7 @@ this.ScratchpadManager = {
|
||||
|
||||
let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
|
||||
SCRATCHPAD_WINDOW_FEATURES, params);
|
||||
|
||||
// Only add the shutdown observer if we've opened a scratchpad window.
|
||||
ShutdownObserver.init();
|
||||
|
||||
@ -128,6 +147,7 @@ var ShutdownObserver = {
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "quit-application-granted", false);
|
||||
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
@ -143,4 +163,4 @@ var ShutdownObserver = {
|
||||
{
|
||||
Services.obs.removeObserver(this, "quit-application-granted");
|
||||
}
|
||||
};
|
||||
};
|
@ -133,6 +133,7 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
|
||||
this.getRTLAttr = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr";
|
||||
|
||||
// Create bound methods.
|
||||
this.siFocusWindow = this.focusWindow.bind(this);
|
||||
this.siBoundMenuUpdate = this.computedViewMenuUpdate.bind(this);
|
||||
this.siBoundCopy = this.computedViewCopy.bind(this);
|
||||
this.siBoundCopyDeclaration = this.computedViewCopyDeclaration.bind(this);
|
||||
@ -140,6 +141,7 @@ this.CssHtmlTree = function CssHtmlTree(aStyleInspector)
|
||||
this.siBoundCopyPropertyValue = this.computedViewCopyPropertyValue.bind(this);
|
||||
|
||||
this.styleDocument.addEventListener("copy", this.siBoundCopy);
|
||||
this.styleDocument.addEventListener("mousedown", this.siFocusWindow);
|
||||
|
||||
// Nodes used in templating
|
||||
this.root = this.styleDocument.getElementById("root");
|
||||
@ -557,6 +559,17 @@ CssHtmlTree.prototype = {
|
||||
menuitem.disabled = disablePropertyItems;
|
||||
},
|
||||
|
||||
/**
|
||||
* Focus the window on mousedown.
|
||||
*
|
||||
* @param aEvent The event object
|
||||
*/
|
||||
focusWindow: function si_focusWindow(aEvent)
|
||||
{
|
||||
let win = this.styleDocument.defaultView;
|
||||
win.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy selected text.
|
||||
*
|
||||
@ -704,6 +717,7 @@ CssHtmlTree.prototype = {
|
||||
|
||||
// Remove bound listeners
|
||||
this.styleDocument.removeEventListener("copy", this.siBoundCopy);
|
||||
this.styleDocument.removeEventListener("mousedown", this.siFocusWindow);
|
||||
|
||||
// Nodes used in templating
|
||||
delete this.root;
|
||||
|
@ -1402,6 +1402,8 @@ RuleEditor.prototype = {
|
||||
}.bind(this), false);
|
||||
|
||||
this.element.addEventListener("mousedown", function() {
|
||||
this.doc.defaultView.focus();
|
||||
|
||||
let editorNodes =
|
||||
this.doc.querySelectorAll(".styleinspector-propertyeditor");
|
||||
|
||||
|
@ -181,7 +181,6 @@ TiltVisualizer.prototype = {
|
||||
if (panel) {
|
||||
this.inspector = panel;
|
||||
this.inspector.selection.on("new-node", this.onNewNodeFromInspector);
|
||||
this.inspector.selection.on("detached", this.onNewNodeFromInspector);
|
||||
this.onNewNodeFromInspector();
|
||||
}
|
||||
}
|
||||
@ -196,7 +195,6 @@ TiltVisualizer.prototype = {
|
||||
|
||||
if (this.inspector) {
|
||||
this.inspector.selection.off("new-node", this.onNewNodeFromInspector);
|
||||
this.inspector.selection.off("detached", this.onNewNodeFromInspector);
|
||||
this.inspector = null;
|
||||
}
|
||||
|
||||
@ -217,7 +215,6 @@ TiltVisualizer.prototype = {
|
||||
if (toolbox.target.tab === this._browserTab) {
|
||||
this.inspector = panel;
|
||||
this.inspector.selection.on("new-node", this.onNewNodeFromInspector);
|
||||
this.inspector.selection.on("detached", this.onNewNodeFromInspector);
|
||||
this.onNewNodeFromTilt();
|
||||
}
|
||||
},
|
||||
@ -231,7 +228,6 @@ TiltVisualizer.prototype = {
|
||||
this.inspector) {
|
||||
if (this.inspector.selection) {
|
||||
this.inspector.selection.off("new-node", this.onNewNodeFromInspector);
|
||||
this.inspector.selection.off("detached", this.onNewNodeFromInspector);
|
||||
}
|
||||
this.inspector = null;
|
||||
}
|
||||
|
@ -2,14 +2,21 @@
|
||||
- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE This file contains the Remove Connection strings.
|
||||
- The Remote Connection window can be start by running the command:
|
||||
- `devtools connect`
|
||||
<!-- LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
|
||||
- The Remote Connection window can reached from the "connect…" menuitem
|
||||
- in the Web Developer menu.
|
||||
- -->
|
||||
|
||||
<!ENTITY title "Connect">
|
||||
<!ENTITY header "Connect to remote device">
|
||||
<!ENTITY host "Host:">
|
||||
<!ENTITY port "Port:">
|
||||
<!ENTITY connect "Connect">
|
||||
<!ENTITY connecting "Connecting…">
|
||||
<!ENTITY availability "Available remote objects:">
|
||||
<!ENTITY remoteProcess "remote process">
|
||||
<!ENTITY connectionError "Error:">
|
||||
<!ENTITY errorTimeout "Error: connection timeout.">
|
||||
<!ENTITY errorRefused "Error: connection refused.">
|
||||
<!ENTITY errorUnexpected "Unexpected error.">
|
||||
<!ENTITY help "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS for example). Make sure that you have turned on the 'Debugger Server' option on the remote device. See <a target='_' href='https://developer.mozilla.org/en-US/docs/Tools/Debugger#Remote_Debugging'>documentation</a>.">
|
||||
|
@ -0,0 +1,9 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE : FILE This file contains the Remote Connection strings.
|
||||
# The Remote Connection window can reached from the "connect…" menuitem
|
||||
# in the Web Developer menu.
|
||||
|
||||
remoteProcess=Remote Process
|
@ -186,6 +186,11 @@ globalScopeLabel=Global
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
ToolboxDebugger.label=Debugger
|
||||
|
||||
# LOCALIZATION NOTE (ToolboxDebugger.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the debugger is
|
||||
# displayed inside the developer tools window..
|
||||
ToolboxDebugger.tooltip=JavaScript Debugger
|
||||
|
||||
# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed
|
||||
# in the variables list on an item with an editable name.
|
||||
variablesEditableNameTooltip=Double click to edit
|
||||
|
@ -33,3 +33,10 @@ nodeMenu.tooltiptext=Node operations
|
||||
inspector.label=Inspector
|
||||
inspector.commandkey=I
|
||||
inspector.accesskey=I
|
||||
|
||||
# LOCALIZATION NOTE (markupView.more.*)
|
||||
# When there are too many nodes to load at once, we will offer to
|
||||
# show all the nodes.
|
||||
markupView.more.showing=Some nodes were hidden.
|
||||
markupView.more.showAll=Show All %S Nodes
|
||||
inspector.tooltip=DOM and Style Inspector
|
||||
|
@ -13,4 +13,9 @@
|
||||
# LOCALIZATION NOTE (profiler.label):
|
||||
# This string is displayed in the title of the tab when the profiler is
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
profiler.label=Profiler
|
||||
profiler.label=Profiler
|
||||
|
||||
# LOCALIZATION NOTE (profiler.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the profiler is
|
||||
# displayed inside the developer tools window.
|
||||
profiler.tooltip=Profiler
|
||||
|
@ -78,3 +78,8 @@ redo.commandkey=Z
|
||||
# This string is displayed in the title of the tab when the debugger is
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
ToolboxStyleEditor.label=Style Editor
|
||||
|
||||
# LOCALIZATION NOTE (ToolboxStyleEditor.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the debugger is
|
||||
# displayed inside the developer tools window.
|
||||
ToolboxStyleEditor.tooltip=CSS Stylesheets Editor
|
||||
|
@ -5,3 +5,5 @@
|
||||
<!ENTITY window.title "Developer Tools">
|
||||
|
||||
<!ENTITY closeCmd.key "W">
|
||||
|
||||
<!ENTITY toolboxCloseButton.tooltip "Close Developer Tools">
|
@ -0,0 +1,3 @@
|
||||
toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window
|
||||
toolboxDockButtons.side.tooltip=Dock to side of browser window
|
||||
toolboxDockButtons.window.tooltip=Show in separate window
|
@ -174,6 +174,11 @@ listTabs.globalConsoleActor=*Global Console*
|
||||
# as webConsoleWindowTitleAndURL before the '-'
|
||||
ToolboxWebconsole.label=Web Console
|
||||
|
||||
# LOCALIZATION NOTE (ToolboxWebconsole.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the web console is
|
||||
# displayed inside the developer tools window.
|
||||
ToolboxWebconsole.tooltip=Web Console
|
||||
|
||||
# LOCALIZATION NOTE (longStringEllipsis): The string displayed after a long
|
||||
# string. This string is clickable such that the rest of the string is retrieved
|
||||
# from the server.
|
||||
|
@ -41,6 +41,7 @@
|
||||
locale/browser/devtools/toolbox.dtd (%chrome/browser/devtools/toolbox.dtd)
|
||||
locale/browser/devtools/inspector.dtd (%chrome/browser/devtools/inspector.dtd)
|
||||
locale/browser/devtools/connection-screen.dtd (%chrome/browser/devtools/connection-screen.dtd)
|
||||
locale/browser/devtools/connection-screen.properties (%chrome/browser/devtools/connection-screen.properties)
|
||||
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
|
||||
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
|
||||
locale/browser/openLocation.dtd (%chrome/browser/openLocation.dtd)
|
||||
|
@ -128,27 +128,33 @@
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
/* Search input */
|
||||
/* Text input */
|
||||
|
||||
.devtools-textinput,
|
||||
.devtools-searchinput {
|
||||
-moz-appearance: none;
|
||||
margin: 0 3px;
|
||||
border: 1px solid hsla(210,8%,5%,.6);
|
||||
border-radius: 2px;
|
||||
background-color: transparent;
|
||||
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4px center, top left, top left;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
-moz-padding-start: 18px;
|
||||
-moz-padding-end: 12px;
|
||||
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
padding: 3px;
|
||||
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
|
||||
0 0 0 1px hsla(210,16%,76%,.1) inset,
|
||||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-searchinput {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
-moz-padding-start: 18px;
|
||||
-moz-padding-end: 12px;
|
||||
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
background-position: 4px center, top left, top left;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.devtools-searchinput:-moz-locale-dir(rtl) {
|
||||
background-position: calc(100% - 4px) center, top left, top left;
|
||||
}
|
||||
|
@ -49,6 +49,10 @@ li.container {
|
||||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
.more-nodes {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
@ -134,14 +134,24 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Search input */
|
||||
/* Text input */
|
||||
|
||||
.devtools-textinput,
|
||||
.devtools-searchinput {
|
||||
-moz-appearance: none;
|
||||
margin: 0 3px;
|
||||
background-color: transparent;
|
||||
border: 1px solid hsla(210,8%,5%,.6);
|
||||
border-radius: 20px;
|
||||
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
padding: 3px;
|
||||
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
|
||||
0 0 0 1px hsla(210,16%,76%,.1) inset,
|
||||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-searchinput {
|
||||
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4px center, top left, top left;
|
||||
@ -149,10 +159,6 @@
|
||||
padding-bottom: 0;
|
||||
-moz-padding-start: 18px;
|
||||
-moz-padding-end: 12px;
|
||||
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
|
||||
0 0 0 1px hsla(210,16%,76%,.1) inset,
|
||||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-searchinput:-moz-locale-dir(rtl) {
|
||||
|
@ -52,6 +52,10 @@ li.container {
|
||||
-moz-appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
.more-nodes {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
@ -132,8 +132,9 @@
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
/* Search input */
|
||||
/* Text input */
|
||||
|
||||
.devtools-textinput,
|
||||
.devtools-searchinput {
|
||||
-moz-appearance: none;
|
||||
margin: 0 3px;
|
||||
@ -141,6 +142,15 @@
|
||||
box-shadow: inset 0 1px 0 hsla(211,68%,6%,.05), 0 0 0 1px hsla(210,40%,83%,.1);
|
||||
border-radius: 2px;
|
||||
background-color: transparent;
|
||||
background-image: -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
padding: 3px;
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-searchinput {
|
||||
background-image: url(magnifying-glass.png), -moz-linear-gradient(hsla(210,16%,76%,.15), hsla(210,16%,76%,.35));
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4px center, top left, top left;
|
||||
@ -148,10 +158,6 @@
|
||||
padding-bottom: 0;
|
||||
-moz-padding-start: 18px;
|
||||
-moz-padding-end: 12px;
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-searchinput[focused] {
|
||||
|
@ -54,6 +54,10 @@ li.container {
|
||||
background-image: url("chrome://global/skin/tree/twisty-open.png");
|
||||
}
|
||||
|
||||
.more-nodes {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.styleinspector-propertyeditor {
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user