chrome-devtools-frontend 1.0.1667564 → 1.0.1669021

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 (211) hide show
  1. package/.agents/skills/devtools-ci/SKILL.md +65 -0
  2. package/.agents/skills/devtools-setting-migration/SKILL.md +290 -0
  3. package/.agents/skills/gerrit-cli/SKILL.md +59 -0
  4. package/.agents/skills/gerrit-cli/references/commands.md +93 -0
  5. package/.agents/skills/gerrit-cli/references/workflows.md +56 -0
  6. package/.agents/skills/gerrit-cli/scripts/gerrit_client_wrapper.py +47 -0
  7. package/.agents/skills/gerrit-cli/scripts/import_upstream.py +230 -0
  8. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +11 -4
  9. package/.agents/skills/ui-widgets/SKILL.md +25 -1
  10. package/docs/contributing/infrastructure.md +7 -1
  11. package/docs/ui_engineering.md +44 -1
  12. package/front_end/core/common/Settings.ts +11 -4
  13. package/front_end/core/host/AidaClient.ts +66 -47
  14. package/front_end/core/host/GcaClient.ts +4 -6
  15. package/front_end/core/host/ResourceLoader.ts +4 -2
  16. package/front_end/core/root/Runtime.ts +5 -5
  17. package/front_end/core/sdk/CSSModel.test.api.ts +102 -0
  18. package/front_end/core/sdk/CSSModel.ts +3 -2
  19. package/front_end/core/sdk/ConsoleModel.ts +3 -2
  20. package/front_end/core/sdk/DebuggerModel.ts +16 -7
  21. package/front_end/core/sdk/SDKSettings.ts +38 -0
  22. package/front_end/core/sdk/sdk-meta.ts +0 -120
  23. package/front_end/core/sdk/sdk.ts +2 -0
  24. package/front_end/entrypoints/main/MainImpl.ts +10 -3
  25. package/front_end/foundation/Universe.ts +7 -0
  26. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  27. package/front_end/generated/protocol.ts +11 -3
  28. package/front_end/models/ai_assistance/AiAgent2.ts +1 -1
  29. package/front_end/models/ai_assistance/AiUtils.ts +67 -4
  30. package/front_end/models/ai_assistance/BuiltInAi.ts +11 -6
  31. package/front_end/models/ai_assistance/ChangeManager.ts +17 -1
  32. package/front_end/models/ai_assistance/StorageItem.ts +26 -5
  33. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +2 -19
  34. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +2 -3
  35. package/front_end/models/javascript_metadata/NativeFunctions.js +22 -9
  36. package/front_end/models/source_map_scopes/NamesResolver.ts +23 -17
  37. package/front_end/models/trace/handlers/RendererHandler.ts +20 -4
  38. package/front_end/models/trace/types/File.ts +1 -0
  39. package/front_end/models/workspace/UISourceCode.ts +0 -10
  40. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +61 -182
  41. package/front_end/panels/ai_assistance/components/ChatInput.ts +25 -8
  42. package/front_end/panels/ai_assistance/components/ChatMessage.ts +13 -69
  43. package/front_end/panels/ai_assistance/components/ChatView.ts +14 -8
  44. package/front_end/panels/ai_assistance/components/chatMessage.css +2 -20
  45. package/front_end/panels/application/ApplicationPanelSidebar.ts +2 -2
  46. package/front_end/panels/application/ApplicationPanelTreeElement.ts +41 -3
  47. package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +131 -134
  48. package/front_end/panels/application/ServiceWorkersView.ts +8 -8
  49. package/front_end/panels/application/application.ts +2 -0
  50. package/front_end/panels/application/components/AdsView.ts +10 -6
  51. package/front_end/panels/application/preloading/PreloadingView.ts +53 -45
  52. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +111 -119
  53. package/front_end/panels/application/preloading/components/preloadingDetailsReportView.css +22 -24
  54. package/front_end/panels/application/serviceWorkerUpdateCycleView.css +105 -102
  55. package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +107 -96
  56. package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +17 -19
  57. package/front_end/panels/common/AiCodeCompletionTeaser.ts +6 -6
  58. package/front_end/panels/common/AiCodeGenerationTeaser.ts +28 -26
  59. package/front_end/panels/common/common.ts +1 -1
  60. package/front_end/panels/console/ConsoleInsightTeaser.ts +6 -8
  61. package/front_end/panels/console/ConsoleView.ts +6 -4
  62. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  63. package/front_end/panels/console/console-meta.ts +28 -0
  64. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -1
  65. package/front_end/panels/elements/StylesSidebarPane.ts +3 -2
  66. package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -2
  67. package/front_end/panels/emulation/DeviceModeView.ts +63 -104
  68. package/front_end/panels/emulation/DeviceModeWrapper.ts +18 -4
  69. package/front_end/panels/explain/components/ConsoleInsight.ts +4 -6
  70. package/front_end/panels/explain/explain-meta.ts +7 -49
  71. package/front_end/panels/network/NetworkDataGridNode.ts +1 -1
  72. package/front_end/panels/network/NetworkLogView.ts +1 -0
  73. package/front_end/panels/network/OriginalResourceChunkView.ts +340 -0
  74. package/front_end/panels/network/ResourceChunkView.ts +72 -46
  75. package/front_end/panels/network/ResourceDirectSocketChunkView.ts +3 -2
  76. package/front_end/panels/network/ResourceWebSocketFrameView.ts +3 -3
  77. package/front_end/panels/network/originalResourceChunkView.css +49 -0
  78. package/front_end/panels/screencast/ScreencastView.ts +401 -260
  79. package/front_end/panels/screencast/screencastView.css +113 -100
  80. package/front_end/panels/sensors/LocationsSettingsTab.ts +329 -135
  81. package/front_end/panels/sensors/locationsSettingsTab.css +78 -4
  82. package/front_end/panels/settings/AISettingsTab.ts +17 -100
  83. package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +2 -2
  84. package/front_end/panels/snippets/SnippetsQuickOpen.ts +4 -4
  85. package/front_end/panels/sources/AddSourceMapURLDialog.ts +3 -3
  86. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -3
  87. package/front_end/panels/sources/BreakpointEditDialog.ts +14 -14
  88. package/front_end/panels/sources/BreakpointsView.ts +14 -14
  89. package/front_end/panels/sources/CallStackSidebarPane.ts +6 -6
  90. package/front_end/panels/sources/CategorizedBreakpointL10n.ts +18 -18
  91. package/front_end/panels/sources/CoveragePlugin.ts +7 -7
  92. package/front_end/panels/sources/DebuggerPausedMessage.ts +23 -23
  93. package/front_end/panels/sources/DebuggerPlugin.ts +31 -31
  94. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -2
  95. package/front_end/panels/sources/GoToLineQuickOpen.ts +10 -10
  96. package/front_end/panels/sources/NavigatorView.ts +34 -27
  97. package/front_end/panels/sources/OutlineQuickOpen.ts +3 -3
  98. package/front_end/panels/sources/PersistenceActions.ts +9 -9
  99. package/front_end/panels/sources/ProfilePlugin.ts +1 -1
  100. package/front_end/panels/sources/ScopeChainSidebarPane.ts +5 -5
  101. package/front_end/panels/sources/SnippetsPlugin.ts +2 -2
  102. package/front_end/panels/sources/SourcesNavigator.ts +20 -18
  103. package/front_end/panels/sources/SourcesPanel.ts +26 -25
  104. package/front_end/panels/sources/SourcesView.ts +5 -6
  105. package/front_end/panels/sources/TabbedEditorContainer.ts +3 -3
  106. package/front_end/panels/sources/ThreadsSidebarPane.ts +1 -1
  107. package/front_end/panels/sources/UISourceCodeFrame.ts +0 -2
  108. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +7 -7
  109. package/front_end/panels/sources/components/HeadersView.ts +2 -2
  110. package/front_end/panels/sources/sources-meta.ts +164 -71
  111. package/front_end/panels/sources/sources.ts +0 -2
  112. package/front_end/panels/timeline/TimelineHistoryManager.ts +14 -3
  113. package/front_end/panels/timeline/TimelineLoader.ts +72 -42
  114. package/front_end/panels/timeline/TimelinePanel.ts +29 -4
  115. package/front_end/panels/timeline/timelineHistoryManager.css +4 -0
  116. package/front_end/third_party/chromium/README.chromium +1 -1
  117. package/front_end/third_party/puppeteer/README.chromium +2 -2
  118. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +187 -1
  119. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +91 -38
  120. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +145 -2
  121. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +0 -2
  123. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts +0 -2
  125. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +0 -2
  127. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.d.ts +3 -2
  129. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.d.ts.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.js +8 -2
  131. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.js.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts +0 -2
  133. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js +0 -2
  135. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js.map +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +1 -3
  137. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +0 -2
  139. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts +0 -1
  141. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts.map +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js +0 -1
  143. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +2 -2
  146. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
  147. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.d.ts +5 -1
  148. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.d.ts.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js +12 -0
  150. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js.map +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js +4 -1
  153. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js.map +1 -1
  154. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +5 -1
  155. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  156. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +49 -0
  157. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  158. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.d.ts +0 -6
  159. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.d.ts.map +1 -1
  160. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js +0 -6
  161. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js.map +1 -1
  162. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
  164. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
  166. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.d.ts.map +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.js +3 -0
  168. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.js.map +1 -1
  169. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +0 -3
  170. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +0 -3
  172. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
  173. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  174. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  175. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/disposable.d.ts +2 -2
  176. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/disposable.js +2 -2
  177. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  178. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  179. package/front_end/third_party/puppeteer/package/lib/types.d.ts +187 -1
  180. package/front_end/third_party/puppeteer/package/package.json +5 -5
  181. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +155 -2
  182. package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +0 -2
  183. package/front_end/third_party/puppeteer/package/src/api/Dialog.ts +10 -2
  184. package/front_end/third_party/puppeteer/package/src/api/JSHandle.ts +0 -2
  185. package/front_end/third_party/puppeteer/package/src/api/Page.ts +1 -3
  186. package/front_end/third_party/puppeteer/package/src/api/Realm.ts +0 -1
  187. package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +4 -2
  188. package/front_end/third_party/puppeteer/package/src/bidi/Browser.ts +17 -0
  189. package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +5 -4
  190. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +66 -0
  191. package/front_end/third_party/puppeteer/package/src/common/EventEmitter.ts +0 -6
  192. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  193. package/front_end/third_party/puppeteer/package/src/injected/util.ts +4 -1
  194. package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +0 -3
  195. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  196. package/front_end/third_party/puppeteer/package/src/util/disposable.ts +2 -2
  197. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  198. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +9 -7
  199. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +7 -8
  200. package/front_end/ui/legacy/Dialog.ts +103 -4
  201. package/front_end/ui/legacy/InspectorView.ts +1 -5
  202. package/front_end/ui/legacy/PopoverHelper.ts +5 -5
  203. package/front_end/ui/legacy/TabbedPane.ts +7 -2
  204. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +40 -24
  205. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -0
  206. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +8 -4
  207. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +14 -7
  208. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +11 -1
  209. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  210. package/package.json +1 -1
  211. package/front_end/panels/sources/AiWarningInfobarPlugin.ts +0 -78
