Merge mozilla-central and mozilla-inbound

This commit is contained in:
Ed Morley 2011-10-28 02:11:57 +01:00
commit 6c08afb7da
135 changed files with 2341 additions and 770 deletions

View File

@ -6705,14 +6705,6 @@ var gPluginHandler = {
return this.CrashSubmit;
},
get crashReportHelpURL() {
delete this.crashReportHelpURL;
let url = formatURL("app.support.baseURL", true);
url += "plugin-crashed";
this.crashReportHelpURL = url;
return this.crashReportHelpURL;
},
// Map the plugin's name to a filtered version more suitable for user UI.
makeNicePluginName : function (aName, aFilename) {
if (aName == "Shockwave Flash")
@ -6851,10 +6843,25 @@ var gPluginHandler = {
BrowserOpenAddonsMgr("addons://list/plugin");
},
// Callback for user clicking "submit a report" link
submitReport : function(pluginDumpID, browserDumpID) {
// The crash reporter wants a DOM element it can append an IFRAME to,
// which it uses to submit a form. Let's just give it gBrowser.
// When user clicks try, checks if we should also send crash report in bg
retryPluginPage: function (browser, plugin, pluginDumpID, browserDumpID) {
let doc = plugin.ownerDocument;
let statusDiv =
doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
let status = statusDiv.getAttribute("status");
let submitChk =
doc.getAnonymousElementByAttribute(plugin, "class", "pleaseSubmitCheckbox");
// Check status to make sure we haven't submitted already
if (status == "please" && submitChk.checked) {
this.submitReport(pluginDumpID, browserDumpID);
}
this.reloadPage(browser);
},
submitReport: function (pluginDumpID, browserDumpID) {
this.CrashSubmit.submit(pluginDumpID);
if (browserDumpID)
this.CrashSubmit.submit(browserDumpID);
@ -7072,8 +7079,7 @@ var gPluginHandler = {
return;
let submittedReport = aEvent.getData("submittedCrashReport");
let doPrompt = true; // XXX followup for .getData("doPrompt");
let submitReports = true; // XXX followup for .getData("submitReports");
let doPrompt = true; // XXX followup to get via gCrashReporter
let pluginName = aEvent.getData("pluginName");
let pluginFilename = aEvent.getData("pluginFilename");
let pluginDumpID = aEvent.getData("pluginDumpID");
@ -7091,6 +7097,7 @@ var gPluginHandler = {
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
#ifdef MOZ_CRASHREPORTER
let submitReports = gCrashReporter.submitReports;
let status;
// Determine which message to show regarding crash reports.
@ -7101,18 +7108,21 @@ var gPluginHandler = {
status = "noSubmit";
}
else { // doPrompt
// link submit checkbox to gCrashReporter submitReports preference
let submitChk = doc.getAnonymousElementByAttribute(
plugin, "class", "pleaseSubmitCheckbox");
submitChk.checked = submitReports;
submitChk.addEventListener("click", function() {
gCrashReporter.submitReports = this.checked;
}, false);
status = "please";
// XXX can we make the link target actually be blank?
let pleaseLink = doc.getAnonymousElementByAttribute(
plugin, "class", "pleaseSubmitLink");
this.addLinkClickCallback(pleaseLink, "submitReport",
pluginDumpID, browserDumpID);
}
// If we don't have a minidumpID, we can't (or didn't) submit anything.
// This can happen if the plugin is killed from the task manager.
if (!pluginDumpID) {
status = "noReport";
status = "noReport";
}
statusDiv.setAttribute("status", status);
@ -7122,10 +7132,23 @@ var gPluginHandler = {
let helpIcon = doc.getAnonymousElementByAttribute(plugin, "class", "helpIcon");
this.addLinkClickCallback(helpIcon, "openHelpPage");
// If we're showing the link to manually trigger report submission, we'll
// want to be able to update all the instances of the UI for this crash to
// show an updated message when a report is submitted.
// If we're showing the checkbox to trigger report submission, we'll want
// to be able to update all the instances of the UI for this crash when
// one instance of the checkbox is modified or the status is updated.
if (doPrompt) {
let submitReportsPrefObserver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
observe : function(subject, topic, data) {
let submitChk = doc.getAnonymousElementByAttribute(
plugin, "class", "pleaseSubmitCheckbox");
submitChk.checked = gCrashReporter.submitReports;
},
handleEvent : function(event) {
// Not expected to be called, just here for the closure.
}
};
let observer = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
@ -7142,16 +7165,21 @@ var gPluginHandler = {
handleEvent : function(event) {
// Not expected to be called, just here for the closure.
}
}
};
// Use a weak reference, so we don't have to remove it...
Services.obs.addObserver(observer, "crash-report-status", true);
Services.obs.addObserver(
submitReportsPrefObserver, "submit-reports-pref-changed", true);
// ...alas, now we need something to hold a strong reference to prevent
// it from being GC. But I don't want to manually manage the reference's
// lifetime (which should be no greater than the page).
// Clever solution? Use a closue with an event listener on the document.
// Clever solution? Use a closure with an event listener on the document.
// When the doc goes away, so do the listener references and the closure.
doc.addEventListener("mozCleverClosureHack", observer, false);
doc.addEventListener(
"mozCleverClosureHack", submitReportsPrefObserver, false);
}
#endif
@ -7161,7 +7189,12 @@ var gPluginHandler = {
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink");
#ifdef MOZ_CRASHREPORTER
this.addLinkClickCallback(
link, "retryPluginPage", browser, plugin, pluginDumpID, browserDumpID);
#else
this.addLinkClickCallback(link, "reloadPage", browser);
#endif
let notificationBox = gBrowser.getNotificationBox(browser);
@ -7227,7 +7260,10 @@ var gPluginHandler = {
let link = notification.ownerDocument.createElementNS(XULNS, "label");
link.className = "text-link";
link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
link.href = gPluginHandler.crashReportHelpURL;
let crashurl = formatURL("app.support.baseURL", true);
crashurl += "plugin-crashed-notificationbar";
link.href = crashurl;
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
description.appendChild(link);

View File

@ -973,14 +973,28 @@
<toolbar id="inspector-toolbar"
nowindowdrag="true"
hidden="true">
<toolbarbutton id="inspector-inspect-toolbutton"
label="&inspectButton.label;"
accesskey="&inspectButton.accesskey;"
command="Inspector:Inspect"/>
<toolbarseparator />
<hbox id="inspector-tools">
<!-- registered tools go here -->
</hbox>
<vbox flex="1">
<resizer id="inspector-top-resizer" flex="1"
class="inspector-resizer"
dir="top" disabled="true"
element="inspector-tree-box"/>
<hbox>
<toolbarbutton id="inspector-inspect-toolbutton"
label="&inspectButton.label;"
accesskey="&inspectButton.accesskey;"
command="Inspector:Inspect"/>
<arrowscrollbox id="inspector-breadcrumbs"
flex="1" orient="horizontal"
clicktoscroll="true"/>
<hbox id="inspector-tools">
<!-- registered tools go here -->
</hbox>
<resizer id="inspector-end-resizer"
class="inspector-resizer"
dir="top" disabled="true"
element="inspector-tree-box"/>
</hbox>
</vbox>
</toolbar>
<toolbar id="addon-bar"
toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"

View File

@ -36,6 +36,10 @@
z-index: 1;
}
.inspector-breadcrumbs-button {
direction: ltr;
}
/*
* Node Infobar
*/

View File

@ -247,6 +247,12 @@ function runTest(testNum) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
ok(true, "Starting test #" + testNum);
var inspectItems = [];
if (SpecialPowers.getBoolPref("devtools.inspector.enabled")) {
inspectItems = ["---", null,
"context-inspect", true];
}
switch (testNum) {
case 1:
// Invoke context menu for next test.
@ -268,9 +274,8 @@ function runTest(testNum) {
"context-selectall", true,
"---", null,
"context-viewsource", true,
"context-viewinfo", true,
"---", null,
"context-inspect", true]);
"context-viewinfo", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(link); // Invoke context menu for next test.
break;
@ -283,18 +288,15 @@ function runTest(testNum) {
"context-bookmarklink", true,
"context-savelink", true,
"context-sendlink", true,
"context-copylink", true,
"---", null,
"context-inspect", true]);
"context-copylink", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(mailto); // Invoke context menu for next test.
break;
case 4:
// Context menu for text mailto-link
checkContextMenu(["context-copyemail", true,
"---", null,
"context-inspect", true]);
checkContextMenu(["context-copyemail", true].concat(inspectItems));
closeContextMenu();
openContextMenuFor(input); // Invoke context menu for next test.
break;
@ -310,9 +312,8 @@ function runTest(testNum) {
"---", null,
"context-selectall", false,
"---", null,
"spell-check-enabled", true,
"---", null,
"context-inspect", true]);
"spell-check-enabled", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(img); // Invoke context menu for next test.
break;
@ -326,9 +327,8 @@ function runTest(testNum) {
"context-saveimage", true,
"context-sendimage", true,
"context-setDesktopBackground", true,
"context-viewimageinfo", true,
"---", null,
"context-inspect", true]);
"context-viewimageinfo", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(canvas); // Invoke context menu for next test.
break;
@ -338,9 +338,8 @@ function runTest(testNum) {
checkContextMenu(["context-viewimage", true,
"context-saveimage", true,
"context-bookmarkpage", true,
"context-selectall", true,
"---", null,
"context-inspect", true]);
"context-selectall", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(video_ok); // Invoke context menu for next test.
break;
@ -358,9 +357,8 @@ function runTest(testNum) {
"---", null,
"context-savevideo", true,
"context-video-saveimage", true,
"context-sendvideo", true,
"---", null,
"context-inspect", true]);
"context-sendvideo", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(video_bad); // Invoke context menu for next test.
break;
@ -378,9 +376,8 @@ function runTest(testNum) {
"---", null,
"context-savevideo", true,
"context-video-saveimage", false,
"context-sendvideo", true,
"---", null,
"context-inspect", true]);
"context-sendvideo", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(video_bad2); // Invoke context menu for next test.
break;
@ -398,9 +395,8 @@ function runTest(testNum) {
"---", null,
"context-savevideo", false,
"context-video-saveimage", false,
"context-sendvideo", false,
"---", null,
"context-inspect", true]);
"context-sendvideo", false
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(iframe); // Invoke context menu for next test.
break;
@ -434,9 +430,8 @@ function runTest(testNum) {
"context-viewframeinfo", true], null,
"---", null,
"context-viewsource", true,
"context-viewinfo", true,
"---", null,
"context-inspect", true]);
"context-viewinfo", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(textarea, false, true); // Invoke context menu for next test, but wait for the spellcheck.
break;
@ -460,8 +455,7 @@ function runTest(testNum) {
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null,
"---", null,
"context-inspect", true]);
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(contenteditable); // Invoke context menu for next test.
@ -485,9 +479,8 @@ function runTest(testNum) {
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null,
"---", null,
"context-inspect", true]);
"spell-add-dictionaries", true], null
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(inputspell); // Invoke context menu for next test.
@ -511,9 +504,8 @@ function runTest(testNum) {
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null,
"---", null,
"context-inspect", true]);
"spell-add-dictionaries", true], null
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(link); // Invoke context menu for next test.
@ -560,9 +552,8 @@ function runTest(testNum) {
"context-selectall", true,
"---", null,
"context-viewsource", true,
"context-viewinfo", true,
"---", null,
"context-inspect", true]);
"context-viewinfo", true
].concat(inspectItems));
invokeItemAction("0");
closeContextMenu();
@ -585,9 +576,8 @@ function runTest(testNum) {
"context-selectall", true,
"---", null,
"context-viewsource", true,
"context-viewinfo", true,
"---", null,
"context-inspect", true]);
"context-viewinfo", true
].concat(inspectItems));
subwindow.close();
SimpleTest.finish();

View File

