forked from mirrors/gecko-dev
		
	 ddd187450f
			
		
	
	
		ddd187450f
		
	
	
	
	
		
			
			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
		
			
				
	
	
		
			185 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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;
 |