forked from mirrors/gecko-dev
		
	 2f68e50e6c
			
		
	
	
		2f68e50e6c
		
	
	
	
	
		
			
			MozReview-Commit-ID: DceweCXElI4 --HG-- extra : rebase_source : c900d38b4e6ffb7bf8a6aa16e9f3b6106f63f6c9
		
			
				
	
	
		
			249 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
	
		
			7.3 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 { writeHeaderText } = require("../../utils/request-utils");
 | |
| const { getHeadersURL } = require("../../utils/mdn-utils");
 | |
| const { getFormattedSize } = require("../../utils/format-utils");
 | |
| const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
 | |
| const Rep = createFactory(REPS.Rep);
 | |
| 
 | |
| // Components
 | |
| const MDNLink = createFactory(require("./mdn-link"));
 | |
| const PropertiesView = createFactory(require("./properties-view"));
 | |
| 
 | |
| const { button, div, input, textarea } = DOM;
 | |
| 
 | |
| const EDIT_AND_RESEND = L10N.getStr("netmonitor.summary.editAndResend");
 | |
| const RAW_HEADERS = L10N.getStr("netmonitor.summary.rawHeaders");
 | |
| const RAW_HEADERS_REQUEST = L10N.getStr("netmonitor.summary.rawHeaders.requestHeaders");
 | |
| const RAW_HEADERS_RESPONSE = L10N.getStr("netmonitor.summary.rawHeaders.responseHeaders");
 | |
| const HEADERS_EMPTY_TEXT = L10N.getStr("headersEmptyText");
 | |
| const HEADERS_FILTER_TEXT = L10N.getStr("headersFilterText");
 | |
| const REQUEST_HEADERS = L10N.getStr("requestHeaders");
 | |
| const REQUEST_HEADERS_FROM_UPLOAD = L10N.getStr("requestHeadersFromUpload");
 | |
| const RESPONSE_HEADERS = L10N.getStr("responseHeaders");
 | |
| const SUMMARY_ADDRESS = L10N.getStr("netmonitor.summary.address");
 | |
| const SUMMARY_METHOD = L10N.getStr("netmonitor.summary.method");
 | |
| const SUMMARY_URL = L10N.getStr("netmonitor.summary.url");
 | |
| const SUMMARY_STATUS = L10N.getStr("netmonitor.summary.status");
 | |
| const SUMMARY_VERSION = L10N.getStr("netmonitor.summary.version");
 | |
| 
 | |
| /*
 | |
|  * Headers panel component
 | |
|  * Lists basic information about the request
 | |
|  */
 | |
