chrome-devtools-frontend 1.0.1518653 → 1.0.1520139

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 (143) hide show
  1. package/config/owner/COMMON_OWNERS +1 -2
  2. package/config/typescript/tsconfig.eslint.json +12 -1
  3. package/docs/ui_engineering.md +1011 -0
  4. package/eslint.config.mjs +1 -0
  5. package/front_end/core/host/GdpClient.ts +12 -3
  6. package/front_end/core/sdk/EnhancedTracesParser.ts +5 -5
  7. package/front_end/core/sdk/NetworkManager.ts +1 -0
  8. package/front_end/core/sdk/NetworkRequest.ts +10 -0
  9. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +211 -0
  10. package/front_end/core/sdk/TargetManager.ts +4 -0
  11. package/front_end/entrypoints/main/MainImpl.ts +6 -1
  12. package/front_end/entrypoints/main/main-meta.ts +3 -3
  13. package/front_end/generated/SupportedCSSProperties.js +19 -4
  14. package/front_end/models/ai_assistance/agents/AiAgent.ts +57 -10
  15. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +64 -87
  16. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
  17. package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -31
  18. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +127 -29
  19. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +106 -55
  20. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
  21. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +23 -19
  22. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
  23. package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
  24. package/front_end/models/ai_assistance/performance/AIContext.ts +63 -8
  25. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -0
  26. package/front_end/models/badges/AiExplorerBadge.ts +19 -3
  27. package/front_end/models/badges/Badge.ts +8 -1
  28. package/front_end/models/badges/CodeWhispererBadge.ts +1 -0
  29. package/front_end/models/badges/DOMDetectiveBadge.ts +1 -0
  30. package/front_end/models/badges/SpeedsterBadge.ts +1 -0
  31. package/front_end/models/badges/StarterBadge.ts +6 -0
  32. package/front_end/models/badges/badges.ts +1 -0
  33. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  34. package/front_end/models/trace/EventsSerializer.ts +4 -3
  35. package/front_end/models/trace/handlers/UserInteractionsHandler.ts +101 -73
  36. package/front_end/models/trace/helpers/Timing.ts +1 -1
  37. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +18 -8
  38. package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
  39. package/front_end/panels/ai_assistance/components/ChatView.ts +44 -68
  40. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +63 -15
  41. package/front_end/panels/ai_assistance/components/chatView.css +12 -0
  42. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  43. package/front_end/panels/animation/animationTimeline.css +4 -0
  44. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
  45. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
  46. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
  47. package/front_end/panels/common/BadgeNotification.ts +3 -3
  48. package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
  49. package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
  50. package/front_end/panels/console/ConsolePrompt.ts +6 -0
  51. package/front_end/panels/console/ConsoleView.ts +4 -2
  52. package/front_end/panels/coverage/CoverageListView.ts +133 -158
  53. package/front_end/panels/coverage/CoverageView.ts +39 -16
  54. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
  55. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
  56. package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
  57. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  58. package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
  59. package/front_end/panels/recorder/components/RecordingView.ts +2 -2
  60. package/front_end/panels/search/SearchResultsPane.ts +186 -134
  61. package/front_end/panels/search/SearchView.ts +42 -36
  62. package/front_end/panels/search/searchResultsPane.css +9 -0
  63. package/front_end/panels/search/searchView.css +0 -2
  64. package/front_end/panels/security/CookieControlsView.ts +2 -1
  65. package/front_end/panels/settings/AISettingsTab.ts +6 -3
  66. package/front_end/panels/settings/components/SyncSection.ts +26 -12
  67. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -1
  68. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -4
  69. package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
  70. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  71. package/front_end/panels/sources/sourcesView.css +6 -1
  72. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
  73. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
  74. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
  75. package/front_end/panels/timeline/TimelinePanel.ts +2 -0
  76. package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
  77. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +1 -1
  78. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +1 -1
  79. package/front_end/panels/timeline/components/RelatedInsightChips.ts +1 -1
  80. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/third_party/puppeteer/README.chromium +2 -2
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.d.ts.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +16 -25
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  104. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +19 -28
  105. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.d.ts.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +16 -25
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
  123. package/front_end/third_party/puppeteer/package/package.json +12 -4
  124. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  125. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  126. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
  127. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
  128. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
  129. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  130. package/front_end/third_party/puppeteer/package/src/util/Function.ts +22 -30
  131. package/front_end/tsconfig.json +12 -1
  132. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  133. package/front_end/ui/components/markdown_view/MarkdownImage.ts +4 -5
  134. package/front_end/ui/components/switch/SwitchImpl.ts +12 -1
  135. package/front_end/ui/components/text_editor/config.ts +16 -2
  136. package/front_end/ui/legacy/InspectorView.ts +86 -13
  137. package/front_end/ui/legacy/TabbedPane.ts +2 -1
  138. package/front_end/ui/legacy/Treeoutline.ts +3 -1
  139. package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -11
  140. package/front_end/ui/lit/i18n-template.ts +5 -2
  141. package/front_end/ui/visual_logging/KnownContextValues.ts +15 -5
  142. package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
  143. package/package.json +1 -1
