зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 965527, bug 859059, bug 812172) for mochitest and xperf orange on a CLOSED TREE
Backed out changeset 18f579c4308e (bug 965527) Backed out changeset 70ed33107301 (bug 859059) Backed out changeset 7b59b92580fa (bug 812172)
This commit is contained in:
Родитель
cbd250673e
Коммит
d269ff5c2a
|
@ -140,9 +140,6 @@ Object.defineProperty(this, "NetworkHelper", {
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Curl",
|
||||
"resource:///modules/devtools/Curl.jsm");
|
||||
|
||||
/**
|
||||
* Object defining the network monitor controller components.
|
||||
*/
|
||||
|
|
|
@ -523,37 +523,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
clipboardHelper.copyString(selected.url, document);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy a cURL command from the currently selected item.
|
||||
*/
|
||||
copyAsCurl: function() {
|
||||
let selected = this.selectedItem.attachment;
|
||||
Task.spawn(function*() {
|
||||
// Create a sanitized object for the Curl command generator.
|
||||
let data = {
|
||||
url: selected.url,
|
||||
method: selected.method,
|
||||
headers: [],
|
||||
httpVersion: selected.httpVersion,
|
||||
postDataText: null
|
||||
};
|
||||
|
||||
// Fetch header values.
|
||||
for (let { name, value } of selected.requestHeaders.headers) {
|
||||
let text = yield gNetwork.getString(value);
|
||||
data.headers.push({ name: name, value: text });
|
||||
}
|
||||
|
||||
// Fetch the request payload.
|
||||
if (selected.requestPostData) {
|
||||
let postData = selected.requestPostData.postData.text;
|
||||
data.postDataText = yield gNetwork.getString(postData);
|
||||
}
|
||||
|
||||
clipboardHelper.copyString(Curl.generateCommand(data), document);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy image as data uri.
|
||||
*/
|
||||
|
@ -1591,9 +1560,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
let copyUrlElement = $("#request-menu-context-copy-url");
|
||||
copyUrlElement.hidden = !selectedItem;
|
||||
|
||||
let copyAsCurlElement = $("#request-menu-context-copy-as-curl");
|
||||
copyAsCurlElement.hidden = !selectedItem || !selectedItem.attachment.responseContent;
|
||||
|
||||
let copyImageAsDataUriElement = $("#request-menu-context-copy-image-as-data-uri");
|
||||
copyImageAsDataUriElement.hidden = !selectedItem ||
|
||||
!selectedItem.attachment.responseContent ||
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
<menuitem id="request-menu-context-copy-url"
|
||||
label="&netmonitorUI.context.copyUrl;"
|
||||
accesskey="&netmonitorUI.context.copyUrl.accesskey;"/>
|
||||
<menuitem id="request-menu-context-copy-as-curl"
|
||||
label="&netmonitorUI.context.copyAsCurl;"
|
||||
oncommand="NetMonitorView.RequestsMenu.copyAsCurl();"/>
|
||||
<menuitem id="request-menu-context-copy-image-as-data-uri"
|
||||
label="&netmonitorUI.context.copyImageAsDataUri;"
|
||||
accesskey="&netmonitorUI.context.copyImageAsDataUri.accesskey;"/>
|
||||
|
|
|
@ -21,8 +21,6 @@ support-files =
|
|||
html_sorting-test-page.html
|
||||
html_statistics-test-page.html
|
||||
html_status-codes-test-page.html
|
||||
html_copy-as-curl.html
|
||||
html_curl-utils.html
|
||||
sjs_content-type-test-server.sjs
|
||||
sjs_simple-test-server.sjs
|
||||
sjs_sorting-test-server.sjs
|
||||
|
@ -41,10 +39,8 @@ support-files =
|
|||
[browser_net_clear.js]
|
||||
[browser_net_complex-params.js]
|
||||
[browser_net_content-type.js]
|
||||
[browser_net_curl-utils.js]
|
||||
[browser_net_copy_image_as_data_uri.js]
|
||||
[browser_net_copy_url.js]
|
||||
[browser_net_copy_as_curl.js]
|
||||
[browser_net_cyrillic-01.js]
|
||||
[browser_net_cyrillic-02.js]
|
||||
[browser_net_filter-01.js]
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if Copy as cURL works.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(CURL_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
const EXPECTED_POSIX_RESULT = [
|
||||
"curl",
|
||||
"'" + SIMPLE_SJS + "'",
|
||||
"-H 'Host: example.com'",
|
||||
"-H 'User-Agent: " + aDebuggee.navigator.userAgent + "'",
|
||||
"-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'",
|
||||
"-H 'Accept-Language: " + aDebuggee.navigator.language + "'",
|
||||
"-H 'Accept-Encoding: gzip, deflate'",
|
||||
"-H 'X-Custom-Header-1: Custom value'",
|
||||
"-H 'X-Custom-Header-2: 8.8.8.8'",
|
||||
"-H 'X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
|
||||
"-H 'Referer: " + CURL_URL + "'",
|
||||
"-H 'Connection: keep-alive'"
|
||||
].join(" ");
|
||||
|
||||
const EXPECTED_WIN_RESULT = [
|
||||
'curl',
|
||||
'"' + SIMPLE_SJS + '"',
|
||||
'-H "Host: example.com"',
|
||||
'-H "User-Agent: ' + aDebuggee.navigator.userAgent + '"',
|
||||
'-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"',
|
||||
'-H "Accept-Language: ' + aDebuggee.navigator.language + '"',
|
||||
'-H "Accept-Encoding: gzip, deflate"',
|
||||
'-H "X-Custom-Header-1: Custom value"',
|
||||
'-H "X-Custom-Header-2: 8.8.8.8"',
|
||||
'-H "X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
|
||||
'-H "Referer: ' + CURL_URL + '"',
|
||||
'-H "Connection: keep-alive"'
|
||||
].join(" ");
|
||||
|
||||
const EXPECTED_RESULT = Services.appinfo.OS == "WINNT" ?
|
||||
EXPECTED_WIN_RESULT : EXPECTED_POSIX_RESULT;
|
||||
|
||||
let { NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1).then(() => {
|
||||
let requestItem = RequestsMenu.getItemAtIndex(0);
|
||||
RequestsMenu.selectedItem = requestItem;
|
||||
|
||||
waitForClipboard(EXPECTED_RESULT, function setup() {
|
||||
RequestsMenu.copyAsCurl();
|
||||
}, function onSuccess() {
|
||||
ok(true, "Clipboard contains a cURL command for the currently selected item's url.");
|
||||
cleanUp();
|
||||
}, function onFailure() {
|
||||
ok(false, "Creating a cURL command for the currently selected item was unsuccessful.");
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
aDebuggee.performRequest(SIMPLE_SJS);
|
||||
|
||||
function cleanUp(){
|
||||
teardown(aMonitor).then(finish);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests Curl Utils functionality.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(CURL_UTILS_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { NetMonitorView, gNetwork } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1, 3).then(() => {
|
||||
let requests = {
|
||||
get: RequestsMenu.getItemAtIndex(0),
|
||||
post: RequestsMenu.getItemAtIndex(1),
|
||||
multipart: RequestsMenu.getItemAtIndex(2),
|
||||
multipartForm: RequestsMenu.getItemAtIndex(3)
|
||||
};
|
||||
|
||||
Task.spawn(function*() {
|
||||
yield createCurlData(requests.get.attachment, gNetwork).then((aData) => {
|
||||
test_findHeader(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.post.attachment, gNetwork).then((aData) => {
|
||||
test_isUrlEncodedRequest(aData);
|
||||
test_writePostDataTextParams(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.multipart.attachment, gNetwork).then((aData) => {
|
||||
test_isMultipartRequest(aData);
|
||||
test_getMultipartBoundary(aData);
|
||||
test_removeBinaryDataFromMultipartText(aData);
|
||||
});
|
||||
|
||||
yield createCurlData(requests.multipartForm.attachment, gNetwork).then((aData) => {
|
||||
test_getHeadersFromMultipartText(aData);
|
||||
});
|
||||
|
||||
if (Services.appinfo.OS != "WINNT") {
|
||||
test_escapeStringPosix();
|
||||
} else {
|
||||
test_escapeStringWin();
|
||||
}
|
||||
|
||||
teardown(aMonitor).then(finish);
|
||||
});
|
||||
});
|
||||
|
||||
aDebuggee.performRequests(SIMPLE_SJS);
|
||||
});
|
||||
}
|
||||
|
||||
function test_isUrlEncodedRequest(aData) {
|
||||
let isUrlEncoded = CurlUtils.isUrlEncodedRequest(aData);
|
||||
ok(isUrlEncoded, "Should return true for url encoded requests.");
|
||||
}
|
||||
|
||||
function test_isMultipartRequest(aData) {
|
||||
let isMultipart = CurlUtils.isMultipartRequest(aData);
|
||||
ok(isMultipart, "Should return true for multipart/form-data requests.");
|
||||
}
|
||||
|
||||
function test_findHeader(aData) {
|
||||
let headers = aData.headers;
|
||||
let hostName = CurlUtils.findHeader(headers, "Host");
|
||||
let requestedWithLowerCased = CurlUtils.findHeader(headers, "x-requested-with");
|
||||
let doesNotExist = CurlUtils.findHeader(headers, "X-Does-Not-Exist");
|
||||
|
||||
is(hostName, "example.com",
|
||||
"Header with name 'Host' should be found in the request array.");
|
||||
is(requestedWithLowerCased, "XMLHttpRequest",
|
||||
"The search should be case insensitive.");
|
||||
is(doesNotExist, null,
|
||||
"Should return null when a header is not found.");
|
||||
}
|
||||
|
||||
function test_writePostDataTextParams(aData) {
|
||||
let params = CurlUtils.writePostDataTextParams(aData.postDataText);
|
||||
is(params, "param1=value1¶m2=value2¶m3=value3",
|
||||
"Should return a serialized representation of the request parameters");
|
||||
}
|
||||
|
||||
function test_getMultipartBoundary(aData) {
|
||||
let boundary = CurlUtils.getMultipartBoundary(aData);
|
||||
ok(/-{3,}\w+/.test(boundary),
|
||||
"A boundary string should be found in a multipart request.");
|
||||
}
|
||||
|
||||
function test_removeBinaryDataFromMultipartText(aData) {
|
||||
let generatedBoundary = CurlUtils.getMultipartBoundary(aData);
|
||||
let text = aData.postDataText;
|
||||
let binaryRemoved =
|
||||
CurlUtils.removeBinaryDataFromMultipartText(text, generatedBoundary);
|
||||
let boundary = "--" + generatedBoundary;
|
||||
|
||||
const EXPECTED_POSIX_RESULT = [
|
||||
"$'",
|
||||
boundary,
|
||||
"\\r\\n\\r\\n",
|
||||
"Content-Disposition: form-data; name=\"param1\"",
|
||||
"\\r\\n\\r\\n",
|
||||
"value1",
|
||||
"\\r\\n",
|
||||
boundary,
|
||||
"\\r\\n\\r\\n",
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"filename.png\"",
|
||||
"\\r\\n",
|
||||
"Content-Type: image/png",
|
||||
"\\r\\n\\r\\n",
|
||||
generatedBoundary,
|
||||
"--\\r\\n",
|
||||
"'"
|
||||
].join("");
|
||||
|
||||
const EXPECTED_WIN_RESULT = [
|
||||
'"' + boundary + '"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"Content-Disposition: form-data; name=""param1"""^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"value1"^',
|
||||
'\u000d\u000A',
|
||||
'"' + boundary + '"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"Content-Disposition: form-data; name=""file""; filename=""filename.png"""^',
|
||||
'\u000d\u000A',
|
||||
'"Content-Type: image/png"^',
|
||||
'\u000d\u000A\u000d\u000A',
|
||||
'"' + generatedBoundary + '--"^',
|
||||
'\u000d\u000A',
|
||||
'""'
|
||||
].join("");
|
||||
|
||||
if (Services.appinfo.OS != "WINNT") {
|
||||
is(CurlUtils.escapeStringPosix(binaryRemoved), EXPECTED_POSIX_RESULT,
|
||||
"The mulitpart request payload should not contain binary data.");
|
||||
} else {
|
||||
is(CurlUtils.escapeStringWin(binaryRemoved), EXPECTED_WIN_RESULT,
|
||||
"WinNT: The mulitpart request payload should not contain binary data.");
|
||||
}
|
||||
}
|
||||
|
||||
function test_getHeadersFromMultipartText(aData) {
|
||||
let headers = CurlUtils.getHeadersFromMultipartText(aData.postDataText);
|
||||
|
||||
ok(Array.isArray(headers),
|
||||
"Should return an array.");
|
||||
ok(headers.length > 0,
|
||||
"There should exist at least one request header.");
|
||||
is(headers[0].name, "Content-Type",
|
||||
"The first header name should be 'Content-Type'.");
|
||||
}
|
||||
|
||||
function test_escapeStringPosix() {
|
||||
let surroundedWithQuotes = "A simple string";
|
||||
is(CurlUtils.escapeStringPosix(surroundedWithQuotes), "'A simple string'",
|
||||
"The string should be surrounded with single quotes.");
|
||||
|
||||
let singleQuotes = "It's unusual to put crickets in your coffee.";
|
||||
is(CurlUtils.escapeStringPosix(singleQuotes),
|
||||
"$'It\\'s unusual to put crickets in your coffee.'",
|
||||
"Single quotes should be escaped.");
|
||||
|
||||
let newLines = "Line 1\r\nLine 2\u000d\u000ALine3";
|
||||
is(CurlUtils.escapeStringPosix(newLines), "$'Line 1\\r\\nLine 2\\r\\nLine3'",
|
||||
"Newlines should be escaped.");
|
||||
|
||||
let controlChars = "\u0007 \u0009 \u000C \u001B";
|
||||
is(CurlUtils.escapeStringPosix(controlChars), "$'\\x07 \\x09 \\x0c \\x1b'",
|
||||
"Control characters should be escaped.");
|
||||
|
||||
let extendedAsciiChars = "æ ø ü ß ö é";
|
||||
is(CurlUtils.escapeStringPosix(extendedAsciiChars),
|
||||
"$'\\xc3\\xa6 \\xc3\\xb8 \\xc3\\xbc \\xc3\\x9f \\xc3\\xb6 \\xc3\\xa9'",
|
||||
"Character codes outside of the decimal range 32 - 126 should be escaped.");
|
||||
}
|
||||
|
||||
function test_escapeStringWin() {
|
||||
let surroundedWithDoubleQuotes = "A simple string";
|
||||
is(CurlUtils.escapeStringWin(surroundedWithDoubleQuotes), '"A simple string"',
|
||||
"The string should be surrounded with double quotes.");
|
||||
|
||||
let doubleQuotes = "Quote: \"Time is an illusion. Lunchtime doubly so.\"";
|
||||
is(CurlUtils.escapeStringWin(doubleQuotes),
|
||||
'"Quote: ""Time is an illusion. Lunchtime doubly so."""',
|
||||
"Double quotes should be escaped.");
|
||||
|
||||
let percentSigns = "%AppData%";
|
||||
is(CurlUtils.escapeStringWin(percentSigns), '""%"AppData"%""',
|
||||
"Percent signs should be escaped.");
|
||||
|
||||
let backslashes = "\\A simple string\\";
|
||||
is(CurlUtils.escapeStringWin(backslashes), '"\\\\A simple string\\\\"',
|
||||
"Backslashes should be escaped.");
|
||||
|
||||
let newLines = "line1\r\nline2\r\nline3";
|
||||
is(CurlUtils.escapeStringWin(newLines),
|
||||
'"line1"^\u000d\u000A"line2"^\u000d\u000A"line3"',
|
||||
"Newlines should be escaped.");
|
||||
}
|
||||
|
||||
function createCurlData(aSelected, aNetwork) {
|
||||
return Task.spawn(function*() {
|
||||
// Create a sanitized object for the Curl command generator.
|
||||
let data = {
|
||||
url: aSelected.url,
|
||||
method: aSelected.method,
|
||||
headers: [],
|
||||
httpVersion: aSelected.httpVersion,
|
||||
postDataText: null
|
||||
};
|
||||
|
||||
// Fetch header values.
|
||||
for (let { name, value } of aSelected.requestHeaders.headers) {
|
||||
let text = yield aNetwork.getString(value);
|
||||
data.headers.push({ name: name, value: text });
|
||||
}
|
||||
|
||||
// Fetch the request payload.
|
||||
if (aSelected.requestPostData) {
|
||||
let postData = aSelected.requestPostData.postData.text;
|
||||
data.postDataText = yield aNetwork.getString(postData);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}
|
|
@ -9,7 +9,6 @@ let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
|||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { CurlUtils } = Cu.import("resource:///modules/devtools/Curl.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
let Toolbox = devtools.Toolbox;
|
||||
|
||||
|
@ -35,8 +34,6 @@ const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
|
|||
const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";
|
||||
const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html";
|
||||
const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
|
||||
const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
|
||||
const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
|
||||
|
||||
const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
|
||||
const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Performing a GET request</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function performRequest(aUrl) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aUrl, true);
|
||||
xhr.setRequestHeader("Accept-Language", window.navigator.language);
|
||||
xhr.setRequestHeader("X-Custom-Header-1", "Custom value");
|
||||
xhr.setRequestHeader("X-Custom-Header-2", "8.8.8.8");
|
||||
xhr.setRequestHeader("X-Custom-Header-3", "Mon, 3 Mar 2014 11:11:11 GMT");
|
||||
xhr.send(null);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,99 +0,0 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Network Monitor test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Performing requests</p>
|
||||
|
||||
<p>
|
||||
<canvas width="100" height="100"></canvas>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<form method="post" action="#" enctype="multipart/form-data" target="target" id="post-form">
|
||||
<input type="text" name="param1" value="value1"/>
|
||||
<input type="text" name="param2" value="value2"/>
|
||||
<input type="text" name="param3" value="value3"/>
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
<iframe name="target"></iframe>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function ajaxGet(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aUrl + "?param1=value1¶m2=value2¶m3=value3", true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function ajaxPost(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aUrl, true);
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
var params = "param1=value1¶m2=value2¶m3=value3";
|
||||
xhr.send(params);
|
||||
}
|
||||
|
||||
function ajaxMultipart(aUrl, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aUrl, true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
xhr.onload = function() {
|
||||
aCallback();
|
||||
};
|
||||
|
||||
getCanvasElem().toBlob((blob) => {
|
||||
var formData = new FormData();
|
||||
formData.append("param1", "value1");
|
||||
formData.append("file", blob, "filename.png");
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
var form = document.querySelector("#post-form");
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function getCanvasElem() {
|
||||
return document.querySelector("canvas");
|
||||
}
|
||||
|
||||
function initCanvas() {
|
||||
var canvas = getCanvasElem();
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillRect(0,0,100,100);
|
||||
ctx.clearRect(20,20,60,60);
|
||||
ctx.strokeRect(25,25,50,50);
|
||||
}
|
||||
|
||||
function performRequests(aUrl) {
|
||||
ajaxGet(aUrl, () => {
|
||||
ajaxPost(aUrl, () => {
|
||||
ajaxMultipart(aUrl, () => {
|
||||
submitForm();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initCanvas();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,396 +0,0 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
|
||||
* Copyright (C) 2011 Google Inc. All rights reserved.
|
||||
* Copyright (C) 2009 Mozilla Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Curl", "CurlUtils"];
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const DEFAULT_HTTP_VERSION = "HTTP/1.1";
|
||||
|
||||
this.Curl = {
|
||||
/**
|
||||
* Generates a cURL command string which can be used from the command line etc.
|
||||
*
|
||||
* @param object aData
|
||||
* Datasource to create the command from.
|
||||
* The object must contain the following properties:
|
||||
* - url:string, the URL of the request.
|
||||
* - method:string, the request method upper cased. HEAD / GET / POST etc.
|
||||
* - headers:array, an array of request headers {name:x, value:x} tuples.
|
||||
* - httpVersion:string, http protocol version rfc2616 formatted. Eg. "HTTP/1.1"
|
||||
* - postDataText:string, optional - the request payload.
|
||||
*
|
||||
* @return string
|
||||
* A cURL command.
|
||||
*/
|
||||
generateCommand: function(aData) {
|
||||
let utils = CurlUtils;
|
||||
|
||||
let command = ["curl"];
|
||||
let ignoredHeaders = new Set();
|
||||
|
||||
// The cURL command is expected to run on the same platform that Firefox runs
|
||||
// (it may be different from the inspected page platform).
|
||||
let escapeString = Services.appinfo.OS == "WINNT" ?
|
||||
utils.escapeStringWin : utils.escapeStringPosix;
|
||||
|
||||
// Add URL.
|
||||
command.push(escapeString(aData.url));
|
||||
|
||||
let postDataText = null;
|
||||
let multipartRequest = utils.isMultipartRequest(aData);
|
||||
|
||||
// Create post data.
|
||||
let data = [];
|
||||
if (utils.isUrlEncodedRequest(aData) || aData.method == "PUT") {
|
||||
postDataText = aData.postDataText;
|
||||
data.push("--data");
|
||||
data.push(escapeString(utils.writePostDataTextParams(postDataText)));
|
||||
ignoredHeaders.add("Content-Length");
|
||||
} else if (multipartRequest) {
|
||||
postDataText = aData.postDataText;
|
||||
data.push("--data-binary");
|
||||
let boundary = utils.getMultipartBoundary(aData);
|
||||
let text = utils.removeBinaryDataFromMultipartText(postDataText, boundary);
|
||||
data.push(escapeString(text));
|
||||
ignoredHeaders.add("Content-Length");
|
||||
}
|
||||
|
||||
// Add method.
|
||||
// For GET and POST requests this is not necessary as GET is the
|
||||
// default. If --data or --binary is added POST is the default.
|
||||
if (!(aData.method == "GET" || aData.method == "POST")) {
|
||||
command.push("-X");
|
||||
command.push(aData.method);
|
||||
}
|
||||
|
||||
// Add -I (HEAD)
|
||||
// For servers that supports HEAD.
|
||||
// This will fetch the header of a document only.
|
||||
if (aData.method == "HEAD") {
|
||||
command.push("-I");
|
||||
}
|
||||
|
||||
// Add http version.
|
||||
if (aData.httpVersion && aData.httpVersion != DEFAULT_HTTP_VERSION) {
|
||||
command.push("--" + aData.httpVersion.split("/")[1]);
|
||||
}
|
||||
|
||||
// Add request headers.
|
||||
let headers = aData.headers;
|
||||
if (multipartRequest) {
|
||||
let multipartHeaders = utils.getHeadersFromMultipartText(postDataText);
|
||||
headers = headers.concat(multipartHeaders);
|
||||
}
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let header = headers[i];
|
||||
if (ignoredHeaders.has(header.name)) {
|
||||
continue;
|
||||
}
|
||||
command.push("-H");
|
||||
command.push(escapeString(header.name + ": " + header.value));
|
||||
}
|
||||
|
||||
// Add post data.
|
||||
command = command.concat(data);
|
||||
|
||||
return command.join(" ");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility functions for the Curl command generator.
|
||||
*/
|
||||
this.CurlUtils = {
|
||||
/**
|
||||
* Check if the request is an URL encoded request.
|
||||
*
|
||||
* @param object aData
|
||||
* The data source. See the description in the Curl object.
|
||||
* @return boolean
|
||||
* True if the request is URL encoded, false otherwise.
|
||||
*/
|
||||
isUrlEncodedRequest: function(aData) {
|
||||
let postDataText = aData.postDataText;
|
||||
if (!postDataText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postDataText = postDataText.toLowerCase();
|
||||
if (postDataText.contains("content-type: application/x-www-form-urlencoded")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let contentType = this.findHeader(aData.headers, "content-type");
|
||||
|
||||
return (contentType &&
|
||||
contentType.toLowerCase().contains("application/x-www-form-urlencoded"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the request is a multipart request.
|
||||
*
|
||||
* @param object aData
|
||||
* The data source.
|
||||
* @return boolean
|
||||
* True if the request is multipart reqeust, false otherwise.
|
||||
*/
|
||||
isMultipartRequest: function(aData) {
|
||||
let postDataText = aData.postDataText;
|
||||
if (!postDataText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
postDataText = postDataText.toLowerCase();
|
||||
if (postDataText.contains("content-type: multipart/form-data")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let contentType = this.findHeader(aData.headers, "content-type");
|
||||
|
||||
return (contentType &&
|
||||
contentType.toLowerCase().contains("multipart/form-data;"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Write out paramters from post data text.
|
||||
*
|
||||
* @param object aPostDataText
|
||||
* Post data text.
|
||||
* @return string
|
||||
* Post data parameters.
|
||||
*/
|
||||
writePostDataTextParams: function(aPostDataText) {
|
||||
let lines = aPostDataText.split("\r\n");
|
||||
return lines[lines.length - 1];
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the header with the given name in the headers array.
|
||||
*
|
||||
* @param array aHeaders
|
||||
* Array of headers info {name:x, value:x}.
|
||||
* @param string aName
|
||||
* The header name to find.
|
||||
* @return string
|
||||
* The found header value or null if not found.
|
||||
*/
|
||||
findHeader: function(aHeaders, aName) {
|
||||
if (!aHeaders) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let name = aName.toLowerCase();
|
||||
for (let header of aHeaders) {
|
||||
if (name == header.name.toLowerCase()) {
|
||||
return header.value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the boundary string for a multipart request.
|
||||
*
|
||||
* @param string aData
|
||||
* The data source. See the description in the Curl object.
|
||||
* @return string
|
||||
* The boundary string for the request.
|
||||
*/
|
||||
getMultipartBoundary: function(aData) {
|
||||
let boundaryRe = /\bboundary=(-{3,}\w+)/i;
|
||||
|
||||
// Get the boundary string from the Content-Type request header.
|
||||
let contentType = this.findHeader(aData.headers, "Content-Type");
|
||||
if (boundaryRe.test(contentType)) {
|
||||
return contentType.match(boundaryRe)[1];
|
||||
}
|
||||
// Temporary workaround. As of 2014-03-11 the requestHeaders array does not
|
||||
// always contain the Content-Type header for mulitpart requests. See bug 978144.
|
||||
// Find the header from the request payload.
|
||||
let boundaryString = aData.postDataText.match(boundaryRe)[1];
|
||||
if (boundaryString) {
|
||||
return boundaryString;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the binary data from mulitpart text.
|
||||
*
|
||||
* @param string aMultipartText
|
||||
* Multipart form data text.
|
||||
* @param string aBoundary
|
||||
* The boundary string.
|
||||
* @return string
|
||||
* The mulitpart text without the binary data.
|
||||
*/
|
||||
removeBinaryDataFromMultipartText: function(aMultipartText, aBoundary) {
|
||||
let result = "";
|
||||
let boundary = "--" + aBoundary;
|
||||
let parts = aMultipartText.split(boundary);
|
||||
for (let part of parts) {
|
||||
// Each part is expected to have a content disposition line.
|
||||
let contentDispositionLine = part.trimLeft().split("\r\n")[0];
|
||||
if (!contentDispositionLine) {
|
||||
continue;
|
||||
}
|
||||
contentDispositionLine = contentDispositionLine.toLowerCase();
|
||||
if (contentDispositionLine.contains("content-disposition: form-data")) {
|
||||
if (contentDispositionLine.contains("filename=")) {
|
||||
// The header lines and the binary blob is separated by 2 CRLF's.
|
||||
// Add only the headers to the result.
|
||||
let headers = part.split("\r\n\r\n")[0];
|
||||
result += boundary + "\r\n" + headers + "\r\n\r\n";
|
||||
}
|
||||
else {
|
||||
result += boundary + "\r\n" + part;
|
||||
}
|
||||
}
|
||||
}
|
||||
result += aBoundary + "--\r\n";
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the headers from a multipart post data text.
|
||||
*
|
||||
* @param string aMultipartText
|
||||
* Multipart post text.
|
||||
* @return array
|
||||
* An array of header objects {name:x, value:x}
|
||||
*/
|
||||
getHeadersFromMultipartText: function(aMultipartText) {
|
||||
let headers = [];
|
||||
if (!aMultipartText || aMultipartText.startsWith("---")) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Get the header section.
|
||||
let index = aMultipartText.indexOf("\r\n\r\n");
|
||||
if (index == -1) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
// Parse the header lines.
|
||||
let headersText = aMultipartText.substring(0, index);
|
||||
let headerLines = headersText.split("\r\n");
|
||||
let lastHeaderName = null;
|
||||
|
||||
for (let line of headerLines) {
|
||||
// Create a header for each line in fields that spans across multiple lines.
|
||||
// Subsquent lines always begins with at least one space or tab character.
|
||||
// (rfc2616)
|
||||
if (lastHeaderName && /^\s+/.test(line)) {
|
||||
headers.push({ name: lastHeaderName, value: line.trim() });
|
||||
continue;
|
||||
}
|
||||
|
||||
let indexOfColon = line.indexOf(":");
|
||||
if (indexOfColon == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let header = [line.slice(0, indexOfColon), line.slice(indexOfColon + 1)];
|
||||
if (header.length != 2) {
|
||||
continue;
|
||||
}
|
||||
lastHeaderName = header[0].trim();
|
||||
headers.push({ name: lastHeaderName, value: header[1].trim() });
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Escape util function for POSIX oriented operating systems.
|
||||
* Credit: Google DevTools
|
||||
*/
|
||||
escapeStringPosix: function(str) {
|
||||
function escapeCharacter(x) {
|
||||
let code = x.charCodeAt(0);
|
||||
if (code < 256) {
|
||||
// Add leading zero when needed to not care about the next character.
|
||||
return code < 16 ? "\\x0" + code.toString(16) : "\\x" + code.toString(16);
|
||||
}
|
||||
code = code.toString(16);
|
||||
return "\\u" + ("0000" + code).substr(code.length, 4);
|
||||
}
|
||||
|
||||
if (/[^\x20-\x7E]|\'/.test(str)) {
|
||||
// Use ANSI-C quoting syntax.
|
||||
return "$\'" + str.replace(/\\/g, "\\\\")
|
||||
.replace(/\'/g, "\\\'")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/[^\x20-\x7E]/g, escapeCharacter) + "'";
|
||||
} else {
|
||||
// Use single quote syntax.
|
||||
return "'" + str + "'";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Escape util function for Windows systems.
|
||||
* Credit: Google DevTools
|
||||
*/
|
||||
escapeStringWin: function(str) {
|
||||
/* Replace quote by double quote (but not by \") because it is
|
||||
recognized by both cmd.exe and MS Crt arguments parser.
|
||||
|
||||
Replace % by "%" because it could be expanded to an environment
|
||||
variable value. So %% becomes "%""%". Even if an env variable ""
|
||||
(2 doublequotes) is declared, the cmd.exe will not
|
||||
substitute it with its value.
|
||||
|
||||
Replace each backslash with double backslash to make sure
|
||||
MS Crt arguments parser won't collapse them.
|
||||
|
||||
Replace new line outside of quotes since cmd.exe doesn't let
|
||||
to do it inside.
|
||||
*/
|
||||
return "\"" + str.replace(/"/g, "\"\"")
|
||||
.replace(/%/g, "\"%\"")
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/[\r\n]+/g, "\"^$&\"") + "\"";
|
||||
}
|
||||
};
|
|
@ -202,12 +202,6 @@
|
|||
- on the context menu that copies the selected request's url -->
|
||||
<!ENTITY netmonitorUI.context.copyUrl "Copy URL">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.context.copyAsCurl): This is the label displayed
|
||||
- on the context menu that copies the selected request as a cURL command.
|
||||
- The capitalization is part of the official name and should be used throughout all languages.
|
||||
- http://en.wikipedia.org/wiki/CURL -->
|
||||
<!ENTITY netmonitorUI.context.copyAsCurl "Copy as cURL">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.context.copyUrl.accesskey): This is the access key
|
||||
- for the Copy URL menu item displayed in the context menu for a request -->
|
||||
<!ENTITY netmonitorUI.context.copyUrl.accesskey "C">
|
||||
|
|
|
@ -135,47 +135,6 @@ for (let [constProp, dirKey] of [
|
|||
*/
|
||||
let clone = SharedAll.clone;
|
||||
|
||||
/**
|
||||
* Extract a shortened version of an object, fit for logging.
|
||||
*
|
||||
* This function returns a copy of the original object in which all
|
||||
* long strings, Arrays, TypedArrays, ArrayBuffers are removed and
|
||||
* replaced with plceholders. Use this function to sanitize objects
|
||||
* if you wish to log them or to keep them in memory.
|
||||
*
|
||||
* @param {*} obj The obj to shorten.
|
||||
* @return {*} array A shorter object, fit for logging.
|
||||
*/
|
||||
function summarizeObject(obj) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
}
|
||||
if (typeof obj == "string") {
|
||||
if (obj.length > 1024) {
|
||||
return {"Long string": obj.length};
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (typeof obj == "object") {
|
||||
if (Array.isArray(obj)) {
|
||||
if (obj.length > 32) {
|
||||
return {"Long array": obj.length};
|
||||
}
|
||||
return [summarizeObject(k) for (k of obj)];
|
||||
}
|
||||
if ("byteLength" in obj) {
|
||||
// Assume TypedArray or ArrayBuffer
|
||||
return {"Binary Data": obj.byteLength};
|
||||
}
|
||||
let result = {};
|
||||
for (let k of Object.keys(obj)) {
|
||||
result[k] = summarizeObject(obj[k]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
let worker = null;
|
||||
let Scheduler = {
|
||||
/**
|
||||
|
@ -198,41 +157,19 @@ let Scheduler = {
|
|||
queue: Promise.resolve(),
|
||||
|
||||
/**
|
||||
* Miscellaneous debugging information
|
||||
* The latest message sent and still waiting for a reply. In DEBUG
|
||||
* builds, the entire message is stored, which may be memory-consuming.
|
||||
* In non-DEBUG builds, only the method name is stored.
|
||||
*/
|
||||
Debugging: {
|
||||
/**
|
||||
* The latest message sent and still waiting for a reply. In DEBUG
|
||||
* builds, the entire message is stored, which may be memory-consuming.
|
||||
* In non-DEBUG builds, only the method name is stored.
|
||||
*/
|
||||
latestSent: undefined,
|
||||
latestSent: undefined,
|
||||
|
||||
/**
|
||||
* The latest reply received, or null if we are waiting for a reply.
|
||||
* In DEBUG builds, the entire response is stored, which may be
|
||||
* memory-consuming. In non-DEBUG builds, only exceptions and
|
||||
* method names are stored.
|
||||
*/
|
||||
latestReceived: undefined,
|
||||
|
||||
/**
|
||||
* Number of messages sent to the worker. This includes the
|
||||
* initial SET_DEBUG, if applicable.
|
||||
*/
|
||||
messagesSent: 0,
|
||||
|
||||
/**
|
||||
* Total number of messages ever queued, including the messages
|
||||
* sent.
|
||||
*/
|
||||
messagesQueued: 0,
|
||||
|
||||
/**
|
||||
* Number of messages received from the worker.
|
||||
*/
|
||||
messagesReceived: 0,
|
||||
},
|
||||
/**
|
||||
* The latest reply received, or null if we are waiting for a reply.
|
||||
* In DEBUG builds, the entire response is stored, which may be
|
||||
* memory-consuming. In non-DEBUG builds, only exceptions and
|
||||
* method names are stored.
|
||||
*/
|
||||
latestReceived: undefined,
|
||||
|
||||
/**
|
||||
* A timer used to automatically shut down the worker after some time.
|
||||
|
@ -297,7 +234,6 @@ let Scheduler = {
|
|||
if (firstLaunch && SharedAll.Config.DEBUG) {
|
||||
// If we have delayed sending SET_DEBUG, do it now.
|
||||
worker.post("SET_DEBUG", [true]);
|
||||
Scheduler.Debugging.messagesSent++;
|
||||
}
|
||||
|
||||
// By convention, the last argument of any message may be an |options| object.
|
||||
|
@ -306,43 +242,41 @@ let Scheduler = {
|
|||
if (methodArgs) {
|
||||
options = methodArgs[methodArgs.length - 1];
|
||||
}
|
||||
Scheduler.Debugging.messagesQueued++;
|
||||
return this.push(() => Task.spawn(function*() {
|
||||
// Update debugging information. As |args| may be quite
|
||||
// expensive, we only keep a shortened version of it.
|
||||
Scheduler.Debugging.latestReceived = null;
|
||||
Scheduler.Debugging.latestSent = [Date.now(), method, summarizeObject(methodArgs)];
|
||||
Scheduler.latestReceived = null;
|
||||
if (OS.Constants.Sys.DEBUG) {
|
||||
// Update possibly memory-expensive debugging information
|
||||
Scheduler.latestSent = [Date.now(), method, ...args];
|
||||
} else {
|
||||
Scheduler.latestSent = [Date.now(), method];
|
||||
}
|
||||
let data;
|
||||
let reply;
|
||||
let isError = false;
|
||||
try {
|
||||
try {
|
||||
data = yield worker.post(method, ...args);
|
||||
} finally {
|
||||
Scheduler.Debugging.messagesReceived++;
|
||||
}
|
||||
data = yield worker.post(method, ...args);
|
||||
reply = data;
|
||||
} catch (error) {
|
||||
} catch (error if error instanceof PromiseWorker.WorkerError) {
|
||||
reply = error;
|
||||
isError = true;
|
||||
if (error instanceof PromiseWorker.WorkerError) {
|
||||
throw EXCEPTION_CONSTRUCTORS[error.data.exn || "OSError"](error.data);
|
||||
throw EXCEPTION_CONSTRUCTORS[error.data.exn || "OSError"](error.data);
|
||||
} catch (error if error instanceof ErrorEvent) {
|
||||
reply = error;
|
||||
let message = error.message;
|
||||
if (message == "uncaught exception: [object StopIteration]") {
|
||||
throw StopIteration;
|
||||
}
|
||||
if (error instanceof ErrorEvent) {
|
||||
let message = error.message;
|
||||
if (message == "uncaught exception: [object StopIteration]") {
|
||||
isError = false;
|
||||
throw StopIteration;
|
||||
}
|
||||
throw new Error(message, error.filename, error.lineno);
|
||||
}
|
||||
throw ex;
|
||||
isError = true;
|
||||
throw new Error(message, error.filename, error.lineno);
|
||||
} finally {
|
||||
Scheduler.Debugging.latestSent = Scheduler.Debugging.latestSent.slice(0, 2);
|
||||
if (isError) {
|
||||
Scheduler.Debugging.latestReceived = [Date.now(), reply.message, reply.fileName, reply.lineNumber];
|
||||
Scheduler.latestSent = Scheduler.latestSent.slice(0, 2);
|
||||
if (OS.Constants.Sys.DEBUG) {
|
||||
// Update possibly memory-expensive debugging information
|
||||
Scheduler.latestReceived = [Date.now(), reply];
|
||||
} else if (isError) {
|
||||
Scheduler.latestReceived = [Date.now(), reply.message, reply.fileName, reply.lineNumber];
|
||||
} else {
|
||||
Scheduler.Debugging.latestReceived = [Date.now(), summarizeObject(reply)];
|
||||
Scheduler.latestReceived = [Date.now()];
|
||||
}
|
||||
if (firstLaunch) {
|
||||
Scheduler._updateTelemetry();
|
||||
|
@ -1429,12 +1363,8 @@ AsyncShutdown.profileBeforeChange.addBlocker(
|
|||
shutdown: Scheduler.shutdown,
|
||||
worker: !!worker,
|
||||
pendingReset: !!Scheduler.resetTimer,
|
||||
latestSent: Scheduler.Debugging.latestSent,
|
||||
latestReceived: Scheduler.Debugging.latestReceived,
|
||||
messagesSent: Scheduler.Debugging.messagesSent,
|
||||
messagesReceived: Scheduler.Debugging.messagesReceived,
|
||||
messagesQueued: Scheduler.Debugging.messagesQueued,
|
||||
DEBUG: SharedAll.Config.DEBUG
|
||||
latestSent: Scheduler.latestSent,
|
||||
latestReceived: Scheduler.latestReceived
|
||||
};
|
||||
// Convert dates to strings for better readability
|
||||
for (let key of ["latestSent", "latestReceived"]) {
|
||||
|
|
|
@ -28,8 +28,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
const { defer, resolve, reject } = promise;
|
||||
|
||||
|
@ -1409,28 +1407,17 @@ ThreadClient.prototype = {
|
|||
* @param function aOnResponse
|
||||
* Called with the thread's response.
|
||||
*/
|
||||
setBreakpoint: function ({ url, line, column, condition }, aOnResponse) {
|
||||
setBreakpoint: function (aLocation, aOnResponse) {
|
||||
// A helper function that sets the breakpoint.
|
||||
let doSetBreakpoint = function (aCallback) {
|
||||
const location = {
|
||||
url: url,
|
||||
line: line,
|
||||
column: column
|
||||
};
|
||||
|
||||
let packet = {
|
||||
to: this._actor,
|
||||
type: "setBreakpoint",
|
||||
location: location,
|
||||
condition: condition
|
||||
};
|
||||
let packet = { to: this._actor, type: "setBreakpoint",
|
||||
location: aLocation };
|
||||
this.client.request(packet, function (aResponse) {
|
||||
// Ignoring errors, since the user may be setting a breakpoint in a
|
||||
// dead script that will reappear on a page reload.
|
||||
if (aOnResponse) {
|
||||
let bpClient = new BreakpointClient(this.client,
|
||||
aResponse.actor,
|
||||
location);
|
||||
let bpClient = new BreakpointClient(this.client, aResponse.actor,
|
||||
aLocation);
|
||||
if (aCallback) {
|
||||
aCallback(aOnResponse(aResponse, bpClient));
|
||||
} else {
|
||||
|
|
|
@ -187,8 +187,6 @@ RootActor.prototype = {
|
|||
storageInspector: true,
|
||||
// Wether storage inspector is read only
|
||||
storageInspectorReadOnly: true,
|
||||
// Wether conditional breakpoints are supported
|
||||
conditionalBreakpoints: true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@ function BreakpointStore() {
|
|||
//
|
||||
// is an object
|
||||
//
|
||||
// { url, line, column[, actor] }
|
||||
// { url, line[, actor] }
|
||||
//
|
||||
// where the `actor` property is optional.
|
||||
this._breakpoints = Object.create(null);
|
||||
|
@ -58,7 +58,6 @@ BreakpointStore.prototype = {
|
|||
* - line
|
||||
* - column (optional; omission implies that the breakpoint is for
|
||||
* the whole line)
|
||||
* - condition (optional)
|
||||
* - actor (optional)
|
||||
*/
|
||||
addBreakpoint: function (aBreakpoint) {
|
||||
|
@ -1375,8 +1374,7 @@ ThreadActor.prototype = {
|
|||
let response = this._createAndStoreBreakpoint({
|
||||
url: url,
|
||||
line: line,
|
||||
column: column,
|
||||
condition: aRequest.condition
|
||||
column: column
|
||||
});
|
||||
// If the original location of our generated location is different from
|
||||
// the original location we attempted to set the breakpoint on, we will
|
||||
|
@ -1444,13 +1442,11 @@ ThreadActor.prototype = {
|
|||
let storedBp = this.breakpointStore.getBreakpoint(aLocation);
|
||||
if (storedBp.actor) {
|
||||
actor = storedBp.actor;
|
||||
actor.condition = aLocation.condition;
|
||||
} else {
|
||||
storedBp.actor = actor = new BreakpointActor(this, {
|
||||
url: aLocation.url,
|
||||
line: aLocation.line,
|
||||
column: aLocation.column,
|
||||
condition: aLocation.condition
|
||||
column: aLocation.column
|
||||
});
|
||||
this.threadLifetimePool.addActor(actor);
|
||||
}
|
||||
|
@ -4225,17 +4221,15 @@ FrameActor.prototype.requestTypes = {
|
|||
* @param object aLocation
|
||||
* The location of the breakpoint as specified in the protocol.
|
||||
*/
|
||||
function BreakpointActor(aThreadActor, { url, line, column, condition })
|
||||
function BreakpointActor(aThreadActor, aLocation)
|
||||
{
|
||||
this.scripts = [];
|
||||
this.threadActor = aThreadActor;
|
||||
this.location = { url: url, line: line, column: column };
|
||||
this.condition = condition;
|
||||
this.location = aLocation;
|
||||
}
|
||||
|
||||
BreakpointActor.prototype = {
|
||||
actorPrefix: "breakpoint",
|
||||
condition: null,
|
||||
|
||||
/**
|
||||
* Called when this same breakpoint is added to another Debugger.Script
|
||||
|
@ -4261,14 +4255,6 @@ BreakpointActor.prototype = {
|
|||
this.scripts = [];
|
||||
},
|
||||
|
||||
isValidCondition: function(aFrame) {
|
||||
if(!this.condition) {
|
||||
return true;
|
||||
}
|
||||
var res = aFrame.eval(this.condition);
|
||||
return res.return;
|
||||
},
|
||||
|
||||
/**
|
||||
* A function that the engine calls when a breakpoint has been hit.
|
||||
*
|
||||
|
@ -4285,9 +4271,7 @@ BreakpointActor.prototype = {
|
|||
column: this.location.column
|
||||
}));
|
||||
|
||||
if (this.threadActor.sources.isBlackBoxed(url)
|
||||
|| aFrame.onStep
|
||||
|| !this.isValidCondition(aFrame)) {
|
||||
if (this.threadActor.sources.isBlackBoxed(url) || aFrame.onStep) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ this.promised = promised;
|
|||
this.all = all;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
function dumpn(str) {
|
||||
if (wantLogging) {
|
||||
|
|
|
@ -30,7 +30,6 @@ function tryImport(url) {
|
|||
tryImport("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
tryImport("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
tryImport("resource://gre/modules/devtools/Loader.jsm");
|
||||
tryImport("resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
function testExceptionHook(ex) {
|
||||
try {
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition evaluates to true.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.setBreakpoint({
|
||||
url: "test.js",
|
||||
line: 3,
|
||||
condition: "a === 1"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.frame.where.line, 3);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n", // 3
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition evaluates to false.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.setBreakpoint({
|
||||
url: "test.js",
|
||||
line: 3,
|
||||
condition: "a === 2"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.frame.where.line, 4);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n" + // 3
|
||||
"debugger;", // 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition throws and make sure it is ignored
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.setBreakpoint({
|
||||
url: "test.js",
|
||||
line: 3,
|
||||
condition: "throw new Error()"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.frame.where.line, 4);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n" + // 3
|
||||
"debugger;", // 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
|
@ -112,9 +112,6 @@ reason = bug 820380
|
|||
[test_breakpoint-16.js]
|
||||
[test_breakpoint-17.js]
|
||||
[test_breakpoint-18.js]
|
||||
[test_conditional_breakpoint-01.js]
|
||||
[test_conditional_breakpoint-02.js]
|
||||
[test_conditional_breakpoint-03.js]
|
||||
[test_eventlooplag_actor.js]
|
||||
run-if = toolkit == "gonk"
|
||||
[test_listsources-01.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче