chrome-devtools-frontend 1.0.1661063 → 1.0.1662289
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/evaluate-ai-css-completion/SKILL.md +19 -9
- package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +44 -16
- package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
- package/docs/ui_engineering.md +75 -42
- package/front_end/core/common/SettingRegistration.ts +0 -5
- package/front_end/core/platform/ArrayUtilities.ts +10 -0
- package/front_end/foundation/README.md +86 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -5
- package/front_end/generated/protocol.ts +20 -38
- package/front_end/models/bindings/CompilerScriptMapping.ts +5 -4
- package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +4 -3
- package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
- package/front_end/models/bindings/NetworkProject.ts +10 -1
- package/front_end/models/bindings/ResourceMapping.ts +4 -3
- package/front_end/models/bindings/ResourceScriptMapping.ts +2 -1
- package/front_end/models/bindings/SASSSourceMapping.ts +4 -3
- package/front_end/models/bindings/StylesSourceMapping.ts +3 -3
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
- package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
- package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/logs/RequestResolver.ts +2 -2
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +0 -5
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +1 -1
- package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
- package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
- package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
- package/front_end/models/trace/handlers/Threads.ts +4 -11
- package/front_end/models/trace/insights/DOMSize.ts +1 -1
- package/front_end/models/workspace/WorkspaceImpl.ts +1 -10
- package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/FrameDetailsView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +494 -411
- package/front_end/panels/application/application.ts +0 -6
- package/front_end/panels/application/components/components.ts +0 -2
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
- package/front_end/panels/application/serviceWorkersView.css +40 -4
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
- package/front_end/panels/common/ExtensionServer.ts +3 -3
- package/front_end/panels/console/ConsoleView.ts +1 -1
- package/front_end/panels/emulation/DeviceModeView.ts +139 -70
- package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
- package/front_end/panels/network/RequestPayloadView.ts +77 -39
- package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
- package/front_end/panels/recorder/RecorderController.ts +213 -49
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/sources/SourcesNavigator.ts +3 -2
- package/front_end/panels/sources/SourcesView.ts +0 -17
- package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
- package/front_end/panels/timeline/ThreadAppender.ts +0 -106
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/report_view/ReportView.ts +11 -5
- package/front_end/ui/components/report_view/report.css +4 -1
- package/front_end/ui/legacy/TextPrompt.ts +49 -1
- package/front_end/ui/legacy/UIUtils.ts +11 -1
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
- package/front_end/ui/legacy/textPrompt.css +10 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
- package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
- package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
- package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
- package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
- package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
- package/front_end/panels/application/interestGroupStorageView.css +0 -9
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
|
@@ -113,9 +113,17 @@ export class DeviceModeView extends UI.Widget.VBox {
|
|
|
113
113
|
this.showRulersSetting = Common.Settings.Settings.instance().moduleSetting('emulation.show-rulers');
|
|
114
114
|
this.showRulersSetting.addChangeListener(this.updateUI, this);
|
|
115
115
|
|
|
116
|
-
this.topRuler = new Ruler(
|
|
116
|
+
this.topRuler = new Ruler();
|
|
117
|
+
this.topRuler.horizontal = true;
|
|
118
|
+
this.topRuler.addEventListener(RulerEvents.MARKER_SELECTED, event => {
|
|
119
|
+
this.model.setWidthAndScaleToFit(event.data);
|
|
120
|
+
});
|
|
117
121
|
this.topRuler.element.classList.add('device-mode-ruler-top');
|
|
118
|
-
this.leftRuler = new Ruler(
|
|
122
|
+
this.leftRuler = new Ruler();
|
|
123
|
+
this.leftRuler.horizontal = false;
|
|
124
|
+
this.leftRuler.addEventListener(RulerEvents.MARKER_SELECTED, event => {
|
|
125
|
+
this.model.setHeightAndScaleToFit(event.data);
|
|
126
|
+
});
|
|
119
127
|
this.leftRuler.element.classList.add('device-mode-ruler-left');
|
|
120
128
|
this.createUI();
|
|
121
129
|
UI.ZoomManager.ZoomManager.instance().addEventListener(UI.ZoomManager.Events.ZOOM_CHANGED, this.zoomChanged, this);
|
|
@@ -566,86 +574,147 @@ export class DeviceModeView extends UI.Widget.VBox {
|
|
|
566
574
|
}
|
|
567
575
|
}
|
|
568
576
|
|
|
569
|
-
export
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
577
|
+
export interface RulerViewInput {
|
|
578
|
+
horizontal: boolean;
|
|
579
|
+
scale: number;
|
|
580
|
+
onMarkerClick: (size: number) => void;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export type RulerView = (input: RulerViewInput, output: undefined, target: HTMLElement) => void;
|
|
584
|
+
|
|
585
|
+
export const DEFAULT_RULER_VIEW: RulerView = (input: RulerViewInput, output: undefined, target: HTMLElement): void => {
|
|
586
|
+
const zoomFactor = UI.ZoomManager.ZoomManager.instance().zoomFactor();
|
|
587
|
+
const size = input.horizontal ? target.offsetWidth : target.offsetHeight;
|
|
588
|
+
|
|
589
|
+
const dipSize = size * zoomFactor / input.scale;
|
|
590
|
+
const count = Math.ceil(dipSize / 5);
|
|
591
|
+
let step = 1;
|
|
592
|
+
if (input.scale < 0.8) {
|
|
593
|
+
step = 2;
|
|
594
|
+
}
|
|
595
|
+
if (input.scale < 0.6) {
|
|
596
|
+
step = 4;
|
|
597
|
+
}
|
|
598
|
+
if (input.scale < 0.4) {
|
|
599
|
+
step = 8;
|
|
600
|
+
}
|
|
601
|
+
if (input.scale < 0.2) {
|
|
602
|
+
step = 16;
|
|
603
|
+
}
|
|
604
|
+
if (input.scale < 0.1) {
|
|
605
|
+
step = 32;
|
|
584
606
|
}
|
|
585
607
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
608
|
+
const markers = [];
|
|
609
|
+
for (let i = 0; i < count; i++) {
|
|
610
|
+
if (i % step) {
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
const isLarge = !(i % 10);
|
|
614
|
+
const isMedium = !(i % 5);
|
|
615
|
+
const offset = i ? `${(5 * i) * input.scale / zoomFactor}px` : undefined;
|
|
616
|
+
|
|
617
|
+
// clang-format off
|
|
618
|
+
markers.push(html`
|
|
619
|
+
<div
|
|
620
|
+
class=${classMap({
|
|
621
|
+
'device-mode-ruler-marker': true,
|
|
622
|
+
'device-mode-ruler-marker-large': isLarge,
|
|
623
|
+
'device-mode-ruler-marker-medium': isMedium && !isLarge,
|
|
624
|
+
})}
|
|
625
|
+
style=${styleMap(input.horizontal ? {left: offset} : {top: offset})}>
|
|
626
|
+
${i && !(i % 20) ?
|
|
627
|
+
html`<div class="device-mode-ruler-text" @click=${() => input.onMarkerClick(i * 5)}>${i * 5}</div>` :
|
|
628
|
+
nothing}
|
|
629
|
+
</div>
|
|
630
|
+
`);
|
|
631
|
+
// clang-format on
|
|
589
632
|
}
|
|
590
633
|
|
|
591
|
-
|
|
592
|
-
|
|
634
|
+
render(html`
|
|
635
|
+
<div class="device-mode-ruler-content">
|
|
636
|
+
<div class="device-mode-ruler-inner">
|
|
637
|
+
${markers}
|
|
638
|
+
</div>
|
|
639
|
+
</div>
|
|
640
|
+
`,
|
|
641
|
+
target, {
|
|
642
|
+
container: {
|
|
643
|
+
classes: ['device-mode-ruler'],
|
|
644
|
+
attributes: {jslog: VisualLogging.deviceModeRuler().track({click: true})},
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
export const enum RulerEvents {
|
|
650
|
+
MARKER_SELECTED = 'MarkerSelected',
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
export interface RulerEventTypes {
|
|
654
|
+
[RulerEvents.MARKER_SELECTED]: number;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export class Ruler extends Common.ObjectWrapper.eventMixin<RulerEventTypes, typeof UI.Widget.Widget>(UI.Widget.Widget) {
|
|
658
|
+
#view: RulerView;
|
|
659
|
+
#horizontal = true;
|
|
660
|
+
#scale = 1;
|
|
661
|
+
|
|
662
|
+
constructor(element?: HTMLElement, view: RulerView = DEFAULT_RULER_VIEW) {
|
|
663
|
+
super(element);
|
|
664
|
+
this.#view = view;
|
|
593
665
|
}
|
|
594
666
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
667
|
+
get horizontal(): boolean {
|
|
668
|
+
return this.#horizontal;
|
|
669
|
+
}
|
|
598
670
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
if (this.scale < 0.8) {
|
|
603
|
-
step = 2;
|
|
604
|
-
}
|
|
605
|
-
if (this.scale < 0.6) {
|
|
606
|
-
step = 4;
|
|
607
|
-
}
|
|
608
|
-
if (this.scale < 0.4) {
|
|
609
|
-
step = 8;
|
|
610
|
-
}
|
|
611
|
-
if (this.scale < 0.2) {
|
|
612
|
-
step = 16;
|
|
613
|
-
}
|
|
614
|
-
if (this.scale < 0.1) {
|
|
615
|
-
step = 32;
|
|
671
|
+
set horizontal(horizontal: boolean) {
|
|
672
|
+
if (this.#horizontal === horizontal) {
|
|
673
|
+
return;
|
|
616
674
|
}
|
|
675
|
+
this.#horizontal = horizontal;
|
|
676
|
+
this.requestUpdate();
|
|
677
|
+
}
|
|
617
678
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
const offset = i ? `${(5 * i) * this.scale / zoomFactor}px` : undefined;
|
|
626
|
-
|
|
627
|
-
// clang-format off
|
|
628
|
-
markers.push(html`
|
|
629
|
-
<div
|
|
630
|
-
class=${classMap({
|
|
631
|
-
'device-mode-ruler-marker': true,
|
|
632
|
-
'device-mode-ruler-marker-large': isLarge,
|
|
633
|
-
'device-mode-ruler-marker-medium': isMedium && !isLarge,
|
|
634
|
-
})}
|
|
635
|
-
style=${styleMap(this.horizontal ? {left: offset} : {top: offset})}>
|
|
636
|
-
${i && !(i % 20) ?
|
|
637
|
-
html`<div class="device-mode-ruler-text" @click=${() => this.onMarkerClick(i * 5)}>${i * 5}</div>` :
|
|
638
|
-
nothing}
|
|
639
|
-
</div>
|
|
640
|
-
`);
|
|
641
|
-
// clang-format on
|
|
679
|
+
get scale(): number {
|
|
680
|
+
return this.#scale;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
set scale(scale: number) {
|
|
684
|
+
if (this.#scale === scale) {
|
|
685
|
+
return;
|
|
642
686
|
}
|
|
687
|
+
this.#scale = scale;
|
|
688
|
+
this.requestUpdate();
|
|
689
|
+
}
|
|
643
690
|
|
|
644
|
-
|
|
645
|
-
|
|
691
|
+
render(scale: number): void {
|
|
692
|
+
this.scale = scale;
|
|
646
693
|
}
|
|
647
694
|
|
|
648
|
-
|
|
649
|
-
|
|
695
|
+
override wasShown(): void {
|
|
696
|
+
super.wasShown();
|
|
697
|
+
this.requestUpdate();
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
override onResize(): void {
|
|
701
|
+
super.onResize();
|
|
702
|
+
this.requestUpdate();
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
#onMarkerClick = (size: number): void => {
|
|
706
|
+
this.dispatchEventToListeners(RulerEvents.MARKER_SELECTED, size);
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
override performUpdate(): void {
|
|
710
|
+
if (!this.isShowing()) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
const viewInput: RulerViewInput = {
|
|
714
|
+
horizontal: this.#horizontal,
|
|
715
|
+
scale: this.#scale,
|
|
716
|
+
onMarkerClick: this.#onMarkerClick,
|
|
717
|
+
};
|
|
718
|
+
this.#view(viewInput, undefined, this.contentElement);
|
|
650
719
|
}
|
|
651
720
|
}
|
|
@@ -84,7 +84,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
|
|
|
84
84
|
|
|
85
85
|
this.affectedResources = this.createAffectedResources();
|
|
86
86
|
this.#affectedResourcesCount = 0;
|
|
87
|
-
this.requestResolver = new Logs.RequestResolver.RequestResolver();
|
|
87
|
+
this.requestResolver = new Logs.RequestResolver.RequestResolver(Logs.NetworkLog.NetworkLog.instance());
|
|
88
88
|
this.#frameListeners = [];
|
|
89
89
|
this.#unresolvedFrameIds = new Set();
|
|
90
90
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
6
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
7
7
|
import type * as Platform from '../../core/platform/platform.js';
|
|
8
|
-
import
|
|
8
|
+
import * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
|
|
9
9
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
10
10
|
import type * as Protocol from '../../generated/protocol.js';
|
|
11
11
|
import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
|
|
@@ -78,6 +78,14 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
78
78
|
private configForTesting?: object;
|
|
79
79
|
private connection?: ProtocolClient.CDPConnection.CDPConnection;
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Session ids that belong to this Lighthouse run. The proxy only relays
|
|
83
|
+
* worker commands and connection events that target one of these sessions
|
|
84
|
+
* so that traffic stays scoped to the parallel session created in
|
|
85
|
+
* `attach()` and its descendants.
|
|
86
|
+
*/
|
|
87
|
+
readonly #knownSessionIds = new Set<string>();
|
|
88
|
+
|
|
81
89
|
/**
|
|
82
90
|
* Tracks pending requests to the Lighthouse worker.
|
|
83
91
|
* Key: The message ID sent to the worker.
|
|
@@ -119,6 +127,8 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
119
127
|
|
|
120
128
|
const rootTargetId = await rootChildTargetManager.getParentTargetId();
|
|
121
129
|
const {sessionId} = await rootTarget.targetAgent().invoke_attachToTarget({targetId: rootTargetId, flatten: true});
|
|
130
|
+
this.#knownSessionIds.clear();
|
|
131
|
+
this.#knownSessionIds.add(sessionId);
|
|
122
132
|
this.connection = connection;
|
|
123
133
|
this.connection.observe(this);
|
|
124
134
|
|
|
@@ -217,6 +227,7 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
217
227
|
this.rootTarget = undefined;
|
|
218
228
|
this.connection?.unobserve(this);
|
|
219
229
|
this.connection = undefined;
|
|
230
|
+
this.#knownSessionIds.clear();
|
|
220
231
|
|
|
221
232
|
if (oldLighthouseWorker) {
|
|
222
233
|
(await oldLighthouseWorker).terminate();
|
|
@@ -237,18 +248,29 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
237
248
|
}
|
|
238
249
|
|
|
239
250
|
private dispatchProtocolMessage(message: ProtocolClient.CDPConnection.CDPReceivableMessage): void {
|
|
240
|
-
//
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
+
// The shared CDPConnection carries traffic for every DevTools session. A
|
|
252
|
+
// parallel session is created for the Lighthouse run in `attach()`, and the
|
|
253
|
+
// worker only ever needs traffic that belongs to that session or one of the
|
|
254
|
+
// child sessions it subsequently attaches. Filtering on `#knownSessionIds`
|
|
255
|
+
// keeps the proxy scoped to the run instead of broadcasting unrelated
|
|
256
|
+
// session traffic into the worker.
|
|
257
|
+
if (!message.sessionId || !this.#knownSessionIds.has(message.sessionId)) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if ('method' in message) {
|
|
261
|
+
if (message.method === 'Target.attachedToTarget') {
|
|
262
|
+
const childSessionId = (message.params as Protocol.Target.AttachedToTargetEvent | undefined)?.sessionId;
|
|
263
|
+
if (childSessionId) {
|
|
264
|
+
this.#knownSessionIds.add(childSessionId);
|
|
265
|
+
}
|
|
266
|
+
} else if (message.method === 'Target.detachedFromTarget') {
|
|
267
|
+
const childSessionId = (message.params as Protocol.Target.DetachedFromTargetEvent | undefined)?.sessionId;
|
|
268
|
+
if (childSessionId) {
|
|
269
|
+
this.#knownSessionIds.delete(childSessionId);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
251
272
|
}
|
|
273
|
+
void this.send('dispatchProtocolMessage', {message});
|
|
252
274
|
}
|
|
253
275
|
|
|
254
276
|
onDisconnect(): void {
|
|
@@ -303,11 +325,30 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
303
325
|
|
|
304
326
|
private sendProtocolMessage(message: string): void {
|
|
305
327
|
const {id, method, params, sessionId} = JSON.parse(message);
|
|
328
|
+
// The worker is expected to only address the parallel session created in
|
|
329
|
+
// `attach()` or sessions discovered beneath it. Anything else, including
|
|
330
|
+
// the root session, is outside the scope of the run.
|
|
331
|
+
if (!sessionId || !this.#knownSessionIds.has(sessionId)) {
|
|
332
|
+
void this.send('dispatchProtocolMessage', {
|
|
333
|
+
message: {
|
|
334
|
+
id,
|
|
335
|
+
sessionId,
|
|
336
|
+
error: {
|
|
337
|
+
code: ProtocolClient.CDPConnection.CDPErrorStatus.SESSION_NOT_FOUND,
|
|
338
|
+
message: `Unknown session id: ${sessionId}`,
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
306
344
|
// CDPConnection manages it's own message IDs and it's important, otherwise we'd clash
|
|
307
345
|
// with the rest of the DevTools traffic.
|
|
308
346
|
// Instead, we ignore the ID coming from the worker when sending the command, but
|
|
309
347
|
// patch it back in when sending the response back to the worker.
|
|
310
348
|
void this.connection?.send(method, params, sessionId).then(response => {
|
|
349
|
+
if ('result' in response && method === 'Target.attachToTarget' && response.result?.sessionId) {
|
|
350
|
+
this.#knownSessionIds.add(response.result.sessionId);
|
|
351
|
+
}
|
|
311
352
|
const message =
|
|
312
353
|
'result' in response ? {id, sessionId, result: response.result} : {id, sessionId, error: response.error};
|
|
313
354
|
this.dispatchProtocolMessage(message);
|
|
@@ -109,8 +109,10 @@ const str_ = i18n.i18n.registerUIStrings('panels/network/RequestPayloadView.ts',
|
|
|
109
109
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
110
110
|
|
|
111
111
|
interface ViewInput {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
decodeQueryParameters: boolean;
|
|
113
|
+
setDecodeQueryParameters(value: boolean): void;
|
|
114
|
+
decodeFormParameters: boolean;
|
|
115
|
+
setDecodeFormParameters(value: boolean): void;
|
|
114
116
|
viewQueryParamSource: boolean;
|
|
115
117
|
setViewQueryParamSource(value: boolean): void;
|
|
116
118
|
viewFormParamSource: boolean;
|
|
@@ -157,15 +159,28 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
157
159
|
</devtools-widget>
|
|
158
160
|
</li>`;
|
|
159
161
|
|
|
160
|
-
const createParsedParams = (params: SDK.NetworkRequest.NameValue[]
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
const createParsedParams = (params: SDK.NetworkRequest.NameValue[],
|
|
163
|
+
decodeParameters: boolean): TemplateResult[] => params.map(param => {
|
|
164
|
+
// clang-format off
|
|
165
|
+
return html`
|
|
166
|
+
<li role=treeitem
|
|
167
|
+
@contextmenu=${copyValueContextmenu(
|
|
168
|
+
i18nString(UIStrings.copyValue),
|
|
169
|
+
() => decodeURIComponent(param.value),
|
|
170
|
+
'copy-value'
|
|
171
|
+
)}>
|
|
172
|
+
${param.name !== '' ? html`
|
|
173
|
+
${RequestPayloadView.formatParameter(param.name, 'payload-name', decodeParameters)}
|
|
174
|
+
${RequestPayloadView.formatParameter(param.value, 'payload-value source-code', decodeParameters)}
|
|
175
|
+
` : RequestPayloadView.formatParameter(
|
|
176
|
+
i18nString(UIStrings.empty),
|
|
177
|
+
'empty-request-payload',
|
|
178
|
+
decodeParameters
|
|
179
|
+
)}
|
|
180
|
+
</li>
|
|
181
|
+
`;
|
|
182
|
+
// clang-format on
|
|
183
|
+
});
|
|
169
184
|
|
|
170
185
|
const parsedFormData = (() => {
|
|
171
186
|
if (input.formData && !input.formParameters) {
|
|
@@ -201,24 +216,23 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
201
216
|
const requestPayloadExpandedSetting =
|
|
202
217
|
Common.Settings.Settings.instance().createSetting('request-info-request-payload-category-expanded', true);
|
|
203
218
|
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const onContextMenu = (viewSource: boolean, callback: (value: boolean) => void, includeURLDecodingOption = true) => (
|
|
210
|
-
event: Event): void => {
|
|
219
|
+
const onContextMenu = (
|
|
220
|
+
viewSource: boolean,
|
|
221
|
+
setViewSource: (value: boolean) => void,
|
|
222
|
+
decoding?: {decode: boolean, toggleDecode: () => void},
|
|
223
|
+
) => (event: Event): void => {
|
|
211
224
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
212
225
|
const section = contextMenu.newSection();
|
|
213
226
|
if (viewSource) {
|
|
214
|
-
section.appendItem(i18nString(UIStrings.viewParsed), () =>
|
|
227
|
+
section.appendItem(i18nString(UIStrings.viewParsed), () => setViewSource(!viewSource),
|
|
228
|
+
{jslogContext: 'view-parsed'});
|
|
215
229
|
} else {
|
|
216
|
-
section.appendItem(i18nString(UIStrings.viewSource), () =>
|
|
217
|
-
|
|
230
|
+
section.appendItem(i18nString(UIStrings.viewSource), () => setViewSource(!viewSource),
|
|
231
|
+
{jslogContext: 'view-source'});
|
|
232
|
+
if (decoding) {
|
|
218
233
|
const viewURLEncodedText =
|
|
219
|
-
|
|
220
|
-
section.appendItem(
|
|
221
|
-
viewURLEncodedText, toggleURLDecoding.bind(this, event), {jslogContext: 'toggle-url-decoding'});
|
|
234
|
+
decoding.decode ? i18nString(UIStrings.viewUrlEncoded) : i18nString(UIStrings.viewDecoded);
|
|
235
|
+
section.appendItem(viewURLEncodedText, () => decoding.toggleDecode(), {jslogContext: 'toggle-url-decoding'});
|
|
222
236
|
}
|
|
223
237
|
}
|
|
224
238
|
void contextMenu.show();
|
|
@@ -235,7 +249,14 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
235
249
|
role=treeitem
|
|
236
250
|
?hidden=${!input.queryParameters}
|
|
237
251
|
jslog=${VisualLogging.section().context('query-string')}
|
|
238
|
-
@contextmenu=${onContextMenu(
|
|
252
|
+
@contextmenu=${onContextMenu(
|
|
253
|
+
input.viewQueryParamSource,
|
|
254
|
+
input.setViewQueryParamSource,
|
|
255
|
+
{
|
|
256
|
+
decode: input.decodeQueryParameters,
|
|
257
|
+
toggleDecode: () => input.setDecodeQueryParameters(!input.decodeQueryParameters),
|
|
258
|
+
}
|
|
259
|
+
)}
|
|
239
260
|
@expanded=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) =>
|
|
240
261
|
queryStringExpandedSetting.set(e.detail.expanded)}
|
|
241
262
|
?open=${queryStringExpandedSetting.get()}
|
|
@@ -248,19 +269,26 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
248
269
|
?hidden=${input.viewQueryParamSource}
|
|
249
270
|
jslog=${VisualLogging.action().track({click: true}).context('decode-encode')}
|
|
250
271
|
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
251
|
-
@click=${
|
|
252
|
-
${input.
|
|
272
|
+
@click=${(e: Event) => { e.consume(); input.setDecodeQueryParameters(!input.decodeQueryParameters); }}>
|
|
273
|
+
${input.decodeQueryParameters ? i18nString(UIStrings.viewUrlEncoded) : i18nString(UIStrings.viewDecoded)}
|
|
253
274
|
</devtools-button>
|
|
254
275
|
<ul role=group>
|
|
255
276
|
${ifExpanded(input.viewQueryParamSource ? createSourceText(input.queryString ?? '')
|
|
256
|
-
: createParsedParams(input.queryParameters ?? []))}
|
|
277
|
+
: createParsedParams(input.queryParameters ?? [], input.decodeQueryParameters))}
|
|
257
278
|
</ul>
|
|
258
279
|
</li>
|
|
259
280
|
<li
|
|
260
281
|
role=treeitem
|
|
261
282
|
?hidden=${!input.formData || !input.formParameters}
|
|
262
283
|
jslog=${VisualLogging.section().context('form-data')}
|
|
263
|
-
@contextmenu=${onContextMenu(
|
|
284
|
+
@contextmenu=${onContextMenu(
|
|
285
|
+
input.viewFormParamSource,
|
|
286
|
+
input.setViewFormParamSource,
|
|
287
|
+
{
|
|
288
|
+
decode: input.decodeFormParameters,
|
|
289
|
+
toggleDecode: () => input.setDecodeFormParameters(!input.decodeFormParameters),
|
|
290
|
+
}
|
|
291
|
+
)}
|
|
264
292
|
@expanded=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => formDataExpandedSetting.set(e.detail.expanded)}
|
|
265
293
|
?open=${formDataExpandedSetting.get()}
|
|
266
294
|
>
|
|
@@ -272,20 +300,22 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
272
300
|
?hidden=${input.viewFormParamSource}
|
|
273
301
|
jslog=${VisualLogging.action().track({click: true}).context('decode-encode')}
|
|
274
302
|
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
275
|
-
@click=${
|
|
276
|
-
${input.
|
|
303
|
+
@click=${(e: Event) => { e.consume(); input.setDecodeFormParameters(!input.decodeFormParameters); }}>
|
|
304
|
+
${input.decodeFormParameters ? i18nString(UIStrings.viewUrlEncoded) : i18nString(UIStrings.viewDecoded)}
|
|
277
305
|
</devtools-button>
|
|
278
306
|
<ul role=group>
|
|
279
307
|
${ifExpanded(input.viewFormParamSource ? createSourceText(input.formData ?? '')
|
|
280
|
-
: createParsedParams(input.formParameters ?? []))}
|
|
308
|
+
: createParsedParams(input.formParameters ?? [], input.decodeFormParameters))}
|
|
281
309
|
</ul>
|
|
282
310
|
</li>
|
|
283
311
|
<li
|
|
284
312
|
role=treeitem
|
|
285
313
|
?hidden=${!input.formData || Boolean(input.formParameters) || Boolean(input.binaryPayloadContentData)}
|
|
286
314
|
jslog=${VisualLogging.section().context('request-payload')}
|
|
287
|
-
@contextmenu=${onContextMenu(
|
|
288
|
-
|
|
315
|
+
@contextmenu=${onContextMenu(
|
|
316
|
+
input.viewJSONPayloadSource,
|
|
317
|
+
input.setViewJSONPayloadSource,
|
|
318
|
+
)}
|
|
289
319
|
@expanded=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) =>
|
|
290
320
|
requestPayloadExpandedSetting.set(e.detail.expanded)}
|
|
291
321
|
?open=${requestPayloadExpandedSetting.get()}
|
|
@@ -324,7 +354,8 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
324
354
|
|
|
325
355
|
export class RequestPayloadView extends UI.Widget.VBox {
|
|
326
356
|
#request?: SDK.NetworkRequest.NetworkRequest;
|
|
327
|
-
#
|
|
357
|
+
#decodeQueryParameters = true;
|
|
358
|
+
#decodeFormParameters = true;
|
|
328
359
|
#formData?: string;
|
|
329
360
|
#formParameters?: SDK.NetworkRequest.NameValue[];
|
|
330
361
|
#binaryPayloadContentData: TextUtils.ContentData.ContentData|null = null;
|
|
@@ -345,9 +376,11 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
345
376
|
}
|
|
346
377
|
this.#request = request;
|
|
347
378
|
|
|
379
|
+
this.#decodeQueryParameters = true;
|
|
380
|
+
this.#decodeFormParameters = true;
|
|
348
381
|
const contentType = request.requestContentType();
|
|
349
382
|
if (contentType) {
|
|
350
|
-
this.#
|
|
383
|
+
this.#decodeFormParameters = Boolean(contentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i));
|
|
351
384
|
}
|
|
352
385
|
|
|
353
386
|
if (this.isShowing()) {
|
|
@@ -402,9 +435,14 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
402
435
|
queryParameters: this.request.queryParameters,
|
|
403
436
|
formData: this.#formData,
|
|
404
437
|
formParameters: this.#formParameters,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
this.#
|
|
438
|
+
decodeQueryParameters: this.#decodeQueryParameters,
|
|
439
|
+
setDecodeQueryParameters: (value: boolean): void => {
|
|
440
|
+
this.#decodeQueryParameters = value;
|
|
441
|
+
this.requestUpdate();
|
|
442
|
+
},
|
|
443
|
+
decodeFormParameters: this.#decodeFormParameters,
|
|
444
|
+
setDecodeFormParameters: (value: boolean): void => {
|
|
445
|
+
this.#decodeFormParameters = value;
|
|
408
446
|
this.requestUpdate();
|
|
409
447
|
},
|
|
410
448
|
viewQueryParamSource: this.#viewQueryParamSource,
|
|
@@ -170,12 +170,14 @@ export class ResponseHeaderSection extends ResponseHeaderSectionBase {
|
|
|
170
170
|
BlockedReasonDetails.get((this.#request.blockedReason() as Protocol.Network.BlockedReason));
|
|
171
171
|
if (headerWithIssues) {
|
|
172
172
|
if (IssuesManager.RelatedIssue.hasIssueOfCategory(
|
|
173
|
-
this.#request, IssuesManager.Issue.IssueCategory.CROSS_ORIGIN_EMBEDDER_POLICY
|
|
173
|
+
this.#request, IssuesManager.Issue.IssueCategory.CROSS_ORIGIN_EMBEDDER_POLICY,
|
|
174
|
+
IssuesManager.IssuesManager.IssuesManager.instance())) {
|
|
174
175
|
const followLink = (): void => {
|
|
175
176
|
Host.userMetrics.issuesPanelOpenedFrom(Host.UserMetrics.IssueOpener.LEARN_MORE_LINK_COEP);
|
|
176
177
|
if (this.#request) {
|
|
177
|
-
void IssuesManager.RelatedIssue.reveal(
|
|
178
|
-
|
|
178
|
+
void IssuesManager.RelatedIssue.reveal(this.#request,
|
|
179
|
+
IssuesManager.IssuesManager.IssuesManager.instance(),
|
|
180
|
+
IssuesManager.Issue.IssueCategory.CROSS_ORIGIN_EMBEDDER_POLICY);
|
|
179
181
|
}
|
|
180
182
|
};
|
|
181
183
|
if (headerWithIssues.blockedDetails) {
|
|
@@ -1795,8 +1795,8 @@ export class HeapProfileHeader extends ProfileHeader {
|
|
|
1795
1795
|
|
|
1796
1796
|
setupWorker(): void {
|
|
1797
1797
|
console.assert(!this.workerProxy, 'HeapSnapshotWorkerProxy already exists');
|
|
1798
|
-
this.workerProxy =
|
|
1799
|
-
|
|
1798
|
+
this.workerProxy = new HeapSnapshotModel.HeapSnapshotProxy.HeapSnapshotWorkerProxy(
|
|
1799
|
+
this.handleWorkerEvent.bind(this), Common.Console.Console.instance());
|
|
1800
1800
|
this.workerProxy.addEventListener(
|
|
1801
1801
|
HeapSnapshotModel.HeapSnapshotProxy.HeapSnapshotWorkerProxy.Events.WAIT, event => {
|
|
1802
1802
|
this.updateStatus(null, event.data);
|