1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 define(function (require, exports, module) {
8 const { render } = require("devtools/client/shared/vendor/react-dom");
9 const { createFactories } = require("devtools/client/shared/react-utils");
10 const { MainTabbedArea } = createFactories(
11 require("devtools/client/jsonview/components/MainTabbedArea")
13 const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
15 const AUTO_EXPAND_MAX_SIZE = 100 * 1024;
16 const AUTO_EXPAND_MAX_LEVEL = 7;
26 // Application state object.
28 jsonText: JSONView.json,
30 headers: JSONView.headers,
33 expandedNodes: new Set(),
37 * Application actions/commands. This list implements all commands
38 * available for the JSON viewer.
42 const text = input.prettified ? input.jsonPretty : input.jsonText;
43 copyString(text.textContent);
47 if (input.prettified && !prettyURL) {
48 prettyURL = URL.createObjectURL(
49 new window.Blob([input.jsonPretty.textContent])
52 dispatchEvent("save", input.prettified ? prettyURL : null);
58 document.documentElement.getAttribute("platform") === "win";
59 const eol = isWinNT ? "\r\n" : "\n";
61 const responseHeaders = input.headers.response;
62 for (let i = 0; i < responseHeaders.length; i++) {
63 const header = responseHeaders[i];
64 value += header.name + ": " + header.value + eol;
69 const requestHeaders = input.headers.request;
70 for (let i = 0; i < requestHeaders.length; i++) {
71 const header = requestHeaders[i];
72 value += header.name + ": " + header.value + eol;
79 theApp.setState({ searchFilter: value });
83 if (input.json instanceof Error) {
84 // Cannot prettify invalid JSON
87 if (input.prettified) {
88 theApp.setState({ jsonText: input.jsonText });
90 if (!input.jsonPretty) {
91 input.jsonPretty = new Text(JSON.stringify(input.json, null, " "));
93 theApp.setState({ jsonText: input.jsonPretty });
96 input.prettified = !input.prettified;
100 input.expandedNodes.clear();
101 theApp.forceUpdate();
105 input.expandedNodes = TreeViewClass.getExpandedNodes(input.json);
106 theApp.setState({ expandedNodes: input.expandedNodes });
111 * Helper for copying a string to the clipboard.
113 * @param {String} string The text to be copied.
115 function copyString(string) {
116 document.addEventListener(
119 event.clipboardData.setData("text/plain", string);
120 event.preventDefault();
125 document.execCommand("copy", false, null);
129 * Helper for dispatching an event. It's handled in chrome scope.
131 * @param {String} type Event detail type
132 * @param {Object} value Event detail value
134 function dispatchEvent(type, value) {
142 const contentMessageEvent = new CustomEvent("contentMessage", data);
143 window.dispatchEvent(contentMessageEvent);
147 * Render the main application component. It's the main tab bar displayed
148 * at the top of the window. This component also represents ReacJS root.
150 const content = document.getElementById("content");
151 const promise = (async function parseJSON() {
152 if (document.readyState == "loading") {
153 // If the JSON has not been loaded yet, render the Raw Data tab first.
155 input.activeTab = TABS.RAW_DATA;
156 return new Promise(resolve => {
157 document.addEventListener("DOMContentLoaded", resolve, { once: true });
161 // Now update the state and switch to the JSON tab.
164 activeTab: TABS.JSON,
166 expandedNodes: input.expandedNodes,
171 // If the JSON has been loaded, parse it immediately before loading the app.
172 const jsonString = input.jsonText.textContent;
174 input.json = JSON.parse(jsonString);
177 // Display the raw data tab for invalid json
178 input.activeTab = TABS.RAW_DATA;
181 // Expand the document by default if its size isn't bigger than 100KB.
183 !(input.json instanceof Error) &&
184 jsonString.length <= AUTO_EXPAND_MAX_SIZE
186 input.expandedNodes = TreeViewClass.getExpandedNodes(input.json, {
187 maxLevel: AUTO_EXPAND_MAX_LEVEL,
193 const appIsReady = new Promise(resolve => {
194 render(MainTabbedArea(input), content, function () {
198 // Send readyState change notification event to the window. Can be useful for
199 // tests as well as extensions.
200 JSONView.readyState = "interactive";
201 window.dispatchEvent(new CustomEvent("AppReadyStateChange"));
204 // Another readyState change notification event.
205 JSONView.readyState = "complete";
206 window.dispatchEvent(new CustomEvent("AppReadyStateChange"));