blob: 1a01f3594b7ae105bbd95f3fb9b341a3c1b9ba55 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Philip Pfaffe7523faf2021-06-28 14:23:1431import type * as PublicAPI from '../../../extension-api/ExtensionAPI'; // eslint-disable-line rulesdir/es_modules_import
Andrés Olivaresd8507932023-12-27 08:59:2832import type * as Platform from '../../core/platform/platform.js';
Philip Pfaffe4b88c662021-06-25 12:30:4733import type * as HAR from '../har/har.js';
Philip Pfaffe7523faf2021-06-28 14:23:1434
Philip Pfaffeddf60d22021-06-25 12:35:4135/* eslint-disable @typescript-eslint/naming-convention,@typescript-eslint/no-non-null-assertion */
Philip Pfaffe939605d2021-06-25 12:20:0436export namespace PrivateAPI {
37 export namespace Panels {
38 export const enum SearchAction {
39 CancelSearch = 'cancelSearch',
40 PerformSearch = 'performSearch',
41 NextSearchResult = 'nextSearchResult',
42 PreviousSearchResult = 'previousSearchResult',
43 }
Tim van der Lippe1d6e57a2019-09-30 11:55:3444 }
Blink Reformat4c46d092018-04-07 15:32:3745
Philip Pfaffe939605d2021-06-25 12:20:0446 export const enum Events {
47 ButtonClicked = 'button-clicked-',
48 PanelObjectSelected = 'panel-objectSelected-',
49 InspectedURLChanged = 'inspected-url-changed',
50 NetworkRequestFinished = 'network-request-finished',
51 OpenResource = 'open-resource',
52 PanelSearch = 'panel-search-',
Philip Pfaffe939605d2021-06-25 12:20:0453 ResourceAdded = 'resource-added',
54 ResourceContentCommitted = 'resource-content-committed',
55 ViewShown = 'view-shown-',
56 ViewHidden = 'view-hidden,',
Paul Lewisada689f2022-01-11 12:03:4057 ThemeChange = 'host-theme-change',
Philip Pfaffe939605d2021-06-25 12:20:0458 }
Blink Reformat4c46d092018-04-07 15:32:3759
Philip Pfaffe939605d2021-06-25 12:20:0460 export const enum Commands {
61 AddRequestHeaders = 'addRequestHeaders',
Philip Pfaffe939605d2021-06-25 12:20:0462 ApplyStyleSheet = 'applyStyleSheet',
Philip Pfaffe939605d2021-06-25 12:20:0463 CreatePanel = 'createPanel',
64 CreateSidebarPane = 'createSidebarPane',
65 CreateToolbarButton = 'createToolbarButton',
66 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
67 ForwardKeyboardEvent = '_forwardKeyboardEvent',
68 GetHAR = 'getHAR',
69 GetPageResources = 'getPageResources',
70 GetRequestContent = 'getRequestContent',
71 GetResourceContent = 'getResourceContent',
72 OpenResource = 'openResource',
73 Reload = 'Reload',
74 Subscribe = 'subscribe',
75 SetOpenResourceHandler = 'setOpenResourceHandler',
Paul Lewisada689f2022-01-11 12:03:4076 SetThemeChangeHandler = 'setThemeChangeHandler',
Philip Pfaffe939605d2021-06-25 12:20:0477 SetResourceContent = 'setResourceContent',
78 SetSidebarContent = 'setSidebarContent',
79 SetSidebarHeight = 'setSidebarHeight',
80 SetSidebarPage = 'setSidebarPage',
81 ShowPanel = 'showPanel',
82 Unsubscribe = 'unsubscribe',
83 UpdateButton = 'updateButton',
84 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
Philip Pfaffe6ed01262022-07-06 10:41:3985 GetWasmLinearMemory = 'getWasmLinearMemory',
86 GetWasmLocal = 'getWasmLocal',
87 GetWasmGlobal = 'getWasmGlobal',
88 GetWasmOp = 'getWasmOp',
Alex Rudenkoa3850822022-05-24 07:34:2289 RegisterRecorderExtensionPlugin = 'registerRecorderExtensionPlugin',
Alex Rudenko0b8b8882023-01-17 12:21:4990 CreateRecorderView = 'createRecorderView',
91 ShowRecorderView = 'showRecorderView',
Philip Pfaffe939605d2021-06-25 12:20:0492 }
Philip Pfaffeedad8322020-07-20 10:24:2593
Philip Pfaffe939605d2021-06-25 12:20:0494 export const enum LanguageExtensionPluginCommands {
95 AddRawModule = 'addRawModule',
96 RemoveRawModule = 'removeRawModule',
97 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
98 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
99 GetScopeInfo = 'getScopeInfo',
100 ListVariablesInScope = 'listVariablesInScope',
101 GetTypeInfo = 'getTypeInfo',
102 GetFormatter = 'getFormatter',
103 GetInspectableAddress = 'getInspectableAddress',
104 GetFunctionInfo = 'getFunctionInfo',
105 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
106 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
107 GetMappedLines = 'getMappedLines',
Philip Pfaffe6ed01262022-07-06 10:41:39108 FormatValue = 'formatValue',
109 GetProperties = 'getProperties',
110 ReleaseObject = 'releaseObject',
Philip Pfaffe939605d2021-06-25 12:20:04111 }
Benedikt Meurer929fc7c2020-11-20 14:21:06112
Philip Pfaffe939605d2021-06-25 12:20:04113 export const enum LanguageExtensionPluginEvents {
114 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
115 }
Philip Pfaffed662bdf2021-06-25 13:30:32116
Alex Rudenkoa3850822022-05-24 07:34:22117 export const enum RecorderExtensionPluginCommands {
118 Stringify = 'stringify',
Alex Rudenko2aa04c02022-06-01 13:05:20119 StringifyStep = 'stringifyStep',
Alex Rudenko0b8b8882023-01-17 12:21:49120 Replay = 'replay',
Alex Rudenkoa3850822022-05-24 07:34:22121 }
122
123 export const enum RecorderExtensionPluginEvents {
124 UnregisteredRecorderExtensionPlugin = 'unregisteredRecorderExtensionPlugin',
125 }
126
Philip Pfaffed662bdf2021-06-25 13:30:32127 export interface EvaluateOptions {
128 frameURL?: string;
129 useContentScriptContext?: boolean;
130 scriptExecutionContext?: string;
131 }
132
Philip Pfaffed662bdf2021-06-25 13:30:32133 type RegisterLanguageExtensionPluginRequest = {
134 command: Commands.RegisterLanguageExtensionPlugin,
135 pluginName: string,
136 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14137 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32138 };
Alex Rudenko0b8b8882023-01-17 12:21:49139 export type RecordingExtensionPluginCapability = 'export'|'replay';
Alex Rudenkoa3850822022-05-24 07:34:22140 type RegisterRecorderExtensionPluginRequest = {
141 command: Commands.RegisterRecorderExtensionPlugin,
142 pluginName: string,
Alex Rudenko0b8b8882023-01-17 12:21:49143 mediaType?: string, capabilities: RecordingExtensionPluginCapability[], port: MessagePort,
144 };
145 type CreateRecorderViewRequest = {
146 command: Commands.CreateRecorderView,
147 id: string,
148 title: string,
149 pagePath: string,
150 };
151 type ShowRecorderViewRequest = {
152 command: Commands.ShowRecorderView,
153 id: string,
Alex Rudenkoa3850822022-05-24 07:34:22154 };
Philip Pfaffed662bdf2021-06-25 13:30:32155 type SubscribeRequest = {command: Commands.Subscribe, type: string};
156 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
157 type AddRequestHeadersRequest = {
158 command: Commands.AddRequestHeaders,
159 extensionId: string,
160 headers: {[key: string]: string},
161 };
162 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
163 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
164 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
165 type CreateToolbarButtonRequest = {
166 command: Commands.CreateToolbarButton,
167 id: string,
168 icon: string,
169 panel: string,
170 tooltip?: string,
171 disabled?: boolean,
172 };
173 type UpdateButtonRequest =
174 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32175 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
176 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
177 type SetSidebarContentRequest = {
178 command: Commands.SetSidebarContent,
179 id: string,
180 evaluateOnPage?: boolean, expression: string,
181 rootTitle?: string,
182 evaluateOptions?: EvaluateOptions,
183 };
184 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Kateryna Prokopenko9964ab12022-03-23 16:41:49185 type OpenResourceRequest =
186 {command: Commands.OpenResource, url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32187 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
Paul Lewisada689f2022-01-11 12:03:40188 type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32189 type ReloadRequest = {
190 command: Commands.Reload,
191 options: null|{
192 userAgent?: string,
193 injectedScript?: string,
194 ignoreCache?: boolean,
195 },
196 };
197 type EvaluateOnInspectedPageRequest = {
198 command: Commands.EvaluateOnInspectedPage,
199 expression: string,
200 evaluateOptions?: EvaluateOptions,
201 };
202 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
203 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
204 type SetResourceContentRequest =
205 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32206 type ForwardKeyboardEventRequest = {
207 command: Commands.ForwardKeyboardEvent,
208 entries: Array<KeyboardEventInit&{eventType: string}>,
209 };
210 type GetHARRequest = {command: Commands.GetHAR};
Danil Somsikov56210832022-10-05 13:17:58211 type GetPageResourcesRequest = {command: Commands.GetPageResources};
Philip Pfaffe6ed01262022-07-06 10:41:39212 type GetWasmLinearMemoryRequest = {
213 command: Commands.GetWasmLinearMemory,
214 offset: number,
215 length: number,
216 stopId: unknown,
217 };
218 type GetWasmLocalRequest = {
219 command: Commands.GetWasmLocal,
220 local: number,
221 stopId: unknown,
222 };
223 type GetWasmGlobalRequest = {
224 command: Commands.GetWasmGlobal,
225 global: number,
226 stopId: unknown,
227 };
228 type GetWasmOpRequest = {command: Commands.GetWasmOp, op: number, stopId: unknown};
Philip Pfaffed662bdf2021-06-25 13:30:32229
Alex Rudenko0b8b8882023-01-17 12:21:49230 export type ServerRequests = ShowRecorderViewRequest|CreateRecorderViewRequest|RegisterRecorderExtensionPluginRequest|
231 RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|AddRequestHeadersRequest|
232 ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|UpdateButtonRequest|
Andrés Olivaresd8507932023-12-27 08:59:28233 CreateSidebarPaneRequest|SetSidebarHeightRequest|SetSidebarContentRequest|SetSidebarPageRequest|
234 OpenResourceRequest|SetOpenResourceHandlerRequest|SetThemeChangeHandlerRequest|ReloadRequest|
235 EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
236 ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest|GetWasmLinearMemoryRequest|GetWasmLocalRequest|
237 GetWasmGlobalRequest|GetWasmOpRequest;
Philip Pfaffed662bdf2021-06-25 13:30:32238 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32239
240 type AddRawModuleRequest = {
241 method: LanguageExtensionPluginCommands.AddRawModule,
242 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
243 };
244 type SourceLocationToRawLocationRequest = {
245 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
246 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
247 };
248 type RawLocationToSourceLocationRequest = {
249 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
250 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
251 };
252 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
253 type ListVariablesInScopeRequest = {
254 method: LanguageExtensionPluginCommands.ListVariablesInScope,
255 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
256 };
257 type RemoveRawModuleRequest = {
258 method: LanguageExtensionPluginCommands.RemoveRawModule,
259 parameters: {rawModuleId: string},
260 };
Philip Pfaffec5d160e2021-07-20 10:53:32261 type GetFunctionInfoRequest = {
262 method: LanguageExtensionPluginCommands.GetFunctionInfo,
263 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
264 };
265 type GetInlinedFunctionRangesRequest = {
266 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
267 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
268 };
269 type GetInlinedCalleesRangesRequest = {
270 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
271 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
272 };
273 type GetMappedLinesRequest = {
274 method: LanguageExtensionPluginCommands.GetMappedLines,
275 parameters: {rawModuleId: string, sourceFileURL: string},
276 };
Philip Pfaffe6ed01262022-07-06 10:41:39277 type FormatValueRequest = {
278 method: LanguageExtensionPluginCommands.FormatValue,
279 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation, stopId: number},
280 };
281 type GetPropertiesRequest = {
282 method: LanguageExtensionPluginCommands.GetProperties,
283 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
284 };
285 type ReleaseObjectRequest = {
286 method: LanguageExtensionPluginCommands.ReleaseObject,
287 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
288 };
Philip Pfaffec5d160e2021-07-20 10:53:32289
Philip Pfaffe6ed01262022-07-06 10:41:39290 export type LanguageExtensionRequests =
291 AddRawModuleRequest|SourceLocationToRawLocationRequest|RawLocationToSourceLocationRequest|GetScopeInfoRequest|
Philip Pfaffe8a3d59b2023-05-04 11:26:00292 ListVariablesInScopeRequest|RemoveRawModuleRequest|GetFunctionInfoRequest|GetInlinedFunctionRangesRequest|
Philip Pfaffe6ed01262022-07-06 10:41:39293 GetInlinedCalleesRangesRequest|GetMappedLinesRequest|FormatValueRequest|GetPropertiesRequest|ReleaseObjectRequest;
Alex Rudenkoa3850822022-05-24 07:34:22294
295 type StringifyRequest = {
296 method: RecorderExtensionPluginCommands.Stringify,
297 parameters: {recording: Record<string, unknown>},
298 };
299
Alex Rudenko2aa04c02022-06-01 13:05:20300 type StringifyStepRequest = {
301 method: RecorderExtensionPluginCommands.StringifyStep,
302 parameters: {step: Record<string, unknown>},
303 };
304
Alex Rudenko0b8b8882023-01-17 12:21:49305 type ReplayRequest = {
306 method: RecorderExtensionPluginCommands.Replay,
307 parameters: {recording: Record<string, unknown>},
308 };
309
310 export type RecorderExtensionRequests = StringifyRequest|StringifyStepRequest|ReplayRequest;
Blink Reformat4c46d092018-04-07 15:32:37311}
312
Philip Pfaffe939605d2021-06-25 12:20:04313declare global {
314 interface Window {
315 injectedExtensionAPI:
316 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14317 testHook:
318 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22319 injectedScriptId: number, targetWindow?: Window) => void;
Philip Pfaffe939605d2021-06-25 12:20:04320 buildExtensionAPIInjectedScript(
321 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32322 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14323 chrome: PublicAPI.Chrome.DevTools.Chrome;
324 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04325 }
326}
327
328export type ExtensionDescriptor = {
329 startPage: string,
330 name: string,
331 exposeExperimentalAPIs: boolean,
332 exposeWebInspectorNamespace?: boolean,
Danil Somsikov28cfaf32022-09-27 15:36:55333 allowFileAccess?: boolean,
Philip Pfaffe939605d2021-06-25 12:20:04334};
335
Philip Pfaffe7523faf2021-06-28 14:23:14336namespace APIImpl {
337 export interface InspectorExtensionAPI {
338 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Alex Rudenkoa3850822022-05-24 07:34:22339 recorder: PublicAPI.Chrome.DevTools.RecorderExtensions;
Philip Pfaffe7523faf2021-06-28 14:23:14340 network: PublicAPI.Chrome.DevTools.Network;
341 panels: PublicAPI.Chrome.DevTools.Panels;
342 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
343 }
344
345 export interface ExtensionServerClient {
346 _callbacks: {[key: string]: (response: unknown) => unknown};
347 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
348 _lastRequestId: number;
349 _lastObjectId: number;
350 _port: MessagePort;
351
352 _onCallback(request: unknown): void;
353 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
354 _registerCallback(callback: (response: unknown) => unknown): number;
355 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
356 unregisterHandler(command: string): void;
357 hasHandler(command: string): boolean;
Philip Pfaffe6ed01262022-07-06 10:41:39358 sendRequest<ResponseT>(
359 request: PrivateAPI.ServerRequests, callback?: ((response: ResponseT) => unknown), transfers?: unknown[]): void;
Philip Pfaffe7523faf2021-06-28 14:23:14360 nextObjectId(): string;
361 }
362
363 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
364 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
365 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28366 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14367 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28368 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14369
370 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
371 _type: string;
372 _listeners: ListenerT[];
373 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
374
375 _fire(..._vararg: Parameters<ListenerT>): void;
376 _dispatch(request: {arguments: unknown[]}): void;
377 }
Philip Pfaffe4b88c662021-06-25 12:30:47378
379 export interface Network extends PublicAPI.Chrome.DevTools.Network {
380 addRequestHeaders(headers: {[key: string]: string}): void;
381 }
382
383 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
384 _id: number;
385 }
Philip Pfaffe6fd04c42021-06-25 12:31:48386
387 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
388 get SearchAction(): {[key: string]: string};
389 applyStyleSheet(styleSheet: string): void;
390 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
391 void;
Paul Lewisada689f2022-01-11 12:03:40392 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48393 }
394
395 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
396 _id: string|null;
397 }
398
399 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
400 setExpression(
401 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
402 callback?: () => unknown): void;
403 }
404
405 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
406 _hostPanelName: string;
407 }
408
409 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
410 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
411 }
412
Alex Rudenkoa3850822022-05-24 07:34:22413 export interface RecorderExtensions extends PublicAPI.Chrome.DevTools.RecorderExtensions {
414 _plugins: Map<PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, MessagePort>;
415 }
416
Philip Pfaffe6fd04c42021-06-25 12:31:48417 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
418 show(): void;
419 }
420
Alex Rudenko0b8b8882023-01-17 12:21:49421 export interface RecorderView extends ExtensionView, PublicAPI.Chrome.DevTools.RecorderView {}
422
Philip Pfaffe6fd04c42021-06-25 12:31:48423 export interface Button extends PublicAPI.Chrome.DevTools.Button {
424 _id: string;
425 }
426
Philip Pfaffe6fd04c42021-06-25 12:31:48427 export type ResourceData = {url: string, type: string};
428 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
429 _type: string;
430 _url: string;
431
432 get type(): string;
433 }
Philip Pfaffe7523faf2021-06-28 14:23:14434}
Philip Pfaffe939605d2021-06-25 12:20:04435
Tim van der Lippe226fc222019-10-10 12:17:12436self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14437 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
438 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22439 injectedScriptId: number, targetWindowForTest?: Window): void {
Jan Schefflerd76b4162021-03-29 07:52:16440 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37441 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16442
Blink Reformat4c46d092018-04-07 15:32:37443 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34444 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37445 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34446 }
Blink Reformat4c46d092018-04-07 15:32:37447 let userAction = false;
Alex Rudenko0b8b8882023-01-17 12:21:49448 let userRecorderAction = false;
Blink Reformat4c46d092018-04-07 15:32:37449
450 // Here and below, all constructors are private to API implementation.
451 // For a public type Foo, if internal fields are present, these are on
452 // a private FooImpl type, an instance of FooImpl is used in a closure
453 // by Foo consutrctor to re-bind publicly exported members to an instance
454 // of Foo.
455
Philip Pfaffe7523faf2021-06-28 14:23:14456 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
457 this: APIImpl.EventSink<ListenerT>, type: string,
458 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37459 this._type = type;
460 this._listeners = [];
461 this._customDispatch = customDispatch;
462 }
463
464 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14465 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
466 void {
467 if (typeof callback !== 'function') {
468 throw 'addListener: callback is not a function';
469 }
470 if (this._listeners.length === 0) {
471 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
472 }
473 this._listeners.push(callback);
474 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
475 },
Blink Reformat4c46d092018-04-07 15:32:37476
Philip Pfaffe7523faf2021-06-28 14:23:14477 removeListener: function<ListenerT extends APIImpl.Callable>(
478 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37479 const listeners = this._listeners;
480
481 for (let i = 0; i < listeners.length; ++i) {
482 if (listeners[i] === callback) {
483 listeners.splice(i, 1);
484 break;
485 }
486 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34487 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04488 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34489 }
Blink Reformat4c46d092018-04-07 15:32:37490 },
491
Philip Pfaffe7523faf2021-06-28 14:23:14492 _fire: function<ListenerT extends APIImpl.Callable>(
493 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37494 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34495 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14496 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34497 }
Blink Reformat4c46d092018-04-07 15:32:37498 },
499
Philip Pfaffe7523faf2021-06-28 14:23:14500 _dispatch: function<ListenerT extends APIImpl.Callable>(
501 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34502 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37503 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34504 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14505 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34506 }
Jan Schefflerd76b4162021-03-29 07:52:16507 },
Blink Reformat4c46d092018-04-07 15:32:37508 };
509
Philip Pfaffe7523faf2021-06-28 14:23:14510 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
511 ThisParameterType<NewT> {
512 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
513 }
514
Philip Pfaffe7523faf2021-06-28 14:23:14515 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41516 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48517 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47518 this.network = new (Constructor(Network))();
Philip Pfaffec5d160e2021-07-20 10:53:32519 this.languageServices = new (Constructor(LanguageServicesAPI))();
Alex Rudenkoa3850822022-05-24 07:34:22520 this.recorder = new (Constructor(RecorderServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37521 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
522 }
523
Philip Pfaffe4b88c662021-06-25 12:30:47524 function Network(this: APIImpl.Network): void {
525 function dispatchRequestEvent(
526 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
527 message: {arguments: unknown[]}): void {
528 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
529
530 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37531 this._fire(request);
532 }
Philip Pfaffe4b88c662021-06-25 12:30:47533
534 this.onRequestFinished =
535 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37536 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47537
538 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37539 }
540
Philip Pfaffe4b88c662021-06-25 12:30:47541 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
542 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
543 function callbackWrapper(response: unknown): void {
544 const result =
545 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37546 const entries = (result && result.entries) || [];
547 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47548 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37549 delete entries[i]._requestId;
550 }
Philip Pfaffe4b88c662021-06-25 12:30:47551 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37552 }
Philip Pfaffe939605d2021-06-25 12:20:04553 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37554 },
555
Philip Pfaffe4b88c662021-06-25 12:30:47556 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37557 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04558 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16559 },
Blink Reformat4c46d092018-04-07 15:32:37560 };
561
Philip Pfaffe4b88c662021-06-25 12:30:47562 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37563 this._id = id;
564 }
565
Philip Pfaffe4b88c662021-06-25 12:30:47566 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
567 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
568 function callbackWrapper(response: unknown): void {
569 const {content, encoding} = response as {content: string, encoding: string};
570 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37571 }
Philip Pfaffe939605d2021-06-25 12:20:04572 extensionServer.sendRequest(
573 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16574 },
Blink Reformat4c46d092018-04-07 15:32:37575 };
576
Philip Pfaffe6fd04c42021-06-25 12:31:48577 function Panels(this: APIImpl.Panels): void {
578 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37579 elements: new ElementsPanel(),
580 sources: new SourcesPanel(),
581 };
582
Philip Pfaffe6fd04c42021-06-25 12:31:48583 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37584 return panels[name];
585 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34586 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12587 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34588 }
Philip Pfaffe6fd04c42021-06-25 12:31:48589 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04590 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37591 };
592 }
593
Paul Lewisada689f2022-01-11 12:03:40594 (Panels.prototype as
595 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48596 create: function(
597 title: string, icon: string, page: string,
598 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37599 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48600 extensionServer.sendRequest(
601 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37602 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37603 },
604
Philip Pfaffe6fd04c42021-06-25 12:31:48605 setOpenResourceHandler: function(
606 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04607 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37608
Philip Pfaffe6fd04c42021-06-25 12:31:48609 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37610 // Allow the panel to show itself when handling the event.
611 userAction = true;
612 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48613 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
Danil Somsikov56210832022-10-05 13:17:58614 if (canAccessResource(resource)) {
615 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
616 }
Blink Reformat4c46d092018-04-07 15:32:37617 } finally {
618 userAction = false;
619 }
620 }
621
Tim van der Lippe1d6e57a2019-09-30 11:55:34622 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04623 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34624 } else {
Philip Pfaffe939605d2021-06-25 12:20:04625 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34626 }
Blink Reformat4c46d092018-04-07 15:32:37627
628 // Only send command if we either removed an existing handler or added handler and had none before.
Tim van der Lippe1d6e57a2019-09-30 11:55:34629 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04630 extensionServer.sendRequest(
631 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34632 }
Blink Reformat4c46d092018-04-07 15:32:37633 },
634
Paul Lewisada689f2022-01-11 12:03:40635 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
636 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
637
638 function callbackWrapper(message: unknown): void {
639 const {themeName} = message as {themeName: string};
640 chrome.devtools.panels.themeName = themeName;
641 callback.call(null, themeName);
642 }
643
644 if (!callback) {
645 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
646 } else {
647 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
648 }
649
650 // Only send command if we either removed an existing handler or added handler and had none before.
651 if (hadHandler === !callback) {
652 extensionServer.sendRequest(
653 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
654 }
655 },
656
Philip Pfaffe140e5432021-09-13 16:34:23657 openResource: function(
Kateryna Prokopenko9964ab12022-03-23 16:41:49658 url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber?: number,
659 _callback?: (response: unknown) => unknown): void {
Philip Pfaffe140e5432021-09-13 16:34:23660 const callbackArg = extractCallbackArgument(arguments);
661 // Handle older API:
662 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
663 extensionServer.sendRequest(
664 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37665 },
666
Philip Pfaffe6fd04c42021-06-25 12:31:48667 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04668 return {
669 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
670 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
671 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
672 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
673 };
Jan Schefflerd76b4162021-03-29 07:52:16674 },
Blink Reformat4c46d092018-04-07 15:32:37675 };
676
Philip Pfaffe6fd04c42021-06-25 12:31:48677 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37678 this._id = id;
679
Philip Pfaffe6fd04c42021-06-25 12:31:48680 function dispatchShowEvent(
681 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37682 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34683 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37684 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34685 } else {
Blink Reformat4c46d092018-04-07 15:32:37686 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34687 }
Blink Reformat4c46d092018-04-07 15:32:37688 }
689
690 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48691 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
692
693 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37694 }
695 }
696
Philip Pfaffe6fd04c42021-06-25 12:31:48697 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37698 ExtensionViewImpl.call(this, null);
699 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48700
701 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37702 }
703
Philip Pfaffe6fd04c42021-06-25 12:31:48704 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
705 {__proto__: APIImpl.ExtensionView}) = {
706 createSidebarPane: function(
707 this: APIImpl.PanelWithSidebar, title: string,
708 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37709 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16710 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48711 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37712 }
Philip Pfaffe7523faf2021-06-28 14:23:14713 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48714 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14715 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37716 },
717
Jan Schefflerd76b4162021-03-29 07:52:16718 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37719 };
720
Alex Rudenkoa3850822022-05-24 07:34:22721 function RecorderServicesAPIImpl(this: APIImpl.RecorderExtensions): void {
722 this._plugins = new Map();
723 }
724
Alex Rudenko0b8b8882023-01-17 12:21:49725 async function registerRecorderExtensionPluginImpl(
726 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, pluginName: string,
727 mediaType?: string): Promise<void> {
728 if (this._plugins.has(plugin)) {
729 throw new Error(`Tried to register plugin '${pluginName}' twice`);
730 }
731 const channel = new MessageChannel();
732 const port = channel.port1;
733 this._plugins.set(plugin, port);
734 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.RecorderExtensionRequests>): void => {
735 const {requestId} = data;
736 dispatchMethodCall(data)
737 .then(result => port.postMessage({requestId, result}))
738 .catch(error => port.postMessage({requestId, error: {message: error.message}}));
739 };
740
741 async function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
742 switch (request.method) {
743 case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
744 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionExportPlugin)
745 .stringify(request.parameters.recording);
746 case PrivateAPI.RecorderExtensionPluginCommands.StringifyStep:
747 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionExportPlugin)
748 .stringifyStep(request.parameters.step);
749 case PrivateAPI.RecorderExtensionPluginCommands.Replay:
750 try {
751 userAction = true;
752 userRecorderAction = true;
753 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionReplayPlugin)
754 .replay(request.parameters.recording);
755 } finally {
756 userAction = false;
757 userRecorderAction = false;
758 }
759 default:
760 // @ts-expect-error
761 throw new Error(`'${request.method}' is not recognized`);
Alex Rudenkoa3850822022-05-24 07:34:22762 }
Alex Rudenko0b8b8882023-01-17 12:21:49763 }
Alex Rudenkoa3850822022-05-24 07:34:22764
Alex Rudenko0b8b8882023-01-17 12:21:49765 const capabilities: PrivateAPI.RecordingExtensionPluginCapability[] = [];
Alex Rudenkoa3850822022-05-24 07:34:22766
Alex Rudenko0b8b8882023-01-17 12:21:49767 if ('stringify' in plugin && 'stringifyStep' in plugin) {
768 capabilities.push('export');
769 }
Alex Rudenkoa3850822022-05-24 07:34:22770
Alex Rudenko0b8b8882023-01-17 12:21:49771 if ('replay' in plugin) {
772 capabilities.push('replay');
773 }
774
775 await new Promise<void>(resolve => {
776 extensionServer.sendRequest(
777 {
778 command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
779 pluginName,
780 mediaType,
781 capabilities,
782 port: channel.port2,
783 },
784 () => resolve(), [channel.port2]);
785 });
786 }
787
788 (RecorderServicesAPIImpl.prototype as Pick<
789 APIImpl.RecorderExtensions,
790 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'|'createView'>) = {
791 registerRecorderExtensionPlugin: registerRecorderExtensionPluginImpl,
Alex Rudenkoa3850822022-05-24 07:34:22792 unregisterRecorderExtensionPlugin: async function(
793 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin): Promise<void> {
794 const port = this._plugins.get(plugin);
795 if (!port) {
796 throw new Error('Tried to unregister a plugin that was not previously registered');
797 }
798 this._plugins.delete(plugin);
799 port.postMessage({event: PrivateAPI.RecorderExtensionPluginEvents.UnregisteredRecorderExtensionPlugin});
800 port.close();
801 },
Alex Rudenko0b8b8882023-01-17 12:21:49802 createView: async function(this: APIImpl.RecorderExtensions, title: string, pagePath: string):
803 Promise<PublicAPI.Chrome.DevTools.RecorderView> {
804 const id = 'recorder-extension-view-' + extensionServer.nextObjectId();
805 await new Promise(resolve => {
806 extensionServer.sendRequest(
807 {command: PrivateAPI.Commands.CreateRecorderView, id, title, pagePath}, resolve);
808 });
809 return new (Constructor(RecorderView))(id);
810 },
Alex Rudenkoa3850822022-05-24 07:34:22811 };
812
Philip Pfaffec5d160e2021-07-20 10:53:32813 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25814 this._plugins = new Map();
815 }
816
Philip Pfaffe6ed01262022-07-06 10:41:39817 (LanguageServicesAPIImpl.prototype as PublicAPI.Chrome.DevTools.LanguageExtensions) = {
Philip Pfaffed662bdf2021-06-25 13:30:32818 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32819 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
820 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
821 if (this._plugins.has(plugin)) {
822 throw new Error(`Tried to register plugin '${pluginName}' twice`);
823 }
824 const channel = new MessageChannel();
825 const port = channel.port1;
826 this._plugins.set(plugin, port);
827 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
828 const {requestId} = data;
829 console.time(`${requestId}: ${data.method}`);
830 dispatchMethodCall(data)
831 .then(result => port.postMessage({requestId, result}))
832 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
833 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
834 };
Philip Pfaffeedad8322020-07-20 10:24:25835
Philip Pfaffec5d160e2021-07-20 10:53:32836 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
837 switch (request.method) {
838 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
839 return plugin.addRawModule(
840 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
841 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
842 return plugin.removeRawModule(request.parameters.rawModuleId);
843 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
844 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
845 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
846 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
847 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
848 return plugin.getScopeInfo(request.parameters.type);
849 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
850 return plugin.listVariablesInScope(request.parameters.rawLocation);
Philip Pfaffec5d160e2021-07-20 10:53:32851 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
852 return plugin.getFunctionInfo(request.parameters.rawLocation);
853 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
854 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
855 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
856 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
857 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
858 if ('getMappedLines' in plugin) {
859 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
860 }
861 return Promise.resolve(undefined);
Philip Pfaffe6ed01262022-07-06 10:41:39862 case PrivateAPI.LanguageExtensionPluginCommands.FormatValue:
Philip Pfaffe889342a2022-07-08 06:18:47863 if ('evaluate' in plugin && plugin.evaluate) {
Philip Pfaffe6ed01262022-07-06 10:41:39864 return plugin.evaluate(
865 request.parameters.expression, request.parameters.context, request.parameters.stopId);
866 }
867 return Promise.resolve(undefined);
868 case PrivateAPI.LanguageExtensionPluginCommands.GetProperties:
Philip Pfaffe889342a2022-07-08 06:18:47869 if ('getProperties' in plugin && plugin.getProperties) {
Philip Pfaffe6ed01262022-07-06 10:41:39870 return plugin.getProperties(request.parameters.objectId);
871 }
Philip Pfaffe889342a2022-07-08 06:18:47872 if (!('evaluate' in plugin &&
873 plugin.evaluate)) { // If evalute is defined but the remote objects methods aren't, that's a bug
Philip Pfaffe6ed01262022-07-06 10:41:39874 return Promise.resolve(undefined);
875 }
876 break;
877 case PrivateAPI.LanguageExtensionPluginCommands.ReleaseObject:
Philip Pfaffe889342a2022-07-08 06:18:47878 if ('releaseObject' in plugin && plugin.releaseObject) {
Philip Pfaffe6ed01262022-07-06 10:41:39879 return plugin.releaseObject(request.parameters.objectId);
880 }
Philip Pfaffe6ed01262022-07-06 10:41:39881 break;
Philip Pfaffec5d160e2021-07-20 10:53:32882 }
Philip Pfaffec5d160e2021-07-20 10:53:32883 throw new Error(`Unknown language plugin method ${request.method}`);
884 }
Philip Pfaffeedad8322020-07-20 10:24:25885
Philip Pfaffec5d160e2021-07-20 10:53:32886 await new Promise<void>(resolve => {
887 extensionServer.sendRequest(
888 {
889 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
890 pluginName,
891 port: channel.port2,
892 supportedScriptTypes,
893 },
894 () => resolve(), [channel.port2]);
895 });
896 },
Benedikt Meurer929fc7c2020-11-20 14:21:06897
Philip Pfaffec5d160e2021-07-20 10:53:32898 unregisterLanguageExtensionPlugin: async function(
899 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06900 const port = this._plugins.get(plugin);
901 if (!port) {
902 throw new Error('Tried to unregister a plugin that was not previously registered');
903 }
904 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04905 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06906 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16907 },
Philip Pfaffe6ed01262022-07-06 10:41:39908
909 getWasmLinearMemory: async function(
910 this: APIImpl.LanguageExtensions, offset: number, length: number, stopId: number): Promise<ArrayBuffer> {
911 const result = await new Promise(
912 resolve => extensionServer.sendRequest(
913 {command: PrivateAPI.Commands.GetWasmLinearMemory, offset, length, stopId}, resolve));
914 if (Array.isArray(result)) {
915 return new Uint8Array(result).buffer;
916 }
917 return new ArrayBuffer(0);
918 },
919 getWasmLocal: async function(
920 this: APIImpl.LanguageExtensions, local: number, stopId: number): Promise<PublicAPI.Chrome.DevTools.WasmValue> {
921 return new Promise(
922 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmLocal, local, stopId}, resolve));
923 },
924 getWasmGlobal: async function(this: APIImpl.LanguageExtensions, global: number, stopId: number):
925 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
926 return new Promise(
927 resolve =>
928 extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmGlobal, global, stopId}, resolve));
929 },
930 getWasmOp: async function(this: APIImpl.LanguageExtensions, op: number, stopId: number):
931 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
932 return new Promise(
933 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmOp, op, stopId}, resolve));
934 },
Philip Pfaffeedad8322020-07-20 10:24:25935 };
936
Philip Pfaffe7523faf2021-06-28 14:23:14937 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
938 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
939 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37940 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14941 implConstructor.apply(impl, args);
942 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37943 };
944 }
945
Philip Pfaffe7523faf2021-06-28 14:23:14946 // eslint-disable-next-line @typescript-eslint/no-explicit-any
947 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37948 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14949 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37950 if (!warningGiven) {
951 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
952 warningGiven = true;
953 }
954 return object[newName];
955 }
956 object.__defineGetter__(oldName, getter);
957 }
958
Philip Pfaffe7523faf2021-06-28 14:23:14959 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37960 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14961 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37962 }
963
Philip Pfaffeedad8322020-07-20 10:24:25964 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Alex Rudenkoa3850822022-05-24 07:34:22965 const RecorderServicesAPI = declareInterfaceClass(RecorderServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37966 const Button = declareInterfaceClass(ButtonImpl);
967 const EventSink = declareInterfaceClass(EventSinkImpl);
968 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
Alex Rudenko0b8b8882023-01-17 12:21:49969 const RecorderView = declareInterfaceClass(RecorderViewImpl);
Blink Reformat4c46d092018-04-07 15:32:37970 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12971 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37972 const Request = declareInterfaceClass(RequestImpl);
973 const Resource = declareInterfaceClass(ResourceImpl);
Blink Reformat4c46d092018-04-07 15:32:37974
Philip Pfaffe6fd04c42021-06-25 12:31:48975 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12976 constructor() {
977 super('elements');
978 }
Blink Reformat4c46d092018-04-07 15:32:37979 }
980
Philip Pfaffe6fd04c42021-06-25 12:31:48981 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12982 constructor() {
983 super('sources');
984 }
Blink Reformat4c46d092018-04-07 15:32:37985 }
986
Philip Pfaffe6fd04c42021-06-25 12:31:48987 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37988 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48989
990 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37991 }
992
Philip Pfaffe6fd04c42021-06-25 12:31:48993 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
994 {__proto__: APIImpl.ExtensionView}) = {
995 createStatusBarButton: function(
996 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
997 PublicAPI.Chrome.DevTools.Button {
998 const id = 'button-' + extensionServer.nextObjectId();
999 extensionServer.sendRequest({
1000 command: PrivateAPI.Commands.CreateToolbarButton,
1001 panel: this._id as string,
1002 id: id,
1003 icon: iconPath,
1004 tooltip: tooltipText,
1005 disabled: Boolean(disabled),
1006 });
Blink Reformat4c46d092018-04-07 15:32:371007
Philip Pfaffe6fd04c42021-06-25 12:31:481008 return new (Constructor(Button))(id);
1009 },
1010
1011 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:341012 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:371013 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341014 }
Blink Reformat4c46d092018-04-07 15:32:371015
Philip Pfaffe6fd04c42021-06-25 12:31:481016 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:371017 },
1018
Jan Schefflerd76b4162021-03-29 07:52:161019 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371020 };
1021
Alex Rudenko0b8b8882023-01-17 12:21:491022 function RecorderViewImpl(this: APIImpl.RecorderView, id: string): void {
1023 ExtensionViewImpl.call(this, id);
1024 }
1025
1026 (RecorderViewImpl.prototype as Pick<APIImpl.RecorderView, 'show'>& {__proto__: APIImpl.ExtensionView}) = {
1027 show: function(this: APIImpl.RecorderView): void {
1028 if (!userAction || !userRecorderAction) {
1029 return;
1030 }
1031
1032 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowRecorderView, id: this._id as string});
1033 },
1034
1035 __proto__: ExtensionViewImpl.prototype,
1036 };
1037
Philip Pfaffe6fd04c42021-06-25 12:31:481038 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371039 ExtensionViewImpl.call(this, id);
1040 }
1041
Philip Pfaffe6fd04c42021-06-25 12:31:481042 (ExtensionSidebarPaneImpl.prototype as
1043 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
1044 {__proto__: APIImpl.ExtensionView}) = {
1045 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
1046 extensionServer.sendRequest(
1047 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:371048 },
1049
Philip Pfaffe6fd04c42021-06-25 12:31:481050 setExpression: function(
1051 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
1052 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:141053 extensionServer.sendRequest(
1054 {
1055 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:481056 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:141057 expression: expression,
1058 rootTitle: rootTitle,
1059 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:481060 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:141061 },
1062 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:371063 },
1064
Philip Pfaffe6fd04c42021-06-25 12:31:481065 setObject: function(
1066 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371067 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:481068 {
1069 command: PrivateAPI.Commands.SetSidebarContent,
1070 id: this._id as string,
1071 expression: jsonObject,
1072 rootTitle: rootTitle,
1073 },
Philip Pfaffe939605d2021-06-25 12:20:041074 callback);
Blink Reformat4c46d092018-04-07 15:32:371075 },
1076
Philip Pfaffe6fd04c42021-06-25 12:31:481077 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
1078 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:371079 },
1080
Jan Schefflerd76b4162021-03-29 07:52:161081 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371082 };
1083
Philip Pfaffe6fd04c42021-06-25 12:31:481084 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371085 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:481086
1087 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:371088 }
1089
Philip Pfaffe6fd04c42021-06-25 12:31:481090 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
1091 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:141092 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041093 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:241094 id: this._id,
1095 icon: iconPath,
1096 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:161097 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:141098 });
Jan Schefflerd76b4162021-03-29 07:52:161099 },
Blink Reformat4c46d092018-04-07 15:32:371100 };
1101
Danil Somsikov56210832022-10-05 13:17:581102 function canAccessResource(resource: APIImpl.ResourceData): boolean {
Danil Somsikovb2e37052023-03-24 12:50:431103 try {
1104 return extensionInfo.allowFileAccess || (new URL(resource.url)).protocol !== 'file:';
1105 } catch (e) {
1106 return false;
1107 }
Danil Somsikov56210832022-10-05 13:17:581108 }
1109
Philip Pfaffeddf60d22021-06-25 12:35:411110 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
1111 function dispatchResourceEvent(
1112 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581113 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1114 if (!canAccessResource(resourceData)) {
1115 return;
1116 }
1117 this._fire(new (Constructor(Resource))(resourceData));
Blink Reformat4c46d092018-04-07 15:32:371118 }
1119
Philip Pfaffeddf60d22021-06-25 12:35:411120 function dispatchResourceContentEvent(
1121 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
1122 message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581123 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1124 if (!canAccessResource(resourceData)) {
1125 return;
1126 }
1127 this._fire(new (Constructor(Resource))(resourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:371128 }
1129
Philip Pfaffeddf60d22021-06-25 12:35:411130 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:041131 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:411132 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:371133 }
1134
Philip Pfaffeddf60d22021-06-25 12:35:411135 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
1136 reload: function(optionsOrUserAgent: {
1137 ignoreCache?: boolean,
1138 injectedScript?: string,
1139 userAgent?: string,
1140 }): void {
Jan Schefflerd76b4162021-03-29 07:52:161141 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:411142 ignoreCache?: boolean,
1143 injectedScript?: string,
1144 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:161145 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:371146 if (typeof optionsOrUserAgent === 'object') {
1147 options = optionsOrUserAgent;
1148 } else if (typeof optionsOrUserAgent === 'string') {
1149 options = {userAgent: optionsOrUserAgent};
1150 console.warn(
1151 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
1152 'Use inspectedWindow.reload({ userAgent: value}) instead.');
1153 }
Philip Pfaffe939605d2021-06-25 12:20:041154 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:371155 },
1156
Philip Pfaffeddf60d22021-06-25 12:35:411157 eval: function(
1158 expression: string,
Benedikt Meurer6428bce2023-09-15 10:47:331159 evaluateOptions: {scriptExecutionContext?: string, frameURL?: string, useContentScriptContext?: boolean}):
Philip Pfaffeddf60d22021-06-25 12:35:411160 Object |
Jan Schefflerd76b4162021-03-29 07:52:161161 null {
1162 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411163 function callbackWrapper(result: unknown): void {
1164 const {isError, isException, value} = result as {
1165 isError?: boolean,
1166 isException?: boolean, value: unknown,
1167 };
1168 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141169 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161170 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411171 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161172 }
1173 }
Philip Pfaffe7523faf2021-06-28 14:23:141174 extensionServer.sendRequest(
1175 {
1176 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1177 expression: expression,
1178 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1179 },
1180 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161181 return null;
1182 },
Blink Reformat4c46d092018-04-07 15:32:371183
Philip Pfaffeddf60d22021-06-25 12:35:411184 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1185 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1186 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371187 }
Philip Pfaffeddf60d22021-06-25 12:35:411188 function callbackWrapper(resources: unknown): void {
Danil Somsikovf8035f02023-07-17 14:05:411189 callback && callback((resources as APIImpl.ResourceData[]).filter(canAccessResource).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:371190 }
Danil Somsikov56210832022-10-05 13:17:581191 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161192 },
Blink Reformat4c46d092018-04-07 15:32:371193 };
1194
Philip Pfaffe6fd04c42021-06-25 12:31:481195 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Danil Somsikovf8035f02023-07-17 14:05:411196 if (!canAccessResource(resourceData)) {
Danil Somsikov56210832022-10-05 13:17:581197 throw new Error('Resource access not allowed');
1198 }
Blink Reformat4c46d092018-04-07 15:32:371199 this._url = resourceData.url;
1200 this._type = resourceData.type;
1201 }
1202
Philip Pfaffe6fd04c42021-06-25 12:31:481203 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161204 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481205 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371206 },
1207
Jan Schefflerd76b4162021-03-29 07:52:161208 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481209 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371210 },
1211
Philip Pfaffe6fd04c42021-06-25 12:31:481212 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1213 function callbackWrapper(response: unknown): void {
1214 const {content, encoding} = response as {content: string, encoding: string};
1215 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371216 }
1217
Philip Pfaffe939605d2021-06-25 12:20:041218 extensionServer.sendRequest(
1219 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371220 },
1221
Philip Pfaffe6fd04c42021-06-25 12:31:481222 setContent: function(
1223 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371224 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041225 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481226 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161227 },
Blink Reformat4c46d092018-04-07 15:32:371228 };
1229
Jan Schefflerd76b4162021-03-29 07:52:161230 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371231 return inspectedTabId;
1232 }
1233
Philip Pfaffe7523faf2021-06-28 14:23:141234 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161235 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141236 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521237 // Check if the event should be forwarded.
1238 // This is a workaround for crbug.com/923338.
1239 const focused = document.activeElement;
1240 if (focused) {
Benedikt Meurer5d508f62022-12-06 14:37:381241 const isInput =
1242 focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA' || (focused as HTMLElement).isContentEditable;
Jan Schefflere7d7bb12019-10-24 09:18:521243 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1244 return;
1245 }
1246 }
1247
Joel Einbinder67f28fb2018-08-02 00:33:471248 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341249 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471250 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341251 }
1252 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471253 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341254 }
1255 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471256 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341257 }
1258 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471259 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341260 }
Joel Einbinder67f28fb2018-08-02 00:33:471261 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371262 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341263 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371264 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341265 }
Joel Einbinder67f28fb2018-08-02 00:33:471266 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371267 const requestPayload = {
1268 eventType: event.type,
1269 ctrlKey: event.ctrlKey,
1270 altKey: event.altKey,
1271 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471272 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141273 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371274 keyIdentifier: event.keyIdentifier,
1275 key: event.key,
1276 code: event.code,
1277 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161278 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371279 };
1280 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341281 if (!forwardTimer) {
Tim van der Lippe6bcbe0f2022-01-11 13:10:311282 forwardTimer = window.setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341283 }
Blink Reformat4c46d092018-04-07 15:32:371284 }
1285
Jan Schefflerd76b4162021-03-29 07:52:161286 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371287 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141288 extensionServer.sendRequest(
1289 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371290 keyboardEventRequestQueue = [];
1291 }
1292
1293 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371294
Alex Rudenkoa3850822022-05-24 07:34:221295 function ExtensionServerClient(this: APIImpl.ExtensionServerClient, targetWindow: Window): void {
Blink Reformat4c46d092018-04-07 15:32:371296 this._callbacks = {};
1297 this._handlers = {};
1298 this._lastRequestId = 0;
1299 this._lastObjectId = 0;
1300
1301 this.registerHandler('callback', this._onCallback.bind(this));
1302
1303 const channel = new MessageChannel();
1304 this._port = channel.port1;
1305 this._port.addEventListener('message', this._onMessage.bind(this), false);
1306 this._port.start();
1307
Alex Rudenkoa3850822022-05-24 07:34:221308 targetWindow.postMessage('registerExtension', '*', [channel.port2]);
Blink Reformat4c46d092018-04-07 15:32:371309 }
1310
Philip Pfaffe7523faf2021-06-28 14:23:141311 (ExtensionServerClient.prototype as Pick<
1312 APIImpl.ExtensionServerClient,
1313 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1314 '_onCallback'|'_onMessage'>) = {
Philip Pfaffe6ed01262022-07-06 10:41:391315 sendRequest: function<ResponseT>(
Philip Pfaffe7523faf2021-06-28 14:23:141316 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
Philip Pfaffe6ed01262022-07-06 10:41:391317 callback?: (response: ResponseT) => unknown, transfers?: Transferable[]): void {
Philip Pfaffe7523faf2021-06-28 14:23:141318 if (typeof callback === 'function') {
Philip Pfaffe6ed01262022-07-06 10:41:391319 (message as PrivateAPI.ExtensionServerRequestMessage).requestId =
1320 this._registerCallback(callback as (response: unknown) => unknown);
Philip Pfaffe7523faf2021-06-28 14:23:141321 }
1322 // @ts-expect-error
1323 this._port.postMessage(message, transfers);
1324 },
Blink Reformat4c46d092018-04-07 15:32:371325
Philip Pfaffe7523faf2021-06-28 14:23:141326 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241327 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371328 },
1329
Philip Pfaffe7523faf2021-06-28 14:23:141330 registerHandler: function(
1331 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1332 void {
1333 this._handlers[command] = handler;
1334 },
Blink Reformat4c46d092018-04-07 15:32:371335
Philip Pfaffe7523faf2021-06-28 14:23:141336 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371337 delete this._handlers[command];
1338 },
1339
Philip Pfaffe7523faf2021-06-28 14:23:141340 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371341 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1342 },
1343
Philip Pfaffe7523faf2021-06-28 14:23:141344 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371345 const id = ++this._lastRequestId;
1346 this._callbacks[id] = callback;
1347 return id;
1348 },
1349
Philip Pfaffe7523faf2021-06-28 14:23:141350 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371351 if (request.requestId in this._callbacks) {
1352 const callback = this._callbacks[request.requestId];
1353 delete this._callbacks[request.requestId];
1354 callback(request.result);
1355 }
1356 },
1357
Philip Pfaffe7523faf2021-06-28 14:23:141358 _onMessage: function(
1359 this: APIImpl.ExtensionServerClient,
1360 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371361 const request = event.data;
1362 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341363 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371364 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341365 }
Jan Schefflerd76b4162021-03-29 07:52:161366 },
Blink Reformat4c46d092018-04-07 15:32:371367 };
1368
Philip Pfaffe7523faf2021-06-28 14:23:141369 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371370 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341371 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371372 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341373 }
Jan Schefflerd76b4162021-03-29 07:52:161374 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371375 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141376 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371377 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341378 }
1379 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371380 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341381 }
1382 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371383 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341384 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141385 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371386 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341387 } else {
Blink Reformat4c46d092018-04-07 15:32:371388 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341389 }
Blink Reformat4c46d092018-04-07 15:32:371390 }
1391 }
1392
Alex Rudenkoa3850822022-05-24 07:34:221393 const extensionServer = new (Constructor(ExtensionServerClient))(targetWindowForTest || window.parent);
Philip Pfaffe7523faf2021-06-28 14:23:141394
1395 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371396
1397 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1398
1399 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141400 // @ts-expect-error
1401 chrome.devtools!.inspectedWindow = {};
1402 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1403 // @ts-expect-error
1404 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1405 chrome.devtools!.network = coreAPI.network;
1406 chrome.devtools!.panels = coreAPI.panels;
1407 chrome.devtools!.panels.themeName = themeName;
1408 chrome.devtools!.languageServices = coreAPI.languageServices;
Alex Rudenkoa3850822022-05-24 07:34:221409 chrome.devtools!.recorder = coreAPI.recorder;
Blink Reformat4c46d092018-04-07 15:32:371410
1411 // default to expose experimental APIs for now.
1412 if (extensionInfo.exposeExperimentalAPIs !== false) {
1413 chrome.experimental = chrome.experimental || {};
1414 chrome.experimental.devtools = chrome.experimental.devtools || {};
1415
1416 const properties = Object.getOwnPropertyNames(coreAPI);
1417 for (let i = 0; i < properties.length; ++i) {
1418 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341419 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371420 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341421 }
Blink Reformat4c46d092018-04-07 15:32:371422 }
1423 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1424 }
1425
Tim van der Lippe1d6e57a2019-09-30 11:55:341426 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371427 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341428 }
Blink Reformat4c46d092018-04-07 15:32:371429 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121430};
Blink Reformat4c46d092018-04-07 15:32:371431
Jan Schefflerd76b4162021-03-29 07:52:161432self.buildExtensionAPIInjectedScript = function(
1433 extensionInfo: {
1434 startPage: string,
1435 name: string,
1436 exposeExperimentalAPIs: boolean,
1437 },
1438 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141439 testHook:
1440 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1441 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251442 const argumentsJSON =
1443 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341444 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161445 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341446 }
Philip Pfaffe939605d2021-06-25 12:20:041447 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121448 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371449 '})';
Tim van der Lippe29fab472019-08-15 14:46:481450};