chrome-devtools-mcp 0.10.2 → 0.11.0

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 (121) hide show
  1. package/README.md +67 -9
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/common.js +1 -3
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +1 -1
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +31 -449
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostStub.js +430 -0
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/ResourceLoader.js +10 -22
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +2 -5
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/i18n/collect-ui-strings.js +1 -1
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/i18n/generate-locales-js.js +1 -1
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/HostRuntime.js +19 -0
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/StringUtilities.js +1 -1
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/HostRuntime.js +4 -0
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/api/api.js +5 -0
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/{common/Worker.js → platform/browser/HostRuntime.js} +18 -7
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/browser/browser.js +5 -0
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/HostRuntime.js +72 -0
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/node/node.js +5 -0
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/platform.js +2 -2
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/root/DevToolsContext.js +4 -0
  20. package/build/node_modules/chrome-devtools-frontend/front_end/core/root/Runtime.js +7 -0
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +1 -1
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +2 -2
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMetadata.js +17 -5
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +3 -3
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +1 -1
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +10 -10
  27. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ConsoleModel.js +1 -1
  28. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Cookie.js +1 -1
  29. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +5 -2
  30. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +1 -1
  31. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +46 -34
  32. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +3 -0
  33. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PageResourceLoader.js +43 -33
  34. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +1 -1
  35. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RemoteObject.js +1 -1
  36. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +1 -1
  37. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Script.js +26 -1
  38. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +4 -0
  39. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapCache.js +16 -0
  40. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapManager.js +11 -5
  41. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapScopesInfo.js +129 -20
  42. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Target.js +4 -13
  43. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TargetManager.js +35 -4
  44. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +72 -0
  45. package/build/node_modules/chrome-devtools-frontend/front_end/foundation/Universe.js +5 -1
  46. package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +48 -4
  47. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +45 -42
  48. package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +56 -77
  49. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +21 -6
  50. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +9 -3
  51. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CSSWorkspaceBinding.js +4 -3
  52. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +34 -0
  53. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +15 -0
  54. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceMapping.js +59 -0
  55. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceScriptMapping.js +38 -0
  56. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/SASSSourceMapping.js +5 -4
  57. package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/CPUProfileDataModel.js +9 -7
  58. package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/CrUXManager.js +5 -3
  59. package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +2 -2
  60. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/AttributionReportingIssue.js +5 -6
  61. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/BounceTrackingIssue.js +3 -11
  62. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/ClientHintIssue.js +4 -9
  63. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/ContentSecurityPolicyIssue.js +4 -9
  64. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/ContrastCheckTrigger.js +1 -1
  65. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/CookieDeprecationMetadataIssue.js +5 -11
  66. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/CookieIssue.js +26 -25
  67. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/CorsIssue.js +7 -14
  68. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/CrossOriginEmbedderPolicyIssue.js +4 -6
  69. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/DeprecationIssue.js +6 -11
  70. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/ElementAccessibilityIssue.js +6 -11
  71. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/FederatedAuthRequestIssue.js +3 -8
  72. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/FederatedAuthUserInfoRequestIssue.js +3 -8
  73. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/GenericIssue.js +36 -21
  74. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/HeavyAdIssue.js +3 -8
  75. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/Issue.js +6 -1
  76. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/IssueAggregator.js +6 -1
  77. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/LowTextContrastIssue.js +2 -7
  78. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/MixedContentIssue.js +6 -10
  79. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/PartitioningBlobURLIssue.js +3 -8
  80. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/PropertyRuleIssue.js +5 -10
  81. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/QuirksModeIssue.js +2 -7
  82. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/SRIMessageSignatureIssue.js +6 -10
  83. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/SharedArrayBufferIssue.js +3 -8
  84. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/SharedDictionaryIssue.js +5 -10
  85. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/StylesheetLoadingIssue.js +7 -11
  86. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/UnencodedDigestIssue.js +1 -6
  87. package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  88. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/FunctionCodeResolver.js +192 -0
  89. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +2 -1
  90. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/SamplesHandler.js +3 -0
  91. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Trace.js +10 -0
  92. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +23 -0
  93. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/IgnoreListManager.js +1 -1
  94. package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/UISourceCode.js +38 -0
  95. package/build/node_modules/chrome-devtools-frontend/mcp/HostBindings.js +222 -0
  96. package/build/node_modules/chrome-devtools-frontend/mcp/mcp.js +15 -1
  97. package/build/src/DevToolsConnectionAdapter.js +56 -19
  98. package/build/src/DevtoolsUtils.js +143 -1
  99. package/build/src/McpContext.js +33 -11
  100. package/build/src/McpResponse.js +18 -26
  101. package/build/src/PageCollector.js +4 -11
  102. package/build/src/browser.js +4 -0
  103. package/build/src/cli.js +11 -3
  104. package/build/src/formatters/consoleFormatter.js +81 -3
  105. package/build/src/formatters/snapshotFormatter.js +18 -4
  106. package/build/src/issue-descriptions.js +4 -0
  107. package/build/src/main.js +20 -49
  108. package/build/src/third_party/THIRD_PARTY_NOTICES +1973 -27
  109. package/build/src/third_party/index.js +58356 -18839
  110. package/build/src/tools/console.js +0 -4
  111. package/build/src/tools/emulation.js +29 -6
  112. package/build/src/tools/screenshot.js +4 -2
  113. package/build/src/tools/snapshot.js +1 -1
  114. package/build/src/tools/tools.js +29 -0
  115. package/build/src/utils/keyboard.js +5 -0
  116. package/package.json +7 -7
  117. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Linkifier.js +0 -34
  118. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/DOMUtilities.js +0 -122
  119. package/build/src/features.js +0 -14
  120. /package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  121. /package/build/node_modules/chrome-devtools-frontend/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
