chrome-devtools-frontend 1.0.1592129 → 1.0.1592362

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.
Files changed (35) hide show
  1. package/front_end/core/host/UserMetrics.ts +2 -1
  2. package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
  3. package/front_end/core/root/ExperimentNames.ts +1 -0
  4. package/front_end/core/sdk/EmulationModel.ts +41 -1
  5. package/front_end/entrypoints/main/MainImpl.ts +8 -0
  6. package/front_end/generated/InspectorBackendCommands.ts +1 -0
  7. package/front_end/generated/protocol-mapping.d.ts +6 -0
  8. package/front_end/generated/protocol-proxy-api.d.ts +7 -0
  9. package/front_end/generated/protocol.ts +16 -0
  10. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +379 -25
  11. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgentOverlay.ts +87 -0
  12. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +8 -8
  13. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +65 -44
  14. package/front_end/models/computed_style/ComputedStyleModel.ts +40 -6
  15. package/front_end/models/emulation/DeviceModeModel.ts +47 -0
  16. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -2
  17. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +55 -1
  18. package/front_end/panels/application/CookieItemsView.ts +194 -134
  19. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
  20. package/front_end/panels/application/StorageItemsToolbar.ts +25 -2
  21. package/front_end/panels/application/cookieItemsView.css +28 -26
  22. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  23. package/front_end/panels/elements/ComputedStyleWidget.ts +11 -25
  24. package/front_end/panels/elements/ElementsPanel.ts +26 -3
  25. package/front_end/panels/elements/StylePropertyTreeElement.ts +33 -0
  26. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +148 -1
  27. package/front_end/panels/elements/elements-meta.ts +3 -5
  28. package/front_end/panels/elements/stylePropertiesTreeOutline.css +6 -0
  29. package/front_end/panels/emulation/DeviceModeToolbar.ts +25 -0
  30. package/front_end/panels/timeline/components/metricCard.css +0 -4
  31. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +13 -2
  32. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +44 -24
  33. package/front_end/ui/visual_logging/Debugging.ts +4 -0
  34. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  35. package/package.json +1 -1
@@ -1,7 +1,6 @@
1
1
  // Copyright 2021 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-imperative-dom-api */
5
4
 