@ -177,6 +177,9 @@ SessionStartup.prototype = {
Services.obs.addObserver(this, "domwindowopened", true);
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
Services.obs.addObserver(this, "browser:purge-session-history", true);
},
/**
@ -197,6 +200,8 @@ SessionStartup.prototype = {
// no reason for initializing at this point (cf. bug 409115)
Services.obs.removeObserver(this, "final-ui-startup");
Services.obs.removeObserver(this, "quit-application");
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
Services.obs.removeObserver(this, "browser:purge-session-history");
break;
case "domwindowopened":
var window = aSubject;
@ -210,6 +215,10 @@ SessionStartup.prototype = {
Services.obs.removeObserver(this, "sessionstore-windows-restored");
// free _initialState after nsSessionStore is done with it
this._initialState = null;
break;
case "browser:purge-session-history":
Services.obs.removeObserver(this, "browser:purge-session-history");
// reset all state on sanitization
this._sessionType = Ci.nsISessionStartup.NO_SESSION;
break;
}

View File

@ -2481,7 +2481,19 @@ SessionStoreService.prototype = {
if (ix != -1 && total[ix] && total[ix].sizemode == "minimized")
ix = -1;
return { windows: total, selectedWindow: ix + 1, _closedWindows: lastClosedWindowsCopy };
let session = {
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
lastUpdate: Date.now(),
startTime: this._sessionStartTime,
recentCrashes: this._recentCrashes
};
return {
windows: total,
selectedWindow: ix + 1,
_closedWindows: lastClosedWindowsCopy,
session: session
};
},
/**
@ -2565,7 +2577,7 @@ SessionStoreService.prototype = {
this._closedWindows = root._closedWindows;
var winData;
if (!root.selectedWindow) {
if (!root.selectedWindow || root.selectedWindow > root.windows.length) {
root.selectedWindow = 0;
} else {
// put the selected window at the beginning of the array to ensure that
@ -3263,31 +3275,48 @@ SessionStoreService.prototype = {
if (!node)
continue;
let eventType;
let value = aData[key];
if (typeof value == "string" && node.type != "file") {
if (node.value == value)
continue; // don't dispatch an input event for no change
node.value = value;
let event = aDocument.createEvent("UIEvents");
event.initUIEvent("input", true, true, aDocument.defaultView, 0);
node.dispatchEvent(event);
eventType = "input";
}
else if (typeof value == "boolean")
else if (typeof value == "boolean") {
if (node.checked == value)
continue; // don't dispatch a change event for no change
node.checked = value;
else if (typeof value == "number")
eventType = "change";
}
else if (typeof value == "number") {
try {
node.selectedIndex = value;
eventType = "change";
} catch (ex) { /* throws for invalid indices */ }
else if (value && value.fileList && value.type == "file" && node.type == "file")
}
else if (value && value.fileList && value.type == "file" && node.type == "file") {
node.mozSetFileNameArray(value.fileList, value.fileList.length);
eventType = "input";
}
else if (value && typeof value.indexOf == "function" && node.options) {
Array.forEach(node.options, function(aOpt, aIx) {
aOpt.selected = value.indexOf(aIx) > -1;
// Only fire the event here if this wasn't selected by default
if (!aOpt.defaultSelected)
eventType = "change";
});
}
// NB: dispatching "change" events might have unintended side-effects
// Fire events for this node if applicable
if (eventType) {
let event = aDocument.createEvent("UIEvents");
event.initUIEvent(eventType, true, true, aDocument.defaultView, 0);
node.dispatchEvent(event);
}
}
}
@ -3521,14 +3550,6 @@ SessionStoreService.prototype = {
}
}
oState.session = {
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
lastUpdate: Date.now(),
startTime: this._sessionStartTime
};
if (this._recentCrashes)
oState.session.recentCrashes = this._recentCrashes;
// Persist the last session if we deferred restoring it
if (this._lastSessionState)
oState.lastSessionState = this._lastSessionState;

View File

@ -50,6 +50,8 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
head.js \
browser_form_restore_events.js \
browser_form_restore_events_sample.html \
browser_248970_a.js \
browser_248970_b.js \
browser_248970_b_sample.html \
@ -98,8 +100,6 @@ _BROWSER_TEST_FILES = \
browser_465223.js \
browser_466937.js \
browser_466937_sample.html \
browser_476161.js \
browser_476161_sample.html \
browser_477657.js \
browser_480148.js \
browser_480893.js \
@ -152,7 +152,9 @@ _BROWSER_TEST_FILES = \
browser_645428.js \
browser_659591.js \
browser_662812.js \
browser_665702-state_session.js \
browser_682507.js \
browser_694378.js \
$(NULL)
ifneq ($(OS_ARCH),Darwin)

View File

@ -1,24 +0,0 @@
<!DOCTYPE html>
<title>Test for bug 476161</title>
<script>
document.addEventListener("input", function(aEvent) {
var inputEl = aEvent.originalTarget;
var changedEl = document.getElementById("changed");
changedEl.textContent += " " + inputEl.id;
}, false);
</script>
<h3>Text fields with changed text</h3>
<input type="text" id="modify1">
<input type="text" id="modify2" value="preset value">
<h3>Text fields with unchanged text</h3>
<input type="text" id="unchanged1">
<input type="text" id="unchanged2" value="preset value">
<h3>Changed field IDs</h3>
<div id="changed"></div>

View File

@ -0,0 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function compareArray(a, b) {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
function test() {
let currentState = JSON.parse(ss.getBrowserState());
ok(currentState.session, "session data returned by getBrowserState");
let keys = Object.keys(currentState.session);
let expectedKeys = ["state", "lastUpdate", "startTime", "recentCrashes"];
ok(compareArray(keys.sort(), expectedKeys.sort()),
"session object from getBrowserState has correct keys");
}

View File

@ -0,0 +1,35 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test Summary:
// 1. call ss.setWindowState with a broken state
// 1a. ensure that it doesn't throw.
function test() {
waitForExplicitFinish();
let brokenState = {
windows: [
{ tabs: [{ entries: [{ url: "about:mozilla" }] }] }
//{ tabs: [{ entries: [{ url: "about:robots" }] }] },
],
selectedWindow: 2
};
let brokenStateString = JSON.stringify(brokenState);
let gotError = false;
try {
ss.setWindowState(window, brokenStateString, true);
}
catch (ex) {
gotError = true;
info(ex);
}
ok(!gotError, "ss.setWindowState did not throw an error");
// Make sure that we reset the state. Use a full state just in case things get crazy.
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
waitForBrowserState(blankState, finish);
}

View File

@ -35,33 +35,64 @@
* ***** END LICENSE BLOCK ***** */
function test() {
/** Test for Bug 476161 **/
/** Originally a test for Bug 476161, but then expanded to include all input types in bug 640136 **/
waitForExplicitFinish();
let file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
let testURL = "http://mochi.test:8888/browser/" +
"browser/components/sessionstore/test/browser/browser_476161_sample.html";
"browser/components/sessionstore/test/browser/browser_form_restore_events_sample.html";
let tab = gBrowser.addTab(testURL);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab.linkedBrowser.contentDocument;
doc.getElementById("modify1").value += Math.random();
doc.getElementById("modify2").value += " " + Date.now();
// text fields
doc.getElementById("modify01").value += Math.random();
doc.getElementById("modify02").value += " " + Date.now();
// textareas
doc.getElementById("modify03").value += Math.random();
doc.getElementById("modify04").value += " " + Date.now();
// file
doc.getElementById("modify05").value = file.path;
// select
doc.getElementById("modify06").selectedIndex = 1;
var multipleChange = doc.getElementById("modify07");
Array.forEach(multipleChange.options, function(option) option.selected = true);
// checkbox
doc.getElementById("modify08").checked = true;
doc.getElementById("modify09").checked = false;
// radio
// select one then another in the same group - only last one should get event on restore
doc.getElementById("modify10").checked = true;
doc.getElementById("modify11").checked = true;
let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
let doc = tab2.linkedBrowser.contentDocument;
let changed = doc.getElementById("changed").textContent.trim().split();
is(changed.sort().join(" "), "modify1 modify2",
"input events were only dispatched for modified text fields");
let inputFired = doc.getElementById("inputFired").textContent.trim().split();
let changeFired = doc.getElementById("changeFired").textContent.trim().split();
is(inputFired.sort().join(" "), "modify01 modify02 modify03 modify04 modify05",
"input events were only dispatched for modified input, textarea fields");
is(changeFired.sort().join(" "), "modify06 unchanged06 modify07 modify08 modify09 modify11",
"change events were only dispatched for modified select, checkbox, radio fields");
// clean up
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab);
finish();
}, true);
}, true);

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<title>Test for form restore events (originally bug 476161)</title>
<script>
document.addEventListener("input", function(aEvent) {
var inputEl = aEvent.originalTarget;
var changedEl = document.getElementById("inputFired");
changedEl.textContent += " " + inputEl.id;
}, false);
document.addEventListener("change", function(aEvent) {
var inputEl = aEvent.originalTarget;
var changedEl = document.getElementById("changeFired");
changedEl.textContent += " " + inputEl.id;
}, false);
</script>
<!-- input events -->
<h3>Text fields with changed text</h3>
<input type="text" id="modify1">
<input type="text" id="modify2" value="preset value">
<input type="text" id="modify01">
<input type="text" id="modify02" value="preset value">
<h3>Text fields with unchanged text</h3>
<input type="text" id="unchanged1">
<input type="text" id="unchanged2" value="preset value">
<input type="text" id="unchanged01">
<input type="text" id="unchanged02" value="preset value">
<h3>Textarea with changed text</h3>
<textarea id="modify03"></textarea>
<textarea id="modify04">preset value</textarea>
<h3>Textarea with unchanged text</h3>
<textarea id="unchanged03"></textarea>
<textarea id="unchanged04">preset value</textarea>
<h3>file field with changed value</h3>
<input type="file" id="modify05">
<h3>file field with unchanged value</h3>
<input type="file" id="unchanged05">
<!-- change events -->
<h3>Select menu with changed selection</h3>
<select id="modify06">
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
<h3>Select menu with unchanged selection (change event still fires)</h3>
<select id="unchanged06">
<option value="one">one</option>
<option value="two" selected>two</option>
<option value="three">three</option>
</select>
<h3>Multiple Select menu with changed selection</h3>
<select id="modify07" multiple>
<option value="one">one</option>
<option value="two" selected>two</option>
<option value="three">three</option>
</select>
<h3>Select menu with unchanged selection</h3>
<select id="unchanged07" multiple>
<option value="one">one</option>
<option value="two" selected>two</option>
<option value="three" selected>three</option>
</select>
<h3>checkbox with changed value</h3>
<input type="checkbox" id="modify08">
<input type="checkbox" id="modify09" checked>
<h3>checkbox with unchanged value</h3>
<input type="checkbox" id="unchanged08">
<input type="checkbox" id="unchanged09" checked>
<h3>radio with changed value</h3>
<input type="radio" id="modify10" name="group">Radio 1</input>
<input type="radio" id="modify11" name="group">Radio 2</input>
<input type="radio" id="modify12" name="group" checked>Radio 3</input>
<h3>radio with unchanged value</h3>
<input type="radio" id="unchanged10" name="group2">Radio 4</input>
<input type="radio" id="unchanged11" name="group2">Radio 5</input>
<input type="radio" id="unchanged12" name="group2" checked>Radio 6</input>
<h3>Changed field IDs</h3>
<div id="changed"></div>
<div id="inputFired"></div>
<div id="changeFired"></div>

View File