@@ -0,0 +1,430 @@
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
+ import * as Common from '../common/common.js';
5
+ import * as i18n from '../i18n/i18n.js';
6
+ import * as Platform from '../platform/platform.js';
7
+ import { Events, } from './InspectorFrontendHostAPI.js';
8
+ import { streamWrite as resourceLoaderStreamWrite } from './ResourceLoader.js';
9
+ const UIStrings = {
10
+ /**
11
+ * @description Document title in Inspector Frontend Host of the DevTools window
12
+ * @example {example.com} PH1
13
+ */
14
+ devtoolsS: 'DevTools - {PH1}',
15
+ };
16
+ const str_ = i18n.i18n.registerUIStrings('core/host/InspectorFrontendHostStub.ts', UIStrings);
17
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
18
+ const MAX_RECORDED_HISTOGRAMS_SIZE = 100;
19
+ const OVERRIDES_FILE_SYSTEM_PATH = '/overrides';
20
+ /**
21
+ * The `InspectorFrontendHostStub` is a stub interface used the frontend is loaded like a webpage. Examples:
22
+ * - devtools://devtools/bundled/devtools_app.html
23
+ * - https://chrome-devtools-frontend.appspot.com/serve_rev/@030cc140435b0152645522b9864b75cac6c0a854/worker_app.html
24
+ * - http://localhost:9222/devtools/inspector.html?ws=localhost:9222/devtools/page/xTARGET_IDx
25
+ *
26
+ * When the frontend runs within the native embedder, then the InspectorFrontendHostAPI methods are provided
27
+ * by devtools_compatibility.js. Those leverage `DevToolsAPI.sendMessageToEmbedder()` which match up with
28
+ * the embedder API defined here: https://source.chromium.org/search?q=f:devtools%20f:dispatcher%20f:cc%20symbol:CreateForDevToolsFrontend&sq=&ss=chromium%2Fchromium%2Fsrc
29
+ * The native implementations live in devtools_ui_bindings.cc: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc
30
+ */
31
+ export class InspectorFrontendHostStub {
32
+ #urlsBeingSaved = new Map();
33
+ #fileSystem = null;
34
+ recordedCountHistograms = [];
35
+ recordedEnumeratedHistograms = [];
36
+ recordedPerformanceHistograms = [];
37
+ constructor() {
38
+ // Guard against errors should this file ever be imported at the top level
39
+ // within a worker - in which case this constructor is run. If there's no
40
+ // document, we can early exit.
41
+ if (typeof document === 'undefined') {
42
+ return;
43
+ }
44
+ function stopEventPropagation(event) {
45
+ // Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode.
46
+ const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey;
47
+ if (zoomModifier && (event.key === '+' || event.key === '-')) {
48
+ event.stopPropagation();
49
+ }
50
+ }
51
+ document.addEventListener('keydown', event => {
52
+ stopEventPropagation.call(this, (event));
53
+ }, true);
54
+ }
55
+ platform() {
56
+ const userAgent = navigator.userAgent;
57
+ if (userAgent.includes('Windows NT')) {
58
+ return 'windows';
59
+ }
60
+ if (userAgent.includes('Mac OS X')) {
61
+ return 'mac';
62
+ }
63
+ return 'linux';
64
+ }
65
+ loadCompleted() {
66
+ }
67
+ bringToFront() {
68
+ }
69
+ closeWindow() {
70
+ }
71
+ setIsDocked(_isDocked, callback) {
72
+ window.setTimeout(callback, 0);
73
+ }
74
+ showSurvey(_trigger, callback) {
75
+ window.setTimeout(() => callback({ surveyShown: false }), 0);
76
+ }
77
+ canShowSurvey(_trigger, callback) {
78
+ window.setTimeout(() => callback({ canShowSurvey: false }), 0);
79
+ }
80
+ /**
81
+ * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
82
+ */
83
+ setInspectedPageBounds(_bounds) {
84
+ }
85
+ inspectElementCompleted() {
86
+ }
87
+ setInjectedScriptForOrigin(_origin, _script) {
88
+ }
89
+ inspectedURLChanged(url) {
90
+ document.title = i18nString(UIStrings.devtoolsS, { PH1: url.replace(/^https?:\/\//, '') });
91
+ }
92
+ copyText(text) {
93
+ if (text === undefined || text === null) {
94
+ return;
95
+ }
96
+ void navigator.clipboard.writeText(text);
97
+ }
98
+ openInNewTab(url) {
99
+ if (Common.ParsedURL.schemeIs(url, 'javascript:')) {
100
+ return;
101
+ }
102
+ window.open(url, '_blank');
103
+ }
104
+ openSearchResultsInNewTab(_query) {
105
+ Common.Console.Console.instance().error('Search is not enabled in hosted mode. Please inspect using chrome://inspect');
106
+ }
107
+ showItemInFolder(_fileSystemPath) {
108
+ Common.Console.Console.instance().error('Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');
109
+ }
110
+ // Reminder: the methods in this class belong to InspectorFrontendHostStub and are typically not executed.
111
+ // 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
112
+ save(url, content, _forceSaveAs, isBase64) {
113
+ let buffer = this.#urlsBeingSaved.get(url)?.buffer;
114
+ if (!buffer) {
115
+ buffer = [];
116
+ this.#urlsBeingSaved.set(url, { isBase64, buffer });
117
+ }
118
+ buffer.push(content);
119
+ this.events.dispatchEventToListeners(Events.SavedURL, { url, fileSystemPath: url });
120
+ }
121
+ append(url, content) {
122
+ const buffer = this.#urlsBeingSaved.get(url)?.buffer;
123
+ if (buffer) {
124
+ buffer.push(content);
125
+ this.events.dispatchEventToListeners(Events.AppendedToURL, url);
126
+ }
127
+ }
128
+ close(url) {
129
+ const { isBase64, buffer } = this.#urlsBeingSaved.get(url) || { isBase64: false, buffer: [] };
130
+ this.#urlsBeingSaved.delete(url);
131
+ let fileName = '';
132
+ if (url) {
133
+ try {
134
+ const trimmed = Platform.StringUtilities.trimURL(url);
135
+ fileName = Platform.StringUtilities.removeURLFragment(trimmed);
136
+ }
137
+ catch {
138
+ // If url is not a valid URL, it is probably a filename.
139
+ fileName = url;
140
+ }
141
+ }
142
+ /* eslint-disable-next-line @devtools/no-imperative-dom-api */
143
+ const link = document.createElement('a');
144
+ link.download = fileName;
145
+ let blob;
146
+ if (isBase64) {
147
+ const bytes = Common.Base64.decode(buffer.join(''));
148
+ blob = new Blob([bytes], { type: 'application/gzip' });
149
+ }
150
+ else {
151
+ blob = new Blob(buffer, { type: 'text/plain' });
152
+ }
153
+ const blobUrl = URL.createObjectURL(blob);
154
+ link.href = blobUrl;
155
+ link.click();
156
+ URL.revokeObjectURL(blobUrl);
157
+ }
158
+ sendMessageToBackend(_message) {
159
+ }
160
+ recordCountHistogram(histogramName, sample, min, exclusiveMax, bucketSize) {
161
+ if (this.recordedCountHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
162
+ this.recordedCountHistograms.shift();
163
+ }
164
+ this.recordedCountHistograms.push({ histogramName, sample, min, exclusiveMax, bucketSize });
165
+ }
166
+ recordEnumeratedHistogram(actionName, actionCode, _bucketSize) {
167
+ if (this.recordedEnumeratedHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
168
+ this.recordedEnumeratedHistograms.shift();
169
+ }
170
+ this.recordedEnumeratedHistograms.push({ actionName, actionCode });
171
+ }
172
+ recordPerformanceHistogram(histogramName, duration) {
173
+ if (this.recordedPerformanceHistograms.length >= MAX_RECORDED_HISTOGRAMS_SIZE) {
174
+ this.recordedPerformanceHistograms.shift();
175
+ }
176
+ this.recordedPerformanceHistograms.push({ histogramName, duration });
177
+ }
178
+ recordUserMetricsAction(_umaName) {
179
+ }
180
+ recordNewBadgeUsage(_featureName) {
181
+ }
182
+ connectAutomaticFileSystem(_fileSystemPath, _fileSystemUUID, _addIfMissing, callback) {
183
+ queueMicrotask(() => callback({ success: false }));
184
+ }
185
+ disconnectAutomaticFileSystem(_fileSystemPath) {
186
+ }
187
+ requestFileSystems() {
188
+ this.events.dispatchEventToListeners(Events.FileSystemsLoaded, []);
189
+ }
190
+ addFileSystem(_type) {
191
+ const onFileSystem = (fs) => {
192
+ this.#fileSystem = fs;
193
+ const fileSystem = {
194
+ fileSystemName: 'sandboxedRequestedFileSystem',
195
+ fileSystemPath: OVERRIDES_FILE_SYSTEM_PATH,
196
+ rootURL: 'filesystem:devtools://devtools/isolated/',
197
+ type: 'overrides',
198
+ };
199
+ this.events.dispatchEventToListeners(Events.FileSystemAdded, { fileSystem });
200
+ };
201
+ window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, onFileSystem);
202
+ }
203
+ removeFileSystem(_fileSystemPath) {
204
+ const removalCallback = (entries) => {
205
+ entries.forEach(entry => {
206
+ if (entry.isDirectory) {
207
+ entry.removeRecursively(() => { });
208
+ }
209
+ else if (entry.isFile) {
210
+ entry.remove(() => { });
211
+ }
212
+ });
213
+ };
214
+ if (this.#fileSystem) {
215
+ this.#fileSystem.root.createReader().readEntries(removalCallback);
216
+ }
217
+ this.#fileSystem = null;
218
+ this.events.dispatchEventToListeners(Events.FileSystemRemoved, OVERRIDES_FILE_SYSTEM_PATH);
219
+ }
220
+ isolatedFileSystem(_fileSystemId, _registeredName) {
221
+ return this.#fileSystem;
222
+ }
223
+ loadNetworkResource(url, _headers, streamId, callback) {
224
+ fetch(url)
225
+ .then(async (result) => {
226
+ const respBuffer = await result.arrayBuffer();
227
+ const text = await Common.Gzip.arrayBufferToString(respBuffer);
228
+ return text;
229
+ })
230
+ .then(function (text) {
231
+ resourceLoaderStreamWrite(streamId, text);
232
+ callback({
233
+ statusCode: 200,
234
+ headers: undefined,
235
+ messageOverride: undefined,
236
+ netError: undefined,
237
+ netErrorName: undefined,
238
+ urlValid: undefined,
239
+ });
240
+ })
241
+ .catch(function () {
242
+ callback({
243
+ statusCode: 404,
244
+ headers: undefined,
245
+ messageOverride: undefined,
246
+ netError: undefined,
247
+ netErrorName: undefined,
248
+ urlValid: undefined,
249
+ });
250
+ });
251
+ }
252
+ registerPreference(_name, _options) {
253
+ }
254
+ getPreferences(callback) {
255
+ const prefs = {};
256
+ for (const name in window.localStorage) {
257
+ prefs[name] = window.localStorage[name];
258
+ }
259
+ callback(prefs);
260
+ }
261
+ getPreference(name, callback) {
262
+ callback(window.localStorage[name]);
263
+ }
264
+ setPreference(name, value) {
265
+ window.localStorage[name] = value;
266
+ }
267
+ removePreference(name) {
268
+ delete window.localStorage[name];
269
+ }
270
+ clearPreferences() {
271
+ window.localStorage.clear();
272
+ }
273
+ getSyncInformation(callback) {
274
+ if ('getSyncInformationForTesting' in globalThis) {
275
+ // @ts-expect-error for testing
276
+ return callback(globalThis.getSyncInformationForTesting());
277
+ }
278
+ callback({
279
+ isSyncActive: false,
280
+ arePreferencesSynced: false,
281
+ });
282
+ }
283
+ getHostConfig(callback) {
284
+ // This HostConfig config is used in the hosted mode (see the
285
+ // comment on top of this class). Only add non-default config params
286
+ // here that you want to also apply in the hosted mode. For tests
287
+ // use the hostConfigForTesting override.
288
+ const hostConfigForHostedMode = {
289
+ devToolsVeLogging: {
290
+ enabled: true,
291
+ },
292
+ thirdPartyCookieControls: {
293
+ thirdPartyCookieMetadataEnabled: true,
294
+ thirdPartyCookieHeuristicsEnabled: true,
295
+ managedBlockThirdPartyCookies: 'Unset',
296
+ },
297
+ devToolsFlexibleLayout: {
298
+ verticalDrawerEnabled: true,
299
+ },
300
+ devToolsStartingStyleDebugging: {
301
+ enabled: false,
302
+ },
303
+ };
304
+ if ('hostConfigForTesting' in globalThis) {
305
+ const { hostConfigForTesting } = globalThis;
306
+ for (const key of Object.keys(hostConfigForTesting)) {
307
+ const mergeEntry = (key) => {
308
+ if (typeof hostConfigForHostedMode[key] === 'object' && typeof hostConfigForTesting[key] === 'object') {
309
+ // If the config is an object, merge the settings, but preferring
310
+ // the hostConfigForTesting values over the result values.
311
+ hostConfigForHostedMode[key] = { ...hostConfigForHostedMode[key], ...hostConfigForTesting[key] };
312
+ }
313
+ else {
314
+ // Override with the testing config if the value is present + not null/undefined.
315
+ hostConfigForHostedMode[key] = hostConfigForTesting[key] ?? hostConfigForHostedMode[key];
316
+ }
317
+ };
318
+ mergeEntry(key);
319
+ }
320
+ }
321
+ callback(hostConfigForHostedMode);
322
+ }
323
+ upgradeDraggedFileSystemPermissions(_fileSystem) {
324
+ }
325
+ indexPath(_requestId, _fileSystemPath, _excludedFolders) {
326
+ }
327
+ stopIndexing(_requestId) {
328
+ }
329
+ searchInPath(_requestId, _fileSystemPath, _query) {
330
+ }
331
+ zoomFactor() {
332
+ return 1;
333
+ }
334
+ zoomIn() {
335
+ }
336
+ zoomOut() {
337
+ }
338
+ resetZoom() {
339
+ }
340
+ setWhitelistedShortcuts(_shortcuts) {
341
+ }
342
+ setEyeDropperActive(_active) {
343
+ }
344
+ showCertificateViewer(_certChain) {
345
+ }
346
+ reattach(_callback) {
347
+ }
348
+ readyForTest() {
349
+ }
350
+ connectionReady() {
351
+ }
352
+ setOpenNewWindowForPopups(_value) {
353
+ }
354
+ setDevicesDiscoveryConfig(_config) {
355
+ }
356
+ setDevicesUpdatesEnabled(_enabled) {
357
+ }
358
+ openRemotePage(_browserId, _url) {
359
+ }
360
+ openNodeFrontend() {
361
+ }
362
+ showContextMenuAtPoint(_x, _y, _items, _document) {
363
+ throw new Error('Soft context menu should be used');
364
+ }
365
+ /**
366
+ * 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.
367
+ * Whereas in **Non-hosted** (aka "embedded"), DevTools is embedded and fully dockable. It's the common way DevTools is run.
368
+ *
369
+ * **Hosted mode** == we're using the `InspectorFrontendHostStub`. impl. (@see `InspectorFrontendHostStub` class comment)
370
+ * Whereas with **non-hosted** mode, native `DevToolsEmbedderMessageDispatcher` is used for CDP and more. `globalThis.DevToolsAPI` is present.
371
+ *
372
+ * Relationships to other signals:
373
+ * - _Connection_: Hosted-ness does not indicate whether the frontend is _connected to a valid CDP target_.
374
+ * - _Dockability_: Being _"dockable"_ (aka `canDock`) is typically aligned but technically orthogonal.
375
+ * - _URL scheme_: If the main frame's URL scheme is `devtools://`, it's non-hosted.
376
+ *
377
+ * | Example case | Mode | Example devtools |
378
+ * | :------------------------------------------ | :------------- | :---------------------------------------------------------------------------- |
379
+ * | tab URL: `devtools://…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?targetType=tab&...` |
380
+ * | tab URL: `devtools://…?ws=…` | **NOT Hosted** | `devtools://devtools/bundled/devtools_app.html?ws=localhost:9228/...` |
381
+ * | tab URL: `devtools://…` but no connection | **NOT Hosted** | `devtools://devtools/bundled/trace_app.html` |
382
+ * | tab URL: `https://…` but no connection | **Hosted** | `https://chrome-devtools-frontend.appspot.com/serve_rev/@.../trace_app.html` |
383
+ * | tab URL: `http://…?ws=` (connected) | **Hosted** | `http://localhost:9222/devtools/inspector.html?ws=localhost:9222/...` |
384
+ */
385
+ isHostedMode() {
386
+ return true;
387
+ }
388
+ setAddExtensionCallback(_callback) {
389
+ // Extensions are not supported in hosted mode.
390
+ }
391
+ async initialTargetId() {
392
+ return null;
393
+ }
394
+ doAidaConversation(_request, _streamId, callback) {
395
+ callback({
396
+ error: 'Not implemented',
397
+ });
398
+ }
399
+ registerAidaClientEvent(_request, callback) {
400
+ callback({
401
+ error: 'Not implemented',
402
+ });
403
+ }
404
+ aidaCodeComplete(_request, callback) {
405
+ callback({
406
+ error: 'Not implemented',
407
+ });
408
+ }
409
+ dispatchHttpRequest(_request, callback) {
410
+ callback({ error: 'Not implemented' });
411
+ }
412
+ recordImpression(_event) {
413
+ }
414
+ recordResize(_event) {
415
+ }
416
+ recordClick(_event) {
417
+ }
418
+ recordHover(_event) {
419
+ }
420
+ recordDrag(_event) {
421
+ }
422
+ recordChange(_event) {
423
+ }
424
+ recordKeyDown(_event) {
425
+ }
426
+ recordSettingAccess(_event) {
427
+ }
428
+ recordFunctionCall(_event) {
429
+ }
430
+ }
@@ -158,27 +158,15 @@ function createErrorMessageFromResponse(response) {
158
158
  console.assert(success === (message.length === 0));
159
159
  return { success, description: { statusCode, netError, netErrorName, urlValid, message } };
160
160
  }
161
- const loadXHR = (url) => {
162
- return new Promise((successCallback, failureCallback) => {
163
- function onReadyStateChanged() {
164
- if (xhr.readyState !== XMLHttpRequest.DONE) {
165
- return;
166
- }
167
- if (xhr.status !== 200) {
168
- xhr.onreadystatechange = null;
169
- failureCallback(new Error(String(xhr.status)));
170
- return;
171
- }
172
- xhr.onreadystatechange = null;
173
- successCallback(xhr.responseText);
174
- }
175
- const xhr = new XMLHttpRequest();
176
- xhr.withCredentials = false;
177
- xhr.open('GET', url, true);
178
- xhr.onreadystatechange = onReadyStateChanged;
179
- xhr.send(null);
180
- });
181
- };
161
+ async function fetchToString(url) {
162
+ try {
163
+ const response = await fetch(url);
164
+ return await response.text();
165
+ }
166
+ catch (cause) {
167
+ throw new Error(`Failed to fetch ${url}`, { cause });
168
+ }
169
+ }
182
170
  function canBeRemoteFilePath(url) {
183
171
  try {
184
172
  const urlObject = new URL(url);
@@ -192,7 +180,7 @@ export const loadAsStream = function (url, headers, stream, callback, allowRemot
192
180
  const streamId = bindOutputStream(stream);
193
181
  const parsedURL = new Common.ParsedURL.ParsedURL(url);
194
182
  if (parsedURL.isDataURL()) {
195
- loadXHR(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed);
183
+ fetchToString(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed);
196
184
  return;
197
185
  }
198
186
  if (!allowRemoteFilePaths && canBeRemoteFilePath(url)) {
@@ -195,9 +195,6 @@ export class UserMetrics {
195
195
  swatchActivated(swatch) {
196
196
  InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.SwatchActivated" /* EnumeratedHistogram.SwatchActivated */, swatch, 13 /* SwatchType.MAX_VALUE */);
197
197
  }
198
- animationPlaybackRateChanged(playbackRate) {
199
- InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.AnimationPlaybackRateChanged" /* EnumeratedHistogram.AnimationPlaybackRateChanged */, playbackRate, 4 /* AnimationsPlaybackRate.MAX_VALUE */);
200
- }
201
198
  workspacesPopulated(wallClockTimeInMilliseconds) {
202
199
  InspectorFrontendHostInstance.recordPerformanceHistogram('DevTools.Workspaces.PopulateWallClocktime', wallClockTimeInMilliseconds);
203
200
  }
@@ -822,9 +819,9 @@ export var IssueCreated;
822
819
  IssueCreated[IssueCreated["GenericIssue::FormInputWithNoLabelError"] = 67] = "GenericIssue::FormInputWithNoLabelError";
823
820
  IssueCreated[IssueCreated["GenericIssue::FormAutocompleteAttributeEmptyError"] = 68] = "GenericIssue::FormAutocompleteAttributeEmptyError";
824
821
  IssueCreated[IssueCreated["GenericIssue::FormEmptyIdAndNameAttributesForInputError"] = 69] = "GenericIssue::FormEmptyIdAndNameAttributesForInputError";
825
- IssueCreated[IssueCreated["GenericIssue::FormAriaLabelledByToNonExistingId"] = 70] = "GenericIssue::FormAriaLabelledByToNonExistingId";
822
+ IssueCreated[IssueCreated["GenericIssue::FormAriaLabelledByToNonExistingIdError"] = 70] = "GenericIssue::FormAriaLabelledByToNonExistingIdError";
826
823
  IssueCreated[IssueCreated["GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError"] = 71] = "GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError";
827
- IssueCreated[IssueCreated["GenericIssue::FormLabelHasNeitherForNorNestedInput"] = 72] = "GenericIssue::FormLabelHasNeitherForNorNestedInput";
824
+ IssueCreated[IssueCreated["GenericIssue::FormLabelHasNeitherForNorNestedInputError"] = 72] = "GenericIssue::FormLabelHasNeitherForNorNestedInputError";
828
825
  IssueCreated[IssueCreated["GenericIssue::FormLabelForMatchesNonExistingIdError"] = 73] = "GenericIssue::FormLabelForMatchesNonExistingIdError";
829
826
  IssueCreated[IssueCreated["GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError"] = 74] = "GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError";
830
827
  IssueCreated[IssueCreated["GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError"] = 75] = "GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError";
@@ -3,7 +3,7 @@
3
3
  // Use of this source code is governed by a BSD-style license that can be
4
4
  // found in the LICENSE file.
5
5
  const glob = require('glob');
6
- const path = require('path');
6
+ const path = require('node:path');
7
7
  const yargs = require('yargs');
8
8
  const { hideBin } = require('yargs/helpers');
9
9
  const { writeIfChanged } = require('../../../scripts/build/ninja/write-if-changed.js');
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 The Chromium Authors
3
3
  // Use of this source code is governed by a BSD-style license that can be
4
4
  // found in the LICENSE file.
5
- const path = require('path');
5
+ const path = require('node:path');
6
6
  const yargs = require('yargs');
7
7
  const { hideBin } = require('yargs/helpers');
8
8
  const { writeIfChanged } = require('../../../scripts/build/ninja/write-if-changed.js');
@@ -0,0 +1,19 @@
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
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5
+ // @ts-ignore 'process' is not available when type-checking against browser types.
6
+ export const IS_NODE = typeof process !== 'undefined' && process.versions?.node !== null;
7
+ export const IS_BROWSER =
8
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
+ // @ts-ignore 'window' is not available when type-checking against node.js types.
10
+ typeof window !== 'undefined' || (typeof self !== 'undefined' && typeof self.postMessage === 'function');
11
+ export const HOST_RUNTIME = await (async () => {
12
+ if (IS_NODE) {
13
+ return (await import('./node/node.js')).HostRuntime.HOST_RUNTIME;
14
+ }
15
+ if (IS_BROWSER) {
16
+ return (await import('./browser/browser.js')).HostRuntime.HOST_RUNTIME;
17
+ }
18
+ throw new Error('Unknown runtime!');
19
+ })();
@@ -534,5 +534,5 @@ export const concatBase64 = function (lhs, rhs) {
534
534
  }
535
535
  const lhsLeaveAsIs = lhs.substring(0, lhs.length - 4);
536
536
  const lhsToDecode = lhs.substring(lhs.length - 4);
537
- return lhsLeaveAsIs + window.btoa(window.atob(lhsToDecode) + window.atob(rhs));
537
+ return lhsLeaveAsIs + globalThis.btoa(globalThis.atob(lhsToDecode) + globalThis.atob(rhs));
538
538
  };
@@ -0,0 +1,4 @@
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
+ export {};
@@ -0,0 +1,5 @@
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
+ import * as HostRuntime from './HostRuntime.js';
5
+ export { HostRuntime };
@@ -1,16 +1,24 @@
1
- // Copyright 2014 The Chromium Authors
1
+ // Copyright 2025 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
- export class WorkerWrapper {
4
+ class WebWorkerScope {
5
+ postMessage(message) {
6
+ self.postMessage(message);
7
+ }
8
+ set onmessage(listener) {
9
+ self.onmessage = listener;
10
+ }
11
+ }
12
+ class WebWorker {
5
13
  #workerPromise;
6
14
  #disposed;
7
15
  #rejectWorkerPromise;
8
16
  constructor(workerLocation) {
9
17
  this.#workerPromise = new Promise((fulfill, reject) => {
10
18
  this.#rejectWorkerPromise = reject;
11
- const worker = new Worker(workerLocation, { type: 'module' });
19
+ const worker = new Worker(new URL(workerLocation), { type: 'module' });
12
20
  worker.onerror = event => {
13
- console.error(`Failed to load worker for ${workerLocation.href}:`, event);
21
+ console.error(`Failed to load worker for ${workerLocation}:`, event);
14
22
  };
15
23
  worker.onmessage = (event) => {
16
24
  console.assert(event.data === 'workerReady');
@@ -19,9 +27,6 @@ export class WorkerWrapper {
19
27
  };
20
28
  });
21
29
  }
22
- static fromURL(url) {
23
- return new WorkerWrapper(url);
24
- }
25
30
  postMessage(message, transfer) {
26
31
  void this.#workerPromise.then(worker => {
27
32
  if (!this.#disposed) {
@@ -50,3 +55,9 @@ export class WorkerWrapper {
50
55
  });
51
56
  }
52
57
  }
58
+ export const HOST_RUNTIME = {
59
+ createWorker(url) {
60
+ return new WebWorker(url);
61
+ },
62
+ workerScope: new WebWorkerScope(),
63
+ };
@@ -0,0 +1,5 @@
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
+ import * as HostRuntime from './HostRuntime.js';
5
+ export { HostRuntime };