@@ -107,15 +107,16 @@ const UIStrings = {
107
107
  const str_ = i18n.i18n.registerUIStrings('panels/search/SearchView.ts', UIStrings);
108
108
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
109
109
  const {ref, live} = Directives;
110
- const {widgetConfig} = UI.Widget;
110
+ const {widgetConfig, widgetRef} = UI.Widget;
111
111
 
112
- interface SearchViewInput {
112
+ export interface SearchViewInput {
113
113
  query: string;
114
114
  matchCase: boolean;
115
115
  isRegex: boolean;
116
+ searchConfig: Workspace.SearchConfig.SearchConfig|null;
116
117
  searchMessage: string;
117
118
  searchResultsMessage: string;
118
- searchResultsPane: SearchResultsPane|null;
119
+ searchResults: SearchResult[];
119
120
  progress: Common.Progress.Progress|null;
120
121
  onQueryChange: (query: string) => void;
121
122
  onQueryKeyDown: (evt: KeyboardEvent) => void;
@@ -127,19 +128,22 @@ interface SearchViewInput {
127
128
  onClearSearch: () => void;
128
129
  }
129
130
 
130
- interface SearchViewOutput {
131
+ export interface SearchViewOutput {
131
132
  focusSearchInput: () => void;
133
+ showAllMatches: () => void;
134
+ collapseAllResults: () => void;
132
135
  }
133
136
 
134
- type View = (input: SearchViewInput, output: SearchViewOutput, target: HTMLElement) => void;
137
+ export type View = (input: SearchViewInput, output: SearchViewOutput, target: HTMLElement) => void;
135
138
 
136
139
  export const DEFAULT_VIEW: View = (input, output, target) => {
137
140
  const {
138
141
  query,
139
142
  matchCase,
140
143
  isRegex,
144
+ searchConfig,
141
145
  searchMessage,
142
- searchResultsPane,
146
+ searchResults,
143
147
  searchResultsMessage,
144
148
  progress,
145
149
  onQueryChange,
@@ -159,12 +163,13 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
159
163
  {PH1: UI.KeyboardShortcut.KeyboardShortcut.shortcutToString(UI.KeyboardShortcut.Keys.Enter)});
160
164
  } else if (progress) {
161
165
  header = i18nString(UIStrings.searching);
162
- } else if (!searchResultsPane) {
166
+ } else if (!searchResults.length) {
163
167
  header = i18nString(UIStrings.noMatchesFound);
164
168
  text = i18nString(UIStrings.nothingMatchedTheQuery);
165
169
  }
166
170
  // clang-format off
167
171
  render(html`
172
+ <style>${UI.inspectorCommonStyles}</style>
168
173
  <style>${searchViewStyles}</style>
169
174
  <div class="search-drawer-header" @keydown=${onPanelKeyDown}>
170
175
  <div class="search-container">
@@ -240,9 +245,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
240
245
  </devtools-toolbar>
241
246
  </div>
242
247
  <div class="search-results" @keydown=${onPanelKeyDown}>
243
- ${searchResultsPane
244
- ? html`<devtools-widget .widgetConfig=${widgetConfig(UI.Widget.VBox)}>
245
- ${searchResultsPane.element}
248
+ ${searchResults.length
249
+ ? html`<devtools-widget .widgetConfig=${widgetConfig(SearchResultsPane, {searchResults, searchConfig})}
250
+ ${widgetRef(SearchResultsPane, w => {
251
+ output.showAllMatches = () => void w.showAllMatches();
252
+ output.collapseAllResults = () => void w.collapseAllResults(); })}>
246
253
  </devtools-widget>`
247
254
  : html`<devtools-widget .widgetConfig=${widgetConfig(UI.EmptyWidget.EmptyWidget, {header, text})}>
248
255
  </devtools-widget>`}
@@ -263,6 +270,8 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
263
270
  export class SearchView extends UI.Widget.VBox {
264
271
  readonly #view: View;
265
272
  #focusSearchInput = (): void => {};
273
+ #showAllMatches = (): void => {};
274
+ #collapseAllResults = (): void => {};
266
275
  #isIndexing: boolean;
267
276
  #searchId: number;
268
277
  #searchMatchesCount: number;
@@ -271,7 +280,6 @@ export class SearchView extends UI.Widget.VBox {
271
280
  #searchingView: UI.Widget.Widget|null;
272
281
  #searchConfig: Workspace.SearchConfig.SearchConfig|null;
273
282
  #pendingSearchConfig: Workspace.SearchConfig.SearchConfig|null;
274
- #searchResultsPane: SearchResultsPane|null;
275
283
  #progress: Common.Progress.Progress|null;
276
284
  #query: string;
277
285
  #matchCase = false;
@@ -288,7 +296,7 @@ export class SearchView extends UI.Widget.VBox {
288
296
  // We throttle adding search results, otherwise we trigger DOM layout for each
289
297
  // result added.
290
298
  #throttler: Common.Throttler.Throttler;
291
- #pendingSearchResults: SearchResult[] = [];
299
+ #searchResults: SearchResult[] = [];
292
300
 
293
301
  constructor(settingKey: string, throttler: Common.Throttler.Throttler, view = DEFAULT_VIEW) {
294
302
  super({
@@ -307,7 +315,6 @@ export class SearchView extends UI.Widget.VBox {
307
315
  this.#searchingView = null;
308
316
  this.#searchConfig = null;
309
317
  this.#pendingSearchConfig = null;
310
- this.#searchResultsPane = null;
311
318
  this.#progress = null;
312
319
  this.#throttler = throttler;
313
320
 
@@ -325,8 +332,9 @@ export class SearchView extends UI.Widget.VBox {
325
332
  query: this.#query,
326
333
  matchCase: this.#matchCase,
327
334
  isRegex: this.#isRegex,
335
+ searchConfig: this.#searchConfig,
328
336
  searchMessage: this.#searchMessage,
329
- searchResultsPane: this.#searchResultsPane,
337
+ searchResults: this.#searchResults.filter(searchResult => searchResult.matchesCount()),
330
338
  searchResultsMessage: this.#searchResultsMessage,
331
339
  progress: this.#progress,
332
340
  onQueryChange: (query: string) => {
@@ -344,6 +352,12 @@ export class SearchView extends UI.Widget.VBox {
344
352
  const output: SearchViewOutput = {
345
353
  set focusSearchInput(value: () => void) {
346
354
  that.#focusSearchInput = value;
355
+ },
356
+ set showAllMatches(value: () => void) {
357
+ that.#showAllMatches = value;
358
+ },
359
+ set collapseAllResults(value: () => void) {
360
+ that.#collapseAllResults = value;
347
361
  }
348
362
  };
349
363
  this.#view(input, output, this.contentElement);
@@ -436,25 +450,18 @@ export class SearchView extends UI.Widget.VBox {
436
450
  this.#onIndexingFinished();
437
451
  return;
438
452
  }
439
- if (!this.#searchResultsPane) {
440
- this.#searchResultsPane = this.createSearchResultsPane();
441
- }
442
- this.#pendingSearchResults.push(searchResult);
443
- void this.#throttler.schedule(async () => this.#addPendingSearchResults());
453
+ this.#searchResults.push(searchResult);
454
+ void this.#throttler.schedule(async () => this.#setSearchResults());
444
455
  }
445
456
 
446
- protected createSearchResultsPane(): SearchResultsPane {
447
- return new SearchResultsPane((this.#searchConfig as Workspace.SearchConfig.SearchConfig));
448
- }
449
-
450
- #addPendingSearchResults(): void {
451
- for (const searchResult of this.#pendingSearchResults) {
457
+ #setSearchResults(): void {
458
+ this.#searchMatchesCount = 0;
459
+ this.#searchResultsCount = 0;
460
+ this.#nonEmptySearchResultsCount = 0;
461
+ for (const searchResult of this.#searchResults) {
452
462
  this.#addSearchResult(searchResult);
453
- if (searchResult.matchesCount()) {
454
- this.#searchResultsPane?.addSearchResult(searchResult);
455
- }
456
463
  }
457
- this.#pendingSearchResults = [];
464
+ this.performUpdate();
458
465
  }
459
466
 
460
467
  #onSearchFinished(searchId: number, finished: boolean): void {
@@ -463,7 +470,6 @@ export class SearchView extends UI.Widget.VBox {
463
470
  }
464
471
  this.#progress = null;
465
472
  this.#searchFinished(finished);
466
- this.#searchConfig = null;
467
473
  UI.ARIAUtils.LiveAnnouncer.alert(this.#searchMessage + ' ' + this.#searchResultsMessage);
468
474
  }
469
475
 
@@ -484,7 +490,7 @@ export class SearchView extends UI.Widget.VBox {
484
490
 
485
491
  #resetSearch(): void {
486
492
  this.#stopSearch();
487
- this.#searchResultsPane = null;
493
+ this.#searchResults = [];
488
494
  this.#searchMessage = '';
489
495
  this.#searchResultsMessage = '';
490
496
  this.performUpdate();
@@ -497,12 +503,12 @@ export class SearchView extends UI.Widget.VBox {
497
503
  if (this.#searchScope) {
498
504
  this.#searchScope.stopSearch();
499
505
  }
500
- this.#searchConfig = null;
501
506
  }
502
507
 
503
508
  #searchStarted(): void {
504
509
  this.#searchMatchesCount = 0;
505
510
  this.#searchResultsCount = 0;
511
+ this.#searchResults = [];
506
512
  this.#nonEmptySearchResultsCount = 0;
507
513
  if (!this.#searchingView) {
508
514
  this.#searchingView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.searching), '');
@@ -541,7 +547,7 @@ export class SearchView extends UI.Widget.VBox {
541
547
 
542
548
  #searchFinished(finished: boolean): void {
543
549
  this.#searchMessage = finished ? i18nString(UIStrings.searchFinished) : i18nString(UIStrings.searchInterrupted);
544
- this.performUpdate();
550
+ this.requestUpdate();
545
551
  }
546
552
 
547
553
  override focus(): void {
@@ -590,15 +596,15 @@ export class SearchView extends UI.Widget.VBox {
590
596
  // "Command + Alt + [" for Mac
591
597
  const shouldCollapseAllForMac =
592
598
  isMac && event.metaKey && !event.ctrlKey && event.altKey && event.code === 'BracketLeft';
593
- // "Command + Alt + {" for other platforms
599
+ // "Ctrl + Alt + {" for other platforms
594
600
  const shouldCollapseAllForOtherPlatforms =
595
601
  !isMac && event.ctrlKey && !event.metaKey && event.shiftKey && event.code === 'BracketLeft';
596
602
 
597
603
  if (shouldShowAllForMac || shouldShowAllForOtherPlatforms) {
598
- this.#searchResultsPane?.showAllMatches();
604
+ this.#showAllMatches();
599
605
  void VisualLogging.logKeyDown(event.currentTarget, event, 'show-all-matches');
600
606
  } else if (shouldCollapseAllForMac || shouldCollapseAllForOtherPlatforms) {
601
- this.#searchResultsPane?.collapseAllResults();
607
+ this.#collapseAllResults();
602
608
  void VisualLogging.logKeyDown(event.currentTarget, event, 'collapse-all-results');
603
609
  }
604
610
  }
@@ -31,6 +31,11 @@ li.search-result {
31
31
  white-space: pre;
32
32
  }
33
33
 
34
+ li.search-result .tree-element-title {
35
+ display: flex;
36
+ width: 100%;
37
+ }
38
+
34
39
  li.search-result:hover {
35
40
  background-color: var(--sys-color-state-hover-on-subtle);
36
41
  }
@@ -68,6 +73,10 @@ li.search-match {
68
73
  white-space: pre;
69
74
  }
70
75
 
76
+ li.search-match .tree-element-title {
77
+ display: flex;
78
+ }
79
+
71
80
  li.search-match.selected:focus-visible {
72
81
  background: var(--sys-color-tonal-container);
73
82
  }
@@ -5,7 +5,6 @@
5
5
  */
6
6
 
7
7
  .search-drawer-header {
8
- align-items: center;
9
8
  flex-shrink: 0;
10
9
  overflow: hidden;
11
10
  display: inline-flex;
@@ -14,7 +13,6 @@
14
13
  .search-container {
15
14
  border-bottom: 1px solid var(--sys-color-divider);
16
15
  display: flex;
17
- height: 100%;
18
16
  align-items: center;
19
17
  flex-grow: 1;
20
18
  }
@@ -186,8 +186,9 @@ export class CookieControlsView extends UI.Widget.VBox {
186
186
  <devtools-switch
187
187
  .checked=${Boolean(toggleEnabledSetting.get())}
188
188
  .disabled=${Boolean(enterpriseEnabledSetting.get())}
189
+ .label=${'Temporarily limit third-party cookies, only when DevTools is open'}
190
+ data-testid="cookie-control-override"
189
191
  @switchchange=${()=>{input.inputChanged(!toggleEnabledSetting.get(), toggleEnabledSetting);}}
190
- aria-label="Temporarily limit third-party cookies, only when DevTools is open"
191
192
  jslog=${VisualLogging.toggle(toggleEnabledSetting.name).track({click: true})}
192
193
  >
193
194
  </devtools-switch>
@@ -381,8 +381,10 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen
381
381
  text: noLogging ? i18nString(UIStrings.codeSuggestionsSendDataNoLogging) :
382
382
  i18nString(UIStrings.codeSuggestionsSendData)
383
383
  }],
384
- // TODO: Add a relevant link
385
- learnMoreLink: {url: '', linkJSLogContext: 'learn-more.code-completion'},
384
+ learnMoreLink: {
385
+ url: ' https://developers.chrome.com/docs/devtools/ai-assistance/code-completion',
386
+ linkJSLogContext: 'learn-more.code-completion'
387
+ },
386
388
  settingExpandState: {
387
389
  isSettingExpanded: false,
388
390
  expandSettingJSLogContext: 'code-completion.accordion',
@@ -590,8 +592,9 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen
590
592
  .checked=${Boolean(setting.get()) && !isDisabled}
591
593
  .jslogContext=${setting.name || ''}
592
594
  .disabled=${isDisabled}
595
+ .label=${disabledReasonsJoined || settingData.enableSettingText}
596
+ data-testid=${settingData.enableSettingText}
593
597
  @switchchange=${this.#toggleSetting.bind(this, setting)}
594
- aria-label=${disabledReasonsJoined || settingData.enableSettingText}
595
598
  ></devtools-switch>
596
599
  </div>
597
600
  <div class=${classMap(detailsClasses)}>
@@ -12,6 +12,7 @@ import * as Host from '../../../core/host/host.js';
12
12
  import * as i18n from '../../../core/i18n/i18n.js';
13
13
  import type * as Platform from '../../../core/platform/platform.js';
14
14
  import * as Root from '../../../core/root/root.js';
15
+ import * as SDK from '../../../core/sdk/sdk.js';
15
16
  import * as Badges from '../../../models/badges/badges.js';
16
17
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
17
18
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
@@ -30,10 +31,10 @@ const UIStrings = {
30
31
  */
31
32
  syncDisabled: 'To turn this setting on, you must enable Chrome sync.',
32
33
  /**
33
- * @description Text shown to the user in the Settings UI. 'This setting' refers
34
- * to a checkbox that is disabled.
34
+ * @description Text shown to the user in the Settings UI. Explains why the checkbox
35
+ * for saving DevTools settings to the user's Google account is inactive.
35
36
  */
36
- preferencesSyncDisabled: 'To turn this setting on, you must first enable settings sync in Chrome.',
37
+ preferencesSyncDisabled: 'You need to first enable saving `Chrome` settings in your `Google` account.',
37
38
  /**
38
39
  * @description Label for the account email address. Shown in the DevTools Settings UI in
39
40
  * front of the email address currently used for Chrome Sync.
@@ -252,16 +253,29 @@ function renderWarningIfNeeded(syncInfo: Host.InspectorFrontendHostAPI.SyncInfor
252
253
  'chrome://settings/syncSetup/advanced' as Platform.DevToolsPath.UrlString;
253
254
  const warningText =
254
255
  !syncInfo.isSyncActive ? i18nString(UIStrings.syncDisabled) : i18nString(UIStrings.preferencesSyncDisabled);
256
+ const handleClick = (event: Event): void => {
257
+ const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();
258
+ if (rootTarget === null) {
259
+ return;
260
+ }
261
+
262
+ void rootTarget.targetAgent().invoke_createTarget({url: warningLink}).then(result => {
263
+ if (result.getError()) {
264
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(warningLink);
265
+ }
266
+ });
267
+ event.consume();
268
+ };
255
269
  // clang-format off
256
270
  return html`
257
- <devtools-chrome-link .href=${warningLink}>
258
- <devtools-button
259
- aria-describedby=settings-sync-info
260
- .iconName=${'info'}
261
- .variant=${Buttons.Button.Variant.ICON}
262
- .size=${Buttons.Button.Size.SMALL}>
263
- </devtools-button>
264
- </devtools-chrome-link>
271
+ <devtools-button
272
+ aria-describedby=settings-sync-info
273
+ aria-label=${warningText}
274
+ .iconName=${'info'}
275
+ .variant=${Buttons.Button.Variant.ICON}
276
+ .size=${Buttons.Button.Size.SMALL}
277
+ @click=${handleClick}>
278
+ </devtools-button>
265
279
  <devtools-tooltip
266
280
  id=settings-sync-info
267
281
  variant=simple>
@@ -315,7 +329,7 @@ function renderGdpSectionIfNeeded({
315
329
  // clang-format off
316
330
  return html`
317
331
  <div class="gdp-profile-header">
318
- <div class="gdp-logo" role="img" tabindex="0" aria-label="Google Developer Program"></div>
332
+ <div class="gdp-logo" role="img" aria-label="Google Developer Program"></div>
319
333
  </div>
320
334
  `;
321
335
  // clang-format on
@@ -585,7 +585,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
585
585
  ${i18nString(UIStrings.mobileCheckboxLabel)}
586
586
  </label>
587
587
  ` :
588
- html``;
588
+ Lit.nothing;
589
589
  return html`
590
590
  <span class="full-row label">${i18nString(UIStrings.deviceModel)}</span>
591
591
  <div class="full-row brand-row" aria-label=${i18nString(UIStrings.deviceProperties)} role="group">
@@ -59,6 +59,9 @@ export class AiCodeCompletionPlugin extends Plugin {
59
59
  if (showTeaser) {
60
60
  this.#teaser = new PanelCommon.AiCodeCompletionTeaser({onDetach: this.#detachAiCodeCompletionTeaser.bind(this)});
61
61
  }
62
+
63
+ this.#aiCodeCompletionDisclaimerContainer.classList.add('ai-code-completion-disclaimer-container');
64
+ this.#aiCodeCompletionDisclaimerContainer.style.paddingInline = 'var(--sys-size-3)';
62
65
  }
63
66
 
64
67
  static override accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
@@ -100,6 +103,7 @@ export class AiCodeCompletionPlugin extends Plugin {
100
103
  if (this.#teaser) {
101
104
  if (update.docChanged) {
102
105
  update.view.dispatch({effects: this.#teaserCompartment.reconfigure([])});
106
+ window.clearTimeout(this.#teaserDisplayTimeout);
103
107
  this.#addTeaserPluginToCompartment(update.view);
104
108
  } else if (update.selectionSet && update.state.doc.length > 0) {
105
109
  update.view.dispatch({effects: this.#teaserCompartment.reconfigure([])});
@@ -184,10 +188,6 @@ export class AiCodeCompletionPlugin extends Plugin {
184
188
  }
185
189
 
186
190
  #addTeaserPluginToCompartment = Common.Debouncer.debounce((view: CodeMirror.EditorView) => {
187
- if (this.#teaserDisplayTimeout) {
188
- window.clearTimeout(this.#teaserDisplayTimeout);
189
- this.#teaserDisplayTimeout = undefined;
190
- }
191
191
  this.#teaserDisplayTimeout = window.setTimeout(() => {
192
192
  this.#addTeaserPluginToCompartmentImmediate(view);
193
193
  }, AiCodeCompletion.AiCodeCompletion.DELAY_BEFORE_SHOWING_RESPONSE_MS);
@@ -10,6 +10,7 @@ import * as i18n from '../../core/i18n/i18n.js';
10
10
  import * as Platform from '../../core/platform/platform.js';
11
11
  import * as SDK from '../../core/sdk/sdk.js';
12
12
  import * as Protocol from '../../generated/protocol.js';
13
+ import * as Badges from '../../models/badges/badges.js';
13
14
  import * as Bindings from '../../models/bindings/bindings.js';
14
15
  import * as Breakpoints from '../../models/breakpoints/breakpoints.js';
15
16
  import * as Formatter from '../../models/formatter/formatter.js';
@@ -1628,6 +1629,9 @@ export class DebuggerPlugin extends Plugin {
1628
1629
  this.uiSourceCode, lineNumber, columnNumber, condition, enabled, isLogpoint,
1629
1630
  Breakpoints.BreakpointManager.BreakpointOrigin.USER_ACTION);
1630
1631
  this.breakpointWasSetForTest(lineNumber, columnNumber, condition, enabled);
1632
+ if (bp) {
1633
+ Badges.UserBadges.instance().recordAction(Badges.BadgeAction.BREAKPOINT_ADDED);
1634
+ }
1631
1635
  return bp;
1632
1636
  }
1633
1637
 
@@ -1197,7 +1197,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
1197
1197
  } else if (position === 'bottom') {
1198
1198
  vertically = true;
1199
1199
  } else {
1200
- vertically = UI.InspectorView.InspectorView.instance().element.offsetWidth < 680;
1200
+ vertically = this.splitWidget.element.offsetWidth < 680;
1201
1201
  }
1202
1202
 
1203
1203
  if (this.sidebarPaneView && vertically === !this.splitWidget.isVertical()) {
@@ -14,11 +14,16 @@
14
14
 
15
15
  #sources-panel-sources-view .sources-toolbar {
16
16
  display: flex;
17
- flex: 0 0 27px;
17
+ flex: 0 0 auto;
18
18
  background-color: var(--sys-color-cdt-base-container);
19
19
  border-top: 1px solid var(--sys-color-divider);
20
20
  overflow: hidden;
21
21
  z-index: 0;
22
+ align-items: flex-end;
23
+
24
+ devtools-toolbar:first-of-type {
25
+ flex-wrap: wrap;
26
+ }
22
27
  }
23
28
 
24
29
  .source-frame-debugger-script {
@@ -226,7 +226,7 @@ export class ThirdPartyTreeViewWidget extends TimelineTreeView.TimelineTreeView
226
226
  const unattributed = i18nString(UIStrings.unattributed);
227
227
  const id = typeof node.id === 'symbol' ? undefined : node.id;
228
228
  // This `undefined` is [unattributed]
229
- // TODO(paulirish,aixba): Improve attribution to reduce amount of items in [unattributed].
229
+ // TODO(paulirish): Improve attribution to reduce amount of items in [unattributed].
230
230
  const domainName = id ? this.entityMapper()?.entityForEvent(node.event)?.name || id : undefined;
231
231
  return {name: domainName || unattributed, color, icon: undefined};
232
232
  }
@@ -254,14 +254,6 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW
254
254
  if (perfAIEntryPointEnabled && this.parsedTrace) {
255
255
  const callTree = AIAssistance.AICallTree.fromEvent(entry, this.parsedTrace);
256
256
  if (callTree) {
257
- let focus = UI.Context.Context.instance().flavor(AIAssistance.AgentFocus);
258
- if (focus) {
259
- focus = focus.withCallTree(callTree);
260
- } else {
261
- focus = AIAssistance.AgentFocus.fromCallTree(callTree);
262
- }
263
- UI.Context.Context.instance().setFlavor(AIAssistance.AgentFocus, focus);
264
-
265
257
  const action = UI.ActionRegistry.ActionRegistry.instance().getAction(PERF_AI_ACTION_ID);
266
258
 
267
259
  if (Root.Runtime.hostConfig.devToolsAiSubmenuPrompts?.enabled) {
@@ -1516,13 +1516,13 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
1516
1516
  return;
1517
1517
  }
1518
1518
 
1519
- const callTree =
1520
- selectionIsEvent(selection) ? AIAssistance.AICallTree.fromEvent(selection.event, this.#parsedTrace) : null;
1519
+ const event = selectionIsEvent(selection) ? selection.event : null;
1520
+
1521
1521
  let focus = UI.Context.Context.instance().flavor(AIAssistance.AgentFocus);
1522
1522
  if (focus) {
1523
- focus = focus.withCallTree(callTree);
1524
- } else if (callTree) {
1525
- focus = AIAssistance.AgentFocus.fromCallTree(callTree);
1523
+ focus = focus.withEvent(event);
1524
+ } else if (event) {
1525
+ focus = AIAssistance.AgentFocus.fromEvent(this.#parsedTrace, event);
1526
1526
  } else {
1527
1527
  focus = null;
1528
1528
  }
@@ -44,6 +44,7 @@ import * as Root from '../../core/root/root.js';
44
44
  import * as SDK from '../../core/sdk/sdk.js';
45
45
  import type * as Protocol from '../../generated/protocol.js';
46
46
  import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
47
+ import * as Badges from '../../models/badges/badges.js';
47
48
  import * as CrUXManager from '../../models/crux-manager/crux-manager.js';
48
49
  import * as TextUtils from '../../models/text_utils/text_utils.js';
49
50
  import * as Trace from '../../models/trace/trace.js';
@@ -1924,6 +1925,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1924
1925
  } else {
1925
1926
  await this.#startTraceRecording();
1926
1927
  }
1928
+ Badges.UserBadges.instance().recordAction(Badges.BadgeAction.PERFORMANCE_RECORDING_STARTED);
1927
1929
  }
1928
1930
 
1929
1931
  private async stopRecording(): Promise<void> {
@@ -1005,7 +1005,7 @@ export class AggregatedTimelineTreeView extends TimelineTreeView {
1005
1005
  case AggregatedTimelineTreeView.GroupBy.Subdomain:
1006
1006
  case AggregatedTimelineTreeView.GroupBy.ThirdParties: {
1007
1007
  // This `undefined` is [unattributed]
1008
- // TODO(paulirish,aixba): Improve attribution to reduce amount of items in [unattributed].
1008
+ // TODO(paulirish): Improve attribution to reduce amount of items in [unattributed].
1009
1009
  const domainName = id ? this.beautifyDomainName(id, node) : undefined;
1010
1010
  return {name: domainName || unattributed, color, icon: undefined};
1011
1011
  }
@@ -158,7 +158,7 @@ export class LayoutShiftDetails extends UI.Widget.Widget {
158
158
  export const DEFAULT_VIEW: (input: ViewInput, output: object, target: HTMLElement) => void =
159
159
  (input, _output, target) => {
160
160
  if (!input.event || !input.parsedTrace) {
161
- render(html``, target);
161
+ render(Lit.nothing, target);
162
162
  return;
163
163
  }
164
164
 
@@ -197,7 +197,7 @@ export interface ViewInput {
197
197
  export const DEFAULT_VIEW: (
198
198
  input: ViewInput, output: object, target: HTMLElement) => void = (input, _output, target) => {
199
199
  if (!input.request) {
200
- render(html``, target);
200
+ render(Lit.nothing, target);
201
201
  return;
202
202
  }
203
203
  const {request} = input;
@@ -86,7 +86,7 @@ export const DEFAULT_VIEW: (input: ViewInput, output: object, target: HTMLElemen
86
86
  const {activeEvent, eventToInsightsMap} = input;
87
87
  const relatedInsights = activeEvent ? eventToInsightsMap.get(activeEvent) ?? [] : [];
88
88
  if (!activeEvent || eventToInsightsMap.size === 0 || relatedInsights.length === 0) {
89
- render(html``, target);
89
+ render(Lit.nothing, target);
90
90
  return;
91
91
  }
92
92
 
@@ -478,7 +478,7 @@ export class SidebarSingleInsightSet extends HTMLElement {
478
478
  insightSetKey,
479
479
  } = this.#data;
480
480
  if (!parsedTrace?.insights || !insightSetKey) {
481
- Lit.render(html``, this.#shadow, {host: this});
481
+ Lit.render(Lit.nothing, this.#shadow, {host: this});
482
482
  return;
483
483
  }
484
484
 
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://source.chromium.org/chromium/chromium/src/+/main:components/variations/proto/devtools/
3
3
  Version: N/A
4
- Revision: 8b6a2b940e6b293e99d648cdf34f8d26ae731d64
4
+ Revision: c0cd408650a942d836b07c15facd3f4fede1d578
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -1,10 +1,10 @@
1
1
  Name: Puppeteer Core
2
2
  Short Name: Puppeteer Core
3
3
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
4
- Version: 24.22.0
4
+ Version: 24.22.3
5
5
  License: Apache-2.0
6
6
  License File: LICENSE
7
- Revision: 0e2affad10d4e4e19ef07504d9b8784b3da9ff91
7
+ Revision: cb4342d28e3450852cbf3c21e16bbe2dc40747df
8
8
  Security Critical: no
9
9
  Shipped: yes
10
10
  Update Mechanism: Autoroll
@@ -34,8 +34,8 @@ export declare abstract class Realm extends EventEmitter<{
34
34
  }> {
35
35
  #private;
36
36
  protected readonly disposables: {
37
- "__#59109@#disposed": boolean;
38
- "__#59109@#stack": Disposable[];
37
+ "__#59155@#disposed": boolean;
38
+ "__#59155@#stack": Disposable[];
39
39
  readonly disposed: boolean;
40
40
  dispose(): void;
41
41
  use<T extends Disposable | null | undefined>(value: T): T;