Bug 1457513 - Let JSON Viewer display unmodified headers
MozReview-Commit-ID: R54uNEefvw
--- a/devtools/client/jsonview/converter-child.js
+++ b/devtools/client/jsonview/converter-child.js
@@ -74,16 +74,18 @@ Converter.prototype = {
},
onStartRequest: function(request, context) {
// Set the content type to HTML in order to parse the doctype, styles
// and scripts. The JSON will be manually inserted as text.
request.QueryInterface(Ci.nsIChannel);
request.contentType = "text/html";
+ let headers = getHttpHeaders(request);
+
// Enforce strict CSP:
try {
request.QueryInterface(Ci.nsIHttpChannel);
request.setResponseHeader("Content-Security-Policy",
"default-src 'none' ; script-src resource:; ", false);
} catch (ex) {
// If this is not an HTTP channel we can't and won't do anything.
}
@@ -100,17 +102,17 @@ Converter.prototype = {
// origin with (other) content.
request.loadInfo.resetPrincipalToInheritToNullPrincipal();
// Start the request.
this.listener.onStartRequest(request, context);
// Initialize stuff.
let win = NetworkHelper.getWindowForRequest(request);
- this.data = exportData(win, request);
+ this.data = exportData(win, headers);
insertJsonData(win, this.data.json);
win.addEventListener("contentMessage", onContentMessage, false, true);
keepThemeUpdated(win);
// Send the initial HTML code.
let buffer = new TextEncoder().encode(initialHTML(win.document)).buffer;
let stream = new BufferStream(buffer, 0, buffer.byteLength);
this.listener.onDataAvailable(request, context, stream, 0, stream.available());
@@ -159,18 +161,40 @@ function fixSave(request) {
originalType = match[1];
} else {
originalType = "application/json";
}
request.QueryInterface(Ci.nsIWritablePropertyBag);
request.setProperty("contentType", originalType);
}
+function getHttpHeaders(request) {
+ let headers = {
+ response: [],
+ request: []
+ };
+ // The request doesn't have to be always nsIHttpChannel
+ // (e.g. in case of data: URLs)
+ if (request instanceof Ci.nsIHttpChannel) {
+ request.visitResponseHeaders({
+ visitHeader: function(name, value) {
+ headers.response.push({name: name, value: value});
+ }
+ });
+ request.visitRequestHeaders({
+ visitHeader: function(name, value) {
+ headers.request.push({name: name, value: value});
+ }
+ });
+ }
+ return headers;
+}
+
// Exports variables that will be accessed by the non-privileged scripts.
-function exportData(win, request) {
+function exportData(win, headers) {
let data = Cu.createObjectIn(win, {
defineAs: "JSONView"
});
data.debugJsModules = debugJsModules;
data.json = new win.Text();
@@ -183,34 +207,16 @@ function exportData(win, request) {
} catch (err) {
console.error(err);
return undefined;
}
}
};
data.Locale = Cu.cloneInto(Locale, win, {cloneFunctions: true});
- let headers = {
- response: [],
- request: []
- };
- // The request doesn't have to be always nsIHttpChannel
- // (e.g. in case of data: URLs)
- if (request instanceof Ci.nsIHttpChannel) {
- request.visitResponseHeaders({
- visitHeader: function(name, value) {
- headers.response.push({name: name, value: value});
- }
- });
- request.visitRequestHeaders({
- visitHeader: function(name, value) {
- headers.request.push({name: name, value: value});
- }
- });
- }
data.headers = Cu.cloneInto(headers, win);
return data;
}
// Builds an HTML string that will be used to load stylesheets and scripts.
function initialHTML(doc) {
// Creates an element with the specified type, attributes and children.
--- a/devtools/client/jsonview/test/browser_jsonview_csp_json.js
+++ b/devtools/client/jsonview/test/browser_jsonview_csp_json.js
@@ -5,13 +5,31 @@
"use strict";
const TEST_JSON_URL = URL_ROOT + "csp_json.json";
add_task(async function() {
info("Test CSP JSON started");
- await addJsonViewTab(TEST_JSON_URL);
+ let tab = await addJsonViewTab(TEST_JSON_URL);
let count = await getElementCount(".jsonPanelBox .treeTable .treeRow");
is(count, 1, "There must be one row");
+
+ // The JSON Viewer alters the CSP, but the displayed header should be the original one
+ await selectJsonViewContentTab("headers");
+ await ContentTask.spawn(tab.linkedBrowser, null, async function() {
+ let responseHeaders = content.document.querySelector(".netHeadersGroup");
+ let names = responseHeaders.querySelectorAll(".netInfoParamName");
+ let found = false;
+ for (let name of names) {
+ if (name.textContent.toLowerCase() == "content-security-policy") {
+ ok(!found, "The CSP header only appears once");
+ found = true;
+ let value = name.nextElementSibling.textContent;
+ let expected = "default-src 'none'; base-uri 'none';";
+ is(value, expected, "The CSP value has not been altered");
+ }
+ }
+ ok(found, "The CSP header is present");
+ });
});