chrome-devtools-frontend 1.0.1548870 → 1.0.1549484

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 (188) hide show
  1. package/docs/contributing/settings-experiments-features.md +35 -0
  2. package/docs/styleguide/ux/patterns.md +27 -0
  3. package/eslint.config.mjs +1 -0
  4. package/front_end/Tests.js +2 -0
  5. package/front_end/core/host/InspectorFrontendHost.ts +26 -558
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +6 -3
  7. package/front_end/core/host/InspectorFrontendHostStub.ts +558 -0
  8. package/front_end/core/host/ResourceLoader.ts +9 -23
  9. package/front_end/core/host/UserMetrics.ts +4 -4
  10. package/front_end/core/root/DevToolsContext.ts +4 -0
  11. package/front_end/core/root/Runtime.ts +10 -0
  12. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -2
  13. package/front_end/core/sdk/CSSModel.ts +24 -24
  14. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +11 -11
  15. package/front_end/core/sdk/CSSQuery.ts +1 -1
  16. package/front_end/core/sdk/CSSRule.ts +2 -2
  17. package/front_end/core/sdk/CSSStyleDeclaration.ts +1 -1
  18. package/front_end/core/sdk/CSSStyleSheetHeader.ts +1 -1
  19. package/front_end/core/sdk/DOMModel.ts +3 -0
  20. package/front_end/core/sdk/NetworkManager.ts +29 -31
  21. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  22. package/front_end/core/sdk/OverlayModel.ts +2 -2
  23. package/front_end/core/sdk/PageResourceLoader.ts +63 -37
  24. package/front_end/core/sdk/SourceMap.ts +6 -0
  25. package/front_end/core/sdk/SourceMapCache.ts +21 -0
  26. package/front_end/core/sdk/SourceMapManager.ts +7 -6
  27. package/front_end/core/sdk/SourceMapScopesInfo.ts +6 -2
  28. package/front_end/core/sdk/TargetManager.ts +14 -2
  29. package/front_end/core/sdk/sdk-meta.ts +13 -0
  30. package/front_end/entrypoints/formatter_worker/FormatterActions.ts +1 -0
  31. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +1 -1
  32. package/front_end/entrypoints/main/MainImpl.ts +13 -3
  33. package/front_end/foundation/Universe.ts +1 -1
  34. package/front_end/generated/Deprecation.ts +18 -4
  35. package/front_end/generated/InspectorBackendCommands.ts +33 -31
  36. package/front_end/generated/SupportedCSSProperties.js +41 -41
  37. package/front_end/generated/protocol-mapping.d.ts +12 -0
  38. package/front_end/generated/protocol-proxy-api.d.ts +11 -0
  39. package/front_end/generated/protocol.ts +70 -35
  40. package/front_end/models/ai_assistance/AiConversation.ts +5 -4
  41. package/front_end/models/ai_assistance/ChangeManager.ts +4 -4
  42. package/front_end/models/ai_assistance/ConversationHandler.ts +0 -15
  43. package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -6
  44. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +135 -3
  45. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +24 -0
  46. package/front_end/models/bindings/CompilerScriptMapping.ts +43 -0
  47. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +19 -0
  48. package/front_end/models/bindings/ResourceMapping.ts +73 -0
  49. package/front_end/models/bindings/ResourceScriptMapping.ts +50 -0
  50. package/front_end/models/issues_manager/GenericIssue.ts +17 -0
  51. package/front_end/models/issues_manager/descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  52. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -3
  53. package/front_end/models/source_map_scopes/FunctionCodeResolver.snapshot.txt +98 -0
  54. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +270 -0
  55. package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
  56. package/front_end/models/workspace/UISourceCode.ts +51 -44
  57. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +76 -34
  58. package/front_end/panels/ai_assistance/aiAssistancePanel.css +1 -0
  59. package/front_end/panels/ai_assistance/components/ChatView.ts +23 -11
  60. package/front_end/panels/application/AppManifestView.ts +3 -2
  61. package/front_end/panels/application/FrameDetailsView.ts +5 -6
  62. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  63. package/front_end/panels/application/TrustTokensTreeElement.ts +2 -6
  64. package/front_end/panels/application/components/PermissionsPolicySection.ts +201 -157
  65. package/front_end/panels/application/components/ProtocolHandlersView.ts +117 -80
  66. package/front_end/panels/application/components/ServiceWorkerRouterView.ts +47 -41
  67. package/front_end/panels/application/components/StorageMetadataView.ts +31 -34
  68. package/front_end/panels/application/components/TrustTokensView.ts +76 -68
  69. package/front_end/panels/console/ConsoleView.ts +3 -2
  70. package/front_end/panels/console/ConsoleViewMessage.ts +6 -4
  71. package/front_end/panels/console/console-meta.ts +0 -13
  72. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +3 -1
  73. package/front_end/panels/elements/CSSRuleValidator.ts +7 -7
  74. package/front_end/panels/elements/CSSRuleValidatorHelper.ts +2 -2
  75. package/front_end/panels/elements/ElementsTreeElement.ts +16 -13
  76. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -1
  77. package/front_end/panels/elements/LayoutPane.ts +12 -10
  78. package/front_end/panels/elements/StylePropertyTreeElement.ts +12 -12
  79. package/front_end/panels/elements/components/AdornerManager.ts +3 -3
  80. package/front_end/panels/elements/components/StylePropertyEditor.ts +6 -6
  81. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +27 -49
  82. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +15 -11
  83. package/front_end/panels/media/PlayerListView.ts +100 -73
  84. package/front_end/panels/media/playerListView.css +5 -0
  85. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +3 -3
  86. package/front_end/panels/network/RequestConditionsDrawer.ts +5 -5
  87. package/front_end/panels/network/components/DirectSocketConnectionView.ts +17 -0
  88. package/front_end/panels/network/resourceChunkView.css +4 -0
  89. package/front_end/panels/security/CookieControlsView.ts +1 -1
  90. package/front_end/panels/sensors/LocationsSettingsTab.ts +1 -1
  91. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +1 -1
  92. package/front_end/panels/settings/KeybindsSettingsTab.ts +1 -1
  93. package/front_end/panels/settings/SettingsScreen.ts +6 -6
  94. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  95. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -1
  96. package/front_end/panels/snippets/SnippetsQuickOpen.ts +4 -2
  97. package/front_end/panels/sources/CSSPlugin.ts +1 -1
  98. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +13 -5
  99. package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -2
  100. package/front_end/panels/sources/NavigatorView.ts +2 -2
  101. package/front_end/panels/sources/OpenFileQuickOpen.ts +7 -8
  102. package/front_end/panels/sources/OutlineQuickOpen.ts +6 -3
  103. package/front_end/panels/sources/ProfilePlugin.ts +21 -12
  104. package/front_end/panels/sources/UISourceCodeFrame.ts +0 -1
  105. package/front_end/panels/sources/filteredUISourceCodeListProvider.css +41 -0
  106. package/front_end/panels/timeline/TimelinePanel.ts +17 -18
  107. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +3 -3
  108. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
  109. package/front_end/panels/timeline/docs/flame_chart_migration.md +11 -16
  110. package/front_end/panels/utils/utils.ts +17 -3
  111. package/front_end/panels/whats_new/ReleaseNoteText.ts +10 -20
  112. package/front_end/panels/whats_new/resources/WNDT.md +8 -8
  113. package/front_end/third_party/chromium/README.chromium +1 -1
  114. package/front_end/third_party/puppeteer/third_party/mitt/README.chromium +1 -0
  115. package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -0
  116. package/front_end/third_party/puppeteer/third_party/rxjs/README.chromium +1 -0
  117. package/front_end/ui/components/adorners/Adorner.ts +1 -1
  118. package/front_end/ui/components/annotations/AnnotationRepository.ts +98 -0
  119. package/front_end/ui/components/annotations/AnnotationType.ts +10 -0
  120. package/front_end/ui/components/annotations/annotations.ts +6 -0
  121. package/front_end/ui/components/buttons/Button.ts +1 -1
  122. package/front_end/ui/components/buttons/FloatingButton.ts +1 -1
  123. package/front_end/ui/components/chrome_link/ChromeLink.ts +1 -1
  124. package/front_end/ui/components/dialogs/ButtonDialog.ts +1 -1
  125. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  126. package/front_end/ui/components/dialogs/ShortcutDialog.ts +1 -0
  127. package/front_end/ui/components/diff_view/DiffView.ts +1 -1
  128. package/front_end/ui/components/expandable_list/ExpandableList.ts +1 -1
  129. package/front_end/ui/components/highlighting/HighlightElement.ts +1 -0
  130. package/front_end/ui/components/highlighting/MarkupHighlight.ts +162 -0
  131. package/front_end/ui/components/highlighting/highlighting.ts +7 -0
  132. package/front_end/ui/components/icon_button/FileSourceIcon.ts +1 -1
  133. package/front_end/ui/components/icon_button/Icon.ts +4 -2
  134. package/front_end/ui/components/icon_button/IconButton.ts +1 -1
  135. package/front_end/ui/components/issue_counter/IssueCounter.ts +1 -1
  136. package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +1 -1
  137. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +1 -1
  138. package/front_end/ui/components/linkifier/LinkifierImpl.ts +1 -1
  139. package/front_end/ui/components/list/List.ts +184 -0
  140. package/front_end/ui/components/list/list.css +90 -0
  141. package/front_end/ui/components/{cards/cards.ts → list/lists.ts} +3 -3
  142. package/front_end/ui/components/markdown_view/CodeBlock.ts +1 -1
  143. package/front_end/ui/components/markdown_view/MarkdownImage.ts +1 -1
  144. package/front_end/ui/components/markdown_view/MarkdownLink.ts +1 -1
  145. package/front_end/ui/components/markdown_view/MarkdownView.ts +1 -1
  146. package/front_end/ui/components/menus/Menu.ts +1 -1
  147. package/front_end/ui/components/menus/SelectMenu.ts +1 -1
  148. package/front_end/ui/components/node_text/NodeText.ts +1 -1
  149. package/front_end/ui/components/panel_feedback/FeedbackButton.ts +1 -1
  150. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +1 -1
  151. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  152. package/front_end/ui/components/panel_introduction_steps/PanelIntroductionSteps.ts +1 -1
  153. package/front_end/ui/components/report_view/ReportView.ts +1 -1
  154. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -1
  155. package/front_end/ui/components/settings/SettingCheckbox.ts +1 -1
  156. package/front_end/ui/components/settings/SettingDeprecationWarning.ts +1 -1
  157. package/front_end/ui/components/snackbars/Snackbar.ts +1 -1
  158. package/front_end/ui/components/spinners/Spinner.ts +1 -1
  159. package/front_end/ui/components/srgb_overlay/SrgbOverlay.ts +1 -1
  160. package/front_end/ui/components/suggestion_input/SuggestionInput.ts +1 -0
  161. package/front_end/ui/components/survey_link/SurveyLink.ts +1 -1
  162. package/front_end/ui/components/switch/SwitchImpl.ts +1 -1
  163. package/front_end/ui/components/text_editor/TextEditor.ts +1 -0
  164. package/front_end/ui/components/text_prompt/TextPrompt.ts +1 -1
  165. package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
  166. package/front_end/ui/components/tree_outline/TreeOutline.ts +1 -1
  167. package/front_end/ui/kit/kit.ts +5 -0
  168. package/front_end/ui/legacy/TabbedPane.ts +98 -0
  169. package/front_end/ui/legacy/UIUtils.ts +0 -184
  170. package/front_end/ui/legacy/ViewManager.ts +23 -8
  171. package/front_end/ui/legacy/ViewRegistration.ts +21 -22
  172. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +5 -4
  173. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +73 -35
  174. package/front_end/ui/legacy/components/perf_ui/LiveHeapProfile.ts +11 -2
  175. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +12 -13
  176. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +7 -16
  177. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +5 -6
  178. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +18 -65
  179. package/front_end/ui/legacy/components/source_frame/JSONView.ts +2 -1
  180. package/front_end/ui/legacy/tabbedPane.css +10 -0
  181. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  182. package/inspector_overlay/README.md +3 -3
  183. package/mcp/HostBindings.ts +310 -0
  184. package/mcp/mcp.ts +17 -0
  185. package/mcp/tsconfig.json +6 -1
  186. package/package.json +26 -24
  187. /package/front_end/ui/{components → kit}/cards/Card.ts +0 -0
  188. /package/front_end/ui/{components → kit}/cards/card.css +0 -0
