blob: 5d6106084df42978e1c490d551c08e2962d4804b [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) IBM Corp. 2009 All rights reserved.
4 * Copyright (C) 2010 Google Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31Network.RequestHeadersView = class extends UI.VBox {
32 /**
33 * @param {!SDK.NetworkRequest} request
34 */
35 constructor(request) {
36 super();
37 this.registerRequiredCSS('network/requestHeadersView.css');
38 this.element.classList.add('request-headers-view');
39
40 this._request = request;
41 this._decodeRequestParameters = true;
42 this._showRequestHeadersText = false;
43 this._showResponseHeadersText = false;
44
45 /** @type {?UI.TreeElement} */
46 this._highlightedElement = null;
47
48 const root = new UI.TreeOutlineInShadow();
Amanda Bakerc3d15272019-10-25 00:56:3949 root.registerRequiredCSS('object_ui/objectValue.css');
50 root.registerRequiredCSS('object_ui/objectPropertiesSection.css');
Blink Reformat4c46d092018-04-07 15:32:3751 root.registerRequiredCSS('network/requestHeadersTree.css');
52 root.element.classList.add('request-headers-tree');
Blink Reformat4c46d092018-04-07 15:32:3753 root.makeDense();
Blink Reformat4c46d092018-04-07 15:32:3754 this.element.appendChild(root.element);
55
56 const generalCategory = new Network.RequestHeadersView.Category(root, 'general', Common.UIString('General'));
57 generalCategory.hidden = false;
Amanda Baker2e19a1b2019-10-25 00:41:0258 this._root = generalCategory;
Blink Reformat4c46d092018-04-07 15:32:3759 this._urlItem = generalCategory.createLeaf();
60 this._requestMethodItem = generalCategory.createLeaf();
61 this._statusCodeItem = generalCategory.createLeaf();
62 this._remoteAddressItem = generalCategory.createLeaf();
63 this._remoteAddressItem.hidden = true;
64 this._referrerPolicyItem = generalCategory.createLeaf();
65 this._referrerPolicyItem.hidden = true;
66
67 this._responseHeadersCategory = new Network.RequestHeadersView.Category(root, 'responseHeaders', '');
68 this._requestHeadersCategory = new Network.RequestHeadersView.Category(root, 'requestHeaders', '');
69 this._queryStringCategory = new Network.RequestHeadersView.Category(root, 'queryString', '');
70 this._formDataCategory = new Network.RequestHeadersView.Category(root, 'formData', '');
71 this._requestPayloadCategory =
72 new Network.RequestHeadersView.Category(root, 'requestPayload', Common.UIString('Request Payload'));
73 }
74
75 /**
76 * @override
77 */
78 wasShown() {
79 this._clearHighlight();
80 this._request.addEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this._refreshRemoteAddress, this);
81 this._request.addEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshRequestHeaders, this);
82 this._request.addEventListener(
83 SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshResponseHeaders, this);
84 this._request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._refreshHTTPInformation, this);
85
86 this._refreshURL();
87 this._refreshQueryString();
88 this._refreshRequestHeaders();
89 this._refreshResponseHeaders();
90 this._refreshHTTPInformation();
91 this._refreshRemoteAddress();
92 this._refreshReferrerPolicy();
Amanda Baker2e19a1b2019-10-25 00:41:0293 this._root.select(/* omitFocus */ true, /* selectedByUser */ false);
Blink Reformat4c46d092018-04-07 15:32:3794 }
95
96 /**
97 * @override
98 */
99 willHide() {
100 this._request.removeEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this._refreshRemoteAddress, this);
101 this._request.removeEventListener(
102 SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshRequestHeaders, this);
103 this._request.removeEventListener(
104 SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshResponseHeaders, this);
105 this._request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._refreshHTTPInformation, this);
106 }
107
108 /**
109 * @param {string} name
110 * @param {string} value
111 * @return {!DocumentFragment}
112 */
113 _formatHeader(name, value) {
114 const fragment = createDocumentFragment();
115 fragment.createChild('div', 'header-name').textContent = name + ': ';
116 fragment.createChild('span', 'header-separator');
117 fragment.createChild('div', 'header-value source-code').textContent = value;
118
119 return fragment;
120 }
121
122 /**
123 * @param {string} value
124 * @param {string} className
125 * @param {boolean} decodeParameters
126 * @return {!Element}
127 */
128 _formatParameter(value, className, decodeParameters) {
129 let errorDecoding = false;
130
131 if (decodeParameters) {
132 value = value.replace(/\+/g, ' ');
133 if (value.indexOf('%') >= 0) {
134 try {
135 value = decodeURIComponent(value);
136 } catch (e) {
137 errorDecoding = true;
138 }
139 }
140 }
141 const div = createElementWithClass('div', className);
Tim van der Lippe1d6e57a2019-09-30 11:55:34142 if (value === '') {
Blink Reformat4c46d092018-04-07 15:32:37143 div.classList.add('empty-value');
Tim van der Lippe1d6e57a2019-09-30 11:55:34144 }
145 if (errorDecoding) {
Blink Reformat4c46d092018-04-07 15:32:37146 div.createChild('span', 'header-decode-error').textContent = Common.UIString('(unable to decode value)');
Tim van der Lippe1d6e57a2019-09-30 11:55:34147 } else {
Blink Reformat4c46d092018-04-07 15:32:37148 div.textContent = value;
Tim van der Lippe1d6e57a2019-09-30 11:55:34149 }
Blink Reformat4c46d092018-04-07 15:32:37150 return div;
151 }
152
153 _refreshURL() {
154 this._urlItem.title = this._formatHeader(Common.UIString('Request URL'), this._request.url());
155 }
156
157 _refreshQueryString() {
158 const queryString = this._request.queryString();
159 const queryParameters = this._request.queryParameters;
160 this._queryStringCategory.hidden = !queryParameters;
161 if (queryParameters) {
162 this._refreshParams(
163 Common.UIString('Query String Parameters'), queryParameters, queryString, this._queryStringCategory);
164 }
165 }
166
167 async _refreshFormData() {
168 this._formDataCategory.hidden = true;
169 this._requestPayloadCategory.hidden = true;
170
171 const formData = await this._request.requestFormData();
Tim van der Lippe1d6e57a2019-09-30 11:55:34172 if (!formData) {
Blink Reformat4c46d092018-04-07 15:32:37173 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34174 }
Blink Reformat4c46d092018-04-07 15:32:37175
176 const formParameters = await this._request.formParameters();
177 if (formParameters) {
178 this._formDataCategory.hidden = false;
179 this._refreshParams(Common.UIString('Form Data'), formParameters, formData, this._formDataCategory);
180 } else {
181 this._requestPayloadCategory.hidden = false;
182 try {
183 const json = JSON.parse(formData);
184 this._refreshRequestJSONPayload(json, formData);
185 } catch (e) {
186 this._populateTreeElementWithSourceText(this._requestPayloadCategory, formData);
187 }
188 }
189 }
190
191 /**
192 * @param {!UI.TreeElement} treeElement
193 * @param {?string} sourceText
194 */
195 _populateTreeElementWithSourceText(treeElement, sourceText) {
196 const max_len = 3000;
197 const text = (sourceText || '').trim();
198 const trim = text.length > max_len;
199
200 const sourceTextElement = createElementWithClass('span', 'header-value source-code');
201 sourceTextElement.textContent = trim ? text.substr(0, max_len) : text;
202
203 const sourceTreeElement = new UI.TreeElement(sourceTextElement);
Blink Reformat4c46d092018-04-07 15:32:37204 treeElement.removeChildren();
205 treeElement.appendChild(sourceTreeElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34206 if (!trim) {
Blink Reformat4c46d092018-04-07 15:32:37207 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34208 }
Blink Reformat4c46d092018-04-07 15:32:37209
210 const showMoreButton = createElementWithClass('button', 'request-headers-show-more-button');
211 showMoreButton.textContent = Common.UIString('Show more');
Amanda Baker89806492019-10-25 01:49:02212
213 function showMore() {
Blink Reformat4c46d092018-04-07 15:32:37214 showMoreButton.remove();
215 sourceTextElement.textContent = text;
Amanda Baker89806492019-10-25 01:49:02216 sourceTreeElement.listItemElement.removeEventListener('contextmenu', onContextMenuShowMore);
217 }
218 showMoreButton.addEventListener('click', showMore);
219
220 /**
221 * @param {!Event} event
222 */
223 function onContextMenuShowMore(event) {
224 const contextMenu = new UI.ContextMenu(event);
225 const section = contextMenu.newSection();
226 section.appendItem(ls`Show more`, showMore);
227 contextMenu.show();
228 }
229 sourceTreeElement.listItemElement.addEventListener('contextmenu', onContextMenuShowMore);
Blink Reformat4c46d092018-04-07 15:32:37230 sourceTextElement.appendChild(showMoreButton);
231 }
232
233 /**
234 * @param {string} title
235 * @param {?Array.<!SDK.NetworkRequest.NameValue>} params
236 * @param {?string} sourceText
237 * @param {!UI.TreeElement} paramsTreeElement
238 */
239 _refreshParams(title, params, sourceText, paramsTreeElement) {
240 paramsTreeElement.removeChildren();
241
242 paramsTreeElement.listItemElement.removeChildren();
Amanda Baker2e19a1b2019-10-25 00:41:02243 paramsTreeElement.listItemElement.createChild('div', 'selection fill');
Blink Reformat4c46d092018-04-07 15:32:37244 paramsTreeElement.listItemElement.createTextChild(title);
245
246 const headerCount = createElementWithClass('span', 'header-count');
Mathias Bynens7d8cd342019-09-17 13:32:10247 headerCount.textContent = Common.UIString('\xA0(%d)', params.length);
Blink Reformat4c46d092018-04-07 15:32:37248 paramsTreeElement.listItemElement.appendChild(headerCount);
249
Amanda Bakere2bb99d2019-10-25 01:28:43250 const shouldViewSource = paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol];
251 if (shouldViewSource) {
252 this._appendParamsSource(title, params, sourceText, paramsTreeElement);
253 } else {
254 this._appendParamsParsed(title, params, sourceText, paramsTreeElement);
255 }
256 }
257
258 /**
259 * @param {string} title
260 * @param {?Array.<!SDK.NetworkRequest.NameValue>} params
261 * @param {?string} sourceText
262 * @param {!UI.TreeElement} paramsTreeElement
263 */
264 _appendParamsSource(title, params, sourceText, paramsTreeElement) {
265 this._populateTreeElementWithSourceText(paramsTreeElement, sourceText);
266
267 const listItemElement = paramsTreeElement.listItemElement;
268
Blink Reformat4c46d092018-04-07 15:32:37269 /**
270 * @param {!Event} event
271 * @this {Network.RequestHeadersView}
272 */
Amanda Bakere2bb99d2019-10-25 01:28:43273 const viewParsed = function(event) {
274 listItemElement.removeEventListener('contextmenu', viewParsedContextMenu);
275
276 paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol] = false;
Blink Reformat4c46d092018-04-07 15:32:37277 this._refreshParams(title, params, sourceText, paramsTreeElement);
278 event.consume();
Amanda Bakere2bb99d2019-10-25 01:28:43279 };
Blink Reformat4c46d092018-04-07 15:32:37280
Amanda Bakere2bb99d2019-10-25 01:28:43281 /**
282 * @param {!Event} event
283 * @this {Network.RequestHeadersView}
284 */
285 const viewParsedContextMenu = function(event) {
286 if (!paramsTreeElement.expanded) {
287 return;
288 }
289 const contextMenu = new UI.ContextMenu(event);
290 contextMenu.newSection().appendItem(ls`View parsed`, viewParsed.bind(this, event));
291 contextMenu.show();
292 }.bind(this);
Blink Reformat4c46d092018-04-07 15:32:37293
Amanda Bakere2bb99d2019-10-25 01:28:43294 const viewParsedButton = this._createViewSourceToggle(/* viewSource */ true, viewParsed.bind(this));
295 listItemElement.appendChild(viewParsedButton);
Blink Reformat4c46d092018-04-07 15:32:37296
Amanda Bakere2bb99d2019-10-25 01:28:43297 listItemElement.addEventListener('contextmenu', viewParsedContextMenu);
298 }
Blink Reformat4c46d092018-04-07 15:32:37299
Amanda Bakere2bb99d2019-10-25 01:28:43300 /**
301 * @param {string} title
302 * @param {?Array.<!SDK.NetworkRequest.NameValue>} params
303 * @param {?string} sourceText
304 * @param {!UI.TreeElement} paramsTreeElement
305 */
306 _appendParamsParsed(title, params, sourceText, paramsTreeElement) {
Blink Reformat4c46d092018-04-07 15:32:37307 for (let i = 0; i < params.length; ++i) {
308 const paramNameValue = createDocumentFragment();
309 if (params[i].name !== '') {
310 const name = this._formatParameter(params[i].name + ': ', 'header-name', this._decodeRequestParameters);
311 const value = this._formatParameter(params[i].value, 'header-value source-code', this._decodeRequestParameters);
312 paramNameValue.appendChild(name);
313 paramNameValue.createChild('span', 'header-separator');
314 paramNameValue.appendChild(value);
315 } else {
316 paramNameValue.appendChild(
317 this._formatParameter(Common.UIString('(empty)'), 'empty-request-header', this._decodeRequestParameters));
318 }
319
320 const paramTreeElement = new UI.TreeElement(paramNameValue);
Blink Reformat4c46d092018-04-07 15:32:37321 paramsTreeElement.appendChild(paramTreeElement);
322 }
Amanda Bakere2bb99d2019-10-25 01:28:43323
324 const listItemElement = paramsTreeElement.listItemElement;
325
326 /**
327 * @param {!Event} event
328 * @this {Network.RequestHeadersView}
329 */
330 const viewSource = function(event) {
331 listItemElement.removeEventListener('contextmenu', viewSourceContextMenu);
332
333 paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol] = true;
334 this._refreshParams(title, params, sourceText, paramsTreeElement);
335 event.consume();
336 };
337
338 /**
339 * @param {!Event} event
340 * @this {Network.RequestHeadersView}
341 */
342 const toggleURLDecoding = function(event) {
343 listItemElement.removeEventListener('contextmenu', viewSourceContextMenu);
344 this._toggleURLDecoding(event);
345 };
346
347 /**
348 * @param {!Event} event
349 * @this {Network.RequestHeadersView}
350 */
351 const viewSourceContextMenu = function(event) {
352 if (!paramsTreeElement.expanded) {
353 return;
354 }
355 const contextMenu = new UI.ContextMenu(event);
356 const section = contextMenu.newSection();
357 section.appendItem(ls`View source`, viewSource.bind(this, event));
358 const viewURLEncodedText = this._decodeRequestParameters ? ls`View URL encoded` : ls`View decoded`;
359 section.appendItem(viewURLEncodedText, toggleURLDecoding.bind(this, event));
360 contextMenu.show();
361 }.bind(this);
362
363 const viewSourceButton = this._createViewSourceToggle(/* viewSource */ false, viewSource.bind(this));
364 listItemElement.appendChild(viewSourceButton);
365
366 const toggleTitle = this._decodeRequestParameters ? ls`view URL encoded` : ls`view decoded`;
367 const toggleButton = this._createToggleButton(toggleTitle);
368 toggleButton.addEventListener('click', toggleURLDecoding.bind(this), false);
369 listItemElement.appendChild(toggleButton);
370
371 listItemElement.addEventListener('contextmenu', viewSourceContextMenu);
Blink Reformat4c46d092018-04-07 15:32:37372 }
373
374 /**
375 * @param {*} parsedObject
376 * @param {string} sourceText
377 */
378 _refreshRequestJSONPayload(parsedObject, sourceText) {
379 const treeElement = this._requestPayloadCategory;
380 treeElement.removeChildren();
381
382 const listItem = this._requestPayloadCategory.listItemElement;
383 listItem.removeChildren();
Amanda Baker2e19a1b2019-10-25 00:41:02384 listItem.createChild('div', 'selection fill');
Blink Reformat4c46d092018-04-07 15:32:37385 listItem.createTextChild(this._requestPayloadCategory.title);
386
387 /**
388 * @param {!Event} event
389 * @this {Network.RequestHeadersView}
390 */
391 function toggleViewSource(event) {
392 treeElement[Network.RequestHeadersView._viewSourceSymbol] =
393 !treeElement[Network.RequestHeadersView._viewSourceSymbol];
394 this._refreshRequestJSONPayload(parsedObject, sourceText);
395 event.consume();
396 }
397
398 listItem.appendChild(this._createViewSourceToggle(
399 treeElement[Network.RequestHeadersView._viewSourceSymbol], toggleViewSource.bind(this)));
400 if (treeElement[Network.RequestHeadersView._viewSourceSymbol]) {
401 this._populateTreeElementWithSourceText(this._requestPayloadCategory, sourceText);
402 } else {
Amanda Bakerc3d15272019-10-25 00:56:39403 const object = /** @type {!SDK.LocalJSONObject} */ (SDK.RemoteObject.fromLocalObject(parsedObject));
404 const section = new ObjectUI.ObjectPropertiesSection.RootElement(object);
405 section.title = object.description;
Blink Reformat4c46d092018-04-07 15:32:37406 section.expand();
407 section.editable = false;
Amanda Bakerc3d15272019-10-25 00:56:39408 treeElement.childrenListElement.classList.add('source-code', 'object-properties-section');
409 treeElement.appendChild(section);
Blink Reformat4c46d092018-04-07 15:32:37410 }
411 }
412
413 /**
414 * @param {boolean} viewSource
415 * @param {function(!Event)} handler
416 * @return {!Element}
417 */
418 _createViewSourceToggle(viewSource, handler) {
419 const viewSourceToggleTitle = viewSource ? Common.UIString('view parsed') : Common.UIString('view source');
420 const viewSourceToggleButton = this._createToggleButton(viewSourceToggleTitle);
421 viewSourceToggleButton.addEventListener('click', handler, false);
422 return viewSourceToggleButton;
423 }
424
425 /**
426 * @param {!Event} event
427 */
428 _toggleURLDecoding(event) {
429 this._decodeRequestParameters = !this._decodeRequestParameters;
430 this._refreshQueryString();
431 this._refreshFormData();
432 event.consume();
433 }
434
435 _refreshRequestHeaders() {
436 const treeElement = this._requestHeadersCategory;
437 const headers = this._request.requestHeaders().slice();
438 headers.sort(function(a, b) {
439 return a.name.toLowerCase().compareTo(b.name.toLowerCase());
440 });
441 const headersText = this._request.requestHeadersText();
442
Tim van der Lippe1d6e57a2019-09-30 11:55:34443 if (this._showRequestHeadersText && headersText) {
Blink Reformat4c46d092018-04-07 15:32:37444 this._refreshHeadersText(Common.UIString('Request Headers'), headers.length, headersText, treeElement);
Tim van der Lippe1d6e57a2019-09-30 11:55:34445 } else {
Blink Reformat4c46d092018-04-07 15:32:37446 this._refreshHeaders(Common.UIString('Request Headers'), headers, treeElement, headersText === undefined);
Tim van der Lippe1d6e57a2019-09-30 11:55:34447 }
Blink Reformat4c46d092018-04-07 15:32:37448
449 if (headersText) {
450 const toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText);
451 toggleButton.addEventListener('click', this._toggleRequestHeadersText.bind(this), false);
452 treeElement.listItemElement.appendChild(toggleButton);
453 }
454
455 this._refreshFormData();
456 }
457
458 _refreshResponseHeaders() {
459 const treeElement = this._responseHeadersCategory;
460 const headers = this._request.sortedResponseHeaders.slice();
461 const headersText = this._request.responseHeadersText;
462
Joey Arhar7199a942019-09-10 22:37:39463 if (this._showResponseHeadersText) {
Blink Reformat4c46d092018-04-07 15:32:37464 this._refreshHeadersText(Common.UIString('Response Headers'), headers.length, headersText, treeElement);
Joey Arhar7199a942019-09-10 22:37:39465 } else {
466 this._refreshHeaders(
467 Common.UIString('Response Headers'), headers, treeElement, /* provisional */ false,
468 this._request.blockedResponseCookies());
469 }
Blink Reformat4c46d092018-04-07 15:32:37470
471 if (headersText) {
472 const toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText);
473 toggleButton.addEventListener('click', this._toggleResponseHeadersText.bind(this), false);
474 treeElement.listItemElement.appendChild(toggleButton);
475 }
476 }
477
478 _refreshHTTPInformation() {
479 const requestMethodElement = this._requestMethodItem;
480 requestMethodElement.hidden = !this._request.statusCode;
481 const statusCodeElement = this._statusCodeItem;
482 statusCodeElement.hidden = !this._request.statusCode;
483
484 if (this._request.statusCode) {
485 const statusCodeFragment = createDocumentFragment();
Tsuyoshi Horo41dcffd2019-05-24 03:59:05486 statusCodeFragment.createChild('div', 'header-name').textContent = ls`Status Code` +
487 ': ';
Blink Reformat4c46d092018-04-07 15:32:37488 statusCodeFragment.createChild('span', 'header-separator');
489
Joel Einbinder7fbe24c2019-01-24 05:19:01490 const statusCodeImage = statusCodeFragment.createChild('span', 'resource-status-image', 'dt-icon-label');
Blink Reformat4c46d092018-04-07 15:32:37491 statusCodeImage.title = this._request.statusCode + ' ' + this._request.statusText;
492
Tim van der Lippe1d6e57a2019-09-30 11:55:34493 if (this._request.statusCode < 300 || this._request.statusCode === 304) {
Blink Reformat4c46d092018-04-07 15:32:37494 statusCodeImage.type = 'smallicon-green-ball';
Tim van der Lippe1d6e57a2019-09-30 11:55:34495 } else if (this._request.statusCode < 400) {
Blink Reformat4c46d092018-04-07 15:32:37496 statusCodeImage.type = 'smallicon-orange-ball';
Tim van der Lippe1d6e57a2019-09-30 11:55:34497 } else {
Blink Reformat4c46d092018-04-07 15:32:37498 statusCodeImage.type = 'smallicon-red-ball';
Tim van der Lippe1d6e57a2019-09-30 11:55:34499 }
Blink Reformat4c46d092018-04-07 15:32:37500
Tsuyoshi Horo41dcffd2019-05-24 03:59:05501 requestMethodElement.title = this._formatHeader(ls`Request Method`, this._request.requestMethod);
Blink Reformat4c46d092018-04-07 15:32:37502
503 const statusTextElement = statusCodeFragment.createChild('div', 'header-value source-code');
504 let statusText = this._request.statusCode + ' ' + this._request.statusText;
Ben Kelly0375f502018-09-11 17:05:50505 if (this._request.cachedInMemory()) {
Tsuyoshi Horo41dcffd2019-05-24 03:59:05506 statusText += ' ' + ls`(from memory cache)`;
Ben Kelly0375f502018-09-11 17:05:50507 statusTextElement.classList.add('status-from-cache');
508 } else if (this._request.fetchedViaServiceWorker) {
Tsuyoshi Horo41dcffd2019-05-24 03:59:05509 statusText += ' ' + ls`(from ServiceWorker)`;
Blink Reformat4c46d092018-04-07 15:32:37510 statusTextElement.classList.add('status-from-cache');
Tsuyoshi Horo8f6a2b12018-10-01 22:24:03511 } else if (
512 this._request.redirectSource() && this._request.redirectSource().signedExchangeInfo() &&
513 !this._request.redirectSource().signedExchangeInfo().errors) {
Tsuyoshi Horo41dcffd2019-05-24 03:59:05514 statusText += ' ' + ls`(from signed-exchange)`;
515 statusTextElement.classList.add('status-from-cache');
516 } else if (this._request.fromPrefetchCache()) {
517 statusText += ' ' + ls`(from prefetch cache)`;
Tsuyoshi Horo02266c32018-05-21 17:01:18518 statusTextElement.classList.add('status-from-cache');
Blink Reformat4c46d092018-04-07 15:32:37519 } else if (this._request.cached()) {
Tsuyoshi Horo41dcffd2019-05-24 03:59:05520 statusText += ' ' + ls`(from disk cache)`;
Blink Reformat4c46d092018-04-07 15:32:37521 statusTextElement.classList.add('status-from-cache');
522 }
523 statusTextElement.textContent = statusText;
524
525 statusCodeElement.title = statusCodeFragment;
526 }
527 }
528
529 /**
530 * @param {string} title
531 * @param {!UI.TreeElement} headersTreeElement
532 * @param {number} headersLength
533 */
534 _refreshHeadersTitle(title, headersTreeElement, headersLength) {
535 headersTreeElement.listItemElement.removeChildren();
Amanda Baker2e19a1b2019-10-25 00:41:02536 headersTreeElement.listItemElement.createChild('div', 'selection fill');
Blink Reformat4c46d092018-04-07 15:32:37537 headersTreeElement.listItemElement.createTextChild(title);
538
Mathias Bynens7d8cd342019-09-17 13:32:10539 const headerCount = Common.UIString('\xA0(%d)', headersLength);
Blink Reformat4c46d092018-04-07 15:32:37540 headersTreeElement.listItemElement.createChild('span', 'header-count').textContent = headerCount;
541 }
542
543 /**
544 * @param {string} title
545 * @param {!Array.<!SDK.NetworkRequest.NameValue>} headers
546 * @param {!UI.TreeElement} headersTreeElement
547 * @param {boolean=} provisionalHeaders
Joey Arhar7199a942019-09-10 22:37:39548 * @param {!Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>=} blockedResponseCookies
Blink Reformat4c46d092018-04-07 15:32:37549 */
Joey Arhar7199a942019-09-10 22:37:39550 _refreshHeaders(title, headers, headersTreeElement, provisionalHeaders, blockedResponseCookies) {
Blink Reformat4c46d092018-04-07 15:32:37551 headersTreeElement.removeChildren();
552
553 const length = headers.length;
554 this._refreshHeadersTitle(title, headersTreeElement, length);
555
556 if (provisionalHeaders) {
557 const cautionText = Common.UIString('Provisional headers are shown');
558 const cautionFragment = createDocumentFragment();
Joel Einbinder7fbe24c2019-01-24 05:19:01559 cautionFragment.createChild('span', '', 'dt-icon-label').type = 'smallicon-warning';
Blink Reformat4c46d092018-04-07 15:32:37560 cautionFragment.createChild('div', 'caution').textContent = cautionText;
561 const cautionTreeElement = new UI.TreeElement(cautionFragment);
Blink Reformat4c46d092018-04-07 15:32:37562 headersTreeElement.appendChild(cautionTreeElement);
563 }
564
Joey Arhar41a5fad2019-09-13 22:18:45565 /** @type {!Map<string, !Array<!Protocol.Network.SetCookieBlockedReason>>} */
566 const blockedCookieLineToReasons = new Map();
Joey Arhar7199a942019-09-10 22:37:39567 if (blockedResponseCookies) {
568 blockedResponseCookies.forEach(blockedCookie => {
Joey Arhar41a5fad2019-09-13 22:18:45569 blockedCookieLineToReasons.set(blockedCookie.cookieLine, blockedCookie.blockedReasons);
Joey Arhar7199a942019-09-10 22:37:39570 });
571 }
572
Blink Reformat4c46d092018-04-07 15:32:37573 headersTreeElement.hidden = !length && !provisionalHeaders;
574 for (let i = 0; i < length; ++i) {
575 const headerTreeElement = new UI.TreeElement(this._formatHeader(headers[i].name, headers[i].value));
Blink Reformat4c46d092018-04-07 15:32:37576 headerTreeElement[Network.RequestHeadersView._headerNameSymbol] = headers[i].name;
Joey Arhar7199a942019-09-10 22:37:39577
578 if (headers[i].name.toLowerCase() === 'set-cookie') {
Joey Arhar41a5fad2019-09-13 22:18:45579 const matchingBlockedReasons = blockedCookieLineToReasons.get(headers[i].value);
580 if (matchingBlockedReasons) {
Joey Arhar7199a942019-09-10 22:37:39581 const icon = UI.Icon.create('smallicon-warning', '');
582 headerTreeElement.listItemElement.appendChild(icon);
Joey Arhar41a5fad2019-09-13 22:18:45583
584 let titleText = '';
585 for (const blockedReason of matchingBlockedReasons) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34586 if (titleText) {
Joey Arhar41a5fad2019-09-13 22:18:45587 titleText += '\n';
Tim van der Lippe1d6e57a2019-09-30 11:55:34588 }
Joey Arhar41a5fad2019-09-13 22:18:45589 titleText += SDK.NetworkRequest.setCookieBlockedReasonToUiString(blockedReason);
590 }
591 icon.title = titleText;
Joey Arhar7199a942019-09-10 22:37:39592 }
593 }
594
595 headersTreeElement.appendChild(headerTreeElement);
Blink Reformat4c46d092018-04-07 15:32:37596 }
597 }
598
599 /**
600 * @param {string} title
601 * @param {number} count
602 * @param {string} headersText
603 * @param {!UI.TreeElement} headersTreeElement
604 */
605 _refreshHeadersText(title, count, headersText, headersTreeElement) {
606 this._populateTreeElementWithSourceText(headersTreeElement, headersText);
607 this._refreshHeadersTitle(title, headersTreeElement, count);
608 }
609
610 _refreshRemoteAddress() {
611 const remoteAddress = this._request.remoteAddress();
612 const treeElement = this._remoteAddressItem;
613 treeElement.hidden = !remoteAddress;
Tim van der Lippe1d6e57a2019-09-30 11:55:34614 if (remoteAddress) {
Blink Reformat4c46d092018-04-07 15:32:37615 treeElement.title = this._formatHeader(Common.UIString('Remote Address'), remoteAddress);
Tim van der Lippe1d6e57a2019-09-30 11:55:34616 }
Blink Reformat4c46d092018-04-07 15:32:37617 }
618
619 _refreshReferrerPolicy() {
620 const referrerPolicy = this._request.referrerPolicy();
621 const treeElement = this._referrerPolicyItem;
622 treeElement.hidden = !referrerPolicy;
Tim van der Lippe1d6e57a2019-09-30 11:55:34623 if (referrerPolicy) {
Blink Reformat4c46d092018-04-07 15:32:37624 treeElement.title = this._formatHeader(Common.UIString('Referrer Policy'), referrerPolicy);
Tim van der Lippe1d6e57a2019-09-30 11:55:34625 }
Blink Reformat4c46d092018-04-07 15:32:37626 }
627
628 /**
629 * @param {!Event} event
630 */
631 _toggleRequestHeadersText(event) {
632 this._showRequestHeadersText = !this._showRequestHeadersText;
633 this._refreshRequestHeaders();
634 event.consume();
635 }
636
637 /**
638 * @param {!Event} event
639 */
640 _toggleResponseHeadersText(event) {
641 this._showResponseHeadersText = !this._showResponseHeadersText;
642 this._refreshResponseHeaders();
643 event.consume();
644 }
645
646 /**
647 * @param {string} title
648 * @return {!Element}
649 */
650 _createToggleButton(title) {
651 const button = createElementWithClass('span', 'header-toggle');
652 button.textContent = title;
653 return button;
654 }
655
656 /**
657 * @param {boolean} isHeadersTextShown
658 * @return {!Element}
659 */
660 _createHeadersToggleButton(isHeadersTextShown) {
661 const toggleTitle = isHeadersTextShown ? Common.UIString('view parsed') : Common.UIString('view source');
662 return this._createToggleButton(toggleTitle);
663 }
664
665 _clearHighlight() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34666 if (this._highlightedElement) {
Blink Reformat4c46d092018-04-07 15:32:37667 this._highlightedElement.listItemElement.classList.remove('header-highlight');
Tim van der Lippe1d6e57a2019-09-30 11:55:34668 }
Blink Reformat4c46d092018-04-07 15:32:37669 this._highlightedElement = null;
670 }
671
672
673 /**
674 * @param {?UI.TreeElement} category
675 * @param {string} name
676 */
677 _revealAndHighlight(category, name) {
678 this._clearHighlight();
679 for (const element of category.children()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34680 if (element[Network.RequestHeadersView._headerNameSymbol] !== name) {
Blink Reformat4c46d092018-04-07 15:32:37681 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34682 }
Blink Reformat4c46d092018-04-07 15:32:37683 this._highlightedElement = element;
684 element.reveal();
685 element.listItemElement.classList.add('header-highlight');
686 return;
687 }
688 }
689
690 /**
691 * @param {string} header
692 */
693 revealRequestHeader(header) {
694 this._revealAndHighlight(this._requestHeadersCategory, header);
695 }
696
697 /**
698 * @param {string} header
699 */
700 revealResponseHeader(header) {
701 this._revealAndHighlight(this._responseHeadersCategory, header);
702 }
703};
704
705Network.RequestHeadersView._headerNameSymbol = Symbol('HeaderName');
706Network.RequestHeadersView._viewSourceSymbol = Symbol('ViewSource');
707
708/**
709 * @unrestricted
710 */
711Network.RequestHeadersView.Category = class extends UI.TreeElement {
712 /**
713 * @param {!UI.TreeOutline} root
714 * @param {string} name
715 * @param {string=} title
716 */
717 constructor(root, name, title) {
718 super(title || '', true);
Blink Reformat4c46d092018-04-07 15:32:37719 this.toggleOnClick = true;
720 this.hidden = true;
721 this._expandedSetting = Common.settings.createSetting('request-info-' + name + '-category-expanded', true);
722 this.expanded = this._expandedSetting.get();
723 root.appendChild(this);
724 }
725
726 /**
727 * @return {!UI.TreeElement}
728 */
729 createLeaf() {
730 const leaf = new UI.TreeElement();
Blink Reformat4c46d092018-04-07 15:32:37731 this.appendChild(leaf);
732 return leaf;
733 }
734
735 /**
736 * @override
737 */
738 onexpand() {
739 this._expandedSetting.set(true);
740 }
741
742 /**
743 * @override
744 */
745 oncollapse() {
746 this._expandedSetting.set(false);
747 }
748};