diff --git a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css index 0ce7066376a4..04c92d863cd2 100644 --- a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css +++ b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css @@ -108,7 +108,8 @@ } .network-monitor .properties-view .devtools-searchbox, -.network-monitor .tree-container .treeTable .tree-section { +.network-monitor .tree-container .treeTable .tree-section, +.network-monitor .properties-view .raw-headers-container { width: 100%; background-color: var(--theme-toolbar-background); } @@ -207,6 +208,19 @@ color: var(--theme-selection-color); } +.theme-dark .network-monitor .edit-and-resend-button { + background-color: var(--toolbarbutton-background); + color: var(--theme-selection-color); +} + +.summary-edit-and-resend { + display: flex; + align-items: center; + flex-wrap: wrap; + justify-content: space-between; + padding-inline-end: 3px; +} + /* Headers tabpanel */ .network-monitor .headers-overview { @@ -219,29 +233,79 @@ align-items: center; } -.network-monitor .headers-summary .devtools-button { - margin-inline-end: 6px; +.theme-light .network-monitor .edit-and-resend-button { + background-color: var(--grey-20); } -.network-monitor .headers-summary .raw-headers-container { +.network-monitor .edit-and-resend-button { + align-self: flex-end; + height: 24px; + padding-left: 8px; + padding-right: 8px; + width: auto; + border: 1px solid var(--theme-splitter-color); +} + +.network-monitor .raw-headers-toggle { display: flex; - width: 100%; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-end; + align-items: center; } -.network-monitor .headers-summary .raw-headers { - width: 50%; - padding: 0 4px; +.network-monitor .raw-headers-toggle .headers-summary-label { + color: var(--theme-toolbar-color); } -.network-monitor .headers-summary .raw-headers textarea { +.network-monitor .raw-headers-toggle-input > input { + display: inline-block; + align-items: center; + background: var(--toggle-track-color); + width: 2em ; + vertical-align: bottom; +} + +.network-monitor .properties-view .tree-container .treeTable .treeValueCell .devtools-checkbox-toggle { + margin-top: 2px; + margin-bottom: 2px; +} + +.network-monitor .properties-view .raw-headers-container .raw-headers { + display: block; + overflow: hidden; width: 100%; - height: 50vh; - font: message-box; + padding: 2px 12px; + white-space: pre; + overflow-wrap: normal; + overflow-x: auto; + border: none; +} + +.network-monitor .properties-view .raw-headers-container td { + display: block; +} + +.network-monitor .properties-view .raw-headers-container textarea { + width: 100%; + font-family: var(--monospace-font-family); font-size: var(--theme-body-font-size); resize: none; } -.network-monitor .headers-summary .raw-headers .tabpanel-summary-label { +.theme-light .network-monitor .properties-view textarea { + background-color: white; + border: 1px solid var(--grey-25); + color: var(--grey-90); +} + +.theme-dark .network-monitor .properties-view textarea { + background-color: var(--grey-70); + border: 1px solid var(--grey-85); + color: white; +} + +.network-monitor .properties-view .raw-headers .tabpanel-summary-label { padding: 0 0 4px 0; } diff --git a/devtools/client/netmonitor/src/components/HeadersPanel.js b/devtools/client/netmonitor/src/components/HeadersPanel.js index bc768c26f857..540559b0f04d 100644 --- a/devtools/client/netmonitor/src/components/HeadersPanel.js +++ b/devtools/client/netmonitor/src/components/HeadersPanel.js @@ -38,13 +38,14 @@ loader.lazyGetter(this, "Rep", function() { loader.lazyGetter(this, "MODE", function() { return require("devtools/client/shared/components/reps/reps").MODE; }); +loader.lazyGetter(this, "TreeRow", function() { + return createFactory(require("devtools/client/shared/components/tree/TreeRow")); +}); -const { button, div, input, textarea, span } = dom; +const { button, div, input, label, span, textarea, tr, td } = 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"); @@ -67,6 +68,7 @@ class HeadersPanel extends Component { return { connector: PropTypes.object.isRequired, cloneSelectedRequest: PropTypes.func.isRequired, + member: PropTypes.object.isRequired, request: PropTypes.object.isRequired, renderValue: PropTypes.func, openLink: PropTypes.func, @@ -77,12 +79,17 @@ class HeadersPanel extends Component { super(props); this.state = { - rawHeadersOpened: false, + rawRequestHeadersOpened: false, + rawResponseHeadersOpened: false, + rawUploadHeadersOpened: false, }; this.getProperties = this.getProperties.bind(this); - this.toggleRawHeaders = this.toggleRawHeaders.bind(this); + this.toggleRawResponseHeaders = this.toggleRawResponseHeaders.bind(this); + this.toggleRawRequestHeaders = this.toggleRawRequestHeaders.bind(this); + this.toggleRawUploadHeaders = this.toggleRawUploadHeaders.bind(this); this.renderSummary = this.renderSummary.bind(this); + this.renderRow = this.renderRow.bind(this); this.renderValue = this.renderValue.bind(this); } @@ -105,29 +112,67 @@ class HeadersPanel extends Component { } getProperties(headers, title) { + let propertiesResult; + if (headers && headers.headers.length) { const headerKey = `${title} (${getFormattedSize(headers.headersSize, 3)})`; - const propertiesResult = { + + propertiesResult = { [headerKey]: new HeaderList(headers.headers), }; - return propertiesResult; - } - return null; + if ((title === RESPONSE_HEADERS && this.state.rawResponseHeadersOpened) || + (title === REQUEST_HEADERS && this.state.rawRequestHeadersOpened) || + (title === REQUEST_HEADERS_FROM_UPLOAD && this.state.rawUploadHeadersOpened)) { + propertiesResult = { + [headerKey]: { RAW_HEADERS_ID: headers.rawHeaders }, + }; + } + } + return propertiesResult; } - toggleRawHeaders() { + toggleRawResponseHeaders() { this.setState({ - rawHeadersOpened: !this.state.rawHeadersOpened, + rawResponseHeadersOpened: !this.state.rawResponseHeadersOpened, }); } - renderSummary(label, value) { + toggleRawRequestHeaders() { + this.setState({ + rawRequestHeadersOpened: !this.state.rawRequestHeadersOpened, + }); + } + + toggleRawUploadHeaders() { + this.setState({ + rawUploadHeadersOpened: !this.state.rawUploadHeadersOpened, + }); + } + + /** + * Helper method to identify what kind of raw header this is. + * Information is in the path variable + */ + getRawHeaderType(path) { + if (path.includes(RESPONSE_HEADERS)) { + return "RESPONSE"; + } + if (path.includes(REQUEST_HEADERS_FROM_UPLOAD)) { + return "UPLOAD"; + } + return "REQUEST"; + } + + /** + * Renders the top part of the headers detail panel - Summary. + */ + renderSummary(summaryLabel, value) { return ( div({ className: "tabpanel-summary-container headers-summary" }, div({ className: "tabpanel-summary-labelvalue"}, span({ className: "tabpanel-summary-label headers-summary-label"}, - label + summaryLabel ), span({ className: "tabpanel-summary-value textbox-input devtools-monospace"}, value @@ -137,9 +182,140 @@ class HeadersPanel extends Component { ); } + /** + * Custom rendering method passed to PropertiesView. It's responsible + * for rendering