Loading devtools/client/jsonview/converter-child.js +142 −119 Original line number Diff line number Diff line Loading @@ -51,8 +51,7 @@ Converter.prototype = { * 2. onStartRequest fires, initializes stuff, modifies the listener * to match our output type * 3. onDataAvailable spits it back to the listener * 4. onStopRequest spits it back to the listener and initializes the JSON Viewer * 4. onStopRequest spits it back to the listener * 5. convert does nothing, it's just the synchronous version * of asyncConvertData */ Loading @@ -69,11 +68,51 @@ Converter.prototype = { }, onStartRequest: function (request, context) { this.channel = request; // Set the content type to HTML in order to parse the doctype, styles // and scripts, but later a <plaintext> element will switch the tokenizer // to the plaintext state in order to parse the JSON. request.QueryInterface(Ci.nsIChannel); request.contentType = "text/html"; // JSON enforces UTF-8 charset (see bug 741776). request.contentCharset = "UTF-8"; // Changing the content type breaks saving functionality. Fix it. fixSave(request); // Because content might still have a reference to this window, // force setting it to a null principal to avoid it being same- // origin with (other) content. request.loadInfo.resetPrincipalToInheritToNullPrincipal(); // Start the request. this.listener.onStartRequest(request, context); // Initialize stuff. let win = NetworkHelper.getWindowForRequest(request); exportData(win, request); win.addEventListener("DOMContentLoaded", event => { win.addEventListener("contentMessage", onContentMessage, false, true); }, {once: true}); // Insert the initial HTML code. let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; let stream = converter.convertToInputStream(initialHTML(win.document)); this.listener.onDataAvailable(request, context, stream, 0, stream.available()); }, onStopRequest: function (request, context, statusCode) { this.listener.onStopRequest(request, context, statusCode); this.listener = null; } }; // Let "save as" save the original JSON, not the viewer. // Lets "save as" save the original JSON, not the viewer. // To save with the proper extension we need the original content type, // which has been replaced by application/vnd.mozilla.json.view function fixSave(request) { let originalType; if (request instanceof Ci.nsIHttpChannel) { try { Loading @@ -95,22 +134,10 @@ Converter.prototype = { } request.QueryInterface(Ci.nsIWritablePropertyBag); request.setProperty("contentType", originalType); } // Parse source as JSON. This is like text/plain, but enforcing // UTF-8 charset (see bug 741776). request.QueryInterface(Ci.nsIChannel); request.contentType = JSON_TYPES[0]; this.charset = request.contentCharset = "UTF-8"; // Because content might still have a reference to this window, // force setting it to a null principal to avoid it being same- // origin with (other) content. request.loadInfo.resetPrincipalToInheritToNullPrincipal(); this.listener.onStartRequest(request, context); }, onStopRequest: function (request, context, statusCode) { // Exports variables that will be accessed by the non-privileged scripts. function exportData(win, request) { let Locale = { $STR: key => { try { Loading @@ -121,6 +148,7 @@ Converter.prototype = { } } }; JsonViewUtils.exportIntoContentScope(win, Locale, "Locale"); let headers = { response: [], Loading @@ -140,26 +168,68 @@ Converter.prototype = { } }); } let win = NetworkHelper.getWindowForRequest(request); JsonViewUtils.exportIntoContentScope(win, Locale, "Locale"); JsonViewUtils.exportIntoContentScope(win, headers, "headers"); } win.addEventListener("DOMContentLoaded", event => { win.addEventListener("contentMessage", onContentMessage.bind(this), false, true); loadJsonViewer(win.document); }, {once: true}); // Serializes a qualifiedName and an optional set of attributes into an HTML // start tag. Be aware qualifiedName and attribute names are not validated. // Attribute values are escaped with escapingString algorithm in attribute mode // (https://html.spec.whatwg.org/multipage/syntax.html#escapingString). function startTag(qualifiedName, attributes = {}) { return Object.entries(attributes).reduce(function (prev, [attr, value]) { return prev + " " + attr + "=\"" + value.replace(/&/g, "&") .replace(/\u00a0/g, " ") .replace(/"/g, """) + "\""; }, "<" + qualifiedName) + ">"; } this.listener.onStopRequest(this.channel, context, statusCode); this.listener = null; // Builds an HTML string that will be used to load stylesheets and scripts, // and switch the parser to plaintext state. function initialHTML(doc) { let os; let platform = Services.appinfo.OS; if (platform.startsWith("WINNT")) { os = "win"; } else if (platform.startsWith("Darwin")) { os = "mac"; } else { os = "linux"; } let base = doc.createElement("base"); base.href = "resource://devtools/client/jsonview/"; let style = doc.createElement("link"); style.rel = "stylesheet"; style.type = "text/css"; style.href = "css/main.css"; let script = doc.createElement("script"); script.src = "lib/require.js"; script.dataset.main = "viewer-config"; script.defer = true; let head = doc.createElement("head"); head.append(base, style, script); return "<!DOCTYPE html>\n" + startTag("html", { "platform": os, "class": "theme-" + JsonViewUtils.getCurrentTheme(), "dir": Services.locale.isAppLocaleRTL ? "rtl" : "ltr" }) + head.outerHTML + startTag("body") + startTag("div", {"id": "content"}) + startTag("plaintext", {"id": "json"}); } }; // Chrome <-> Content communication function onContentMessage(e) { // Do not handle events from different documents. let win = NetworkHelper.getWindowForRequest(this.channel); let win = this; if (win != e.target) { return; } Loading @@ -183,53 +253,6 @@ function onContentMessage(e) { } } // Loads the JSON Viewer into a text/plain document function loadJsonViewer(doc) { function addStyleSheet(url) { let link = doc.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = url; doc.head.appendChild(link); } let os; let platform = Services.appinfo.OS; if (platform.startsWith("WINNT")) { os = "win"; } else if (platform.startsWith("Darwin")) { os = "mac"; } else { os = "linux"; } doc.documentElement.setAttribute("platform", os); doc.documentElement.dataset.contentType = doc.contentType; doc.documentElement.classList.add("theme-" + JsonViewUtils.getCurrentTheme()); doc.documentElement.dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr"; let base = doc.createElement("base"); base.href = "resource://devtools/client/jsonview/"; doc.head.appendChild(base); addStyleSheet("../themes/variables.css"); addStyleSheet("../themes/common.css"); addStyleSheet("../themes/toolbars.css"); addStyleSheet("css/main.css"); let json = doc.querySelector("pre"); json.id = "json"; let content = doc.createElement("div"); content.id = "content"; content.appendChild(json); doc.body.appendChild(content); let script = doc.createElement("script"); script.src = "lib/require.js"; script.dataset.main = "viewer-config"; doc.body.appendChild(script); } function copyHeaders(win, headers) { let value = ""; let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n"; Loading devtools/client/jsonview/css/general.css +1 −7 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ pre { #json { margin: 8px; white-space: pre-wrap; } /******************************************************************************/ Loading @@ -46,10 +47,3 @@ body.theme-dark { .theme-dark pre { background-color: var(--theme-body-background); } /******************************************************************************/ /* Fixes for quirks mode */ table { font: inherit; } devtools/client/jsonview/css/main.css +4 −2 Original line number Diff line number Diff line Loading @@ -3,7 +3,10 @@ * 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/. */ @import "resource://devtools/client/shared/components/reps/reps.css"; @import "resource://devtools/client/themes/variables.css"; @import "resource://devtools/client/themes/common.css"; @import "resource://devtools/client/themes/toolbars.css"; @import "resource://devtools/client/shared/components/tree/tree-view.css"; @import "resource://devtools/client/shared/components/tabs/tabs.css"; Loading Loading @@ -53,4 +56,3 @@ .theme-firebug .tabs .tabs-navigation { font-size: 14px; } Loading
devtools/client/jsonview/converter-child.js +142 −119 Original line number Diff line number Diff line Loading @@ -51,8 +51,7 @@ Converter.prototype = { * 2. onStartRequest fires, initializes stuff, modifies the listener * to match our output type * 3. onDataAvailable spits it back to the listener * 4. onStopRequest spits it back to the listener and initializes the JSON Viewer * 4. onStopRequest spits it back to the listener * 5. convert does nothing, it's just the synchronous version * of asyncConvertData */ Loading @@ -69,11 +68,51 @@ Converter.prototype = { }, onStartRequest: function (request, context) { this.channel = request; // Set the content type to HTML in order to parse the doctype, styles // and scripts, but later a <plaintext> element will switch the tokenizer // to the plaintext state in order to parse the JSON. request.QueryInterface(Ci.nsIChannel); request.contentType = "text/html"; // JSON enforces UTF-8 charset (see bug 741776). request.contentCharset = "UTF-8"; // Changing the content type breaks saving functionality. Fix it. fixSave(request); // Because content might still have a reference to this window, // force setting it to a null principal to avoid it being same- // origin with (other) content. request.loadInfo.resetPrincipalToInheritToNullPrincipal(); // Start the request. this.listener.onStartRequest(request, context); // Initialize stuff. let win = NetworkHelper.getWindowForRequest(request); exportData(win, request); win.addEventListener("DOMContentLoaded", event => { win.addEventListener("contentMessage", onContentMessage, false, true); }, {once: true}); // Insert the initial HTML code. let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; let stream = converter.convertToInputStream(initialHTML(win.document)); this.listener.onDataAvailable(request, context, stream, 0, stream.available()); }, onStopRequest: function (request, context, statusCode) { this.listener.onStopRequest(request, context, statusCode); this.listener = null; } }; // Let "save as" save the original JSON, not the viewer. // Lets "save as" save the original JSON, not the viewer. // To save with the proper extension we need the original content type, // which has been replaced by application/vnd.mozilla.json.view function fixSave(request) { let originalType; if (request instanceof Ci.nsIHttpChannel) { try { Loading @@ -95,22 +134,10 @@ Converter.prototype = { } request.QueryInterface(Ci.nsIWritablePropertyBag); request.setProperty("contentType", originalType); } // Parse source as JSON. This is like text/plain, but enforcing // UTF-8 charset (see bug 741776). request.QueryInterface(Ci.nsIChannel); request.contentType = JSON_TYPES[0]; this.charset = request.contentCharset = "UTF-8"; // Because content might still have a reference to this window, // force setting it to a null principal to avoid it being same- // origin with (other) content. request.loadInfo.resetPrincipalToInheritToNullPrincipal(); this.listener.onStartRequest(request, context); }, onStopRequest: function (request, context, statusCode) { // Exports variables that will be accessed by the non-privileged scripts. function exportData(win, request) { let Locale = { $STR: key => { try { Loading @@ -121,6 +148,7 @@ Converter.prototype = { } } }; JsonViewUtils.exportIntoContentScope(win, Locale, "Locale"); let headers = { response: [], Loading @@ -140,26 +168,68 @@ Converter.prototype = { } }); } let win = NetworkHelper.getWindowForRequest(request); JsonViewUtils.exportIntoContentScope(win, Locale, "Locale"); JsonViewUtils.exportIntoContentScope(win, headers, "headers"); } win.addEventListener("DOMContentLoaded", event => { win.addEventListener("contentMessage", onContentMessage.bind(this), false, true); loadJsonViewer(win.document); }, {once: true}); // Serializes a qualifiedName and an optional set of attributes into an HTML // start tag. Be aware qualifiedName and attribute names are not validated. // Attribute values are escaped with escapingString algorithm in attribute mode // (https://html.spec.whatwg.org/multipage/syntax.html#escapingString). function startTag(qualifiedName, attributes = {}) { return Object.entries(attributes).reduce(function (prev, [attr, value]) { return prev + " " + attr + "=\"" + value.replace(/&/g, "&") .replace(/\u00a0/g, " ") .replace(/"/g, """) + "\""; }, "<" + qualifiedName) + ">"; } this.listener.onStopRequest(this.channel, context, statusCode); this.listener = null; // Builds an HTML string that will be used to load stylesheets and scripts, // and switch the parser to plaintext state. function initialHTML(doc) { let os; let platform = Services.appinfo.OS; if (platform.startsWith("WINNT")) { os = "win"; } else if (platform.startsWith("Darwin")) { os = "mac"; } else { os = "linux"; } let base = doc.createElement("base"); base.href = "resource://devtools/client/jsonview/"; let style = doc.createElement("link"); style.rel = "stylesheet"; style.type = "text/css"; style.href = "css/main.css"; let script = doc.createElement("script"); script.src = "lib/require.js"; script.dataset.main = "viewer-config"; script.defer = true; let head = doc.createElement("head"); head.append(base, style, script); return "<!DOCTYPE html>\n" + startTag("html", { "platform": os, "class": "theme-" + JsonViewUtils.getCurrentTheme(), "dir": Services.locale.isAppLocaleRTL ? "rtl" : "ltr" }) + head.outerHTML + startTag("body") + startTag("div", {"id": "content"}) + startTag("plaintext", {"id": "json"}); } }; // Chrome <-> Content communication function onContentMessage(e) { // Do not handle events from different documents. let win = NetworkHelper.getWindowForRequest(this.channel); let win = this; if (win != e.target) { return; } Loading @@ -183,53 +253,6 @@ function onContentMessage(e) { } } // Loads the JSON Viewer into a text/plain document function loadJsonViewer(doc) { function addStyleSheet(url) { let link = doc.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = url; doc.head.appendChild(link); } let os; let platform = Services.appinfo.OS; if (platform.startsWith("WINNT")) { os = "win"; } else if (platform.startsWith("Darwin")) { os = "mac"; } else { os = "linux"; } doc.documentElement.setAttribute("platform", os); doc.documentElement.dataset.contentType = doc.contentType; doc.documentElement.classList.add("theme-" + JsonViewUtils.getCurrentTheme()); doc.documentElement.dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr"; let base = doc.createElement("base"); base.href = "resource://devtools/client/jsonview/"; doc.head.appendChild(base); addStyleSheet("../themes/variables.css"); addStyleSheet("../themes/common.css"); addStyleSheet("../themes/toolbars.css"); addStyleSheet("css/main.css"); let json = doc.querySelector("pre"); json.id = "json"; let content = doc.createElement("div"); content.id = "content"; content.appendChild(json); doc.body.appendChild(content); let script = doc.createElement("script"); script.src = "lib/require.js"; script.dataset.main = "viewer-config"; doc.body.appendChild(script); } function copyHeaders(win, headers) { let value = ""; let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n"; Loading
devtools/client/jsonview/css/general.css +1 −7 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ pre { #json { margin: 8px; white-space: pre-wrap; } /******************************************************************************/ Loading @@ -46,10 +47,3 @@ body.theme-dark { .theme-dark pre { background-color: var(--theme-body-background); } /******************************************************************************/ /* Fixes for quirks mode */ table { font: inherit; }
devtools/client/jsonview/css/main.css +4 −2 Original line number Diff line number Diff line Loading @@ -3,7 +3,10 @@ * 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/. */ @import "resource://devtools/client/shared/components/reps/reps.css"; @import "resource://devtools/client/themes/variables.css"; @import "resource://devtools/client/themes/common.css"; @import "resource://devtools/client/themes/toolbars.css"; @import "resource://devtools/client/shared/components/tree/tree-view.css"; @import "resource://devtools/client/shared/components/tabs/tabs.css"; Loading Loading @@ -53,4 +56,3 @@ .theme-firebug .tabs .tabs-navigation { font-size: 14px; }