Bug 1250255 - Properly decode response body; r=gasolin
MozReview-Commit-ID: DQu5KGqHqEv
--- a/devtools/client/netmonitor/src/components/response-panel.js
+++ b/devtools/client/netmonitor/src/components/response-panel.js
@@ -6,29 +6,35 @@
const {
createClass,
createFactory,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils/l10n");
-const { formDataURI, getUrlBaseName } = require("../utils/request-utils");
+const {
+ decodeUnicodeBase64,
+ 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");
+const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
+
/*
* Response panel component
* Displays the GET parameters and POST data of a request
*/
const ResponsePanel = createClass({
displayName: "ResponsePanel",
propTypes: {
@@ -141,16 +147,21 @@ const ResponsePanel = createClass({
div({ className: "response-summary" },
div({ className: "tabpanel-summary-label" }, RESPONSE_IMG_MIMETYPE),
div({ className: "tabpanel-summary-value" }, mimeType),
),
)
);
}
+ // Decode response if it's coming from JSONView.
+ if (mimeType.includes(JSON_VIEW_MIME_TYPE) && encoding === "base64") {
+ text = decodeUnicodeBase64(text);
+ }
+
// Display Properties View
let { json, jsonpCallback, error } = this.isJSON(mimeType, text) || {};
let object = {};
let sectionName;
if (json) {
if (jsonpCallback) {
sectionName = L10N.getFormatStr("jsonpScopeName", jsonpCallback);
--- a/devtools/client/netmonitor/src/connector/firefox-data-provider.js
+++ b/devtools/client/netmonitor/src/connector/firefox-data-provider.js
@@ -2,17 +2,20 @@
* 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/. */
/* eslint-disable block-scoped-var */
"use strict";
const { EVENTS } = require("../constants");
const { CurlUtils } = require("devtools/client/shared/curl");
-const { fetchHeaders, formDataURI } = require("../utils/request-utils");
+const {
+ fetchHeaders,
+ formDataURI,
+} = require("../utils/request-utils");
/**
* This object is responsible for fetching additional HTTP
* data from the backend.
*/
class FirefoxDataProvider {
constructor({webConsoleClient, actions}) {
// Options
@@ -22,17 +25,17 @@ class FirefoxDataProvider {
// Internal properties
this.payloadQueue = [];
// Public methods
this.addRequest = this.addRequest.bind(this);
this.updateRequest = this.updateRequest.bind(this);
// Internals
- this.fetchImage = this.fetchImage.bind(this);
+ this.fetchResponseBody = this.fetchResponseBody.bind(this);
this.fetchRequestHeaders = this.fetchRequestHeaders.bind(this);
this.fetchResponseHeaders = this.fetchResponseHeaders.bind(this);
this.fetchPostData = this.fetchPostData.bind(this);
this.fetchResponseCookies = this.fetchResponseCookies.bind(this);
this.fetchRequestCookies = this.fetchRequestCookies.bind(this);
this.getPayloadFromQueue = this.getPayloadFromQueue.bind(this);
this.isQueuePayloadReady = this.isQueuePayloadReady.bind(this);
this.pushPayloadToQueue = this.pushPayloadToQueue.bind(this);
@@ -107,17 +110,17 @@ class FirefoxDataProvider {
let [
imageObj,
requestHeadersObj,
responseHeadersObj,
postDataObj,
requestCookiesObj,
responseCookiesObj,
] = await Promise.all([
- this.fetchImage(mimeType, responseContent),
+ this.fetchResponseBody(mimeType, responseContent),
this.fetchRequestHeaders(requestHeaders),
this.fetchResponseHeaders(responseHeaders),
this.fetchPostData(requestPostData),
this.fetchRequestCookies(requestCookies),
this.fetchResponseCookies(responseCookies),
]);
let payload = Object.assign({},
@@ -132,17 +135,17 @@ class FirefoxDataProvider {
this.pushPayloadToQueue(id, payload);
if (this.actions.updateRequest && this.isQueuePayloadReady(id)) {
await this.actions.updateRequest(id, this.getPayloadFromQueue(id).payload, true);
}
}
- async fetchImage(mimeType, responseContent) {
+ async fetchResponseBody(mimeType, responseContent) {
let payload = {};
if (mimeType && responseContent && responseContent.content) {
let { encoding, text } = responseContent.content;
let response = await this.getLongString(text);
if (mimeType.includes("image/")) {
payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
}
--- a/devtools/client/netmonitor/src/utils/request-utils.js
+++ b/devtools/client/netmonitor/src/utils/request-utils.js
@@ -104,16 +104,31 @@ function decodeUnicodeUrl(string) {
return decodeURIComponent(string);
} catch (err) {
// Ignore error and return input string directly.
}
return string;
}
/**
+ * Decode base64 string.
+ *
+ * @param {string} url - a string
+ * @return {string} decoded string
+ */
+function decodeUnicodeBase64(string) {
+ try {
+ return decodeURIComponent(atob(string));
+ } catch (err) {
+ // Ignore error and return input string directly.
+ }
+ return string;
+}
+
+/**
* Helper for getting an abbreviated string for a mime type.
*
* @param {string} mimeType - mime type
* @return {string} abbreviated mime type
*/
function getAbbreviatedMimeType(mimeType) {
if (!mimeType) {
return "";
@@ -370,16 +385,17 @@ function getResponseHeader(item, header)
if (responseHeader.name.toLowerCase() == header) {
return responseHeader.value;
}
}
return null;
}
module.exports = {
+ decodeUnicodeBase64,
getFormDataSections,
fetchHeaders,
formDataURI,
writeHeaderText,
decodeUnicodeUrl,
getAbbreviatedMimeType,
getEndTime,
getFormattedProtocol,