chrome-devtools-frontend 1.0.1611390 → 1.0.1613465
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/Images/src/flowsheet.svg +1 -0
- package/front_end/core/common/Color.ts +3 -2
- package/front_end/core/host/AidaClientTypes.ts +5 -0
- package/front_end/core/host/AidaGcaTranslation.ts +1 -0
- package/front_end/core/platform/StringUtilities.ts +5 -0
- package/front_end/core/sdk/NetworkManager.ts +7 -0
- package/front_end/core/sdk/ResourceTreeModel.ts +2 -1
- package/front_end/core/sdk/Target.ts +1 -3
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.js +4 -0
- package/front_end/generated/protocol.ts +12 -10
- package/front_end/models/greendev/Prototypes.ts +7 -4
- package/front_end/models/har/HARFormat.ts +30 -0
- package/front_end/models/har/Importer.ts +12 -1
- package/front_end/models/har/Log.ts +28 -0
- package/front_end/models/web_mcp/WebMCPModel.ts +73 -18
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +64 -25
- package/front_end/panels/ai_assistance/PatchWidget.ts +7 -23
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +3 -3
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +7 -0
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +21 -11
- package/front_end/panels/ai_assistance/components/ChatView.ts +4 -0
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +20 -10
- package/front_end/panels/ai_assistance/components/OptInChangeDialog.ts +179 -0
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +6 -2
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +1 -1
- package/front_end/panels/ai_assistance/components/optInChangeDialog.css +95 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +19 -18
- package/front_end/panels/application/CookieItemsView.ts +3 -2
- package/front_end/panels/application/WebMCPView.ts +97 -6
- package/front_end/panels/application/webMCPView.css +7 -1
- package/front_end/panels/changes/ChangesView.ts +0 -12
- package/front_end/panels/common/common.ts +0 -1
- package/front_end/panels/console/ConsolePrompt.ts +2 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -1
- package/front_end/panels/elements/elements-meta.ts +14 -0
- package/front_end/panels/network/NetworkLogView.ts +58 -28
- package/front_end/panels/recorder/RecorderController.ts +4 -4
- package/front_end/panels/settings/AISettingsTab.ts +39 -3
- package/front_end/panels/settings/SettingsScreen.ts +2 -2
- package/front_end/panels/sources/BreakpointEditDialog.ts +6 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +6 -0
- package/front_end/ui/legacy/SplitWidget.ts +9 -6
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +3 -3
- package/front_end/ui/legacy/components/source_frame/FontView.ts +101 -88
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +10 -0
- package/mcp/mcp.ts +1 -1
- package/package.json +1 -1
- package/front_end/panels/common/CopyChangesToPrompt.ts +0 -233
|
@@ -45,6 +45,10 @@ const UIStrings = {
|
|
|
45
45
|
* @description Title for the button that hides the walkthrough when there are widgets in the walkthrough.
|
|
46
46
|
*/
|
|
47
47
|
hideAgentWalkthrough: 'Hide agent walkthrough',
|
|
48
|
+
/**
|
|
49
|
+
* @description Aria label for the spinner to be read by screen reader when a step is in progress.
|
|
50
|
+
*/
|
|
51
|
+
inProgress: 'In progress',
|
|
48
52
|
} as const;
|
|
49
53
|
const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/components/WalkthroughView.ts', UIStrings);
|
|
50
54
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -118,7 +122,7 @@ function renderInlineWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate,
|
|
|
118
122
|
<div class="inline-wrapper" ?data-open=${input.isExpanded}>
|
|
119
123
|
<span class="inline-icon">
|
|
120
124
|
${input.isLoading ?
|
|
121
|
-
html`<devtools-spinner></devtools-spinner>` :
|
|
125
|
+
html`<devtools-spinner aria-label=${lockedString(UIStrings.inProgress)}></devtools-spinner>` :
|
|
122
126
|
html`<devtools-icon name=${icon}></devtools-icon>`
|
|
123
127
|
}
|
|
124
128
|
</span>
|
|
@@ -149,7 +153,7 @@ function renderSidebarWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate
|
|
|
149
153
|
return html`
|
|
150
154
|
<div class="walkthrough-view">
|
|
151
155
|
<div class="walkthrough-header">
|
|
152
|
-
<
|
|
156
|
+
<h2 class="walkthrough-title">${i18nString(UIStrings.title)}</h2>
|
|
153
157
|
<devtools-button
|
|
154
158
|
.data=${{
|
|
155
159
|
variant: Buttons.Button.Variant.TOOLBAR,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 The Chromium Authors
|
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@scope to (devtools-widget > *) {
|
|
8
|
+
:scope {
|
|
9
|
+
width: 100%;
|
|
10
|
+
box-shadow: none;
|
|
11
|
+
padding: var(--sys-size-8);
|
|
12
|
+
background-color: var(--sys-color-surface);
|
|
13
|
+
border-radius: var(--sys-shape-corner-medium);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.opt-in-change-dialog {
|
|
17
|
+
width: var(--sys-size-33);
|
|
18
|
+
max-width: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
header {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: row;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: var(--sys-size-8);
|
|
26
|
+
margin-bottom: var(--sys-size-8);
|
|
27
|
+
|
|
28
|
+
h2 {
|
|
29
|
+
margin: 0;
|
|
30
|
+
color: var(--sys-color-on-surface);
|
|
31
|
+
font: var(--sys-typescale-headline5);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.header-icon-container {
|
|
35
|
+
background: linear-gradient(
|
|
36
|
+
135deg,
|
|
37
|
+
var(--sys-color-gradient-primary),
|
|
38
|
+
var(--sys-color-gradient-tertiary)
|
|
39
|
+
);
|
|
40
|
+
border-radius: var(--sys-size-4);
|
|
41
|
+
height: var(--sys-size-14);
|
|
42
|
+
width: var(--sys-size-14);
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
|
|
47
|
+
devtools-icon {
|
|
48
|
+
width: var(--sys-size-9);
|
|
49
|
+
height: var(--sys-size-9);
|
|
50
|
+
color: var(--sys-color-on-primary);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
main {
|
|
56
|
+
background-color: var(--sys-color-surface4);
|
|
57
|
+
border-radius: var(--sys-shape-corner-medium-small);
|
|
58
|
+
padding: var(--sys-size-8);
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
gap: var(--sys-size-6);
|
|
62
|
+
margin-bottom: var(--sys-size-8);
|
|
63
|
+
|
|
64
|
+
.item {
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: row;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: var(--sys-size-8);
|
|
69
|
+
|
|
70
|
+
devtools-icon {
|
|
71
|
+
width: var(--sys-size-8);
|
|
72
|
+
height: var(--sys-size-8);
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
color: var(--sys-color-on-surface-subtle);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.text {
|
|
78
|
+
font: var(--sys-typescale-body4);
|
|
79
|
+
color: var(--sys-color-on-surface);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
footer {
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-direction: row;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: flex-end;
|
|
89
|
+
|
|
90
|
+
.right-buttons {
|
|
91
|
+
display: flex;
|
|
92
|
+
gap: var(--sys-size-5);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
.inline-wrapper {
|
|
101
101
|
display: flex;
|
|
102
|
-
align-items:
|
|
102
|
+
align-items: flex-start;
|
|
103
103
|
gap: var(--sys-size-2);
|
|
104
104
|
justify-content: flex-start;
|
|
105
105
|
|
|
@@ -118,21 +118,9 @@
|
|
|
118
118
|
&[open] {
|
|
119
119
|
border-radius: var(--sys-size-5);
|
|
120
120
|
width: auto;
|
|
121
|
-
background-color: var(--sys-color-
|
|
121
|
+
background-color: var(--sys-color-surface2);
|
|
122
122
|
margin-left: calc(var(--sys-size-6) / 2);
|
|
123
123
|
flex-grow: 1;
|
|
124
|
-
|
|
125
|
-
> summary {
|
|
126
|
-
border-radius: var(--sys-shape-corner-medium-small);
|
|
127
|
-
border-bottom-right-radius: 0;
|
|
128
|
-
border-bottom-left-radius: 0;
|
|
129
|
-
background: var(--sys-color-surface5);
|
|
130
|
-
color: var(--sys-color-on-surface);
|
|
131
|
-
|
|
132
|
-
&[data-has-widgets] {
|
|
133
|
-
margin-left: 0;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
124
|
}
|
|
137
125
|
}
|
|
138
126
|
|
|
@@ -177,6 +165,23 @@
|
|
|
177
165
|
}
|
|
178
166
|
}
|
|
179
167
|
|
|
168
|
+
.walkthrough-inline[open] > summary {
|
|
169
|
+
border-radius: var(--sys-shape-corner-medium-small);
|
|
170
|
+
border-bottom-right-radius: 0;
|
|
171
|
+
border-bottom-left-radius: 0;
|
|
172
|
+
background: var(--sys-color-surface5);
|
|
173
|
+
color: var(--sys-color-on-surface);
|
|
174
|
+
|
|
175
|
+
&[data-has-widgets] {
|
|
176
|
+
margin-left: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
> devtools-icon[name='chevron-right'] {
|
|
180
|
+
transform: rotate(270deg);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
180
185
|
.walkthrough-inline > summary::-webkit-details-marker {
|
|
181
186
|
display: none;
|
|
182
187
|
}
|
|
@@ -201,8 +206,4 @@
|
|
|
201
206
|
.walkthrough-inline .step {
|
|
202
207
|
background-color: var(--sys-color-surface5);
|
|
203
208
|
}
|
|
204
|
-
|
|
205
|
-
.walkthrough-inline[open] > summary > devtools-icon[name='chevron-right'] {
|
|
206
|
-
transform: rotate(270deg);
|
|
207
|
-
}
|
|
208
209
|
}
|
|
@@ -375,9 +375,10 @@ export class CookieItemsView extends UI.Widget.VBox {
|
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
deleteSelectedItem(): void {
|
|
378
|
-
|
|
378
|
+
const cookie = this.selectedCookie;
|
|
379
|
+
if (cookie) {
|
|
379
380
|
this.showPreview(null);
|
|
380
|
-
void this.model.deleteCookie(
|
|
381
|
+
void this.model.deleteCookie(cookie);
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
384
|
|
|
@@ -433,19 +433,23 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
433
433
|
@click=${() => input.onCallSelect(null)}
|
|
434
434
|
></devtools-button>
|
|
435
435
|
<devtools-widget
|
|
436
|
-
id="details"
|
|
436
|
+
id="webmcp.tool-details"
|
|
437
437
|
title=${i18nString(UIStrings.toolDetails)}
|
|
438
438
|
${widget(ToolDetailsWidget, {tool: input.selectedCall?.tool})}>
|
|
439
439
|
</devtools-widget>
|
|
440
440
|
<devtools-widget
|
|
441
|
-
id="inputs"
|
|
441
|
+
id="webmcp.call-inputs"
|
|
442
442
|
title=${i18nString(UIStrings.input)}
|
|
443
443
|
${widget(PayloadWidget, parsePayload(input.selectedCall?.input))}>
|
|
444
444
|
</devtools-widget>
|
|
445
445
|
<devtools-widget
|
|
446
|
-
id="outputs"
|
|
446
|
+
id="webmcp.call-outputs"
|
|
447
447
|
title=${i18nString(UIStrings.output)}
|
|
448
|
-
${widget(PayloadWidget,
|
|
448
|
+
${widget(PayloadWidget, {
|
|
449
|
+
valueObject: input.selectedCall?.result?.output,
|
|
450
|
+
errorText: input.selectedCall?.result?.errorText,
|
|
451
|
+
exceptionDetails: input.selectedCall?.result?.exceptionDetails,
|
|
452
|
+
})}>
|
|
449
453
|
</devtools-widget>
|
|
450
454
|
</devtools-tabbed-pane>
|
|
451
455
|
</div>
|
|
@@ -685,10 +689,12 @@ export class WebMCPView extends UI.Widget.VBox {
|
|
|
685
689
|
export interface PayloadViewInput {
|
|
686
690
|
valueObject?: unknown;
|
|
687
691
|
valueString?: string;
|
|
692
|
+
errorText?: string;
|
|
693
|
+
exceptionDetails?: WebMCP.WebMCPModel.ExceptionDetails;
|
|
688
694
|
}
|
|
689
695
|
|
|
690
696
|
export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, target: HTMLElement): void => {
|
|
691
|
-
if (input.valueObject
|
|
697
|
+
if (!input.valueObject && !input.valueString && !input.errorText && !input.exceptionDetails) {
|
|
692
698
|
render(nothing, target);
|
|
693
699
|
return;
|
|
694
700
|
}
|
|
@@ -715,6 +721,52 @@ export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, ta
|
|
|
715
721
|
};
|
|
716
722
|
|
|
717
723
|
const createSourceText = (text: string): TemplateResult => html`<div class="payload-value source-code">${text}</div>`;
|
|
724
|
+
const createErrorText = (text: string): TemplateResult =>
|
|
725
|
+
html`<div class="payload-value source-code error-text">${text}</div>`;
|
|
726
|
+
|
|
727
|
+
const createException = (
|
|
728
|
+
details: WebMCP.WebMCPModel.ExceptionDetails,
|
|
729
|
+
linkifier: Components.Linkifier.Linkifier = new Components.Linkifier.Linkifier(),
|
|
730
|
+
): TemplateResult => {
|
|
731
|
+
const renderFrame = (
|
|
732
|
+
frame: StackTrace.ErrorStackParser.ParsedErrorFrame,
|
|
733
|
+
index: number,
|
|
734
|
+
array: StackTrace.ErrorStackParser.ParsedErrorFrame[],
|
|
735
|
+
): TemplateResult => {
|
|
736
|
+
const newline = index < array.length - 1 ? '\n' : '';
|
|
737
|
+
const {line, link, isCallFrame} = frame;
|
|
738
|
+
|
|
739
|
+
if (!isCallFrame) {
|
|
740
|
+
return html`<span>${line}${newline}</span>`;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (!link) {
|
|
744
|
+
return html`<span class="formatted-builtin-stack-frame">${line}${newline}</span>`;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const scriptLocationLink = linkifier.linkifyScriptLocation(
|
|
748
|
+
details.error.runtimeModel().target(),
|
|
749
|
+
link.scriptId || null,
|
|
750
|
+
link.url,
|
|
751
|
+
link.lineNumber,
|
|
752
|
+
{
|
|
753
|
+
columnNumber: link.columnNumber,
|
|
754
|
+
inlineFrameIndex: 0,
|
|
755
|
+
showColumnNumber: true,
|
|
756
|
+
},
|
|
757
|
+
);
|
|
758
|
+
scriptLocationLink.tabIndex = -1;
|
|
759
|
+
|
|
760
|
+
return html`<span class="formatted-stack-frame">${link.prefix}${scriptLocationLink}${link.suffix}${
|
|
761
|
+
newline}</span>`;
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
return html`
|
|
765
|
+
<div class="payload-value source-code error-text">
|
|
766
|
+
${details.frames.length === 0 && details.description ? html`<span>${details.description}\n</span>` : nothing}
|
|
767
|
+
<div>${details.frames.map(renderFrame)}</div>
|
|
768
|
+
${details.cause ? html`\nCaused by:\n${createException(details.cause, linkifier)}` : nothing}</div>`;
|
|
769
|
+
};
|
|
718
770
|
|
|
719
771
|
render(
|
|
720
772
|
html`
|
|
@@ -723,7 +775,10 @@ export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, ta
|
|
|
723
775
|
<div class="call-payload-content">
|
|
724
776
|
${
|
|
725
777
|
isParsable ? createPayload(input.valueObject) :
|
|
726
|
-
(input.valueString !== undefined ?
|
|
778
|
+
(input.valueString !== undefined ?
|
|
779
|
+
createSourceText(input.valueString) :
|
|
780
|
+
(input.exceptionDetails ? createException(input.exceptionDetails) :
|
|
781
|
+
(input.errorText ? createErrorText(input.errorText) : nothing)))}
|
|
727
782
|
</div>
|
|
728
783
|
</div>
|
|
729
784
|
`,
|
|
@@ -733,6 +788,9 @@ export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, ta
|
|
|
733
788
|
export class PayloadWidget extends UI.Widget.Widget {
|
|
734
789
|
#valueObject?: unknown;
|
|
735
790
|
#valueString?: string;
|
|
791
|
+
#errorText?: string;
|
|
792
|
+
#exceptionDetailsPromise?: Promise<WebMCP.WebMCPModel.ExceptionDetails|undefined>;
|
|
793
|
+
#exceptionDetails?: WebMCP.WebMCPModel.ExceptionDetails;
|
|
736
794
|
#view: typeof PAYLOAD_DEFAULT_VIEW;
|
|
737
795
|
|
|
738
796
|
constructor(element?: HTMLElement, view = PAYLOAD_DEFAULT_VIEW) {
|
|
@@ -758,6 +816,37 @@ export class PayloadWidget extends UI.Widget.Widget {
|
|
|
758
816
|
return this.#valueString;
|
|
759
817
|
}
|
|
760
818
|
|
|
819
|
+
set errorText(errorText: string|undefined) {
|
|
820
|
+
this.#errorText = errorText;
|
|
821
|
+
this.requestUpdate();
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
get errorText(): string|undefined {
|
|
825
|
+
return this.#errorText;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
async #updateExceptionDetails(
|
|
829
|
+
exceptionDetailsPromise: Promise<WebMCP.WebMCPModel.ExceptionDetails|undefined>|undefined): Promise<void> {
|
|
830
|
+
if (this.#exceptionDetailsPromise === exceptionDetailsPromise) {
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
this.#exceptionDetailsPromise = exceptionDetailsPromise;
|
|
834
|
+
this.#exceptionDetails = undefined;
|
|
835
|
+
this.requestUpdate();
|
|
836
|
+
const exceptionDetails = await exceptionDetailsPromise;
|
|
837
|
+
if (this.#exceptionDetailsPromise === exceptionDetailsPromise) {
|
|
838
|
+
this.#exceptionDetails = exceptionDetails;
|
|
839
|
+
this.requestUpdate();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
set exceptionDetails(exceptionDetailsPromise: Promise<WebMCP.WebMCPModel.ExceptionDetails|undefined>|undefined) {
|
|
844
|
+
void this.#updateExceptionDetails(exceptionDetailsPromise);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
get exceptionDetails(): Promise<WebMCP.WebMCPModel.ExceptionDetails|undefined>|undefined {
|
|
848
|
+
return this.#exceptionDetailsPromise;
|
|
849
|
+
}
|
|
761
850
|
override wasShown(): void {
|
|
762
851
|
super.wasShown();
|
|
763
852
|
this.requestUpdate();
|
|
@@ -767,6 +856,8 @@ export class PayloadWidget extends UI.Widget.Widget {
|
|
|
767
856
|
const input: PayloadViewInput = {
|
|
768
857
|
valueObject: this.#valueObject,
|
|
769
858
|
valueString: this.#valueString,
|
|
859
|
+
errorText: this.#errorText,
|
|
860
|
+
exceptionDetails: this.#exceptionDetails,
|
|
770
861
|
};
|
|
771
862
|
this.#view(input, {}, this.contentElement);
|
|
772
863
|
}
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
background-color: var(--sys-color-tonal-container);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
tr.selected.status-error
|
|
51
|
+
tbody tr.selected.status-error,
|
|
52
|
+
tbody tr.selected.status-error.revealed {
|
|
52
53
|
background-color: var(--sys-color-error-container);
|
|
53
54
|
color: var(--sys-color-error);
|
|
54
55
|
}
|
|
@@ -210,4 +211,9 @@
|
|
|
210
211
|
flex: auto;
|
|
211
212
|
overflow: auto;
|
|
212
213
|
}
|
|
214
|
+
|
|
215
|
+
.payload-value.error-text {
|
|
216
|
+
color: var(--sys-color-error);
|
|
217
|
+
white-space: pre-wrap;
|
|
218
|
+
}
|
|
213
219
|
}
|
|
@@ -6,13 +6,11 @@ import '../../ui/legacy/legacy.js';
|
|
|
6
6
|
|
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
8
8
|
import type * as Platform from '../../core/platform/platform.js';
|
|
9
|
-
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
10
9
|
import type * as Workspace from '../../models/workspace/workspace.js';
|
|
11
10
|
import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
|
|
12
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
13
12
|
import * as Lit from '../../ui/lit/lit.js';
|
|
14
13
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
|
-
import * as PanelsCommon from '../common/common.js';
|
|
16
14
|
|
|
17
15
|
import {ChangesSidebar, Events} from './ChangesSidebar.js';
|
|
18
16
|
import changesViewStyles from './changesView.css.js';
|
|
@@ -48,8 +46,6 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
48
46
|
Events.SELECTED_UI_SOURCE_CODE_CHANGED, () => input.onSelect(sidebar.selectedUISourceCode()));
|
|
49
47
|
};
|
|
50
48
|
|
|
51
|
-
const hasCopyToPrompt = GreenDev.Prototypes.instance().isEnabled('copyToGemini');
|
|
52
|
-
|
|
53
49
|
render(
|
|
54
50
|
// clang-format off
|
|
55
51
|
html`
|
|
@@ -70,14 +66,6 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
70
66
|
workspaceDiff: input.workspaceDiff
|
|
71
67
|
})}
|
|
72
68
|
</div>
|
|
73
|
-
${hasCopyToPrompt ? html`
|
|
74
|
-
<devtools-widget class="copy-to-prompt"
|
|
75
|
-
${widget(PanelsCommon.CopyChangesToPrompt, {
|
|
76
|
-
workspaceDiff: input.workspaceDiff,
|
|
77
|
-
patchAgentCSSChange: null,
|
|
78
|
-
})}
|
|
79
|
-
></devtools-widget>
|
|
80
|
-
` : Lit.nothing}
|
|
81
69
|
</div>
|
|
82
70
|
<devtools-widget slot="sidebar" ${widget(ChangesSidebar, {workspaceDiff: input.workspaceDiff})}
|
|
83
71
|
${UI.Widget.widgetRef(ChangesSidebar, onSidebar)}>
|
|
@@ -111,4 +111,3 @@ export * as PersistenceUtils from './PersistenceUtils.js';
|
|
|
111
111
|
export * as DOMLinkifier from './DOMLinkifier.js';
|
|
112
112
|
export * as ThrottlingUtils from './ThrottlingUtils.js';
|
|
113
113
|
export * as ExtensionIframe from './ExtensionView.js';
|
|
114
|
-
export {CopyChangesToPrompt} from './CopyChangesToPrompt.js';
|
|
@@ -29,11 +29,11 @@ const UIStrings = {
|
|
|
29
29
|
*/
|
|
30
30
|
consolePrompt: 'Console prompt',
|
|
31
31
|
/**
|
|
32
|
-
* @description Warning shown to users when pasting text into the DevTools console.
|
|
32
|
+
* @description Warning shown to users when pasting text into the DevTools console. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
|
|
33
33
|
* @example {allow pasting} PH1
|
|
34
34
|
*/
|
|
35
35
|
selfXssWarning:
|
|
36
|
-
'Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type
|
|
36
|
+
'Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type “{PH1}” below and press Enter to allow pasting.',
|
|
37
37
|
/**
|
|
38
38
|
* @description Text a user needs to type in order to confirm that they are aware of the danger of pasting code into the DevTools console.
|
|
39
39
|
*/
|
|
@@ -2782,7 +2782,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2782
2782
|
existingElement?.remove();
|
|
2783
2783
|
}
|
|
2784
2784
|
|
|
2785
|
-
if (!this.overriddenByAnimation() || UI.ViewManager.ViewManager.instance().isViewVisible('animations')
|
|
2785
|
+
if (!this.overriddenByAnimation() || UI.ViewManager.ViewManager.instance().isViewVisible('animations') ||
|
|
2786
|
+
!Common.Settings.Settings.instance().moduleSetting('css-animations-only-when-animations-tab-open').get()) {
|
|
2786
2787
|
return;
|
|
2787
2788
|
}
|
|
2788
2789
|
|
|
@@ -1096,10 +1096,12 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
|
1096
1096
|
// the matched styles we reenable the button.
|
|
1097
1097
|
LayersWidget.ButtonProvider.instance().item().setVisible(false);
|
|
1098
1098
|
const animationsPanelVisible = UI.ViewManager.ViewManager.instance().isViewVisible('animations');
|
|
1099
|
+
const cssAnimationsOnlyWhenAnimationsTabOpen =
|
|
1100
|
+
Common.Settings.Settings.instance().moduleSetting('css-animations-only-when-animations-tab-open').get();
|
|
1099
1101
|
for (const style of matchedStyles.nodeStyles()) {
|
|
1100
1102
|
const isTransitionOrAnimationStyle = style.type === SDK.CSSStyleDeclaration.Type.Transition ||
|
|
1101
1103
|
style.type === SDK.CSSStyleDeclaration.Type.Animation;
|
|
1102
|
-
if (isTransitionOrAnimationStyle && !animationsPanelVisible) {
|
|
1104
|
+
if (isTransitionOrAnimationStyle && cssAnimationsOnlyWhenAnimationsTabOpen && !animationsPanelVisible) {
|
|
1103
1105
|
continue;
|
|
1104
1106
|
}
|
|
1105
1107
|
|
|
@@ -163,6 +163,10 @@ const UIStrings = {
|
|
|
163
163
|
* @description Command for toggling the eye dropper when the color picker is open
|
|
164
164
|
*/
|
|
165
165
|
toggleEyeDropper: 'Toggle eye dropper',
|
|
166
|
+
/**
|
|
167
|
+
* @description Title of a setting under the Elements category.
|
|
168
|
+
*/
|
|
169
|
+
cssAnimationsOnlyWhenAnimationsTabOpen: 'Show animation styles only when the Animations tab is open',
|
|
166
170
|
} as const;
|
|
167
171
|
const str_ = i18n.i18n.registerUIStrings('panels/elements/elements-meta.ts', UIStrings);
|
|
168
172
|
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
@@ -569,6 +573,16 @@ Common.Settings.registerSettingExtension({
|
|
|
569
573
|
defaultValue: true,
|
|
570
574
|
});
|
|
571
575
|
|
|
576
|
+
Common.Settings.registerSettingExtension({
|
|
577
|
+
category: Common.Settings.SettingCategory.ELEMENTS,
|
|
578
|
+
storageType: Common.Settings.SettingStorageType.SYNCED,
|
|
579
|
+
order: 6,
|
|
580
|
+
title: i18nLazyString(UIStrings.cssAnimationsOnlyWhenAnimationsTabOpen),
|
|
581
|
+
settingName: 'css-animations-only-when-animations-tab-open',
|
|
582
|
+
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
583
|
+
defaultValue: true,
|
|
584
|
+
});
|
|
585
|
+
|
|
572
586
|
Common.Settings.registerSettingExtension({
|
|
573
587
|
settingName: 'show-event-listeners-for-ancestors',
|
|
574
588
|
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
@@ -1880,10 +1880,30 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
1880
1880
|
const throttlingMenu =
|
|
1881
1881
|
contextMenu.debugSection().appendSubMenuItem(i18nString(UIStrings.throttleRequests), /* disabled=*/ true);
|
|
1882
1882
|
|
|
1883
|
-
const
|
|
1884
|
-
|
|
1883
|
+
const parsed = request.parsedURL;
|
|
1884
|
+
let urlPatternString = '';
|
|
1885
|
+
if (parsed.isValid) {
|
|
1886
|
+
// We cannot escape parsed.urlWithoutScheme() directly. If we escaped the first '?'
|
|
1887
|
+
// URLPattern would treat the entire string as the pathname and fail to match the query string.
|
|
1888
|
+
// Thus, we must escape the components individually and reconstruct the pattern string.
|
|
1889
|
+
urlPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.host);
|
|
1890
|
+
if (parsed.port) {
|
|
1891
|
+
urlPatternString += ':' + Platform.StringUtilities.escapeForURLPattern(parsed.port);
|
|
1892
|
+
}
|
|
1893
|
+
urlPatternString += Platform.StringUtilities.escapeForURLPattern(parsed.path);
|
|
1894
|
+
if (parsed.queryParams) {
|
|
1895
|
+
urlPatternString += '?' + Platform.StringUtilities.escapeForURLPattern(parsed.queryParams);
|
|
1896
|
+
}
|
|
1897
|
+
if (parsed.fragment) {
|
|
1898
|
+
urlPatternString += '#' + Platform.StringUtilities.escapeForURLPattern(parsed.fragment);
|
|
1899
|
+
}
|
|
1900
|
+
} else if (parsed.urlWithoutScheme()) {
|
|
1901
|
+
urlPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.urlWithoutScheme());
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
const urlPattern = urlPatternString &&
|
|
1885
1905
|
SDK.NetworkManager.RequestURLPattern.create(
|
|
1886
|
-
|
|
1906
|
+
urlPatternString as SDK.NetworkManager.URLPatternConstructorString);
|
|
1887
1907
|
if (urlPattern) {
|
|
1888
1908
|
throttlingMenu.setEnabled(true);
|
|
1889
1909
|
blockingMenu.setEnabled(true);
|
|
@@ -1906,30 +1926,39 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
1906
1926
|
{jslogContext: 'throttle-request-url'});
|
|
1907
1927
|
}
|
|
1908
1928
|
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1929
|
+
let domainPatternString = '';
|
|
1930
|
+
if (parsed.isValid) {
|
|
1931
|
+
domainPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.host);
|
|
1932
|
+
if (parsed.port) {
|
|
1933
|
+
domainPatternString += ':' + Platform.StringUtilities.escapeForURLPattern(parsed.port);
|
|
1934
|
+
}
|
|
1935
|
+
} else if (parsed.domain()) {
|
|
1936
|
+
domainPatternString = '*://' + Platform.StringUtilities.escapeForURLPattern(parsed.domain());
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
const domainPattern = domainPatternString &&
|
|
1940
|
+
SDK.NetworkManager.RequestURLPattern.create(
|
|
1941
|
+
domainPatternString as SDK.NetworkManager.URLPatternConstructorString);
|
|
1942
|
+
if (domainPattern) {
|
|
1943
|
+
throttlingMenu.setEnabled(true);
|
|
1944
|
+
blockingMenu.setEnabled(true);
|
|
1945
|
+
const existingConditions = manager.requestConditions.findCondition(domainPattern.constructorString);
|
|
1946
|
+
const isBlocking = existingConditions?.conditions === SDK.NetworkManager.BlockingConditions;
|
|
1947
|
+
const isThrottling = existingConditions &&
|
|
1948
|
+
existingConditions.conditions !== SDK.NetworkManager.BlockingConditions &&
|
|
1949
|
+
existingConditions.conditions !== SDK.NetworkManager.NoThrottlingConditions;
|
|
1950
|
+
const croppedURL = Platform.StringUtilities.trimMiddle(domainPattern.constructorString, maxBlockedURLLength);
|
|
1951
|
+
blockingMenu.debugSection().appendItem(
|
|
1952
|
+
isBlocking ? i18nString(UIStrings.unblockS, {PH1: croppedURL}) : i18nString(UIStrings.blockRequestDomain),
|
|
1953
|
+
() => isBlocking ? removeRequestCondition(domainPattern) :
|
|
1954
|
+
addRequestCondition(domainPattern, SDK.NetworkManager.BlockingConditions),
|
|
1955
|
+
{jslogContext: 'block-request-domain'});
|
|
1956
|
+
throttlingMenu.debugSection().appendItem(
|
|
1957
|
+
isThrottling ? i18nString(UIStrings.unthrottleS, {PH1: croppedURL}) :
|
|
1958
|
+
i18nString(UIStrings.throttleRequestDomain),
|
|
1959
|
+
() => isThrottling ? removeRequestCondition(domainPattern) :
|
|
1960
|
+
addRequestCondition(domainPattern, SDK.NetworkManager.Slow3GConditions),
|
|
1961
|
+
{jslogContext: 'throttle-request-domain'});
|
|
1933
1962
|
}
|
|
1934
1963
|
|
|
1935
1964
|
if (SDK.NetworkManager.NetworkManager.canReplayRequest(request)) {
|
|
@@ -1944,7 +1973,8 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
1944
1973
|
const requests = Logs.NetworkLog.NetworkLog.instance().requests().filter(request => this.applyFilter(request));
|
|
1945
1974
|
return requests.filter(NetworkLogView.getHTTPRequestsFilter).filter(request => {
|
|
1946
1975
|
return request.finished ||
|
|
1947
|
-
(request.resourceType() === Common.ResourceType.resourceTypes.WebSocket && request.responseReceivedTime)
|
|
1976
|
+
(request.resourceType() === Common.ResourceType.resourceTypes.WebSocket && request.responseReceivedTime) ||
|
|
1977
|
+
Boolean(request.eventSourceMessages()?.length);
|
|
1948
1978
|
});
|
|
1949
1979
|
}
|
|
1950
1980
|
|
|
@@ -133,21 +133,21 @@ const UIStrings = {
|
|
|
133
133
|
*/
|
|
134
134
|
doYouTrustThisCode: 'Do you trust this recording?',
|
|
135
135
|
/**
|
|
136
|
-
* @description Warning shown to users when imports code into DevTools Recorder.
|
|
136
|
+
* @description Warning shown to users when imports code into DevTools Recorder. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
|
|
137
137
|
* @example {allow importing} PH1
|
|
138
138
|
*/
|
|
139
139
|
doNotImport:
|
|
140
|
-
'Don\'t import recordings you do not understand or have not reviewed yourself into DevTools. This could allow attackers to steal your identity or take control of your computer. Please type
|
|
140
|
+
'Don\'t import recordings you do not understand or have not reviewed yourself into DevTools. This could allow attackers to steal your identity or take control of your computer. Please type “{PH1}” below to allow importing.',
|
|
141
141
|
/**
|
|
142
142
|
* @description Text a user needs to type in order to confirm that they
|
|
143
143
|
*are aware of the danger of import code into the DevTools Recorder.
|
|
144
144
|
*/
|
|
145
145
|
allowImporting: 'allow importing',
|
|
146
146
|
/**
|
|
147
|
-
* @description Input box placeholder which instructs the user to type 'allow importing' into the input box.
|
|
147
|
+
* @description Input box placeholder which instructs the user to type 'allow importing' into the input box. IMPORTANT: keep double quotes around PH1 and do not use single quotes.
|
|
148
148
|
* @example {allow importing} PH1
|
|
149
149
|
*/
|
|
150
|
-
typeAllowImporting: 'Type
|
|
150
|
+
typeAllowImporting: 'Type “{PH1}”',
|
|
151
151
|
} as const;
|
|
152
152
|
const str_ = i18n.i18n.registerUIStrings('panels/recorder/RecorderController.ts', UIStrings);
|
|
153
153
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|