Merge mozilla-central to mozilla-inbound
@ -1048,10 +1048,12 @@ pref("devtools.debugger.remote-autoconnect", false);
|
||||
pref("devtools.debugger.remote-connection-retries", 3);
|
||||
pref("devtools.debugger.remote-timeout", 3000);
|
||||
|
||||
// The default Debugger UI height
|
||||
// The default Debugger UI settings
|
||||
pref("devtools.debugger.ui.height", 250);
|
||||
pref("devtools.debugger.ui.remote-win.width", 900);
|
||||
pref("devtools.debugger.ui.remote-win.height", 400);
|
||||
pref("devtools.debugger.ui.stackframes-width", 200);
|
||||
pref("devtools.debugger.ui.variables-width", 300);
|
||||
|
||||
// Enable the style inspector
|
||||
pref("devtools.styleinspector.enabled", true);
|
||||
|
@ -552,3 +552,16 @@ statuspanel[inactive][previoustype=overLink] {
|
||||
|
||||
/* highlighter */
|
||||
%include highlighter.css
|
||||
|
||||
html|*#gcli-tooltip-frame,
|
||||
html|*#gcli-output-frame,
|
||||
#gcli-output,
|
||||
#gcli-tooltip {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node,
|
||||
.gclitoolbar-complete-node,
|
||||
.gclitoolbar-prompt {
|
||||
direction: ltr;
|
||||
}
|
||||
|
@ -1034,8 +1034,10 @@
|
||||
tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
|
||||
#endif
|
||||
<stack class="gclitoolbar-stack-node" flex="1">
|
||||
<description class="gclitoolbar-prompt">»</description>
|
||||
<description class="gclitoolbar-complete-node"/>
|
||||
<hbox class="gclitoolbar-prompt">
|
||||
<label class="gclitoolbar-prompt-label">»</label>
|
||||
</hbox>
|
||||
<hbox class="gclitoolbar-complete-node"/>
|
||||
<textbox class="gclitoolbar-input-node" rows="1"/>
|
||||
</stack>
|
||||
<toolbarbutton id="developer-toolbar-webconsole"
|
||||
|
@ -5,10 +5,23 @@
|
||||
|
||||
let EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
Components.utils.import("resource:///modules/devtools/gcli.jsm");
|
||||
Components.utils.import("resource:///modules/HUDService.jsm");
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
Cu.import("resource:///modules/devtools/gcli.jsm");
|
||||
Cu.import("resource:///modules/HUDService.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
Components.utils.import("resource:///modules/devtools/GcliTiltCommands.jsm", {});
|
||||
Cu.import("resource:///modules/devtools/GcliTiltCommands.jsm", {});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "Services", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource://gre/modules/Services.jsm", obj);
|
||||
return obj.Services;
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, "LayoutHelpers", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", obj);
|
||||
return obj.LayoutHelpers;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
@ -31,6 +44,129 @@ gcli.addCommand({
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'screenshot' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "screenshot",
|
||||
description: gcli.lookup("screenshotDesc"),
|
||||
manual: gcli.lookup("screenshotManual"),
|
||||
returnType: "string",
|
||||
params: [
|
||||
{
|
||||
name: "filename",
|
||||
type: "string",
|
||||
description: gcli.lookup("screenshotFilenameDesc"),
|
||||
manual: gcli.lookup("screenshotFilenameManual")
|
||||
},
|
||||
{
|
||||
name: "delay",
|
||||
type: { name: "number", min: 0 },
|
||||
defaultValue: 0,
|
||||
description: gcli.lookup("screenshotDelayDesc"),
|
||||
manual: gcli.lookup("screenshotDelayManual")
|
||||
},
|
||||
{
|
||||
name: "fullpage",
|
||||
type: "boolean",
|
||||
defaultValue: false,
|
||||
description: gcli.lookup("screenshotFullPageDesc"),
|
||||
manual: gcli.lookup("screenshotFullPageManual")
|
||||
},
|
||||
{
|
||||
name: "node",
|
||||
type: "node",
|
||||
defaultValue: null,
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function Command_screenshot(args, context) {
|
||||
var document = context.environment.contentDocument;
|
||||
if (args.delay > 0) {
|
||||
var promise = context.createPromise();
|
||||
document.defaultView.setTimeout(function Command_screenshotDelay() {
|
||||
let reply = this.grabScreen(document, args.filename);
|
||||
promise.resolve(reply);
|
||||
}.bind(this), args.delay * 1000);
|
||||
return promise;
|
||||
}
|
||||
else {
|
||||
return this.grabScreen(document, args.filename, args.fullpage, args.node);
|
||||
}
|
||||
},
|
||||
grabScreen:
|
||||
function Command_screenshotGrabScreen(document, filename, fullpage, node) {
|
||||
let window = document.defaultView;
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let width;
|
||||
let height;
|
||||
|
||||
if (!fullpage) {
|
||||
if (!node) {
|
||||
left = window.scrollX;
|
||||
top = window.scrollY;
|
||||
width = window.innerWidth;
|
||||
height = window.innerHeight;
|
||||
} else {
|
||||
let rect = LayoutHelpers.getRect(node, window);
|
||||
top = rect.top;
|
||||
left = rect.left;
|
||||
width = rect.width;
|
||||
height = rect.height;
|
||||
}
|
||||
} else {
|
||||
width = window.innerWidth + window.scrollMaxX;
|
||||
height = window.innerHeight + window.scrollMaxY;
|
||||
}
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawWindow(window, left, top, width, height, "#fff");
|
||||
|
||||
let data = canvas.toDataURL("image/png", "");
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
|
||||
// Check there is a .png extension to filename
|
||||
if (!filename.match(/.png$/i)) {
|
||||
filename += ".png";
|
||||
}
|
||||
|
||||
// If the filename is relative, tack it onto the download directory
|
||||
if (!filename.match(/[\\\/]/)) {
|
||||
let downloadMgr = Cc["@mozilla.org/download-manager;1"]
|
||||
.getService(Ci.nsIDownloadManager);
|
||||
let tempfile = downloadMgr.userDownloadsDirectory;
|
||||
tempfile.append(filename);
|
||||
filename = tempfile.path;
|
||||
}
|
||||
|
||||
try {
|
||||
file.initWithPath(filename);
|
||||
} catch (ex) {
|
||||
return "Error saving to " + filename;
|
||||
}
|
||||
|
||||
let ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
let Persist = Ci.nsIWebBrowserPersist;
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
||||
.createInstance(Persist);
|
||||
persist.persistFlags = Persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
Persist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
let source = ioService.newURI(data, "UTF8", null);
|
||||
persist.saveURI(source, null, null, null, null, file);
|
||||
|
||||
return "Saved to " + filename;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'console' command
|
||||
*/
|
||||
@ -51,13 +187,13 @@ gcli.addCommand({
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
|
||||
// Use a timeout so we also clear the reporting of the clear command
|
||||
let threadManager = Components.classes["@mozilla.org/thread-manager;1"]
|
||||
.getService(Components.interfaces.nsIThreadManager);
|
||||
let threadManager = Cc["@mozilla.org/thread-manager;1"]
|
||||
.getService(Ci.nsIThreadManager);
|
||||
threadManager.mainThread.dispatch({
|
||||
run: function() {
|
||||
hud.gcliterm.clearOutput();
|
||||
}
|
||||
}, Components.interfaces.nsIThread.DISPATCH_NORMAL);
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
});
|
||||
|
||||
@ -135,9 +271,8 @@ gcli.addCommand({
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
let StyleEditor = hud.gcliterm.document.defaultView.StyleEditor;
|
||||
StyleEditor.openChrome(args.resource.element, args.line);
|
||||
let win = HUDService.currentContext();
|
||||
win.StyleEditor.openChrome(args.resource.element, args.line);
|
||||
}
|
||||
});
|
||||
|
||||
@ -160,7 +295,7 @@ gcli.addCommand({
|
||||
returnType: "html",
|
||||
exec: function(args, context) {
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let dbg = win.DebuggerUI.getDebugger();
|
||||
if (!dbg) {
|
||||
return gcli.lookup("breakaddDebuggerStopped");
|
||||
}
|
||||
@ -206,7 +341,7 @@ gcli.addCommand({
|
||||
name: "selection",
|
||||
data: function() {
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let dbg = win.DebuggerUI.getDebugger();
|
||||
let files = [];
|
||||
if (dbg) {
|
||||
let scriptsView = dbg.contentWindow.DebuggerView.Scripts;
|
||||
@ -229,7 +364,7 @@ gcli.addCommand({
|
||||
exec: function(args, context) {
|
||||
args.type = "line";
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let dbg = win.DebuggerUI.getDebugger();
|
||||
if (!dbg) {
|
||||
return gcli.lookup("breakaddDebuggerStopped");
|
||||
}
|
||||
@ -261,7 +396,7 @@ gcli.addCommand({
|
||||
min: 0,
|
||||
max: function() {
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let dbg = win.DebuggerUI.getDebugger();
|
||||
if (!dbg) {
|
||||
return gcli.lookup("breakaddDebuggerStopped");
|
||||
}
|
||||
@ -274,7 +409,7 @@ gcli.addCommand({
|
||||
returnType: "html",
|
||||
exec: function(args, context) {
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let dbg = win.DebuggerUI.getDebugger();
|
||||
if (!dbg) {
|
||||
return gcli.lookup("breakaddDebuggerStopped");
|
||||
}
|
||||
|
@ -2,23 +2,17 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.gclichrome-output {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.gclichrome-tooltip {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.gcli-help-name {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut:before,
|
||||
.gcli-help-synopsis:before {
|
||||
content: '\bb';
|
||||
}
|
||||
@ -34,8 +28,9 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gcli-menu-error {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
.gcli-menu-name,
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
|
@ -4157,7 +4157,7 @@ var ResourceCache = {
|
||||
* Drop all cache entries. Helpful to prevent memory leaks
|
||||
*/
|
||||
clear: function() {
|
||||
ResourceCache._cached = {};
|
||||
ResourceCache._cached = [];
|
||||
}
|
||||
};
|
||||
|
||||
@ -8082,7 +8082,7 @@ define("text!gcli/commands/help_list.html", [], "\n" +
|
||||
" <tr foreach=\"command in ${getMatchingCommands()}\"\n" +
|
||||
" onclick=\"${onclick}\" ondblclick=\"${ondblclick}\">\n" +
|
||||
" <th class=\"gcli-help-name\">${command.name}</th>\n" +
|
||||
" <td class=\"gcli-help-arrow\">→</td>\n" +
|
||||
" <td class=\"gcli-help-arrow\">-</td>\n" +
|
||||
" <td>\n" +
|
||||
" ${command.description}\n" +
|
||||
" <span class=\"gcli-out-shortcut\" data-command=\"help ${command.name}\">help ${command.name}</span>\n" +
|
||||
|
@ -15,6 +15,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_gcli_break.js \
|
||||
browser_gcli_commands.js \
|
||||
browser_gcli_edit.js \
|
||||
browser_gcli_inspect.js \
|
||||
browser_gcli_integrate.js \
|
||||
browser_gcli_pref.js \
|
||||
@ -26,6 +27,10 @@ _BROWSER_TEST_FILES = \
|
||||
_BROWSER_TEST_PAGES = \
|
||||
browser_gcli_break.html \
|
||||
browser_gcli_inspect.html \
|
||||
resources_inpage.js \
|
||||
resources_inpage1.css \
|
||||
resources_inpage2.css \
|
||||
resources.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
145
browser/devtools/commandline/test/browser_gcli_edit.js
Normal file
@ -0,0 +1,145 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the edit command works
|
||||
|
||||
const TEST_URI = TEST_BASE_HTTP + "resources.html";
|
||||
|
||||
function test() {
|
||||
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
|
||||
testEditStatus(browser, tab);
|
||||
// Bug 759853
|
||||
// testEditExec(browser, tab); // calls finish()
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function testEditStatus(browser, tab) {
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit",
|
||||
markup: "VVVV",
|
||||
status: "ERROR",
|
||||
emptyParameters: [ " <resource>", " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit i",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
directTabText: "nline-css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit c",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
directTabText: "ss#style2",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit http",
|
||||
markup: "VVVVVIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "://example.com/browser/browser/devtools/commandline/test/resources_inpage1.css",
|
||||
arrowTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit page1",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "http://example.com/browser/browser/devtools/commandline/test/resources_inpage1.css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit page2",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "http://example.com/browser/browser/devtools/commandline/test/resources_inpage2.css",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit stylez",
|
||||
markup: "VVVVVEEEEEE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
arrowTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2",
|
||||
markup: "VVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
directTabText: "",
|
||||
emptyParameters: [ " [line]" ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 5",
|
||||
markup: "VVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 0",
|
||||
markup: "VVVVVVVVVVVVVVVVE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "edit css#style2 -1",
|
||||
markup: "VVVVVVVVVVVVVVVVEE",
|
||||
status: "ERROR",
|
||||
directTabText: "",
|
||||
emptyParameters: [ ],
|
||||
});
|
||||
}
|
||||
|
||||
var windowListener = {
|
||||
onOpenWindow: function(win) {
|
||||
// Wait for the window to finish loading
|
||||
let win = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
win.close();
|
||||
}, false);
|
||||
win.addEventListener("unload", function onUnload() {
|
||||
win.removeEventListener("unload", onUnload, false);
|
||||
Services.wm.removeListener(windowListener);
|
||||
finish();
|
||||
}, false);
|
||||
},
|
||||
onCloseWindow: function(win) { },
|
||||
onWindowTitleChange: function(win, title) { }
|
||||
};
|
||||
|
||||
function testEditExec(browser, tab) {
|
||||
|
||||
Services.wm.addListener(windowListener);
|
||||
|
||||
var style2 = browser.contentDocument.getElementById("style2");
|
||||
DeveloperToolbarTest.exec({
|
||||
typed: "edit css#style2",
|
||||
args: {
|
||||
resource: function(resource) {
|
||||
return resource.element.ownerNode == style2;
|
||||
},
|
||||
line: 1
|
||||
},
|
||||
completed: true,
|
||||
blankOutput: true,
|
||||
});
|
||||
}
|
@ -95,7 +95,7 @@ function testPrefStatus() {
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "pref show devtools.toolbar.ena",
|
||||
markup: "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
|
||||
markup: "VVVVVVVVVVIIIIIIIIIIIIIIIIIIII",
|
||||
directTabText: "bled",
|
||||
status: "ERROR",
|
||||
emptyParameters: [ ]
|
||||
@ -103,7 +103,7 @@ function testPrefStatus() {
|
||||
|
||||
DeveloperToolbarTest.checkInputStatus({
|
||||
typed: "pref show hideIntro",
|
||||
markup: "VVVVVVVVVVVVVVVVVVV",
|
||||
markup: "VVVVVVVVVVIIIIIIIII",
|
||||
directTabText: "",
|
||||
arrowTabText: "devtools.gcli.hideIntro",
|
||||
status: "ERROR",
|
||||
|
@ -2,6 +2,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/commandline/test/";
|
||||
const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/commandline/test/";
|
||||
|
||||
let console = (function() {
|
||||
let tempScope = {};
|
||||
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
|
||||
@ -83,57 +86,69 @@ let DeveloperToolbarTest = {
|
||||
* emptyParameters: [ "<message>" ], // Still to type
|
||||
* directTabText: "o", // Simple completion text
|
||||
* arrowTabText: "", // When the completion is not an extension
|
||||
* markup: "VVVIIIEEE", // What state should the error markup be in
|
||||
* });
|
||||
*/
|
||||
checkInputStatus: function DTT_checkInputStatus(test) {
|
||||
if (test.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(test.typed);
|
||||
checkInputStatus: function DTT_checkInputStatus(tests) {
|
||||
let display = DeveloperToolbar.display;
|
||||
|
||||
if (tests.typed) {
|
||||
display.inputter.setInput(tests.typed);
|
||||
}
|
||||
else {
|
||||
ok(false, "Missing typed for " + JSON.stringify(test));
|
||||
return;
|
||||
ok(false, "Missing typed for " + JSON.stringify(tests));
|
||||
return;
|
||||
}
|
||||
|
||||
if (test.cursor) {
|
||||
DeveloperToolbar.display.inputter.setCursor(test.cursor)
|
||||
if (tests.cursor) {
|
||||
display.inputter.setCursor(tests.cursor)
|
||||
}
|
||||
|
||||
if (test.status) {
|
||||
is(DeveloperToolbar.display.requisition.getStatus().toString(),
|
||||
test.status,
|
||||
"status for " + test.typed);
|
||||
if (tests.status) {
|
||||
is(display.requisition.getStatus().toString(),
|
||||
tests.status, "status for " + tests.typed);
|
||||
}
|
||||
|
||||
if (test.emptyParameters == null) {
|
||||
test.emptyParameters = [];
|
||||
if (tests.emptyParameters == null) {
|
||||
tests.emptyParameters = [];
|
||||
}
|
||||
|
||||
let completer = DeveloperToolbar.display.completer;
|
||||
let realParams = completer.emptyParameters;
|
||||
is(realParams.length, test.emptyParameters.length,
|
||||
'emptyParameters.length for \'' + test.typed + '\'');
|
||||
let realParams = display.completer.emptyParameters;
|
||||
is(realParams.length, tests.emptyParameters.length,
|
||||
'emptyParameters.length for \'' + tests.typed + '\'');
|
||||
|
||||
if (realParams.length === test.emptyParameters.length) {
|
||||
if (realParams.length === tests.emptyParameters.length) {
|
||||
for (let i = 0; i < realParams.length; i++) {
|
||||
is(realParams[i].replace(/\u00a0/g, ' '), test.emptyParameters[i],
|
||||
'emptyParameters[' + i + '] for \'' + test.typed + '\'');
|
||||
is(realParams[i].replace(/\u00a0/g, ' '), tests.emptyParameters[i],
|
||||
'emptyParameters[' + i + '] for \'' + tests.typed + '\'');
|
||||
}
|
||||
}
|
||||
|
||||
if (test.directTabText) {
|
||||
is(completer.directTabText, test.directTabText,
|
||||
'directTabText for \'' + test.typed + '\'');
|
||||
if (tests.directTabText) {
|
||||
is(display.completer.directTabText, tests.directTabText,
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(completer.directTabText, '', 'directTabText for \'' + test.typed + '\'');
|
||||
is(display.completer.directTabText, '',
|
||||
'directTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
|
||||
if (test.arrowTabText) {
|
||||
is(completer.arrowTabText, ' \u00a0\u21E5 ' + test.arrowTabText,
|
||||
'arrowTabText for \'' + test.typed + '\'');
|
||||
if (tests.arrowTabText) {
|
||||
is(display.completer.arrowTabText, ' \u00a0\u21E5 ' + tests.arrowTabText,
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
else {
|
||||
is(completer.arrowTabText, '', 'arrowTabText for \'' + test.typed + '\'');
|
||||
is(display.completer.arrowTabText, '',
|
||||
'arrowTabText for \'' + tests.typed + '\'');
|
||||
}
|
||||
|
||||
if (tests.markup) {
|
||||
let cursor = tests.cursor ? tests.cursor.start : tests.typed.length;
|
||||
let statusMarkup = display.requisition.getInputStatusMarkup(cursor);
|
||||
let actualMarkup = statusMarkup.map(function(s) {
|
||||
return Array(s.string.length + 1).join(s.status.toString()[0]);
|
||||
}).join('');
|
||||
is(tests.markup, actualMarkup, 'markup for ' + tests.typed);
|
||||
}
|
||||
},
|
||||
|
||||
@ -151,11 +166,11 @@ let DeveloperToolbarTest = {
|
||||
* blankOutput: true, // Special checks when there is no output
|
||||
* });
|
||||
*/
|
||||
exec: function DTT_exec(test) {
|
||||
test = test || {};
|
||||
exec: function DTT_exec(tests) {
|
||||
tests = tests || {};
|
||||
|
||||
if (test.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(test.typed);
|
||||
if (tests.typed) {
|
||||
DeveloperToolbar.display.inputter.setInput(tests.typed);
|
||||
}
|
||||
|
||||
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
|
||||
@ -163,7 +178,7 @@ let DeveloperToolbarTest = {
|
||||
|
||||
is(typed, output.typed, 'output.command for: ' + typed);
|
||||
|
||||
if (test.completed !== false) {
|
||||
if (tests.completed !== false) {
|
||||
ok(output.completed, 'output.completed false for: ' + typed);
|
||||
}
|
||||
else {
|
||||
@ -172,36 +187,41 @@ let DeveloperToolbarTest = {
|
||||
// ok(!output.completed, 'output.completed true for: ' + typed);
|
||||
}
|
||||
|
||||
if (test.args != null) {
|
||||
is(Object.keys(test.args).length, Object.keys(output.args).length,
|
||||
if (tests.args != null) {
|
||||
is(Object.keys(tests.args).length, Object.keys(output.args).length,
|
||||
'arg count for ' + typed);
|
||||
|
||||
Object.keys(output.args).forEach(function(arg) {
|
||||
let expectedArg = test.args[arg];
|
||||
let expectedArg = tests.args[arg];
|
||||
let actualArg = output.args[arg];
|
||||
|
||||
if (Array.isArray(expectedArg)) {
|
||||
if (!Array.isArray(actualArg)) {
|
||||
ok(false, 'actual is not an array. ' + typed + '/' + arg);
|
||||
return;
|
||||
}
|
||||
|
||||
is(expectedArg.length, actualArg.length,
|
||||
'array length: ' + typed + '/' + arg);
|
||||
for (let i = 0; i < expectedArg.length; i++) {
|
||||
is(expectedArg[i], actualArg[i],
|
||||
'member: "' + typed + '/' + arg + '/' + i);
|
||||
}
|
||||
if (typeof expectedArg === 'function') {
|
||||
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
|
||||
}
|
||||
else {
|
||||
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
|
||||
if (Array.isArray(expectedArg)) {
|
||||
if (!Array.isArray(actualArg)) {
|
||||
ok(false, 'actual is not an array. ' + typed + '/' + arg);
|
||||
return;
|
||||
}
|
||||
|
||||
is(expectedArg.length, actualArg.length,
|
||||
'array length: ' + typed + '/' + arg);
|
||||
for (let i = 0; i < expectedArg.length; i++) {
|
||||
is(expectedArg[i], actualArg[i],
|
||||
'member: "' + typed + '/' + arg + '/' + i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let displayed = DeveloperToolbar.outputPanel._div.textContent;
|
||||
|
||||
if (test.outputMatch) {
|
||||
if (tests.outputMatch) {
|
||||
function doTest(match, against) {
|
||||
if (!match.test(against)) {
|
||||
ok(false, "html output for " + typed + " against " + match.source +
|
||||
@ -210,17 +230,17 @@ let DeveloperToolbarTest = {
|
||||
info(against);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(test.outputMatch)) {
|
||||
test.outputMatch.forEach(function(match) {
|
||||
if (Array.isArray(tests.outputMatch)) {
|
||||
tests.outputMatch.forEach(function(match) {
|
||||
doTest(match, displayed);
|
||||
});
|
||||
}
|
||||
else {
|
||||
doTest(test.outputMatch, displayed);
|
||||
doTest(tests.outputMatch, displayed);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.blankOutput != null) {
|
||||
if (tests.blankOutput != null) {
|
||||
if (!/^$/.test(displayed)) {
|
||||
ok(false, "html output for " + typed + " (textContent sent to info)");
|
||||
info("Actual textContent");
|
||||
@ -260,6 +280,8 @@ let DeveloperToolbarTest = {
|
||||
if (appMenuItem) {
|
||||
appMenuItem.hidden = true;
|
||||
}
|
||||
|
||||
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
|
||||
});
|
||||
|
||||
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
|
||||
@ -289,3 +311,158 @@ let DeveloperToolbarTest = {
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Memory leak hunter. Walks a tree of objects looking for DOM nodes.
|
||||
* Usage:
|
||||
* leakHunt({
|
||||
* thing: thing,
|
||||
* otherthing: otherthing
|
||||
* });
|
||||
*/
|
||||
|
||||
var noRecurse = [
|
||||
/^string$/, /^number$/, /^boolean$/, /^null/, /^undefined/,
|
||||
/^Window$/, /^Document$/,
|
||||
/^XULDocument$/, /^XULElement$/,
|
||||
/^DOMWindow$/, /^HTMLDocument$/, /^HTML.*Element$/
|
||||
];
|
||||
|
||||
var hide = [ /^string$/, /^number$/, /^boolean$/, /^null/, /^undefined/ ];
|
||||
|
||||
function leakHunt(root, path, seen) {
|
||||
path = path || [];
|
||||
seen = seen || [];
|
||||
|
||||
try {
|
||||
var output = leakHuntInner(root, path, seen);
|
||||
output.forEach(function(line) {
|
||||
dump(line + '\n');
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
dump(ex + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
function leakHuntInner(root, path, seen) {
|
||||
var prefix = new Array(path.length).join(' ');
|
||||
|
||||
var reply = [];
|
||||
function log(msg) {
|
||||
reply.push(msg);
|
||||
}
|
||||
|
||||
var direct
|
||||
try {
|
||||
direct = Object.keys(root);
|
||||
}
|
||||
catch (ex) {
|
||||
log(prefix + ' Error enumerating: ' + ex);
|
||||
return reply;
|
||||
}
|
||||
|
||||
for (var prop in root) {
|
||||
var newPath = path.slice();
|
||||
newPath.push(prop);
|
||||
prefix = new Array(newPath.length).join(' ');
|
||||
|
||||
var data;
|
||||
try {
|
||||
data = root[prop];
|
||||
}
|
||||
catch (ex) {
|
||||
log(prefix + prop + ' Error reading: ' + ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
var recurse = true;
|
||||
var message = getType(data);
|
||||
|
||||
if (matchesAnyPattern(message, hide)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message === 'function' && direct.indexOf(prop) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message === 'string') {
|
||||
var extra = data.length > 10 ? data.substring(0, 9) + '_' : data;
|
||||
message += ' "' + extra.replace(/\n/g, "|") + '"';
|
||||
recurse = false;
|
||||
}
|
||||
else if (matchesAnyPattern(message, noRecurse)) {
|
||||
message += ' (no recurse)'
|
||||
recurse = false;
|
||||
}
|
||||
else if (seen.indexOf(data) !== -1) {
|
||||
message += ' (already seen)';
|
||||
recurse = false;
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
seen.push(data);
|
||||
var lines = leakHuntInner(data, newPath, seen);
|
||||
if (lines.length == 0) {
|
||||
if (message !== 'function') {
|
||||
log(prefix + prop + ' = ' + message + ' { }');
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(prefix + prop + ' = ' + message + ' {');
|
||||
lines.forEach(function(line) {
|
||||
reply.push(line);
|
||||
});
|
||||
log(prefix + '}');
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(prefix + prop + ' = ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
function matchesAnyPattern(str, patterns) {
|
||||
var match = false;
|
||||
patterns.forEach(function(pattern) {
|
||||
if (str.match(pattern)) {
|
||||
match = true;
|
||||
}
|
||||
});
|
||||
return match;
|
||||
}
|
||||
|
||||
function getType(data) {
|
||||
if (data === null) {
|
||||
return 'null';
|
||||
}
|
||||
if (data === undefined) {
|
||||
return 'undefined';
|
||||
}
|
||||
|
||||
var type = typeof data;
|
||||
if (type === 'object' || type === 'Object') {
|
||||
type = getCtorName(data);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
function getCtorName(aObj) {
|
||||
try {
|
||||
if (aObj.constructor && aObj.constructor.name) {
|
||||
return aObj.constructor.name;
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
return 'UnknownObject';
|
||||
}
|
||||
|
||||
// If that fails, use Objects toString which sometimes gives something
|
||||
// better than 'Object', and at least defaults to Object if nothing better
|
||||
return Object.prototype.toString.call(aObj).slice(8, -1);
|
||||
}
|
||||
|
50
browser/devtools/commandline/test/resources.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Resources</title>
|
||||
<script type="text/javascript" id="script1">
|
||||
window.addEventListener('load', function() {
|
||||
var pid = document.getElementById('pid');
|
||||
var div = document.createElement('div');
|
||||
div.id = 'divid';
|
||||
div.classList.add('divclass');
|
||||
div.appendChild(document.createTextNode('div'));
|
||||
div.setAttribute('data-a1', 'div');
|
||||
pid.parentNode.appendChild(div);
|
||||
});
|
||||
</script>
|
||||
<script src="resources_inpage.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage1.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage2.css"/>
|
||||
<style type="text/css">
|
||||
p { color: #800; }
|
||||
div { color: #008; }
|
||||
h4 { color: #080; }
|
||||
h3 { color: #880; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<style type="text/css" id=style2>
|
||||
.pclass { background-color: #FEE; }
|
||||
.divclass { background-color: #EEF; }
|
||||
.h4class { background-color: #EFE; }
|
||||
.h3class { background-color: #FFE; }
|
||||
</style>
|
||||
|
||||
<p class="pclass" id="pid" data-a1="p">paragraph</p>
|
||||
|
||||
<script>
|
||||
var pid = document.getElementById('pid');
|
||||
var h4 = document.createElement('h4');
|
||||
h4.id = 'h4id';
|
||||
h4.classList.add('h4class');
|
||||
h4.appendChild(document.createTextNode('h4'));
|
||||
h4.setAttribute('data-a1', 'h4');
|
||||
pid.parentNode.appendChild(h4);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
12
browser/devtools/commandline/test/resources_inpage.js
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
// This script is used from within browser_gcli_edit.html
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var pid = document.getElementById('pid');
|
||||
var h3 = document.createElement('h3');
|
||||
h3.id = 'h3id';
|
||||
h3.classList.add('h3class');
|
||||
h3.appendChild(document.createTextNode('h3'));
|
||||
h3.setAttribute('data-a1', 'h3');
|
||||
pid.parentNode.appendChild(h3);
|
||||
});
|
11
browser/devtools/commandline/test/resources_inpage1.css
Normal file
@ -0,0 +1,11 @@
|
||||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#pid { border-top: 2px dotted #F00; }
|
||||
#divid { border-top: 2px dotted #00F; }
|
||||
#h4id { border-top: 2px dotted #0F0; }
|
||||
#h3id { border-top: 2px dotted #FF0; }
|
11
browser/devtools/commandline/test/resources_inpage2.css
Normal file
@ -0,0 +1,11 @@
|
||||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
*[data-a1=p] { border-left: 4px solid #F00; }
|
||||
*[data-a1=div] { border-left: 4px solid #00F; }
|
||||
*[data-a1=h4] { border-left: 4px solid #0F0; }
|
||||
*[data-a1=h3] { border-left: 4px solid #FF0; }
|
@ -12,6 +12,7 @@ const Cu = Components.utils;
|
||||
const DBG_XUL = "chrome://browser/content/debugger.xul";
|
||||
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const REMOTE_PROFILE_NAME = "_remote-debug";
|
||||
const TAB_SWITCH_NOTIFICATION = "debugger-tab-switch";
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -31,6 +32,7 @@ function DebuggerUI(aWindow) {
|
||||
}
|
||||
|
||||
DebuggerUI.prototype = {
|
||||
|
||||
/**
|
||||
* Called by the DebuggerPane to update the Debugger toggle switches with the
|
||||
* debugger state.
|
||||
@ -39,7 +41,7 @@ DebuggerUI.prototype = {
|
||||
let selectedTab = this.chromeWindow.getBrowser().selectedTab;
|
||||
let command = this.chromeWindow.document.getElementById("Tools:Debugger");
|
||||
|
||||
if (this.getDebugger(selectedTab) != null) {
|
||||
if (this.getDebugger()) {
|
||||
command.setAttribute("checked", "true");
|
||||
} else {
|
||||
command.removeAttribute("checked");
|
||||
@ -51,13 +53,18 @@ DebuggerUI.prototype = {
|
||||
* @return DebuggerPane if the debugger is started, null if it's stopped.
|
||||
*/
|
||||
toggleDebugger: function DUI_toggleDebugger() {
|
||||
let tab = this.chromeWindow.gBrowser.selectedTab;
|
||||
let scriptDebugger = this.getDebugger();
|
||||
let selectedTab = this.chromeWindow.gBrowser.selectedTab;
|
||||
|
||||
if (tab._scriptDebugger) {
|
||||
tab._scriptDebugger.close();
|
||||
if (scriptDebugger) {
|
||||
if (scriptDebugger.ownerTab !== selectedTab) {
|
||||
this.showTabSwitchNotification();
|
||||
return scriptDebugger;
|
||||
}
|
||||
scriptDebugger.close();
|
||||
return null;
|
||||
}
|
||||
return new DebuggerPane(this, tab);
|
||||
return new DebuggerPane(this, selectedTab);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -65,10 +72,10 @@ DebuggerUI.prototype = {
|
||||
* @return RemoteDebuggerWindow if the debugger is started, null if stopped.
|
||||
*/
|
||||
toggleRemoteDebugger: function DUI_toggleRemoteDebugger() {
|
||||
let win = this.chromeWindow;
|
||||
let remoteDebugger = this.getRemoteDebugger();
|
||||
|
||||
if (win._remoteDebugger) {
|
||||
win._remoteDebugger.close();
|
||||
if (remoteDebugger) {
|
||||
remoteDebugger.close();
|
||||
return null;
|
||||
}
|
||||
return new RemoteDebuggerWindow(this);
|
||||
@ -79,21 +86,22 @@ DebuggerUI.prototype = {
|
||||
* @return ChromeDebuggerProcess if the debugger is started, null if stopped.
|
||||
*/
|
||||
toggleChromeDebugger: function DUI_toggleChromeDebugger(aOnClose, aOnRun) {
|
||||
let win = this.chromeWindow;
|
||||
let chromeDebugger = this.getChromeDebugger();
|
||||
|
||||
if (win._chromeDebugger) {
|
||||
win._chromeDebugger.close();
|
||||
if (chromeDebugger) {
|
||||
chromeDebugger.close();
|
||||
return null;
|
||||
}
|
||||
return new ChromeDebuggerProcess(win, aOnClose, aOnRun, true);
|
||||
return new ChromeDebuggerProcess(this.chromeWindow, aOnClose, aOnRun, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the debugger for a specified tab.
|
||||
* Get the current script debugger.
|
||||
* @return DebuggerPane if a debugger exists for the tab, null otherwise.
|
||||
*/
|
||||
getDebugger: function DUI_getDebugger(aTab) {
|
||||
return '_scriptDebugger' in aTab ? aTab._scriptDebugger : null;
|
||||
getDebugger: function DUI_getDebugger() {
|
||||
let win = this.chromeWindow;
|
||||
return '_scriptDebugger' in win ? win._scriptDebugger : null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -120,6 +128,52 @@ DebuggerUI.prototype = {
|
||||
*/
|
||||
get preferences() {
|
||||
return DebuggerPreferences;
|
||||
},
|
||||
|
||||
/**
|
||||
* Currently, there can only be one debugger per tab.
|
||||
* Show an asynchronous notification which asks the user to switch the
|
||||
* script debugger to the current tab if it's already open in another one.
|
||||
*/
|
||||
showTabSwitchNotification: function DUI_showTabSwitchNotification()
|
||||
{
|
||||
let gBrowser = this.chromeWindow.gBrowser;
|
||||
let selectedBrowser = gBrowser.selectedBrowser;
|
||||
|
||||
let nbox = gBrowser.getNotificationBox(selectedBrowser);
|
||||
let notification = nbox.getNotificationWithValue(TAB_SWITCH_NOTIFICATION);
|
||||
if (notification) {
|
||||
nbox.removeNotification(notification);
|
||||
return;
|
||||
}
|
||||
|
||||
let buttons = [{
|
||||
id: "debugger.confirmTabSwitch.buttonSwitch",
|
||||
label: L10N.getStr("confirmTabSwitch.buttonSwitch"),
|
||||
accessKey: L10N.getStr("confirmTabSwitch.buttonSwitch.accessKey"),
|
||||
callback: function DUI_notificationButtonSwitch() {
|
||||
gBrowser.selectedTab = this.getDebugger().ownerTab;
|
||||
}.bind(this)
|
||||
}, {
|
||||
id: "debugger.confirmTabSwitch.buttonOpen",
|
||||
label: L10N.getStr("confirmTabSwitch.buttonOpen"),
|
||||
accessKey: L10N.getStr("confirmTabSwitch.buttonOpen.accessKey"),
|
||||
callback: function DUI_notificationButtonOpen() {
|
||||
this.getDebugger().close();
|
||||
this.toggleDebugger();
|
||||
}.bind(this)
|
||||
}];
|
||||
|
||||
let message = L10N.getStr("confirmTabSwitch.message");
|
||||
let imageURL = "chrome://browser/skin/Info.png";
|
||||
|
||||
notification = nbox.appendNotification(
|
||||
message, TAB_SWITCH_NOTIFICATION,
|
||||
imageURL, nbox.PRIORITY_WARNING_HIGH, buttons, null);
|
||||
|
||||
// Make sure this is not a transient notification, to avoid the automatic
|
||||
// transient notification removal.
|
||||
notification.persistence = -1;
|
||||
}
|
||||
};
|
||||
|
||||
@ -133,6 +187,7 @@ DebuggerUI.prototype = {
|
||||
*/
|
||||
function DebuggerPane(aDebuggerUI, aTab) {
|
||||
this._globalUI = aDebuggerUI;
|
||||
this._win = aDebuggerUI.chromeWindow;
|
||||
this._tab = aTab;
|
||||
|
||||
this._initServer();
|
||||
@ -155,9 +210,9 @@ DebuggerPane.prototype = {
|
||||
* Creates and initializes the widgets containing the debugger UI.
|
||||
*/
|
||||
_create: function DP__create() {
|
||||
this._tab._scriptDebugger = this;
|
||||
this._win._scriptDebugger = this;
|
||||
|
||||
let gBrowser = this._tab.linkedBrowser.getTabBrowser();
|
||||
let gBrowser = this._win.gBrowser;
|
||||
let ownerDocument = gBrowser.parentNode.ownerDocument;
|
||||
|
||||
this._splitter = ownerDocument.createElement("splitter");
|
||||
@ -193,10 +248,11 @@ DebuggerPane.prototype = {
|
||||
* Closes the debugger, removing child nodes and event listeners.
|
||||
*/
|
||||
close: function DP_close() {
|
||||
if (!this._tab) {
|
||||
if (!this._win) {
|
||||
return;
|
||||
}
|
||||
delete this._tab._scriptDebugger;
|
||||
delete this._win._scriptDebugger;
|
||||
this._win = null;
|
||||
this._tab = null;
|
||||
|
||||
DebuggerPreferences.height = this._frame.height;
|
||||
@ -213,6 +269,14 @@ DebuggerPane.prototype = {
|
||||
this._globalUI.refreshCommand();
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the tab owning this debugger instance.
|
||||
* @return XULElement
|
||||
*/
|
||||
get ownerTab() {
|
||||
return this._tab;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the debugger content window.
|
||||
* @return nsIDOMWindow if a debugger window exists, null otherwise
|
||||
|
@ -48,6 +48,7 @@ let DebuggerController = {
|
||||
this._isInitialized = true;
|
||||
window.removeEventListener("DOMContentLoaded", this._startupDebugger, true);
|
||||
|
||||
DebuggerView.initializePanes();
|
||||
DebuggerView.initializeEditor();
|
||||
DebuggerView.StackFrames.initialize();
|
||||
DebuggerView.Properties.initialize();
|
||||
@ -69,6 +70,7 @@ let DebuggerController = {
|
||||
this._isDestroyed = true;
|
||||
window.removeEventListener("unload", this._shutdownDebugger, true);
|
||||
|
||||
DebuggerView.destroyPanes();
|
||||
DebuggerView.destroyEditor();
|
||||
DebuggerView.Scripts.destroy();
|
||||
DebuggerView.StackFrames.destroy();
|
||||
@ -659,15 +661,6 @@ StackFrames.prototype = {
|
||||
|
||||
let objClient = this.activeThread.pauseGrip(aObject);
|
||||
objClient.getPrototypeAndProperties(function SF_onProtoAndProps(aResponse) {
|
||||
// Add __proto__.
|
||||
if (aResponse.prototype.type !== "null") {
|
||||
let properties = { "__proto__ ": { value: aResponse.prototype } };
|
||||
aVar.addProperties(properties);
|
||||
|
||||
// Expansion handlers must be set after the properties are added.
|
||||
this._addExpander(aVar["__proto__ "], aResponse.prototype);
|
||||
}
|
||||
|
||||
// Sort all of the properties before adding them, for better UX.
|
||||
let properties = {};
|
||||
for each (let prop in Object.keys(aResponse.ownProperties).sort()) {
|
||||
@ -680,6 +673,14 @@ StackFrames.prototype = {
|
||||
this._addExpander(aVar[prop], aResponse.ownProperties[prop].value);
|
||||
}
|
||||
|
||||
// Add __proto__.
|
||||
if (aResponse.prototype.type !== "null") {
|
||||
let properties = { "__proto__ ": { value: aResponse.prototype } };
|
||||
aVar.addProperties(properties);
|
||||
|
||||
// Expansion handlers must be set after the properties are added.
|
||||
this._addExpander(aVar["__proto__ "], aResponse.prototype);
|
||||
}
|
||||
aVar.fetched = true;
|
||||
}.bind(this));
|
||||
},
|
||||
@ -1419,6 +1420,46 @@ XPCOMUtils.defineLazyGetter(L10N, "stringBundle", function() {
|
||||
*/
|
||||
let Prefs = {
|
||||
|
||||
/**
|
||||
* Gets the preferred stackframes pane width.
|
||||
* @return number
|
||||
*/
|
||||
get stackframesWidth() {
|
||||
if (this._sfrmWidth === undefined) {
|
||||
this._sfrmWidth = Services.prefs.getIntPref("devtools.debugger.ui.stackframes-width");
|
||||
}
|
||||
return this._sfrmWidth;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the preferred stackframes pane width.
|
||||
* @return number
|
||||
*/
|
||||
set stackframesWidth(value) {
|
||||
Services.prefs.setIntPref("devtools.debugger.ui.stackframes-width", value);
|
||||
this._sfrmWidth = value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the preferred variables pane width.
|
||||
* @return number
|
||||
*/
|
||||
get variablesWidth() {
|
||||
if (this._varsWidth === undefined) {
|
||||
this._varsWidth = Services.prefs.getIntPref("devtools.debugger.ui.variables-width");
|
||||
}
|
||||
return this._varsWidth;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the preferred variables pane width.
|
||||
* @return number
|
||||
*/
|
||||
set variablesWidth(value) {
|
||||
Services.prefs.setIntPref("devtools.debugger.ui.variables-width", value);
|
||||
this._varsWidth = value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a flag specifying if the the debugger should automatically connect to
|
||||
* the default host and port number.
|
||||
|
@ -18,6 +18,17 @@ let DebuggerView = {
|
||||
*/
|
||||
editor: null,
|
||||
|
||||
/**
|
||||
* Initializes UI properties for all the displayed panes.
|
||||
*/
|
||||
initializePanes: function DV_initializePanes() {
|
||||
let stackframes = document.getElementById("stackframes");
|
||||
stackframes.setAttribute("width", Prefs.stackframesWidth);
|
||||
|
||||
let variables = document.getElementById("variables");
|
||||
variables.setAttribute("width", Prefs.variablesWidth);
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the SourceEditor instance.
|
||||
*/
|
||||
@ -36,6 +47,17 @@ let DebuggerView = {
|
||||
this.editor.init(placeholder, config, this._onEditorLoad.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the displayed panes and saves any necessary state.
|
||||
*/
|
||||
destroyPanes: function DV_destroyPanes() {
|
||||
let stackframes = document.getElementById("stackframes");
|
||||
Prefs.stackframesWidth = stackframes.getAttribute("width");
|
||||
|
||||
let variables = document.getElementById("variables");
|
||||
Prefs.variablesWidth = variables.getAttribute("width");
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the SourceEditor instance and added breakpoints.
|
||||
*/
|
||||
@ -813,6 +835,12 @@ PropertiesView.prototype = {
|
||||
*/
|
||||
element.addToHierarchy = this.addScopeToHierarchy.bind(this, element);
|
||||
|
||||
// Setup the additional elements specific for a scope node.
|
||||
element.refresh(function() {
|
||||
let title = element.getElementsByClassName("title")[0];
|
||||
title.classList.add("devtools-toolbar");
|
||||
}.bind(this));
|
||||
|
||||
// Return the element for later use if necessary.
|
||||
return element;
|
||||
},
|
||||
@ -1035,12 +1063,12 @@ PropertiesView.prototype = {
|
||||
|
||||
// Handle data property and accessor property descriptors.
|
||||
if (value !== undefined) {
|
||||
this._addProperty(aVar, [i, value]);
|
||||
this._addProperty(aVar, [i, value], desc);
|
||||
}
|
||||
if (getter !== undefined || setter !== undefined) {
|
||||
let prop = this._addProperty(aVar, [i]).expand();
|
||||
prop.getter = this._addProperty(prop, ["get", getter]);
|
||||
prop.setter = this._addProperty(prop, ["set", setter]);
|
||||
prop.getter = this._addProperty(prop, ["get", getter], desc);
|
||||
prop.setter = this._addProperty(prop, ["set", setter], desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1054,7 +1082,7 @@ PropertiesView.prototype = {
|
||||
*
|
||||
* @param object aVar
|
||||
* The parent variable element.
|
||||
* @param {Array} aProperty
|
||||
* @param array aProperty
|
||||
* An array containing the key and grip properties, specifying
|
||||
* the value and/or type & class of the variable (if the type
|
||||
* is not specified, it will be inferred from the value).
|
||||
@ -1064,6 +1092,8 @@ PropertiesView.prototype = {
|
||||
* ["someProp3", { type: "undefined" }]
|
||||
* ["someProp4", { type: "null" }]
|
||||
* ["someProp5", { type: "object", class: "Object" }]
|
||||
* @param object aFlags
|
||||
* Contans configurable, enumberable or writable flags.
|
||||
* @param string aName
|
||||
* Optional, the property name.
|
||||
* @paarm string aId
|
||||
@ -1071,7 +1101,7 @@ PropertiesView.prototype = {
|
||||
* @return object
|
||||
* The newly created html node representing the added prop.
|
||||
*/
|
||||
_addProperty: function DVP__addProperty(aVar, aProperty, aName, aId) {
|
||||
_addProperty: function DVP__addProperty(aVar, aProperty, aFlags, aName, aId) {
|
||||
// Make sure the variable container exists.
|
||||
if (!aVar) {
|
||||
return null;
|
||||
@ -1109,7 +1139,15 @@ PropertiesView.prototype = {
|
||||
|
||||
if ("undefined" !== typeof pKey) {
|
||||
// Use a key element to specify the property name.
|
||||
nameLabel.className = "key plain";
|
||||
let className = "";
|
||||
if (aFlags) {
|
||||
if (aFlags.configurable === false) { className += "non-configurable "; }
|
||||
if (aFlags.enumerable === false) { className += "non-enumerable "; }
|
||||
if (aFlags.writable === false) { className += "non-writable "; }
|
||||
}
|
||||
if (pKey === "__proto__ ") { className += "proto "; }
|
||||
|
||||
nameLabel.className = className + "key plain";
|
||||
nameLabel.setAttribute("value", pKey.trim());
|
||||
title.appendChild(nameLabel);
|
||||
}
|
||||
|
@ -45,7 +45,6 @@
|
||||
tooltiptext="&debuggerUI.closeButton.tooltip;"
|
||||
class="devtools-closebutton"/>
|
||||
#endif
|
||||
|
||||
<hbox id="debugger-controls">
|
||||
<toolbarbutton id="resume"
|
||||
class="devtools-toolbarbutton"
|
||||
@ -77,17 +76,11 @@
|
||||
#endif
|
||||
</toolbar>
|
||||
<hbox id="dbg-content" flex="1">
|
||||
<vbox id="stack" flex="1">
|
||||
<vbox id="stackframes" class="dbg-default" flex="1"/>
|
||||
</vbox>
|
||||
<splitter id="stack-script-splitter"
|
||||
class="devtools-side-splitter"/>
|
||||
<vbox id="editor" class="dbg-default" flex="1"/>
|
||||
<splitter id="script-properties-splitter"
|
||||
class="devtools-side-splitter"/>
|
||||
<vbox id="properties" flex="1">
|
||||
<vbox id="variables" class="dbg-default" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="stackframes"/>
|
||||
<splitter id="stack-script-splitter" class="devtools-side-splitter"/>
|
||||
<vbox id="editor" flex="1"/>
|
||||
<splitter id="script-properties-splitter" class="devtools-side-splitter"/>
|
||||
<vbox id="variables"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
|
@ -14,6 +14,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_dbg_createRemote.js \
|
||||
browser_dbg_createChrome.js \
|
||||
browser_dbg_debugger-tab-switch.js \
|
||||
browser_dbg_debuggerstatement.js \
|
||||
browser_dbg_listtabs.js \
|
||||
browser_dbg_tabactor-01.js \
|
||||
@ -34,6 +35,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_dbg_propertyview-10.js \
|
||||
browser_dbg_propertyview-edit.js \
|
||||
browser_dbg_panesize.js \
|
||||
browser_dbg_panesize-inner.js \
|
||||
browser_dbg_stack-01.js \
|
||||
browser_dbg_stack-02.js \
|
||||
browser_dbg_stack-03.js \
|
||||
|
@ -27,7 +27,7 @@ function testCleanExit() {
|
||||
is(gDebugger.DebuggerController.activeThread.paused, true,
|
||||
"Should be paused after the debugger statement.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
|
@ -37,7 +37,7 @@ function test() {
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
closeDebuggerAndFinish(gTab, true);
|
||||
closeDebuggerAndFinish(true);
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,228 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
let gTab1, gTab2, gTab3, gTab4;
|
||||
let gPane1, gPane2;
|
||||
let gNbox;
|
||||
|
||||
function test() {
|
||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
|
||||
testTab1(function() {
|
||||
testTab2(function() {
|
||||
testTab3(function() {
|
||||
testTab4(function() {
|
||||
lastTest(function() {
|
||||
cleanup(function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testTab1(callback) {
|
||||
gTab1 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = gTab1;
|
||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
|
||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
||||
"Shouldn't have a tab switch notification.");
|
||||
ok(!DebuggerUI.getDebugger(),
|
||||
"Shouldn't have a debugger pane for this tab yet.");
|
||||
|
||||
info("Toggling a debugger (1).");
|
||||
|
||||
gPane1 = DebuggerUI.toggleDebugger();
|
||||
ok(gPane1, "toggleDebugger() should return a pane.");
|
||||
is(gPane1.ownerTab, gTab1, "Incorrect tab owner.");
|
||||
|
||||
is(DebuggerUI.getDebugger(), gPane1,
|
||||
"getDebugger() should return the same pane as toggleDebugger().");
|
||||
|
||||
gPane1._frame.addEventListener("Debugger:Loaded", function dbgLoaded() {
|
||||
gPane1._frame.removeEventListener("Debugger:Loaded", dbgLoaded, true);
|
||||
|
||||
info("First debugger has finished loading correctly.");
|
||||
executeSoon(function() {
|
||||
callback();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function testTab2(callback) {
|
||||
gTab2 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = gTab2;
|
||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
|
||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
||||
"Shouldn't have a tab switch notification yet.");
|
||||
ok(DebuggerUI.getDebugger(),
|
||||
"Should already have a debugger pane for another tab.");
|
||||
|
||||
gNbox.addEventListener("AlertActive", function active() {
|
||||
gNbox.removeEventListener("AlertActive", active, true);
|
||||
executeSoon(function() {
|
||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
||||
|
||||
is(DebuggerUI.getDebugger(), gPane1,
|
||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
||||
is(DebuggerUI.getDebugger(), gPane2,
|
||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
||||
|
||||
info("Second debugger has not loaded.");
|
||||
|
||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
||||
|
||||
info("Notification will be simply closed.");
|
||||
notification.close();
|
||||
|
||||
executeSoon(function() {
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
|
||||
info("Toggling a debugger (2).");
|
||||
|
||||
gPane2 = DebuggerUI.toggleDebugger();
|
||||
});
|
||||
}
|
||||
|
||||
function testTab3(callback) {
|
||||
gTab3 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = gTab3;
|
||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
|
||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
||||
"Shouldn't have a tab switch notification.");
|
||||
ok(DebuggerUI.getDebugger(),
|
||||
"Should already have a debugger pane for another tab.");
|
||||
|
||||
gNbox.addEventListener("AlertActive", function active() {
|
||||
gNbox.removeEventListener("AlertActive", active, true);
|
||||
executeSoon(function() {
|
||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
||||
|
||||
is(DebuggerUI.getDebugger(), gPane1,
|
||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
||||
is(DebuggerUI.getDebugger(), gPane2,
|
||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
||||
|
||||
info("Second debugger has not loaded.");
|
||||
|
||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", function tabSelect() {
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, true);
|
||||
executeSoon(function() {
|
||||
callback();
|
||||
});
|
||||
}, true);
|
||||
|
||||
let buttonSwitch = notification.querySelectorAll("button")[0];
|
||||
buttonSwitch.focus();
|
||||
EventUtils.sendKey("SPACE");
|
||||
info("The switch button on the notification was pressed.");
|
||||
});
|
||||
}, true);
|
||||
|
||||
info("Toggling a debugger (3).");
|
||||
|
||||
gPane2 = DebuggerUI.toggleDebugger();
|
||||
});
|
||||
}
|
||||
|
||||
function testTab4(callback) {
|
||||
is(gBrowser.selectedTab, gTab1,
|
||||
"Should've switched to the first debugged tab.");
|
||||
|
||||
gTab4 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = gTab4;
|
||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
|
||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
||||
"Shouldn't have a tab switch notification.");
|
||||
ok(DebuggerUI.getDebugger(),
|
||||
"Should already have a debugger pane for another tab.");
|
||||
|
||||
gNbox.addEventListener("AlertActive", function active() {
|
||||
gNbox.removeEventListener("AlertActive", active, true);
|
||||
executeSoon(function() {
|
||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
||||
|
||||
is(DebuggerUI.getDebugger(), gPane1,
|
||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
||||
is(DebuggerUI.getDebugger(), gPane2,
|
||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
||||
|
||||
info("Second debugger has not loaded.");
|
||||
|
||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
||||
|
||||
let buttonOpen = notification.querySelectorAll("button")[1];
|
||||
buttonOpen.focus();
|
||||
EventUtils.sendKey("SPACE");
|
||||
info("The open button on the notification was pressed.");
|
||||
|
||||
executeSoon(function() {
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
|
||||
info("Toggling a debugger (4).");
|
||||
|
||||
gPane2 = DebuggerUI.toggleDebugger();
|
||||
});
|
||||
}
|
||||
|
||||
function lastTest(callback) {
|
||||
isnot(gBrowser.selectedTab, gTab1,
|
||||
"Shouldn't have switched to the first debugged tab.");
|
||||
is(gBrowser.selectedTab, gTab4,
|
||||
"Should currently be in the fourth tab.");
|
||||
is(DebuggerUI.getDebugger().ownerTab, gTab4,
|
||||
"The debugger should be open for the fourth tab.");
|
||||
|
||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
||||
"Shouldn't have a tab switch notification.");
|
||||
|
||||
info("Second debugger has loaded.");
|
||||
|
||||
executeSoon(function() {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup(callback) {
|
||||
removeTab(gTab1);
|
||||
removeTab(gTab2);
|
||||
removeTab(gTab3);
|
||||
removeTab(gTab4);
|
||||
|
||||
gTab1 = null;
|
||||
gTab2 = null;
|
||||
gTab3 = null;
|
||||
gTab4 = null;
|
||||
gPane1 = null;
|
||||
gPane2 = null;
|
||||
gNbox = null;
|
||||
|
||||
callback();
|
||||
}
|
@ -36,7 +36,7 @@ function test() {
|
||||
|
||||
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
|
@ -55,7 +55,7 @@ function testLocationChange()
|
||||
gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
|
||||
ok(true, "Successfully reattached to the tab again.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
content.location = TAB1_URL;
|
||||
|
63
browser/devtools/debugger/test/browser_dbg_panesize-inner.js
Normal file
@ -0,0 +1,63 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function test() {
|
||||
var tab1 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
||||
ok(!DebuggerUI.getDebugger(),
|
||||
"Shouldn't have a debugger pane for this tab yet.");
|
||||
|
||||
let pane = DebuggerUI.toggleDebugger();
|
||||
let someWidth1 = parseInt(Math.random() * 200) + 100;
|
||||
let someWidth2 = parseInt(Math.random() * 200) + 100;
|
||||
|
||||
ok(pane, "toggleDebugger() should return a pane.");
|
||||
|
||||
is(DebuggerUI.getDebugger(), pane,
|
||||
"getDebugger() should return the same pane as toggleDebugger().");
|
||||
|
||||
let frame = pane._frame;
|
||||
let content = pane.contentWindow;
|
||||
let stackframes;
|
||||
let variables;
|
||||
|
||||
frame.addEventListener("Debugger:Loaded", function dbgLoaded() {
|
||||
frame.removeEventListener("Debugger:Loaded", dbgLoaded, true);
|
||||
|
||||
ok(content.Prefs.stackframesWidth,
|
||||
"The debugger preferences should have a saved stackframesWidth value.");
|
||||
ok(content.Prefs.variablesWidth,
|
||||
"The debugger preferences should have a saved variablesWidth value.");
|
||||
|
||||
stackframes = content.document.getElementById("stackframes");
|
||||
variables = content.document.getElementById("variables");
|
||||
|
||||
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
|
||||
"The stackframes pane width should be the same as the preferred value.");
|
||||
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
|
||||
"The variables pane width should be the same as the preferred value.");
|
||||
|
||||
stackframes.setAttribute("width", someWidth1);
|
||||
variables.setAttribute("width", someWidth2);
|
||||
|
||||
removeTab(tab1);
|
||||
|
||||
}, true);
|
||||
|
||||
frame.addEventListener("Debugger:Unloaded", function dbgUnloaded() {
|
||||
frame.removeEventListener("Debugger:Unloaded", dbgUnloaded, true);
|
||||
|
||||
is(content.Prefs.stackframesWidth, stackframes.getAttribute("width"),
|
||||
"The stackframes pane width should have been saved by now.");
|
||||
is(content.Prefs.variablesWidth, variables.getAttribute("width"),
|
||||
"The variables pane width should have been saved by now.");
|
||||
|
||||
finish();
|
||||
|
||||
}, true);
|
||||
});
|
||||
}
|
@ -8,7 +8,7 @@ function test() {
|
||||
var tab1 = addTab(TAB1_URL, function() {
|
||||
gBrowser.selectedTab = tab1;
|
||||
|
||||
ok(!DebuggerUI.getDebugger(gBrowser.selectedTab),
|
||||
ok(!DebuggerUI.getDebugger(),
|
||||
"Shouldn't have a debugger pane for this tab yet.");
|
||||
|
||||
let pane = DebuggerUI.toggleDebugger();
|
||||
@ -16,7 +16,7 @@ function test() {
|
||||
|
||||
ok(pane, "toggleDebugger() should return a pane.");
|
||||
|
||||
is(DebuggerUI.getDebugger(gBrowser.selectedTab), pane,
|
||||
is(DebuggerUI.getDebugger(), pane,
|
||||
"getDebugger() should return the same pane as toggleDebugger().");
|
||||
|
||||
ok(DebuggerUI.preferences.height,
|
||||
|
@ -61,7 +61,7 @@ function testResume() {
|
||||
is(button.getAttribute("tooltiptext"), gDebugger.L10N.getStr("pauseTooltip"),
|
||||
"Button tooltip should be pause when running.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
|
@ -89,7 +89,7 @@ function testScriptLabelShortening() {
|
||||
is(vs._scripts.itemCount, 9,
|
||||
"Didn't get the correct number of scripts in the list.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ function testSimpleCall() {
|
||||
"Clicking again the testScope tilte should collapse it.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -189,7 +189,7 @@ function testSimpleCall() {
|
||||
"The scope should have been removed from the parent container tree.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ function testSimpleCall() {
|
||||
"The var should have been removed from the parent container tree.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -82,7 +82,7 @@ function testSimpleCall() {
|
||||
"The var should have been removed from the parent container tree.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -129,7 +129,7 @@ function testSimpleCall() {
|
||||
"The grip information for the localVar5 wasn't set correctly.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -105,7 +105,7 @@ function resumeAndFinish() {
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}, true);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume();
|
||||
|
@ -79,36 +79,51 @@ function testFrameParameters()
|
||||
}
|
||||
window.clearInterval(intervalID);
|
||||
is(localNodes[0].querySelector(".property > .title > .key")
|
||||
.getAttribute("value"), "__proto__",
|
||||
"Should have the right property name for __proto__.");
|
||||
|
||||
.getAttribute("value"), "Array",
|
||||
"Should have the right property name for Array.");
|
||||
ok(localNodes[0].querySelector(".property > .title > .value")
|
||||
.getAttribute("value").search(/object/) != -1,
|
||||
"Array should be an object.");
|
||||
|
||||
is(localNodes[8].querySelector(".value")
|
||||
.getAttribute("value"), "[object Arguments]",
|
||||
"Should have the right property value for 'arguments'.");
|
||||
ok(localNodes[8].querySelector(".property > .title > .value")
|
||||
.getAttribute("value").search(/object/) != -1,
|
||||
"Arguments should be an object.");
|
||||
|
||||
is(localNodes[8].querySelectorAll(".property > .title > .key")[7]
|
||||
.getAttribute("value"), "__proto__",
|
||||
"Should have the right property name for '__proto__'.");
|
||||
ok(localNodes[8].querySelectorAll(".property > .title > .value")[7]
|
||||
.getAttribute("value").search(/object/) != -1,
|
||||
"__proto__ should be an object.");
|
||||
|
||||
is(localNodes[8].querySelector(".value").getAttribute("value"),
|
||||
"[object Arguments]",
|
||||
"Should have the right property value for 'arguments'.");
|
||||
|
||||
is(localNodes[8].querySelectorAll(".property > .title > .key")[7]
|
||||
.getAttribute("value"), "length",
|
||||
"Should have the right property name for 'length'.");
|
||||
|
||||
is(localNodes[8].querySelectorAll(".property > .title > .value")[7]
|
||||
.getAttribute("value"), 5,
|
||||
"Should have the right argument length.");
|
||||
|
||||
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
is(localNodes[10].querySelector(".value")
|
||||
.getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'c'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[1]
|
||||
.getAttribute("value"), "a",
|
||||
"Should have the right property name for 'a'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[1]
|
||||
.getAttribute("value"), 1,
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[0]
|
||||
.getAttribute("value"), "a",
|
||||
"Should have the right property name for 'c.a'.");
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[0]
|
||||
.getAttribute("value"), "1",
|
||||
"Should have the right value for 'c.a'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[1]
|
||||
.getAttribute("value"), "b",
|
||||
"Should have the right property name for 'c.b'.");
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[1]
|
||||
.getAttribute("value"), "\"beta\"",
|
||||
"Should have the right value for 'c.b'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[2]
|
||||
.getAttribute("value"), "c",
|
||||
"Should have the right property name for 'c.c'.");
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[2]
|
||||
.getAttribute("value"), "true",
|
||||
"Should have the right value for 'c.c'.");
|
||||
|
||||
resumeAndFinish();
|
||||
}, 100);
|
||||
}}, 0);
|
||||
@ -127,7 +142,7 @@ function resumeAndFinish() {
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}, true);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume();
|
||||
|
@ -79,7 +79,7 @@ function resumeAndFinish() {
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}}, 0);
|
||||
}, true);
|
||||
|
||||
|
@ -90,7 +90,7 @@ function resumeAndFinish() {
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}}, 0);
|
||||
}, true);
|
||||
|
||||
|
@ -97,7 +97,7 @@ function testModification(aVar, aCallback, aNewValue, aNewResult) {
|
||||
|
||||
function resumeAndFinish() {
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ function testSwitchRunning()
|
||||
is(gDebugger.editor.getDebugLocation(), -1,
|
||||
"editor debugger location is still -1.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
|
@ -157,7 +157,7 @@ function testScriptSearching() {
|
||||
is(gScripts.visibleItemsCount, 1,
|
||||
"Not all the scripts are shown after the search. (20)");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ function finalCheck() {
|
||||
is(gScripts.visibleItemsCount, 2,
|
||||
"Not all the scripts are shown after the search. (3)");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}
|
||||
|
||||
function clear() {
|
||||
|
@ -35,7 +35,7 @@ function resumeAndFinish() {
|
||||
addScriptsAndCheckOrder(1, function() {
|
||||
addScriptsAndCheckOrder(2, function() {
|
||||
addScriptsAndCheckOrder(3, function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ function testSelectLine() {
|
||||
"The correct line is selected.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ function testSimpleCall() {
|
||||
"All children should be frames.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ function testEvalCall() {
|
||||
"Second frame should not be selected after click inside the first frame.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}}, 0);
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ function testRecurse() {
|
||||
"Should have reached the recurse limit.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -49,7 +49,7 @@ function testEvalCallResume() {
|
||||
is(frames.querySelectorAll(".empty").length, 1,
|
||||
"Should have the empty list explanation.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
}, true);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume();
|
||||
|
@ -98,7 +98,7 @@ function testRecurse()
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
is(gDebugger.editor.getDebugLocation(), -1,
|
||||
"editor debugger location is correct after resume.");
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ function testSwitchPaused()
|
||||
"Found the expected editor mode.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish(gTab);
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -49,13 +49,13 @@ function removeTab(aTab) {
|
||||
gBrowser.removeTab(aTab);
|
||||
}
|
||||
|
||||
function closeDebuggerAndFinish(aTab, aRemoteFlag) {
|
||||
function closeDebuggerAndFinish(aRemoteFlag) {
|
||||
DebuggerUI.chromeWindow.addEventListener("Debugger:Shutdown", function cleanup() {
|
||||
DebuggerUI.chromeWindow.removeEventListener("Debugger:Shutdown", cleanup, false);
|
||||
finish();
|
||||
}, false);
|
||||
if (!aRemoteFlag) {
|
||||
DebuggerUI.getDebugger(aTab).close();
|
||||
DebuggerUI.getDebugger().close();
|
||||
} else {
|
||||
DebuggerUI.getRemoteDebugger().close();
|
||||
}
|
||||
|
@ -3,18 +3,18 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
browser.jar:
|
||||
* content/browser/inspector.html (highlighter/inspector.html)
|
||||
content/browser/inspector.html (highlighter/inspector.html)
|
||||
content/browser/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
|
||||
content/browser/devtools/HUDService-content.js (webconsole/HUDService-content.js)
|
||||
* content/browser/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
content/browser/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/splitview.css (shared/splitview.css)
|
||||
* content/browser/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
content/browser/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
content/browser/styleeditor.css (styleeditor/styleeditor.css)
|
||||
content/browser/devtools/csshtmltree.xul (styleinspector/csshtmltree.xul)
|
||||
content/browser/devtools/cssruleview.xul (styleinspector/cssruleview.xul)
|
||||
content/browser/devtools/styleinspector.css (styleinspector/styleinspector.css)
|
||||
* content/browser/devtools/layoutview/view.xhtml (layoutview/view.xhtml)
|
||||
content/browser/devtools/layoutview/view.xhtml (layoutview/view.xhtml)
|
||||
content/browser/devtools/layoutview/view.css (layoutview/view.css)
|
||||
content/browser/orion.js (sourceeditor/orion/orion.js)
|
||||
* content/browser/source-editor-overlay.xul (sourceeditor/source-editor-overlay.xul)
|
||||
|
@ -1,9 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
#ifdef 0
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
#endif
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % layoutviewDTD SYSTEM "chrome://browser/locale/devtools/layoutview.dtd" >
|
||||
%layoutviewDTD;
|
||||
|
@ -327,6 +327,10 @@ OutputPanel.prototype._onload = function OP_onload()
|
||||
this._div.classList.add('gcli-row-out');
|
||||
this._div.setAttribute('aria-live', 'assertive');
|
||||
|
||||
let styles = this._toolbar.ownerDocument.defaultView
|
||||
.getComputedStyle(this._toolbar);
|
||||
this._div.setAttribute("dir", styles.direction);
|
||||
|
||||
this.loaded = true;
|
||||
if (this._loadCallback) {
|
||||
this._loadCallback();
|
||||
@ -501,6 +505,10 @@ TooltipPanel.prototype._onload = function TP_onload()
|
||||
this.hintElement = this.document.getElementById("gcli-tooltip-root");
|
||||
this._connector = this.document.getElementById("gcli-tooltip-connector");
|
||||
|
||||
let styles = this._toolbar.ownerDocument.defaultView
|
||||
.getComputedStyle(this._toolbar);
|
||||
this.hintElement.setAttribute("dir", styles.direction);
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
if (this._loadCallback) {
|
||||
|
@ -10,6 +10,15 @@
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (confirmTabSwitch): The messages displayed for all the
|
||||
# title and buttons on the notification shown when a user attempts to open a
|
||||
# debugger in a new tab while a different tab is already being debugged.
|
||||
confirmTabSwitch.message=Debugger is already open in another tab. Continuing will close the other instance.
|
||||
confirmTabSwitch.buttonSwitch=Switch to debugged tab
|
||||
confirmTabSwitch.buttonSwitch.accessKey=S
|
||||
confirmTabSwitch.buttonOpen=Open anyway
|
||||
confirmTabSwitch.buttonOpen.accessKey=O
|
||||
|
||||
# LOCALIZATION NOTE (remoteDebuggerWindowTitle): The title displayed for the
|
||||
# remote debugger window.
|
||||
remoteDebuggerWindowTitle=Remote Debugger
|
||||
|
@ -40,6 +40,46 @@ consoleManual=Filter, clear and close the web console
|
||||
# function of the 'console clear' command.
|
||||
consoleclearDesc=Clear the console
|
||||
|
||||
# LOCALIZATION NOTE (screenshotDesc) A very short description of the
|
||||
# 'screenshot' command. See screenshotManual 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.
|
||||
screenshotDesc=Save an image of the page
|
||||
|
||||
# LOCALIZATION NOTE (screenshotManual) A fuller description of the 'screenshot'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
screenshotManual=Save an PNG image of the entire visible window (optionally after a delay)
|
||||
|
||||
# LOCALIZATION NOTE (screenshotFilenameDesc) A very short string to describe
|
||||
# the 'filename' parameter to the 'screenshot' command, which is displayed in
|
||||
# a dialog when the user is using this command.
|
||||
screenshotFilenameDesc=Destination filename
|
||||
|
||||
# LOCALIZATION NOTE (screenshotFilenameManual) A fuller description of the
|
||||
# 'filename' parameter to the 'screenshot' command, displayed when the user
|
||||
# asks for help on what it does.
|
||||
screenshotFilenameManual=The name of the file (should have a '.png' extension) to which we write the screenshot.
|
||||
|
||||
# LOCALIZATION NOTE (screenshotDelayDesc) A very short string to describe
|
||||
# the 'delay' parameter to the 'screenshot' command, which is displayed in
|
||||
# a dialog when the user is using this command.
|
||||
screenshotDelayDesc=Delay (seconds)
|
||||
|
||||
# LOCALIZATION NOTE (screenshotDelayManual) A fuller description of the
|
||||
# 'delay' parameter to the 'screenshot' command, displayed when the user
|
||||
# asks for help on what it does.
|
||||
screenshotDelayManual=The time to wait (in seconds) before the screenshot is taken
|
||||
|
||||
# LOCALIZATION NOTE (screenshotFullscreenDesc) A very short string to describe
|
||||
# the 'fullscreen' parameter to the 'screenshot' command, which is displayed in
|
||||
# a dialog when the user is using this command.
|
||||
screenshotFullPageDesc=Entire webpage? (true/false)
|
||||
|
||||
# LOCALIZATION NOTE (screenshotFullscreenManual) A fuller description of the
|
||||
# 'fullscreen' parameter to the 'screenshot' command, displayed when the user
|
||||
# asks for help on what it does.
|
||||
screenshotFullPageManual=True if the screenshot should also include parts of the webpage which are outside the current scrolled bounds.
|
||||
|
||||
# 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
|
||||
|
@ -1982,7 +1982,8 @@ panel[dimmed="true"] {
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
}
|
||||
|
||||
#inspector-toolbar {
|
||||
#inspector-toolbar,
|
||||
#developer-toolbar {
|
||||
border-top: 1px solid hsla(210, 8%, 5%, .65);
|
||||
}
|
||||
|
||||
@ -2383,42 +2384,69 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
.gcli-panel-inner-arrowcontent {
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
html|*#gcli-tooltip-frame,
|
||||
html|*#gcli-output-frame {
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#gcli-output,
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node,
|
||||
.gclitoolbar-complete-node,
|
||||
.gclitoolbar-prompt {
|
||||
font-family: monospace;
|
||||
margin: 0;
|
||||
-moz-margin-end: 3px;
|
||||
-moz-box-align: center;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-right: 4px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node {
|
||||
padding-left: 20px;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0 0 0 22px;
|
||||
border-color: hsl(210,11%,10%);
|
||||
color: hsl(210,30%,85%);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
|
||||
0 0 0 1px hsla(210,16%,76%,.1) inset,
|
||||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
padding: 10px 0 0 27px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt {
|
||||
color: hsl(25,78%,50%);
|
||||
-moz-appearance: textfield;
|
||||
padding-left: 4px;
|
||||
padding-bottom: 2px;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
line-height: 100%;
|
||||
padding-top: 1px;
|
||||
padding-left: 3px;
|
||||
color: hsl(210,30%,85%);
|
||||
background-color: hsl(210,11%,16%);
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt-label,
|
||||
.gcli-in-incomplete,
|
||||
.gcli-in-error,
|
||||
.gcli-in-ontab,
|
||||
@ -2439,20 +2467,13 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
}
|
||||
|
||||
.gcli-in-ontab {
|
||||
color: hsl(200,40%,70%);
|
||||
color: hsl(210,0%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-todo {
|
||||
color: hsl(48,28%,76%);
|
||||
color: hsl(210,50%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-closebrace {
|
||||
color: hsl(0,0%,80%);
|
||||
}
|
||||
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@
|
||||
margin: -4px;
|
||||
}
|
||||
|
||||
/* Splitter */
|
||||
/* Splitters */
|
||||
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
@ -129,3 +129,14 @@
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
border: 0;
|
||||
-moz-border-start: 1px solid black;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-end: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
BIN
browser/themes/gnomestripe/devtools/debugger-play.png
Normal file
After Width: | Height: | Size: 686 B |
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#dbg-content {
|
||||
padding: 6px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties elements
|
||||
* Properties view
|
||||
*/
|
||||
|
||||
#variables {
|
||||
@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic element details container
|
||||
* Property element details container
|
||||
*/
|
||||
|
||||
.details {
|
||||
@ -73,24 +73,17 @@
|
||||
*/
|
||||
|
||||
.scope > .title {
|
||||
margin-top: 1px;
|
||||
-moz-margin-start: 1px;
|
||||
-moz-padding-start: 2px;
|
||||
|
||||
background: -moz-linear-gradient(bottom,
|
||||
rgb(160,175,205) 0,
|
||||
rgb(120,140,175) 100%);
|
||||
|
||||
border-bottom: 1px solid #888;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
text-shadow: 0 1px #777;
|
||||
text-shadow: 0 1px #222;
|
||||
color: #fff;
|
||||
font: -moz-list;
|
||||
}
|
||||
|
||||
.scope > .title > .arrow {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.scope > .title > .name {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.scope > .details {
|
||||
@ -106,7 +99,7 @@
|
||||
-moz-margin-start: 1px;
|
||||
-moz-margin-end: 1px;
|
||||
margin-top: 2px;
|
||||
border-bottom: 1px dotted #aaa;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
border-radius: 8px;
|
||||
-moz-transition: background 1s ease-in-out;
|
||||
background: #fff;
|
||||
@ -143,8 +136,13 @@
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
.property > .title > .non-enumerable.key,
|
||||
.property > .title > .proto.key {
|
||||
color: #c48bc8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property colors
|
||||
* Property values colors
|
||||
*/
|
||||
|
||||
.token-undefined {
|
||||
@ -219,7 +217,7 @@
|
||||
*/
|
||||
|
||||
#resume {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-pause.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-play.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,44 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#gclichrome-body {
|
||||
.gcli-body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font: message-box;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
#gcli-output-root,
|
||||
#gcli-tooltip-root {
|
||||
border: 1px solid hsl(210,11%,10%);
|
||||
box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
|
||||
background-image: -moz-linear-gradient(top, hsla(209,11%,18%,0.9), hsl(210,11%,16%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#gcli-output-root {
|
||||
padding: 5px 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#gcli-tooltip-root {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
|
||||
#gcli-tooltip-connector {
|
||||
margin-top: -1px;
|
||||
margin-left: 8px;
|
||||
width: 20px;
|
||||
height: 0;
|
||||
border-left: 1px solid hsl(210,11%,10%);
|
||||
border-right: 1px solid hsl(210,11%,10%);
|
||||
background-color: hsl(210,11%,16%);
|
||||
}
|
||||
|
||||
.gcli-tt-description,
|
||||
.gcli-tt-error {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.gcli-row-out {
|
||||
@ -13,6 +47,7 @@
|
||||
line-height: 1.2em;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
.gcli-row-out p,
|
||||
@ -22,43 +57,35 @@
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut {
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
padding: 1px 4px 0;
|
||||
.gcli-row-out h1,
|
||||
.gcli-row-out h2,
|
||||
.gcli-row-out h3,
|
||||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
margin: 0 4px;
|
||||
font-size: 80%;
|
||||
font-family: monospace;
|
||||
cursor: pointer;
|
||||
vertical-align: bottom;
|
||||
white-space: pre;
|
||||
background-color: #fff;
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
border-radius: 3px;
|
||||
background-color: hsl(210,11%,16%);
|
||||
border: 1px solid hsl(210,11%,10%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut:before {
|
||||
color: #66F;
|
||||
content: '\bb';
|
||||
.gcli-out-shortcut:before,
|
||||
.gcli-help-synopsis:before {
|
||||
color: hsl(210,30%,85%);
|
||||
-moz-padding-end: 2px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/commands/help.css */
|
||||
|
||||
.gcli-help-arrow {
|
||||
font-size: 70%;
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis {
|
||||
font-family: monospace;
|
||||
font-weight: normal;
|
||||
padding: 0 3px;
|
||||
margin: 0 10px;
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis:before {
|
||||
color: #66F;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcli-help-description {
|
||||
@ -75,31 +102,22 @@
|
||||
margin: 10px 0 6px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/fields/menu.css */
|
||||
|
||||
.gcli-menu-name {
|
||||
-moz-padding-start: 8px;
|
||||
}
|
||||
|
||||
.gcli-menu-desc {
|
||||
-moz-padding-end: 8px;
|
||||
color: #999;
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
background-color: #EEE;
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
.gcli-menu-error {
|
||||
padding: 8px 10px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-typed {
|
||||
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 308 B |
@ -152,6 +152,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
|
||||
skin/classic/browser/devtools/layout-buttons.png (devtools/layout-buttons.png)
|
||||
skin/classic/browser/devtools/debugger-pause.png (devtools/debugger-pause.png)
|
||||
skin/classic/browser/devtools/debugger-play.png (devtools/debugger-play.png)
|
||||
skin/classic/browser/devtools/debugger-step-in.png (devtools/debugger-step-in.png)
|
||||
skin/classic/browser/devtools/debugger-step-out.png (devtools/debugger-step-out.png)
|
||||
skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png)
|
||||
|
@ -2711,18 +2711,21 @@ panel[dimmed="true"] {
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
}
|
||||
|
||||
#inspector-toolbar {
|
||||
#inspector-toolbar,
|
||||
#developer-toolbar {
|
||||
border-top: 1px solid hsla(210, 8%, 5%, .65);
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
#inspector-toolbar:-moz-locale-dir(ltr) {
|
||||
#inspector-toolbar:-moz-locale-dir(ltr),
|
||||
#developer-toolbar:-moz-locale-dir(ltr) {
|
||||
padding-left: 2px;
|
||||
padding-right: 16px; /* use -moz-padding-end when/if bug 631729 gets fixed */
|
||||
}
|
||||
|
||||
#inspector-toolbar:-moz-locale-dir(rtl) {
|
||||
#inspector-toolbar:-moz-locale-dir(rtl),
|
||||
#developer-toolbar:-moz-locale-dir(rtl) {
|
||||
padding-left: 4px;
|
||||
padding-right: 18px; /* use -moz-padding-end when/if bug 631729 gets fixed */
|
||||
}
|
||||
@ -3122,39 +3125,69 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
border-radius: 0 @toolbarbuttonCornerRadius@ @toolbarbuttonCornerRadius@ 0;
|
||||
}
|
||||
|
||||
.gcli-panel-inner-arrowcontent {
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
html|*#gcli-tooltip-frame,
|
||||
html|*#gcli-output-frame {
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#gcli-output,
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node,
|
||||
.gclitoolbar-complete-node,
|
||||
.gclitoolbar-prompt {
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
margin: 0;
|
||||
-moz-margin-end: 3px;
|
||||
-moz-box-align: center;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-right: 4px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: @toolbarbuttonCornerRadius@;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node {
|
||||
padding-left: 20px;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0 0 0 12px;
|
||||
border-color: hsl(210,11%,10%);
|
||||
color: hsl(210,30%,85%);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: 0 1px 1px hsla(210,8%,5%,.3) inset,
|
||||
0 0 0 1px hsla(210,16%,76%,.1) inset,
|
||||
0 1px 0 hsla(210,16%,76%,.15);
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
padding: 7px 0 0 18px;
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt {
|
||||
color: hsl(25,78%,50%);
|
||||
-moz-appearance: textfield;
|
||||
padding-left: 4px;
|
||||
padding-bottom: 2px;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
line-height: 100%;
|
||||
padding-top: 2px;
|
||||
color: hsl(210,30%,85%);
|
||||
background-color: hsl(210,11%,16%);
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt-label,
|
||||
.gcli-in-incomplete,
|
||||
.gcli-in-error,
|
||||
.gcli-in-ontab,
|
||||
@ -3175,20 +3208,13 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
}
|
||||
|
||||
.gcli-in-ontab {
|
||||
color: hsl(200,40%,70%);
|
||||
color: hsl(210,0%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-todo {
|
||||
color: hsl(48,28%,76%);
|
||||
color: hsl(210,50%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-closebrace {
|
||||
color: hsl(0,0%,80%);
|
||||
}
|
||||
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
/* Splitter */
|
||||
/* Splitters */
|
||||
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
@ -144,3 +144,14 @@
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
border: 0;
|
||||
-moz-border-start: 1px solid black;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
-moz-margin-end: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
BIN
browser/themes/pinstripe/devtools/debugger-play.png
Normal file
After Width: | Height: | Size: 686 B |
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#dbg-content {
|
||||
padding: 6px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,7 +54,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties elements
|
||||
* Properties view
|
||||
*/
|
||||
|
||||
#variables {
|
||||
@ -62,7 +62,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic element details container
|
||||
* Property element details container
|
||||
*/
|
||||
|
||||
.details {
|
||||
@ -75,23 +75,17 @@
|
||||
*/
|
||||
|
||||
.scope > .title {
|
||||
margin-top: 1px;
|
||||
-moz-margin-start: 1px;
|
||||
-moz-padding-start: 2px;
|
||||
|
||||
background: -moz-linear-gradient(bottom,
|
||||
rgb(160,175,205) 0,
|
||||
rgb(120,140,175) 100%);
|
||||
|
||||
border-bottom: 1px solid #888;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
text-shadow: 0 1px #777;
|
||||
text-shadow: 0 1px #222;
|
||||
color: #fff;
|
||||
font: -moz-list;
|
||||
}
|
||||
|
||||
.scope > .title > .arrow {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.scope > .title > .name {
|
||||
padding-top: 4px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.scope > .details {
|
||||
@ -107,7 +101,7 @@
|
||||
-moz-margin-start: 1px;
|
||||
-moz-margin-end: 1px;
|
||||
margin-top: 2px;
|
||||
border-bottom: 1px dotted #aaa;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
border-radius: 8px;
|
||||
-moz-transition: background 1s ease-in-out;
|
||||
background: #fff;
|
||||
@ -144,8 +138,13 @@
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
.property > .title > .non-enumerable.key,
|
||||
.property > .title > .proto.key {
|
||||
color: #c48bc8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property colors
|
||||
* Property values colors
|
||||
*/
|
||||
|
||||
.token-undefined {
|
||||
@ -218,7 +217,7 @@
|
||||
*/
|
||||
|
||||
#resume {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-pause.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-play.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,45 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#gclichrome-body {
|
||||
.gcli-body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font: message-box;
|
||||
color: #fff;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
#gcli-output-root,
|
||||
#gcli-tooltip-root {
|
||||
border: 1px solid hsl(210,11%,10%);
|
||||
box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
|
||||
background-image: url(background-noise-toolbar.png),
|
||||
-moz-linear-gradient(top, hsla(209,18%,18%,0.9), hsl(210,11%,16%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#gcli-output-root {
|
||||
padding: 5px 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#gcli-tooltip-root {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
|
||||
#gcli-tooltip-connector {
|
||||
margin-top: -1px;
|
||||
margin-left: 8px;
|
||||
width: 20px;
|
||||
height: 0;
|
||||
border-left: 1px solid hsl(210,11%,10%);
|
||||
border-right: 1px solid hsl(210,11%,10%);
|
||||
background-color: hsl(210,11%,16%);
|
||||
}
|
||||
|
||||
.gcli-tt-description,
|
||||
.gcli-tt-error {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.gcli-row-out {
|
||||
@ -27,50 +61,32 @@
|
||||
.gcli-row-out h1,
|
||||
.gcli-row-out h2,
|
||||
.gcli-row-out h3,
|
||||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
color: #fff;
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut {
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
padding: 1px 4px 0;
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
margin: 0 4px;
|
||||
font-size: 80%;
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
cursor: pointer;
|
||||
vertical-align: bottom;
|
||||
white-space: pre;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
border-radius: 3px;
|
||||
background-color: hsl(210,11%,16%);
|
||||
border: 1px solid hsl(210,11%,10%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut:before {
|
||||
color: #66F;
|
||||
content: '\bb';
|
||||
.gcli-out-shortcut:before,
|
||||
.gcli-help-synopsis:before {
|
||||
color: hsl(210,30%,85%);
|
||||
-moz-padding-end: 2px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/commands/help.css */
|
||||
|
||||
.gcli-help-arrow {
|
||||
font-size: 70%;
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis {
|
||||
font-family: Menlo, Monaco, monospace;
|
||||
font-weight: normal;
|
||||
padding: 0 3px;
|
||||
margin: 0 10px;
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis:before {
|
||||
color: #66F;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcli-help-description {
|
||||
@ -87,33 +103,22 @@
|
||||
margin: 10px 0 6px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/fields/menu.css */
|
||||
|
||||
.gcli-menu-name {
|
||||
-moz-padding-start: 8px;
|
||||
}
|
||||
|
||||
.gcli-menu-desc {
|
||||
-moz-padding-end: 8px;
|
||||
color: #999;
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
background-image: url(background-noise-toolbar.png),
|
||||
-moz-linear-gradient(top, hsl(210,11%,22%), hsl(210,11%,18%));
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
background-image: url(background-noise-toolbar.png),
|
||||
-moz-linear-gradient(top, hsl(210,11%,18%), hsl(210,11%,14%));
|
||||
}
|
||||
|
||||
.gcli-menu-error {
|
||||
padding: 8px 10px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-typed {
|
||||
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 308 B |
@ -193,6 +193,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
|
||||
skin/classic/browser/devtools/layout-buttons.png (devtools/layout-buttons.png)
|
||||
skin/classic/browser/devtools/debugger-pause.png (devtools/debugger-pause.png)
|
||||
skin/classic/browser/devtools/debugger-play.png (devtools/debugger-play.png)
|
||||
skin/classic/browser/devtools/debugger-step-in.png (devtools/debugger-step-in.png)
|
||||
skin/classic/browser/devtools/debugger-step-out.png (devtools/debugger-step-out.png)
|
||||
skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png)
|
||||
|
@ -2654,7 +2654,8 @@ panel[dimmed="true"] {
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
}
|
||||
|
||||
#inspector-toolbar {
|
||||
#inspector-toolbar,
|
||||
#developer-toolbar {
|
||||
border-top: 1px solid hsla(211,68%,6%,.65) !important;
|
||||
}
|
||||
|
||||
@ -3057,42 +3058,68 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
.gcli-panel-inner-arrowcontent {
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
html|*#gcli-tooltip-frame,
|
||||
html|*#gcli-output-frame {
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#gcli-output,
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node,
|
||||
.gclitoolbar-complete-node,
|
||||
.gclitoolbar-prompt {
|
||||
font-family: Consolas, Lucida Console, monospace;
|
||||
margin: 0;
|
||||
-moz-margin-end: 3px;
|
||||
-moz-box-align: center;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-right: 4px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node {
|
||||
padding-left: 20px;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0 0 0 22px;
|
||||
border-color: hsl(210,24%,10%);
|
||||
color: hsl(210,30%,85%);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: inset 0 1px 0 hsla(211,68%,6%,.05),
|
||||
0 0 0 1px hsla(210,40%,83%,.1);
|
||||
}
|
||||
|
||||
.gclitoolbar-complete-node {
|
||||
padding-left: 21px;
|
||||
background-color: transparent;
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
padding: 7px 0 0 27px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt {
|
||||
color: hsl(25,78%,50%);
|
||||
-moz-appearance: textfield;
|
||||
padding-left: 4px;
|
||||
padding-bottom: 2px;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
line-height: 100%;
|
||||
padding-top: 1px;
|
||||
padding-left: 4px;
|
||||
color: hsl(210,30%,85%);
|
||||
background-color: hsl(210,24%,16%);
|
||||
}
|
||||
|
||||
.gclitoolbar-prompt-label,
|
||||
.gcli-in-incomplete,
|
||||
.gcli-in-error,
|
||||
.gcli-in-ontab,
|
||||
@ -3113,20 +3140,13 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
|
||||
}
|
||||
|
||||
.gcli-in-ontab {
|
||||
color: hsl(200,40%,70%);
|
||||
color: hsl(210,0%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-todo {
|
||||
color: hsl(48,28%,76%);
|
||||
color: hsl(210,50%,35%);
|
||||
}
|
||||
|
||||
.gcli-in-closebrace {
|
||||
color: hsl(0,0%,80%);
|
||||
}
|
||||
|
||||
/* Highlight toolbar - Option menu */
|
||||
|
||||
#inspector-option-toolbarbutton:-moz-focusring {
|
||||
outline: 1px dotted hsla(210,30%,85%,0.4);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
@ -140,7 +140,7 @@
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
/* Splitter */
|
||||
/* Splitters */
|
||||
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
@ -152,3 +152,13 @@
|
||||
margin-bottom: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.devtools-side-splitter {
|
||||
border: 0;
|
||||
-moz-border-start: 1px solid #242b33;
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
background-color: transparent;
|
||||
-moz-margin-end: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
BIN
browser/themes/winstripe/devtools/debugger-play.png
Normal file
After Width: | Height: | Size: 686 B |
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#dbg-content {
|
||||
padding: 6px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties elements
|
||||
* Properties view
|
||||
*/
|
||||
|
||||
#variables {
|
||||
@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic element details container
|
||||
* Property element details container
|
||||
*/
|
||||
|
||||
.details {
|
||||
@ -73,24 +73,17 @@
|
||||
*/
|
||||
|
||||
.scope > .title {
|
||||
margin-top: 1px;
|
||||
-moz-margin-start: 1px;
|
||||
-moz-padding-start: 2px;
|
||||
|
||||
background: -moz-linear-gradient(bottom,
|
||||
rgb(160,175,205) 0,
|
||||
rgb(120,140,175) 100%);
|
||||
|
||||
border-bottom: 1px solid #888;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
text-shadow: 0 1px #777;
|
||||
text-shadow: 0 1px #222;
|
||||
color: #fff;
|
||||
font: -moz-list;
|
||||
}
|
||||
|
||||
.scope > .title > .arrow {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.scope > .title > .name {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.scope > .details {
|
||||
@ -106,7 +99,7 @@
|
||||
-moz-margin-start: 1px;
|
||||
-moz-margin-end: 1px;
|
||||
margin-top: 2px;
|
||||
border-bottom: 1px dotted #aaa;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
border-radius: 8px;
|
||||
-moz-transition: background 1s ease-in-out;
|
||||
background: #fff;
|
||||
@ -143,8 +136,13 @@
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
.property > .title > .non-enumerable.key,
|
||||
.property > .title > .proto.key {
|
||||
color: #c48bc8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property colors
|
||||
* Property values colors
|
||||
*/
|
||||
|
||||
.token-undefined {
|
||||
@ -222,12 +220,12 @@
|
||||
*/
|
||||
|
||||
#resume {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-play.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
#resume[checked=true] {
|
||||
-moz-image-region: rect(0px, 32px, 16px, 16px);
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-pause.png");
|
||||
}
|
||||
|
||||
#step-over {
|
||||
|
@ -2,10 +2,44 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#gclichrome-body {
|
||||
.gcli-body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font: message-box;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
#gcli-output-root,
|
||||
#gcli-tooltip-root {
|
||||
border: 1px solid hsl(210,24%,10%);
|
||||
box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
|
||||
background-image: -moz-linear-gradient(top, hsla(209,18%,18%,0.9), hsl(210,24%,16%));
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#gcli-output-root {
|
||||
padding: 5px 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#gcli-tooltip-root {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
|
||||
#gcli-tooltip-connector {
|
||||
margin-top: -1px;
|
||||
margin-left: 8px;
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
border-left: 1px solid hsl(210,24%,10%);
|
||||
border-right: 1px solid hsl(210,24%,10%);
|
||||
background-color: hsl(210,24%,16%);
|
||||
}
|
||||
|
||||
.gcli-tt-description,
|
||||
.gcli-tt-error {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.gcli-row-out {
|
||||
@ -13,6 +47,7 @@
|
||||
line-height: 1.2em;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
color: hsl(210,30%,85%);
|
||||
}
|
||||
|
||||
.gcli-row-out p,
|
||||
@ -22,43 +57,35 @@
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.gcli-out-shortcut {
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
padding: 1px 4px 0;
|
||||
.gcli-row-out h1,
|
||||
.gcli-row-out h2,
|
||||
.gcli-row-out h3,
|
||||
.gcli-row-out h4,
|
||||
.gcli-row-out h5,
|
||||
.gcli-row-out th,
|
||||
.gcli-row-out strong {
|
||||
color: hsl(210,30%,95%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut,
|
||||
.gcli-help-synopsis {
|
||||
padding: 0 3px;
|
||||
margin: 0 4px;
|
||||
font-size: 80%;
|
||||
font-family: Consolas, Inconsolata, "Courier New", monospace;
|
||||
cursor: pointer;
|
||||
vertical-align: bottom;
|
||||
white-space: pre;
|
||||
background-color: #fff;
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
border-radius: 3px;
|
||||
background-color: hsl(210,24%,16%);
|
||||
border: 1px solid hsl(210,24%,10%);
|
||||
}
|
||||
|
||||
.gcli-out-shortcut:before {
|
||||
color: #66F;
|
||||
content: '\bb';
|
||||
.gcli-out-shortcut:before,
|
||||
.gcli-help-synopsis:before {
|
||||
color: hsl(210,30%,85%);
|
||||
-moz-padding-end: 2px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/commands/help.css */
|
||||
|
||||
.gcli-help-arrow {
|
||||
font-size: 70%;
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis {
|
||||
font-family: Consolas, Inconsolata, "Courier New", monospace;
|
||||
font-weight: normal;
|
||||
padding: 0 3px;
|
||||
margin: 0 10px;
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.gcli-help-synopsis:before {
|
||||
color: #66F;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.gcli-help-description {
|
||||
@ -75,31 +102,22 @@
|
||||
margin: 10px 0 6px;
|
||||
}
|
||||
|
||||
|
||||
/* From: $GCLI/lib/gcli/ui/fields/menu.css */
|
||||
|
||||
.gcli-menu-name {
|
||||
-moz-padding-start: 8px;
|
||||
}
|
||||
|
||||
.gcli-menu-desc {
|
||||
-moz-padding-end: 8px;
|
||||
color: #999;
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
background-color: #EEE;
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
.gcli-menu-error {
|
||||
padding: 8px 10px 2px;
|
||||
font-size: 80%;
|
||||
color: red;
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-typed {
|
||||
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 308 B |
@ -179,6 +179,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/layoutview.css (devtools/layoutview.css)
|
||||
skin/classic/browser/devtools/layout-buttons.png (devtools/layout-buttons.png)
|
||||
skin/classic/browser/devtools/debugger-pause.png (devtools/debugger-pause.png)
|
||||
skin/classic/browser/devtools/debugger-play.png (devtools/debugger-play.png)
|
||||
skin/classic/browser/devtools/debugger-step-in.png (devtools/debugger-step-in.png)
|
||||
skin/classic/browser/devtools/debugger-step-out.png (devtools/debugger-step-out.png)
|
||||
skin/classic/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png)
|
||||
@ -373,6 +374,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/layoutview.css (devtools/layoutview.css)
|
||||
skin/classic/aero/browser/devtools/layout-buttons.png (devtools/layout-buttons.png)
|
||||
skin/classic/aero/browser/devtools/debugger-pause.png (devtools/debugger-pause.png)
|
||||
skin/classic/aero/browser/devtools/debugger-play.png (devtools/debugger-play.png)
|
||||
skin/classic/aero/browser/devtools/debugger-step-in.png (devtools/debugger-step-in.png)
|
||||
skin/classic/aero/browser/devtools/debugger-step-out.png (devtools/debugger-step-out.png)
|
||||
skin/classic/aero/browser/devtools/debugger-step-over.png (devtools/debugger-step-over.png)
|
||||
|
@ -255,6 +255,7 @@ _TEST_FILES1 = \
|
||||
test_DOMException.html \
|
||||
test_mutationobservers.html \
|
||||
mutationobserver_dialog.html \
|
||||
test_bug744830.html \
|
||||
$(NULL)
|
||||
|
||||
_TEST_FILES2 = \
|
||||
|
@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392511
|
||||
/** Test for Bug 392511 **/
|
||||
|
||||
var results = [
|
||||
"'\"&'",
|
||||
"\""&\"",
|
||||
"\""&\"",
|
||||
"\"'&\"",
|
||||
"\"'&\"",
|
||||
|
126
content/base/test/test_bug744830.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=744830
|
||||
-->
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=166235">Mozilla Bug 166235</a>
|
||||
<div id="testnodes"><span>hi</span> there <!-- mon ami --></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
var t = document.getElementById('testnodes');
|
||||
is(t.innerHTML,
|
||||
"<span>hi</span> there <!-- mon ami -->",
|
||||
"comment nodes should be included");
|
||||
|
||||
var PI = document.createProcessingInstruction('foo', 'bar="1.0"');
|
||||
t.appendChild(PI);
|
||||
is(t.innerHTML, '<span>hi</span> there <!-- mon ami --><?foo bar="1.0">',
|
||||
"pi nodes should be included");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("textarea"));
|
||||
t.firstChild.appendChild(document.createTextNode("\nhello"));
|
||||
// This is the old behavior. Spec requires something else.
|
||||
is(t.innerHTML, "<textarea>\nhello</textarea>",
|
||||
"No extra newlines should be inserted to the textarea!");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<svg><foo></svg>");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math:math"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<math><foo></math>");
|
||||
|
||||
// Prefix is serialized if element isn't HTML/SVG/MathML
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.example.org", "ex:example"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<ex:example><foo></ex:example>");
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.example.org", "example"));
|
||||
t.firstChild.textContent = "<foo>";
|
||||
is(t.innerHTML, "<example><foo></example>");
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "us-en");
|
||||
is(t.innerHTML, '<example xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo");
|
||||
is(t.innerHTML, '<example xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://foo");
|
||||
is(t.innerHTML, '<example xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:bar", "http://bar");
|
||||
is(t.innerHTML, '<example xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttributeNS("http://www.helloworldns.org", "hello:world", "!");
|
||||
is(t.innerHTML, '<example hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.firstChild.setAttribute("foo", '-"&\xA0-');
|
||||
is(t.innerHTML, '<example foo="-"& -" hello:world="!" xmlns:bar="http://bar" xmlns="http://foo" xlink:href="foo" xml:lang="us-en"><foo></example>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("div"));
|
||||
t.firstChild.appendChild(document.implementation
|
||||
.createDocument(null, null, null)
|
||||
.createCDATASection("foo"));
|
||||
is(t.innerHTML, '<div>foo</div>');
|
||||
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<div>1&2<3>4 </div>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("script"));
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<script>1&2<3>4\xA0\u003C/script>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElement("style"));
|
||||
t.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<style>1&2<3>4\xA0\u003C/style>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<svg><script>1&2<3>4 \u003C/script></svg>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "style"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/2000/svg");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<svg><style>1&2<3>4 \u003C/style></svg>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<math><script>1&2<3>4 \u003C/script></math>');
|
||||
|
||||
t.innerHTML = null;
|
||||
t.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"));
|
||||
is(t.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "style"));
|
||||
is(t.firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
|
||||
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
|
||||
is(t.innerHTML, '<math><style>1&2<3>4 \u003C/style></math>');
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "nsDOMMutationObserver.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -632,19 +633,609 @@ nsGenericHTMLElement::GetOffsetParent(nsIDOMElement** aOffsetParent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Try to keep the size of StringBuilder close to a jemalloc bucket size.
|
||||
#define STRING_BUFFER_UNITS 1020
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
private:
|
||||
class Unit
|
||||
{
|
||||
public:
|
||||
Unit() : mType(eUnknown), mLength(0) {}
|
||||
~Unit()
|
||||
{
|
||||
if (mType == eString || mType == eStringWithEncode) {
|
||||
delete mString;
|
||||
}
|
||||
}
|
||||
|
||||
enum Type
|
||||
{
|
||||
eUnknown,
|
||||
eAtom,
|
||||
eString,
|
||||
eStringWithEncode,
|
||||
eLiteral,
|
||||
eTextFragment,
|
||||
eTextFragmentWithEncode,
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
nsIAtom* mAtom;
|
||||
const char* mLiteral;
|
||||
nsAutoString* mString;
|
||||
const nsTextFragment* mTextFragment;
|
||||
};
|
||||
Type mType;
|
||||
PRUint32 mLength;
|
||||
};
|
||||
public:
|
||||
StringBuilder() : mLast(this), mLength(0) {}
|
||||
|
||||
void Append(nsIAtom* aAtom)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mAtom = aAtom;
|
||||
u->mType = Unit::eAtom;
|
||||
PRUint32 len = aAtom->GetLength();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void Append(const char (&aLiteral)[N])
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mLiteral = aLiteral;
|
||||
u->mType = Unit::eLiteral;
|
||||
PRUint32 len = N - 1;
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void Append(char (&aLiteral)[N])
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mLiteral = aLiteral;
|
||||
u->mType = Unit::eLiteral;
|
||||
PRUint32 len = N - 1;
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void Append(const nsAString& aString)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = new nsAutoString(aString);
|
||||
u->mType = Unit::eString;
|
||||
PRUint32 len = aString.Length();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void Append(nsAutoString* aString)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = aString;
|
||||
u->mType = Unit::eString;
|
||||
PRUint32 len = aString->Length();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void AppendWithAttrEncode(nsAutoString* aString, PRUint32 aLen)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mString = aString;
|
||||
u->mType = Unit::eStringWithEncode;
|
||||
u->mLength = aLen;
|
||||
mLength += aLen;
|
||||
}
|
||||
|
||||
void Append(const nsTextFragment* aTextFragment)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mTextFragment = aTextFragment;
|
||||
u->mType = Unit::eTextFragment;
|
||||
PRUint32 len = aTextFragment->GetLength();
|
||||
u->mLength = len;
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
void AppendWithEncode(const nsTextFragment* aTextFragment, PRUint32 aLen)
|
||||
{
|
||||
Unit* u = AddUnit();
|
||||
u->mTextFragment = aTextFragment;
|
||||
u->mType = Unit::eTextFragmentWithEncode;
|
||||
u->mLength = aLen;
|
||||
mLength += aLen;
|
||||
}
|
||||
|
||||
bool ToString(nsAString& aOut)
|
||||
{
|
||||
if (!aOut.SetCapacity(mLength, fallible_t())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (StringBuilder* current = this; current; current = current->mNext) {
|
||||
PRUint32 len = current->mUnits.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
Unit& u = current->mUnits[i];
|
||||
switch (u.mType) {
|
||||
case Unit::eAtom:
|
||||
aOut.Append(nsDependentAtomString(u.mAtom));
|
||||
break;
|
||||
case Unit::eString:
|
||||
aOut.Append(*(u.mString));
|
||||
break;
|
||||
case Unit::eStringWithEncode:
|
||||
EncodeAttrString(*(u.mString), aOut);
|
||||
break;
|
||||
case Unit::eLiteral:
|
||||
aOut.AppendASCII(u.mLiteral, u.mLength);
|
||||
break;
|
||||
case Unit::eTextFragment:
|
||||
u.mTextFragment->AppendTo(aOut);
|
||||
break;
|
||||
case Unit::eTextFragmentWithEncode:
|
||||
EncodeTextFragment(u.mTextFragment, aOut);
|
||||
break;
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unknown unit type?");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
Unit* AddUnit()
|
||||
{
|
||||
if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
|
||||
new StringBuilder(this);
|
||||
}
|
||||
return mLast->mUnits.AppendElement();
|
||||
}
|
||||
|
||||
StringBuilder(StringBuilder* aFirst)
|
||||
: mLast(nsnull), mLength(0)
|
||||
{
|
||||
aFirst->mLast->mNext = this;
|
||||
aFirst->mLast = this;
|
||||
}
|
||||
|
||||
void EncodeAttrString(const nsAutoString& aValue, nsAString& aOut)
|
||||
{
|
||||
const PRUnichar* c = aValue.BeginReading();
|
||||
const PRUnichar* end = aValue.EndReading();
|
||||
while (c < end) {
|
||||
switch (*c) {
|
||||
case '"':
|
||||
aOut.AppendLiteral(""");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(*c);
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeTextFragment(const nsTextFragment* aValue, nsAString& aOut)
|
||||
{
|
||||
PRUint32 len = aValue->GetLength();
|
||||
if (aValue->Is2b()) {
|
||||
const PRUnichar* data = aValue->Get2b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const PRUnichar c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
aOut.AppendLiteral("<");
|
||||
break;
|
||||
case '>':
|
||||
aOut.AppendLiteral(">");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* data = aValue->Get1b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const unsigned char c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
aOut.AppendLiteral("<");
|
||||
break;
|
||||
case '>':
|
||||
aOut.AppendLiteral(">");
|
||||
break;
|
||||
case '&':
|
||||
aOut.AppendLiteral("&");
|
||||
break;
|
||||
case 0x00A0:
|
||||
aOut.AppendLiteral(" ");
|
||||
break;
|
||||
default:
|
||||
aOut.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
|
||||
nsAutoPtr<StringBuilder> mNext;
|
||||
StringBuilder* mLast;
|
||||
// mLength is used only in the first StringBuilder object in the linked list.
|
||||
PRUint32 mLength;
|
||||
};
|
||||
|
||||
static void
|
||||
AppendEncodedCharacters(const nsTextFragment* aText, StringBuilder& aBuilder)
|
||||
{
|
||||
PRUint32 extraSpaceNeeded = 0;
|
||||
PRUint32 len = aText->GetLength();
|
||||
if (aText->Is2b()) {
|
||||
const PRUnichar* data = aText->Get2b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const PRUnichar c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
extraSpaceNeeded += ArrayLength("<") - 2;
|
||||
break;
|
||||
case '>':
|
||||
extraSpaceNeeded += ArrayLength(">") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const char* data = aText->Get1b();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
const unsigned char c = data[i];
|
||||
switch (c) {
|
||||
case '<':
|
||||
extraSpaceNeeded += ArrayLength("<") - 2;
|
||||
break;
|
||||
case '>':
|
||||
extraSpaceNeeded += ArrayLength(">") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extraSpaceNeeded) {
|
||||
aBuilder.AppendWithEncode(aText, len + extraSpaceNeeded);
|
||||
} else {
|
||||
aBuilder.Append(aText);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AppendEncodedAttributeValue(nsAutoString* aValue, StringBuilder& aBuilder)
|
||||
{
|
||||
const PRUnichar* c = aValue->BeginReading();
|
||||
const PRUnichar* end = aValue->EndReading();
|
||||
|
||||
PRUint32 extraSpaceNeeded = 0;
|
||||
while (c < end) {
|
||||
switch (*c) {
|
||||
case '"':
|
||||
extraSpaceNeeded += ArrayLength(""") - 2;
|
||||
break;
|
||||
case '&':
|
||||
extraSpaceNeeded += ArrayLength("&") - 2;
|
||||
break;
|
||||
case 0x00A0:
|
||||
extraSpaceNeeded += ArrayLength(" ") - 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
|
||||
if (extraSpaceNeeded) {
|
||||
aBuilder.AppendWithAttrEncode(aValue, aValue->Length() + extraSpaceNeeded);
|
||||
} else {
|
||||
aBuilder.Append(aValue);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
StartElement(Element* aContent, StringBuilder& aBuilder)
|
||||
{
|
||||
nsIAtom* localName = aContent->Tag();
|
||||
PRInt32 tagNS = aContent->GetNameSpaceID();
|
||||
|
||||
aBuilder.Append("<");
|
||||
if (aContent->IsHTML() || aContent->IsSVG() || aContent->IsMathML()) {
|
||||
aBuilder.Append(localName);
|
||||
} else {
|
||||
aBuilder.Append(aContent->NodeName());
|
||||
}
|
||||
|
||||
PRInt32 count = aContent->GetAttrCount();
|
||||
for (PRInt32 i = count; i > 0;) {
|
||||
--i;
|
||||
const nsAttrName* name = aContent->GetAttrNameAt(i);
|
||||
PRInt32 attNs = name->NamespaceID();
|
||||
nsIAtom* attName = name->LocalName();
|
||||
|
||||
// Filter out any attribute starting with [-|_]moz
|
||||
nsDependentAtomString attrNameStr(attName);
|
||||
if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
|
||||
StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString* attValue = new nsAutoString();
|
||||
aContent->GetAttr(attNs, attName, *attValue);
|
||||
|
||||
// Filter out special case of <br type="_moz*"> used by the editor.
|
||||
// Bug 16988. Yuck.
|
||||
if (localName == nsGkAtoms::br && tagNS == kNameSpaceID_XHTML &&
|
||||
attName == nsGkAtoms::type && attNs == kNameSpaceID_None &&
|
||||
StringBeginsWith(*attValue, NS_LITERAL_STRING("_moz"))) {
|
||||
delete attValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_LIKELY(attNs == kNameSpaceID_None) ||
|
||||
(attNs == kNameSpaceID_XMLNS &&
|
||||
attName == nsGkAtoms::xmlns)) {
|
||||
aBuilder.Append(" ");
|
||||
} else if (attNs == kNameSpaceID_XML) {
|
||||
aBuilder.Append(" xml:");
|
||||
} else if (attNs == kNameSpaceID_XMLNS) {
|
||||
aBuilder.Append(" xmlns:");
|
||||
} else if (attNs == kNameSpaceID_XLink) {
|
||||
aBuilder.Append(" xlink:");
|
||||
} else {
|
||||
nsIAtom* prefix = name->GetPrefix();
|
||||
if (prefix) {
|
||||
aBuilder.Append(" ");
|
||||
aBuilder.Append(prefix);
|
||||
aBuilder.Append(":");
|
||||
}
|
||||
}
|
||||
|
||||
aBuilder.Append(attName);
|
||||
aBuilder.Append("=\"");
|
||||
AppendEncodedAttributeValue(attValue, aBuilder);
|
||||
aBuilder.Append("\"");
|
||||
}
|
||||
|
||||
aBuilder.Append(">");
|
||||
|
||||
/*
|
||||
// Per HTML spec we should append one \n if the first child of
|
||||
// pre/textarea/listing is a textnode and starts with a \n.
|
||||
// But because browsers haven't traditionally had that behavior,
|
||||
// we're not changing our behavior either - yet.
|
||||
if (aContent->IsHTML()) {
|
||||
if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
|
||||
localName == nsGkAtoms::listing) {
|
||||
nsIContent* fc = aContent->GetFirstChild();
|
||||
if (fc &&
|
||||
(fc->NodeType() == nsIDOMNode::TEXT_NODE ||
|
||||
fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
|
||||
const nsTextFragment* text = fc->GetText();
|
||||
if (text && text->GetLength() && text->CharAt(0) == PRUnichar('\n')) {
|
||||
aBuilder.Append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ShouldEscape(nsIContent* aParent)
|
||||
{
|
||||
if (!aParent || !aParent->IsHTML()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const nsIAtom* nonEscapingElements[] = {
|
||||
nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
|
||||
nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
|
||||
nsGkAtoms::plaintext,
|
||||
// Per the current spec noscript should be escaped in case
|
||||
// scripts are disabled or if document doesn't have
|
||||
// browsing context. However the latter seems to be a spec bug
|
||||
// and Gecko hasn't traditionally done the former.
|
||||
nsGkAtoms::noscript
|
||||
};
|
||||
static mozilla::BloomFilter<12, nsIAtom> sFilter;
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
sInitialized = true;
|
||||
for (PRUint32 i = 0; i < ArrayLength(nonEscapingElements); ++i) {
|
||||
sFilter.add(nonEscapingElements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsIAtom* tag = aParent->Tag();
|
||||
if (sFilter.mightContain(tag)) {
|
||||
for (PRUint32 i = 0; i < ArrayLength(nonEscapingElements); ++i) {
|
||||
if (tag == nonEscapingElements[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsVoidTag(Element* aElement)
|
||||
{
|
||||
if (!aElement->IsHTML()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const nsIAtom* voidElements[] = {
|
||||
nsGkAtoms::area, nsGkAtoms::base, nsGkAtoms::basefont,
|
||||
nsGkAtoms::bgsound, nsGkAtoms::br, nsGkAtoms::col,
|
||||
nsGkAtoms::command, nsGkAtoms::embed, nsGkAtoms::frame,
|
||||
nsGkAtoms::hr, nsGkAtoms::img, nsGkAtoms::input,
|
||||
nsGkAtoms::keygen, nsGkAtoms::link, nsGkAtoms::meta,
|
||||
nsGkAtoms::param, nsGkAtoms::source, nsGkAtoms::track,
|
||||
nsGkAtoms::wbr
|
||||
};
|
||||
|
||||
static mozilla::BloomFilter<12, nsIAtom> sFilter;
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
sInitialized = true;
|
||||
for (PRUint32 i = 0; i < ArrayLength(voidElements); ++i) {
|
||||
sFilter.add(voidElements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nsIAtom* tag = aElement->Tag();
|
||||
if (sFilter.mightContain(tag)) {
|
||||
for (PRUint32 i = 0; i < ArrayLength(voidElements); ++i) {
|
||||
if (tag == voidElements[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
Serialize(Element* aRoot, bool aDescendentsOnly, nsAString& aOut)
|
||||
{
|
||||
nsINode* current = aDescendentsOnly ? aRoot->GetFirstChild() : aRoot;
|
||||
if (!current) {
|
||||
return true;
|
||||
}
|
||||
|
||||
StringBuilder builder;
|
||||
nsIContent* next;
|
||||
while (true) {
|
||||
bool isVoid = false;
|
||||
switch (current->NodeType()) {
|
||||
case nsIDOMNode::ELEMENT_NODE: {
|
||||
Element* elem = current->AsElement();
|
||||
StartElement(elem, builder);
|
||||
isVoid = IsVoidTag(elem);
|
||||
if (!isVoid && (next = current->GetFirstChild())) {
|
||||
current = next;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
case nsIDOMNode::CDATA_SECTION_NODE: {
|
||||
const nsTextFragment* text = static_cast<nsIContent*>(current)->GetText();
|
||||
nsIContent* parent = current->GetParent();
|
||||
if (ShouldEscape(parent)) {
|
||||
AppendEncodedCharacters(text, builder);
|
||||
} else {
|
||||
builder.Append(text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::COMMENT_NODE: {
|
||||
builder.Append("<!--");
|
||||
builder.Append(static_cast<nsIContent*>(current)->GetText());
|
||||
builder.Append("-->");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::DOCUMENT_TYPE_NODE: {
|
||||
builder.Append("<!DOCTYPE ");
|
||||
builder.Append(current->NodeName());
|
||||
builder.Append(">");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: {
|
||||
builder.Append("<?");
|
||||
builder.Append(current->NodeName());
|
||||
builder.Append(" ");
|
||||
builder.Append(static_cast<nsIContent*>(current)->GetText());
|
||||
builder.Append(">");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (!isVoid && current->NodeType() == nsIDOMNode::ELEMENT_NODE) {
|
||||
builder.Append("</");
|
||||
nsIContent* elem = static_cast<nsIContent*>(current);
|
||||
if (elem->IsHTML() || elem->IsSVG() || elem->IsMathML()) {
|
||||
builder.Append(elem->Tag());
|
||||
} else {
|
||||
builder.Append(current->NodeName());
|
||||
}
|
||||
builder.Append(">");
|
||||
}
|
||||
isVoid = false;
|
||||
|
||||
if (current == aRoot) {
|
||||
return builder.ToString(aOut);
|
||||
}
|
||||
|
||||
if ((next = current->GetNextSibling())) {
|
||||
current = next;
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->GetNodeParent();
|
||||
if (aDescendentsOnly && current == aRoot) {
|
||||
return builder.ToString(aOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
{
|
||||
aMarkup.Truncate();
|
||||
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (IsInHTMLDocument()) {
|
||||
return Serialize(this, !aIncludeSelf, aMarkup) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoString contentType;
|
||||
if (IsInHTMLDocument()) {
|
||||
contentType.AssignLiteral("text/html");
|
||||
} else {
|
||||
doc->GetContentType(contentType);
|
||||
}
|
||||
doc->GetContentType(contentType);
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
|
||||
if (!docEncoder) {
|
||||
@ -654,7 +1245,7 @@ nsGenericHTMLElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
|
||||
NS_ConvertUTF16toUTF8(contentType)
|
||||
).get());
|
||||
}
|
||||
if (!(docEncoder || doc->IsHTML())) {
|
||||
if (!docEncoder) {
|
||||
// This could be some type for which we create a synthetic document. Try
|
||||
// again as XML
|
||||
contentType.AssignLiteral("application/xml");
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "nsSVGSVGElement.h"
|
||||
#include "nsSVGTextContainerFrame.h"
|
||||
#include "SVGAnimatedPreserveAspectRatio.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1669,9 +1670,9 @@ nsSVGUtils::WritePPM(const char *fname, gfxImageSurface *aSurface)
|
||||
PRInt32 stride = aSurface->Stride();
|
||||
for (int y=0; y<size.height; y++) {
|
||||
for (int x=0; x<size.width; x++) {
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_R, 1, 1, f);
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_G, 1, 1, f);
|
||||
fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_B, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_R, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_G, 1, 1, f);
|
||||
unused << fwrite(data + y * stride + 4 * x + GFX_ARGB32_OFFSET_B, 1, 1, f);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
76
netwerk/base/src/AutoClose.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_AutoClose_h
|
||||
#define mozilla_net_AutoClose_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
// Like an nsAutoPtr for XPCOM streams (e.g. nsIAsyncInputStream) and other
|
||||
// refcounted classes that need to have the Close() method called explicitly
|
||||
// before they are destroyed.
|
||||
template <typename T>
|
||||
class AutoClose
|
||||
{
|
||||
public:
|
||||
AutoClose() { }
|
||||
~AutoClose(){
|
||||
Close();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
already_AddRefed<T> forget()
|
||||
{
|
||||
return mPtr.forget();
|
||||
}
|
||||
|
||||
void takeOver(AutoClose<T> & rhs)
|
||||
{
|
||||
Close();
|
||||
mPtr = rhs.mPtr.forget();
|
||||
}
|
||||
|
||||
// assign from |do_QueryInterface(expr, &rv)|
|
||||
void operator=(const nsQueryInterfaceWithError rhs)
|
||||
{
|
||||
Close();
|
||||
mPtr = rhs;
|
||||
}
|
||||
|
||||
void CloseAndRelease()
|
||||
{
|
||||
Close();
|
||||
mPtr = nsnull;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return mPtr.operator->();
|
||||
}
|
||||
|
||||
private:
|
||||
void Close()
|
||||
{
|
||||
if (mPtr) {
|
||||
mPtr->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(const AutoClose<T> &) MOZ_DELETE;
|
||||
AutoClose(const AutoClose<T> &) MOZ_DELETE;
|
||||
|
||||
nsCOMPtr<T> mPtr;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_AutoClose_h
|
14
netwerk/cache/nsCacheEntryDescriptor.cpp
vendored
@ -540,6 +540,11 @@ nsInputStreamWrapper::LazyInit()
|
||||
rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode,
|
||||
mStartOffset,
|
||||
getter_AddRefs(mInput));
|
||||
|
||||
CACHE_LOG_DEBUG(("nsInputStreamWrapper::LazyInit "
|
||||
"[entry=%p, wrapper=%p, mInput=%p, rv=%d]",
|
||||
mDescriptor, this, mInput.get(), PRIntn(rv)));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mInitialized = true;
|
||||
@ -568,9 +573,14 @@ nsresult nsCacheEntryDescriptor::
|
||||
nsInputStreamWrapper::Read(char *buf, PRUint32 count, PRUint32 *countRead)
|
||||
{
|
||||
nsresult rv = EnsureInit();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = mInput->Read(buf, count, countRead);
|
||||
|
||||
return mInput->Read(buf, count, countRead);
|
||||
CACHE_LOG_DEBUG(("nsInputStreamWrapper::Read "
|
||||
"[entry=%p, wrapper=%p, mInput=%p, rv=%d]",
|
||||
mDescriptor, this, mInput.get(), rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsCacheEntryDescriptor::
|
||||
|
2
netwerk/cache/nsCacheService.cpp
vendored
@ -1759,7 +1759,7 @@ nsCacheService::ProcessRequest(nsCacheRequest * request,
|
||||
|
||||
if (request->mListener) { // Asynchronous
|
||||
|
||||
if (NS_FAILED(rv) && calledFromOpenCacheEntry)
|
||||
if (NS_FAILED(rv) && calledFromOpenCacheEntry && request->IsBlocking())
|
||||
return rv; // skip notifying listener, just return rv to caller
|
||||
|
||||
// call listener to report error or descriptor
|
||||
|
19
netwerk/cache/nsDiskCacheBlockFile.cpp
vendored
@ -4,6 +4,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCache.h"
|
||||
#include "nsDiskCache.h"
|
||||
#include "nsDiskCacheBlockFile.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
@ -31,14 +32,15 @@ nsDiskCacheBlockFile::Open(nsILocalFile * blockFile,
|
||||
|
||||
// open the file - restricted to user, the data could be confidential
|
||||
nsresult rv = blockFile->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE, 00600, &mFD);
|
||||
if (NS_FAILED(rv)) return rv; // unable to open or create file
|
||||
if (NS_FAILED(rv)) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open "
|
||||
"[this=%p] unable to open or create file: %d",
|
||||
this, rv));
|
||||
return rv; // unable to open or create file
|
||||
}
|
||||
|
||||
// allocate bit map buffer
|
||||
mBitMap = new PRUint32[mBitMapWords];
|
||||
if (!mBitMap) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// check if we just creating the file
|
||||
mFileSize = PR_Available(mFD);
|
||||
@ -79,9 +81,13 @@ nsDiskCacheBlockFile::Open(nsILocalFile * blockFile,
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open [this=%p] succeeded",
|
||||
this));
|
||||
return NS_OK;
|
||||
|
||||
error_exit:
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Open [this=%p] failed with "
|
||||
"error %d", this, rv));
|
||||
Close(false);
|
||||
return rv;
|
||||
}
|
||||
@ -234,6 +240,9 @@ nsDiskCacheBlockFile::ReadBlocks( void * buffer,
|
||||
}
|
||||
*bytesRead = PR_Read(mFD, buffer, bytesToRead);
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Read [this=%p] "
|
||||
"returned %d / %d bytes", this, *bytesRead, bytesToRead));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
6
netwerk/cache/nsDiskCacheMap.cpp
vendored
@ -77,6 +77,8 @@ nsDiskCacheMap::Open(nsILocalFile * cacheDirectory)
|
||||
if (!cacheFilesExist)
|
||||
goto error_exit;
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheMap::Open [this=%p] reading map", this));
|
||||
|
||||
// read the header
|
||||
PRUint32 bytesRead = PR_Read(mMapFD, &mHeader, sizeof(nsDiskCacheHeader));
|
||||
if (sizeof(nsDiskCacheHeader) != bytesRead) goto error_exit;
|
||||
@ -686,7 +688,11 @@ nsDiskCacheMap::ReadDiskCacheEntry(nsDiskCacheRecord * record)
|
||||
getter_AddRefs(file));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheMap::ReadDiskCacheEntry"
|
||||
"[this=%p] reading disk cache entry", this));
|
||||
|
||||
PRFileDesc * fd = nsnull;
|
||||
|
||||
// open the file - restricted to user, the data could be confidential
|
||||
rv = file->OpenNSPRFileDesc(PR_RDONLY, 00600, &fd);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
34
netwerk/cache/nsDiskCacheStreams.cpp
vendored
@ -108,11 +108,25 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
{
|
||||
*bytesRead = 0;
|
||||
|
||||
if (mClosed)
|
||||
if (mClosed) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream was closed",
|
||||
this, buffer, count));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mPos == mStreamEnd) return NS_OK;
|
||||
if (mPos > mStreamEnd) return NS_ERROR_UNEXPECTED;
|
||||
if (mPos == mStreamEnd) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream at end of file",
|
||||
this, buffer, count));
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPos > mStreamEnd) {
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p] stream past end of file (!)",
|
||||
this, buffer, count));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (count > mStreamEnd - mPos)
|
||||
count = mStreamEnd - mPos;
|
||||
@ -120,7 +134,14 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
if (mFD) {
|
||||
// just read from file
|
||||
PRInt32 result = PR_Read(mFD, buffer, count);
|
||||
if (result < 0) return NS_ErrorAccordingToNSPR();
|
||||
if (result < 0) {
|
||||
PRErrorCode error = PR_GetError();
|
||||
nsresult rv = NS_ErrorAccordingToNSPR();
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read PR_Read failed"
|
||||
"[stream=%p, rv=%d, NSPR error %s",
|
||||
this, PRIntn(rv), PR_ErrorToName(error)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPos += (PRUint32)result;
|
||||
*bytesRead = (PRUint32)result;
|
||||
@ -134,6 +155,9 @@ nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead
|
||||
// no data source for input stream
|
||||
}
|
||||
|
||||
CACHE_LOG_DEBUG(("CACHE: nsDiskCacheInputStream::Read "
|
||||
"[stream=%p, count=%ud, byteRead=%ud] ",
|
||||
this, PRUintn(count), PRUintn(*bytesRead)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -679,6 +703,8 @@ nsDiskCacheStreamIO::OpenCacheFile(PRIntn flags, PRFileDesc ** fd)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(fd);
|
||||
|
||||
CACHE_LOG_DEBUG(("nsDiskCacheStreamIO::OpenCacheFile"));
|
||||
|
||||
nsresult rv;
|
||||
nsDiskCacheMap * cacheMap = mDevice->CacheMap();
|
||||
|
||||
|
@ -50,7 +50,6 @@ HttpBaseChannel::HttpBaseChannel()
|
||||
, mTimingEnabled(false)
|
||||
, mAllowSpdy(true)
|
||||
, mSuspendCount(0)
|
||||
, mRedirectedCachekeys(nsnull)
|
||||
{
|
||||
LOG(("Creating HttpBaseChannel @%x\n", this));
|
||||
|
||||
@ -1626,8 +1625,7 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
if (mRedirectedCachekeys) {
|
||||
LOG(("HttpBaseChannel::SetupReplacementChannel "
|
||||
"[this=%p] transferring chain of redirect cache-keys", this));
|
||||
httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys);
|
||||
mRedirectedCachekeys = nsnull;
|
||||
httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,10 +140,7 @@ public:
|
||||
|
||||
inline void CleanRedirectCacheChainIfNecessary()
|
||||
{
|
||||
if (mRedirectedCachekeys) {
|
||||
delete mRedirectedCachekeys;
|
||||
mRedirectedCachekeys = nsnull;
|
||||
}
|
||||
mRedirectedCachekeys = nsnull;
|
||||
}
|
||||
NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName,
|
||||
nsIHttpUpgradeListener *aListener);
|
||||
@ -272,7 +269,7 @@ protected:
|
||||
// Current suspension depth for this channel object
|
||||
PRUint32 mSuspendCount;
|
||||
|
||||
nsTArray<nsCString> *mRedirectedCachekeys;
|
||||
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
||||
};
|
||||
|
||||
// Share some code while working around C++'s absurd inability to handle casting
|
||||
|
@ -26,15 +26,17 @@
|
||||
#include "nsIHttpAuthenticableChannel.h"
|
||||
#include "nsIHttpChannelAuthProvider.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsDNSPrefetch.h"
|
||||
#include "TimingStruct.h"
|
||||
#include "AutoClose.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
class nsAHttpConnection;
|
||||
class AutoRedirectVetoNotifier;
|
||||
|
||||
using namespace mozilla::net;
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class HttpCacheQuery;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel
|
||||
@ -156,7 +158,8 @@ private:
|
||||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||
|
||||
bool RequestIsConditional();
|
||||
nsresult Connect(bool firstTime = true);
|
||||
nsresult Connect();
|
||||
nsresult ContinueConnect();
|
||||
void SpeculativeConnect();
|
||||
nsresult SetupTransaction();
|
||||
nsresult CallOnStartRequest();
|
||||
@ -172,7 +175,6 @@ private:
|
||||
nsresult ProcessFailedSSLConnect(PRUint32 httpStatus);
|
||||
nsresult ProcessFallback(bool *waitingForRedirectCallback);
|
||||
nsresult ContinueProcessFallback(nsresult);
|
||||
bool ResponseWouldVary();
|
||||
void HandleAsyncAbort();
|
||||
nsresult EnsureAssocReq();
|
||||
|
||||
@ -200,11 +202,11 @@ private:
|
||||
nsresult ResolveProxy();
|
||||
|
||||
// cache specific methods
|
||||
nsresult OpenCacheEntry();
|
||||
nsresult OpenCacheEntry(bool usingSSL);
|
||||
nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult aResult);
|
||||
nsresult OpenNormalCacheEntry();
|
||||
nsresult OpenNormalCacheEntry(bool usingSSL);
|
||||
nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult aResult);
|
||||
@ -219,8 +221,9 @@ private:
|
||||
nsresult GenerateCacheKey(PRUint32 postID, nsACString &key);
|
||||
nsresult UpdateExpirationTime();
|
||||
nsresult CheckCache();
|
||||
nsresult ShouldUpdateOfflineCacheEntry(bool *shouldCacheForOfflineUse);
|
||||
nsresult ReadFromCache();
|
||||
bool ShouldUpdateOfflineCacheEntry();
|
||||
nsresult StartBufferingCachedEntity(bool usingSSL);
|
||||
nsresult ReadFromCache(bool alreadyMarkedValid);
|
||||
void CloseCacheEntry(bool doomOnFailure);
|
||||
void CloseOfflineCacheEntry();
|
||||
nsresult InitCacheEntry();
|
||||
@ -232,7 +235,7 @@ private:
|
||||
nsresult InstallCacheListener(PRUint32 offset = 0);
|
||||
nsresult InstallOfflineCacheListener();
|
||||
void MaybeInvalidateCacheEntryForSubsequentGet();
|
||||
nsCacheStoragePolicy DetermineStoragePolicy();
|
||||
nsCacheStoragePolicy DetermineStoragePolicy(bool isPrivate);
|
||||
nsresult DetermineCacheAccess(nsCacheAccessMode *_retval);
|
||||
void AsyncOnExamineCachedResponse();
|
||||
|
||||
@ -240,12 +243,10 @@ private:
|
||||
void ClearBogusContentEncodingIfNeeded();
|
||||
|
||||
// byte range request specific methods
|
||||
nsresult SetupByteRangeRequest(PRUint32 partialLen);
|
||||
nsresult ProcessPartialContent();
|
||||
nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
|
||||
|
||||
nsresult DoAuthRetry(nsAHttpConnection *);
|
||||
bool MustValidateBasedOnQueryUrl();
|
||||
|
||||
void HandleAsyncRedirectChannelToHttps();
|
||||
nsresult AsyncRedirectChannelToHttps();
|
||||
@ -259,16 +260,10 @@ private:
|
||||
*/
|
||||
nsresult ProcessSTSHeader();
|
||||
|
||||
/**
|
||||
* Computes and returns a 64 bit encoded string holding a hash of the
|
||||
* input buffer. Input buffer must be a null-terminated string.
|
||||
*/
|
||||
nsresult Hash(const char *buf, nsACString &hash);
|
||||
|
||||
void InvalidateCacheEntryForLocation(const char *location);
|
||||
void AssembleCacheKey(const char *spec, PRUint32 postID, nsACString &key);
|
||||
nsresult CreateNewURI(const char *loc, nsIURI **newURI);
|
||||
void DoInvalidateCacheEntry(nsACString &key);
|
||||
void DoInvalidateCacheEntry(const nsCString &key);
|
||||
|
||||
// Ref RFC2616 13.10: "invalidation... MUST only be performed if
|
||||
// the host part is the same as in the Request-URI"
|
||||
@ -289,10 +284,15 @@ private:
|
||||
PRUint64 mLogicalOffset;
|
||||
|
||||
// cache specific data
|
||||
nsRefPtr<HttpCacheQuery> mCacheQuery;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||
// We must close mCacheAsyncInputStream explicitly to avoid leaks.
|
||||
AutoClose<nsIAsyncInputStream> mCacheAsyncInputStream;
|
||||
nsRefPtr<nsInputStreamPump> mCachePump;
|
||||
nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
|
||||
nsCOMPtr<nsISupports> mCachedSecurityInfo;
|
||||
nsCacheAccessMode mCacheAccess;
|
||||
mozilla::Telemetry::ID mCacheEntryDeviceTelemetryID;
|
||||
PRUint32 mPostID;
|
||||
PRUint32 mRequestTime;
|
||||
|
||||
@ -317,6 +317,8 @@ private:
|
||||
|
||||
friend class AutoRedirectVetoNotifier;
|
||||
friend class HttpAsyncAborter<nsHttpChannel>;
|
||||
friend class HttpCacheQuery;
|
||||
|
||||
nsCOMPtr<nsIURI> mRedirectURI;
|
||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
PRUint32 mRedirectType;
|
||||
@ -344,8 +346,6 @@ private:
|
||||
|
||||
nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
|
||||
|
||||
nsCOMPtr<nsICryptoHash> mHasher;
|
||||
|
||||
PRTime mChannelCreationTime;
|
||||
mozilla::TimeStamp mChannelCreationTimestamp;
|
||||
mozilla::TimeStamp mAsyncOpenTime;
|
||||
@ -374,4 +374,6 @@ private: // cache telemetry
|
||||
bool mDidReval;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::net
|
||||
|
||||
#endif // nsHttpChannel_h__
|
||||
|
@ -406,52 +406,6 @@ nsHttpHandler::IsAcceptableEncoding(const char *enc)
|
||||
return nsHttp::FindToken(mAcceptEncodings.get(), enc, HTTP_LWS ",") != nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate,
|
||||
nsICacheSession **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Skip cache if disabled in preferences
|
||||
if (!mUseCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// We want to get the pointer to the cache service each time we're called,
|
||||
// because it's possible for some add-ons (such as Google Gears) to swap
|
||||
// in new cache services on the fly, and we want to pick them up as
|
||||
// appropriate.
|
||||
nsCOMPtr<nsICacheService> serv = do_GetService(NS_CACHESERVICE_CONTRACTID,
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
const char *sessionName = "HTTP";
|
||||
switch (storagePolicy) {
|
||||
case nsICache::STORE_IN_MEMORY:
|
||||
sessionName = isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only";
|
||||
break;
|
||||
case nsICache::STORE_OFFLINE:
|
||||
sessionName = "HTTP-offline";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheSession> cacheSession;
|
||||
rv = serv->CreateSession(sessionName,
|
||||
storagePolicy,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(cacheSession));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = cacheSession->SetDoomEntriesIfExpired(false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ADDREF(*result = cacheSession);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
nsHttpConnectionMgr *ConnMgr() { return mConnMgr; }
|
||||
|
||||
// cache support
|
||||
nsresult GetCacheSession(nsCacheStoragePolicy, bool isPrivate, nsICacheSession **);
|
||||
bool UseCache() const { return mUseCache; }
|
||||
PRUint32 GenerateUniqueID() { return ++mLastUniqueID; }
|
||||
PRUint32 SessionStartTime() { return mSessionStartTime; }
|
||||
|
||||
|
@ -380,7 +380,11 @@ nsHttpResponseHead::IsResumable() const
|
||||
{
|
||||
// even though some HTTP/1.0 servers may support byte range requests, we're not
|
||||
// going to bother with them, since those servers wouldn't understand If-Range.
|
||||
return mVersion >= NS_HTTP_VERSION_1_1 &&
|
||||
// Also, while in theory it may be possible to resume when the status code
|
||||
// is not 200, it is unlikely to be worth the trouble, especially for
|
||||
// non-2xx responses.
|
||||
return mStatus == 200 &&
|
||||
mVersion >= NS_HTTP_VERSION_1_1 &&
|
||||
PeekHeader(nsHttp::Content_Length) &&
|
||||
(PeekHeader(nsHttp::ETag) || PeekHeader(nsHttp::Last_Modified)) &&
|
||||
HasHeaderValue(nsHttp::Accept_Ranges, "bytes");
|
||||
|
@ -491,10 +491,7 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint32 aKey, bool *_retval)
|
||||
// The user wants explicitely to use that result, so this ensures
|
||||
// association of the result with the autocompleted text.
|
||||
nsAutoString value;
|
||||
nsAutoString inputValue;
|
||||
input->GetTextValue(inputValue);
|
||||
if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, value)) &&
|
||||
value.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
|
||||
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(value))) {
|
||||
input->SetTextValue(value);
|
||||
input->SelectTextRange(value.Length(), value.Length());
|
||||
}
|
||||
@ -1184,10 +1181,7 @@ nsAutoCompleteController::EnterMatch(bool aIsPopupSelection)
|
||||
// The user wants explicitely to use that result, so this ensures
|
||||
// association of the result with the autocompleted text.
|
||||
nsAutoString defaultIndexValue;
|
||||
nsAutoString inputValue;
|
||||
input->GetTextValue(inputValue);
|
||||
if (NS_SUCCEEDED(GetDefaultCompleteValue(-1, false, defaultIndexValue)) &&
|
||||
defaultIndexValue.Equals(inputValue, nsCaseInsensitiveStringComparator()))
|
||||
if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(defaultIndexValue)))
|
||||
value = defaultIndexValue;
|
||||
}
|
||||
|
||||
@ -1444,34 +1438,34 @@ nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aResultIndex)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
bool aPreserveCasing,
|
||||
nsAString &_retval)
|
||||
nsAutoCompleteController::GetDefaultCompleteResult(PRInt32 aResultIndex,
|
||||
nsIAutoCompleteResult** _result,
|
||||
PRInt32* _defaultIndex)
|
||||
{
|
||||
PRInt32 defaultIndex = -1;
|
||||
PRInt32 index = aResultIndex;
|
||||
if (index < 0) {
|
||||
PRUint32 count = mResults.Count();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsIAutoCompleteResult *result = mResults[i];
|
||||
if (result && NS_SUCCEEDED(result->GetDefaultIndex(&defaultIndex)) &&
|
||||
defaultIndex >= 0) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
*_defaultIndex = -1;
|
||||
PRInt32 resultIndex = aResultIndex;
|
||||
|
||||
// If a result index was not provided, find the first defaultIndex result.
|
||||
for (PRInt32 i = 0; resultIndex < 0 && i < mResults.Count(); ++i) {
|
||||
nsIAutoCompleteResult *result = mResults[i];
|
||||
if (result &&
|
||||
NS_SUCCEEDED(result->GetDefaultIndex(_defaultIndex)) &&
|
||||
*_defaultIndex >= 0) {
|
||||
resultIndex = i;
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(index >= 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(resultIndex >= 0, NS_ERROR_FAILURE);
|
||||
|
||||
nsIAutoCompleteResult *result = mResults.SafeObjectAt(index);
|
||||
NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE);
|
||||
*_result = mResults.SafeObjectAt(resultIndex);
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_FAILURE);
|
||||
|
||||
if (defaultIndex < 0) {
|
||||
if (*_defaultIndex < 0) {
|
||||
// The search must explicitly provide a default index in order
|
||||
// for us to be able to complete.
|
||||
result->GetDefaultIndex(&defaultIndex);
|
||||
(*_result)->GetDefaultIndex(_defaultIndex);
|
||||
}
|
||||
if (defaultIndex < 0) {
|
||||
|
||||
if (*_defaultIndex < 0) {
|
||||
// We were given a result index, but that result doesn't want to
|
||||
// be autocompleted.
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1481,10 +1475,24 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
// provides a defaultIndex greater than its matchCount, avoid trying to
|
||||
// complete to an empty value.
|
||||
PRUint32 matchCount = 0;
|
||||
result->GetMatchCount(&matchCount);
|
||||
(*_result)->GetMatchCount(&matchCount);
|
||||
// Here defaultIndex is surely non-negative, so can be cast to unsigned.
|
||||
if ((PRUint32)defaultIndex >= matchCount)
|
||||
if ((PRUint32)(*_defaultIndex) >= matchCount) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
bool aPreserveCasing,
|
||||
nsAString &_retval)
|
||||
{
|
||||
nsIAutoCompleteResult *result;
|
||||
PRInt32 defaultIndex = -1;
|
||||
nsresult rv = GetDefaultCompleteResult(aResultIndex, &result, &defaultIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString resultValue;
|
||||
result->GetValueAt(defaultIndex, resultValue);
|
||||
@ -1512,6 +1520,37 @@ nsAutoCompleteController::GetDefaultCompleteValue(PRInt32 aResultIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::GetFinalDefaultCompleteValue(nsAString &_retval)
|
||||
{
|
||||
nsIAutoCompleteResult *result;
|
||||
PRInt32 defaultIndex = -1;
|
||||
nsresult rv = GetDefaultCompleteResult(-1, &result, &defaultIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Hack: For typeAheadResults allow the comment to be used as the final
|
||||
// defaultComplete value if provided, otherwise fall back to the usual
|
||||
// value. This allows to provide a different complete text when the user
|
||||
// confirms the match. Don't rely on this for production code, since it's a
|
||||
// temporary solution that needs a dedicated API (bug 754265).
|
||||
bool isTypeAheadResult = false;
|
||||
if (NS_SUCCEEDED(result->GetTypeAheadResult(&isTypeAheadResult)) &&
|
||||
isTypeAheadResult &&
|
||||
NS_SUCCEEDED(result->GetCommentAt(defaultIndex, _retval)) &&
|
||||
!_retval.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
result->GetValueAt(defaultIndex, _retval);
|
||||
nsAutoString inputValue;
|
||||
mInput->GetTextValue(inputValue);
|
||||
if (!_retval.Equals(inputValue, nsCaseInsensitiveStringComparator())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoCompleteController::CompleteValue(nsString &aValue)
|
||||
/* mInput contains mSearchString, which we want to autocomplete to aValue. If
|
||||
|
@ -66,8 +66,50 @@ private:
|
||||
nsresult GetResultValueLabelAt(PRInt32 aIndex, bool aValueOnly,
|
||||
bool aGetValue, nsAString & _retval);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Gets and validates the defaultComplete result and the relative
|
||||
* defaultIndex value.
|
||||
*
|
||||
* @param aResultIndex
|
||||
* Index of the defaultComplete result to be used. Pass -1 to search
|
||||
* for the first result providing a valid defaultIndex.
|
||||
* @param _result
|
||||
* The found result.
|
||||
* @param _defaultIndex
|
||||
* The defaultIndex relative to _result.
|
||||
*/
|
||||
nsresult GetDefaultCompleteResult(PRInt32 aResultIndex,
|
||||
nsIAutoCompleteResult** _result,
|
||||
PRInt32* _defaultIndex);
|
||||
|
||||
/**
|
||||
* Gets the defaultComplete value to be suggested to the user.
|
||||
*
|
||||
* @param aResultIndex
|
||||
* Index of the defaultComplete result to be used.
|
||||
* @param aPreserveCasing
|
||||
* Whether user casing should be preserved.
|
||||
* @param _retval
|
||||
* The value to be completed.
|
||||
*/
|
||||
nsresult GetDefaultCompleteValue(PRInt32 aResultIndex, bool aPreserveCasing,
|
||||
nsAString &_retval);
|
||||
|
||||
/**
|
||||
* Gets the defaultComplete value to be used when the user navigates or
|
||||
* confirms the current match.
|
||||
* The value is returned only if it case-insensitively matches the current
|
||||
* input text, otherwise the method returns NS_ERROR_FAILURE.
|
||||
* This happens because we don't want to override user casing in case of a
|
||||
* navigation key (unless the text is the same), or to replace text if the
|
||||
* user backspaces just before Enter.
|
||||
*
|
||||
* @param _retval
|
||||
* The value to be completed.
|
||||
*/
|
||||
nsresult GetFinalDefaultCompleteValue(nsAString &_retval);
|
||||
|
||||
nsresult ClearResults();
|
||||
|
||||
nsresult RowIndexToSearch(PRInt32 aRowIndex,
|
||||
|
@ -718,7 +718,12 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 14 uses schema version 20.
|
||||
if (currentSchemaVersion < 21) {
|
||||
rv = MigrateV21Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 14 uses schema version 21.
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
|
||||
@ -1839,6 +1844,39 @@ Database::MigrateV20Up()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::MigrateV21Up()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Add a prefix column to moz_hosts.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT prefix FROM moz_hosts"
|
||||
), getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"ALTER TABLE moz_hosts ADD COLUMN prefix"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Update prefixes.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> updatePrefixesStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_hosts SET prefix = ( "
|
||||
HOSTS_PREFIX_PRIORITY_FRAGMENT
|
||||
") "
|
||||
), getter_AddRefs(updatePrefixesStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
rv = updatePrefixesStmt->ExecuteAsync(nsnull, getter_AddRefs(ps));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Database::Shutdown()
|
||||
{
|
||||
|