@@ -1,14 +1,16 @@
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
  import * as i18n from '../../core/i18n/i18n.js';
7
6
  import * as SDK from '../../core/sdk/sdk.js';
8
7
  import * as Protocol from '../../generated/protocol.js';
9
8
  import * as UI from '../../ui/legacy/legacy.js';
9
+ import {html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
10
10
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
11
11
 
12
+ import serviceWorkerUpdateCycleViewStyles from './serviceWorkerUpdateCycleView.css.js';
13
+
12
14
  const UIStrings = {
13
15
  /**
14
16
  * @description Text in Indexed DBViews of the Application panel
@@ -35,17 +37,107 @@ const UIStrings = {
35
37
  } as const;
36
38
  const str_ = i18n.i18n.registerUIStrings('panels/application/ServiceWorkerUpdateCycleView.ts', UIStrings);
37
39
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
38
- export class ServiceWorkerUpdateCycleView {
39
- private registration: SDK.ServiceWorkerManager.ServiceWorkerRegistration;
40
+ export interface ViewInput {
41
+ timeRanges: ServiceWorkerUpdateRange[];
42
+ expandedRows: Set<string>;
43
+ onFocus: (event: Event) => void;
44
+ onKeydown: (event: Event, key: string) => void;
45
+ onClick: (event: Event, key: string) => void;
46
+ }
47
+
48
+ export type View = (input: ViewInput, output: unknown, target: HTMLElement) => void;
49
+
50
+ export const DEFAULT_VIEW: View = (input, _output, target) => {
51
+ let tableRows: LitTemplate|typeof nothing = nothing;
52
+
53
+ if (input.timeRanges.length > 0) {
54
+ const startTimes = input.timeRanges.map(r => r.start);
55
+ const endTimes = input.timeRanges.map(r => r.end);
56
+ const startTime = startTimes.reduce((a, b) => Math.min(a, b));
57
+ const endTime = endTimes.reduce((a, b) => Math.max(a, b));
58
+ const scale = 100 / (endTime - startTime);
59
+
60
+ tableRows = html`${input.timeRanges.map(range => {
61
+ const phaseName = range.phase;
62
+ const left = (scale * (range.start - startTime));
63
+ const right = (scale * (endTime - range.end));
64
+ const key = `${range.id}-${range.phase}`;
65
+ const expanded = input.expandedRows.has(key);
66
+
67
+ // clang-format off
68
+ return html`
69
+ <tr class="service-worker-update-timeline" jslog=${VisualLogging.treeItem('update-timeline').track({
70
+ click: true,
71
+ resize: true,
72
+ keydown: 'ArrowLeft|ArrowRight|ArrowUp|ArrowDown|Enter|Space',
73
+ })}>
74
+ <td class="service-worker-update-timing-bar-clickable" tabindex="0" role="switch"
75
+ aria-checked=${expanded ? 'true' : 'false'}
76
+ @focus=${input.onFocus}
77
+ @keydown=${(e: Event) => input.onKeydown(e, key)}
78
+ @click=${(e: Event) => input.onClick(e, key)}
79
+ jslog=${VisualLogging.expand('timing-info').track({click: true})}>
80
+ #${range.id}
81
+ </td>
82
+ <td>${phaseName}</td>
83
+ <td>
84
+ <div class="service-worker-update-timing-row">
85
+ <span class="service-worker-update-timing-bar ${phaseName.toLowerCase()}"
86
+ style="left: ${left}%; right: ${right}%;">\u200B</span>
87
+ </div>
88
+ </td>
89
+ </tr>
90
+ <tr class="service-worker-update-timing-bar-details ${expanded ? 'service-worker-update-timing-bar-details-expanded' : 'service-worker-update-timing-bar-details-collapsed'}" tabindex="0">
91
+ <td colspan="3"><span>${i18nString(UIStrings.startTimeS, {PH1: new Date(range.start).toISOString()})}</span></td>
92
+ </tr>
93
+ <tr class="service-worker-update-timing-bar-details ${expanded ? 'service-worker-update-timing-bar-details-expanded' : 'service-worker-update-timing-bar-details-collapsed'}" tabindex="0">
94
+ <td colspan="3"><span>${i18nString(UIStrings.endTimeS, {PH1: new Date(range.end).toISOString()})}</span></td>
95
+ </tr>
96
+ `;
97
+ // clang-format on
98
+ })}`;
99
+ }
100
+
101
+ // clang-format off
102
+ render(html`
103
+ <style>${serviceWorkerUpdateCycleViewStyles}</style>
104
+ <table class="service-worker-update-timing-table" jslog=${VisualLogging.tree('update-timing-table')}>
105
+ <tr class="service-worker-update-timing-table-header">
106
+ <td>${i18nString(UIStrings.version)}</td>
107
+ <td>${i18nString(UIStrings.updateActivity)}</td>
108
+ <td>${i18nString(UIStrings.timeline)}</td>
109
+ </tr>
110
+ ${tableRows}
111
+ </table>
112
+ `, target);
113
+ // clang-format on
114
+ };
115
+
116
+ export class ServiceWorkerUpdateCycleView extends UI.Widget.Widget {
117
+ #registration?: SDK.ServiceWorkerManager.ServiceWorkerRegistration;
40
118
  private rows: HTMLTableRowElement[];
41
119
  private selectedRowIndex: number;
42
- tableElement: HTMLElement;
43
- constructor(registration: SDK.ServiceWorkerManager.ServiceWorkerRegistration) {
44
- this.registration = registration;
120
+ private expandedRows = new Set<string>();
121
+ #view: View;
122
+
123
+ constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
124
+ super(element);
125
+ this.#view = view;
45
126
  this.rows = [];
46
127
  this.selectedRowIndex = -1;
47
- this.tableElement = document.createElement('table');
48
- this.createTimingTable();
128
+ }
129
+
130
+ set registration(registration: SDK.ServiceWorkerManager.ServiceWorkerRegistration|undefined) {
131
+ this.#registration = registration;
132
+ this.requestUpdate();
133
+ }
134
+
135
+ get registration(): SDK.ServiceWorkerManager.ServiceWorkerRegistration|undefined {
136
+ return this.#registration;
137
+ }
138
+
139
+ set registrationFingerprint(_fingerprint: symbol|undefined) {
140
+ this.requestUpdate();
49
141
  }
50
142
 
51
143
  calculateServiceWorkerUpdateRanges(): ServiceWorkerUpdateRange[] {
@@ -113,7 +205,10 @@ export class ServiceWorkerUpdateCycleView {
113
205
  return ranges;
114
206
  }
115
207
 
116
- const versions = this.registration.versionsByMode();
208
+ if (!this.#registration) {
209
+ return [];
210
+ }
211
+ const versions = this.#registration.versionsByMode();
117
212
  const modes = [
118
213
  SDK.ServiceWorkerManager.ServiceWorkerVersion.Modes.ACTIVE,
119
214
  SDK.ServiceWorkerManager.ServiceWorkerVersion.Modes.WAITING,
@@ -132,119 +227,32 @@ export class ServiceWorkerUpdateCycleView {
132
227
  return [];
133
228
  }
134
229
 
135
- private createTimingTable(): void {
136
- this.tableElement.classList.add('service-worker-update-timing-table');
137
- this.tableElement.setAttribute('jslog', `${VisualLogging.tree('update-timing-table')}`);
230
+ override performUpdate(): void {
138
231
  const timeRanges = this.calculateServiceWorkerUpdateRanges();
139
- this.updateTimingTable(timeRanges);
140
- }
141
-
142
- private createTimingTableHead(): void {
143
- const serverHeader = this.tableElement.createChild('tr', 'service-worker-update-timing-table-header');
144
- UI.UIUtils.createTextChild(serverHeader.createChild('td'), i18nString(UIStrings.version));
145
- UI.UIUtils.createTextChild(serverHeader.createChild('td'), i18nString(UIStrings.updateActivity));
146
- UI.UIUtils.createTextChild(serverHeader.createChild('td'), i18nString(UIStrings.timeline));
147
- }
148
232
 
149
- private removeRows(): void {
150
- const rows = this.tableElement.getElementsByTagName('tr');
151
- while (rows[0]) {
152
- if (rows[0].parentNode) {
153
- rows[0].parentNode.removeChild(rows[0]);
154
- }
155
- }
156
- this.rows = [];
157
- }
158
-
159
- private updateTimingTable(timeRanges: ServiceWorkerUpdateRange[]): void {
160
- this.selectedRowIndex = -1;
161
- this.removeRows();
162
- this.createTimingTableHead();
163
- const timeRangeArray = timeRanges;
164
- if (timeRangeArray.length === 0) {
165
- return;
166
- }
167
-
168
- const startTimes = timeRangeArray.map(r => r.start);
169
- const endTimes = timeRangeArray.map(r => r.end);
170
- const startTime = startTimes.reduce((a, b) => Math.min(a, b));
171
- const endTime = endTimes.reduce((a, b) => Math.max(a, b));
172
- const scale = 100 / (endTime - startTime);
173
-
174
- for (const range of timeRangeArray) {
175
- const phaseName = range.phase;
176
-
177
- const left = (scale * (range.start - startTime));
178
- const right = (scale * (endTime - range.end));
179
-
180
- const tr = this.tableElement.createChild('tr', 'service-worker-update-timeline');
181
- tr.setAttribute('jslog', `${VisualLogging.treeItem('update-timeline').track({
182
- click: true,
183
- resize: true,
184
- keydown: 'ArrowLeft|ArrowRight|ArrowUp|ArrowDown|Enter|Space',
185
- })}`);
186
- this.rows.push(tr);
187
- const timingBarVersionElement = tr.createChild('td');
188
- UI.UIUtils.createTextChild(timingBarVersionElement, '#' + range.id);
189
- timingBarVersionElement.classList.add('service-worker-update-timing-bar-clickable');
190
- timingBarVersionElement.setAttribute('tabindex', '0');
191
- timingBarVersionElement.setAttribute('role', 'switch');
192
- timingBarVersionElement.addEventListener('focus', (event: Event) => {
193
- this.onFocus(event);
194
- });
195
- timingBarVersionElement.setAttribute('jslog', `${VisualLogging.expand('timing-info').track({click: true})}`);
196
- UI.ARIAUtils.setChecked(timingBarVersionElement, false);
197
- const timingBarTitleElement = tr.createChild('td');
198
- UI.UIUtils.createTextChild(timingBarTitleElement, phaseName);
199
- const barContainer = tr.createChild('td').createChild('div', 'service-worker-update-timing-row');
200
-
201
- const bar = barContainer.createChild('span', 'service-worker-update-timing-bar ' + phaseName.toLowerCase());
202
-
203
- bar.style.left = left + '%';
204
- bar.style.right = right + '%';
205
- bar.textContent = '\u200B'; // Important for 0-time items to have 0 width.
206
-
207
- this.constructUpdateDetails(tr, range);
233
+ const input: ViewInput = {
234
+ timeRanges,
235
+ expandedRows: this.expandedRows,
236
+ onFocus: this.onFocus.bind(this),
237
+ onKeydown: this.onKeydown.bind(this),
238
+ onClick: this.onClick.bind(this),
239
+ };
240
+
241
+ this.#view(input, this, this.contentElement);
242
+ this.rows =
243
+ Array.from(this.contentElement.querySelectorAll<HTMLTableRowElement>('.service-worker-update-timeline'));
244
+ if (this.selectedRowIndex >= this.rows.length) {
245
+ this.selectedRowIndex = -1;
208
246
  }
209
247
  }
210
248
 
211
- /**
212
- * Detailed information about an update phase. Currently starting and ending time.
213
- */
214
- private constructUpdateDetails(tr: HTMLElement, range: ServiceWorkerUpdateRange): void {
215
- const startRow = this.tableElement.createChild('tr', 'service-worker-update-timing-bar-details');
216
- startRow.classList.add('service-worker-update-timing-bar-details-collapsed');
217
- const startTimeItem = startRow.createChild('td');
218
- startTimeItem.colSpan = 3;
219
- const startTime = (new Date(range.start)).toISOString();
220
- UI.UIUtils.createTextChild(startTimeItem.createChild('span'), i18nString(UIStrings.startTimeS, {PH1: startTime}));
221
- startRow.tabIndex = 0;
222
-
223
- const endRow = this.tableElement.createChild('tr', 'service-worker-update-timing-bar-details');
224
- endRow.classList.add('service-worker-update-timing-bar-details-collapsed');
225
- const endTimeItem = endRow.createChild('td');
226
- endTimeItem.colSpan = 3;
227
- const endTime = (new Date(range.end)).toISOString();
228
- UI.UIUtils.createTextChild(endTimeItem.createChild('span'), i18nString(UIStrings.endTimeS, {PH1: endTime}));
229
- endRow.tabIndex = 0;
230
-
231
- tr.addEventListener('keydown', (event: Event) => {
232
- this.onKeydown(event, startRow, endRow);
233
- });
234
-
235
- tr.addEventListener('click', (event: Event) => {
236
- this.onClick(event, startRow, endRow);
237
- });
238
- }
239
-
240
- private toggle(startRow: Element, endRow: Element, target: Element, expanded: boolean): void {
241
- if (target.classList.contains('service-worker-update-timing-bar-clickable')) {
242
- startRow.classList.toggle('service-worker-update-timing-bar-details-collapsed');
243
- startRow.classList.toggle('service-worker-update-timing-bar-details-expanded');
244
- endRow.classList.toggle('service-worker-update-timing-bar-details-collapsed');
245
- endRow.classList.toggle('service-worker-update-timing-bar-details-expanded');
246
- UI.ARIAUtils.setChecked(target, !expanded);
249
+ private toggle(key: string, expanded: boolean): void {
250
+ if (expanded) {
251
+ this.expandedRows.delete(key);
252
+ } else {
253
+ this.expandedRows.add(key);
247
254
  }
255
+ this.requestUpdate();
248
256
  }
249
257
 
250
258
  private onFocus(event: Event): void {
@@ -260,21 +268,20 @@ export class ServiceWorkerUpdateCycleView {
260
268
  this.selectedRowIndex = this.rows.indexOf(tr);
261
269
  }
262
270
 
263
- private onKeydown(event: Event, startRow: HTMLElement, endRow: HTMLElement): void {
271
+ private onKeydown(event: Event, key: string): void {
264
272
  if (!event.target) {
265
273
  return;
266
274
  }
267
- const target: HTMLElement = event.target as HTMLElement;
268
275
  const keyboardEvent = event as KeyboardEvent;
269
- const expanded = target.getAttribute('aria-checked') === 'true';
276
+ const expanded = this.expandedRows.has(key);
270
277
 
271
278
  if (keyboardEvent.key === 'Enter' || keyboardEvent.key === ' ') {
272
- this.toggle(startRow, endRow, target, expanded);
279
+ this.toggle(key, expanded);
273
280
  event.preventDefault();
274
281
  return;
275
282
  }
276
283
  if ((!expanded && keyboardEvent.key === 'ArrowRight') || (expanded && keyboardEvent.key === 'ArrowLeft')) {
277
- this.toggle(startRow, endRow, target, expanded);
284
+ this.toggle(key, expanded);
278
285
  event.preventDefault();
279
286
  return;
280
287
  }
@@ -346,21 +353,11 @@ export class ServiceWorkerUpdateCycleView {
346
353
  this.focusRow(this.rows[this.selectedRowIndex]);
347
354
  }
348
355
 
349
- private onClick(event: Event, startRow: Element, endRow: Element): void {
350
- const tr = event.target as Element;
351
- if (!tr) {
352
- return;
353
- }
354
-
355
- const expanded = tr.getAttribute('aria-checked') === 'true';
356
- this.toggle(startRow, endRow, tr, expanded);
356
+ private onClick(event: Event, key: string): void {
357
+ const expanded = this.expandedRows.has(key);
358
+ this.toggle(key, expanded);
357
359
  event.preventDefault();
358
360
  }
359
-
360
- refresh(): void {
361
- const timeRanges = this.calculateServiceWorkerUpdateRanges();
362
- this.updateTimingTable(timeRanges);
363
- }
364
361
  }
365
362
 
366
363
  export const enum ServiceWorkerUpdateNames {
@@ -20,7 +20,6 @@ import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
20
20
 
21
21
  import * as ApplicationComponents from './components/components.js';
22
22
  import serviceWorkersViewStyles from './serviceWorkersView.css.js';
23
- import serviceWorkerUpdateCycleViewStyles from './serviceWorkerUpdateCycleView.css.js';
24
23
  import {ServiceWorkerUpdateCycleView} from './ServiceWorkerUpdateCycleView.js';
25
24
 
26
25
  const UIStrings = {
@@ -479,7 +478,7 @@ export interface SectionViewInput {
479
478
  pushData: string;
480
479
  syncTag: string;
481
480
  periodicSyncTag: string;
482
- updateCycleTable: HTMLElement;
481
+ registration: SDK.ServiceWorkerManager.ServiceWorkerRegistration;
483
482
  activeVersion?: SDK.ServiceWorkerManager.ServiceWorkerVersion;
484
483
  waitingVersion?: SDK.ServiceWorkerManager.ServiceWorkerVersion;
485
484
  installingVersion?: SDK.ServiceWorkerManager.ServiceWorkerVersion;
@@ -695,13 +694,18 @@ function renderStatusField(input: SectionViewInput, active?: SDK.ServiceWorkerMa
695
694
  }
696
695
 
697
696
  function renderUpdateCycleField(input: SectionViewInput): LitTemplate {
697
+ // clang-format off
698
698
  return html`
699
699
  <div class="report-field">
700
700
  <div class="report-field-name">${i18nString(UIStrings.updateCycle)}</div>
701
701
  <div class="report-field-value">
702
- ${input.updateCycleTable}
702
+ ${widget(ServiceWorkerUpdateCycleView, {
703
+ registration: input.registration,
704
+ registrationFingerprint: input.registration.fingerprint(),
705
+ })}
703
706
  </div>
704
707
  </div>`;
708
+ // clang-format on
705
709
  }
706
710
 
707
711
  function renderRouterField(input: SectionViewInput): LitTemplate {
@@ -729,7 +733,6 @@ export const DEFAULT_SECTION_VIEW: SectionView =
729
733
  // clang-format off
730
734
  render(html`
731
735
  <style>${serviceWorkersViewStyles}</style>
732
- <style>${serviceWorkerUpdateCycleViewStyles}</style>
733
736
  <devtools-report-section-header role="heading" aria-level="2"
734
737
  aria-label=${i18nString(UIStrings.serviceWorkerForS, { PH1: input.title })}>
735
738
  <span style="flex: 1 1 auto">${input.title}</span>
@@ -761,7 +764,6 @@ export class Section extends UI.Widget.VBox {
761
764
  private pushNotificationDataSetting!: Common.Settings.Setting<string>;
762
765
  private syncTagNameSetting!: Common.Settings.Setting<string>;
763
766
  private periodicSyncTagNameSetting!: Common.Settings.Setting<string>;
764
- private updateCycleView!: ServiceWorkerUpdateCycleView;
765
767
  private readonly clientInfoCache: Map<string, Protocol.Target.TargetInfo>;
766
768
  private readonly throttler: Common.Throttler.Throttler;
767
769
  #view: SectionView;
@@ -790,7 +792,6 @@ export class Section extends UI.Widget.VBox {
790
792
  }
791
793
 
792
794
  if (registrationChanged) {
793
- this.updateCycleView = new ServiceWorkerUpdateCycleView(this.registration);
794
795
  this.clientInfoCache.clear();
795
796
  }
796
797
  }
@@ -838,7 +839,7 @@ export class Section extends UI.Widget.VBox {
838
839
  pushData: this.pushNotificationDataSetting.get(),
839
840
  syncTag: this.syncTagNameSetting.get(),
840
841
  periodicSyncTag: this.periodicSyncTagNameSetting.get(),
841
- updateCycleTable: this.updateCycleView.tableElement,
842
+ registration: this.registration,
842
843
  activeVersion: active,
843
844
  waitingVersion: waiting,
844
845
  installingVersion: installing,
@@ -856,7 +857,6 @@ export class Section extends UI.Widget.VBox {
856
857
  };
857
858
 
858
859
  this.#view(input, undefined, this.contentElement);
859
- this.updateCycleView.refresh();
860
860
 
861
861
  return Promise.resolve();
862
862
  }
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as ApplicationPanelSidebar from './ApplicationPanelSidebar.js';
6
+ import * as ApplicationPanelTreeElement from './ApplicationPanelTreeElement.js';
6
7
  import * as AppManifestView from './AppManifestView.js';
7
8
  import * as BackgroundServiceModel from './BackgroundServiceModel.js';
8
9
  import * as BackgroundServiceView from './BackgroundServiceView.js';
@@ -45,6 +46,7 @@ import * as WebMCPView from './WebMCPView.js';
45
46
  export * as Components from './components/components.js';
46
47
  export {
47
48
  ApplicationPanelSidebar,
49
+ ApplicationPanelTreeElement,
48
50
  AppManifestView,
49
51
  BackgroundServiceModel,
50
52
  BackgroundServiceView,
@@ -101,7 +101,9 @@ interface AdFrameNodeData {
101
101
  elementId: string;
102
102
  initialOrigin: string;
103
103
  networkBytes: string;
104
+ rawNetworkBytes: number;
104
105
  cpuTime: string;
106
+ rawCpuTime: number;
105
107
  revealFrame: (e: Event) => void;
106
108
  }
107
109
 
@@ -206,10 +208,10 @@ const DEFAULT_VIEW: View = (input, output, target) => {
206
208
  <devtools-data-grid striped resize="last" class="ad-frames-data-grid" name=${i18nString(UIStrings.adIframes)}>
207
209
  <table>
208
210
  <tr>
209
- <th id="elementId" weight="1">${i18nString(UIStrings.elementId)}</th>
210
- <th id="initialOrigin" weight="2">${i18nString(UIStrings.initialOrigin)}</th>
211
- <th id="cpuTime" weight="1">${i18nString(UIStrings.cpu)}</th>
212
- <th id="networkBytes" weight="1">${i18nString(UIStrings.network)}</th>
211
+ <th id="elementId" weight="1" sortable>${i18nString(UIStrings.elementId)}</th>
212
+ <th id="initialOrigin" weight="2" sortable>${i18nString(UIStrings.initialOrigin)}</th>
213
+ <th id="cpuTime" weight="1" sortable type="numeric">${i18nString(UIStrings.cpu)}</th>
214
+ <th id="networkBytes" weight="1" sortable type="numeric">${i18nString(UIStrings.network)}</th>
213
215
  </tr>
214
216
  ${input.adFrames.map(frame => html`
215
217
  <tr>
@@ -223,8 +225,8 @@ const DEFAULT_VIEW: View = (input, output, target) => {
223
225
  : Lit.nothing}
224
226
  </td>
225
227
  <td title=${frame.initialOrigin}>${frame.initialOrigin}</td>
226
- <td title=${frame.cpuTime}>${frame.cpuTime}</td>
227
- <td title=${frame.networkBytes}>${frame.networkBytes}</td>
228
+ <td title=${frame.cpuTime} data-value=${frame.rawCpuTime}>${frame.cpuTime}</td>
229
+ <td title=${frame.networkBytes} data-value=${frame.rawNetworkBytes}>${frame.networkBytes}</td>
228
230
  </tr>
229
231
  `)}
230
232
  </table>
@@ -421,7 +423,9 @@ export class AdsView extends UI.Widget.Widget {
421
423
  elementId: elementIdText,
422
424
  initialOrigin: frame.initialOrigin || '',
423
425
  cpuTime: formatCpu(frame.cpuTime),
426
+ rawCpuTime: frame.cpuTime ?? -1,
424
427
  networkBytes: formatNetwork(frame.networkBytes),
428
+ rawNetworkBytes: frame.networkBytes ?? -1,
425
429
  revealFrame,
426
430
  });
427
431
  }
@@ -445,8 +445,8 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
445
445
  private readonly warningsContainer: HTMLDivElement;
446
446
  private readonly warningsView = new PreloadingComponents.PreloadingDisabledInfobar.PreloadingDisabledInfobar();
447
447
  private readonly preloadingGrid = new PreloadingComponents.PreloadingGrid.PreloadingGrid();
448
- private readonly preloadingDetails =
449
- new PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView();
448
+ private readonly preloadingGridContainer: HTMLDivElement;
449
+ private readonly renderContainer: HTMLElement;
450
450
  private readonly ruleSetSelector: PreloadingRuleSetSelector;
451
451
  private readonly textFilterUI: UI.Toolbar.ToolbarFilter;
452
452
  private hsplit?: UI.SplitWidget.SplitWidget;
@@ -525,38 +525,12 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
525
525
 
526
526
  this.preloadingGrid.onSelect = this.onPreloadingGridCellFocused.bind(this);
527
527
 
528
- const preloadingGridContainer = document.createElement('div');
529
- preloadingGridContainer.className = 'preloading-grid-widget-container';
530
- preloadingGridContainer.style = 'height: 100%';
531
- this.preloadingGrid.show(preloadingGridContainer, null, true);
528
+ this.preloadingGridContainer = document.createElement('div');
529
+ this.preloadingGridContainer.className = 'preloading-grid-widget-container';
530
+ this.preloadingGridContainer.style.height = '100%';
531
+ this.preloadingGrid.show(this.preloadingGridContainer, null, true);
532
532
 
533
- render(
534
- html`
535
- <div class="empty-state">
536
- <span class="empty-state-header">${i18nString(UIStrings.noPrefetchAttempts)}</span>
537
- <div class="empty-state-description">
538
- <span>${i18nString(UIStrings.prefetchDescription)}</span>
539
- <devtools-link
540
- class="devtools-link"
541
- href=${SPECULATION_EXPLANATION_URL}
542
- jslogcontext="learn-more"
543
- >${i18nString(UIStrings.learnMore)}</devtools-link>
544
- </div>
545
- </div>
546
- <devtools-split-view sidebar-position="second" ${
547
- UI.Widget.widgetRef(
548
- UI.SplitWidget.SplitWidget,
549
- w => {
550
- this.hsplit = w;
551
- })}>
552
- <div slot="main" class="overflow-auto" style="height: 100%">
553
- ${preloadingGridContainer}
554
- </div>
555
- <div slot="sidebar" class="overflow-auto" style="height: 100%">
556
- ${this.preloadingDetails}
557
- </div>
558
- </devtools-split-view>`,
559
- vbox.contentElement, {host: this});
533
+ this.renderContainer = vbox.contentElement;
560
534
 
561
535
  vbox.show(this.contentElement);
562
536
  }
@@ -593,20 +567,20 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
593
567
  this.render();
594
568
  }
595
569
 
596
- private updatePreloadingDetails(): void {
570
+ private getPreloadingDetailsData(): PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportViewData {
597
571
  const id = this.focusedPreloadingAttemptId;
598
572
  const preloadingAttempt = id === null ? null : this.model.getPreloadingAttemptById(id);
599
573
  if (preloadingAttempt === null) {
600
- this.preloadingDetails.data = null;
601
- } else {
602
- const pipeline = this.model.getPipeline(preloadingAttempt);
603
- const ruleSets = preloadingAttempt.ruleSetIds.map(id => this.model.getRuleSetById(id)).filter(x => x !== null);
604
- this.preloadingDetails.data = {
605
- pipeline,
606
- ruleSets,
607
- pageURL: pageURL(),
608
- };
574
+ return null;
609
575
  }
576
+
577
+ const pipeline = this.model.getPipeline(preloadingAttempt);
578
+ const ruleSets = preloadingAttempt.ruleSetIds.map(id => this.model.getRuleSetById(id)).filter(x => x !== null);
579
+ return {
580
+ pipeline,
581
+ ruleSets,
582
+ pageURL: pageURL(),
583
+ };
610
584
  }
611
585
 
612
586
  render(): void {
@@ -647,7 +621,36 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
647
621
  this.hsplit?.doLayout();
648
622
  }
649
623
 
650
- this.updatePreloadingDetails();
624
+ // clang-format off
625
+ render(html`
626
+ <div class="empty-state">
627
+ <span class="empty-state-header">${i18nString(UIStrings.noPrefetchAttempts)}</span>
628
+ <div class="empty-state-description">
629
+ <span>${i18nString(UIStrings.prefetchDescription)}</span>
630
+ <devtools-link
631
+ class="devtools-link"
632
+ href=${SPECULATION_EXPLANATION_URL}
633
+ jslogcontext="learn-more"
634
+ >${i18nString(UIStrings.learnMore)}</devtools-link>
635
+ </div>
636
+ </div>
637
+ <devtools-split-view sidebar-position="second" ${
638
+ UI.Widget.widgetRef(
639
+ UI.SplitWidget.SplitWidget,
640
+ w => {
641
+ this.hsplit = w;
642
+ })}>
643
+ <div slot="main" class="overflow-auto" style="height: 100%">
644
+ ${this.preloadingGridContainer}
645
+ </div>
646
+ <div slot="sidebar" class="overflow-auto" style="height: 100%">
647
+ ${widget(PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView, {
648
+ data: this.getPreloadingDetailsData(),
649
+ })}
650
+ </div>
651
+ </devtools-split-view>
652
+ `, this.renderContainer, {host: this});
653
+ // clang-format on
651
654
  }
652
655
 
653
656
  private onPreloadingGridCellFocused({rowId}: {rowId: string}): void {
@@ -664,7 +667,12 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
664
667
  }
665
668
 
666
669
  getPreloadingDetailsForTest(): PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView {
667
- return this.preloadingDetails;
670
+ const widgetElement = this.renderContainer.querySelector('div[slot="sidebar"] devtools-widget') as
671
+ UI.Widget.WidgetElement<PreloadingComponents.PreloadingDetailsReportView.PreloadingDetailsReportView>|
672
+ null;
673
+ const widget = widgetElement?.getWidget();
674
+ assertNotNullOrUndefined(widget);
675
+ return widget;
668
676
  }
669
677
 
670
678
  selectRuleSetOnFilterForTest(id: Protocol.Preload.RuleSetId|null): void {