chrome-devtools-frontend 1.0.1515988 → 1.0.1518653
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/docs/checklist/README.md +2 -2
- package/docs/checklist/javascript.md +1 -1
- package/docs/contributing/README.md +1 -1
- package/docs/contributing/settings-experiments-features.md +9 -8
- package/docs/cookbook/devtools_on_devtools.md +2 -2
- package/docs/cookbook/localization.md +10 -10
- package/docs/devtools-protocol.md +9 -8
- package/docs/ecosystem/automatic_workspace_folders.md +3 -3
- package/docs/get_the_code.md +0 -2
- package/docs/styleguide/ux/components.md +166 -85
- package/docs/styleguide/ux/numbers.md +3 -4
- package/front_end/core/common/README.md +13 -12
- package/front_end/core/host/GdpClient.ts +16 -1
- package/front_end/core/host/UserMetrics.ts +8 -2
- package/front_end/core/root/Runtime.ts +13 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +5 -1
- package/front_end/entrypoints/main/MainImpl.ts +6 -3
- package/front_end/generated/InspectorBackendCommands.js +10 -7
- package/front_end/generated/SupportedCSSProperties.js +21 -7
- package/front_end/generated/protocol-mapping.d.ts +16 -1
- package/front_end/generated/protocol-proxy-api.d.ts +13 -1
- package/front_end/generated/protocol.ts +95 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +170 -54
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +14 -181
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +13 -315
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +224 -50
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +310 -11
- package/front_end/models/ai_assistance/performance/AIContext.ts +15 -2
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +41 -19
- package/front_end/models/badges/Badge.ts +8 -3
- package/front_end/models/badges/CodeWhispererBadge.ts +2 -4
- package/front_end/models/badges/StarterBadge.ts +2 -2
- package/front_end/models/badges/UserBadges.ts +59 -6
- package/front_end/models/formatter/FormatterWorkerPool.ts +3 -3
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/trace/README.md +28 -1
- package/front_end/models/trace/handlers/UserTimingsHandler.ts +1 -1
- package/front_end/models/trace/helpers/Trace.ts +99 -43
- package/front_end/models/trace/types/TraceEvents.ts +9 -0
- package/front_end/panels/accessibility/ARIAAttributesView.ts +113 -191
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +9 -9
- package/front_end/panels/accessibility/AccessibilitySubPane.ts +6 -4
- package/front_end/panels/accessibility/accessibilityProperties.css +2 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +16 -2
- package/front_end/panels/ai_assistance/components/ChatView.ts +9 -10
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +42 -0
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +32 -9
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +7 -1
- package/front_end/panels/common/BadgeNotification.ts +67 -15
- package/front_end/panels/common/GdpSignUpDialog.ts +18 -9
- package/front_end/panels/console/ConsolePrompt.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +6 -2
- package/front_end/panels/elements/ComputedStyleWidget.ts +1 -2
- package/front_end/panels/elements/ElementsPanel.ts +4 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +18 -0
- package/front_end/panels/elements/ElementsTreeOutline.ts +13 -0
- package/front_end/panels/elements/LayoutPane.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +21 -6
- package/front_end/panels/media/TickingFlameChart.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +5 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +34 -19
- package/front_end/panels/search/SearchResultsPane.ts +126 -145
- package/front_end/panels/search/SearchView.ts +43 -59
- package/front_end/panels/settings/components/SyncSection.ts +16 -8
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +6 -1
- package/front_end/panels/sources/OutlineQuickOpen.ts +3 -1
- package/front_end/panels/sources/SourcesPanel.ts +3 -0
- package/front_end/panels/timeline/AppenderUtils.ts +2 -2
- package/front_end/panels/timeline/ExtensionTrackAppender.ts +13 -4
- package/front_end/panels/timeline/GPUTrackAppender.ts +2 -1
- package/front_end/panels/timeline/InteractionsTrackAppender.ts +5 -1
- package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +2 -1
- package/front_end/panels/timeline/ThreadAppender.ts +12 -3
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +9 -4
- package/front_end/panels/timeline/TimelinePanel.ts +3 -2
- package/front_end/panels/timeline/TimelineUIUtils.ts +18 -12
- package/front_end/panels/timeline/TimingsTrackAppender.ts +6 -1
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +95 -82
- package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
- package/front_end/panels/timeline/components/cpuThrottlingSelector.css +17 -15
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +3 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +6 -9
- package/front_end/third_party/codemirror.next/package.json +2 -1
- package/front_end/third_party/diff/README.chromium +1 -0
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Accessibility.js +0 -20
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +2 -23
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Accessibility.js +0 -20
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Accessibility.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/package.json +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +1 -21
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +1 -1
- package/front_end/ui/components/text_editor/config.ts +36 -8
- package/front_end/ui/components/tooltips/Tooltip.ts +71 -34
- package/front_end/ui/legacy/README.md +33 -24
- package/front_end/ui/legacy/SearchableView.ts +19 -26
- package/front_end/ui/legacy/TextPrompt.ts +166 -1
- package/front_end/ui/legacy/Treeoutline.ts +16 -2
- package/front_end/ui/legacy/UIUtils.ts +15 -2
- package/front_end/ui/legacy/XElement.ts +0 -43
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +20 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +24 -6
- package/front_end/ui/visual_logging/README.md +43 -27
- package/package.json +1 -1
@@ -33,6 +33,10 @@ const UIStringsNotTranslate = {
|
|
33
33
|
*/
|
34
34
|
tooltipDisclaimerTextForAiCodeCompletionNoLogging:
|
35
35
|
'To generate code suggestions, your console input and the history of your current console session are shared with Google. This data will not be used to improve Google’s AI models.',
|
36
|
+
/**
|
37
|
+
* Text for tooltip shown on hovering over spinner.
|
38
|
+
*/
|
39
|
+
tooltipTextForSpinner: 'Shows when data is being sent to Google to generate code suggestions',
|
36
40
|
/**
|
37
41
|
* @description Text for tooltip button which redirects to AI settings
|
38
42
|
*/
|
@@ -47,6 +51,7 @@ const lockedString = i18n.i18n.lockedString;
|
|
47
51
|
|
48
52
|
export interface ViewInput {
|
49
53
|
disclaimerTooltipId?: string;
|
54
|
+
spinnerTooltipId?: string;
|
50
55
|
noLogging: boolean;
|
51
56
|
aidaAvailability?: Host.AidaClient.AidaAccessPreconditions;
|
52
57
|
onManageInSettingsTooltipClick: () => void;
|
@@ -59,12 +64,14 @@ export interface ViewOutput {
|
|
59
64
|
|
60
65
|
export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
|
61
66
|
|
62
|
-
export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View =
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
67
|
+
export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View =
|
68
|
+
(input, output, target) => {
|
69
|
+
if (input.aidaAvailability !== Host.AidaClient.AidaAccessPreconditions.AVAILABLE || !input.disclaimerTooltipId ||
|
70
|
+
!input.spinnerTooltipId) {
|
71
|
+
render(nothing, target);
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
// clang-format off
|
68
75
|
render(
|
69
76
|
html`
|
70
77
|
<style>${styles}</style>
|
@@ -76,7 +83,16 @@ export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View = (input, output, target) => {
|
|
76
83
|
el.toggleAttribute('active', isLoading);
|
77
84
|
};
|
78
85
|
}
|
79
|
-
})}
|
86
|
+
})}
|
87
|
+
aria-details=${input.spinnerTooltipId}
|
88
|
+
aria-describedby=${input.spinnerTooltipId}></devtools-spinner>
|
89
|
+
<devtools-tooltip
|
90
|
+
id=${input.spinnerTooltipId}
|
91
|
+
variant=${'rich'}
|
92
|
+
jslogContext=${'ai-code-completion-spinner-tooltip'}>
|
93
|
+
<div class="disclaimer-tooltip-container"><div class="tooltip-text">
|
94
|
+
${lockedString(UIStringsNotTranslate.tooltipTextForSpinner)}
|
95
|
+
</div></div></devtools-tooltip>
|
80
96
|
<span
|
81
97
|
tabIndex="0"
|
82
98
|
class="link"
|
@@ -115,8 +131,8 @@ export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View = (input, output, target) => {
|
|
115
131
|
>${lockedString(UIStringsNotTranslate.manageInSettings)}</span></div></devtools-tooltip>
|
116
132
|
</div>
|
117
133
|
`, target);
|
118
|
-
|
119
|
-
};
|
134
|
+
// clang-format on
|
135
|
+
};
|
120
136
|
|
121
137
|
const MINIMUM_LOADING_STATE_TIMEOUT = 1000;
|
122
138
|
|
@@ -124,6 +140,7 @@ export class AiCodeCompletionDisclaimer extends UI.Widget.Widget {
|
|
124
140
|
readonly #view: View;
|
125
141
|
#viewOutput: ViewOutput = {};
|
126
142
|
|
143
|
+
#spinnerTooltipId?: string;
|
127
144
|
#disclaimerTooltipId?: string;
|
128
145
|
#noLogging: boolean; // Whether the enterprise setting is `ALLOW_WITHOUT_LOGGING` or not.
|
129
146
|
#loading = false;
|
@@ -147,6 +164,11 @@ export class AiCodeCompletionDisclaimer extends UI.Widget.Widget {
|
|
147
164
|
this.requestUpdate();
|
148
165
|
}
|
149
166
|
|
167
|
+
set spinnerTooltipId(spinnerTooltipId: string) {
|
168
|
+
this.#spinnerTooltipId = spinnerTooltipId;
|
169
|
+
this.requestUpdate();
|
170
|
+
}
|
171
|
+
|
150
172
|
set loading(loading: boolean) {
|
151
173
|
if (!loading && !this.#loading) {
|
152
174
|
return;
|
@@ -191,6 +213,7 @@ export class AiCodeCompletionDisclaimer extends UI.Widget.Widget {
|
|
191
213
|
this.#view(
|
192
214
|
{
|
193
215
|
disclaimerTooltipId: this.#disclaimerTooltipId,
|
216
|
+
spinnerTooltipId: this.#spinnerTooltipId,
|
194
217
|
noLogging: this.#noLogging,
|
195
218
|
aidaAvailability: this.#aidaAvailability,
|
196
219
|
onManageInSettingsTooltipClick: this.#onManageInSettingsTooltipClick.bind(this),
|
@@ -30,11 +30,13 @@ const lockedString = i18n.i18n.lockedString;
|
|
30
30
|
export interface AiCodeCompletionSummaryToolbarProps {
|
31
31
|
citationsTooltipId: string;
|
32
32
|
disclaimerTooltipId?: string;
|
33
|
+
spinnerTooltipId?: string;
|
33
34
|
hasTopBorder?: boolean;
|
34
35
|
}
|
35
36
|
|
36
37
|
export interface ViewInput {
|
37
38
|
disclaimerTooltipId?: string;
|
39
|
+
spinnerTooltipId?: string;
|
38
40
|
citations?: Set<string>;
|
39
41
|
citationsTooltipId: string;
|
40
42
|
loading: boolean;
|
@@ -57,10 +59,11 @@ export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View = (input, _output, target) => {
|
|
57
59
|
});
|
58
60
|
|
59
61
|
// clang-format off
|
60
|
-
const disclaimer = input.disclaimerTooltipId ?
|
62
|
+
const disclaimer = input.disclaimerTooltipId && input.spinnerTooltipId ?
|
61
63
|
html`<devtools-widget
|
62
64
|
.widgetConfig=${UI.Widget.widgetConfig(AiCodeCompletionDisclaimer, {
|
63
65
|
disclaimerTooltipId: input.disclaimerTooltipId,
|
66
|
+
spinnerTooltipId: input.spinnerTooltipId,
|
64
67
|
loading: input.loading,
|
65
68
|
})} class="disclaimer-widget"></devtools-widget>` : nothing;
|
66
69
|
|
@@ -102,6 +105,7 @@ export class AiCodeCompletionSummaryToolbar extends UI.Widget.Widget {
|
|
102
105
|
readonly #view: View;
|
103
106
|
|
104
107
|
#disclaimerTooltipId?: string;
|
108
|
+
#spinnerTooltipId?: string;
|
105
109
|
#citationsTooltipId: string;
|
106
110
|
#citations = new Set<string>();
|
107
111
|
#loading = false;
|
@@ -113,6 +117,7 @@ export class AiCodeCompletionSummaryToolbar extends UI.Widget.Widget {
|
|
113
117
|
constructor(props: AiCodeCompletionSummaryToolbarProps, view?: View) {
|
114
118
|
super();
|
115
119
|
this.#disclaimerTooltipId = props.disclaimerTooltipId;
|
120
|
+
this.#spinnerTooltipId = props.spinnerTooltipId;
|
116
121
|
this.#citationsTooltipId = props.citationsTooltipId;
|
117
122
|
this.#hasTopBorder = props.hasTopBorder ?? false;
|
118
123
|
this.#boundOnAidaAvailabilityChange = this.#onAidaAvailabilityChange.bind(this);
|
@@ -147,6 +152,7 @@ export class AiCodeCompletionSummaryToolbar extends UI.Widget.Widget {
|
|
147
152
|
this.#view(
|
148
153
|
{
|
149
154
|
disclaimerTooltipId: this.#disclaimerTooltipId,
|
155
|
+
spinnerTooltipId: this.#spinnerTooltipId,
|
150
156
|
citations: this.#citations,
|
151
157
|
citationsTooltipId: this.#citationsTooltipId,
|
152
158
|
loading: this.#loading,
|
@@ -69,21 +69,25 @@ const lockedString = i18n.i18n.lockedString;
|
|
69
69
|
|
70
70
|
const LEFT_OFFSET = 5;
|
71
71
|
const BOTTOM_OFFSET = 5;
|
72
|
+
const AUTO_CLOSE_TIME_IN_MS = 30000;
|
73
|
+
|
72
74
|
export interface BadgeNotificationAction {
|
73
75
|
label: string;
|
74
|
-
jslogContext
|
76
|
+
jslogContext: string;
|
75
77
|
title?: string;
|
76
78
|
onClick: () => void;
|
77
79
|
}
|
78
80
|
|
79
81
|
export interface BadgeNotificationProperties {
|
80
82
|
message: HTMLElement|string;
|
83
|
+
jslogContext: string;
|
81
84
|
imageUri: string;
|
82
85
|
actions: BadgeNotificationAction[];
|
86
|
+
isStarterBadge: boolean;
|
83
87
|
}
|
84
88
|
|
85
89
|
export interface ViewInput extends BadgeNotificationProperties {
|
86
|
-
|
90
|
+
onDismissClick: () => void;
|
87
91
|
}
|
88
92
|
|
89
93
|
// clang-format off
|
@@ -101,7 +105,7 @@ const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement)
|
|
101
105
|
|
102
106
|
const crossButton = html`<devtools-button
|
103
107
|
class="dismiss notification-button"
|
104
|
-
@click=${input.
|
108
|
+
@click=${input.onDismissClick}
|
105
109
|
jslog=${VisualLogging.action('badge-notification.dismiss').track({click: true})}
|
106
110
|
aria-label=${i18nString(UIStrings.close)}
|
107
111
|
.iconName=${'cross'}
|
@@ -112,8 +116,8 @@ const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement)
|
|
112
116
|
|
113
117
|
render(html`
|
114
118
|
<style>${badgeNotificationStyles}</style>
|
115
|
-
<div class="container">
|
116
|
-
<div class="badge-container">
|
119
|
+
<div class="container" jslog=${VisualLogging.dialog('badge-notification')}>
|
120
|
+
<div class="badge-container" jslog=${VisualLogging.item(input.jslogContext)}>
|
117
121
|
<img class="badge-image" role="presentation" src=${input.imageUri}>
|
118
122
|
</div>
|
119
123
|
<div class="action-and-text-container">
|
@@ -135,12 +139,14 @@ function revealBadgeSettings(): void {
|
|
135
139
|
}
|
136
140
|
|
137
141
|
export class BadgeNotification extends UI.Widget.Widget {
|
142
|
+
jslogContext = '';
|
138
143
|
message: HTMLElement|string = '';
|
139
144
|
imageUri = '';
|
140
145
|
actions: BadgeNotificationAction[] = [];
|
146
|
+
isStarterBadge = false;
|
141
147
|
|
148
|
+
#autoCloseTimeout?: number;
|
142
149
|
#view: View;
|
143
|
-
|
144
150
|
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
145
151
|
super(element);
|
146
152
|
this.#view = view;
|
@@ -170,12 +176,19 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
170
176
|
this.message = properties.message;
|
171
177
|
this.imageUri = properties.imageUri;
|
172
178
|
this.actions = properties.actions;
|
179
|
+
this.isStarterBadge = properties.isStarterBadge;
|
180
|
+
this.jslogContext = properties.jslogContext;
|
173
181
|
this.requestUpdate();
|
174
182
|
this.show(document.body);
|
175
183
|
|
176
184
|
void this.updateComplete.then(() => {
|
177
185
|
this.#positionNotification();
|
178
186
|
});
|
187
|
+
|
188
|
+
if (this.#autoCloseTimeout) {
|
189
|
+
window.clearTimeout(this.#autoCloseTimeout);
|
190
|
+
}
|
191
|
+
this.#autoCloseTimeout = window.setTimeout(this.#onAutoClose, AUTO_CLOSE_TIME_IN_MS);
|
179
192
|
}
|
180
193
|
|
181
194
|
async #presentStarterBadge(badge: Badges.Badge): Promise<void> {
|
@@ -183,7 +196,7 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
183
196
|
const receiveBadgesSettingEnabled = Badges.UserBadges.instance().isReceiveBadgesSettingEnabled();
|
184
197
|
const googleDeveloperProgramLink = UI.XLink.XLink.create(
|
185
198
|
'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
|
186
|
-
'
|
199
|
+
'program-link');
|
187
200
|
|
188
201
|
// If the user already has a GDP profile and the receive badges setting enabled,
|
189
202
|
// starter badge behaves as if it's an activity based badge.
|
@@ -198,20 +211,27 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
198
211
|
this.#show({
|
199
212
|
message: i18nFormatString(
|
200
213
|
UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
214
|
+
jslogContext: badge.name,
|
201
215
|
actions: [
|
202
216
|
{
|
203
217
|
label: i18nString(UIStrings.remindMeLater),
|
204
|
-
|
218
|
+
jslogContext: 'remind-me-later',
|
219
|
+
onClick: () => {
|
220
|
+
this.detach();
|
221
|
+
Badges.UserBadges.instance().snoozeStarterBadge();
|
222
|
+
},
|
205
223
|
},
|
206
224
|
{
|
207
225
|
label: i18nString(UIStrings.receiveBadges),
|
226
|
+
jslogContext: 'receive-badges',
|
208
227
|
onClick: () => {
|
209
|
-
this
|
228
|
+
this.detach();
|
210
229
|
revealBadgeSettings();
|
211
230
|
}
|
212
231
|
}
|
213
232
|
],
|
214
233
|
imageUri: badge.imageUri,
|
234
|
+
isStarterBadge: true,
|
215
235
|
});
|
216
236
|
return;
|
217
237
|
}
|
@@ -220,47 +240,77 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
220
240
|
this.#show({
|
221
241
|
message: i18nFormatString(
|
222
242
|
UIStrings.starterBadgeAwardMessageNoGdpProfile, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
243
|
+
jslogContext: badge.name,
|
223
244
|
actions: [
|
224
245
|
{
|
225
246
|
label: i18nString(UIStrings.remindMeLater),
|
226
|
-
|
247
|
+
jslogContext: 'remind-me-later',
|
248
|
+
onClick: () => {
|
249
|
+
this.detach();
|
250
|
+
Badges.UserBadges.instance().snoozeStarterBadge();
|
251
|
+
},
|
227
252
|
},
|
228
253
|
{
|
229
254
|
label: i18nString(UIStrings.createProfile),
|
255
|
+
jslogContext: 'create-profile',
|
230
256
|
onClick: () => {
|
231
|
-
this
|
232
|
-
GdpSignUpDialog.GdpSignUpDialog.show(
|
257
|
+
this.detach();
|
258
|
+
GdpSignUpDialog.GdpSignUpDialog.show({
|
259
|
+
// We want to consider cancelling from the starter badge as a "snooze" for starter badge.
|
260
|
+
onCancel: () => Badges.UserBadges.instance().snoozeStarterBadge(),
|
261
|
+
});
|
233
262
|
}
|
234
263
|
}
|
235
264
|
],
|
236
265
|
imageUri: badge.imageUri,
|
266
|
+
isStarterBadge: true,
|
237
267
|
});
|
238
268
|
}
|
239
269
|
|
240
270
|
#presentActivityBasedBadge(badge: Badges.Badge): void {
|
241
271
|
this.#show({
|
242
272
|
message: i18nString(UIStrings.activityBasedBadgeAwardMessage, {PH1: badge.title}),
|
273
|
+
jslogContext: badge.name,
|
243
274
|
actions: [
|
244
275
|
{
|
245
276
|
label: i18nString(UIStrings.manageSettings),
|
277
|
+
jslogContext: 'manage-settings',
|
246
278
|
onClick: () => {
|
247
|
-
this
|
279
|
+
this.detach();
|
248
280
|
revealBadgeSettings();
|
249
281
|
},
|
250
282
|
},
|
251
283
|
{
|
252
284
|
label: i18nString(UIStrings.viewProfile),
|
285
|
+
jslogContext: 'view-profile',
|
253
286
|
onClick: () => {
|
254
287
|
UI.UIUtils.openInNewTab(Host.GdpClient.GOOGLE_DEVELOPER_PROGRAM_PROFILE_LINK);
|
255
288
|
}
|
256
289
|
}
|
257
290
|
],
|
258
291
|
imageUri: badge.imageUri,
|
292
|
+
isStarterBadge: badge.isStarterBadge,
|
259
293
|
});
|
260
294
|
}
|
261
295
|
|
262
|
-
|
296
|
+
override onDetach(): void {
|
297
|
+
window.clearTimeout(this.#autoCloseTimeout);
|
298
|
+
}
|
299
|
+
|
300
|
+
#onDismissClick = (): void => {
|
301
|
+
this.detach();
|
302
|
+
|
303
|
+
if (this.isStarterBadge) {
|
304
|
+
Badges.UserBadges.instance().dismissStarterBadge();
|
305
|
+
}
|
306
|
+
};
|
307
|
+
|
308
|
+
#onAutoClose = (): void => {
|
263
309
|
this.detach();
|
310
|
+
|
311
|
+
if (this.isStarterBadge) {
|
312
|
+
Badges.UserBadges.instance().snoozeStarterBadge();
|
313
|
+
}
|
264
314
|
};
|
265
315
|
|
266
316
|
override wasShown(): void {
|
@@ -273,7 +323,9 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
273
323
|
message: this.message,
|
274
324
|
imageUri: this.imageUri,
|
275
325
|
actions: this.actions,
|
276
|
-
|
326
|
+
isStarterBadge: this.isStarterBadge,
|
327
|
+
onDismissClick: this.#onDismissClick,
|
328
|
+
jslogContext: this.jslogContext,
|
277
329
|
};
|
278
330
|
this.#view(viewInput, undefined, this.contentElement);
|
279
331
|
}
|
@@ -137,7 +137,7 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
137
137
|
<devtools-switch
|
138
138
|
.checked=${input.keepMeUpdated}
|
139
139
|
@switchchange=${(e: Switch.Switch.SwitchChangeEvent) => input.onKeepMeUpdatedChange(e.checked)}
|
140
|
-
jslog=${VisualLogging.toggle('
|
140
|
+
jslog=${VisualLogging.toggle('keep-me-updated').track({ click: true })}
|
141
141
|
aria-label=${i18nString(UIStrings.keepUpdated)}
|
142
142
|
>
|
143
143
|
</devtools-switch>
|
@@ -152,11 +152,11 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
152
152
|
<div class="section-text">
|
153
153
|
<div>${i18nString(UIStrings.tailorProfileBody)}</div><br/>
|
154
154
|
<div>${i18n.i18n.getFormatLocalizedString(str_, UIStrings.tailorProfileBodyDisclaimer, {
|
155
|
-
PH1: UI.XLink.XLink.create(CONTENT_POLICY_URL, i18nString(UIStrings.contentPolicy), 'link', undefined, '
|
155
|
+
PH1: UI.XLink.XLink.create(CONTENT_POLICY_URL, i18nString(UIStrings.contentPolicy), 'link', undefined, 'content-policy'),
|
156
156
|
PH2: UI.XLink.XLink.create(TERMS_OF_SERVICE_URL, i18nString(UIStrings.termsOfService), 'link',
|
157
|
-
undefined, '
|
157
|
+
undefined, 'terms-of-service'),
|
158
158
|
PH3: UI.XLink.XLink.create(PRIVACY_POLICY_URL, i18nString(UIStrings.privacyPolicy), 'link',
|
159
|
-
undefined, '
|
159
|
+
undefined, 'privacy-policy'),
|
160
160
|
})}</div>
|
161
161
|
</div>
|
162
162
|
</div>
|
@@ -176,7 +176,7 @@ export const DEFAULT_VIEW: View = (input, _output, target): void => {
|
|
176
176
|
@click=${input.onCancelClick}>${i18nString(UIStrings.cancel)}</devtools-button>
|
177
177
|
<devtools-button
|
178
178
|
.variant=${Buttons.Button.Variant.PRIMARY}
|
179
|
-
.jslogContext=${'
|
179
|
+
.jslogContext=${'sign-up'}
|
180
180
|
.spinner=${input.isSigningUp}
|
181
181
|
.disabled=${input.isSigningUp}
|
182
182
|
@click=${input.onSignUpClick}>${i18nString(UIStrings.signUp)}</devtools-button>
|
@@ -194,11 +194,19 @@ export class GdpSignUpDialog extends UI.Widget.VBox {
|
|
194
194
|
#keepMeUpdated = false;
|
195
195
|
#isSigningUp = false;
|
196
196
|
#onSuccess?: () => void;
|
197
|
+
#onCancel?: () => void;
|
197
198
|
|
198
|
-
constructor(
|
199
|
+
constructor(
|
200
|
+
options: {
|
201
|
+
dialog: UI.Dialog.Dialog,
|
202
|
+
onSuccess?: () => void,
|
203
|
+
onCancel?: () => void,
|
204
|
+
},
|
205
|
+
view?: View) {
|
199
206
|
super();
|
200
207
|
this.#dialog = options.dialog;
|
201
208
|
this.#onSuccess = options.onSuccess;
|
209
|
+
this.#onCancel = options.onCancel;
|
202
210
|
this.#view = view ?? DEFAULT_VIEW;
|
203
211
|
this.requestUpdate();
|
204
212
|
}
|
@@ -231,6 +239,7 @@ export class GdpSignUpDialog extends UI.Widget.VBox {
|
|
231
239
|
onSignUpClick: this.#onSignUpClick.bind(this),
|
232
240
|
onCancelClick: () => {
|
233
241
|
this.#dialog.hide();
|
242
|
+
this.#onCancel?.();
|
234
243
|
},
|
235
244
|
keepMeUpdated: this.#keepMeUpdated,
|
236
245
|
onKeepMeUpdatedChange: (value: boolean) => {
|
@@ -243,14 +252,14 @@ export class GdpSignUpDialog extends UI.Widget.VBox {
|
|
243
252
|
this.#view(viewInput, undefined, this.contentElement);
|
244
253
|
}
|
245
254
|
|
246
|
-
static show({onSuccess}: {onSuccess?: () => void} = {}): void {
|
247
|
-
const dialog = new UI.Dialog.Dialog();
|
255
|
+
static show({onSuccess, onCancel}: {onSuccess?: () => void, onCancel?: () => void} = {}): void {
|
256
|
+
const dialog = new UI.Dialog.Dialog('gdp-sign-up-dialog');
|
248
257
|
dialog.setAriaLabel(i18nString(UIStrings.gdpDialogAriaLabel));
|
249
258
|
dialog.setMaxContentSize(new Geometry.Size(384, 500));
|
250
259
|
dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SET_EXACT_WIDTH_MAX_HEIGHT);
|
251
260
|
dialog.setDimmed(true);
|
252
261
|
|
253
|
-
new GdpSignUpDialog({dialog, onSuccess}).show(dialog.contentElement);
|
262
|
+
new GdpSignUpDialog({dialog, onSuccess, onCancel}).show(dialog.contentElement);
|
254
263
|
dialog.show(undefined, /* stack */ true);
|
255
264
|
}
|
256
265
|
}
|
@@ -529,7 +529,7 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
529
529
|
this.teaser = undefined;
|
530
530
|
}
|
531
531
|
this.aiCodeCompletion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
|
532
|
-
{aidaClient: this.aidaClient}, this.editor, AiCodeCompletion.AiCodeCompletion.
|
532
|
+
{aidaClient: this.aidaClient}, this.editor, AiCodeCompletion.AiCodeCompletion.ContextFlavor.CONSOLE, ['\n\n']);
|
533
533
|
this.aiCodeCompletion.addEventListener(AiCodeCompletion.AiCodeCompletion.Events.RESPONSE_RECEIVED, event => {
|
534
534
|
this.aiCodeCompletionCitations = event.data.citations;
|
535
535
|
this.dispatchEventToListeners(Events.AI_CODE_COMPLETION_RESPONSE_RECEIVED, event.data);
|
@@ -270,6 +270,7 @@ let consoleViewInstance: ConsoleView;
|
|
270
270
|
|
271
271
|
const MIN_HISTORY_LENGTH_FOR_DISABLING_SELF_XSS_WARNING = 5;
|
272
272
|
const DISCLAIMER_TOOLTIP_ID = 'console-ai-code-completion-disclaimer-tooltip';
|
273
|
+
const SPINNER_TOOLTIP_ID = 'console-ai-code-completion-spinner-tooltip';
|
273
274
|
const CITATIONS_TOOLTIP_ID = 'console-ai-code-completion-citations-tooltip';
|
274
275
|
|
275
276
|
export class ConsoleView extends UI.Widget.VBox implements
|
@@ -624,8 +625,11 @@ export class ConsoleView extends UI.Widget.VBox implements
|
|
624
625
|
}
|
625
626
|
|
626
627
|
createAiCodeCompletionSummaryToolbar(): void {
|
627
|
-
this.aiCodeCompletionSummaryToolbar = new AiCodeCompletionSummaryToolbar(
|
628
|
-
|
628
|
+
this.aiCodeCompletionSummaryToolbar = new AiCodeCompletionSummaryToolbar({
|
629
|
+
citationsTooltipId: CITATIONS_TOOLTIP_ID,
|
630
|
+
disclaimerTooltipId: DISCLAIMER_TOOLTIP_ID,
|
631
|
+
spinnerTooltipId: SPINNER_TOOLTIP_ID
|
632
|
+
});
|
629
633
|
this.aiCodeCompletionSummaryToolbarContainer = this.element.createChild('div');
|
630
634
|
this.aiCodeCompletionSummaryToolbar.show(this.aiCodeCompletionSummaryToolbarContainer, undefined, true);
|
631
635
|
}
|
@@ -205,7 +205,6 @@ class ColorRenderer extends rendererBase(SDK.CSSPropertyParserMatchers.ColorMatc
|
|
205
205
|
swatch.renderColor(color);
|
206
206
|
const valueElement = document.createElement('span');
|
207
207
|
valueElement.textContent = match.text;
|
208
|
-
swatch.append(valueElement);
|
209
208
|
|
210
209
|
swatch.addEventListener(
|
211
210
|
InlineEditor.ColorSwatch.ColorChangedEvent.eventName, (event: InlineEditor.ColorSwatch.ColorChangedEvent) => {
|
@@ -214,7 +213,7 @@ class ColorRenderer extends rendererBase(SDK.CSSPropertyParserMatchers.ColorMatc
|
|
214
213
|
});
|
215
214
|
|
216
215
|
context.addControl('color', swatch);
|
217
|
-
return [swatch];
|
216
|
+
return [swatch, valueElement];
|
218
217
|
}
|
219
218
|
|
220
219
|
matcher(): SDK.CSSPropertyParserMatchers.ColorMatcher {
|
@@ -774,6 +774,10 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
|
|
774
774
|
this.#domTreeWidget.selectDOMNode(node, focus);
|
775
775
|
}
|
776
776
|
|
777
|
+
highlightNodeAttribute(node: SDK.DOMModel.DOMNode, attribute: string): void {
|
778
|
+
this.#domTreeWidget.highlightNodeAttribute(node, attribute);
|
779
|
+
}
|
780
|
+
|
777
781
|
selectAndShowSidebarTab(tabId: SidebarPaneTabId): void {
|
778
782
|
if (!this.sidebarPaneView) {
|
779
783
|
return;
|
@@ -488,6 +488,24 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
|
|
488
488
|
}
|
489
489
|
}
|
490
490
|
|
491
|
+
highlightAttribute(attributeName: string): void {
|
492
|
+
// If the attribute is not found, we highlight the tag name instead.
|
493
|
+
let animationElement = this.listItemElement.querySelector('.webkit-html-tag-name') ?? this.listItemElement;
|
494
|
+
|
495
|
+
if (this.nodeInternal.getAttribute(attributeName) !== undefined) {
|
496
|
+
const tag = this.listItemElement.getElementsByClassName('webkit-html-tag')[0];
|
497
|
+
const attributes = tag.getElementsByClassName('webkit-html-attribute');
|
498
|
+
for (const attribute of attributes) {
|
499
|
+
const attributeElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];
|
500
|
+
if (attributeElement.textContent === attributeName) {
|
501
|
+
animationElement = attributeElement;
|
502
|
+
break;
|
503
|
+
}
|
504
|
+
}
|
505
|
+
}
|
506
|
+
UI.UIUtils.runCSSAnimationOnce(animationElement, 'dom-update-highlight');
|
507
|
+
}
|
508
|
+
|
491
509
|
isClosingTag(): boolean {
|
492
510
|
return !isOpeningTag(this.tagTypeContext);
|
493
511
|
}
|
@@ -260,6 +260,10 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
|
260
260
|
this.#viewOutput?.elementsTreeOutline?.selectDOMNode(node, focus);
|
261
261
|
}
|
262
262
|
|
263
|
+
highlightNodeAttribute(node: SDK.DOMModel.DOMNode, attribute: string): void {
|
264
|
+
this.#viewOutput?.elementsTreeOutline?.highlightNodeAttribute(node, attribute);
|
265
|
+
}
|
266
|
+
|
263
267
|
setWordWrap(wrap: boolean): void {
|
264
268
|
this.#wrap = wrap;
|
265
269
|
this.performUpdate();
|
@@ -1006,6 +1010,15 @@ export class ElementsTreeOutline extends
|
|
1006
1010
|
treeElement.revealAndSelect(omitFocus);
|
1007
1011
|
}
|
1008
1012
|
|
1013
|
+
highlightNodeAttribute(node: SDK.DOMModel.DOMNode, attribute: string): void {
|
1014
|
+
const treeElement = this.findTreeElement(node);
|
1015
|
+
if (!treeElement) {
|
1016
|
+
return;
|
1017
|
+
}
|
1018
|
+
treeElement.reveal();
|
1019
|
+
treeElement.highlightAttribute(attribute);
|
1020
|
+
}
|
1021
|
+
|
1009
1022
|
treeElementFromEventInternal(event: MouseEvent): UI.TreeOutline.TreeElement|null {
|
1010
1023
|
const scrollContainer = this.element.parentElement;
|
1011
1024
|
if (!scrollContainer) {
|
@@ -284,7 +284,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
284
284
|
render(html`
|
285
285
|
<div style="min-width: min-content;" jslog=${VisualLogging.pane('layout').track({resize: true})}>
|
286
286
|
<style>${layoutPaneStyles}</style>
|
287
|
-
<style
|
287
|
+
<style>@scope to (devtools-widget > *) { ${UI.inspectorCommonStyles} }</style>
|
288
288
|
<details open>
|
289
289
|
<summary class="header"
|
290
290
|
@keydown=${input.onSummaryKeyDown}
|
@@ -52,7 +52,7 @@ import {
|
|
52
52
|
StylesSidebarPane,
|
53
53
|
} from './StylesSidebarPane.js';
|
54
54
|
|
55
|
-
const {html, nothing, render, Directives: {classMap
|
55
|
+
const {html, nothing, render, Directives: {classMap}} = Lit;
|
56
56
|
const ASTUtils = SDK.CSSPropertyParser.ASTUtils;
|
57
57
|
const FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;
|
58
58
|
const GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;
|
@@ -446,19 +446,25 @@ export class AttributeRenderer extends rendererBase(SDK.CSSPropertyParserMatcher
|
|
446
446
|
const attrCall =
|
447
447
|
this.#treeElement?.getTracingTooltip('attr', match.node, this.#matchedStyles, this.#computedStyles, context);
|
448
448
|
const tooltipId = attributeMissing ? undefined : this.#treeElement?.getTooltipId('custom-attribute');
|
449
|
+
const tooltip = tooltipId ? {tooltipId} : undefined;
|
449
450
|
// clang-format off
|
450
451
|
render(html`
|
451
452
|
<span data-title=${computedValue || ''}
|
452
453
|
jslog=${VisualLogging.link('css-variable').track({click: true, hover: true})}
|
453
|
-
>${attrCall ?? 'attr'}(<
|
454
|
-
|
455
|
-
|
456
|
-
|
454
|
+
>${attrCall ?? 'attr'}(<devtools-link-swatch class=${attributeClass} .data=${{
|
455
|
+
tooltip,
|
456
|
+
text: match.name,
|
457
|
+
isDefined: true,
|
458
|
+
onLinkActivate: () => this.#handleAttributeActivate(this.#matchedStyles.originatingNodeForStyle(match.style), match.name),
|
459
|
+
}}></devtools-link-swatch>${tooltipId ? html`
|
457
460
|
<devtools-tooltip
|
458
461
|
id=${tooltipId}
|
459
462
|
variant=rich
|
460
463
|
jslogContext=elements.css-var
|
461
|
-
>${JSON.stringify(rawValue)}</devtools-tooltip>` :
|
464
|
+
>${JSON.stringify(rawValue)}</devtools-tooltip>` : nothing}${
|
465
|
+
match.type ? html` <span class=${typeClass}>${match.type}</span>` : nothing
|
466
|
+
}${renderedFallback ? html`, <span class=${fallbackClass}>${renderedFallback.nodes}</span>` : nothing
|
467
|
+
})</span>`, varSwatch);
|
462
468
|
// clang-format on
|
463
469
|
|
464
470
|
const color = computedValue && Common.Color.parse(computedValue);
|
@@ -478,6 +484,15 @@ export class AttributeRenderer extends rendererBase(SDK.CSSPropertyParserMatcher
|
|
478
484
|
|
479
485
|
return [colorSwatch, varSwatch];
|
480
486
|
}
|
487
|
+
|
488
|
+
#handleAttributeActivate(node: SDK.DOMModel.DOMNode|null, attribute: string): void {
|
489
|
+
if (!node) {
|
490
|
+
return;
|
491
|
+
}
|
492
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AttributeLinkClicked);
|
493
|
+
Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.ATTR_LINK);
|
494
|
+
ElementsPanel.instance().highlightNodeAttribute(node, attribute);
|
495
|
+
}
|
481
496
|
}
|
482
497
|
|
483
498
|
// clang-format off
|
@@ -19,7 +19,7 @@ function getGroupDefaultTextColor(): string {
|
|
19
19
|
const DefaultStyle: () => PerfUI.FlameChart.GroupStyle = () => ({
|
20
20
|
height: 20,
|
21
21
|
padding: 2,
|
22
|
-
collapsible:
|
22
|
+
collapsible: PerfUI.FlameChart.GroupCollapsibleState.NEVER,
|
23
23
|
font: defaultFont,
|
24
24
|
color: getGroupDefaultTextColor(),
|
25
25
|
backgroundColor: 'rgba(100 0 0 / 10%)',
|
@@ -2391,6 +2391,10 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
2391
2391
|
Lastly we replace new lines with ^ and TWO new lines because the first
|
2392
2392
|
new line is there to enact the escape command the second is the character
|
2393
2393
|
to escape (in this case new line).
|
2394
|
+
|
2395
|
+
All other whitespace characters are replaced with a single space, as there
|
2396
|
+
is no way to enter their literal values in a command line, and they do break
|
2397
|
+
the command allowing for injection.
|
2394
2398
|
*/
|
2395
2399
|
const encapsChars = '^"';
|
2396
2400
|
return encapsChars +
|
@@ -2398,7 +2402,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
2398
2402
|
.replace(/"/g, '\\"')
|
2399
2403
|
.replace(/[^a-zA-Z0-9\s_\-:=+~'\/.',?;()*`]/g, '^$&')
|
2400
2404
|
.replace(/%(?=[a-zA-Z0-9_])/g, '%^')
|
2401
|
-
.replace(/[^\S \r\n]/g, '
|
2405
|
+
.replace(/[^\S \r\n]/g, ' ')
|
2402
2406
|
.replace(/\r?\n|\r/g, '^\n\n') +
|
2403
2407
|
encapsChars;
|
2404
2408
|
}
|