chrome-devtools-frontend 1.0.1661063 → 1.0.1662965
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/devtools-unicode-escaping/SKILL.md +64 -0
- 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 +32 -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 -10
- package/front_end/core/common/Settings.ts +69 -3
- package/front_end/core/platform/ArrayUtilities.ts +10 -0
- package/front_end/core/platform/StringUtilities.ts +38 -6
- package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -10
- package/front_end/core/sdk/StorageBucketsModel.ts +0 -10
- package/front_end/core/sdk/sdk-meta.ts +0 -1
- package/front_end/entrypoints/inspector_main/OutermostTargetSelector.ts +0 -13
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +8 -3
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +3 -3
- package/front_end/entrypoints/main/MainImpl.ts +7 -2
- package/front_end/foundation/README.md +86 -0
- package/front_end/foundation/Universe.ts +16 -0
- package/front_end/generated/InspectorBackendCommands.ts +6 -19
- package/front_end/generated/protocol-mapping.d.ts +0 -53
- package/front_end/generated/protocol-proxy-api.d.ts +0 -46
- package/front_end/generated/protocol.ts +20 -186
- package/front_end/models/ai_assistance/AiAgent2.ts +3 -3
- package/front_end/models/ai_assistance/AiConversation.ts +21 -10
- package/front_end/models/ai_assistance/AiHistoryStorage.ts +21 -10
- package/front_end/models/ai_assistance/ChangeManager.ts +2 -2
- package/front_end/models/ai_assistance/ExtensionScope.ts +6 -2
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/AiAgent.ts +8 -1
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
- package/front_end/models/badges/UserBadges.ts +31 -17
- 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 +22 -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/emulation/DeviceModeModel.ts +67 -5
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
- package/front_end/models/extensions/RecorderPluginManager.ts +10 -6
- package/front_end/models/har/Log.snapshot.txt +193 -0
- package/front_end/models/har/Log.ts +3 -2
- 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 +8 -6
- package/front_end/models/source_map_scopes/NamesResolver.ts +36 -30
- package/front_end/models/stack_trace/StackTrace.ts +17 -0
- 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/IndexedDBModel.ts +0 -10
- package/front_end/panels/application/IndexedDBViews.ts +240 -164
- package/front_end/panels/application/ServiceWorkersView.ts +494 -411
- package/front_end/panels/application/SharedStorageModel.ts +0 -10
- package/front_end/panels/application/application.ts +0 -6
- package/front_end/panels/application/components/AdsView.ts +23 -0
- package/front_end/panels/application/components/SharedStorageAccessGrid.ts +1 -1
- package/front_end/panels/application/components/adsView.css +21 -1
- package/front_end/panels/application/components/components.ts +0 -2
- package/front_end/panels/application/indexedDBViews.css +1 -1
- 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/NetworkDataGridNode.ts +43 -1
- package/front_end/panels/network/RequestInitiatorView.ts +24 -2
- package/front_end/panels/network/RequestPayloadView.ts +77 -39
- package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
- package/front_end/panels/network/networkLogView.css +5 -0
- package/front_end/panels/network/requestInitiatorViewTree.css +5 -0
- package/front_end/panels/profiler/HeapProfileView.ts +198 -79
- package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
- package/front_end/panels/recorder/README.md +1 -2
- package/front_end/panels/recorder/RecorderPanel.ts +1749 -17
- package/front_end/panels/recorder/recorder.ts +0 -2
- package/front_end/panels/settings/AISettingsTab.ts +13 -0
- 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/components/spinners/Spinner.ts +29 -32
- package/front_end/ui/components/spinners/spinner.css +32 -84
- package/front_end/ui/legacy/TextPrompt.ts +49 -1
- package/front_end/ui/legacy/Treeoutline.ts +14 -6
- package/front_end/ui/legacy/UIUtils.ts +36 -11
- package/front_end/ui/legacy/Widget.ts +17 -10
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +36 -7
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +63 -68
- package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/objectValue.css +2 -1
- package/front_end/ui/legacy/inspectorCommon.css +4 -4
- package/front_end/ui/legacy/textPrompt.css +10 -0
- package/front_end/ui/lit/lit.ts +1 -0
- package/front_end/ui/lit/render.ts +44 -10
- package/front_end/ui/lit/strip-whitespace.ts +23 -2
- 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/recorder/RecorderController.ts +0 -1595
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
- /package/front_end/panels/recorder/{recorderController.css → recorderPanel.css} +0 -0
|
@@ -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);
|
|
@@ -47,6 +47,7 @@ import * as Bindings from '../../models/bindings/bindings.js';
|
|
|
47
47
|
import type * as HAR from '../../models/har/har.js';
|
|
48
48
|
import * as Logs from '../../models/logs/logs.js';
|
|
49
49
|
import type * as NetworkTimeCalculator from '../../models/network_time_calculator/network_time_calculator.js';
|
|
50
|
+
import * as StackTrace from '../../models/stack_trace/stack_trace.js';
|
|
50
51
|
import * as NetworkForward from '../../panels/network/forward/forward.js';
|
|
51
52
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
52
53
|
import {createIcon} from '../../ui/kit/kit.js';
|
|
@@ -343,6 +344,16 @@ const UIStrings = {
|
|
|
343
344
|
* @description Text in Network Data Grid Node of the Network panel. Noun. Refers to a potentially blocking resource.
|
|
344
345
|
*/
|
|
345
346
|
potentiallyBlocking: 'Potentially blocking',
|
|
347
|
+
/**
|
|
348
|
+
* @description Text indicating a request originated from the DevTools console. Used as a subtitle in the
|
|
349
|
+
* Initiator column.
|
|
350
|
+
*/
|
|
351
|
+
console: 'Console',
|
|
352
|
+
/**
|
|
353
|
+
* @description Tooltip for the console icon in the Network panel, indicating a request was initiated
|
|
354
|
+
* from the Console.
|
|
355
|
+
*/
|
|
356
|
+
requestOriginatedFromConsole: 'Request originated from Console',
|
|
346
357
|
|
|
347
358
|
} as const;
|
|
348
359
|
const str_ = i18n.i18n.registerUIStrings('panels/network/NetworkDataGridNode.ts', UIStrings);
|
|
@@ -1009,6 +1020,29 @@ export class NetworkRequestNode extends NetworkNode {
|
|
|
1009
1020
|
return aValue.localeCompare(bValue) || aRequest.identityCompare(bRequest);
|
|
1010
1021
|
}
|
|
1011
1022
|
|
|
1023
|
+
static isConsoleOriginated(request: SDK.NetworkRequest.NetworkRequest): boolean {
|
|
1024
|
+
const resourceType = request.resourceType();
|
|
1025
|
+
if (resourceType !== Common.ResourceType.resourceTypes.Fetch &&
|
|
1026
|
+
resourceType !== Common.ResourceType.resourceTypes.XHR) {
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
const initiator = request.initiator();
|
|
1030
|
+
if (!initiator || initiator.type !== Protocol.Network.InitiatorType.Script) {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
if (initiator.url) {
|
|
1034
|
+
return false;
|
|
1035
|
+
}
|
|
1036
|
+
if (!initiator.stack) {
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
return StackTrace.StackTrace.isConsoleOriginated(initiator.stack);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
private isConsoleOriginated(): boolean {
|
|
1043
|
+
return NetworkRequestNode.isConsoleOriginated(this.requestInternal);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1012
1046
|
override showingInitiatorChainChanged(): void {
|
|
1013
1047
|
const showInitiatorChain = this.showingInitiatorChain();
|
|
1014
1048
|
|
|
@@ -1340,6 +1374,13 @@ export class NetworkRequestNode extends NetworkNode {
|
|
|
1340
1374
|
// eslint-disable-next-line @devtools/no-lit-render-outside-of-view
|
|
1341
1375
|
render(iconElement, cell);
|
|
1342
1376
|
|
|
1377
|
+
// render Console icon if this request originated from Console
|
|
1378
|
+
if (this.isConsoleOriginated()) {
|
|
1379
|
+
const consoleIcon = createIcon('terminal', 'network-console-icon');
|
|
1380
|
+
UI.Tooltip.Tooltip.install(consoleIcon, i18nString(UIStrings.requestOriginatedFromConsole));
|
|
1381
|
+
cell.appendChild(consoleIcon);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1343
1384
|
// render Ask AI button
|
|
1344
1385
|
const aiButtonContainer = this.createAiButtonIfAvailable();
|
|
1345
1386
|
if (aiButtonContainer) {
|
|
@@ -1590,7 +1631,8 @@ export class NetworkRequestNode extends NetworkNode {
|
|
|
1590
1631
|
}
|
|
1591
1632
|
UI.Tooltip.Tooltip.install((this.linkifiedInitiatorAnchor), '');
|
|
1592
1633
|
cell.appendChild(this.linkifiedInitiatorAnchor);
|
|
1593
|
-
this.appendSubtitle(cell,
|
|
1634
|
+
this.appendSubtitle(cell,
|
|
1635
|
+
this.isConsoleOriginated() ? i18nString(UIStrings.console) : i18nString(UIStrings.script));
|
|
1594
1636
|
cell.classList.add('network-script-initiated');
|
|
1595
1637
|
break;
|
|
1596
1638
|
}
|
|
@@ -12,6 +12,7 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
12
12
|
import {Directives, html, type LitTemplate, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
13
13
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
14
14
|
|
|
15
|
+
import {NetworkRequestNode} from './NetworkDataGridNode.js';
|
|
15
16
|
import requestInitiatorViewStyles from './requestInitiatorView.css.js';
|
|
16
17
|
import requestInitiatorViewTreeStyles from './requestInitiatorViewTree.css.js';
|
|
17
18
|
|
|
@@ -30,6 +31,10 @@ const UIStrings = {
|
|
|
30
31
|
* @description Title of a section in Request Initiator view of the Network Panel
|
|
31
32
|
*/
|
|
32
33
|
requestInitiatorChain: 'Request initiator chain',
|
|
34
|
+
/**
|
|
35
|
+
* @description Label shown in the initiator chain when a request was initiated from the Console.
|
|
36
|
+
*/
|
|
37
|
+
console: 'Console',
|
|
33
38
|
} as const;
|
|
34
39
|
const str_ = i18n.i18n.registerUIStrings('panels/network/RequestInitiatorView.ts', UIStrings);
|
|
35
40
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -51,6 +56,7 @@ export interface ViewInput {
|
|
|
51
56
|
initiatorGraph: Logs.NetworkLog.InitiatorGraph;
|
|
52
57
|
stackTrace: StackTrace.StackTrace.StackTrace|null;
|
|
53
58
|
request: SDK.NetworkRequest.NetworkRequest;
|
|
59
|
+
isConsoleOriginated: boolean;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
|
|
@@ -83,6 +89,11 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLE
|
|
|
83
89
|
stackTrace: input.stackTrace,
|
|
84
90
|
})}
|
|
85
91
|
</li>
|
|
92
|
+
${input.isConsoleOriginated ? html`
|
|
93
|
+
<li role="treeitem" class="console-origin-label">
|
|
94
|
+
${i18nString(UIStrings.console)}
|
|
95
|
+
</li>
|
|
96
|
+
` : nothing}
|
|
86
97
|
</ul>
|
|
87
98
|
</li>
|
|
88
99
|
`;
|
|
@@ -167,13 +178,21 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLE
|
|
|
167
178
|
${i18nString(UIStrings.requestInitiatorChain)}
|
|
168
179
|
${hasInitiatorChain ? html`
|
|
169
180
|
<ul role="group">
|
|
170
|
-
${
|
|
181
|
+
${input.isConsoleOriginated ? html`
|
|
182
|
+
<li role="treeitem" aria-expanded="true" open>
|
|
183
|
+
<span>${i18nString(UIStrings.console)}</span>
|
|
184
|
+
<ul role="group">
|
|
185
|
+
${renderInitiatorNodes(initiators, 0, initiatorGraph.initiated, visited)}
|
|
186
|
+
</ul>
|
|
187
|
+
</li>` :
|
|
188
|
+
renderInitiatorNodes(initiators, 0, initiatorGraph.initiated, visited)}
|
|
171
189
|
</ul>` : nothing}
|
|
172
190
|
</li>`;
|
|
173
191
|
// clang-format on
|
|
174
192
|
};
|
|
175
193
|
|
|
176
|
-
const hasInitiatorChain =
|
|
194
|
+
const hasInitiatorChain =
|
|
195
|
+
input.initiatorGraph.initiators.size > 1 || input.initiatorGraph.initiated.size > 1 || input.isConsoleOriginated;
|
|
177
196
|
|
|
178
197
|
// clang-format off
|
|
179
198
|
render(html`
|
|
@@ -242,10 +261,13 @@ export class RequestInitiatorView extends UI.Widget.VBox {
|
|
|
242
261
|
.createStackTraceFromProtocolRuntime(rawStack, target);
|
|
243
262
|
}
|
|
244
263
|
|
|
264
|
+
const isConsoleOriginated = NetworkRequestNode.isConsoleOriginated(this.request);
|
|
265
|
+
|
|
245
266
|
const viewInput: ViewInput = {
|
|
246
267
|
initiatorGraph,
|
|
247
268
|
stackTrace,
|
|
248
269
|
request: this.request,
|
|
270
|
+
isConsoleOriginated,
|
|
249
271
|
};
|
|
250
272
|
|
|
251
273
|
this.#view(viewInput, undefined, this.contentElement);
|