@ -230,7 +230,14 @@ TreePanel.prototype = {
treeBox.minHeight = 10;
treeBox.flex = 1;
toolbarParent.insertBefore(treeBox, toolbar);
this.createResizer();
let resizerTop =
this.IUI.browser.ownerDocument.getElementById("inspector-top-resizer");
let resizerEnd =
this.IUI.browser.ownerDocument.getElementById("inspector-end-resizer");
resizerTop.removeAttribute("disabled");
resizerEnd.removeAttribute("disabled");
treeBox.appendChild(this.treeIFrame);
let boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
@ -251,28 +258,19 @@ TreePanel.prototype = {
}
},
/**
* Lame resizer on the toolbar.
*/
createResizer: function TP_createResizer()
{
let resizer = this.document.createElement("resizer");
resizer.id = "inspector-horizontal-splitter";
resizer.setAttribute("dir", "top");
resizer.flex = 1;
resizer.setAttribute("element", "inspector-tree-box");
resizer.height = 24;
this.IUI.toolbar.appendChild(resizer);
this.resizer = resizer;
},
/**
* Close the TreePanel.
*/
close: function TP_close()
{
if (this.openInDock) {
this.IUI.toolbar.removeChild(this.resizer);
let resizerTop =
this.IUI.browser.ownerDocument.getElementById("inspector-top-resizer");
let resizerEnd =
this.IUI.browser.ownerDocument.getElementById("inspector-end-resizer");
resizerTop.setAttribute("disabled", "true");
resizerEnd.setAttribute("disabled", "true");
let treeBox = this.container;
let treeBoxParent = treeBox.parentNode;
treeBoxParent.removeChild(treeBox);
@ -679,8 +677,6 @@ TreePanel.prototype = {
domplateUtils.setDOM(null);
delete this.resizer;
if (this.DOMHelpers) {
this.DOMHelpers.destroy();
delete this.DOMHelpers;

View File

@ -49,6 +49,7 @@ var EXPORTED_SYMBOLS = ["InspectorUI"];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/TreePanel.jsm");
const INSPECTOR_INVISIBLE_ELEMENTS = {
"head": true,
@ -874,9 +875,8 @@ InspectorUI.prototype = {
this.initTools();
if (!this.TreePanel && this.treePanelEnabled) {
Cu.import("resource:///modules/TreePanel.jsm", this);
this.treePanel = new this.TreePanel(this.chromeWin, this);
if (this.treePanelEnabled) {
this.treePanel = new TreePanel(this.chromeWin, this);
}
if (Services.prefs.getBoolPref("devtools.styleinspector.enabled") &&
@ -887,6 +887,9 @@ InspectorUI.prototype = {
this.toolbar.hidden = false;
this.inspectMenuitem.setAttribute("checked", true);
// initialize the HTML Breadcrumbs
this.breadcrumbs = new HTMLBreadcrumbs(this);
this.isDirty = false;
this.progressListener = new InspectorProgressListener(this);
@ -999,6 +1002,11 @@ InspectorUI.prototype = {
this.highlighter = null;
}
if (this.breadcrumbs) {
this.breadcrumbs.destroy();
this.breadcrumbs = null;
}
this.inspectMenuitem.setAttribute("checked", false);
this.browser = this.win = null; // null out references to browser and window
this.winID = null;
@ -1009,7 +1017,6 @@ InspectorUI.prototype = {
delete this.treePanel;
delete this.stylePanel;
delete this.toolbar;
delete this.TreePanel;
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.CLOSED, null);
},
@ -1093,6 +1100,8 @@ InspectorUI.prototype = {
}
}
this.breadcrumbs.update();
this.toolsSelect(aScroll);
},
@ -1888,13 +1897,463 @@ InspectorProgressListener.prototype = {
},
};
///////////////////////////////////////////////////////////////////////////
//// HTML Breadcrumbs
/**
* Display the ancestors of the current node and its children.
* Only one "branch" of children are displayed (only one line).
*
* Mechanism:
* . If no nodes displayed yet:
* then display the ancestor of the selected node and the selected node;
* else select the node;
* . If the selected node is the last node displayed, append its first (if any).
*
* @param object aInspector
* The InspectorUI instance.
*/
function HTMLBreadcrumbs(aInspector)
{
this.IUI = aInspector;
this.DOMHelpers = new DOMHelpers(this.IUI.win);
this._init();
}
HTMLBreadcrumbs.prototype = {
_init: function BC__init()
{
this.container = this.IUI.chromeDoc.getElementById("inspector-breadcrumbs");
this.container.addEventListener("mousedown", this, true);
// We will save a list of already displayed nodes in this array.
this.nodeHierarchy = [];
// Last selected node in nodeHierarchy.
this.currentIndex = -1;
// Siblings menu
this.menu = this.IUI.chromeDoc.createElement("menupopup");
this.menu.id = "inspector-breadcrumbs-menu";
let popupSet = this.IUI.chromeDoc.getElementById("mainPopupSet");
popupSet.appendChild(this.menu);
this.menu.addEventListener("popuphiding", (function() {
while (this.menu.hasChildNodes()) {
this.menu.removeChild(this.menu.firstChild);
}
let button = this.container.querySelector("button[siblings-menu-open]");
button.removeAttribute("siblings-menu-open");
}).bind(this), false);
},
/**
* Build a string that represents the node: tagName#id.class1.class2.
*
* @param aNode The node to pretty-print
* @returns a string
*/
prettyPrintNodeAsText: function BC_prettyPrintNodeText(aNode)
{
let text = aNode.tagName.toLowerCase();
if (aNode.id) {
text += "#" + aNode.id;
}
for (let i = 0; i < aNode.classList.length; i++) {
text += "." + aNode.classList[i];
}
return text;
},
/**
* Build <label>s that represent the node:
* <label class="inspector-breadcrumbs-tag">tagName</label>
* <label class="inspector-breadcrumbs-id">#id</label>
* <label class="inspector-breadcrumbs-classes">.class1.class2</label>
*
* @param aNode The node to pretty-print
* @returns a document fragment.
*/
prettyPrintNodeAsXUL: function BC_prettyPrintNodeXUL(aNode)
{
let fragment = this.IUI.chromeDoc.createDocumentFragment();
let tagLabel = this.IUI.chromeDoc.createElement("label");
tagLabel.className = "inspector-breadcrumbs-tag plain";
let idLabel = this.IUI.chromeDoc.createElement("label");
idLabel.className = "inspector-breadcrumbs-id plain";
let classesLabel = this.IUI.chromeDoc.createElement("label");
classesLabel.className = "inspector-breadcrumbs-classes plain";
tagLabel.textContent = aNode.tagName.toLowerCase();
idLabel.textContent = aNode.id ? ("#" + aNode.id) : "";
let classesText = "";
for (let i = 0; i < aNode.classList.length; i++) {
classesText += "." + aNode.classList[i];
}
classesLabel.textContent = classesText;
fragment.appendChild(tagLabel);
fragment.appendChild(idLabel);
fragment.appendChild(classesLabel);
return fragment;
},
/**
* Open the sibling menu.
*
* @param aButton the button representing the node.
* @param aNode the node we want the siblings from.
*/
openSiblingMenu: function BC_openSiblingMenu(aButton, aNode)
{
let title = this.IUI.chromeDoc.createElement("menuitem");
title.setAttribute("label",
this.IUI.strings.GetStringFromName("breadcrumbs.siblings"));
title.setAttribute("disabled", "true");
let separator = this.IUI.chromeDoc.createElement("menuseparator");
this.menu.appendChild(title);
this.menu.appendChild(separator);
let fragment = this.IUI.chromeDoc.createDocumentFragment();
let nodes = aNode.parentNode.childNodes;
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].nodeType == aNode.ELEMENT_NODE) {
let item = this.IUI.chromeDoc.createElement("menuitem");
let inspector = this.IUI;
if (nodes[i] === aNode) {
item.setAttribute("disabled", "true");
item.setAttribute("checked", "true");
}
item.setAttribute("type", "radio");
item.setAttribute("label", this.prettyPrintNodeAsText(nodes[i]));
item.onmouseup = (function(aNode) {
return function() {
inspector.select(aNode, true, true);
}
})(nodes[i]);
fragment.appendChild(item);
}
}
this.menu.appendChild(fragment);
this.menu.openPopup(aButton, "before_start", 0, 0, true, false);
},
/**
* Generic event handler.
*
* @param nsIDOMEvent aEvent
* The DOM event object.
*/
handleEvent: function BC_handleEvent(aEvent)
{
if (aEvent.type == "mousedown") {
// on Click and Hold, open the Siblings menu
let timer;
let container = this.container;
let window = this.IUI.win;
function openMenu(aEvent) {
cancelHold();
let target = aEvent.originalTarget;
if (target.tagName == "button") {
target.onBreadcrumbsHold();
target.setAttribute("siblings-menu-open", "true");
}
}
function handleClick(aEvent) {
cancelHold();
let target = aEvent.originalTarget;
if (target.tagName == "button") {
target.onBreadcrumbsClick();
}
}
function cancelHold(aEvent) {
window.clearTimeout(timer);
container.removeEventListener("mouseout", cancelHold, false);
container.removeEventListener("mouseup", handleClick, false);
}
container.addEventListener("mouseout", cancelHold, false);
container.addEventListener("mouseup", handleClick, false);
timer = window.setTimeout(openMenu, 500, aEvent);
}
},
/**
* Remove nodes and delete properties.
*/
destroy: function BC_destroy()
{
this.empty();
this.container.removeEventListener("mousedown", this, true);
this.menu.parentNode.removeChild(this.menu);
this.container = null;
this.nodeHierarchy = null;
},
/**
* Empty the breadcrumbs container.
*/
empty: function BC_empty()
{
while (this.container.hasChildNodes()) {
this.container.removeChild(this.container.firstChild);
}
},
/**
* Re-init the cache and remove all the buttons.
*/
invalidateHierarchy: function BC_invalidateHierarchy()
{
this.menu.hidePopup();
this.nodeHierarchy = [];
this.empty();
},
/**
* Set which button represent the selected node.
*
* @param aIdx Index of the displayed-button to select
*/
setCursor: function BC_setCursor(aIdx)
{
// Unselect the previously selected button
if (this.currentIndex > -1 && this.currentIndex < this.nodeHierarchy.length) {
this.nodeHierarchy[this.currentIndex].button.removeAttribute("checked");
}
if (aIdx > -1) {
this.nodeHierarchy[aIdx].button.setAttribute("checked", "true");
}
this.currentIndex = aIdx;
},
/**
* Get the index of the node in the cache.
*
* @param aNode
* @returns integer the index, -1 if not found
*/
indexOf: function BC_indexOf(aNode)
{
let i = this.nodeHierarchy.length - 1;
for (let i = this.nodeHierarchy.length - 1; i >= 0; i--) {
if (this.nodeHierarchy[i].node === aNode) {
return i;
}
}
return -1;
},
/**
* Remove all the buttons and their references in the cache
* after a given index.
*
* @param aIdx
*/
cutAfter: function BC_cutAfter(aIdx)
{
while (this.nodeHierarchy.length > (aIdx + 1)) {
let toRemove = this.nodeHierarchy.pop();
this.container.removeChild(toRemove.button);
}
},
/**
* Build a button representing the node.
*
* @param aNode The node from the page.
* @returns aNode The <button>.
*/
buildButton: function BC_buildButton(aNode)
{
let button = this.IUI.chromeDoc.createElement("button");
let inspector = this.IUI;
button.appendChild(this.prettyPrintNodeAsXUL(aNode));
button.className = "inspector-breadcrumbs-button";
button.setAttribute("tooltiptext", this.prettyPrintNodeAsText(aNode));
button.onBreadcrumbsClick = function onBreadcrumbsClick() {
inspector.stopInspecting();
inspector.select(aNode, true, true);
};
button.onclick = (function _onBreadcrumbsRightClick(aEvent) {
if (aEvent.button == 2) {
this.openSiblingMenu(button, aNode);
}
}).bind(this);
button.onBreadcrumbsHold = (function _onBreadcrumbsHold() {
this.openSiblingMenu(button, aNode);
}).bind(this);
return button;
},
/**
* Connecting the end of the breadcrumbs to a node.
*
* @param aNode The node to reach.
*/
expand: function BC_expand(aNode)
{
let fragment = this.IUI.chromeDoc.createDocumentFragment();
let toAppend = aNode;
let lastButtonInserted = null;
let originalLength = this.nodeHierarchy.length;
let stopNode = null;
if (originalLength > 0) {
stopNode = this.nodeHierarchy[originalLength - 1].node;
}
while (toAppend && toAppend.tagName && toAppend != stopNode) {
let button = this.buildButton(toAppend);
fragment.insertBefore(button, lastButtonInserted);
lastButtonInserted = button;
this.nodeHierarchy.splice(originalLength, 0, {node: toAppend, button: button});
toAppend = this.DOMHelpers.getParentObject(toAppend);
}
this.container.appendChild(fragment, this.container.firstChild);
},
/**
* Get a child of a node that can be displayed in the breadcrumbs.
* By default, we want a node that can highlighted by the highlighter.
* If no highlightable child is found, we return the first node of type
* ELEMENT_NODE.
*
* @param aNode The parent node.
* @returns nsIDOMNode|null
*/
getFirstHighlightableChild: function BC_getFirstHighlightableChild(aNode)
{
let nextChild = this.DOMHelpers.getChildObject(aNode, 0);
let fallback = null;
while (nextChild) {
if (this.IUI.highlighter.isNodeHighlightable(nextChild)) {
return nextChild;
}
if (!fallback && nextChild.nodeType == aNode.ELEMENT_NODE) {
fallback = nextChild;
}
nextChild = this.DOMHelpers.getNextSibling(nextChild);
}
return fallback;
},
/**
* Find the "youngest" ancestor of a node which is already in the breadcrumbs.
*
* @param aNode
* @returns Index of the ancestor in the cache
*/
getCommonAncestor: function BC_getCommonAncestor(aNode)
{
let node = aNode;
while (node) {
let idx = this.indexOf(node);
if (idx > -1) {
return idx;
} else {
node = this.DOMHelpers.getParentObject(node);
}
}
return -1;
},
/**
* Make sure that the latest node in the breadcrumbs is not the selected node
* if the selected node still has children.
*/
ensureFirstChild: function BC_ensureFirstChild()
{
// If the last displayed node is the selected node
if (this.currentIndex == this.nodeHierarchy.length - 1) {
let node = this.nodeHierarchy[this.currentIndex].node;
let child = this.getFirstHighlightableChild(node);
// If the node has a child
if (child) {
// Show this child
this.expand(child);
}
}
},
/**
* Ensure the selected node is visible.
*/
scroll: function BC_scroll()
{
// FIXME bug 684352: make sure its immediate neighbors are visible too.
let scrollbox = this.container;
let element = this.nodeHierarchy[this.currentIndex].button;
scrollbox.ensureElementIsVisible(element);
},
/**
* Update the breadcrumbs display when a new node is selected.
*/
update: function BC_update()
{
this.menu.hidePopup();
let selection = this.IUI.selection;
let idx = this.indexOf(selection);
// Is the node already displayed in the breadcrumbs?
if (idx > -1) {
// Yes. We select it.
this.setCursor(idx);
} else {
// No. Is the breadcrumbs display empty?
if (this.nodeHierarchy.length > 0) {
// No. We drop all the element that are not direct ancestors
// of the selection
let parent = this.DOMHelpers.getParentObject(selection);
let idx = this.getCommonAncestor(parent);
this.cutAfter(idx);
}
// we append the missing button between the end of the breadcrumbs display
// and the current node.
this.expand(selection);
// we select the current node button
idx = this.indexOf(selection);
this.setCursor(idx);
}
// Add the first child of the very last node of the breadcrumbs if possible.
this.ensureFirstChild();
// Make sure the selected node and its neighbours are visible.
this.scroll();
}
}
/////////////////////////////////////////////////////////////////////////
//// Initializers
XPCOMUtils.defineLazyGetter(InspectorUI.prototype, "strings",
function () {
return Services.strings.
createBundle("chrome://browser/locale/inspector.properties");
return Services.strings.createBundle(
"chrome://browser/locale/devtools/inspector.properties");
});
XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {

View File

@ -63,6 +63,8 @@ _BROWSER_FILES = \
browser_inspector_bug_690361.js \
browser_inspector_bug_672902_keyboard_shortcuts.js \
browser_inspector_keybindings.js \
browser_inspector_breadcrumbs.html \
browser_inspector_breadcrumbs.js \
$(NULL)
# Disabled due to constant failures

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
min-height: 10px; min-width: 10px;
border: 1px solid red;
margin: 10px;
}
</style>
</head>
<body>
<article id="i1">
<div id="i11">
<div id="i111">
<div id="i1111">
</div>
</div>
</div>
</article>
<article id="i2">
<div id="i21">
<div id="i211">
<div id="i2111">
</div>
</div>
</div>
<div id="i22">
<div id="i221">
</div>
<div id="i222">
<div id="i2221">
<div id="i22211">
</div>
</div>
</div>
</div>
</article>
</body>
</html>

View File

@ -0,0 +1,105 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
let nodes = [
{nodeId: "i1111", result: "i1 i11 i111 i1111"},
{nodeId: "i22", result: "i2 i22 i221"},
{nodeId: "i2111", result: "i2 i21 i211 i2111"},
{nodeId: "i21", result: "i2 i21 i211 i2111"},
{nodeId: "i22211", result: "i2 i22 i222 i2221 i22211"},
{nodeId: "i22", result: "i2 i22 i222 i2221 i22211"},
];
let doc;
let nodes;
let cursor;
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/highlighter/test/browser_inspector_breadcrumbs.html";
function setupTest()
{
for (let i = 0; i < nodes.length; i++) {
let node = doc.getElementById(nodes[i].nodeId);
nodes[i].node = node;
ok(nodes[i].node, "node " + nodes[i].nodeId + " found");
}
Services.obs.addObserver(runTests,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
InspectorUI.toggleInspectorUI();
}
function runTests()
{
Services.obs.removeObserver(runTests,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
cursor = 0;
executeSoon(function() {
Services.obs.addObserver(nodeSelected,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
InspectorUI.inspectNode(nodes[0].node);
});
}
function nodeSelected()
{
executeSoon(function() {
performTest();
cursor++;
if (cursor >= nodes.length) {
Services.obs.removeObserver(nodeSelected,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
Services.obs.addObserver(finishUp,
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
executeSoon(function() {
InspectorUI.closeInspectorUI();
});
} else {
let node = nodes[cursor].node;
InspectorUI.inspectNode(node);
}
});
}
function performTest()
{
let container = document.getElementById("inspector-breadcrumbs");
let buttonsLabelIds = nodes[cursor].result.split(" ");
// html > body > …
is(container.childNodes.length, buttonsLabelIds.length + 2, "Node " + cursor + ": Items count");
for (let i = 2; i < container.childNodes.length; i++) {
let expectedId = "#" + buttonsLabelIds[i - 2];
let button = container.childNodes[i];
let labelId = button.querySelector(".inspector-breadcrumbs-id");
is(labelId.textContent, expectedId, "Node " + cursor + ": button " + i + " matches");
}
let checkedButton = container.querySelector("button[checked]");
let labelId = checkedButton.querySelector(".inspector-breadcrumbs-id");
is(labelId.textContent, "#" + InspectorUI.selection.id, "Node " + cursor + ": selection matches");
}
function finishUp() {
Services.obs.removeObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
doc = nodes = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -63,7 +63,7 @@ Cu.import("resource:///modules/source-editor.jsm");
const SCRATCHPAD_CONTEXT_CONTENT = 1;
const SCRATCHPAD_CONTEXT_BROWSER = 2;
const SCRATCHPAD_WINDOW_URL = "chrome://browser/content/scratchpad.xul";
const SCRATCHPAD_L10N = "chrome://browser/locale/scratchpad.properties";
const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties";
const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
@ -84,10 +84,10 @@ var Scratchpad = {
executionContext: SCRATCHPAD_CONTEXT_CONTENT,
/**
* Retrieve the xul:statusbarpanel DOM element. The status bar tells the
* current code execution context.
* Retrieve the xul:notificationbox DOM element. It notifies the user when
* the current code execution context is SCRATCHPAD_CONTEXT_BROWSER.
*/
get statusbarStatus() document.getElementById("scratchpad-status"),
get notificationBox() document.getElementById("scratchpad-notificationbox"),
/**
* Get the selected text from the editor.
@ -599,11 +599,15 @@ var Scratchpad = {
*/
setContentContext: function SP_setContentContext()
{
if (this.executionContext == SCRATCHPAD_CONTEXT_CONTENT) {
return;
}
let content = document.getElementById("sp-menu-content");
document.getElementById("sp-menu-browser").removeAttribute("checked");
content.setAttribute("checked", true);
this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
this.statusbarStatus.label = content.getAttribute("label");
this.notificationBox.removeAllNotifications(false);
this.resetContext();
},
@ -612,11 +616,20 @@ var Scratchpad = {
*/
setBrowserContext: function SP_setBrowserContext()
{
if (this.executionContext == SCRATCHPAD_CONTEXT_BROWSER) {
return;
}
let browser = document.getElementById("sp-menu-browser");
document.getElementById("sp-menu-content").removeAttribute("checked");
browser.setAttribute("checked", true);
this.executionContext = SCRATCHPAD_CONTEXT_BROWSER;
this.statusbarStatus.label = browser.getAttribute("label");
this.notificationBox.appendNotification(
this.strings.GetStringFromName("browserContext.notification"),
SCRATCHPAD_CONTEXT_BROWSER,
null,
this.notificationBox.PRIORITY_WARNING_HIGH,
null);
this.resetContext();
},
@ -657,17 +670,14 @@ var Scratchpad = {
return;
}
let chromeContextMenu = document.getElementById("sp-menu-browser");
let errorConsoleMenu = document.getElementById("sp-menu-errorConsole");
let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
if (chrome) {
chromeContextMenu.removeAttribute("hidden");
errorConsoleMenu.removeAttribute("hidden");
errorConsoleCommand.removeAttribute("disabled");
let environmentMenu = document.getElementById("sp-environment-menu");
let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
environmentMenu.removeAttribute("hidden");
chromeContextCommand.removeAttribute("disabled");
errorConsoleCommand.removeAttribute("disabled");
}
this.editor = new SourceEditor();

View File

@ -40,7 +40,7 @@
- ***** END LICENSE BLOCK ***** -->
#endif
<!DOCTYPE window [
<!ENTITY % scratchpadDTD SYSTEM "chrome://browser/locale/scratchpad.dtd" >
<!ENTITY % scratchpadDTD SYSTEM "chrome://browser/locale/devtools/scratchpad.dtd" >
%scratchpadDTD;
]>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
@ -261,12 +261,18 @@
accesskey="&display.accesskey;"
key="sp-key-display"
command="sp-cmd-display"/>
<menuseparator/>
<menuitem id="sp-text-resetContext"
label="&resetContext2.label;"
accesskey="&resetContext2.accesskey;"
command="sp-cmd-resetContext"/>
</menupopup>
</menu>
<menu id="sp-environment-menu"
label="&environmentMenu.label;"
accesskey="&environmentMenu.accesskey;">
accesskey="&environmentMenu.accesskey;"
hidden="true">
<menupopup id="sp-menu-environment">
<menuitem id="sp-menu-content"
label="&contentContext.label;"
@ -274,33 +280,11 @@
command="sp-cmd-contentContext"
checked="true"
type="radio"/>
<menuitem id="sp-menu-browser" hidden="true"
<menuitem id="sp-menu-browser"
command="sp-cmd-browserContext"
label="&browserContext.label;"
accesskey="&browserContext.accesskey;"
type="radio"/>
<menuseparator/>
<menuitem id="sp-menu-resetContext"
command="sp-cmd-resetContext"
label="&resetContext.label;"
accesskey="&resetContext.accesskey;"/>
</menupopup>
</menu>
<menu id="sp-tools-menu"
label="&toolsMenu.label;"
accesskey="&toolsMenu.accesskey;">
<menupopup id="sp-menu-tools">
<menuitem id="sp-menu-errorConsole" hidden="true"
label="&errorConsoleCmd.label;"
accesskey="&errorConsoleCmd.accesskey;"
key="sp-key-errorConsole"
command="sp-cmd-errorConsole"/>
<menuitem id="sp-menu-webConsole"
label="&webConsoleCmd.label;"
accesskey="&webConsoleCmd.accesskey;"
key="sp-key-webConsole"
command="sp-cmd-webConsole"/>
</menupopup>
</menu>
</menubar>
@ -329,15 +313,16 @@
accesskey="&display.accesskey;"
key="sp-key-display"
command="sp-cmd-display"/>
<menuseparator/>
<menuitem id="sp-text-resetContext"
label="&resetContext2.label;"
accesskey="&resetContext2.accesskey;"
command="sp-cmd-resetContext"/>
</menupopup>
</popupset>
<hbox id="scratchpad-editor" flex="1" context="scratchpad-text-popup" />
<notificationbox id="scratchpad-notificationbox" flex="1">
<hbox id="scratchpad-editor" flex="1" context="scratchpad-text-popup" />
</notificationbox>
<statusbar id="scratchpad-statusbar" align="end">
<statusbarpanel id="scratchpad-status"
label="&contentContext.label;"
class="statusbarpanel-iconic-text"/>
<spacer flex="1"/>
</statusbar>
</window>

View File

@ -35,11 +35,11 @@ function runTests()
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
let chromeContextMenu = gScratchpadWindow.document.
getElementById("sp-menu-browser");
ok(chromeContextMenu, "Chrome context menuitem element exists");
ok(!chromeContextMenu.hasAttribute("hidden"),
"Chrome context menuitem is visible");
let environmentMenu = gScratchpadWindow.document.
getElementById("sp-environment-menu");
ok(environmentMenu, "Environment menu element exists");
ok(!environmentMenu.hasAttribute("hidden"),
"Environment menu is visible");
let errorConsoleCommand = gScratchpadWindow.document.
getElementById("sp-cmd-errorConsole");
@ -47,12 +47,6 @@ function runTests()
ok(!errorConsoleCommand.hasAttribute("disabled"),
"Error console command is enabled");
let errorConsoleMenu = gScratchpadWindow.document.
getElementById("sp-menu-errorConsole");
ok(errorConsoleMenu, "Error console menu element exists");
ok(!errorConsoleMenu.hasAttribute("hidden"),
"Error console menuitem is visible");
let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists");

View File

@ -28,11 +28,11 @@ function runTests()
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let chromeMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let statusbar = sp.statusbarStatus;
let notificationBox = sp.notificationBox;
ok(contentMenu, "found #sp-menu-content");
ok(chromeMenu, "found #sp-menu-browser");
ok(statusbar, "found Scratchpad.statusbarStatus");
ok(notificationBox, "found Scratchpad.notificationBox");
sp.setContentContext();
@ -45,8 +45,8 @@ function runTests()
ok(!chromeMenu.hasAttribute("checked"),
"chrome menuitem is not checked");
is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
"statusbar label is correct");
ok(!notificationBox.currentNotification,
"there is no notification in content context");
sp.setText("window.foobarBug636725 = 'aloha';");
@ -69,8 +69,8 @@ function runTests()
ok(!contentMenu.hasAttribute("checked"),
"content menuitem is not checked");
is(statusbar.getAttribute("label"), chromeMenu.getAttribute("label"),
"statusbar label is correct");
ok(notificationBox.currentNotification,
"there is a notification in browser context");
sp.setText("2'", 31, 33);

View File

@ -32,11 +32,11 @@ function runTests()
is(typeof sp.inspect, "function", "Scratchpad.inspect() exists");
is(typeof sp.display, "function", "Scratchpad.display() exists");
let chromeContextMenu = gScratchpadWindow.document.
getElementById("sp-menu-browser");
ok(chromeContextMenu, "Chrome context menuitem element exists");
is(chromeContextMenu.getAttribute("hidden"), "true",
"Chrome context menuitem is hidden");
let environmentMenu = gScratchpadWindow.document.
getElementById("sp-environment-menu");
ok(environmentMenu, "Environment menu element exists");
ok(environmentMenu.hasAttribute("hidden"),
"Environment menu is not visible");
let errorConsoleCommand = gScratchpadWindow.document.
getElementById("sp-cmd-errorConsole");
@ -44,12 +44,6 @@ function runTests()
is(errorConsoleCommand.getAttribute("disabled"), "true",
"Error console command is disabled");
let errorConsoleMenu = gScratchpadWindow.document.
getElementById("sp-menu-errorConsole");
ok(errorConsoleMenu, "Error console menu element exists");
is(errorConsoleMenu.getAttribute("hidden"), "true",
"Error console menu item is hidden");
let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists");

View File

@ -38,11 +38,11 @@ function runTests()
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let browserMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let statusbar = sp.statusbarStatus;
let notificationBox = sp.notificationBox;
ok(contentMenu, "found #sp-menu-content");
ok(browserMenu, "found #sp-menu-browser");
ok(statusbar, "found Scratchpad.statusbarStatus");
ok(notificationBox, "found Scratchpad.notificationBox");
sp.setContentContext();
@ -55,8 +55,8 @@ function runTests()
ok(!browserMenu.hasAttribute("checked"),
"chrome menuitem is not checked");
is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
"statusbar label is correct");
is(notificationBox.currentNotification, null,
"there is no notification currently shown for content context");
sp.setText("window.foosbug653108 = 'aloha';");

View File

@ -36,11 +36,9 @@ function runTests()
"sp-text-run": "run",
"sp-text-inspect": "inspect",
"sp-text-display": "display",
"sp-text-resetContext": "resetContext",
"sp-menu-content": "setContentContext",
"sp-menu-browser": "setBrowserContext",
"sp-menu-resetContext": "resetContext",
"sp-menu-errorConsole": "openErrorConsole",
"sp-menu-webConsole": "openWebConsole",
"sp-menu-undo": "undo",
"sp-menu-redo": "redo",
};

View File

@ -130,7 +130,7 @@ CssHtmlTree.processTemplate = function CssHtmlTree_processTemplate(aTemplate,
};
XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
.createBundle("chrome://browser/locale/styleinspector.properties"));
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
CssHtmlTree.prototype = {
htmlComplete: false,
@ -681,17 +681,17 @@ SelectorView.prototype = {
text: function SelectorView_text(aElement) {
let result = this.selectorInfo.selector.text;
if (this.selectorInfo.elementStyle) {
if (this.tree.styleInspector.IUI) {
if (this.selectorInfo.sourceElement == this.tree.styleInspector.IUI.selection)
{
result = "this";
} else {
result = CssLogic.getShortName(this.selectorInfo.sourceElement);
}
let source = this.selectorInfo.sourceElement;
let IUI = this.tree.styleInspector.IUI;
if (IUI && IUI.selection == source) {
result = "this";
} else {
result = CssLogic.getShortName(source);
}
aElement.parentNode.querySelector(".rule-link > a").
addEventListener("click", function(aEvent) {
this.tree.styleInspector.selectFromPath(this.selectorInfo.sourceElement);
this.tree.styleInspector.selectFromPath(source);
aEvent.preventDefault();
}.bind(this), false);
result += ".style";

View File

@ -606,10 +606,12 @@ CssLogic.prototype = {
/**
* Check if the highlighted element or it's parents have matched selectors.
* If aCallback is provided then the domRules for the element are passed to
* the callback function.
*
* @param {function} [aCallback] Simple callback method
* @param {function} [aCallback] Simple callback method. If aCallback is
* provided then the domRules for each element in the loop are passed to
* the callback function. When the element has .style properties, the callback
* receives {style: element.style}. If the callback returns true then the
* element has matched rules, otherwise not.
* @return {Boolean} true if the current element or it's parents have
* matching CssSelector objects, false otherwise
*/
@ -628,11 +630,22 @@ CssLogic.prototype = {
continue;
}
// Check if the are DOM rules that we can consider as matched rules
// (depending on the callback).
if (domRules.Count() && (!aCallback || aCallback(domRules))) {
matched = true;
break;
}
// Check if the element has any element.style properties that we can
// consider as "matched" (depending on the callback).
if (element.style.length > 0 &&
(!aCallback || aCallback({style: element.style}))) {
matched = true;
}
if (matched) {
break;
}
} while ((element = element.parentNode) &&
element.nodeType === Ci.nsIDOMNode.ELEMENT_NODE);
@ -746,7 +759,7 @@ CssLogic.getShortNamePath = function CssLogic_getShortNamePath(aElement)
CssLogic.l10n = function(aName) CssLogic._strings.GetStringFromName(aName);
XPCOMUtils.defineLazyGetter(CssLogic, "_strings", function() Services.strings
.createBundle("chrome://browser/locale/styleinspector.properties"));
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
/**
* Is the given property sheet a system (user agent) stylesheet?
@ -1499,6 +1512,11 @@ CssPropertyInfo.prototype = {
{
if (this._hasMatchedSelectors === null) {
this._hasMatchedSelectors = this._cssLogic.hasMatchedSelectors(function(aDomRules) {
if (!aDomRules.Count) {
// For element.style.
return !!aDomRules.style.getPropertyValue(this.property);
}
for (let i = 0; i < aDomRules.Count(); i++) {
let domRule = aDomRules.GetElementAt(i);

View File

@ -314,7 +314,7 @@ StyleInspector.prototype = {
};
XPCOMUtils.defineLazyGetter(this, "_strings", function() Services.strings
.createBundle("chrome://browser/locale/styleinspector.properties"));
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
XPCOMUtils.defineLazyGetter(this, "CssLogic", function() {
let tmp = {};

View File

@ -1,7 +1,7 @@
<!DOCTYPE html [
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
%htmlDTD;
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/styleinspector.dtd">
<!ENTITY % inspectorDTD SYSTEM "chrome://browser/locale/devtools/styleinspector.dtd">
%inspectorDTD;
<!ELEMENT loop ANY>
<!ATTLIST li foreach CDATA #IMPLIED>

View File

@ -51,6 +51,7 @@ _BROWSER_TEST_FILES = \
browser_bug683672.js \
browser_styleinspector_bug_672746_default_styles.js \
browser_styleinspector_bug_672744_search_filter.js \
browser_bug_692400_element_style.js \
head.js \
$(NULL)

View File

@ -0,0 +1,84 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests for selector text errors.
let doc;
let stylePanel;
function createDocument()
{
doc.body.innerHTML = "<div style='color:blue;'></div>";
doc.title = "Style Inspector Selector Text Test";
ok(window.StyleInspector, "StyleInspector exists");
stylePanel = new StyleInspector(window);
stylePanel.createPanel(false, function() {
Services.obs.addObserver(SI_checkText, "StyleInspector-populated", false);
let span = doc.querySelector("div");
ok(span, "captain, we have the test div");
stylePanel.open(span);
});
}
function SI_checkText()
{
Services.obs.removeObserver(SI_checkText, "StyleInspector-populated", false);
let propertyView = null;
stylePanel.cssHtmlTree.propertyViews.some(function(aView) {
if (aView.name == "color") {
propertyView = aView;
return true;
}
});
ok(propertyView, "found PropertyView for color");
is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true");
propertyView.matchedExpanded = true;
propertyView.refreshMatchedSelectors();
let td = propertyView.matchedSelectorTable.querySelector("td.rule-text");
ok(td, "found the first table row");
let selector = propertyView.matchedSelectorViews[0];
ok(selector, "found the first matched selector view");
try {
is(td.textContent.trim(), selector.humanReadableText(td).trim(),
"selector text is correct");
} catch (ex) {
info("EXCEPTION: " + ex);
ok(false, "getting the selector text should not raise an exception");
}
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
stylePanel.close();
}
function finishUp()
{
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
doc = stylePanel = null;
gBrowser.removeCurrentTab();
finish();
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,selector text test, bug 692400";
}

View File

@ -164,7 +164,7 @@ function styleInspectorClosedByHide()
{
Services.obs.removeObserver(styleInspectorClosedByHide, "StyleInspector-closed", false);
is(stylePanels[0].state, "open", "instance stylePanels[0] is still open");
is(stylePanels[1].state, "closed", "instance stylePanels[1] is hidden");
isnot(stylePanels[1].state, "open", "instance stylePanels[1] is not open");
is(stylePanels[2].state, "open", "instance stylePanels[2] is still open");
info("closing web console");

View File

@ -42,7 +42,7 @@ const Cu = Components.utils;
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const HUD_STRINGS_URI = "chrome://global/locale/headsUpDisplay.properties";
const HUD_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
Cu.import("resource://gre/modules/Services.jsm");

View File

@ -38,82 +38,21 @@
let EXPORTED_SYMBOLS = [ "GcliCommands" ];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource:///modules/gcli.jsm");
Components.utils.import("resource:///modules/HUDService.jsm");
let bundleName = "chrome://browser/locale/devtools/gclicommands.properties";
let stringBundle = Services.strings.createBundle(bundleName);
let gcli = gcli._internal.require("gcli/index");
let canon = gcli._internal.require("gcli/canon");
let document;
/**
* The exported API
*/
let GcliCommands = {
/**
* Allow HUDService to inform us of the document against which we work
*/
setDocument: function GcliCommands_setDocument(aDocument) {
document = aDocument;
},
/**
* Undo the effects of GcliCommands.setDocument()
*/
unsetDocument: function GcliCommands_unsetDocument() {
document = undefined;
}
};
/**
* Lookup a string in the GCLI string bundle
* @param aName The name to lookup
* @return The looked up name
*/
function lookup(aName)
{
try {
return stringBundle.GetStringFromName(aName);
} catch (ex) {
throw new Error("Failure in lookup('" + aName + "')");
}
};
/**
* Lookup a string in the GCLI string bundle
* @param aName The name to lookup
* @param aSwaps An array of swaps. See stringBundle.formatStringFromName
* @return The looked up name
*/
function lookupFormat(aName, aSwaps)
{
try {
return stringBundle.formatStringFromName(aName, aSwaps, aSwaps.length);
} catch (ex) {
Services.console.logStringMessage("Failure in lookupFormat('" + aName + "')");
throw new Error("Failure in lookupFormat('" + aName + "')");
}
}
/**
* 'echo' command
*/
gcli.addCommand({
name: "echo",
description: lookup("echoDesc"),
description: gcli.lookup("echoDesc"),
params: [
{
name: "message",
type: "string",
description: lookup("echoMessageDesc")
description: gcli.lookup("echoMessageDesc")
}
],
returnType: "string",
@ -123,17 +62,19 @@ gcli.addCommand({
});
let canon = gcli._internal.require("gcli/canon");
/**
* 'help' command
*/
gcli.addCommand({
name: "help",
returnType: "html",
description: lookup("helpDesc"),
description: gcli.lookup("helpDesc"),
exec: function Command_help(args, context) {
let output = [];
output.push("<strong>" + lookup("helpAvailable") + ":</strong><br/>");
output.push("<strong>" + gcli.lookup("helpAvailable") + ":</strong><br/>");
let commandNames = canon.getCommandNames();
commandNames.sort();
@ -160,8 +101,8 @@ gcli.addCommand({
*/
gcli.addCommand({
name: "console",
description: lookup("consoleDesc"),
manual: lookup("consoleManual")
description: gcli.lookup("consoleDesc"),
manual: gcli.lookup("consoleManual")
});
/**
@ -169,10 +110,32 @@ gcli.addCommand({
*/
gcli.addCommand({
name: "console clear",
description: lookup("consoleclearDesc"),
description: gcli.lookup("consoleclearDesc"),
exec: function(args, context) {
let hud = HUDService.getHudReferenceById(context.environment.hudId);
hud.gcliterm.clearOutput();
}
});
/**
* 'inspect' command
*/
gcli.addCommand({
name: "inspect",
description: gcli.lookup("inspectDesc"),
manual: gcli.lookup("inspectManual"),
params: [
{
name: "node",
type: "node",
description: gcli.lookup("inspectNodeDesc"),
manual: gcli.lookup("inspectNodeManual")
}
],
exec: function Command_inspect(args, context) {
let hud = HUDService.getHudReferenceById(context.environment.hudId);
let InspectorUI = hud.gcliterm.document.defaultView.InspectorUI;
InspectorUI.openInspectorUI(args.node);
}
});

View File

@ -79,12 +79,6 @@ XPCOMUtils.defineLazyGetter(this, "gcli", function () {
return obj.gcli;
});
XPCOMUtils.defineLazyGetter(this, "GcliCommands", function () {
var obj = {};
Cu.import("resource:///modules/GcliCommands.jsm", obj);
return obj.GcliCommands;
});
XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
var obj = {};
Cu.import("resource:///modules/devtools/StyleInspector.jsm", obj);
@ -133,9 +127,26 @@ function LogFactory(aMessagePrefix)
return log;
}
/**
* Load the various Command JSMs.
* Should be called when the console first opens.
*
* @return an object containing the EXPORTED_SYMBOLS from all the command
* modules. In general there is no reason when JSMs need to export symbols
* except when they need the host environment to inform them of things like the
* current window/document/etc.
*/
function loadCommands() {
let commandExports = {};
Cu.import("resource:///modules/GcliCommands.jsm", commandExports);
return commandExports;
}
let log = LogFactory("*** HUDService:");
const HUD_STRINGS_URI = "chrome://global/locale/headsUpDisplay.properties";
const HUD_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
XPCOMUtils.defineLazyGetter(this, "stringBundle", function () {
return Services.strings.createBundle(HUD_STRINGS_URI);
@ -6882,6 +6893,11 @@ catch (ex) {
// GcliTerm
///////////////////////////////////////////////////////////////////////////
/**
* Some commands need customization - this is how we get at them.
*/
let commandExports = undefined;
/**
* GcliTerm
*
@ -6932,7 +6948,10 @@ function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode)
gcli._internal.commandOutputManager.addListener(this.onCommandOutput, this);
gcli._internal.createView(this.opts);
GcliCommands.setDocument(aContentWindow.document);
if (!commandExports) {
commandExports = loadCommands();
}
}
GcliTerm.prototype = {
@ -6957,7 +6976,6 @@ GcliTerm.prototype = {
*/
destroy: function Gcli_destroy()
{
GcliCommands.unsetDocument();
gcli._internal.removeView(this.opts);
gcli._internal.commandOutputManager.removeListener(this.onCommandOutput, this);

View File

@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
<!ENTITY % webConsoleDTD SYSTEM "chrome://global/locale/webConsole.dtd" >
<!ENTITY % webConsoleDTD SYSTEM "chrome://browser/locale/devtools/webConsole.dtd" >
%webConsoleDTD;
]>

View File

@ -630,11 +630,52 @@ var require = define.globalDomain.require.bind(define.globalDomain);
* http://opensource.org/licenses/BSD-3-Clause
*/
var mozl10n = {};
(function(aMozl10n) {
var temp = {};
Components.utils.import("resource://gre/modules/Services.jsm", temp);
var stringBundle = temp.Services.strings.createBundle(
"chrome://browser/locale/devtools/gclicommands.properties");
/**
* Lookup a string in the GCLI string bundle
* @param name The name to lookup
* @return The looked up name
*/
aMozl10n.lookup = function(name) {
try {
return stringBundle.GetStringFromName(name);
}
catch (ex) {
throw new Error("Failure in lookup('" + name + "')");
}
};
/**
* Lookup a string in the GCLI string bundle
* @param name The name to lookup
* @param swaps An array of swaps. See stringBundle.formatStringFromName
* @return The looked up name
*/
aMozl10n.lookupFormat = function(name, swaps) {
try {
return stringBundle.formatStringFromName(name, swaps, swaps.length);
}
catch (ex) {
throw new Error("Failure in lookupFormat('" + name + "')");
}
};
})(mozl10n);
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
// The API for use by command authors
exports.addCommand = require('gcli/canon').addCommand;
exports.removeCommand = require('gcli/canon').removeCommand;
exports.lookup = mozl10n.lookup;
exports.lookupFormat = mozl10n.lookupFormat;
// Internal startup process. Not exported
require('gcli/types/basic').startup();
@ -3437,9 +3478,10 @@ exports.JavascriptType = JavascriptType;
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/types/node', ['require', 'exports', 'module' , 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
define('gcli/types/node', ['require', 'exports', 'module' , 'gcli/host', 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
var host = require('gcli/host');
var l10n = require('gcli/l10n');
var types = require('gcli/types');
var Type = require('gcli/types').Type;
@ -3521,13 +3563,13 @@ NodeType.prototype.parse = function(arg) {
var node = nodes.item(0);
node.__gcliQuery = arg.text;
flashNode(node, 'green');
host.flashNode(node, 'green');
return new Conversion(node, arg, Status.VALID, '');
}
Array.prototype.forEach.call(nodes, function(n) {
flashNode(n, 'red');
host.flashNode(n, 'red');
});
return new Conversion(null, arg, Status.ERROR,
@ -3537,11 +3579,21 @@ NodeType.prototype.parse = function(arg) {
NodeType.prototype.name = 'node';
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/host', ['require', 'exports', 'module' ], function(require, exports, module) {
/**
* Helper to turn a node background it's complementary color for 1 second.
* There is likely a better way to do this, but this will do for now.
*/
function flashNode(node, color) {
exports.flashNode = function(node, color) {
if (!node.__gcliHighlighting) {
node.__gcliHighlighting = true;
var original = node.style.background;
@ -3551,7 +3603,7 @@ function flashNode(node, color) {
delete node.__gcliHighlighting;
}, 1000);
}
}
};
});
@ -4197,16 +4249,17 @@ Requisition.prototype._onCommandAssignmentChange = function(ev) {
/**
* Assignments have an order, so we need to store them in an array.
* But we also need named access ...
* @return The found assignment, or undefined, if no match was found
*/
Requisition.prototype.getAssignment = function(nameOrNumber) {
var name = (typeof nameOrNumber === 'string') ?
nameOrNumber :
Object.keys(this._assignments)[nameOrNumber];
return this._assignments[name];
return this._assignments[name] || undefined;
},
/**
* Where parameter name == assignment names - they are the same.
* Where parameter name == assignment names - they are the same
*/
Requisition.prototype.getParameterNames = function() {
return Object.keys(this._assignments);
@ -5041,210 +5094,8 @@ ExecutionContext.prototype.createPromise = function() {
define('gcli/promise', ['require', 'exports', 'module' ], function(require, exports, module) {
/**
* Create an unfulfilled promise
* @constructor
*/
function Promise() {
this._status = Promise.PENDING;
this._value = undefined;
this._onSuccessHandlers = [];
this._onErrorHandlers = [];
// Debugging help
this._id = Promise._nextId++;
Promise._outstanding[this._id] = this;
};
/**
* We give promises and ID so we can track which are outstanding
*/
Promise._nextId = 0;
/**
* Outstanding promises. Handy list for debugging only.
*/
Promise._outstanding = [];
/**
* Recently resolved promises. Also for debugging only.
*/
Promise._recent = [];
/**
* A promise can be in one of 2 states.
* The ERROR and SUCCESS states are terminal, the PENDING state is the only
* start state.
*/
Promise.ERROR = -1;
Promise.PENDING = 0;
Promise.SUCCESS = 1;
/**
* Yeay for RTTI.
*/
Promise.prototype.isPromise = true;
/**
* Have we either been resolve()ed or reject()ed?
*/
Promise.prototype.isComplete = function() {
return this._status != Promise.PENDING;
};
/**
* Have we resolve()ed?
*/
Promise.prototype.isResolved = function() {
return this._status == Promise.SUCCESS;
};
/**
* Have we reject()ed?
*/
Promise.prototype.isRejected = function() {
return this._status == Promise.ERROR;
};
/**
* Take the specified action of fulfillment of a promise, and (optionally)
* a different action on promise rejection.
*/
Promise.prototype.then = function(onSuccess, onError) {
if (typeof onSuccess === 'function') {
if (this._status === Promise.SUCCESS) {
onSuccess.call(null, this._value);
} else if (this._status === Promise.PENDING) {
this._onSuccessHandlers.push(onSuccess);
}
}
if (typeof onError === 'function') {
if (this._status === Promise.ERROR) {
onError.call(null, this._value);
} else if (this._status === Promise.PENDING) {
this._onErrorHandlers.push(onError);
}
}
return this;
};
/**
* Like then() except that rather than returning <tt>this</tt> we return
* a promise which resolves when the original promise resolves.
*/
Promise.prototype.chainPromise = function(onSuccess) {
var chain = new Promise();
chain._chainedFrom = this;
this.then(function(data) {
try {
chain.resolve(onSuccess(data));
} catch (ex) {
chain.reject(ex);
}
}, function(ex) {
chain.reject(ex);
});
return chain;
};
/**
* Supply the fulfillment of a promise
*/
Promise.prototype.resolve = function(data) {
return this._complete(this._onSuccessHandlers, Promise.SUCCESS, data, 'resolve');
};
/**
* Renege on a promise
*/
Promise.prototype.reject = function(data) {
return this._complete(this._onErrorHandlers, Promise.ERROR, data, 'reject');
};
/**
* Internal method to be called on resolve() or reject().
* @private
*/
Promise.prototype._complete = function(list, status, data, name) {
// Complain if we've already been completed
if (this._status != Promise.PENDING) {
console.group('Promise already closed');
console.error('Attempted ' + name + '() with ', data);
console.error('Previous status = ', this._status,
', previous value = ', this._value);
console.trace();
console.groupEnd();
return this;
}
this._status = status;
this._value = data;
// Call all the handlers, and then delete them
list.forEach(function(handler) {
handler.call(null, this._value);
}, this);
delete this._onSuccessHandlers;
delete this._onErrorHandlers;
// Remove the given {promise} from the _outstanding list, and add it to the
// _recent list, pruning more than 20 recent promises from that list.
delete Promise._outstanding[this._id];
Promise._recent.push(this);
while (Promise._recent.length > 20) {
Promise._recent.shift();
}
return this;
};
/**
* Takes an array of promises and returns a promise that that is fulfilled once
* all the promises in the array are fulfilled
* @param promiseList The array of promises
* @return the promise that is fulfilled when all the array is fulfilled
*/
Promise.group = function(promiseList) {
if (!(promiseList instanceof Array)) {
promiseList = Array.prototype.slice.call(arguments);
}
// If the original array has nothing in it, return now to avoid waiting
if (promiseList.length === 0) {
return new Promise().resolve([]);
}
var groupPromise = new Promise();
var results = [];
var fulfilled = 0;
var onSuccessFactory = function(index) {
return function(data) {
results[index] = data;
fulfilled++;
// If the group has already failed, silently drop extra results
if (groupPromise._status !== Promise.ERROR) {
if (fulfilled === promiseList.length) {
groupPromise.resolve(results);
}
}
};
};
promiseList.forEach(function(promise, index) {
var onSuccess = onSuccessFactory(index);
var onError = groupPromise.reject.bind(groupPromise);
promise.then(onSuccess, onError);
});
return groupPromise;
};
exports.Promise = Promise;
Components.utils.import("resource:///modules/devtools/Promise.jsm");
exports.Promise = Promise;
});
/*

View File

@ -145,8 +145,9 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_659907_console_dir.js \
browser_webconsole_bug_678816.js \
browser_webconsole_bug_664131_console_group.js \
browser_gcli_require.js \
browser_gcli_inspect.js \
browser_gcli_integrate.js \
browser_gcli_require.js \
browser_gcli_web.js \
head.js \
$(NULL)
@ -218,6 +219,7 @@ _BROWSER_TEST_PAGES = \
test-bug-646025-console-file-location.html \
test-bug-678816-content.js \
test-file-location.js \
browser_gcli_inspect.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,25 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GCLI inspect command test</title>
</head>
<body>
<!-- This is a list of 0 h1 elements -->
<!-- This is a list of 1 div elements -->
<div>Hello, I'm a div</div>
<!-- This is a list of 2 span elements -->
<span>Hello, I'm a span</span>
<span>And me</span>
<!-- This is a collection of various things that match only once -->
<p class="someclass">.someclass</p>
<p id="someid">#someid</p>
<button disabled>button[disabled]</button>
<p><strong>p&gt;strong</strong></p>
</body>
</html>

View File

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// For more information on GCLI see:
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
// - https://wiki.mozilla.org/DevTools/Features/GCLI
// Tests that the inspect command works as it should
Components.utils.import("resource:///modules/gcli.jsm");
registerCleanupFunction(function() {
gcliterm = undefined;
requisition = undefined;
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", true);
addTab("http://example.com/browser/browser/devtools/webconsole/test/browser/browser_gcli_inspect.html");
browser.addEventListener("DOMContentLoaded", onLoad, false);
}
let gcliterm;
let requisition;
function onLoad() {
browser.removeEventListener("DOMContentLoaded", onLoad, false);
try {
openConsole();
let hud = HUDService.getHudByWindow(content);
gcliterm = hud.gcliterm;
requisition = gcliterm.opts.requisition;
testSetup();
testCreateCommands();
}
catch (ex) {
ok(false, "Caught exception: " + ex)
gcli._internal.console.error("Test Failure", ex);
}
finally {
closeConsole();
finishTest();
}
}
function testSetup() {
ok(gcliterm, "We have a GCLI term");
ok(requisition, "We have a Requisition");
}
function testCreateCommands() {
type("inspec");
is(gcliterm.completeNode.textContent, " inspect", "Completion for \"inspec\"");
is(requisition.getStatus().toString(), "ERROR", "inspec is ERROR");
type("inspect");
is(requisition.getStatus().toString(), "ERROR", "inspect is ERROR");
type("inspect h1");
is(requisition.getStatus().toString(), "ERROR", "inspect h1 is ERROR");
type("inspect span");
is(requisition.getStatus().toString(), "ERROR", "inspect span is ERROR");
type("inspect div");
is(requisition.getStatus().toString(), "VALID", "inspect div is VALID");
type("inspect .someclass");
is(requisition.getStatus().toString(), "VALID", "inspect .someclass is VALID");
type("inspect #someid");
is(requisition.getStatus().toString(), "VALID", "inspect #someid is VALID");
type("inspect button[disabled]");
is(requisition.getStatus().toString(), "VALID", "inspect button[disabled] is VALID");
type("inspect p>strong");
is(requisition.getStatus().toString(), "VALID", "inspect p>strong is VALID");
type("inspect :root");
is(requisition.getStatus().toString(), "VALID", "inspect :root is VALID");
}
function type(command) {
gcliterm.inputNode.value = command.slice(0, -1);
gcliterm.inputNode.focus();
EventUtils.synthesizeKey(command.slice(-1), {});
}

View File

@ -54,7 +54,7 @@ var Node = Components.interfaces.nsIDOMNode;
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/index', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
// We need to make sure GCLI is initialized before we begin testing it
require('gcli/index');
@ -65,7 +65,6 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gcli/index', 'test/e
examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit'));
examiner.addSuite('gclitest/testCli', require('gclitest/testCli'));
examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory'));
examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire'));
examiner.run();
@ -1373,7 +1372,7 @@ define('gclitest/requirable', ['require', 'exports', 'module' ], function(requir
});
function undefine() {
delete define.modules['gclitest/index'];
delete define.modules['gclitest/suite'];
delete define.modules['test/examiner'];
delete define.modules['gclitest/testTokenize'];
delete define.modules['test/assert'];
@ -1384,7 +1383,7 @@ function undefine() {
delete define.modules['gclitest/testRequire'];
delete define.modules['gclitest/requirable'];
delete define.globalDomain.modules['gclitest/index'];
delete define.globalDomain.modules['gclitest/suite'];
delete define.globalDomain.modules['test/examiner'];
delete define.globalDomain.modules['gclitest/testTokenize'];
delete define.globalDomain.modules['test/assert'];

View File

@ -35,3 +35,25 @@ consoleManual=Filter, clear and close the web console
# LOCALIZATION NOTE (consoleclearDesc) A very short string used to describe the
# function of the 'console clear' command.
consoleclearDesc=Clear the console
# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
# command. See inspectManual for a fuller description of what it does. This
# string is designed to be shown in a menu alongside the command name, which
# is why it should be as short as possible.
inspectDesc=Inspect a node
# LOCALIZATION NOTE (inspectManual) A fuller description of the 'inspect'
# command, displayed when the user asks for help on what it does.
inspectManual=Investigate the dimensions and properties of an element using \
a CSS selector to open the DOM highlighter
# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
# 'node' parameter to the 'inspect' command, which is displayed in a dialog
# when the user is using this command.
inspectNodeDesc=CSS selector
# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
# parameter to the 'inspect' command, displayed when the user asks for help
# on what it does.
inspectNodeManual=A CSS selector for use with Document.querySelector which \
identifies a single element

View File

@ -7,6 +7,7 @@ confirmNavigationAway.buttonLeaveAccesskey=L
confirmNavigationAway.buttonStay=Stay on Page
confirmNavigationAway.buttonStayAccesskey=S
breadcrumbs.siblings=Siblings
# LOCALIZATION NOTE (htmlPanel): Used in the Inspector tool's openInspectorUI
# method when registering the HTML panel.

View File

@ -95,22 +95,23 @@
<!ENTITY browserContext.label "Browser">
<!ENTITY browserContext.accesskey "B">
<!-- LOCALIZATION NOTE (resetContext.label): This command allows the developer
<!-- LOCALIZATION NOTE (resetContext2.label): This command allows the developer
- to reset/clear the global object of the environment where the code executes.
-->
<!ENTITY resetContext.label "Reset">
<!ENTITY resetContext.accesskey "R">
<!ENTITY resetContext2.label "Reset Variables">
<!ENTITY resetContext2.accesskey "T">
<!ENTITY executeMenu.label "Execute">
<!ENTITY executeMenu.accesskey "X">
<!ENTITY toolsMenu.label "Tools">
<!ENTITY toolsMenu.accesskey "T">
<!ENTITY errorConsoleCmd.label "Error Console">
<!ENTITY errorConsoleCmd.accesskey "C">
<!-- LOCALIZATION NOTE (errorConsoleCmd.commandkey): This command key launches
- the browser Error Console, the key should be identical to the property of
- the same name in browser.dtd.
-->
<!ENTITY errorConsoleCmd.commandkey "j">
<!ENTITY webConsoleCmd.label "Web Console">
<!ENTITY webConsoleCmd.accesskey "W">
<!-- LOCALIZATION NOTE (webConsoleCmd.commandkey): This command key launches
- the browser WebConsole, the key should be identical to the property of
- the same name in browser.dtd.
-->
<!ENTITY webConsoleCmd.commandkey "k">

View File

@ -33,3 +33,7 @@ saveFile.failed=The file save operation failed.
# how to use the Scratchpad. Note that this should be a valid JavaScript
# comment inside /* and */.
scratchpadIntro=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaScript, then Right Click or choose from the Execute Menu:\n * 1. Run to evaluate the selected text,\n * 2. Inspect to bring up an Object Inspector on the result, or,\n * 3. Display to insert the result in a comment after the selection.\n */\n\n
# LOCALIZATION NOTE (notification.browserContext): This is the message displayed
# over the top of the editor when the user has switched to browser context.
browserContext.notification=This scratchpad executes in the Browser context.

View File

@ -0,0 +1,174 @@
typeError=Error:
typeWarning=Warning:
typeNetwork=Network:
typeException=Exception:
typeCssParser=CSS Parser:
typeStrict=Strict Warning:
msgCategory=Category:
errLine=Line: %S
btnHide=Hide
btnPrefs=Preferences
categoryPage=Page:
categoryConsole=Console:
btnMutation=DOM Mutation
tipMutation=Toggle DOM Mutation event logging
btnPageNet=Net
tipPageNet=Log network access
btnPageCSS=CSS
tipPageCSS=Log CSS parsing errors
btnPageJS=JS
tipPageJS=Log JavaScript exceptions
# LOCALIZATION NOTE (btnPageWebDeveloper):
#
# This is used as the text of the "Web Developer" button on the toolbar. It
# shows or hides messages that the web developer inserted on the page for
# debugging purposes, using calls such console.log() and console.error(). You
# may wish to localize this as "Page" if that is clearer in your locale. See
# bug 601667 for more information.
btnPageWebDeveloper=Web Developer
# LOCALIZATION NOTE (tipPageWebDeveloper):
#
# This is used as the text of the tool tip for the "Web Developer" button on
# the toolbar.
tipPageWebDeveloper=Log messages sent to the "console" object
btnConsoleErrors=Errors
tipConsoleErrors=Log calls to console.error()
btnConsoleInfo=Info
tipConsoleInfo=Log calls to console.info()
btnConsoleWarnings=Warnings
tipConsoleWarnings=Log calls to console.warn()
btnConsoleLog=Log
tipConsoleLog=Log calls to console.log()
btnGlobal=Global Messages
tipGlobal=Toggle Global Message logging
localConsole=Local Console
clearConsoleCmd.label=Clear Console
clearConsoleCmd.accesskey=e
# LOCALIZATION NOTE (btnClear):
#
# This is used as the text of the "Clear" button for the toolbar. It clears the
# contents of the console.
btnClear=Clear
stringFilter=Filter
close.button=Close
close.accesskey=C
update.button=Update
update.accesskey=U
# LOCALIZATION NOTE FOR `jsPropertyTitle` AND `jsPropertyInspectTitle`:
#
# The "PropertyPanel" is used to display a JS object to the user.
# If it is clear which object is being inspected (e.g., window, document object)
# the title of the panel is based on the `jsPropertyInspectTitle` string.
# If it isn't clear which object is being inspected, the `jsPropertyTitle` string
# gets used. This can be the case when the user logs an object to the WebConsole
# output using the console.log(aObjectToInspect) method.
#
# You can find a screenshot of the PropertyPanel here:
# https://bug585030.bugzilla.mozilla.org/attachment.cgi?id=464034
jsPropertyTitle=Object Inspector
# LOCALIZATION NOTE (jsPropertyInspectTitle):
#
# The %S is replaced by the evaluated code the user clicked on in the console.
#
# Example: The user executed `window.document` in the WebConsole. The `document`
# object is written to the output. If the user clicks on the `document` output
# in the console, a PropertyPanel will show up. The title of the PropertyPanel
# is set to `Inspect: window.document` because the clicked `document` object was
# evaluated based on the `window.document` string.
jsPropertyInspectTitle=Inspect: %S
saveBodies.label=Log Request and Response Bodies
saveBodies.accesskey=L
copyCmd.label=Copy
copyCmd.accesskey=C
selectAllCmd.label=Select All
selectAllCmd.accesskey=A
# LOCALIZATION NOTE (timestampFormat): %1$02S = hours (24-hour clock),
# %2$02S = minutes, %3$02S = seconds, %4$03S = milliseconds.
timestampFormat=%02S:%02S:%02S.%03S
helperFuncUnsupportedTypeError=Can't call pprint on this type of object.
NetworkPanel.label=Inspect Network Request
# LOCALIZATION NOTE (NetworkPanel.deltaDurationMS):
#
# This string is used to show the duration between two network events (e.g
# request and respones header or response header and response body).
NetworkPanel.durationMS=%Sms
# LOCALIZATION NOTE (NetworkPanel.imageSizeDeltaDurationMS):
# This string is used to show the duration between the response header and the
# response body event. It also shows the size of the received or cached image.
#
# The first %S is replace by the width of the inspected image.
# The second %S is replaced by the height of the inspected image.
# The third %S is replaced by the duration between the response header and the
# response body event.
NetworkPanel.imageSizeDeltaDurationMS=%Sx%Spx, Δ%Sms
# LOCALIZATION NOTE (NetworkPanel.responseBodyUnableToDisplay.content):
#
# This string is displayed within the response body section of the NetworkPanel
# if the content type of the network request can't be displayed in the
# NetworkPanel. E.g. any kind of text is easy to display, but some audio or
# flash data received from the server can't be displayed.
#
# The %S is replaced by the content type, that can't be displayed, examples are
# o application/x-shockwave-flash
# o music/crescendo
NetworkPanel.responseBodyUnableToDisplay.content=Unable to display responses of type "%S"
ConsoleAPIDisabled=The Web Console logging API (console.log, console.info, console.warn, console.error) has been disabled by a script on this page.
# LOCALIZATION NOTE (inspectStyle.nullObjectPassed):
# This message is returned when a null object is passed in to inspectstyle()
inspectStyle.nullObjectPassed=Object is null
# LOCALIZATION NOTE (inspectStyle.mustBeDomNode):
# This message is returned when a non-DOM node is passed in to inspectstyle()
inspectStyle.mustBeDomNode=Object must be a valid DOM node
# LOCALIZATION NOTE (inspectStyle.nodeHasNoStyleProps):
# This message is returned when an unstyleable object is passed in to inspectstyle()
inspectStyle.nodeHasNoStyleProps=Object cannot be styled
# LOCALIZATION NOTE (inspectStyle.styleInspectorNotEnabled):
# This message is returned when devtools.styleinspector.enabled is not set to
# true
inspectStyle.styleInspectorNotEnabled=The style inspector is not enabled. Please set the option devtools.styleinspector.enabled to true in about:config to use this command.
# LOCALIZATION NOTE (webConsolePosition): The label shown for the menu which
# allows the user to toggle between the Web Console positioning types.
webConsolePosition=Position
# LOCALIZATION NOTE (webConsolePositionTooltip): The tooltip shown when the user
# hovers the Position button in the Web Console toolbar.
webConsolePositionTooltip=Position the Web Console above or below the document
# LOCALIZATION NOTE (webConsolePositionAbove): When this option is selected the
# Web Console interface is displayed above the web page.
webConsolePositionAbove=Above
# LOCALIZATION NOTE (webConsolePositionBelow): When this option is selected the
# Web Console interface is displayed below the web page.
webConsolePositionBelow=Below
# LOCALIZATION NOTE (webConsolePositionWindow): When this option is selected the
# Web Console interface is displayed in a floating panel.
webConsolePositionWindow=Window
# LOCALIZATION NOTE (webConsoleWindowTitleAndURL): The Web Console floating
# panel title, followed by the web page URL.
# For RTL languages you need to set the LRM in the string to give the URL
# the correct direction.
webConsoleWindowTitleAndURL=Web Console - %S
# LOCALIZATION NOTE (Autocomplete.label):
# The autocomplete popup panel label/title.
Autocomplete.label=Autocomplete popup
# LOCALIZATION NOTE (stacktrace.anonymousFunction):
# This string is used to display JavaScript functions that have no given name -
# they are said to be anonymous. See stacktrace.outputMessage.
stacktrace.anonymousFunction=<anonymous>
# LOCALIZATION NOTE (stacktrace.outputMessage):
# This string is used in the Web Console output to identify a web developer call
# to console.trace(). The stack trace of JavaScript function calls is displayed.
# In this minimal message we only show the last call.
stacktrace.outputMessage=Stack trace from %S, function %S, line %S.

View File

@ -15,13 +15,15 @@
* locale/browser/browser.dtd (%chrome/browser/browser.dtd)
locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd)
locale/browser/browser.properties (%chrome/browser/browser.properties)
locale/browser/devtools/gcli.properties (%chrome/browser/devtools/gcli.properties)
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
locale/browser/styleinspector.properties (%chrome/browser/styleinspector.properties)
locale/browser/styleinspector.dtd (%chrome/browser/styleinspector.dtd)
locale/browser/scratchpad.properties (%chrome/browser/scratchpad.properties)
locale/browser/scratchpad.dtd (%chrome/browser/scratchpad.dtd)
locale/browser/inspector.properties (%chrome/browser/inspector.properties)
locale/browser/devtools/gcli.properties (%chrome/browser/devtools/gcli.properties)
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
locale/browser/devtools/webconsole.properties (%chrome/browser/devtools/webconsole.properties)
locale/browser/devtools/inspector.properties (%chrome/browser/devtools/inspector.properties)
locale/browser/devtools/scratchpad.properties (%chrome/browser/devtools/scratchpad.properties)
locale/browser/devtools/scratchpad.dtd (%chrome/browser/devtools/scratchpad.dtd)
locale/browser/devtools/styleinspector.properties (%chrome/browser/devtools/styleinspector.properties)
locale/browser/devtools/styleinspector.dtd (%chrome/browser/devtools/styleinspector.dtd)
locale/browser/devtools/webConsole.dtd (%chrome/browser/devtools/webConsole.dtd)
locale/browser/openLocation.dtd (%chrome/browser/openLocation.dtd)
locale/browser/openLocation.properties (%chrome/browser/openLocation.properties)
* locale/browser/pageInfo.dtd (%chrome/browser/pageInfo.dtd)

View File

@ -1954,7 +1954,7 @@ panel[dimmed="true"] {
#inspector-toolbar {
-moz-appearance: none;
padding: 4px 3px;
padding: 0 3px 4px;
border-top: 1px solid hsla(210, 8%, 5%, .65);
box-shadow: 0 1px 0 0 hsla(210, 16%, 76%, .2) inset;
background-image: -moz-linear-gradient(top, hsl(210,11%,36%), hsl(210,11%,18%));
@ -1998,15 +1998,35 @@ panel[dimmed="true"] {
background-color: hsla(210,8%,5%,.2) !important;
}
/*
* need a "bumpy" background image for this!
*/
#inspector-horizontal-splitter {
background: none !important;
/* Highlighter - toolbar resizers */
.inspector-resizer {
-moz-appearance: none;
cursor: n-resize;
}
.inspector-resizer[disabled] {
visibility: hidden;
}
#inspector-top-resizer {
background: none;
height: 4px;
}
#inspector-end-resizer {
width: 12px;
height: 8px;
background-image: -moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px);
background-size: 10px 2px;
background-clip: padding-box;
background-repeat: repeat-y;
border-width: 1px 1px 0;
border-style: solid;
border-color: rgba(255, 255, 255, 0.05);
margin: 7px 7px 8px;
}
/* Highlighter - Node Infobar */
/* Highlighter - Node Infobar - text */
@ -2066,3 +2086,161 @@ panel[dimmed="true"] {
#highlighter-nodeinfobar-container[hide-arrow] > #highlighter-nodeinfobar {
margin: 7px 0;
}
/* Highlighter toolbar - breadcrumbs */
#inspector-breadcrumbs {
padding: 0 6px;
/* A fake 1px-shadow is included in the border-images of the
inspector-breadcrumbs-buttons, to match toolbar-buttons style.
This negative margin compensate the extra row of pixels created
by the shadow.*/
margin-bottom: -1px;
}
.inspector-breadcrumbs-button {
-moz-appearance: none;
background-color: transparent;
border-width: 1px 13px 2px 13px;
color: hsl(210,30%,85%);
max-width: 85px;
/* The content of the button can be larger than the button */
overflow: hidden;
min-height: 25px;
margin: 0 -11px 0 0;
padding: 0 9px;
}
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-tag {
color: hsl(208,100%,60%);
}
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-id {
color: hsl(205,100%,70%);
}
.inspector-breadcrumbs-id,
.inspector-breadcrumbs-classes {
color: #8d99a6;
}
/* Highlighter toolbar - breadcrumbs - LTR */
.inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
margin-left: 0;
}
.inspector-breadcrumbs-button {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:not([checked]),
.inspector-breadcrumbs-button:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked][siblings-menu-open],
.inspector-breadcrumbs-button[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]),
.inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked],
.inspector-breadcrumbs-button:first-of-type[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]),
.inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked],
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 stretch;
}
/* Highlighter toolbar - breadcrumbs - RTL */
.inspector-breadcrumbs-button:-moz-locale-dir(rtl):first-of-type {
margin-right: 0;
}
.inspector-breadcrumbs-button:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked][siblings-menu-open]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:first-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 stretch;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

View File

@ -87,6 +87,31 @@ browser.jar:
skin/classic/browser/devtools/search.png (devtools/search.png)
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end.png (devtools/breadcrumbs/ltr-end.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png (devtools/breadcrumbs/ltr-middle-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png (devtools/breadcrumbs/ltr-middle-selected.png)
skin/classic/browser/devtools/breadcrumbs/ltr-middle.png (devtools/breadcrumbs/ltr-middle.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-pressed.png (devtools/breadcrumbs/ltr-start-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-selected-pressed.png (devtools/breadcrumbs/ltr-start-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start.png (devtools/breadcrumbs/ltr-start.png)
skin/classic/browser/devtools/breadcrumbs/ltr-start-selected.png (devtools/breadcrumbs/ltr-start-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-pressed.png (devtools/breadcrumbs/rtl-end-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-selected-pressed.png (devtools/breadcrumbs/rtl-end-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end-selected.png (devtools/breadcrumbs/rtl-end-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-end.png (devtools/breadcrumbs/rtl-end.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-pressed.png (devtools/breadcrumbs/rtl-middle-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-selected-pressed.png (devtools/breadcrumbs/rtl-middle-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle-selected.png (devtools/breadcrumbs/rtl-middle-selected.png)
skin/classic/browser/devtools/breadcrumbs/rtl-middle.png (devtools/breadcrumbs/rtl-middle.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-pressed.png (devtools/breadcrumbs/rtl-start-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected-pressed.png (devtools/breadcrumbs/rtl-start-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start.png (devtools/breadcrumbs/rtl-start.png)
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16-throbber.png
skin/classic/browser/sync-16.png

View File

@ -2549,7 +2549,7 @@ panel[dimmed="true"] {
#inspector-toolbar {
-moz-appearance: none;
padding: 4px 3px;
padding: 0 3px 4px;
border-top: 1px solid hsla(210, 8%, 5%, .65);
box-shadow: 0 1px 0 0 hsla(210, 16%, 76%, .2) inset;
background-image: -moz-linear-gradient(top, hsl(210,11%,36%), hsl(210,11%,18%));
@ -2593,15 +2593,35 @@ panel[dimmed="true"] {
background-color: hsla(210,8%,5%,.2);
}
/*
* need a "bumpy" background image for this!
*/
#inspector-horizontal-splitter {
background: none !important;
/* Highlighter - toolbar resizers */
.inspector-resizer {
-moz-appearance: none;
cursor: n-resize;
}
.inspector-resizer[disabled] {
visibility: hidden;
}
#inspector-top-resizer {
background: none;
height: 4px;
}
#inspector-end-resizer {
width: 12px;
height: 8px;
background-image: -moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px);
background-size: 10px 2px;
background-clip: padding-box;
background-repeat: repeat-y;
border-width: 1px 1px 0;
border-style: solid;
border-color: rgba(255, 255, 255, 0.05);
margin: 7px 7px 8px;
}
/* Highlighter - Node Infobar */
/* Highlighter - Node Infobar - text */
@ -2661,3 +2681,160 @@ panel[dimmed="true"] {
#highlighter-nodeinfobar-container[hide-arrow] > #highlighter-nodeinfobar {
margin: 7px 0;
}
/* Highlighter toolbar - breadcrumbs */
#inspector-breadcrumbs {
padding: 0 6px;
/* A fake 1px-shadow is included in the border-images of the
inspector-breadcrumbs-buttons, to match toolbar-buttons style.
This negative margin compensate the extra row of pixels created
by the shadow.*/
margin-bottom: -1px;
}
.inspector-breadcrumbs-button {
-moz-appearance: none;
border-width: 1px 13px 2px 13px;
color: hsl(210,30%,85%);
max-width: 85px;
/* The content of the button can be larger than the button */
overflow: hidden;
min-height: 25px;
margin: 0 -11px 0 0;
padding: 0 9px;
}
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-tag {
color: hsl(208,100%,60%);
}
.inspector-breadcrumbs-button[checked] > .inspector-breadcrumbs-id {
color: hsl(205,100%,70%);
}
.inspector-breadcrumbs-id,
.inspector-breadcrumbs-classes {
color: #8d99a6;
}
/* Highlighter toolbar - breadcrumbs - LTR */
.inspector-breadcrumbs-button:-moz-locale-dir(ltr):first-of-type {
margin-left: 0;
}
.inspector-breadcrumbs-button {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:not([checked]),
.inspector-breadcrumbs-button:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked][siblings-menu-open],
.inspector-breadcrumbs-button[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-middle-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]),
.inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked],
.inspector-breadcrumbs-button:first-of-type[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-start-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]),
.inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type[checked] {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked],
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/ltr-end-selected-pressed.png") 1 13 2 13 stretch;
}
/* Highlighter toolbar - breadcrumbs - RTL */
.inspector-breadcrumbs-button:-moz-locale-dir(rtl):first-of-type {
margin-right: 0;
}
.inspector-breadcrumbs-button:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[checked][siblings-menu-open]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-middle-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:first-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:first-of-type[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:first-of-type[checked]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:first-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-start-selected-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type:not([checked]):-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:last-of-type:not([checked]):hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-pressed.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button:last-of-type[checked]:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected.png") 1 13 2 13 stretch;
}
.inspector-breadcrumbs-button[siblings-menu-open]:last-of-type[checked]:-moz-locale-dir(rtl),
.inspector-breadcrumbs-button:last-of-type[checked]:hover:active:-moz-locale-dir(rtl) {
-moz-border-image: url("chrome://browser/skin/devtools/breadcrumbs/rtl-end-selected-pressed.png") 1 13 2 13 stretch;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

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