| const HeadersPanel = createClass({
 | |
|   displayName: "HeadersPanel",
 | |
| 
 | |
|   propTypes: {
 | |
|     cloneSelectedRequest: PropTypes.func.isRequired,
 | |
|     request: PropTypes.object.isRequired,
 | |
|     renderValue: PropTypes.func
 | |
|   },
 | |
| 
 | |
|   getInitialState() {
 | |
|     return {
 | |
|       rawHeadersOpened: false,
 | |
|     };
 | |
|   },
 | |
| 
 | |
|   getProperties(headers, title) {
 | |
|     if (headers && headers.headers.length) {
 | |
|       return {
 | |
|         [`${title} (${getFormattedSize(headers.headersSize, 3)})`]:
 | |
|           headers.headers.reduce((acc, { name, value }) =>
 | |
|             name ? Object.assign(acc, { [name]: value }) : acc
 | |
|           , {})
 | |
|       };
 | |
|     }
 | |
| 
 | |
|     return null;
 | |
|   },
 | |
| 
 | |
|   toggleRawHeaders() {
 | |
|     this.setState({
 | |
|       rawHeadersOpened: !this.state.rawHeadersOpened,
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   renderSummary(label, value) {
 | |
|     return (
 | |
|       div({ className: "tabpanel-summary-container headers-summary" },
 | |
|         div({
 | |
|           className: "tabpanel-summary-label headers-summary-label",
 | |
|         }, label),
 | |
|         input({
 | |
|           className: "tabpanel-summary-value textbox-input devtools-monospace",
 | |
|           readOnly: true,
 | |
|           value,
 | |
|         }),
 | |
|       )
 | |
|     );
 | |
|   },
 | |
| 
 | |
|   renderValue(props) {
 | |
|     const member = props.member;
 | |
|     const value = props.value;
 | |
| 
 | |
|     if (typeof value !== "string") {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     let headerDocURL = getHeadersURL(member.name);
 | |
| 
 | |
|     return (
 | |
|       div({ className: "treeValueCellDivider" },
 | |
|         Rep(Object.assign(props, {
 | |
|           // FIXME: A workaround for the issue in StringRep
 | |
|           // Force StringRep to crop the text everytime
 | |
|           member: Object.assign({}, member, { open: false }),
 | |
|           mode: MODE.TINY,
 | |
|           cropLimit: 60,
 | |
|         })),
 | |
|         headerDocURL ? MDNLink({
 | |
|           url: headerDocURL,
 | |
|         }) : null
 | |
|       )
 | |
|     );
 | |
|   },
 | |
| 
 | |
|   render() {
 | |
|     const {
 | |
|       cloneSelectedRequest,
 | |
|       request: {
 | |
|         fromCache,
 | |
|         fromServiceWorker,
 | |
|         httpVersion,
 | |
|         method,
 | |
|         remoteAddress,
 | |
|         remotePort,
 | |
|         requestHeaders,
 | |
|         requestHeadersFromUploadStream: uploadHeaders,
 | |
|         responseHeaders,
 | |
|         status,
 | |
|         statusText,
 | |
|         urlDetails,
 | |
|       },
 | |
|     } = this.props;
 | |
| 
 | |
|     if ((!requestHeaders || !requestHeaders.headers.length) &&
 | |
|         (!uploadHeaders || !uploadHeaders.headers.length) &&
 | |
|         (!responseHeaders || !responseHeaders.headers.length)) {
 | |
|       return div({ className: "empty-notice" },
 | |
|         HEADERS_EMPTY_TEXT
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     let object = Object.assign({},
 | |
|       this.getProperties(responseHeaders, RESPONSE_HEADERS),
 | |
|       this.getProperties(requestHeaders, REQUEST_HEADERS),
 | |
|       this.getProperties(uploadHeaders, REQUEST_HEADERS_FROM_UPLOAD),
 | |
|     );
 | |
| 
 | |
|     let summaryUrl = urlDetails.unicodeUrl ?
 | |
|       this.renderSummary(SUMMARY_URL, urlDetails.unicodeUrl) : null;
 | |
| 
 | |
|     let summaryMethod = method ?
 | |
|       this.renderSummary(SUMMARY_METHOD, method) : null;
 | |
| 
 | |
|     let summaryAddress = remoteAddress ?
 | |
|       this.renderSummary(SUMMARY_ADDRESS,
 | |
|         remotePort ? `${remoteAddress}:${remotePort}` : remoteAddress) : null;
 | |
| 
 | |
|     let summaryStatus;
 | |
| 
 | |
|     if (status) {
 | |
|       let code;
 | |
|       if (fromCache) {
 | |
|         code = "cached";
 | |
|       } else if (fromServiceWorker) {
 | |
|         code = "service worker";
 | |
|       } else {
 | |
|         code = status;
 | |
|       }
 | |
| 
 | |
|       summaryStatus = (
 | |
|         div({ className: "tabpanel-summary-container headers-summary" },
 | |
|           div({
 | |
|             className: "tabpanel-summary-label headers-summary-label",
 | |
|           }, SUMMARY_STATUS),
 | |
|           div({
 | |
|             className: "requests-list-status-icon",
 | |
|             "data-code": code,
 | |
|           }),
 | |
|           input({
 | |
|             className: "tabpanel-summary-value textbox-input devtools-monospace",
 | |
|             readOnly: true,
 | |
|             value: `${status} ${statusText}`,
 | |
|           }),
 | |
|           window.NetMonitorController.supportsCustomRequest && button({
 | |
|             className: "devtools-button",
 | |
|             onClick: cloneSelectedRequest,
 | |
|           }, EDIT_AND_RESEND),
 | |
|           button({
 | |
|             className: "devtools-button",
 | |
|             onClick: this.toggleRawHeaders,
 | |
|           }, RAW_HEADERS),
 | |
|         )
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     let summaryVersion = httpVersion ?
 | |
|       this.renderSummary(SUMMARY_VERSION, httpVersion) : null;
 | |
| 
 | |
|     let summaryRawHeaders;
 | |
|     if (this.state.rawHeadersOpened) {
 | |
|       summaryRawHeaders = (
 | |
|         div({ className: "tabpanel-summary-container headers-summary" },
 | |
|           div({ className: "raw-headers-container" },
 | |
|             div({ className: "raw-headers" },
 | |
|               div({ className: "tabpanel-summary-label" }, RAW_HEADERS_REQUEST),
 | |
|               textarea({
 | |
|                 value: writeHeaderText(requestHeaders.headers),
 | |
|                 readOnly: true,
 | |
|               }),
 | |
|             ),
 | |
|             div({ className: "raw-headers" },
 | |
|               div({ className: "tabpanel-summary-label" }, RAW_HEADERS_RESPONSE),
 | |
|               textarea({
 | |
|                 value: writeHeaderText(responseHeaders.headers),
 | |
|                 readOnly: true,
 | |
|               }),
 | |
|             ),
 | |
|           )
 | |
|         )
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     return (
 | |
|       div({ className: "panel-container" },
 | |
|         div({ className: "headers-overview" },
 | |
|           summaryUrl,
 | |
|           summaryMethod,
 | |
|           summaryAddress,
 | |
|           summaryStatus,
 | |
|           summaryVersion,
 | |
|           summaryRawHeaders,
 | |
|         ),
 | |
|         PropertiesView({
 | |
|           object,
 | |
|           filterPlaceHolder: HEADERS_FILTER_TEXT,
 | |
|           sectionNames: Object.keys(object),
 | |
|           renderValue: this.renderValue,
 | |
|         }),
 | |
|       )
 | |
|     );
 | |
|   }
 | |
| });
 | |
| 
 | |
| module.exports = HeadersPanel;
 |