chrome-devtools-frontend 1.0.1608453 → 1.0.1609381
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/front_end/core/host/AidaGcaTranslation.ts +13 -0
- package/front_end/core/sdk/PreloadingModel.ts +1 -1
- package/front_end/entrypoints/heap_snapshot_worker/AllocationProfile.ts +1 -1
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +1 -1
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +1 -1
- package/front_end/generated/InspectorBackendCommands.ts +1 -2
- package/front_end/generated/protocol-mapping.d.ts +0 -9
- package/front_end/generated/protocol-proxy-api.d.ts +0 -7
- package/front_end/generated/protocol.ts +0 -20
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +6 -4
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +11 -10
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +26 -2
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +49 -30
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +5 -3
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +69 -69
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -1
- package/front_end/models/live-metrics/LiveMetrics.ts +43 -41
- package/front_end/models/trace/EntityMapper.ts +12 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +44 -15
- package/front_end/panels/ai_assistance/components/chatMessage.css +13 -0
- package/front_end/panels/application/ApplicationPanelSidebar.ts +8 -0
- package/front_end/panels/application/IndexedDBViews.ts +1 -1
- package/front_end/panels/application/ReportingApiTreeElement.ts +40 -1
- package/front_end/panels/application/ResourcesPanel.ts +8 -0
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
- package/front_end/panels/application/WebMCPView.ts +122 -4
- package/front_end/panels/application/application-meta.ts +11 -0
- package/front_end/panels/application/application.ts +3 -0
- package/front_end/panels/application/components/StorageMetadataView.ts +31 -7
- package/front_end/panels/application/components/backForwardCacheView.css +4 -0
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +29 -0
- package/front_end/panels/application/webMCPView.css +12 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +4 -0
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +1 -1
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +1 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
- package/front_end/panels/timeline/TimelinePanel.ts +2 -6
- package/front_end/panels/timeline/utils/Helpers.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/legacy/InspectorDrawerView.ts +188 -15
- package/front_end/ui/legacy/InspectorView.ts +162 -11
- package/front_end/ui/legacy/TabbedPane.ts +2 -2
- package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
- package/front_end/ui/legacy/components/utils/imagePreview.css +1 -1
- package/front_end/ui/legacy/inspectorDrawerTabbedPane.css +54 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/front_end/ui/visual_logging/LoggingDriver.ts +3 -3
- package/mcp/mcp.ts +1 -1
- package/package.json +1 -1
- /package/front_end/models/{heap_snapshot_model → heap_snapshot}/ChildrenProvider.ts +0 -0
- /package/front_end/models/{heap_snapshot_model → heap_snapshot}/HeapSnapshotModel.ts +0 -0
- /package/front_end/models/{heap_snapshot_model → heap_snapshot}/HeapSnapshotProxy.ts +0 -0
- /package/front_end/models/{heap_snapshot_model/heap_snapshot_model.ts → heap_snapshot/heap_snapshot.ts} +0 -0
|
@@ -482,7 +482,6 @@ function renderStepCode(step: Step): Lit.LitTemplate {
|
|
|
482
482
|
<devtools-code-block
|
|
483
483
|
.code=${step.code.trim()}
|
|
484
484
|
.codeLang=${'js'}
|
|
485
|
-
.displayLimit=${MAX_NUM_LINES_IN_CODEBLOCK}
|
|
486
485
|
.displayNotice=${!Boolean(step.output)}
|
|
487
486
|
.header=${codeHeadingText}
|
|
488
487
|
.showCopyButton=${true}
|
|
@@ -493,7 +492,6 @@ function renderStepCode(step: Step): Lit.LitTemplate {
|
|
|
493
492
|
<devtools-code-block
|
|
494
493
|
.code=${step.output}
|
|
495
494
|
.codeLang=${'js'}
|
|
496
|
-
.displayLimit=${MAX_NUM_LINES_IN_CODEBLOCK}
|
|
497
495
|
.displayNotice=${true}
|
|
498
496
|
.header=${lockedString(UIStringsNotTranslate.dataReturned)}
|
|
499
497
|
.showCopyButton=${false}
|
|
@@ -526,7 +524,6 @@ function renderStepDetails({
|
|
|
526
524
|
<devtools-code-block
|
|
527
525
|
.code=${contextDetail.text}
|
|
528
526
|
.codeLang=${contextDetail.codeLang || ''}
|
|
529
|
-
.displayLimit=${MAX_NUM_LINES_IN_CODEBLOCK}
|
|
530
527
|
.displayNotice=${false}
|
|
531
528
|
.header=${contextDetail.title}
|
|
532
529
|
.showCopyButton=${true}
|
|
@@ -568,9 +565,14 @@ function renderWalkthroughSidebarButton(
|
|
|
568
565
|
const variant = hasOneStepWithWidget && !input.isLoading ? Buttons.Button.Variant.TONAL : Buttons.Button.Variant.TEXT;
|
|
569
566
|
const icon = AiAssistanceModel.AiUtils.getIconName();
|
|
570
567
|
|
|
568
|
+
const toggleContainerClasses = Lit.Directives.classMap({
|
|
569
|
+
'walkthrough-toggle-container': true,
|
|
570
|
+
// We only apply the widget styling when loading is complete
|
|
571
|
+
'has-widgets': hasOneStepWithWidget && !input.isLoading,
|
|
572
|
+
});
|
|
571
573
|
// clang-format off
|
|
572
574
|
return html`
|
|
573
|
-
<div class
|
|
575
|
+
<div class=${toggleContainerClasses}>
|
|
574
576
|
${input.isLoading ?
|
|
575
577
|
html`<devtools-spinner></devtools-spinner>` :
|
|
576
578
|
html`<devtools-icon name=${icon}></devtools-icon>`}
|
|
@@ -589,9 +591,7 @@ function renderWalkthroughSidebarButton(
|
|
|
589
591
|
// the walkthrough open with an alternative message.
|
|
590
592
|
walkthrough.onOpen(message as ModelChatMessage);
|
|
591
593
|
}
|
|
592
|
-
}}
|
|
593
|
-
>
|
|
594
|
-
${title}<devtools-icon class="chevron" .name=${isExpanded ? 'cross' : 'chevron-right'}></devtools-icon>
|
|
594
|
+
}}>${title}<devtools-icon class="chevron" .name=${isExpanded ? 'cross' : 'chevron-right'}></devtools-icon>
|
|
595
595
|
</devtools-button>
|
|
596
596
|
</div>
|
|
597
597
|
`;
|
|
@@ -761,6 +761,15 @@ async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promi
|
|
|
761
761
|
}
|
|
762
762
|
const styles = new ComputedStyle.ComputedStyleModel.ComputedStyle(domNodeForId, widgetData.data.computedStyles);
|
|
763
763
|
|
|
764
|
+
let filterText: RegExp|null = null;
|
|
765
|
+
try {
|
|
766
|
+
filterText = new RegExp(widgetData.data.properties.join('|'), 'i');
|
|
767
|
+
} catch {
|
|
768
|
+
// If the AI provides an invalid regex (e.g. "*"), we don't want to crash.
|
|
769
|
+
// We can just skip the widget in this case.
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
|
|
764
773
|
// clang-format off
|
|
765
774
|
const renderedWidget = html`<devtools-widget
|
|
766
775
|
class="computed-styles-widget" ${widget(Elements.ComputedStyleWidget.ComputedStyleWidget, {
|
|
@@ -769,7 +778,7 @@ async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promi
|
|
|
769
778
|
// This disables showing the nested traces and detailed information in the widget.
|
|
770
779
|
propertyTraces: null,
|
|
771
780
|
allowUserControl: false,
|
|
772
|
-
filterText
|
|
781
|
+
filterText,
|
|
773
782
|
enableNarrowViewResizing: false,
|
|
774
783
|
})}></devtools-widget>`;
|
|
775
784
|
// clang-format on
|
|
@@ -777,11 +786,19 @@ async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promi
|
|
|
777
786
|
return {
|
|
778
787
|
renderedWidget,
|
|
779
788
|
revealable: new Elements.ElementsPanel.NodeComputedStyles(domNodeForId),
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
789
|
+
// clang-format off
|
|
790
|
+
title: html`
|
|
791
|
+
<span class="computed-style-title-wrapper">
|
|
792
|
+
<span class="computed-style-title-prefix">Computed styles</span>
|
|
793
|
+
<span class="style-class-wrapper">
|
|
794
|
+
(<devtools-widget
|
|
795
|
+
${widget(PanelsCommon.DOMLinkifier.DOMNodeLink, {
|
|
796
|
+
node: domNodeForId,
|
|
797
|
+
})}
|
|
798
|
+
></devtools-widget>)
|
|
799
|
+
</span>
|
|
800
|
+
</span>`,
|
|
801
|
+
// clang-format on
|
|
785
802
|
};
|
|
786
803
|
}
|
|
787
804
|
|
|
@@ -804,12 +821,21 @@ async function makeStylePropertiesWidget(widgetData: StylePropertiesAiWidget): P
|
|
|
804
821
|
return null;
|
|
805
822
|
}
|
|
806
823
|
|
|
824
|
+
let filter: RegExp|null = null;
|
|
825
|
+
try {
|
|
826
|
+
filter = widgetData.data.selector ? new RegExp(widgetData.data.selector) : null;
|
|
827
|
+
} catch {
|
|
828
|
+
// If the AI provides an invalid regex (e.g. "*"), we don't want to crash.
|
|
829
|
+
// We can just skip the widget in this case.
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
|
|
807
833
|
// clang-format off
|
|
808
834
|
const renderedWidget = html`<devtools-widget
|
|
809
835
|
class="styling-preview-widget"
|
|
810
836
|
${widget(Elements.StandaloneStylesContainer.StandaloneStylesContainer, {
|
|
811
837
|
domNode: domNodeForId,
|
|
812
|
-
filter
|
|
838
|
+
filter,
|
|
813
839
|
})}>
|
|
814
840
|
</devtools-widget>`;
|
|
815
841
|
// clang-format on
|
|
@@ -1519,7 +1545,7 @@ async function makeTimelineRangeSummaryWidget(widgetData: TimelineRangeSummaryAi
|
|
|
1519
1545
|
eventsArray.sort((a, b) => a.ts - b.ts);
|
|
1520
1546
|
|
|
1521
1547
|
const thirdPartyTree = new Timeline.ThirdPartyTreeView.ThirdPartyTreeViewWidget();
|
|
1522
|
-
const mapper =
|
|
1548
|
+
const mapper = Trace.EntityMapper.EntityMapper.getOrCreate(parsedTrace);
|
|
1523
1549
|
thirdPartyTree.model = {selectedEvents: eventsArray, parsedTrace, entityMapper: mapper};
|
|
1524
1550
|
thirdPartyTree.activeSelection = Timeline.TimelineSelection.selectionFromRangeMicroSeconds(bounds.min, bounds.max);
|
|
1525
1551
|
thirdPartyTree.refreshTree(true);
|
|
@@ -1542,6 +1568,9 @@ async function makeTimelineRangeSummaryWidget(widgetData: TimelineRangeSummaryAi
|
|
|
1542
1568
|
entityMapper: thirdPartyTree.entityMapper(),
|
|
1543
1569
|
},
|
|
1544
1570
|
activeSelection: { bounds },
|
|
1571
|
+
onBottomUpButtonClicked: (node: Trace.Extras.TraceTree.Node|null) => {
|
|
1572
|
+
void Common.Revealer.reveal(new TimelineUtils.Helpers.RevealableBottomUpProfile(bounds, node ?? undefined));
|
|
1573
|
+
},
|
|
1545
1574
|
})}`,
|
|
1546
1575
|
} as TimelineComponents.TimelineRangeSummaryView.TimelineRangeSummaryViewData,
|
|
1547
1576
|
})}
|
|
@@ -456,6 +456,19 @@
|
|
|
456
456
|
white-space: nowrap; /* stop the titles going onto multiple lines */
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
+
/* This widget's title is some text + then a DOM node link, so it
|
|
460
|
+
* needs some extra styling */
|
|
461
|
+
.computed-style-title-wrapper {
|
|
462
|
+
display: flex;
|
|
463
|
+
align-items: center;
|
|
464
|
+
justify-content: flex-start;
|
|
465
|
+
gap: var(--sys-size-3);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.computed-style-title-prefix {
|
|
469
|
+
flex-shrink: 0;
|
|
470
|
+
}
|
|
471
|
+
|
|
459
472
|
.widget-reveal-container {
|
|
460
473
|
padding: 0;
|
|
461
474
|
background: none;
|
|
@@ -1031,6 +1031,14 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
|
1031
1031
|
}
|
|
1032
1032
|
}
|
|
1033
1033
|
|
|
1034
|
+
showStorageBucket(bucketInfo: Protocol.Storage.StorageBucketInfo): void {
|
|
1035
|
+
const bucketsModel = SDK.TargetManager.TargetManager.instance().primaryPageTarget()?.model(
|
|
1036
|
+
SDK.StorageBucketsModel.StorageBucketsModel);
|
|
1037
|
+
if (bucketsModel) {
|
|
1038
|
+
this.storageBucketsTreeElement?.getBucketTreeElement(bucketsModel, bucketInfo)?.revealAndSelect(true);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1034
1042
|
private onmousemove(event: MouseEvent): void {
|
|
1035
1043
|
const nodeUnderMouse = (event.target as Node);
|
|
1036
1044
|
if (!nodeUnderMouse) {
|
|
@@ -8,6 +8,7 @@ import type * as Platform from '../../core/platform/platform.js';
|
|
|
8
8
|
import {createIcon} from '../../ui/kit/kit.js';
|
|
9
9
|
|
|
10
10
|
import {ApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';
|
|
11
|
+
import {CrashReportContextView} from './CrashReportContextView.js';
|
|
11
12
|
import {ReportingApiView} from './ReportingApiView.js';
|
|
12
13
|
import type {ResourcesPanel} from './ResourcesPanel.js';
|
|
13
14
|
|
|
@@ -16,19 +17,32 @@ const UIStrings = {
|
|
|
16
17
|
* @description Label for an item in the Application Panel Sidebar of the Application panel
|
|
17
18
|
*/
|
|
18
19
|
reportingApi: 'Reporting API',
|
|
20
|
+
/**
|
|
21
|
+
* @description Label for the Crash Report Context child item in the Reporting API section.
|
|
22
|
+
*/
|
|
23
|
+
crashReportContext: 'Crash Report Context',
|
|
19
24
|
} as const;
|
|
20
25
|
const str_ = i18n.i18n.registerUIStrings('panels/application/ReportingApiTreeElement.ts', UIStrings);
|
|
21
26
|
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
22
27
|
|
|
23
28
|
export class ReportingApiTreeElement extends ApplicationPanelTreeElement {
|
|
24
29
|
private view?: ReportingApiView;
|
|
30
|
+
#childrenInitialized = false;
|
|
25
31
|
|
|
26
32
|
constructor(storagePanel: ResourcesPanel) {
|
|
27
|
-
super(storagePanel, i18nString(UIStrings.reportingApi),
|
|
33
|
+
super(storagePanel, i18nString(UIStrings.reportingApi), true, 'reporting-api');
|
|
28
34
|
const icon = createIcon('document');
|
|
29
35
|
this.setLeadingIcons([icon]);
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
override onattach(): void {
|
|
39
|
+
super.onattach();
|
|
40
|
+
if (!this.#childrenInitialized) {
|
|
41
|
+
this.#childrenInitialized = true;
|
|
42
|
+
this.appendChild(new CrashReportContextTreeElement(this.resourcesPanel));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
override get itemURL(): Platform.DevToolsPath.UrlString {
|
|
33
47
|
return 'reportingApi://' as Platform.DevToolsPath.UrlString;
|
|
34
48
|
}
|
|
@@ -43,3 +57,28 @@ export class ReportingApiTreeElement extends ApplicationPanelTreeElement {
|
|
|
43
57
|
return false;
|
|
44
58
|
}
|
|
45
59
|
}
|
|
60
|
+
|
|
61
|
+
export class CrashReportContextTreeElement extends ApplicationPanelTreeElement {
|
|
62
|
+
private view?: CrashReportContextView;
|
|
63
|
+
|
|
64
|
+
constructor(storagePanel: ResourcesPanel) {
|
|
65
|
+
super(storagePanel, i18nString(UIStrings.crashReportContext), false, 'crash-report-context');
|
|
66
|
+
const icon = createIcon('table');
|
|
67
|
+
this.setLeadingIcons([icon]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override get itemURL(): Platform.DevToolsPath.UrlString {
|
|
71
|
+
return 'reportingApi://crash-report-context' as Platform.DevToolsPath.UrlString;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override onselect(selectedByUser?: boolean): boolean {
|
|
75
|
+
super.onselect(selectedByUser);
|
|
76
|
+
if (!this.view) {
|
|
77
|
+
this.view = new CrashReportContextView();
|
|
78
|
+
}
|
|
79
|
+
this.view.requestUpdate();
|
|
80
|
+
this.showView(this.view);
|
|
81
|
+
Host.userMetrics.panelShown('crash-report-context');
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -12,6 +12,7 @@ import * as UI from '../../ui/legacy/legacy.js';
|
|
|
12
12
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
13
13
|
|
|
14
14
|
import {ApplicationPanelSidebar, StorageCategoryView} from './ApplicationPanelSidebar.js';
|
|
15
|
+
import type {StorageMetadataView} from './components/components.js';
|
|
15
16
|
import {CookieItemsView} from './CookieItemsView.js';
|
|
16
17
|
import type {DeviceBoundSessionsModel} from './DeviceBoundSessionsModel.js';
|
|
17
18
|
import {DeviceBoundSessionsView} from './DeviceBoundSessionsView.js';
|
|
@@ -260,3 +261,10 @@ export class AttemptViewWithFilterRevealer implements
|
|
|
260
261
|
sidebar.showPreloadingAttemptViewWithFilter(filter);
|
|
261
262
|
}
|
|
262
263
|
}
|
|
264
|
+
|
|
265
|
+
export class StorageBucketRevealer implements Common.Revealer.Revealer<StorageMetadataView.StorageBucketRevealInfo> {
|
|
266
|
+
async reveal(revealInfo: StorageMetadataView.StorageBucketRevealInfo): Promise<void> {
|
|
267
|
+
const sidebar = await ResourcesPanel.showAndGetSidebar();
|
|
268
|
+
sidebar.showStorageBucket(revealInfo.bucketInfo);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -133,7 +133,7 @@ export class ServiceWorkerCacheView extends UI.View.SimpleView {
|
|
|
133
133
|
.model(SDK.StorageBucketsModel.StorageBucketsModel)
|
|
134
134
|
?.getBucketByName(cache.storageBucket.storageKey, cache.storageBucket.name);
|
|
135
135
|
|
|
136
|
-
this.metadataView.setShowOnlyBucket(
|
|
136
|
+
this.metadataView.setShowOnlyBucket(true);
|
|
137
137
|
|
|
138
138
|
if (bucketInfo) {
|
|
139
139
|
this.metadataView.setStorageBucket(bucketInfo);
|
|
@@ -19,6 +19,7 @@ import * as Adorners from '../../ui/components/adorners/adorners.js';
|
|
|
19
19
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
20
20
|
import type * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
|
21
21
|
import type * as NodeText from '../../ui/components/node_text/node_text.js';
|
|
22
|
+
import * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';
|
|
22
23
|
import * as Components from '../../ui/legacy/components/utils/utils.js';
|
|
23
24
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
24
25
|
import {
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
html,
|
|
27
28
|
nothing,
|
|
28
29
|
render,
|
|
30
|
+
type TemplateResult,
|
|
29
31
|
} from '../../ui/lit/lit.js';
|
|
30
32
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
31
33
|
|
|
@@ -299,6 +301,23 @@ function getIconGroupsFromStats(toolStats: ReturnType<typeof calculateToolStats>
|
|
|
299
301
|
return groups;
|
|
300
302
|
}
|
|
301
303
|
|
|
304
|
+
export function parsePayload(payload?: unknown): {
|
|
305
|
+
valueObject: unknown,
|
|
306
|
+
valueString: string|undefined,
|
|
307
|
+
} {
|
|
308
|
+
if (payload === undefined) {
|
|
309
|
+
return {valueObject: undefined, valueString: undefined};
|
|
310
|
+
}
|
|
311
|
+
if (typeof payload === 'string') {
|
|
312
|
+
try {
|
|
313
|
+
return {valueObject: JSON.parse(payload), valueString: undefined};
|
|
314
|
+
} catch {
|
|
315
|
+
return {valueObject: undefined, valueString: payload};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {valueObject: payload, valueString: undefined};
|
|
319
|
+
}
|
|
320
|
+
|
|
302
321
|
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
303
322
|
const tools = input.tools;
|
|
304
323
|
const stats = calculateToolStats(input.toolCalls);
|
|
@@ -393,11 +412,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
393
412
|
<span>${statusString(call)}</span>
|
|
394
413
|
</div>
|
|
395
414
|
</td>
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
415
|
+
${!input.selectedCall ? html`
|
|
416
|
+
<td>${call.input}</td>
|
|
417
|
+
<td>${call.result?.output ? JSON.stringify(call.result.output)
|
|
399
418
|
: call.result?.errorText ?? ''}</td>
|
|
400
|
-
|
|
419
|
+
` : nothing}
|
|
401
420
|
</tr>
|
|
402
421
|
`)}
|
|
403
422
|
</table>`}>
|
|
@@ -418,6 +437,16 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
418
437
|
title=${i18nString(UIStrings.toolDetails)}
|
|
419
438
|
${widget(ToolDetailsWidget, {tool: input.selectedCall?.tool})}>
|
|
420
439
|
</devtools-widget>
|
|
440
|
+
<devtools-widget
|
|
441
|
+
id="inputs"
|
|
442
|
+
title=${i18nString(UIStrings.input)}
|
|
443
|
+
${widget(PayloadWidget, parsePayload(input.selectedCall?.input))}>
|
|
444
|
+
</devtools-widget>
|
|
445
|
+
<devtools-widget
|
|
446
|
+
id="outputs"
|
|
447
|
+
title=${i18nString(UIStrings.output)}
|
|
448
|
+
${widget(PayloadWidget, parsePayload(input.selectedCall?.result?.output))}>
|
|
449
|
+
</devtools-widget>
|
|
421
450
|
</devtools-tabbed-pane>
|
|
422
451
|
</div>
|
|
423
452
|
</devtools-split-view>
|
|
@@ -653,6 +682,95 @@ export class WebMCPView extends UI.Widget.VBox {
|
|
|
653
682
|
this.#view(input, {}, this.contentElement);
|
|
654
683
|
}
|
|
655
684
|
}
|
|
685
|
+
export interface PayloadViewInput {
|
|
686
|
+
valueObject?: unknown;
|
|
687
|
+
valueString?: string;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, target: HTMLElement): void => {
|
|
691
|
+
if (input.valueObject === undefined && input.valueString === undefined) {
|
|
692
|
+
render(nothing, target);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
const isParsable = input.valueObject !== undefined;
|
|
696
|
+
|
|
697
|
+
const createPayload = (parsedInput: unknown): TemplateResult => {
|
|
698
|
+
const object = new SDK.RemoteObject.LocalJSONObject(parsedInput);
|
|
699
|
+
const section =
|
|
700
|
+
new ObjectUI.ObjectPropertiesSection.RootElement(new ObjectUI.ObjectPropertiesSection.ObjectTree(object, {
|
|
701
|
+
readOnly: true,
|
|
702
|
+
propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
|
|
703
|
+
}));
|
|
704
|
+
section.title = document.createTextNode(object.description);
|
|
705
|
+
section.listItemElement.classList.add('source-code', 'object-properties-section');
|
|
706
|
+
section.childrenListElement.classList.add('source-code', 'object-properties-section');
|
|
707
|
+
section.expand();
|
|
708
|
+
return html`<devtools-tree .template=${html`
|
|
709
|
+
<style>${ObjectUI.ObjectPropertiesSection.objectValueStyles}</style>
|
|
710
|
+
<style>${ObjectUI.ObjectPropertiesSection.objectPropertiesSectionStyles}</style>
|
|
711
|
+
<ul role="tree">
|
|
712
|
+
<devtools-tree-wrapper .treeElement=${section}></devtools-tree-wrapper>
|
|
713
|
+
</ul>
|
|
714
|
+
`}></devtools-tree>`;
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
const createSourceText = (text: string): TemplateResult => html`<div class="payload-value source-code">${text}</div>`;
|
|
718
|
+
|
|
719
|
+
render(
|
|
720
|
+
html`
|
|
721
|
+
<style>${webMCPViewStyles}</style>
|
|
722
|
+
<div class="call-payload-view">
|
|
723
|
+
<div class="call-payload-content">
|
|
724
|
+
${
|
|
725
|
+
isParsable ? createPayload(input.valueObject) :
|
|
726
|
+
(input.valueString !== undefined ? createSourceText(input.valueString) : nothing)}
|
|
727
|
+
</div>
|
|
728
|
+
</div>
|
|
729
|
+
`,
|
|
730
|
+
target);
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
export class PayloadWidget extends UI.Widget.Widget {
|
|
734
|
+
#valueObject?: unknown;
|
|
735
|
+
#valueString?: string;
|
|
736
|
+
#view: typeof PAYLOAD_DEFAULT_VIEW;
|
|
737
|
+
|
|
738
|
+
constructor(element?: HTMLElement, view = PAYLOAD_DEFAULT_VIEW) {
|
|
739
|
+
super(element);
|
|
740
|
+
this.#view = view;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
set valueObject(valueObject: unknown) {
|
|
744
|
+
this.#valueObject = valueObject;
|
|
745
|
+
this.requestUpdate();
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
get valueObject(): unknown {
|
|
749
|
+
return this.#valueObject;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
set valueString(valueString: string|undefined) {
|
|
753
|
+
this.#valueString = valueString;
|
|
754
|
+
this.requestUpdate();
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
get valueString(): string|undefined {
|
|
758
|
+
return this.#valueString;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
override wasShown(): void {
|
|
762
|
+
super.wasShown();
|
|
763
|
+
this.requestUpdate();
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
override performUpdate(): void {
|
|
767
|
+
const input: PayloadViewInput = {
|
|
768
|
+
valueObject: this.#valueObject,
|
|
769
|
+
valueString: this.#valueString,
|
|
770
|
+
};
|
|
771
|
+
this.#view(input, {}, this.contentElement);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
656
774
|
|
|
657
775
|
export interface ToolDetailsViewInput {
|
|
658
776
|
tool: WebMCP.WebMCPModel.Tool|null|undefined;
|
|
@@ -174,3 +174,14 @@ Common.Revealer.registerRevealer({
|
|
|
174
174
|
return new Resources.ResourcesPanel.AttemptViewWithFilterRevealer();
|
|
175
175
|
},
|
|
176
176
|
});
|
|
177
|
+
|
|
178
|
+
Common.Revealer.registerRevealer({
|
|
179
|
+
contextTypes() {
|
|
180
|
+
return maybeRetrieveContextTypes(Resources => [Resources.Components.StorageMetadataView.StorageBucketRevealInfo]);
|
|
181
|
+
},
|
|
182
|
+
destination: Common.Revealer.RevealerDestination.APPLICATION_PANEL,
|
|
183
|
+
async loadRevealer() {
|
|
184
|
+
const Resources = await loadResourcesModule();
|
|
185
|
+
return new Resources.ResourcesPanel.StorageBucketRevealer();
|
|
186
|
+
},
|
|
187
|
+
});
|
|
@@ -27,6 +27,7 @@ import * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';
|
|
|
27
27
|
import * as OriginTrialTreeView from './OriginTrialTreeView.js';
|
|
28
28
|
import * as PreloadingView from './preloading/PreloadingView.js';
|
|
29
29
|
import * as PreloadingTreeElement from './PreloadingTreeElement.js';
|
|
30
|
+
import * as ReportingApiTreeElement from './ReportingApiTreeElement.js';
|
|
30
31
|
import * as ReportingApiView from './ReportingApiView.js';
|
|
31
32
|
import * as ResourcesPanel from './ResourcesPanel.js';
|
|
32
33
|
import * as ServiceWorkerCacheViews from './ServiceWorkerCacheViews.js';
|
|
@@ -44,6 +45,7 @@ import * as TrustTokensTreeElement from './TrustTokensTreeElement.js';
|
|
|
44
45
|
import * as WebMCPTreeElement from './WebMCPTreeElement.js';
|
|
45
46
|
import * as WebMCPView from './WebMCPView.js';
|
|
46
47
|
|
|
48
|
+
export * as Components from './components/components.js';
|
|
47
49
|
export {
|
|
48
50
|
ApplicationPanelSidebar,
|
|
49
51
|
AppManifestView,
|
|
@@ -70,6 +72,7 @@ export {
|
|
|
70
72
|
OriginTrialTreeView,
|
|
71
73
|
PreloadingTreeElement,
|
|
72
74
|
PreloadingView,
|
|
75
|
+
ReportingApiTreeElement,
|
|
73
76
|
ReportingApiView,
|
|
74
77
|
ResourcesPanel,
|
|
75
78
|
ServiceWorkerCacheViews,
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
/* eslint-disable @devtools/no-lit-render-outside-of-view */
|
|
5
5
|
|
|
6
6
|
import '../../../ui/components/report_view/report_view.js';
|
|
7
|
+
import '../../../ui/kit/kit.js';
|
|
7
8
|
|
|
9
|
+
import * as Common from '../../../core/common/common.js';
|
|
8
10
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
9
11
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
10
12
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
@@ -13,6 +15,7 @@ import * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wra
|
|
|
13
15
|
import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
|
|
14
16
|
import * as UI from '../../../ui/legacy/legacy.js';
|
|
15
17
|
import {html, type LitTemplate, nothing, render, type TemplateResult} from '../../../ui/lit/lit.js';
|
|
18
|
+
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
16
19
|
|
|
17
20
|
import storageMetadataViewStyle from './storageMetadataView.css.js';
|
|
18
21
|
|
|
@@ -113,12 +116,17 @@ const UIStrings = {
|
|
|
113
116
|
const str_ = i18n.i18n.registerUIStrings('panels/application/components/StorageMetadataView.ts', UIStrings);
|
|
114
117
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
115
118
|
|
|
119
|
+
export class StorageBucketRevealInfo {
|
|
120
|
+
constructor(public bucketInfo: Protocol.Storage.StorageBucketInfo) {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
116
124
|
export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableComponent {
|
|
117
125
|
readonly #shadow = this.attachShadow({mode: 'open'});
|
|
118
126
|
#storageBucketsModel?: SDK.StorageBucketsModel.StorageBucketsModel;
|
|
119
127
|
#storageKey: SDK.StorageKeyManager.StorageKey|null = null;
|
|
120
128
|
#storageBucket: Protocol.Storage.StorageBucketInfo|null = null;
|
|
121
|
-
#showOnlyBucket =
|
|
129
|
+
#showOnlyBucket = false;
|
|
122
130
|
|
|
123
131
|
setStorageKey(storageKey: string): void {
|
|
124
132
|
this.#storageKey = SDK.StorageKeyManager.parseStorageKey(storageKey);
|
|
@@ -220,20 +228,36 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
|
220
228
|
const {bucket: {name}, persistent, durability, quota} = this.#storageBucket;
|
|
221
229
|
const isDefault = !name;
|
|
222
230
|
|
|
223
|
-
|
|
231
|
+
const renderBucketName = (): TemplateResult => {
|
|
224
232
|
if (isDefault) {
|
|
225
|
-
return html
|
|
226
|
-
${this.key(i18nString(UIStrings.bucketName))}
|
|
227
|
-
${this.value(html`<span class="default-bucket">default</span>`)}`;
|
|
233
|
+
return html`<span class="default-bucket">${i18nString(UIStrings.defaultBucket)}</span>`;
|
|
228
234
|
}
|
|
235
|
+
if (!this.#showOnlyBucket) {
|
|
236
|
+
return html`${name}`;
|
|
237
|
+
}
|
|
238
|
+
const revealBucket = (e: Event): void => {
|
|
239
|
+
e.preventDefault();
|
|
240
|
+
void Common.Revealer.reveal(
|
|
241
|
+
new StorageBucketRevealInfo(this.#storageBucket as Protocol.Storage.StorageBucketInfo));
|
|
242
|
+
};
|
|
243
|
+
return html`<devtools-link
|
|
244
|
+
@click=${revealBucket}
|
|
245
|
+
title=${name}
|
|
246
|
+
jslog=${VisualLogging.action('storage-bucket').track({
|
|
247
|
+
click: true
|
|
248
|
+
})}
|
|
249
|
+
>${name}</devtools-link>`;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
if (this.#showOnlyBucket) {
|
|
229
253
|
return html`
|
|
230
254
|
${this.key(i18nString(UIStrings.bucketName))}
|
|
231
|
-
${this.value(
|
|
255
|
+
${this.value(renderBucketName())}`;
|
|
232
256
|
}
|
|
233
257
|
// clang-format off
|
|
234
258
|
return html`
|
|
235
259
|
${this.key(i18nString(UIStrings.bucketName))}
|
|
236
|
-
${this.value(
|
|
260
|
+
${this.value(renderBucketName())}
|
|
237
261
|
${this.key(i18nString(UIStrings.persistent))}
|
|
238
262
|
${this.value(persistent ? i18nString(UIStrings.yes) : i18nString(UIStrings.no))}
|
|
239
263
|
${this.key(i18nString(UIStrings.durability))}
|
|
@@ -54,6 +54,10 @@ const UIStrings = {
|
|
|
54
54
|
* @description Text in details
|
|
55
55
|
*/
|
|
56
56
|
detailsTargetHint: 'Target hint',
|
|
57
|
+
/**
|
|
58
|
+
* @description Text in details
|
|
59
|
+
*/
|
|
60
|
+
detailsFormSubmission: 'Form submission',
|
|
57
61
|
/**
|
|
58
62
|
* @description Text in details
|
|
59
63
|
*/
|
|
@@ -62,6 +66,14 @@ const UIStrings = {
|
|
|
62
66
|
* @description Header of rule set
|
|
63
67
|
*/
|
|
64
68
|
detailsRuleSet: 'Rule set',
|
|
69
|
+
/**
|
|
70
|
+
* @description Text indicating that the preloading field is true.
|
|
71
|
+
*/
|
|
72
|
+
yes: 'Yes',
|
|
73
|
+
/**
|
|
74
|
+
* @description Text indicating that the preloading field is false.
|
|
75
|
+
*/
|
|
76
|
+
no: 'No',
|
|
65
77
|
/**
|
|
66
78
|
* @description Description: status
|
|
67
79
|
*/
|
|
@@ -202,6 +214,7 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
|
|
|
202
214
|
${this.#action(isFallbackToPrefetch)}
|
|
203
215
|
${this.#status(isFallbackToPrefetch)}
|
|
204
216
|
${this.#targetHint()}
|
|
217
|
+
${this.#formSubmission()}
|
|
205
218
|
${this.#maybePrefetchFailureReason()}
|
|
206
219
|
${this.#maybePrerenderFailureReason()}
|
|
207
220
|
|
|
@@ -381,6 +394,22 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
|
|
|
381
394
|
`;
|
|
382
395
|
}
|
|
383
396
|
|
|
397
|
+
#formSubmission(): Lit.LitTemplate {
|
|
398
|
+
assertNotNullOrUndefined(this.#data);
|
|
399
|
+
const attempt = this.#data.pipeline.getOriginallyTriggered();
|
|
400
|
+
const hasFormSubmission = attempt.key.formSubmission !== undefined;
|
|
401
|
+
if (!hasFormSubmission || !this.#isPrerenderLike(attempt.action)) {
|
|
402
|
+
return Lit.nothing;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return html`
|
|
406
|
+
<devtools-report-key>${i18nString(UIStrings.detailsFormSubmission)}</devtools-report-key>
|
|
407
|
+
<devtools-report-value>
|
|
408
|
+
${attempt.key.formSubmission ? i18nString(UIStrings.yes) : i18nString(UIStrings.no)}
|
|
409
|
+
</devtools-report-value>
|
|
410
|
+
`;
|
|
411
|
+
}
|
|
412
|
+
|
|
384
413
|
#maybePrerenderFailureReason(): Lit.LitTemplate {
|
|
385
414
|
assertNotNullOrUndefined(this.#data);
|
|
386
415
|
const attempt = this.#data.pipeline.getOriginallyTriggered();
|
|
@@ -198,4 +198,16 @@
|
|
|
198
198
|
flex: auto;
|
|
199
199
|
border-bottom: 1px solid var(--sys-color-divider);
|
|
200
200
|
}
|
|
201
|
+
|
|
202
|
+
.call-payload-view {
|
|
203
|
+
display: flex;
|
|
204
|
+
flex-direction: column;
|
|
205
|
+
height: 100%;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.call-payload-content {
|
|
209
|
+
padding: var(--sys-size-5);
|
|
210
|
+
flex: auto;
|
|
211
|
+
overflow: auto;
|
|
212
|
+
}
|
|
201
213
|
}
|
|
@@ -2850,6 +2850,10 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2850
2850
|
}
|
|
2851
2851
|
|
|
2852
2852
|
updateDecorations(): void {
|
|
2853
|
+
// Important to keep the entire tree node row as a clickable area for that
|
|
2854
|
+
// node.
|
|
2855
|
+
this.listItemElement.style.setProperty('--indent', this.computeLeftIndent() + 'px');
|
|
2856
|
+
|
|
2853
2857
|
if (this.isClosingTag()) {
|
|
2854
2858
|
return;
|
|
2855
2859
|
}
|