@@ -0,0 +1,558 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Common from '../common/common.js';
6
+ import * as i18n from '../i18n/i18n.js';
7
+ import * as Platform from '../platform/platform.js';
8
+ import type * as Root from '../root/root.js';
9
+
10
+ import {
11
+ type AidaClientResult,
12
+ type AidaCodeCompleteResult,
13
+ type CanShowSurveyResult,
14
+ type ChangeEvent,
15
+ type ClickEvent,
16
+ type ContextMenuDescriptor,
17
+ type DispatchHttpRequestRequest,
18
+ type DispatchHttpRequestResult,
19
+ type DoAidaConversationResult,
20
+ type DragEvent,
21
+ type EnumeratedHistogram,
22
+ Events,
23
+ type EventTypes,
24
+ type ExtensionDescriptor,
25
+ type FunctionCallEvent,
26
+ type HoverEvent,
27
+ type ImpressionEvent,
28
+ type InspectorFrontendHostAPI,
29
+ type KeyDownEvent,
30
+ type LoadNetworkResourceResult,
31
+ type ResizeEvent,
32
+ type SettingAccessEvent,
33
+ type ShowSurveyResult,
34
+ type SyncInformation,
35
+ } from './InspectorFrontendHostAPI.js';
36
+ import {streamWrite as resourceLoaderStreamWrite} from './ResourceLoader.js';
37
+
38
+ const UIStrings = {
39
+ /**
40
+ * @description Document title in Inspector Frontend Host of the DevTools window
41
+ * @example {example.com} PH1
42
+ */
43
+ devtoolsS: 'DevTools - {PH1}',
44
+ } as const;
45
+ const str_ = i18n.i18n.registerUIStrings('core/host/InspectorFrontendHostStub.ts', UIStrings);
46
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
47
+
48
+ const MAX_RECORDED_HISTOGRAMS_SIZE = 100;
49
+ const OVERRIDES_FILE_SYSTEM_PATH = '/overrides' as Platform.DevToolsPath.RawPathString;
50
+
51
+ /**
52
+ * The `InspectorFrontendHostStub` is a stub interface used the frontend is loaded like a webpage. Examples:
53
+ * - devtools://devtools/bundled/devtools_app.html
54
+ * - https://chrome-devtools-frontend.appspot.com/serve_rev/@030cc140435b0152645522b9864b75cac6c0a854/worker_app.html
55
+ * - http://localhost:9222/devtools/inspector.html?ws=localhost:9222/devtools/page/xTARGET_IDx
56
+ *
57
+ * When the frontend runs within the native embedder, then the InspectorFrontendHostAPI methods are provided
58
+ * by devtools_compatibility.js. Those leverage `DevToolsAPI.sendMessageToEmbedder()` which match up with
59
+ * the embedder API defined here: https://source.chromium.org/search?q=f:devtools%20f:dispatcher%20f:cc%20symbol:CreateForDevToolsFrontend&sq=&ss=chromium%2Fchromium%2Fsrc
60
+ * The native implementations live in devtools_ui_bindings.cc: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc
61
+ */
62
+ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
63
+ readonly #urlsBeingSaved = new Map<
64
+ Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, {isBase64: boolean, buffer: string[]}>();
65
+ #fileSystem: FileSystem|null = null;
66
+ /**
67
+ * Injected bellow in both stub and normal runs via:
68
+ * ```ts
69
+ * InspectorFrontendHostInstance.events = new Common.ObjectWrapper.ObjectWrapper();
70
+ * ```
71
+ */
72
+ declare events: Common.EventTarget.EventTarget<EventTypes>;
73
+
74
+ recordedCountHistograms:
75
+ Array<{histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number}> = [];
76
+ recordedEnumeratedHistograms: Array<{actionName: EnumeratedHistogram, actionCode: number}> = [];
77
+ recordedPerformanceHistograms: Array<{histogramName: string, duration: number}> = [];
78
+
79
+ constructor() {
80
+ // Guard against errors should this file ever be imported at the top level
81
+ // within a worker - in which case this constructor is run. If there's no
82
+ // document, we can early exit.
83
+ if (typeof document === 'undefined') {
84
+ return;
85
+ }
86
+
87
+ function stopEventPropagation(this: InspectorFrontendHostAPI, event: KeyboardEvent): void {
88
+ // Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode.
89
+ const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey;
90
+ if (zoomModifier && (event.key === '+' || event.key === '-')) {
91
+ event.stopPropagation();
92
+ }
93
+ }
94
+
95
+ document.addEventListener('keydown', event => {
96
+ stopEventPropagation.call(this, (event));
97
+ }, true);
98
+ }
99
+
100
+ platform(): string {
101
+ const userAgent = navigator.userAgent;
102
+ if (userAgent.includes('Windows NT')) {
103
+ return 'windows';
104
+ }
105
+ if (userAgent.includes('Mac OS X')) {
106
+ return 'mac';
107
+ }
108
+ return 'linux';
109
+ }
110
+
111
+ loadCompleted(): void {
112
+ }
113
+
114
+ bringToFront(): void {
115
+ }
116
+
117
+ closeWindow(): void {
118
+ }
119
+
120
+ setIsDocked(_isDocked: boolean, callback: () => void): void {
121
+ window.setTimeout(callback, 0);
122
+ }
123
+
124
+ showSurvey(_trigger: string, callback: (arg0: ShowSurveyResult) => void): void {
125
+ window.setTimeout(() => callback({surveyShown: false}), 0);
126
+ }
127
+
128
+ canShowSurvey(_trigger: string, callback: (arg0: CanShowSurveyResult) => void): void {
129
+ window.setTimeout(() => callback({canShowSurvey: false}), 0);
130
+ }
131
+
132
+ /**
133
+ * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
134
+ */
135
+ setInspectedPageBounds(_bounds: {
136
+ x: number,
137
+ y: number,
138
+ width: number,
139
+ height: number,
140
+ }): void {
141
+ }
142
+
143
+ inspectElementCompleted(): void {
144
+ }
145
+
146
+ setInjectedScriptForOrigin(_origin: string, _script: string): void {
147
+ }
148
+
149
+ inspectedURLChanged(url: Platform.DevToolsPath.UrlString): void {
150
+ document.title = i18nString(UIStrings.devtoolsS, {PH1: url.replace(/^https?:\/\//, '')});
151
+ }
152
+
153
+ copyText(text: string|null|undefined): void {
154
+ if (text === undefined || text === null) {
155
+ return;
156
+ }
157
+ void navigator.clipboard.writeText(text);
158
+ }
159
+
160
+ openInNewTab(url: Platform.DevToolsPath.UrlString): void {
161
+ if (Common.ParsedURL.schemeIs(url, 'javascript:')) {
162
+ return;
163
+ }
164
+ window.open(url, '_blank');
165
+ }
166
+
167
+ openSearchResultsInNewTab(_query: string): void {
168
+ Common.Console.Console.instance().error(
169
+ 'Search is not enabled in hosted mode. Please inspect using chrome://inspect');
170
+ }
171
+
172
+ showItemInFolder(_fileSystemPath: Platform.DevToolsPath.RawPathString): void {
173
+ Common.Console.Console.instance().error(
174
+ 'Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');
175
+ }
176
+
177
+ // Reminder: the methods in this class belong to InspectorFrontendHostStub and are typically not executed.
178
+ // InspectorFrontendHostStub is ONLY used in the uncommon case of devtools not being embedded. For example: trace.cafe or http://localhost:9222/devtools/inspector.html?ws=localhost:9222/devtools/page/xTARGET_IDx
179
+ save(
180
+ url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string, _forceSaveAs: boolean,
181
+ isBase64: boolean): void {
182
+ let buffer = this.#urlsBeingSaved.get(url)?.buffer;
183
+ if (!buffer) {
184
+ buffer = [];
185
+ this.#urlsBeingSaved.set(url, {isBase64, buffer});
186
+ }
187
+ buffer.push(content);
188
+ this.events.dispatchEventToListeners(Events.SavedURL, {url, fileSystemPath: url});
189
+ }
190
+
191
+ append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {
192
+ const buffer = this.#urlsBeingSaved.get(url)?.buffer;
193
+ if (buffer) {
194
+ buffer.push(content);
195
+ this.events.dispatchEventToListeners(Events.AppendedToURL, url);
196
+ }
197
+ }
198
+
199
+ close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {
200
+ const {isBase64, buffer} = this.#urlsBeingSaved.get(url) || {isBase64: false, buffer: []};
201
+ this.#urlsBeingSaved.delete(url);
202
+ let fileName = '';
203
+
204
+ if (url) {
205
+ try {
206
+ const trimmed = Platform.StringUtilities.trimURL(url);
207
+ fileName = Platform.StringUtilities.removeURLFragment(trimmed);
208
+ } catch {
209
+ // If url is not a valid URL, it is probably a filename.
210
+ fileName = url;
211
+ }
212
+ }
213
+
214
+ /* eslint-disable-next-line @devtools/no-imperative-dom-api */
215
+ const link = document.createElement('a');
216
+ link.download = fileName;
217
+ let blob;
218
+ if (isBase64) {
219
+ const bytes = Common.Base64.decode(buffer.join(''));
220
+ blob = new Blob([bytes], {type: 'application/gzip'});
221
+ } else {
222
+ blob = new Blob(buffer, {type: 'text/plain'});
223
+ }
224
+ const blobUrl = URL.createObjectURL(blob);
225
+ link.href = blobUrl;
226
+ link.click();
227
+ URL.revokeObjectURL(blobUrl);
228
+ }
229
+
230
+ sendMessageToBackend(_message: string): void {
231
+ }
232
+
233
+ recordCountHistogram(histogramName: string, sample: number, min: number, exclusiveMax: number, bucketSize: number):
234
+ void {
235
+ if (this.recordedCountHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
236
+ this.recordedCountHistograms.shift();
237
+ }
238
+ this.recordedCountHistograms.push({histogramName, sample, min, exclusiveMax, bucketSize});
239
+ }
240
+
241
+ recordEnumeratedHistogram(actionName: EnumeratedHistogram, actionCode: number, _bucketSize: number): void {
242
+ if (this.recordedEnumeratedHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
243
+ this.recordedEnumeratedHistograms.shift();
244
+ }
245
+ this.recordedEnumeratedHistograms.push({actionName, actionCode});
246
+ }
247
+
248
+ recordPerformanceHistogram(histogramName: string, duration: number): void {
249
+ if (this.recordedPerformanceHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
250
+ this.recordedPerformanceHistograms.shift();
251
+ }
252
+ this.recordedPerformanceHistograms.push({histogramName, duration});
253
+ }
254
+
255
+ recordUserMetricsAction(_umaName: string): void {
256
+ }
257
+
258
+ recordNewBadgeUsage(_featureName: string): void {
259
+ }
260
+
261
+ connectAutomaticFileSystem(
262
+ _fileSystemPath: Platform.DevToolsPath.RawPathString,
263
+ _fileSystemUUID: string,
264
+ _addIfMissing: boolean,
265
+ callback: (result: {success: boolean}) => void,
266
+ ): void {
267
+ queueMicrotask(() => callback({success: false}));
268
+ }
269
+
270
+ disconnectAutomaticFileSystem(_fileSystemPath: Platform.DevToolsPath.RawPathString): void {
271
+ }
272
+
273
+ requestFileSystems(): void {
274
+ this.events.dispatchEventToListeners(Events.FileSystemsLoaded, []);
275
+ }
276
+
277
+ addFileSystem(_type?: string): void {
278
+ const onFileSystem = (fs: FileSystem): void => {
279
+ this.#fileSystem = fs;
280
+ const fileSystem = {
281
+ fileSystemName: 'sandboxedRequestedFileSystem',
282
+ fileSystemPath: OVERRIDES_FILE_SYSTEM_PATH,
283
+ rootURL: 'filesystem:devtools://devtools/isolated/',
284
+ type: 'overrides' as const,
285
+ };
286
+ this.events.dispatchEventToListeners(Events.FileSystemAdded, {fileSystem});
287
+ };
288
+ window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, onFileSystem);
289
+ }
290
+
291
+ removeFileSystem(_fileSystemPath: Platform.DevToolsPath.RawPathString): void {
292
+ const removalCallback = (entries: Entry[]): void => {
293
+ entries.forEach(entry => {
294
+ if (entry.isDirectory) {
295
+ (entry as DirectoryEntry).removeRecursively(() => {});
296
+ } else if (entry.isFile) {
297
+ entry.remove(() => {});
298
+ }
299
+ });
300
+ };
301
+
302
+ if (this.#fileSystem) {
303
+ this.#fileSystem.root.createReader().readEntries(removalCallback);
304
+ }
305
+
306
+ this.#fileSystem = null;
307
+ this.events.dispatchEventToListeners(Events.FileSystemRemoved, OVERRIDES_FILE_SYSTEM_PATH);
308
+ }
309
+
310
+ isolatedFileSystem(_fileSystemId: string, _registeredName: string): FileSystem|null {
311
+ return this.#fileSystem;
312
+ }
313
+
314
+ loadNetworkResource(
315
+ url: string, _headers: string, streamId: number, callback: (arg0: LoadNetworkResourceResult) => void): void {
316
+ fetch(url)
317
+ .then(async result => {
318
+ const respBuffer = await result.arrayBuffer();
319
+ const text = await Common.Gzip.arrayBufferToString(respBuffer);
320
+ return text;
321
+ })
322
+ .then(function(text) {
323
+ resourceLoaderStreamWrite(streamId, text);
324
+ callback({
325
+ statusCode: 200,
326
+ headers: undefined,
327
+ messageOverride: undefined,
328
+ netError: undefined,
329
+ netErrorName: undefined,
330
+ urlValid: undefined,
331
+ });
332
+ })
333
+ .catch(function() {
334
+ callback({
335
+ statusCode: 404,
336
+ headers: undefined,
337
+ messageOverride: undefined,
338
+ netError: undefined,
339
+ netErrorName: undefined,
340
+ urlValid: undefined,
341
+ });
342
+ });
343
+ }
344
+
345
+ registerPreference(_name: string, _options: {synced?: boolean}): void {
346
+ }
347
+
348
+ getPreferences(callback: (arg0: Record<string, string>) => void): void {
349
+ const prefs: Record<string, string> = {};
350
+ for (const name in window.localStorage) {
351
+ prefs[name] = window.localStorage[name];
352
+ }
353
+ callback(prefs);
354
+ }
355
+
356
+ getPreference(name: string, callback: (arg0: string) => void): void {
357
+ callback(window.localStorage[name]);
358
+ }
359
+
360
+ setPreference(name: string, value: string): void {
361
+ window.localStorage[name] = value;
362
+ }
363
+
364
+ removePreference(name: string): void {
365
+ delete window.localStorage[name];
366
+ }
367
+
368
+ clearPreferences(): void {
369
+ window.localStorage.clear();
370
+ }
371
+
372
+ getSyncInformation(callback: (arg0: SyncInformation) => void): void {
373
+ if ('getSyncInformationForTesting' in globalThis) {
374
+ // @ts-expect-error for testing
375
+ return callback(globalThis.getSyncInformationForTesting());
376
+ }
377
+ callback({
378
+ isSyncActive: false,
379
+ arePreferencesSynced: false,
380
+ });
381
+ }
382
+
383
+ getHostConfig(callback: (hostConfig: Root.Runtime.HostConfig) => void): void {
384
+ // This HostConfig config is used in the hosted mode (see the
385
+ // comment on top of this class). Only add non-default config params
386
+ // here that you want to also apply in the hosted mode. For tests
387
+ // use the hostConfigForTesting override.
388
+ const hostConfigForHostedMode: Root.Runtime.HostConfig = {
389
+ devToolsVeLogging: {
390
+ enabled: true,
391
+ },
392
+ thirdPartyCookieControls: {
393
+ thirdPartyCookieMetadataEnabled: true,
394
+ thirdPartyCookieHeuristicsEnabled: true,
395
+ managedBlockThirdPartyCookies: 'Unset',
396
+ },
397
+ devToolsFlexibleLayout: {
398
+ verticalDrawerEnabled: true,
399
+ },
400
+ devToolsStartingStyleDebugging: {
401
+ enabled: false,
402
+ },
403
+ };
404
+ if ('hostConfigForTesting' in globalThis) {
405
+ const {hostConfigForTesting} = (globalThis as unknown as {hostConfigForTesting: Root.Runtime.HostConfig});
406
+ for (const key of Object.keys(hostConfigForTesting)) {
407
+ const mergeEntry = <K extends keyof Root.Runtime.HostConfig>(key: K): void => {
408
+ if (typeof hostConfigForHostedMode[key] === 'object' && typeof hostConfigForTesting[key] === 'object') {
409
+ // If the config is an object, merge the settings, but preferring
410
+ // the hostConfigForTesting values over the result values.
411
+ hostConfigForHostedMode[key] = {...hostConfigForHostedMode[key], ...hostConfigForTesting[key]};
412
+ } else {
413
+ // Override with the testing config if the value is present + not null/undefined.
414
+ hostConfigForHostedMode[key] = hostConfigForTesting[key] ?? hostConfigForHostedMode[key];
415
+ }
416
+ };
417
+ mergeEntry(key as keyof Root.Runtime.HostConfig);
418
+ }
419
+ }
420
+ callback(hostConfigForHostedMode);
421
+ }
422
+
423
+ upgradeDraggedFileSystemPermissions(_fileSystem: FileSystem): void {
424
+ }
425
+
426
+ indexPath(_requestId: number, _fileSystemPath: Platform.DevToolsPath.RawPathString, _excludedFolders: string): void {
427
+ }
428
+
429
+ stopIndexing(_requestId: number): void {
430
+ }
431
+
432
+ searchInPath(_requestId: number, _fileSystemPath: Platform.DevToolsPath.RawPathString, _query: string): void {
433
+ }
434
+
435
+ zoomFactor(): number {
436
+ return 1;
437
+ }
438
+
439
+ zoomIn(): void {
440
+ }
441
+
442
+ zoomOut(): void {
443
+ }
444
+
445
+ resetZoom(): void {
446
+ }
447
+
448
+ setWhitelistedShortcuts(_shortcuts: string): void {
449
+ }
450
+
451
+ setEyeDropperActive(_active: boolean): void {
452
+ }
453
+
454
+ showCertificateViewer(_certChain: string[]): void {
455
+ }
456
+
457
+ reattach(_callback: () => void): void {
458
+ }
459
+
460
+ readyForTest(): void {
461
+ }
462
+
463
+ connectionReady(): void {
464
+ }
465
+
466
+ setOpenNewWindowForPopups(_value: boolean): void {
467
+ }
468
+
469
+ setDevicesDiscoveryConfig(_config: Adb.Config): void {
470
+ }
471
+
472
+ setDevicesUpdatesEnabled(_enabled: boolean): void {
473
+ }
474
+
475
+ openRemotePage(_browserId: string, _url: string): void {
476
+ }
477
+
478
+ openNodeFrontend(): void {
479
+ }
480
+
481
+ showContextMenuAtPoint(_x: number, _y: number, _items: ContextMenuDescriptor[], _document: Document): void {
482
+ throw new Error('Soft context menu should be used');
483
+ }
484
+
485
+ /**
486
+ * Think of **Hosted mode** as "non-embedded" mode; you can see a devtools frontend URL as the tab's URL. It's an atypical way that DevTools is run.
487
+ * Whereas in **Non-hosted** (aka "embedded"), DevTools is embedded and fully dockable. It's the common way DevTools is run.
488
+ *
489
+ * **Hosted mode** == we're using the `InspectorFrontendHostStub`. impl. (@see `InspectorFrontendHostStub` class comment)
490
+ * Whereas with **non-hosted** mode, native `DevToolsEmbedderMessageDispatcher` is used for CDP and more. `globalThis.DevToolsAPI` is present.
491
+ *
492
+ * Relationships to other signals:
493
+ * - _Connection_: Hosted-ness does not indicate whether the frontend is _connected to a valid CDP target_.
494
+ * - _Dockability_: Being _"dockable"_ (aka `canDock`) is typically aligned but technically orthogonal.
495
+ * - _URL scheme_: If the main frame's URL scheme is `devtools://`, it's non-hosted.
496
+ *
497
+ * | Example case | Mode | Example devtools |
498
+ * | :------------------------------------------ | :------------- | :---------------------------------------------------------------------------- |
499
+ * | tab URL: `devtools://…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?targetType=tab&...` |
500
+ * | tab URL: `devtools://…?ws=…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?ws=localhost:9228/...` |
501
+ * | tab URL: `devtools://…` but no connection | **NOT Hosted** | `devtools://devtools/bundled/trace_app.html` |
502
+ * | tab URL: `https://…` but no connection | **Hosted** | `https://chrome-devtools-frontend.appspot.com/serve_rev/@.../trace_app.html` |
503
+ * | tab URL: `http://…?ws=` (connected) | **Hosted** | `http://localhost:9222/devtools/inspector.html?ws=localhost:9222/...` |
504
+ */
505
+ isHostedMode(): boolean {
506
+ return true;
507
+ }
508
+
509
+ setAddExtensionCallback(_callback: (arg0: ExtensionDescriptor) => void): void {
510
+ // Extensions are not supported in hosted mode.
511
+ }
512
+
513
+ async initialTargetId(): Promise<string|null> {
514
+ return null;
515
+ }
516
+
517
+ doAidaConversation(_request: string, _streamId: number, callback: (result: DoAidaConversationResult) => void): void {
518
+ callback({
519
+ error: 'Not implemented',
520
+ });
521
+ }
522
+
523
+ registerAidaClientEvent(_request: string, callback: (result: AidaClientResult) => void): void {
524
+ callback({
525
+ error: 'Not implemented',
526
+ });
527
+ }
528
+
529
+ aidaCodeComplete(_request: string, callback: (result: AidaCodeCompleteResult) => void): void {
530
+ callback({
531
+ error: 'Not implemented',
532
+ });
533
+ }
534
+
535
+ dispatchHttpRequest(_request: DispatchHttpRequestRequest, callback: (result: DispatchHttpRequestResult) => void):
536
+ void {
537
+ callback({error: 'Not implemented'});
538
+ }
539
+
540
+ recordImpression(_event: ImpressionEvent): void {
541
+ }
542
+ recordResize(_event: ResizeEvent): void {
543
+ }
544
+ recordClick(_event: ClickEvent): void {
545
+ }
546
+ recordHover(_event: HoverEvent): void {
547
+ }
548
+ recordDrag(_event: DragEvent): void {
549
+ }
550
+ recordChange(_event: ChangeEvent): void {
551
+ }
552
+ recordKeyDown(_event: KeyDownEvent): void {
553
+ }
554
+ recordSettingAccess(_event: SettingAccessEvent): void {
555
+ }
556
+ recordFunctionCall(_event: FunctionCallEvent): void {
557
+ }
558
+ }
@@ -195,28 +195,14 @@ function createErrorMessageFromResponse(response: LoadNetworkResourceResult): {
195
195
  return {success, description: {statusCode, netError, netErrorName, urlValid, message}};
196
196
  }
197
197
 
198
- const loadXHR = (url: string): Promise<string> => {
199
- return new Promise((successCallback, failureCallback) => {
200
- function onReadyStateChanged(): void {
201
- if (xhr.readyState !== XMLHttpRequest.DONE) {
202
- return;
203
- }
204
- if (xhr.status !== 200) {
205
- xhr.onreadystatechange = null;
206
- failureCallback(new Error(String(xhr.status)));
207
- return;
208
- }
209
- xhr.onreadystatechange = null;
210
- successCallback(xhr.responseText);
211
- }
212
-
213
- const xhr = new XMLHttpRequest();
214
- xhr.withCredentials = false;
215
- xhr.open('GET', url, true);
216
- xhr.onreadystatechange = onReadyStateChanged;
217
- xhr.send(null);
218
- });
219
- };
198
+ async function fetchToString(url: string): Promise<string> {
199
+ try {
200
+ const response = await fetch(url);
201
+ return await response.text();
202
+ } catch (cause) {
203
+ throw new Error(`Failed to fetch ${url}`, {cause});
204
+ }
205
+ }
220
206
 
221
207
  function canBeRemoteFilePath(url: string): boolean {
222
208
  try {
@@ -237,7 +223,7 @@ export const loadAsStream = function(
237
223
  const streamId = bindOutputStream(stream);
238
224
  const parsedURL = new Common.ParsedURL.ParsedURL(url);
239
225
  if (parsedURL.isDataURL()) {
240
- loadXHR(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed);
226
+ fetchToString(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed);
241
227
  return;
242
228
  }
243
229
 
@@ -923,9 +923,9 @@ export enum IssueCreated {
923
923
  'GenericIssue::FormInputWithNoLabelError' = 67,
924
924
  'GenericIssue::FormAutocompleteAttributeEmptyError' = 68,
925
925
  'GenericIssue::FormEmptyIdAndNameAttributesForInputError' = 69,
926
- 'GenericIssue::FormAriaLabelledByToNonExistingId' = 70,
926
+ 'GenericIssue::FormAriaLabelledByToNonExistingIdError' = 70,
927
927
  'GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError' = 71,
928
- 'GenericIssue::FormLabelHasNeitherForNorNestedInput' = 72,
928
+ 'GenericIssue::FormLabelHasNeitherForNorNestedInputError' = 72,
929
929
  'GenericIssue::FormLabelForMatchesNonExistingIdError' = 73,
930
930
  'GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError' = 74,
931
931
  'GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError' = 75,
@@ -973,7 +973,7 @@ export enum IssueCreated {
973
973
 
974
974
  export const enum DeveloperResourceLoaded {
975
975
  LOAD_THROUGH_PAGE_VIA_TARGET = 0,
976
- LOAD_THROUGH_PAGE_VIA_FRAME = 1,
976
+ /* LOAD_THROUGH_PAGE_VIA_FRAME = 1 was barely used */
977
977
  LOAD_THROUGH_PAGE_FAILURE = 2,
978
978
  LOAD_THROUGH_PAGE_FALLBACK = 3,
979
979
  FALLBACK_AFTER_FAILURE = 4,
@@ -1211,7 +1211,7 @@ export const enum SwatchType {
1211
1211
  LENGTH = 8,
1212
1212
  POSITION_TRY_LINK = 10,
1213
1213
  ATTR_LINK = 11,
1214
- MASONRY = 12,
1214
+ GRID_LANES = 12,
1215
1215
  MAX_VALUE = 13,
1216
1216
  }
1217
1217
 
@@ -6,6 +6,10 @@ export type ConstructorT<T> = new (...args: any[]) => T;
6
6
 
7
7
  /**
8
8
  * Container for singletons scoped to a single DevTools universe.
9
+ *
10
+ * When wiring up dependencies, strongly prefer to pass all direct dependencies
11
+ * via constructor, and not just pass a {@link DevToolsContext} around. That would hide
12
+ * dependencies and we want to be explicit.
9
13
  */
10
14
  export class DevToolsContext {
11
15
  readonly #instances = new Map<ConstructorT<unknown>, unknown>();
@@ -434,6 +434,10 @@ export interface HostConfigDeepLinksViaExtensibilityApi {
434
434
  enabled: boolean;
435
435
  }
436
436
 
437
+ export interface HostConfigGreenDevUi {
438
+ enabled: boolean;
439
+ }
440
+
437
441
  export interface HostConfigVeLogging {
438
442
  enabled: boolean;
439
443
  testing: boolean;
@@ -532,6 +536,10 @@ export interface DevToolsEnableDurableMessages {
532
536
  enabled: boolean;
533
537
  }
534
538
 
539
+ interface HostConfigAiAssistanceContextSelectionAgent {
540
+ enabled: boolean;
541
+ }
542
+
535
543
  /**
536
544
  * The host configuration that we expect from the DevTools back-end.
537
545
  *
@@ -551,6 +559,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
551
559
  devToolsConsoleInsights: HostConfigConsoleInsights,
552
560
  devToolsDeepLinksViaExtensibilityApi: HostConfigDeepLinksViaExtensibilityApi,
553
561
  devToolsFreestyler: HostConfigFreestyler,
562
+ devToolsGreenDevUi: HostConfigGreenDevUi,
554
563
  devToolsAiAssistanceNetworkAgent: HostConfigAiAssistanceNetworkAgent,
555
564
  devToolsAiDebugWithAi: AiDebugWithAi,
556
565
  devToolsAiAssistanceFileAgent: HostConfigAiAssistanceFileAgent,
@@ -580,6 +589,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
580
589
  devToolsStartingStyleDebugging: DevToolsStartingStyleDebugging,
581
590
  devToolsAiPromptApi: AiPromptApi,
582
591
  devToolsEnableDurableMessages: DevToolsEnableDurableMessages,
592
+ devToolsAiAssistanceContextSelectionAgent: HostConfigAiAssistanceContextSelectionAgent,
583
593
  }>;
584
594
 
585
595
  /**
@@ -24,7 +24,7 @@ import {
24
24
  CustomFunctionMatcher,
25
25
  defaultValueForCSSType,
26
26
  EnvFunctionMatcher,
27
- FlexGridMasonryMatcher,
27
+ FlexGridGridLanesMatcher,
28
28
  GridTemplateMatcher,
29
29
  LengthMatcher,
30
30
  LightDarkColorMatcher,
@@ -937,7 +937,7 @@ export class CSSMatchedStyles {
937
937
  new LinearGradientMatcher(),
938
938
  new AnchorFunctionMatcher(),
939
939
  new PositionAnchorMatcher(),
940
- new FlexGridMasonryMatcher(),
940
+ new FlexGridGridLanesMatcher(),
941
941
  new PositionTryMatcher(),
942
942
  new LengthMatcher(),
943
943
  new MathFunctionMatcher(),