6
5
  /*
7
6
  * Copyright (C) 2009 Apple Inc. All rights reserved.
@@ -35,9 +34,11 @@
35
34
  import * as Common from '../../core/common/common.js';
36
35
  import * as i18n from '../../core/i18n/i18n.js';
37
36
  import * as SDK from '../../core/sdk/sdk.js';
37
+ import * as Geometry from '../../models/geometry/geometry.js';
38
38
  import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
39
39
  import * as CookieTable from '../../ui/legacy/components/cookie_table/cookie_table.js';
40
40
  import * as UI from '../../ui/legacy/legacy.js';
41
+ import {html, render} from '../../ui/lit/lit.js';
41
42
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
42
43
 
43
44
  import cookieItemsViewStyles from './cookieItemsView.css.js';
@@ -80,74 +81,24 @@ const UIStrings = {
80
81
  } as const;
81
82
  const str_ = i18n.i18n.registerUIStrings('panels/application/CookieItemsView.ts', UIStrings);
82
83
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
83
- class CookiePreviewWidget extends UI.Widget.VBox {
84
- private cookie: SDK.Cookie.Cookie|null;
85
- private showDecodedSetting: Common.Settings.Setting<boolean>;
86
- private toggle: UI.UIUtils.CheckboxLabel;
87
- private value: HTMLDivElement;
88
-
89
- constructor() {
90
- super({jslog: `${VisualLogging.section('cookie-preview')}`});
91
- this.setMinimumSize(230, 45);
92
- this.cookie = null;
93
- this.showDecodedSetting = Common.Settings.Settings.instance().createSetting('cookie-view-show-decoded', false);
84
+ const {Size} = Geometry;
94
85
 
95
- const header = document.createElement('div');
96
- header.classList.add('cookie-preview-widget-header');
97
- const span = document.createElement('span');
98
- span.classList.add('cookie-preview-widget-header-label');
99
- span.textContent = 'Cookie Value';
100
- header.appendChild(span);
101
- this.contentElement.appendChild(header);
102
-
103
- const toggle = UI.UIUtils.CheckboxLabel.create(
104
- i18nString(UIStrings.showUrlDecoded), this.showDecodedSetting.get(), undefined, 'show-url-decoded');
105
- toggle.title = i18nString(UIStrings.showUrlDecoded);
106
- toggle.classList.add('cookie-preview-widget-toggle');
107
- toggle.addEventListener('click', () => this.showDecoded(!this.showDecodedSetting.get()));
108
- header.appendChild(toggle);
109
- this.toggle = toggle;
110
-
111
- const value = document.createElement('div');
112
- value.classList.add('cookie-preview-widget-cookie-value');
113
- value.textContent = '';
114
- value.addEventListener('dblclick', this.handleDblClickOnCookieValue.bind(this));
115
- this.value = value;
116
-
117
- this.contentElement.classList.add('cookie-preview-widget');
118
- this.contentElement.appendChild(value);
119
- }
120
-
121
- showDecoded(decoded: boolean): void {
122
- if (!this.cookie) {
123
- return;
124
- }
125
- this.showDecodedSetting.set(decoded);
126
- this.toggle.checked = decoded;
127
- this.updatePreview();
128
- }
86
+ interface CookiePreviewWidgetInput {
87
+ cookie: SDK.Cookie.Cookie|null;
88
+ showDecoded: boolean;
89
+ onShowDecodedChanged: (showDecoded: boolean) => void;
90
+ }
129
91
 
130
- private updatePreview(): void {
131
- if (this.cookie) {
132
- this.value.textContent =
133
- this.showDecodedSetting.get() ? decodeURIComponent(this.cookie.value()) : this.cookie.value();
134
- } else {
135
- this.value.textContent = '';
136
- }
137
- }
92
+ type CookiePreviewWidgetView = (input: CookiePreviewWidgetInput, output: undefined, target: HTMLElement) => void;
138
93
 
139
- setCookie(cookie: SDK.Cookie.Cookie): void {
140
- this.cookie = cookie;
141
- this.updatePreview();
142
- }
94
+ export const DEFAULT_COOKIE_PREVIEW_WIDGET_VIEW: CookiePreviewWidgetView = (input, output, target) => {
95
+ const cookieValue =
96
+ input.cookie ? (input.showDecoded ? decodeURIComponent(input.cookie.value()) : input.cookie.value()) : '';
143
97
 
144
- /**
145
- * Select all text even if there a spaces in it
146
- */
147
- handleDblClickOnCookieValue(event: Event): void {
98
+ function handleDblClickOnCookieValue(event: Event): void {
148
99
  event.preventDefault();
149
100
  const range = document.createRange();
150
- range.selectNode(this.value);
101
+ range.selectNode(event.currentTarget as Node);
151
102
  const selection = window.getSelection();
152
103
  if (!selection) {
153
104
  return;
@@ -155,73 +106,159 @@ class CookiePreviewWidget extends UI.Widget.VBox {
155
106
  selection.removeAllRanges();
156
107
  selection.addRange(range);
157
108
  }
109
+
110
+ // clang-format off
111
+ render(html`<style>${cookieItemsViewStyles}</style>
112
+ <div class="cookie-preview-widget">
113
+ <div class="cookie-preview-widget-header">
114
+ <span class="cookie-preview-widget-header-label">Cookie Value</span>
115
+ <devtools-checkbox
116
+ .checked=${input.showDecoded}
117
+ @change=${(e: Event) => input.onShowDecodedChanged((e.target as HTMLInputElement).checked)}
118
+ title=${i18nString(UIStrings.showUrlDecoded)}
119
+ jslog=${VisualLogging.toggle('show-url-decoded').track({ click: true })}>
120
+ ${i18nString(UIStrings.showUrlDecoded)}
121
+ </devtools-checkbox>
122
+ </div>
123
+ <div class="cookie-preview-widget-cookie-value"
124
+ @dblclick=${handleDblClickOnCookieValue}>
125
+ ${cookieValue}
126
+ </div>
127
+ </div>
128
+ `,
129
+ // clang-format on
130
+ target);
131
+ };
132
+
133
+ class CookiePreviewWidget extends UI.Widget.VBox {
134
+ private view: CookiePreviewWidgetView;
135
+ #cookie: SDK.Cookie.Cookie|null;
136
+ private showDecodedSetting: Common.Settings.Setting<boolean>;
137
+
138
+ constructor(element?: HTMLElement, view: CookiePreviewWidgetView = DEFAULT_COOKIE_PREVIEW_WIDGET_VIEW) {
139
+ super(element, {jslog: `${VisualLogging.section('cookie-preview')}`});
140
+ this.view = view;
141
+ this.setMinimumSize(230, 45);
142
+ this.#cookie = null;
143
+ this.showDecodedSetting = Common.Settings.Settings.instance().createSetting('cookie-view-show-decoded', false);
144
+ this.requestUpdate();
145
+ }
146
+
147
+ set cookie(cookie: SDK.Cookie.Cookie|null) {
148
+ this.#cookie = cookie;
149
+ this.requestUpdate();
150
+ }
151
+
152
+ override performUpdate(): void {
153
+ const input: CookiePreviewWidgetInput = {
154
+ cookie: this.#cookie,
155
+ showDecoded: this.showDecodedSetting.get(),
156
+ onShowDecodedChanged: (showDecoded: boolean) => {
157
+ this.showDecodedSetting.set(showDecoded);
158
+ this.requestUpdate();
159
+ },
160
+ };
161
+ this.view(input, undefined, this.contentElement);
162
+ }
163
+ }
164
+
165
+ interface CookieItemsViewInput {
166
+ cookieDomain: string;
167
+ cookiesData: CookieTable.CookiesTable.CookiesTableData;
168
+ onSaveCookie: (arg0: SDK.Cookie.Cookie, arg1: SDK.Cookie.Cookie|null) => Promise<boolean>;
169
+ onRefresh: () => void;
170
+ onSelect: (arg0: SDK.Cookie.Cookie|null) => void;
171
+ onDelete: (arg0: SDK.Cookie.Cookie, arg1: () => void) => void;
172
+ onDeleteSelectedItems: () => void;
173
+ onDeleteAllItems: () => void;
174
+ onRefreshItems: () => void;
175
+ selectedCookie: SDK.Cookie.Cookie|null;
176
+ }
177
+
178
+ interface CookieItemsViewOutput {
179
+ toolbar: StorageItemsToolbar;
158
180
  }
159
181
 
182
+ type View = (input: CookieItemsViewInput, output: CookieItemsViewOutput, target: HTMLElement) => void;
183
+
184
+ export const DEFAULT_VIEW: View = (input, output, target) => {
185
+ // clang-format off
186
+ render(html`<style>${cookieItemsViewStyles}</style>
187
+ <devtools-widget class="storage-view"
188
+ .widgetConfig=${UI.Widget.widgetConfig(UI.Widget.VBox, {minimumSize: new Size(0, 50)})}>
189
+ <devtools-widget
190
+ .widgetConfig=${UI.Widget.widgetConfig(StorageItemsToolbar, {
191
+ onDeleteSelectedCallback: input.onDeleteSelectedItems,
192
+ onDeleteAllCallback: input.onDeleteAllItems,
193
+ onRefreshCallback: input.onRefreshItems,
194
+ })}
195
+ class=flex-none
196
+ ${UI.Widget.widgetRef(StorageItemsToolbar, toolbar => { output.toolbar = toolbar; })}
197
+ ></devtools-widget>
198
+ <devtools-split-view sidebar-position="second" name="cookie-items-split-view-state">
199
+ <devtools-widget
200
+ slot="main"
201
+ .widgetConfig=${UI.Widget.widgetConfig(UI.Widget.VBox, {minimumSize: new Size(0, 50)})}>
202
+ <devtools-widget slot="main" .widgetConfig=${UI.Widget.widgetConfig(CookieTable.CookiesTable.CookiesTable, {
203
+ cookieDomain: input.cookieDomain,
204
+ cookiesData: input.cookiesData,
205
+ saveCallback: input.onSaveCookie,
206
+ refreshCallback: input.onRefresh,
207
+ selectedCallback: input.onSelect,
208
+ deleteCallback: input.onDelete,
209
+ editable: true,
210
+ })}
211
+ ></devtools-widget>
212
+ </devtools-widget>
213
+ <devtools-widget
214
+ slot="sidebar"
215
+ .widgetConfig=${UI.Widget.widgetConfig(UI.Widget.VBox, {minimumSize: new Size(0, 50)})}
216
+ jslog=${VisualLogging.pane('preview').track({resize: true})}>
217
+ ${input.selectedCookie ?
218
+ html`<devtools-widget .widgetConfig=${UI.Widget.widgetConfig(CookiePreviewWidget, {
219
+ cookie: input.selectedCookie
220
+ })}></devtools-widget>` :
221
+ html`<devtools-widget .widgetConfig=${UI.Widget.widgetConfig(UI.EmptyWidget.EmptyWidget, {
222
+ header: i18nString(UIStrings.noCookieSelected),
223
+ text: i18nString(UIStrings.selectACookieToPreviewItsValue)
224
+ })}></devtools-widget>`}
225
+ </devtools-widget>
226
+ </devtools-split-view>
227
+ </devtools-widget>
228
+ `,
229
+ // clang-format on
230
+ target);
231
+ };
232
+
160
233
  export class CookieItemsView extends UI.Widget.VBox {
234
+ private view: View;
161
235
  private model: SDK.CookieModel.CookieModel;
162
236
  private cookieDomain: string;
163
- private cookiesTable: CookieTable.CookiesTable.CookiesTable;
164
- private readonly splitWidget: UI.SplitWidget.SplitWidget;
165
- private readonly previewPanel: UI.Widget.VBox;
166
- private readonly previewWidget: CookiePreviewWidget;
167
- private readonly emptyWidget: UI.EmptyWidget.EmptyWidget;
168
237
  private onlyIssuesFilterUI: UI.Toolbar.ToolbarCheckbox;
169
238
  private allCookies: SDK.Cookie.Cookie[];
170
239
  private shownCookies: SDK.Cookie.Cookie[];
171
240
  private selectedCookie: SDK.Cookie.Cookie|null;
172
- #toolbar: StorageItemsToolbar;
173
- constructor(model: SDK.CookieModel.CookieModel, cookieDomain: string) {
241
+ #toolbar?: StorageItemsToolbar;
242
+
243
+ constructor(model: SDK.CookieModel.CookieModel, cookieDomain: string, view: View = DEFAULT_VIEW) {
174
244
  super({jslog: `${VisualLogging.pane('cookies-data')}`});
175
- this.registerRequiredCSS(cookieItemsViewStyles);
176
245
 
177
- this.element.classList.add('storage-view');
246
+ this.view = view;
178
247
 
179
248
  this.model = model;
180
249
  this.cookieDomain = cookieDomain;
181
250
 
182
- this.#toolbar = new StorageItemsToolbar();
183
- this.#toolbar.element.classList.add('flex-none');
184
- this.#toolbar.show(this.element);
185
-
186
- this.cookiesTable = new CookieTable.CookiesTable.CookiesTable(
187
- undefined,
188
- /* renderInline */ false, this.saveCookie.bind(this), this.refreshItems.bind(this),
189
- this.handleCookieSelected.bind(this), this.deleteCookie.bind(this));
190
-
191
- this.cookiesTable.setMinimumSize(0, 50);
192
-
193
- this.splitWidget = new UI.SplitWidget.SplitWidget(
194
- /* isVertical: */ false, /* secondIsSidebar: */ true, 'cookie-items-split-view-state');
195
- this.splitWidget.show(this.element);
196
-
197
- this.previewPanel = new UI.Widget.VBox();
198
- this.previewPanel.element.setAttribute('jslog', `${VisualLogging.pane('preview').track({resize: true})}`);
199
- const resizer = this.previewPanel.element.createChild('div', 'preview-panel-resizer');
200
-
201
- this.splitWidget.setMainWidget(this.cookiesTable);
202
- this.splitWidget.setSidebarWidget(this.previewPanel);
203
- this.splitWidget.installResizer(resizer);
204
-
205
- this.previewWidget = new CookiePreviewWidget();
206
- this.emptyWidget = new UI.EmptyWidget.EmptyWidget(
207
- i18nString(UIStrings.noCookieSelected), i18nString(UIStrings.selectACookieToPreviewItsValue));
208
- this.emptyWidget.show(this.previewPanel.contentElement);
209
-
210
251
  this.onlyIssuesFilterUI = new UI.Toolbar.ToolbarCheckbox(
211
252
  i18nString(UIStrings.onlyShowCookiesWithAnIssue), i18nString(UIStrings.onlyShowCookiesWhichHaveAn), () => {
212
253
  this.updateWithCookies(this.allCookies);
213
254
  }, 'only-show-cookies-with-issues');
214
- this.#toolbar.appendToolbarItem(this.onlyIssuesFilterUI);
215
255
 
216
256
  this.allCookies = [];
217
257
  this.shownCookies = [];
218
258
  this.selectedCookie = null;
219
259
 
220
260
  this.setCookiesDomain(model, cookieDomain);
221
-
222
- this.#toolbar.addEventListener(StorageItemsToolbar.Events.DELETE_SELECTED, this.deleteSelectedItem, this);
223
- this.#toolbar.addEventListener(StorageItemsToolbar.Events.DELETE_ALL, this.deleteAllItems, this);
224
- this.#toolbar.addEventListener(StorageItemsToolbar.Events.REFRESH, this.refreshItems, this);
261
+ this.requestUpdate();
225
262
  }
226
263
 
227
264
  setCookiesDomain(model: SDK.CookieModel.CookieModel, domain: string): void {
@@ -232,6 +269,43 @@ export class CookieItemsView extends UI.Widget.VBox {
232
269
  this.model.addEventListener(SDK.CookieModel.Events.COOKIE_LIST_UPDATED, this.onCookieListUpdate, this);
233
270
  }
234
271
 
272
+ override performUpdate(): void {
273
+ const that = this;
274
+ const output = {
275
+ set toolbar(toolbar: StorageItemsToolbar) {
276
+ if (that.#toolbar === toolbar) {
277
+ return;
278
+ }
279
+ that.#toolbar = toolbar;
280
+ that.#toolbar.appendToolbarItem(that.onlyIssuesFilterUI);
281
+ that.updateWithCookies(that.allCookies);
282
+ },
283
+ };
284
+
285
+ const cookiesData: CookieTable.CookiesTable.CookiesTableData = {
286
+ cookies: this.shownCookies,
287
+ cookieToBlockedReasons: this.model.getCookieToBlockedReasonsMap(),
288
+ };
289
+
290
+ const parsedURL = Common.ParsedURL.ParsedURL.fromString(this.cookieDomain);
291
+ const host = parsedURL ? parsedURL.host : '';
292
+
293
+ const input: CookieItemsViewInput = {
294
+ cookieDomain: host,
295
+ cookiesData,
296
+ onSaveCookie: this.saveCookie.bind(this),
297
+ onRefresh: this.refreshItems.bind(this),
298
+ onSelect: this.handleCookieSelected.bind(this),
299
+ onDelete: this.deleteCookie.bind(this),
300
+ onDeleteSelectedItems: this.deleteSelectedItem.bind(this),
301
+ onDeleteAllItems: this.deleteAllItems.bind(this),
302
+ onRefreshItems: this.refreshItems.bind(this),
303
+ selectedCookie: this.selectedCookie,
304
+ };
305
+
306
+ this.view(input, output, this.contentElement);
307
+ }
308
+
235
309
  override wasShown(): void {
236
310
  super.wasShown();
237
311
  this.refreshItems();
@@ -242,22 +316,15 @@ export class CookieItemsView extends UI.Widget.VBox {
242
316
  return;
243
317
  }
244
318
  this.selectedCookie = cookie;
245
-
246
- if (!cookie) {
247
- this.previewWidget.detach();
248
- this.emptyWidget.show(this.previewPanel.contentElement);
249
- } else {
250
- this.emptyWidget.detach();
251
- this.previewWidget.setCookie(cookie);
252
- this.previewWidget.show(this.previewPanel.contentElement);
253
- }
319
+ this.requestUpdate();
254
320
  }
255
321
 
256
- private handleCookieSelected(): void {
257
- const cookie = this.cookiesTable.selectedCookie();
258
- this.#toolbar.setCanDeleteSelected(Boolean(cookie));
259
-
260
- this.showPreview(cookie);
322
+ private handleCookieSelected(selectedCookie: SDK.Cookie.Cookie|null): void {
323
+ if (!this.#toolbar) {
324
+ return;
325
+ }
326
+ this.#toolbar.setCanDeleteSelected(Boolean(selectedCookie));
327
+ this.showPreview(selectedCookie);
261
328
  }
262
329
 
263
330
  private async saveCookie(newCookie: SDK.Cookie.Cookie, oldCookie: SDK.Cookie.Cookie|null): Promise<boolean> {
@@ -272,12 +339,10 @@ export class CookieItemsView extends UI.Widget.VBox {
272
339
  }
273
340
 
274
341
  private updateWithCookies(allCookies: SDK.Cookie.Cookie[]): void {
342
+ if (!this.#toolbar) {
343
+ return;
344
+ }
275
345
  this.allCookies = allCookies;
276
-
277
- const parsedURL = Common.ParsedURL.ParsedURL.fromString(this.cookieDomain);
278
- const host = parsedURL ? parsedURL.host : '';
279
- this.cookiesTable.setCookieDomain(host);
280
-
281
346
  this.shownCookies = this.filter(allCookies, cookie => `${cookie.name()} ${cookie.value()} ${cookie.domain()}`);
282
347
  if (this.#toolbar.hasFilter()) {
283
348
  this.#toolbar.setDeleteAllTitle(i18nString(UIStrings.clearFilteredCookies));
@@ -286,16 +351,12 @@ export class CookieItemsView extends UI.Widget.VBox {
286
351
  this.#toolbar.setDeleteAllTitle(i18nString(UIStrings.clearAllCookies));
287
352
  this.#toolbar.setDeleteAllGlyph('clear-list');
288
353
  }
289
- this.cookiesTable.setCookies(this.shownCookies, this.model.getCookieToBlockedReasonsMap());
290
354
  UI.ARIAUtils.LiveAnnouncer.alert(
291
355
  i18nString(UIStrings.numberOfCookiesShownInTableS, {PH1: this.shownCookies.length}));
292
356
  this.#toolbar.setCanFilter(true);
293
357
  this.#toolbar.setCanDeleteAll(this.shownCookies.length > 0);
294
- this.#toolbar.setCanDeleteSelected(Boolean(this.cookiesTable.selectedCookie()));
295
-
296
- if (!this.cookiesTable.selectedCookie()) {
297
- this.showPreview(null);
298
- }
358
+ this.#toolbar.setCanDeleteSelected(Boolean(this.selectedCookie));
359
+ this.requestUpdate();
299
360
  }
300
361
 
301
362
  filter<T>(items: T[], keyFunction: (arg0: T) => string): T[] {
@@ -308,7 +369,7 @@ export class CookieItemsView extends UI.Widget.VBox {
308
369
  }
309
370
  return false;
310
371
  };
311
- return items.filter(item => this.#toolbar.filterRegex?.test(keyFunction(item)) ?? true).filter(predicate);
372
+ return items.filter(item => this.#toolbar?.filterRegex?.test(keyFunction(item)) ?? true).filter(predicate);
312
373
  }
313
374
 
314
375
  /**
@@ -320,10 +381,9 @@ export class CookieItemsView extends UI.Widget.VBox {
320
381
  }
321
382
 
322
383
  deleteSelectedItem(): void {
323
- const selectedCookie = this.cookiesTable.selectedCookie();
324
- if (selectedCookie) {
384
+ if (this.selectedCookie) {
325
385
  this.showPreview(null);
326
- void this.model.deleteCookie(selectedCookie);
386
+ void this.model.deleteCookie(this.selectedCookie);
327
387
  }
328
388
  }
329
389
 
@@ -119,7 +119,7 @@ export class RootTreeElement extends ApplicationPanelTreeElement {
119
119
  if (isSiteAllowed && !isElementPresent) {
120
120
  // Appending a child element that already has children requires a workaround of
121
121
  // detaching and repopulating them so that the selection background color UI works.
122
- // TODO(crbug.com/471021582): Can this fix safely be moved to Treeoutline.ts?
122
+ // TODO(crbug.com/486866983): Can this fix safely be moved to Treeoutline.ts?
123
123
  this.appendChild(siteTreeElement);
124
124
  const children = [...siteTreeElement.children()];
125
125
  siteTreeElement.removeChildren();
@@ -106,6 +106,9 @@ export class StorageItemsToolbar extends
106
106
  #deleteAllButtonIconName = 'clear';
107
107
  #deleteAllButtonTitle: string = i18nString(UIStrings.clearAll);
108
108
  #mainToolbarItems: UI.Toolbar.ToolbarItem[] = [];
109
+ #onRefreshCallback?: () => void;
110
+ #onDeleteAllCallback?: () => void;
111
+ #onDeleteSelectedCallback?: () => void;
109
112
 
110
113
  constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
111
114
  super(element);
@@ -113,6 +116,18 @@ export class StorageItemsToolbar extends
113
116
  this.filterRegex = null;
114
117
  }
115
118
 
119
+ set onRefreshCallback(callback: () => void) {
120
+ this.#onRefreshCallback = callback;
121
+ }
122
+
123
+ set onDeleteAllCallback(callback: () => void) {
124
+ this.#onDeleteAllCallback = callback;
125
+ }
126
+
127
+ set onDeleteSelectedCallback(callback: () => void) {
128
+ this.#onDeleteSelectedCallback = callback;
129
+ }
130
+
116
131
  set metadataView(view: ApplicationComponents.StorageMetadataView.StorageMetadataView) {
117
132
  this.#metadataView = view;
118
133
  }
@@ -135,11 +150,18 @@ export class StorageItemsToolbar extends
135
150
  metadataView: this.metadataView,
136
151
  onFilterChanged: this.filterChanged.bind(this),
137
152
  onRefresh: () => {
153
+ this.#onRefreshCallback?.();
138
154
  this.dispatchEventToListeners(StorageItemsToolbar.Events.REFRESH);
139
155
  UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.refreshedStatus));
140
156
  },
141
- onDeleteAll: () => this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_ALL),
142
- onDeleteSelected: () => this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_SELECTED),
157
+ onDeleteAll: () => {
158
+ this.#onDeleteAllCallback?.();
159
+ this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_ALL);
160
+ },
161
+ onDeleteSelected: () => {
162
+ this.#onDeleteSelectedCallback?.();
163
+ this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_SELECTED);
164
+ },
143
165
  };
144
166
  this.#view(viewInput, {}, this.contentElement);
145
167
  }
@@ -165,6 +187,7 @@ export class StorageItemsToolbar extends
165
187
 
166
188
  filterChanged({detail: text}: CustomEvent<string|null>): void {
167
189
  this.filterRegex = text ? new RegExp(Platform.StringUtilities.escapeForRegExp(text), 'i') : null;
190
+ this.#onRefreshCallback?.();
168
191
  this.dispatchEventToListeners(StorageItemsToolbar.Events.REFRESH);
169
192
  }
170
193
 
@@ -4,34 +4,36 @@
4
4
  * found in the LICENSE file.
5
5
  */
6
6
 
7
- .cookie-preview-widget {
8
- padding: 2px 6px;
9
- }
7
+ @scope to (devtools-widget > *) {
8
+ .cookie-preview-widget {
9
+ padding: 2px 6px;
10
+ }
10
11
 
11
- .cookie-preview-widget-header {
12
- font-weight: bold;
13
- user-select: none;
14
- white-space: nowrap;
15
- margin-bottom: 4px;
16
- flex: 0 0 18px;
17
- display: flex;
18
- align-items: center;
19
- }
12
+ .cookie-preview-widget-header {
13
+ font-weight: bold;
14
+ user-select: none;
15
+ white-space: nowrap;
16
+ margin-bottom: 4px;
17
+ flex: 0 0 18px;
18
+ display: flex;
19
+ align-items: center;
20
+ }
20
21
 
21
- .cookie-preview-widget-header-label {
22
- line-height: 18px;
23
- flex-shrink: 0;
24
- }
22
+ .cookie-preview-widget-header-label {
23
+ line-height: 18px;
24
+ flex-shrink: 0;
25
+ }
25
26
 
26
- .cookie-preview-widget-cookie-value {
27
- user-select: text;
28
- word-break: break-all;
29
- flex: 1;
30
- overflow: auto;
31
- }
27
+ .cookie-preview-widget-cookie-value {
28
+ user-select: text;
29
+ word-break: break-all;
30
+ flex: 1;
31
+ overflow: auto;
32
+ }
32
33
 
33
- .cookie-preview-widget-toggle {
34
- margin-left: 12px;
35
- font-weight: normal;
36
- flex-shrink: 1;
34
+ .cookie-preview-widget-toggle {
35
+ margin-left: 12px;
36
+ font-weight: normal;
37
+ flex-shrink: 1;
38
+ }
37
39
  }
@@ -1675,7 +1675,7 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
1675
1675
  Breakpoints.BreakpointManager.EMPTY_BREAKPOINT_CONDITION, /* enabled */ true,
1676
1676
  /* isLogpoint */ false, Breakpoints.BreakpointManager.BreakpointOrigin.OTHER);
1677
1677
  const aiPanel = await AiAssistancePanel.AiAssistancePanel.instance();
1678
- void aiPanel.handleBreakpointConversation(uiLocation);
1678
+ void aiPanel.handleBreakpointConversation(uiLocation, this.text);
1679
1679
  }
1680
1680
  };
1681
1681
 
@@ -297,6 +297,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
297
297
  #computedStyleModel?: ComputedStyleModule.ComputedStyleModel.ComputedStyleModel;
298
298
  #nodeStyle: ComputedStyleModule.ComputedStyleModel.ComputedStyle|null = null;
299
299
  #matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null = null;
300
+ #propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>|null = null;
300
301
  private readonly showInheritedComputedStylePropertiesSetting: Common.Settings.Setting<boolean>;
301
302
  private readonly groupComputedStylesSetting: Common.Settings.Setting<boolean>;
302
303
  private filterRegex: RegExp|null = null;
@@ -335,9 +336,9 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
335
336
  #filterIsRegex = false;
336
337
  #allowUserControl = true;
337
338
 
338
- constructor() {
339
- super({useShadowDom: true});
340
- this.#view = DEFAULT_VIEW;
339
+ constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
340
+ super(element, {useShadowDom: true});
341
+ this.#view = view;
341
342
 
342
343
  this.contentElement.classList.add('styles-sidebar-computed-style-widget');
343
344
 
@@ -432,6 +433,11 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
432
433
  this.requestUpdate();
433
434
  }
434
435
 
436
+ set propertyTraces(propertyTraces: Map<string, SDK.CSSProperty.CSSProperty[]>|null) {
437
+ this.#propertyTraces = propertyTraces;
438
+ this.requestUpdate();
439
+ }
440
+
435
441
  get computedStyleModel(): ComputedStyleModule.ComputedStyleModel.ComputedStyleModel|undefined {
436
442
  return this.#computedStyleModel;
437
443
  }
@@ -477,7 +483,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
477
483
  uniqueProperties.sort(propertySorter);
478
484
 
479
485
  const node = nodeStyle.node;
480
- const propertyTraces = this.computePropertyTraces(matchedStyles);
486
+ const propertyTraces = this.#propertyTraces || new Map();
481
487
  const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
482
488
  const showInherited = this.#shouldShowAllStyles();
483
489
  const tree: Array<TreeOutline.TreeOutlineUtils.TreeNode<ComputedStyleData>> = [];
@@ -518,7 +524,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
518
524
  }
519
525
 
520
526
  const node = nodeStyle.node;
521
- const propertyTraces = this.computePropertyTraces(matchedStyles);
527
+ const propertyTraces = this.#propertyTraces || new Map();
522
528
  const nonInheritedProperties = this.computeNonInheritedProperties(matchedStyles);
523
529
  const showInherited = this.showInheritedComputedStylePropertiesSetting.get();
524
530
 
@@ -664,26 +670,6 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
664
670
  void contextMenu.show();
665
671
  }
666
672
 
667
- private computePropertyTraces(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):
668
- Map<string, SDK.CSSProperty.CSSProperty[]> {
669
- const result = new Map<string, SDK.CSSProperty.CSSProperty[]>();
670
- for (const style of matchedStyles.nodeStyles()) {
671
- const allProperties = style.allProperties();
672
- for (const property of allProperties) {
673
- if (!property.activeInStyle() || !matchedStyles.propertyState(property)) {
674
- continue;
675
- }
676
- if (!result.has(property.name)) {
677
- result.set(property.name, []);
678
- }
679
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
680
- // @ts-expect-error
681
- result.get(property.name).push(property);
682
- }
683
- }
684
- return result;
685
- }
686
-
687
673
  private computeNonInheritedProperties(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles): Set<string> {
688
674
  const result = new Set<string>();
689
675
  for (const style of matchedStyles.nodeStyles()) {