Skip to content

Commit 7dc9931

Browse files
quasi-modDevtools-frontend LUCI CQ
authored andcommitted
[ServiceWorker] Add SW static routing API source types to devtools
This CL adds `actualSourceType` and `matchedSourceType` of SW static routing API to the devtools network panel under `Router Evaluation` field. This is only showed when the ServiceWorker static routing API is used. Bug: 41496865 Bug: 374656289 Change-Id: I867c712d2c2ad6c981b3cc87ebdf04850416494a Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6000197 Reviewed-by: Shunya Shishido <[email protected]> Reviewed-by: Yoshisato Yanagisawa <[email protected]> Commit-Queue: Alex Rudenko <[email protected]> Reviewed-by: Alex Rudenko <[email protected]>
1 parent d25ae31 commit 7dc9931

File tree

3 files changed

+133
-2
lines changed

3 files changed

+133
-2
lines changed

front_end/panels/network/RequestTimingView.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import type * as Platform from '../../core/platform/platform.js';
66
import * as SDK from '../../core/sdk/sdk.js';
77
import * as Protocol from '../../generated/protocol.js';
8+
import {getCleanTextContentFromElements, renderElementIntoDOM} from '../../testing/DOMHelpers.js';
9+
import {describeWithLocale} from '../../testing/EnvironmentHelpers.js';
810

11+
import * as Network from './NetworkTimeCalculator.js';
912
import * as RequestTimingView from './RequestTimingView.js';
1013

