Commit 4ac04d63 authored by Tsuyoshi Horo's avatar Tsuyoshi Horo Committed by Commit Bot

Brush up DevTools SignedExchange support

This incorporats with dgozman's comments in crrev.com/c/1004890
- Change "from SignedExchange" to "from signed-exchange" in NetworkRequestNode.
- Show the signed exchagne url as the initiator of certificate request.
- Show "from signed-exchange" in the headers tab of the inner request.
- Add "View request" link in the preview tab of signed exchange to show the inner request.
- Add "Learn more" link in the preview tab of signed exchange.

Bug: 830505
Change-Id: Ica7ae52e563efb283c600c812be196951a12a336
Reviewed-on: https://chromium-review.googlesource.com/1065558
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarKunihiko Sakamoto <ksakamoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#560287}
parent 07e3d0d9
......@@ -1588,12 +1588,17 @@ void NetworkHandler::NavigationRequestWillBeSent(
void NetworkHandler::RequestSent(const std::string& request_id,
const std::string& loader_id,
const network::ResourceRequest& request,
const char* initiator_type) {
const char* initiator_type,
const base::Optional<GURL>& initiator_url) {
if (!enabled_)
return;
std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();)
headers_dict->setString(it.name(), it.value());
std::unique_ptr<Network::Initiator> initiator =
Network::Initiator::Create().SetType(initiator_type).Build();
if (initiator_url)
initiator->SetUrl(initiator_url->spec());
frontend_->RequestWillBeSent(
request_id, loader_id, StripFragment(request.url),
Network::Request::Create()
......@@ -1605,8 +1610,7 @@ void NetworkHandler::RequestSent(const std::string& request_id,
.Build(),
base::TimeTicks::Now().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond),
base::Time::Now().ToDoubleT(),
Network::Initiator::Create().SetType(initiator_type).Build(),
base::Time::Now().ToDoubleT(), std::move(initiator),
std::unique_ptr<Network::Response>(),
std::string(Page::ResourceTypeEnum::Other),
Maybe<std::string>() /* frame_id */, request.has_user_gesture);
......
......@@ -149,7 +149,8 @@ class NetworkHandler : public DevToolsDomainHandler,
void RequestSent(const std::string& request_id,
const std::string& loader_id,
const network::ResourceRequest& request,
const char* initiator_type);
const char* initiator_type,
const base::Optional<GURL>& initiator_url);
void ResponseReceived(const std::string& request_id,
const std::string& loader_id,
const GURL& url,
......
......@@ -244,10 +244,12 @@ void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
FrameTreeNode* frame_tree_node,
const base::UnguessableToken& request_id,
const base::UnguessableToken& loader_id,
const network::ResourceRequest& request) {
const network::ResourceRequest& request,
const GURL& signed_exchange_url) {
DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
request_id.ToString(), loader_id.ToString(), request,
protocol::Network::Initiator::TypeEnum::Other);
protocol::Network::Initiator::TypeEnum::SignedExchange,
signed_exchange_url);
}
// static
......
......@@ -108,7 +108,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
FrameTreeNode* frame_tree_node,
const base::UnguessableToken& request_id,
const base::UnguessableToken& loader_id,
const network::ResourceRequest& request);
const network::ResourceRequest& request,
const GURL& signed_exchange_url);
static void OnSignedExchangeCertificateResponseReceived(
FrameTreeNode* frame_tree_node,
const base::UnguessableToken& request_id,
......
......@@ -188,7 +188,8 @@ void ServiceWorkerDevToolsManager::NavigationPreloadRequestSent(
for (auto* network :
protocol::NetworkHandler::ForAgentHost(it->second.get())) {
network->RequestSent(request_id, std::string(), request,
protocol::Network::Initiator::TypeEnum::Preload);
protocol::Network::Initiator::TypeEnum::Preload,
base::nullopt /* initiator_url */);
}
}
......
......@@ -32,13 +32,14 @@ void CertificateRequestSentOnUI(
base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
const base::UnguessableToken& request_id,
const base::UnguessableToken& loader_id,
const network::ResourceRequest& request) {
const network::ResourceRequest& request,
const GURL& signed_exchange_url) {
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
if (!frame_tree_node)
return;
RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
frame_tree_node, request_id, loader_id, request);
frame_tree_node, request_id, loader_id, request, signed_exchange_url);
}
void CertificateResponseReceivedOnUI(
......@@ -125,7 +126,7 @@ void SignedExchangeDevToolsProxy::CertificateRequestSent(
base::BindOnce(
&CertificateRequestSentOnUI, frame_tree_node_id_getter_, request_id,
devtools_navigation_token_ ? *devtools_navigation_token_ : request_id,
request));
request, outer_request_url_));
}
void SignedExchangeDevToolsProxy::CertificateResponseReceived(
......
......@@ -3542,10 +3542,11 @@ domain Network
parser
script
preload
SignedExchange
other
# Initiator JavaScript stack trace, set for Script only.
optional Runtime.StackTrace stack
# Initiator URL, set for Parser type or for Script type (when script is importing module).
# Initiator URL, set for Parser type or for Script type (when script is importing module) or for SignedExchange type.
optional string url
# Initiator line number, set for Parser type or for Script type (when script is importing
# module) (0-based).
......
......@@ -209,6 +209,9 @@ BrowserSDK.NetworkLog = class extends Common.Object {
initiatorStack = initiator.stack || null;
} else if (initiator.type === Protocol.Network.InitiatorType.Preload) {
type = SDK.NetworkRequest.InitiatorType.Preload;
} else if (initiator.type === Protocol.Network.InitiatorType.SignedExchange) {
type = SDK.NetworkRequest.InitiatorType.SignedExchange;
url = initiator.url;
}
}
......
......@@ -932,6 +932,11 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
cell.appendChild(createTextNode(Common.UIString('Preload')));
break;
case SDK.NetworkRequest.InitiatorType.SignedExchange:
cell.appendChild(Components.Linkifier.linkifyURL(initiator.url));
this._appendSubtitle(cell, Common.UIString('signed-exchange'));
break;
default:
cell.title = Common.UIString('Other');
cell.classList.add('network-dim-cell');
......@@ -947,7 +952,7 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
this._setTextAndTitle(cell, Common.UIString('(from ServiceWorker)'));
cell.classList.add('network-dim-cell');
} else if (this._request.redirectSource() && this._request.redirectSource().signedExchangeInfo()) {
this._setTextAndTitle(cell, Common.UIString('(from SignedExchange)'));
this._setTextAndTitle(cell, Common.UIString('(from signed-exchange)'));
cell.classList.add('network-dim-cell');
} else if (this._request.cached()) {
if (this._request.cachedInMemory())
......
......@@ -396,6 +396,9 @@ Network.RequestHeadersView = class extends UI.VBox {
if (this._request.fetchedViaServiceWorker) {
statusText += ' ' + Common.UIString('(from ServiceWorker)');
statusTextElement.classList.add('status-from-cache');
} else if (this._request.redirectSource() && this._request.redirectSource().signedExchangeInfo()) {
statusText += ' ' + Common.UIString('(from signed-exchange)');
statusTextElement.classList.add('status-from-cache');
} else if (this._request.cached()) {
if (this._request.cachedInMemory())
statusText += ' ' + Common.UIString('(from memory cache)');
......
......@@ -79,9 +79,8 @@ Network.RequestPreviewView = class extends Network.RequestResponseView {
* @return {!Promise<!UI.Widget>}
*/
async createPreview() {
const signedExchangeInfo = this.request.signedExchangeInfo();
if (signedExchangeInfo)
return new Network.SignedExchangeInfoView(signedExchangeInfo);
if (this.request.signedExchangeInfo())
return new Network.SignedExchangeInfoView(this.request);
const htmlErrorPreview = await this._htmlPreview();
if (htmlErrorPreview)
......
......@@ -4,10 +4,13 @@
Network.SignedExchangeInfoView = class extends UI.VBox {
/**
* @param {!Protocol.Network.SignedExchangeInfo} signedExchangeInfo
* @param {!SDK.NetworkRequest} request
*/
constructor(signedExchangeInfo) {
constructor(request) {
super();
const signedExchangeInfo = request.signedExchangeInfo();
console.assert(signedExchangeInfo);
this.registerRequiredCSS('network/signedExchangeInfoView.css');
this.element.classList.add('signed-exchange-info-view');
......@@ -30,8 +33,21 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
}
if (signedExchangeInfo.header) {
const header = signedExchangeInfo.header;
const headerCategory = new Network.SignedExchangeInfoView.Category(root, Common.UIString('Signed HTTP exchange'));
headerCategory.createLeaf(this._formatHeader(Common.UIString('Request URL'), header.requestUrl));
const titleElement = createDocumentFragment();
titleElement.createChild('div', 'header-name').textContent = Common.UIString('Signed HTTP exchange');
const learnMoreNode =
UI.XLink.create('https://github.com/WICG/webpackage', Common.UIString('Learn\xa0more'), 'header-toggle');
titleElement.appendChild(learnMoreNode);
const headerCategory = new Network.SignedExchangeInfoView.Category(root, titleElement);
const redirectDestination = request.redirectDestination();
const requestURLElement = this._formatHeader(Common.UIString('Request URL'), header.requestUrl);
if (redirectDestination) {
const viewRequestLink = Components.Linkifier.linkifyRevealable(redirectDestination, 'View request');
viewRequestLink.classList.add('header-toggle');
requestURLElement.appendChild(viewRequestLink);
}
headerCategory.createLeaf(requestURLElement);
headerCategory.createLeaf(this._formatHeader(Common.UIString('Request method'), header.requestMethod));
headerCategory.createLeaf(this._formatHeader(Common.UIString('Response code'), header.responseCode + ''));
......@@ -90,7 +106,7 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
Network.SignedExchangeInfoView.Category = class extends UI.TreeElement {
/**
* @param {!UI.TreeOutline} root
* @param {string} title
* @param {(string|!Node)=} title
*/
constructor(root, title) {
super(title, true);
......
......@@ -59,6 +59,18 @@
margin-top: 1px;
}
.tree-outline .header-toggle {
display: inline;
margin-left: 30px;
font-weight: normal;
color: rgb(45%, 45%, 45%);
}
.tree-outline .header-toggle:hover {
color: rgb(20%, 20%, 45%);
cursor: pointer;
}
.tree-outline .error-log {
color: red;
display: inline-block;
......
......@@ -786,6 +786,7 @@ SDK.NetworkDispatcher = class {
requestId, originalNetworkRequest.frameId, originalNetworkRequest.loaderId, redirectURL,
originalNetworkRequest.documentURL, originalNetworkRequest.initiator());
newNetworkRequest.setRedirectSource(originalNetworkRequest);
originalNetworkRequest.setRedirectDestination(newNetworkRequest);
return newNetworkRequest;
}
......
......@@ -53,6 +53,8 @@ SDK.NetworkRequest = class extends Common.Object {
this._initiator = initiator;
/** @type {?SDK.NetworkRequest} */
this._redirectSource = null;
/** @type {?SDK.NetworkRequest} */
this._redirectDestination = null;
this._issueTime = -1;
this._startTime = -1;
this._endTime = -1;
......@@ -622,6 +624,20 @@ SDK.NetworkRequest = class extends Common.Object {
this._redirectSource = originatingRequest;
}
/**
* @return {?SDK.NetworkRequest}
*/
redirectDestination() {
return this._redirectDestination;
}
/**
* @param {?SDK.NetworkRequest} redirectDestination
*/
setRedirectDestination(redirectDestination) {
this._redirectDestination = redirectDestination;
}
/**
* @return {!Array.<!SDK.NetworkRequest.NameValue>}
*/
......@@ -1167,7 +1183,8 @@ SDK.NetworkRequest.InitiatorType = {
Parser: 'parser',
Redirect: 'redirect',
Script: 'script',
Preload: 'preload'
Preload: 'preload',
SignedExchange: 'signedExchange'
};
/** @typedef {!{name: string, value: string}} */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment