зеркало из https://github.com/mozilla/gecko-dev.git
Bug 964977 - Infer JSON from response, r=rcampbell
This commit is contained in:
Родитель
4124f6c54b
Коммит
7e7788903b
|
@ -2126,19 +2126,33 @@ NetworkDetailsView.prototype = {
|
|||
// Handle json, which we tentatively identify by checking the MIME type
|
||||
// for "json" after any word boundary. This works for the standard
|
||||
// "application/json", and also for custom types like "x-bigcorp-json".
|
||||
// This should be marginally more reliable than just looking for "json".
|
||||
if (/\bjson/.test(mimeType)) {
|
||||
let jsonpRegex = /^[a-zA-Z0-9_$]+\(|\)$/g; // JSONP with callback.
|
||||
// Additionally, we also directly parse the response text content to
|
||||
// verify whether it's json or not, to handle responses incorrectly
|
||||
// labeled as text/plain instead.
|
||||
let jsonMimeType, jsonObject, jsonObjectParseError;
|
||||
try {
|
||||
// Test the mime type *and* parse the string, because "JSONP" responses
|
||||
// (json with callback) aren't actually valid json.
|
||||
jsonMimeType = /\bjson/.test(mimeType);
|
||||
jsonObject = JSON.parse(aString);
|
||||
} catch (e) {
|
||||
jsonObjectParseError = e;
|
||||
}
|
||||
if (jsonMimeType || jsonObject) {
|
||||
// Extract the actual json substring in case this might be a "JSONP".
|
||||
let jsonpRegex = /^[a-zA-Z0-9_$]+\(|\)$/g;
|
||||
let sanitizedJSON = aString.replace(jsonpRegex, "");
|
||||
let callbackPadding = aString.match(jsonpRegex);
|
||||
|
||||
// Make sure this is a valid JSON object first. If so, nicely display
|
||||
// the parsing results in a variables view. Otherwise, simply show
|
||||
// the contents as plain text.
|
||||
try {
|
||||
var jsonObject = JSON.parse(sanitizedJSON);
|
||||
} catch (e) {
|
||||
var parsingError = e;
|
||||
if (sanitizedJSON != aString) {
|
||||
try {
|
||||
jsonObject = JSON.parse(sanitizedJSON);
|
||||
} catch (e) {
|
||||
jsonObjectParseError = e;
|
||||
}
|
||||
}
|
||||
|
||||
// Valid JSON.
|
||||
|
@ -2157,8 +2171,8 @@ NetworkDetailsView.prototype = {
|
|||
else {
|
||||
$("#response-content-textarea-box").hidden = false;
|
||||
let infoHeader = $("#response-content-info-header");
|
||||
infoHeader.setAttribute("value", parsingError);
|
||||
infoHeader.setAttribute("tooltiptext", parsingError);
|
||||
infoHeader.setAttribute("value", jsonObjectParseError);
|
||||
infoHeader.setAttribute("tooltiptext", jsonObjectParseError);
|
||||
infoHeader.hidden = false;
|
||||
return NetMonitorView.editor("#response-content-textarea").then(aEditor => {
|
||||
aEditor.setMode(Editor.modes.js);
|
||||
|
|
|
@ -10,6 +10,7 @@ support-files =
|
|||
html_json-custom-mime-test-page.html
|
||||
html_json-long-test-page.html
|
||||
html_json-malformed-test-page.html
|
||||
html_json-text-mime-test-page.html
|
||||
html_jsonp-test-page.html
|
||||
html_navigate-test-page.html
|
||||
html_post-data-test-page.html
|
||||
|
@ -46,6 +47,7 @@ support-files =
|
|||
[browser_net_json-long.js]
|
||||
[browser_net_json-malformed.js]
|
||||
[browser_net_json_custom_mime.js]
|
||||
[browser_net_json_text_mime.js]
|
||||
[browser_net_jsonp.js]
|
||||
[browser_net_large-response.js]
|
||||
[browser_net_open_request_in_tab.js]
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if JSON responses with unusal/custom MIME types are handled correctly.
|
||||
*/
|
||||
|
||||
function test() {
|
||||
initNetMonitor(JSON_TEXT_MIME_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1).then(() => {
|
||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
||||
"GET", CONTENT_TYPE_SJS + "?fmt=json-text-mime", {
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
type: "plain",
|
||||
fullMimeType: "text/plain; charset=utf-8",
|
||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
||||
time: true
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.getElementById("details-pane-toggle"));
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[3]);
|
||||
|
||||
let RESPONSE_BODY_DISPLAYED = aMonitor.panelWin.EVENTS.RESPONSE_BODY_DISPLAYED;
|
||||
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED)
|
||||
.then(testResponseTab)
|
||||
.then(() => teardown(aMonitor))
|
||||
.then(finish);
|
||||
|
||||
function testResponseTab() {
|
||||
let tab = document.querySelectorAll("#details-pane tab")[3];
|
||||
let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
|
||||
|
||||
is(tab.getAttribute("selected"), "true",
|
||||
"The response tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-info-header")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response info header doesn't have the intended visibility.");
|
||||
is(tabpanel.querySelector("#response-content-json-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The response content json box doesn't have the intended visibility.");
|
||||
is(tabpanel.querySelector("#response-content-textarea-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content textarea box doesn't have the intended visibility.");
|
||||
is(tabpanel.querySelector("#response-content-image-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content image box doesn't have the intended visibility.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 1,
|
||||
"There should be 1 json scope displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-property").length, 2,
|
||||
"There should be 2 json properties displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
|
||||
let jsonScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .name")[0].getAttribute("value"),
|
||||
"greeting", "The first json property name was incorrect.");
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .value")[0].getAttribute("value"),
|
||||
"\"Hello third-party JSON!\"", "The first json property value was incorrect.");
|
||||
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"),
|
||||
"__proto__", "The second json property name was incorrect.");
|
||||
is(jsonScope.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"),
|
||||
"Object", "The second json property value was incorrect.");
|
||||
}
|
||||
});
|
||||
|
||||
aDebuggee.performRequests();
|
||||
});
|
||||
}
|
|
@ -26,6 +26,7 @@ const JSONP_URL = EXAMPLE_URL + "html_jsonp-test-page.html";
|
|||
const JSON_LONG_URL = EXAMPLE_URL + "html_json-long-test-page.html";
|
||||
const JSON_MALFORMED_URL = EXAMPLE_URL + "html_json-malformed-test-page.html";
|
||||
const JSON_CUSTOM_MIME_URL = EXAMPLE_URL + "html_json-custom-mime-test-page.html";
|
||||
const JSON_TEXT_MIME_URL = EXAMPLE_URL + "html_json-text-mime-test-page.html";
|
||||
const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html";
|
||||
const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
|
||||
const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!-- 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>JSON text test</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function get(aAddress, aCallback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aAddress, true);
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (this.readyState == this.DONE) {
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function performRequests() {
|
||||
get("sjs_content-type-test-server.sjs?fmt=json-text-mime", function() {
|
||||
// Done.
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -112,6 +112,14 @@ function handleRequest(request, response) {
|
|||
response.finish();
|
||||
break;
|
||||
}
|
||||
case "json-text-mime": {
|
||||
response.setStatusLine(request.httpVersion, status, "OK");
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
maybeMakeCached();
|
||||
response.write("{ \"greeting\": \"Hello third-party JSON!\" }");
|
||||
response.finish();
|
||||
break;
|
||||
}
|
||||
case "json-custom-mime": {
|
||||
response.setStatusLine(request.httpVersion, status, "OK");
|
||||
response.setHeader("Content-Type", "text/x-bigcorp-json; charset=utf-8", false);
|
||||
|
|
Загрузка…
Ссылка в новой задаче