1114
function createNetworkRequest(
@@ -53,7 +56,7 @@ function createNetworkRequest(
5356
return request;
5457
}
5558

56-
describe('ResourceTimingView', () => {
59+
describeWithLocale('ResourceTimingView', () => {
5760
it('RequestTimeRanges has router evaluation field with SW router source as network', async () => {
5861
const request = createNetworkRequest(
5962
Protocol.Network.ServiceWorkerRouterSource.Network, Protocol.Network.ServiceWorkerRouterSource.Network);
@@ -133,4 +136,35 @@ describe('ResourceTimingView', () => {
133136
assert.strictEqual(cacheLookup?.start, timingInfo.requestTime + cacheLookupStart / 1000);
134137
assert.strictEqual(cacheLookup?.end, timingInfo.requestTime + timingInfo.sendStart / 1000);
135138
});
139+
140+
it('Timing table has router evaluation field with detail tabs', async () => {
141+
const request = createNetworkRequest(
142+
Protocol.Network.ServiceWorkerRouterSource.Network, Protocol.Network.ServiceWorkerRouterSource.Network);
143+
144+
const component = new RequestTimingView.RequestTimingView(request, new Network.NetworkTimeCalculator(true));
145+
const div = document.createElement('div');
146+
renderElementIntoDOM(div);
147+
component.markAsRoot();
148+
component.show(div);
149+
150+
// Test if we correctly set details element
151+
const routerEvaluationDetailsElement = document.querySelector('.router-evaluation-timing-bar-details');
152+
assert.isNotNull(routerEvaluationDetailsElement, 'router evaluation details does not exist');
153+
assert.strictEqual(
154+
routerEvaluationDetailsElement.childElementCount, 1,
155+
'router evaluation details child element count does not match');
156+
assert.isNotNull(routerEvaluationDetailsElement.firstElementChild, 'router evaluation first element is non null');
157+
158+
// Test if we correctly set the tree item inside shadow root
159+
const shadowElement = routerEvaluationDetailsElement.firstElementChild.shadowRoot;
160+
assert.isNotNull(shadowElement, 'shadow element does not exist');
161+
const content = getCleanTextContentFromElements(shadowElement, '.network-fetch-details-treeitem');
162+
assert.strictEqual(content.length, 2, 'does not match the tree item');
163+
164+
// Check the content of the view. Since the value is set from matched to actual,
165+
// the order should be the same.
166+
const networkString = String(Protocol.Network.ServiceWorkerRouterSource.Network);
167+
assert.strictEqual(content[0], `Matched source: ${networkString}`, 'matched source does not match');
168+
assert.strictEqual(content[1], `Actual source: ${networkString}`, 'actual source does not match');
169+
});
136170
});

front_end/panels/network/RequestTimingView.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ const UIStrings = {
106106
*@description Text in Signed Exchange Info View of the Network panel
107107
*/
108108
label: 'Label',
109+
/**
110+
*@description Text in Request Timing View of the Network panel
111+
*/
112+
routerEvaluation: 'Router Evaluation',
113+
/**
114+
*@description Text in Request Timing View of the Network panel
115+
*/
116+
routerCacheLookup: 'Cache Lookup',
109117
/**
110118
*@description Inner element text content in Network Log View Columns of the Network panel
111119
*/
@@ -217,6 +225,16 @@ const UIStrings = {
217225
*@description Text used to show that data was retrieved using ServiceWorker fallback code
218226
*/
219227
fallbackCode: 'Fallback code',
228+
/**
229+
*@description Name of the specified source for SW static routing API.
230+
*@example {network} PH1
231+
*/
232+
routerMatchedSource: 'Matched source: {PH1}',
233+
/**
234+
*@description Name of the actually used source for SW static routing API.
235+
*@example {network} PH1
236+
*/
237+
routerActualSource: 'Actual source: {PH1}',
220238
};
221239
const str_ = i18n.i18n.registerUIStrings('panels/network/RequestTimingView.ts', UIStrings);
222240
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -258,6 +276,10 @@ export class RequestTimingView extends UI.Widget.VBox {
258276
return i18nString(UIStrings.requestToServiceworker);
259277
case RequestTimeRangeNames.SERVICE_WORKER_PREPARATION:
260278
return i18nString(UIStrings.startup);
279+
case RequestTimeRangeNames.SERVICE_WORKER_ROUTER_EVALUATION:
280+
return i18nString(UIStrings.routerEvaluation);
281+
case RequestTimeRangeNames.SERVICE_WORKER_CACHE_LOOKUP:
282+
return i18nString(UIStrings.routerCacheLookup);
261283
case RequestTimeRangeNames.SERVICE_WORKER_RESPOND_WITH:
262284
return i18nString(UIStrings.respondwith);
263285
case RequestTimeRangeNames.SSL:
@@ -490,6 +512,15 @@ export class RequestTimingView extends UI.Widget.VBox {
490512
timingBarTitleElement.setAttribute('role', 'switch');
491513
UI.ARIAUtils.setChecked(timingBarTitleElement, false);
492514
}
515+
516+
if (range.name === 'serviceworker-routerevaluation') {
517+
timingBarTitleElement.classList.add('network-fetch-timing-bar-clickable');
518+
tableElement.createChild('tr', 'router-evaluation-timing-bar-details');
519+
520+
timingBarTitleElement.setAttribute('tabindex', '0');
521+
timingBarTitleElement.setAttribute('role', 'switch');
522+
UI.ARIAUtils.setChecked(timingBarTitleElement, false);
523+
}
493524
}
494525

495526
if (!request.finished && !request.preserved) {
@@ -683,6 +714,67 @@ export class RequestTimingView extends UI.Widget.VBox {
683714
}
684715
}
685716

717+
private constructRouterEvaluationView(): void {
718+
if (!this.tableElement) {
719+
return;
720+
}
721+
722+
const routerEvaluationDetailsElement = this.tableElement.querySelector('.router-evaluation-timing-bar-details');
723+
if (!routerEvaluationDetailsElement) {
724+
return;
725+
}
726+
727+
routerEvaluationDetailsElement.classList.add('network-fetch-timing-bar-details-collapsed');
728+
729+
self.onInvokeElement(
730+
this.tableElement, this.onToggleRouterEvaluationDetails.bind(this, routerEvaluationDetailsElement));
731+
732+
const detailsView = new UI.TreeOutline.TreeOutlineInShadow();
733+
routerEvaluationDetailsElement.appendChild(detailsView.element);
734+
735+
const {serviceWorkerRouterInfo} = this.request;
736+
if (!serviceWorkerRouterInfo) {
737+
return;
738+
}
739+
740+
const document = this.tableElement.ownerDocument;
741+
742+
// Add matched source type element
743+
const matchedSourceTypeElement = document.createElement('div');
744+
matchedSourceTypeElement.classList.add('network-fetch-details-treeitem');
745+
const matchedSourceType = serviceWorkerRouterInfo.matchedSourceType;
746+
const matchedSourceTypeString = String(matchedSourceType) || i18nString(UIStrings.unknown);
747+
matchedSourceTypeElement.textContent = i18nString(UIStrings.routerMatchedSource, {PH1: matchedSourceTypeString});
748+
749+
const matchedSourceTypeTreeElement = new UI.TreeOutline.TreeElement(matchedSourceTypeElement);
750+
detailsView.appendChild(matchedSourceTypeTreeElement);
751+
752+
// Add actual source type element
753+
const actualSourceTypeElement = document.createElement('div');
754+
actualSourceTypeElement.classList.add('network-fetch-details-treeitem');
755+
const actualSourceType = serviceWorkerRouterInfo.actualSourceType;
756+
const actualSourceTypeString = String(actualSourceType) || i18nString(UIStrings.unknown);
757+
actualSourceTypeElement.textContent = i18nString(UIStrings.routerActualSource, {PH1: actualSourceTypeString});
758+
759+
const actualSourceTypeTreeElement = new UI.TreeOutline.TreeElement(actualSourceTypeElement);
760+
detailsView.appendChild(actualSourceTypeTreeElement);
761+
}
762+
763+
private onToggleRouterEvaluationDetails(routerEvaluationDetailsElement: Element, event: Event): void {
764+
if (!event.target) {
765+
return;
766+
}
767+
768+
const target = (event.target as Element);
769+
if (target.classList.contains('network-fetch-timing-bar-clickable')) {
770+
const expanded = target.getAttribute('aria-checked') === 'true';
771+
target.setAttribute('aria-checked', String(!expanded));
772+
773+
routerEvaluationDetailsElement.classList.toggle('network-fetch-timing-bar-details-collapsed');
774+
routerEvaluationDetailsElement.classList.toggle('network-fetch-timing-bar-details-expanded');
775+
}
776+
}
777+
686778
override wasShown(): void {
687779
this.request.addEventListener(SDK.NetworkRequest.Events.TIMING_CHANGED, this.refresh, this);
688780
this.request.addEventListener(SDK.NetworkRequest.Events.FINISHED_LOADING, this.refresh, this);
@@ -709,6 +801,10 @@ export class RequestTimingView extends UI.Widget.VBox {
709801
if (this.request.fetchedViaServiceWorker) {
710802
this.constructFetchDetailsView();
711803
}
804+
805+
if (this.request.serviceWorkerRouterInfo) {
806+
this.constructRouterEvaluationView();
807+
}
712808
}
713809

714810
private boundaryChanged(): void {

front_end/panels/network/networkTimingTable.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ table.network-timing-table > tr:not(.network-timing-table-header):not(.network-t
161161
display: block;
162162
}
163163

164-
.network-fetch-timing-bar-details {
164+
.network-fetch-timing-bar-details,
165+
.router-evaluation-timing-bar-details {
165166
padding-left: 11px;
166167
width: fit-content;
167168
}

0 commit comments

Comments
 (0)