fune/devtools/client/netmonitor/shared/components/response-panel.js
Fred Lin ddd187450f Bug 1314921 - move top-level files into utils;r=Honza
MozReview-Commit-ID: GtAe9ggiCeA

--HG--
rename : devtools/client/netmonitor/filter-predicates.js => devtools/client/netmonitor/utils/filter-predicates.js
rename : devtools/client/netmonitor/l10n.js => devtools/client/netmonitor/utils/l10n.js
rename : devtools/client/netmonitor/prefs.js => devtools/client/netmonitor/utils/prefs.js
rename : devtools/client/netmonitor/request-utils.js => devtools/client/netmonitor/utils/request-utils.js
rename : devtools/client/netmonitor/sort-predicates.js => devtools/client/netmonitor/utils/sort-predicates.js
extra : rebase_source : a543be5c81e3552f831c1c26107d5109fc90fc96
2017-02-16 15:24:26 +08:00

185 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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/. */
"use strict";
const {
createClass,
createFactory,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { L10N } = require("../../utils/l10n");
const { formDataURI, getUrlBaseName } = require("../../utils/request-utils");
// Components
const PropertiesView = createFactory(require("./properties-view"));
const { div, img } = DOM;
const JSON_SCOPE_NAME = L10N.getStr("jsonScopeName");
const JSON_FILTER_TEXT = L10N.getStr("jsonFilterText");
const RESPONSE_IMG_NAME = L10N.getStr("netmonitor.response.name");
const RESPONSE_IMG_DIMENSIONS = L10N.getStr("netmonitor.response.dimensions");
const RESPONSE_IMG_MIMETYPE = L10N.getStr("netmonitor.response.mime");
const RESPONSE_PAYLOAD = L10N.getStr("responsePayload");
/*
* Response panel component
* Displays the GET parameters and POST data of a request
*/
const ResponsePanel = createClass({
displayName: "ResponsePanel",
propTypes: {
request: PropTypes.object.isRequired,
},
getInitialState() {
return {
imageDimensions: {
width: 0,
height: 0,
},
};
},
updateImageDimemsions({ target }) {
this.setState({
imageDimensions: {
width: target.naturalWidth,
height: target.naturalHeight,
},
});
},
// 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".
// 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.
isJSON(mimeType, response) {
let json, error;
try {
json = JSON.parse(response);
} catch (err) {
try {
json = JSON.parse(atob(response));
} catch (err64) {
error = err;
}
}
if (/\bjson/.test(mimeType) || json) {
// Extract the actual json substring in case this might be a "JSONP".
// This regex basically parses a function call and captures the
// function name and arguments in two separate groups.
let jsonpRegex = /^\s*([\w$]+)\s*\(\s*([^]*)\s*\)\s*;?\s*$/;
let [, jsonpCallback, jsonp] = response.match(jsonpRegex) || [];
let result = {};
// Make sure this is a valid JSON object first. If so, nicely display
// the parsing results in a tree view.
if (jsonpCallback && jsonp) {
error = null;
try {
json = JSON.parse(jsonp);
} catch (err) {
error = err;
}
}
// Valid JSON
if (json) {
result.json = json;
}
// Valid JSONP
if (jsonpCallback) {
result.jsonpCallback = jsonpCallback;
}
// Malformed JSON
if (error) {
result.error = "" + error;
}
return result;
}
return null;
},
render() {
let { responseContent, url } = this.props.request;
if (!responseContent || typeof responseContent.content.text !== "string") {
return null;
}
let { encoding, mimeType, text } = responseContent.content;
if (mimeType.includes("image/")) {
let { width, height } = this.state.imageDimensions;
return (
div({ className: "panel-container response-image-box devtools-monospace" },
img({
className: "response-image",
src: formDataURI(mimeType, encoding, text),
onLoad: this.updateImageDimemsions,
}),
div({ className: "response-summary" },
div({ className: "tabpanel-summary-label" }, RESPONSE_IMG_NAME),
div({ className: "tabpanel-summary-value" }, getUrlBaseName(url)),
),
div({ className: "response-summary" },
div({ className: "tabpanel-summary-label" }, RESPONSE_IMG_DIMENSIONS),
div({ className: "tabpanel-summary-value" }, `${width} × ${height}`),
),
div({ className: "response-summary" },
div({ className: "tabpanel-summary-label" }, RESPONSE_IMG_MIMETYPE),
div({ className: "tabpanel-summary-value" }, mimeType),
),
)
);
}
// Display Properties View
let { json, jsonpCallback, error } = this.isJSON(mimeType, text) || {};
let object = {};
let sectionName;
if (json) {
if (jsonpCallback) {
sectionName = L10N.getFormatStr("jsonpScopeName", jsonpCallback);
} else {
sectionName = JSON_SCOPE_NAME;
}
object[sectionName] = json;
} else {
sectionName = RESPONSE_PAYLOAD;
object[sectionName] = {
EDITOR_CONFIG: {
text,
mode: mimeType.replace(/;.+/, ""),
},
};
}
return (
div({ className: "panel-container" },
error && div({ className: "response-error-header", title: error },
error
),
PropertiesView({
object,
filterPlaceHolder: JSON_FILTER_TEXT,
sectionNames: [sectionName],
}),
)
);
}
});
module.exports = ResponsePanel;