Files
react-native-devtools-frontend/front_end/network/NetworkItemView.js
T
Simon Zünd 7ba7696cf1 Prepare Trust Token report view for result section
This CL adds the trust token operation result to NetworkRequest and
forwards the data to the Trust Token tab in the Network panel.
As the operation result can arrive after the report was initially
rendered, this CL adds a new event to trigger a re-render as
necessary.

The CL doesn't yet add the rendering for the result itself, just
prepares the component to have the necessary data.

R=jacktfranklin@chromium.org

Bug: chromium:1126824
Change-Id: I9c6c080de9268219cd8b4b12804a7ca7c4de39a8
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2567783
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
2020-12-02 12:48:49 +00:00

209 lines
7.8 KiB
JavaScript

/*
* Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import * as Common from '../common/common.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';
import {EventSourceMessagesView} from './EventSourceMessagesView.js';
import {NetworkTimeCalculator} from './NetworkTimeCalculator.js'; // eslint-disable-line no-unused-vars
import {RequestCookiesView} from './RequestCookiesView.js';
import {RequestHeadersView} from './RequestHeadersView.js';
import {RequestInitiatorView} from './RequestInitiatorView.js';
import {RequestPreviewView} from './RequestPreviewView.js';
import {RequestResponseView} from './RequestResponseView.js';
import {RequestTimingView} from './RequestTimingView.js';
import {RequestTrustTokensView} from './RequestTrustTokensView.js';
import {ResourceWebSocketFrameView} from './ResourceWebSocketFrameView.js';
export class NetworkItemView extends UI.TabbedPane.TabbedPane {
/**
* @param {!SDK.NetworkRequest.NetworkRequest} request
* @param {!NetworkTimeCalculator} calculator
* @param {!Tabs=} initialTab If specified, will open `initalTab` when the view shows. Otherwise the tab that
* was last shown is opened. Note that specifying `initalTab` won't override the
* setting that stores the 'last opened tab' (similar to how revealers work).
*/
constructor(request, calculator, initialTab) {
super();
this._request = request;
this.element.classList.add('network-item-view');
this._resourceViewTabSetting = Common.Settings.Settings.instance().createSetting('resourceViewTab', 'preview');
this._headersView = new RequestHeadersView(request);
this.appendTab(
Tabs.Headers, Common.UIString.UIString('Headers'), this._headersView,
Common.UIString.UIString('Headers and request body'));
this.addEventListener(UI.TabbedPane.Events.TabSelected, this._tabSelected, this);
if (request.resourceType() === Common.ResourceType.resourceTypes.WebSocket) {
const frameView = new ResourceWebSocketFrameView(request);
this.appendTab(
Tabs.WsFrames, Common.UIString.UIString('Messages'), frameView,
Common.UIString.UIString('WebSocket messages'));
} else if (request.mimeType === 'text/event-stream') {
this.appendTab(Tabs.EventSource, Common.UIString.UIString('EventStream'), new EventSourceMessagesView(request));
} else {
this._responseView = new RequestResponseView(request);
const previewView = new RequestPreviewView(request);
this.appendTab(
Tabs.Preview, Common.UIString.UIString('Preview'), previewView, Common.UIString.UIString('Response preview'));
const signedExchangeInfo = request.signedExchangeInfo();
if (signedExchangeInfo && signedExchangeInfo.errors && signedExchangeInfo.errors.length) {
const icon = UI.Icon.Icon.create('smallicon-error');
UI.Tooltip.Tooltip.install(icon, Common.UIString.UIString('SignedExchange error'));
this.setTabIcon(Tabs.Preview, icon);
}
this.appendTab(
Tabs.Response, Common.UIString.UIString('Response'), this._responseView,
Common.UIString.UIString('Raw response data'));
}
this.appendTab(Tabs.Initiator, ls`Initiator`, new RequestInitiatorView(request), ls`Request initiator call stack`);
this.appendTab(
Tabs.Timing, Common.UIString.UIString('Timing'), new RequestTimingView(request, calculator),
Common.UIString.UIString('Request and response timeline'));
if (request.trustTokenParams()) {
this.appendTab(
Tabs.TrustTokens, ls`Trust Tokens`, new RequestTrustTokensView(request), ls`Trust Token operation details`);
}
/** @type {?RequestCookiesView} */
this._cookiesView = null;
/** @type {!Tabs} */
this._initialTab = initialTab || this._resourceViewTabSetting.get();
}
/**
* @override
*/
wasShown() {
super.wasShown();
this._request.addEventListener(
SDK.NetworkRequest.Events.RequestHeadersChanged, this._maybeAppendCookiesPanel, this);
this._request.addEventListener(
SDK.NetworkRequest.Events.ResponseHeadersChanged, this._maybeAppendCookiesPanel, this);
this._maybeAppendCookiesPanel();
this._selectTab(this._initialTab);
}
/**
* @override
*/
willHide() {
this._request.removeEventListener(
SDK.NetworkRequest.Events.RequestHeadersChanged, this._maybeAppendCookiesPanel, this);
this._request.removeEventListener(
SDK.NetworkRequest.Events.ResponseHeadersChanged, this._maybeAppendCookiesPanel, this);
}
_maybeAppendCookiesPanel() {
const cookiesPresent = this._request.hasRequestCookies() || this._request.responseCookies.length > 0;
console.assert(cookiesPresent || !this._cookiesView, 'Cookies were introduced in headers and then removed!');
if (cookiesPresent && !this._cookiesView) {
this._cookiesView = new RequestCookiesView(this._request);
this.appendTab(
Tabs.Cookies, Common.UIString.UIString('Cookies'), this._cookiesView,
Common.UIString.UIString('Request and response cookies'));
}
}
/**
* @param {string} tabId
*/
_selectTab(tabId) {
if (!this.selectTab(tabId)) {
this.selectTab('headers');
}
}
/** @param {!{data: *}} event */
_tabSelected(event) {
if (!event.data.isUserGesture) {
return;
}
this._resourceViewTabSetting.set(event.data.tabId);
}
/**
* @return {!SDK.NetworkRequest.NetworkRequest}
*/
request() {
return this._request;
}
/**
* @param {number=} line
* @return {!Promise<void>}
*/
async revealResponseBody(line) {
this._selectTab(Tabs.Response);
if (this._responseView && typeof line === 'number') {
await this._responseView.revealLine(/** @type {number} */ (line));
}
}
/**
* @param {string} header
*/
revealRequestHeader(header) {
this._selectTab(Tabs.Headers);
this._headersView.revealRequestHeader(header);
}
/**
* @param {string} header
*/
revealResponseHeader(header) {
this._selectTab(Tabs.Headers);
this._headersView.revealResponseHeader(header);
}
}
/**
* @enum {string}
*/
export const Tabs = {
Cookies: 'cookies',
EventSource: 'eventSource',
Headers: 'headers',
Initiator: 'initiator',
Preview: 'preview',
Response: 'response',
Timing: 'timing',
TrustTokens: 'trustTokens',
WsFrames: 'webSocketFrames'
};