blob: 04d576a174555318a3ecf8d5ccbe07e831143e91 [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
Kateryna Prokopenko6fa122c2022-05-06 08:54:4731import * as Platform from '../../core/platform/platform.js';
Philip Pfaffe7523faf2021-06-28 14:23:1432import type * as PublicAPI from '../../../extension-api/ExtensionAPI'; // eslint-disable-line rulesdir/es_modules_import
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-',
53 RecordingStarted = 'trace-recording-started-',
54 RecordingStopped = 'trace-recording-stopped-',
55 ResourceAdded = 'resource-added',
56 ResourceContentCommitted = 'resource-content-committed',
57 ViewShown = 'view-shown-',
58 ViewHidden = 'view-hidden,',
Paul Lewisada689f2022-01-11 12:03:4059 ThemeChange = 'host-theme-change',
Philip Pfaffe939605d2021-06-25 12:20:0460 }
Blink Reformat4c46d092018-04-07 15:32:3761
Philip Pfaffe939605d2021-06-25 12:20:0462 export const enum Commands {
63 AddRequestHeaders = 'addRequestHeaders',
64 AddTraceProvider = 'addTraceProvider',
65 ApplyStyleSheet = 'applyStyleSheet',
66 CompleteTraceSession = 'completeTra.eSession',
67 CreatePanel = 'createPanel',
68 CreateSidebarPane = 'createSidebarPane',
69 CreateToolbarButton = 'createToolbarButton',
70 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
71 ForwardKeyboardEvent = '_forwardKeyboardEvent',
72 GetHAR = 'getHAR',
73 GetPageResources = 'getPageResources',
74 GetRequestContent = 'getRequestContent',
75 GetResourceContent = 'getResourceContent',
76 OpenResource = 'openResource',
77 Reload = 'Reload',
78 Subscribe = 'subscribe',
79 SetOpenResourceHandler = 'setOpenResourceHandler',
Paul Lewisada689f2022-01-11 12:03:4080 SetThemeChangeHandler = 'setThemeChangeHandler',
Philip Pfaffe939605d2021-06-25 12:20:0481 SetResourceContent = 'setResourceContent',
82 SetSidebarContent = 'setSidebarContent',
83 SetSidebarHeight = 'setSidebarHeight',
84 SetSidebarPage = 'setSidebarPage',
85 ShowPanel = 'showPanel',
86 Unsubscribe = 'unsubscribe',
87 UpdateButton = 'updateButton',
88 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
Philip Pfaffe6ed01262022-07-06 10:41:3989 GetWasmLinearMemory = 'getWasmLinearMemory',
90 GetWasmLocal = 'getWasmLocal',
91 GetWasmGlobal = 'getWasmGlobal',
92 GetWasmOp = 'getWasmOp',
Alex Rudenkoa3850822022-05-24 07:34:2293 RegisterRecorderExtensionPlugin = 'registerRecorderExtensionPlugin',
Philip Pfaffe939605d2021-06-25 12:20:0494 }
Philip Pfaffeedad8322020-07-20 10:24:2595
Philip Pfaffe939605d2021-06-25 12:20:0496 export const enum LanguageExtensionPluginCommands {
97 AddRawModule = 'addRawModule',
98 RemoveRawModule = 'removeRawModule',
99 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
100 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
101 GetScopeInfo = 'getScopeInfo',
102 ListVariablesInScope = 'listVariablesInScope',
103 GetTypeInfo = 'getTypeInfo',
104 GetFormatter = 'getFormatter',
105 GetInspectableAddress = 'getInspectableAddress',
106 GetFunctionInfo = 'getFunctionInfo',
107 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
108 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
109 GetMappedLines = 'getMappedLines',
Philip Pfaffe6ed01262022-07-06 10:41:39110 FormatValue = 'formatValue',
111 GetProperties = 'getProperties',
112 ReleaseObject = 'releaseObject',
Philip Pfaffe939605d2021-06-25 12:20:04113 }
Benedikt Meurer929fc7c2020-11-20 14:21:06114
Philip Pfaffe939605d2021-06-25 12:20:04115 export const enum LanguageExtensionPluginEvents {
116 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
117 }
Philip Pfaffed662bdf2021-06-25 13:30:32118
Alex Rudenkoa3850822022-05-24 07:34:22119 export const enum RecorderExtensionPluginCommands {
120 Stringify = 'stringify',
Alex Rudenko2aa04c02022-06-01 13:05:20121 StringifyStep = 'stringifyStep',
Alex Rudenkoa3850822022-05-24 07:34:22122 }
123
124 export const enum RecorderExtensionPluginEvents {
125 UnregisteredRecorderExtensionPlugin = 'unregisteredRecorderExtensionPlugin',
126 }
127
Philip Pfaffed662bdf2021-06-25 13:30:32128 export interface EvaluateOptions {
129 frameURL?: string;
130 useContentScriptContext?: boolean;
131 scriptExecutionContext?: string;
132 }
133
Philip Pfaffed662bdf2021-06-25 13:30:32134 type RegisterLanguageExtensionPluginRequest = {
135 command: Commands.RegisterLanguageExtensionPlugin,
136 pluginName: string,
137 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14138 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32139 };
Alex Rudenkoa3850822022-05-24 07:34:22140 type RegisterRecorderExtensionPluginRequest = {
141 command: Commands.RegisterRecorderExtensionPlugin,
142 pluginName: string,
Alex Rudenko53dbba42022-06-02 13:01:23143 mediaType: string,
Alex Rudenkoa3850822022-05-24 07:34:22144 port: MessagePort,
145 };
Philip Pfaffed662bdf2021-06-25 13:30:32146 type SubscribeRequest = {command: Commands.Subscribe, type: string};
147 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
148 type AddRequestHeadersRequest = {
149 command: Commands.AddRequestHeaders,
150 extensionId: string,
151 headers: {[key: string]: string},
152 };
153 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
154 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
155 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
156 type CreateToolbarButtonRequest = {
157 command: Commands.CreateToolbarButton,
158 id: string,
159 icon: string,
160 panel: string,
161 tooltip?: string,
162 disabled?: boolean,
163 };
164 type UpdateButtonRequest =
165 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
166 type CompleteTraceSessionRequest =
Kateryna Prokopenko6fa122c2022-05-06 08:54:47167 {command: Commands.CompleteTraceSession, id: string, url: Platform.DevToolsPath.UrlString, timeOffset: number};
Philip Pfaffed662bdf2021-06-25 13:30:32168 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
169 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
170 type SetSidebarContentRequest = {
171 command: Commands.SetSidebarContent,
172 id: string,
173 evaluateOnPage?: boolean, expression: string,
174 rootTitle?: string,
175 evaluateOptions?: EvaluateOptions,
176 };
177 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Kateryna Prokopenko9964ab12022-03-23 16:41:49178 type OpenResourceRequest =
179 {command: Commands.OpenResource, url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32180 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
Paul Lewisada689f2022-01-11 12:03:40181 type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32182 type ReloadRequest = {
183 command: Commands.Reload,
184 options: null|{
185 userAgent?: string,
186 injectedScript?: string,
187 ignoreCache?: boolean,
188 },
189 };
190 type EvaluateOnInspectedPageRequest = {
191 command: Commands.EvaluateOnInspectedPage,
192 expression: string,
193 evaluateOptions?: EvaluateOptions,
194 };
195 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
196 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
197 type SetResourceContentRequest =
198 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
199 type AddTraceProviderRequest =
200 {command: Commands.AddTraceProvider, id: string, categoryName: string, categoryTooltip: string};
201 type ForwardKeyboardEventRequest = {
202 command: Commands.ForwardKeyboardEvent,
203 entries: Array<KeyboardEventInit&{eventType: string}>,
204 };
205 type GetHARRequest = {command: Commands.GetHAR};
Danil Somsikov56210832022-10-05 13:17:58206 type GetPageResourcesRequest = {command: Commands.GetPageResources};
Philip Pfaffe6ed01262022-07-06 10:41:39207 type GetWasmLinearMemoryRequest = {
208 command: Commands.GetWasmLinearMemory,
209 offset: number,
210 length: number,
211 stopId: unknown,
212 };
213 type GetWasmLocalRequest = {
214 command: Commands.GetWasmLocal,
215 local: number,
216 stopId: unknown,
217 };
218 type GetWasmGlobalRequest = {
219 command: Commands.GetWasmGlobal,
220 global: number,
221 stopId: unknown,
222 };
223 type GetWasmOpRequest = {command: Commands.GetWasmOp, op: number, stopId: unknown};
Philip Pfaffed662bdf2021-06-25 13:30:32224
Alex Rudenkoa3850822022-05-24 07:34:22225 export type ServerRequests = RegisterRecorderExtensionPluginRequest|RegisterLanguageExtensionPluginRequest|
226 SubscribeRequest|UnsubscribeRequest|AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|
227 ShowPanelRequest|CreateToolbarButtonRequest|UpdateButtonRequest|CompleteTraceSessionRequest|
228 CreateSidebarPaneRequest|SetSidebarHeightRequest|SetSidebarContentRequest|SetSidebarPageRequest|
229 OpenResourceRequest|SetOpenResourceHandlerRequest|SetThemeChangeHandlerRequest|ReloadRequest|
230 EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
Philip Pfaffe6ed01262022-07-06 10:41:39231 AddTraceProviderRequest|ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest|
232 GetWasmLinearMemoryRequest|GetWasmLocalRequest|GetWasmGlobalRequest|GetWasmOpRequest;
Philip Pfaffed662bdf2021-06-25 13:30:32233 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32234
235 type AddRawModuleRequest = {
236 method: LanguageExtensionPluginCommands.AddRawModule,
237 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
238 };
239 type SourceLocationToRawLocationRequest = {
240 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
241 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
242 };
243 type RawLocationToSourceLocationRequest = {
244 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
245 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
246 };
247 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
248 type ListVariablesInScopeRequest = {
249 method: LanguageExtensionPluginCommands.ListVariablesInScope,
250 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
251 };
252 type RemoveRawModuleRequest = {
253 method: LanguageExtensionPluginCommands.RemoveRawModule,
254 parameters: {rawModuleId: string},
255 };
256 type GetTypeInfoRequest = {
257 method: LanguageExtensionPluginCommands.GetTypeInfo,
258 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation},
259 };
260 type GetFormatterRequest = {
261 method: LanguageExtensionPluginCommands.GetFormatter,
262 parameters: {
263 expressionOrField: string|{
264 base: PublicAPI.Chrome.DevTools.EvalBase,
265 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
266 },
267 context: PublicAPI.Chrome.DevTools.RawLocation,
268 },
269 };
270 type GetInspectableAddressRequest = {
271 method: LanguageExtensionPluginCommands.GetInspectableAddress,
272 parameters: {
273 field: {
274 base: PublicAPI.Chrome.DevTools.EvalBase,
275 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
276 },
277 },
278 };
279 type GetFunctionInfoRequest = {
280 method: LanguageExtensionPluginCommands.GetFunctionInfo,
281 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
282 };
283 type GetInlinedFunctionRangesRequest = {
284 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
285 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
286 };
287 type GetInlinedCalleesRangesRequest = {
288 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
289 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
290 };
291 type GetMappedLinesRequest = {
292 method: LanguageExtensionPluginCommands.GetMappedLines,
293 parameters: {rawModuleId: string, sourceFileURL: string},
294 };
Philip Pfaffe6ed01262022-07-06 10:41:39295 type FormatValueRequest = {
296 method: LanguageExtensionPluginCommands.FormatValue,
297 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation, stopId: number},
298 };
299 type GetPropertiesRequest = {
300 method: LanguageExtensionPluginCommands.GetProperties,
301 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
302 };
303 type ReleaseObjectRequest = {
304 method: LanguageExtensionPluginCommands.ReleaseObject,
305 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
306 };
Philip Pfaffec5d160e2021-07-20 10:53:32307
Philip Pfaffe6ed01262022-07-06 10:41:39308 export type LanguageExtensionRequests =
309 AddRawModuleRequest|SourceLocationToRawLocationRequest|RawLocationToSourceLocationRequest|GetScopeInfoRequest|
310 ListVariablesInScopeRequest|RemoveRawModuleRequest|GetTypeInfoRequest|GetFormatterRequest|
311 GetInspectableAddressRequest|GetFunctionInfoRequest|GetInlinedFunctionRangesRequest|
312 GetInlinedCalleesRangesRequest|GetMappedLinesRequest|FormatValueRequest|GetPropertiesRequest|ReleaseObjectRequest;
Alex Rudenkoa3850822022-05-24 07:34:22313
314 type StringifyRequest = {
315 method: RecorderExtensionPluginCommands.Stringify,
316 parameters: {recording: Record<string, unknown>},
317 };
318
Alex Rudenko2aa04c02022-06-01 13:05:20319 type StringifyStepRequest = {
320 method: RecorderExtensionPluginCommands.StringifyStep,
321 parameters: {step: Record<string, unknown>},
322 };
323
324 export type RecorderExtensionRequests = StringifyRequest|StringifyStepRequest;
Blink Reformat4c46d092018-04-07 15:32:37325}
326
Philip Pfaffe939605d2021-06-25 12:20:04327declare global {
328 interface Window {
329 injectedExtensionAPI:
330 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14331 testHook:
332 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22333 injectedScriptId: number, targetWindow?: Window) => void;
Philip Pfaffe939605d2021-06-25 12:20:04334 buildExtensionAPIInjectedScript(
335 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32336 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14337 chrome: PublicAPI.Chrome.DevTools.Chrome;
338 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04339 }
340}
341
342export type ExtensionDescriptor = {
343 startPage: string,
344 name: string,
345 exposeExperimentalAPIs: boolean,
346 exposeWebInspectorNamespace?: boolean,
Danil Somsikov28cfaf32022-09-27 15:36:55347 allowFileAccess?: boolean,
Philip Pfaffe939605d2021-06-25 12:20:04348};
349
Philip Pfaffe7523faf2021-06-28 14:23:14350namespace APIImpl {
351 export interface InspectorExtensionAPI {
352 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Alex Rudenkoa3850822022-05-24 07:34:22353 recorder: PublicAPI.Chrome.DevTools.RecorderExtensions;
Philip Pfaffe1c827212021-06-25 12:33:20354 timeline: Timeline;
Philip Pfaffe7523faf2021-06-28 14:23:14355 network: PublicAPI.Chrome.DevTools.Network;
356 panels: PublicAPI.Chrome.DevTools.Panels;
357 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
358 }
359
360 export interface ExtensionServerClient {
361 _callbacks: {[key: string]: (response: unknown) => unknown};
362 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
363 _lastRequestId: number;
364 _lastObjectId: number;
365 _port: MessagePort;
366
367 _onCallback(request: unknown): void;
368 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
369 _registerCallback(callback: (response: unknown) => unknown): number;
370 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
371 unregisterHandler(command: string): void;
372 hasHandler(command: string): boolean;
Philip Pfaffe6ed01262022-07-06 10:41:39373 sendRequest<ResponseT>(
374 request: PrivateAPI.ServerRequests, callback?: ((response: ResponseT) => unknown), transfers?: unknown[]): void;
Philip Pfaffe7523faf2021-06-28 14:23:14375 nextObjectId(): string;
376 }
377
378 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
379 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
380 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28381 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14382 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28383 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14384
385 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
386 _type: string;
387 _listeners: ListenerT[];
388 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
389
390 _fire(..._vararg: Parameters<ListenerT>): void;
391 _dispatch(request: {arguments: unknown[]}): void;
392 }
Philip Pfaffe4b88c662021-06-25 12:30:47393
394 export interface Network extends PublicAPI.Chrome.DevTools.Network {
395 addRequestHeaders(headers: {[key: string]: string}): void;
396 }
397
398 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
399 _id: number;
400 }
Philip Pfaffe6fd04c42021-06-25 12:31:48401
402 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
403 get SearchAction(): {[key: string]: string};
404 applyStyleSheet(styleSheet: string): void;
405 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
406 void;
Paul Lewisada689f2022-01-11 12:03:40407 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48408 }
409
410 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
411 _id: string|null;
412 }
413
414 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
415 setExpression(
416 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
417 callback?: () => unknown): void;
418 }
419
420 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
421 _hostPanelName: string;
422 }
423
424 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
425 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
426 }
427
Alex Rudenkoa3850822022-05-24 07:34:22428 export interface RecorderExtensions extends PublicAPI.Chrome.DevTools.RecorderExtensions {
429 _plugins: Map<PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, MessagePort>;
430 }
431
Philip Pfaffe6fd04c42021-06-25 12:31:48432 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
433 show(): void;
434 }
435
436 export interface Button extends PublicAPI.Chrome.DevTools.Button {
437 _id: string;
438 }
439
Philip Pfaffe1c827212021-06-25 12:33:20440 export interface TraceSession {
441 _id: string;
442
443 complete(url?: string, timeOffset?: number): void;
444 }
445
446 export interface TraceProvider {
447 onRecordingStarted: EventSink<(session: TraceSession) => unknown>;
448 onRecordingStopped: EventSink<() => unknown>;
449 }
450
451 export interface Timeline {
452 addTraceProvider(categoryName: string, categoryTooltip: string): TraceProvider;
453 }
454
Philip Pfaffe6fd04c42021-06-25 12:31:48455 export type ResourceData = {url: string, type: string};
456 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
457 _type: string;
458 _url: string;
459
460 get type(): string;
461 }
Philip Pfaffe7523faf2021-06-28 14:23:14462}
Philip Pfaffe939605d2021-06-25 12:20:04463
Tim van der Lippe226fc222019-10-10 12:17:12464self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14465 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
466 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22467 injectedScriptId: number, targetWindowForTest?: Window): void {
Jan Schefflerd76b4162021-03-29 07:52:16468 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37469 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16470
Blink Reformat4c46d092018-04-07 15:32:37471 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34472 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37473 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34474 }
Blink Reformat4c46d092018-04-07 15:32:37475 let userAction = false;
476
477 // Here and below, all constructors are private to API implementation.
478 // For a public type Foo, if internal fields are present, these are on
479 // a private FooImpl type, an instance of FooImpl is used in a closure
480 // by Foo consutrctor to re-bind publicly exported members to an instance
481 // of Foo.
482
Philip Pfaffe7523faf2021-06-28 14:23:14483 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
484 this: APIImpl.EventSink<ListenerT>, type: string,
485 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37486 this._type = type;
487 this._listeners = [];
488 this._customDispatch = customDispatch;
489 }
490
491 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14492 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
493 void {
494 if (typeof callback !== 'function') {
495 throw 'addListener: callback is not a function';
496 }
497 if (this._listeners.length === 0) {
498 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
499 }
500 this._listeners.push(callback);
501 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
502 },
Blink Reformat4c46d092018-04-07 15:32:37503
Philip Pfaffe7523faf2021-06-28 14:23:14504 removeListener: function<ListenerT extends APIImpl.Callable>(
505 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37506 const listeners = this._listeners;
507
508 for (let i = 0; i < listeners.length; ++i) {
509 if (listeners[i] === callback) {
510 listeners.splice(i, 1);
511 break;
512 }
513 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34514 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04515 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34516 }
Blink Reformat4c46d092018-04-07 15:32:37517 },
518
Philip Pfaffe7523faf2021-06-28 14:23:14519 _fire: function<ListenerT extends APIImpl.Callable>(
520 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37521 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34522 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14523 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34524 }
Blink Reformat4c46d092018-04-07 15:32:37525 },
526
Philip Pfaffe7523faf2021-06-28 14:23:14527 _dispatch: function<ListenerT extends APIImpl.Callable>(
528 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34529 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37530 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34531 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14532 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34533 }
Jan Schefflerd76b4162021-03-29 07:52:16534 },
Blink Reformat4c46d092018-04-07 15:32:37535 };
536
Philip Pfaffe7523faf2021-06-28 14:23:14537 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
538 ThisParameterType<NewT> {
539 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
540 }
541
Philip Pfaffe7523faf2021-06-28 14:23:14542 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41543 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48544 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47545 this.network = new (Constructor(Network))();
Philip Pfaffe1c827212021-06-25 12:33:20546 this.timeline = new (Constructor(Timeline))();
Philip Pfaffec5d160e2021-07-20 10:53:32547 this.languageServices = new (Constructor(LanguageServicesAPI))();
Alex Rudenkoa3850822022-05-24 07:34:22548 this.recorder = new (Constructor(RecorderServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37549 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
550 }
551
Philip Pfaffe4b88c662021-06-25 12:30:47552 function Network(this: APIImpl.Network): void {
553 function dispatchRequestEvent(
554 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
555 message: {arguments: unknown[]}): void {
556 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
557
558 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37559 this._fire(request);
560 }
Philip Pfaffe4b88c662021-06-25 12:30:47561
562 this.onRequestFinished =
563 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37564 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47565
566 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37567 }
568
Philip Pfaffe4b88c662021-06-25 12:30:47569 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
570 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
571 function callbackWrapper(response: unknown): void {
572 const result =
573 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37574 const entries = (result && result.entries) || [];
575 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47576 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37577 delete entries[i]._requestId;
578 }
Philip Pfaffe4b88c662021-06-25 12:30:47579 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37580 }
Philip Pfaffe939605d2021-06-25 12:20:04581 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37582 },
583
Philip Pfaffe4b88c662021-06-25 12:30:47584 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37585 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04586 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16587 },
Blink Reformat4c46d092018-04-07 15:32:37588 };
589
Philip Pfaffe4b88c662021-06-25 12:30:47590 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37591 this._id = id;
592 }
593
Philip Pfaffe4b88c662021-06-25 12:30:47594 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
595 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
596 function callbackWrapper(response: unknown): void {
597 const {content, encoding} = response as {content: string, encoding: string};
598 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37599 }
Philip Pfaffe939605d2021-06-25 12:20:04600 extensionServer.sendRequest(
601 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16602 },
Blink Reformat4c46d092018-04-07 15:32:37603 };
604
Philip Pfaffe6fd04c42021-06-25 12:31:48605 function Panels(this: APIImpl.Panels): void {
606 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37607 elements: new ElementsPanel(),
608 sources: new SourcesPanel(),
609 };
610
Philip Pfaffe6fd04c42021-06-25 12:31:48611 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37612 return panels[name];
613 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34614 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12615 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34616 }
Philip Pfaffe6fd04c42021-06-25 12:31:48617 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04618 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37619 };
620 }
621
Paul Lewisada689f2022-01-11 12:03:40622 (Panels.prototype as
623 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48624 create: function(
625 title: string, icon: string, page: string,
626 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37627 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48628 extensionServer.sendRequest(
629 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37630 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37631 },
632
Philip Pfaffe6fd04c42021-06-25 12:31:48633 setOpenResourceHandler: function(
634 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04635 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37636
Philip Pfaffe6fd04c42021-06-25 12:31:48637 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37638 // Allow the panel to show itself when handling the event.
639 userAction = true;
640 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48641 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
Danil Somsikov56210832022-10-05 13:17:58642 if (canAccessResource(resource)) {
643 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
644 }
Blink Reformat4c46d092018-04-07 15:32:37645 } finally {
646 userAction = false;
647 }
648 }
649
Tim van der Lippe1d6e57a2019-09-30 11:55:34650 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04651 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34652 } else {
Philip Pfaffe939605d2021-06-25 12:20:04653 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34654 }
Blink Reformat4c46d092018-04-07 15:32:37655
656 // 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:34657 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04658 extensionServer.sendRequest(
659 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34660 }
Blink Reformat4c46d092018-04-07 15:32:37661 },
662
Paul Lewisada689f2022-01-11 12:03:40663 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
664 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
665
666 function callbackWrapper(message: unknown): void {
667 const {themeName} = message as {themeName: string};
668 chrome.devtools.panels.themeName = themeName;
669 callback.call(null, themeName);
670 }
671
672 if (!callback) {
673 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
674 } else {
675 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
676 }
677
678 // Only send command if we either removed an existing handler or added handler and had none before.
679 if (hadHandler === !callback) {
680 extensionServer.sendRequest(
681 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
682 }
683 },
684
Philip Pfaffe140e5432021-09-13 16:34:23685 openResource: function(
Kateryna Prokopenko9964ab12022-03-23 16:41:49686 url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber?: number,
687 _callback?: (response: unknown) => unknown): void {
Philip Pfaffe140e5432021-09-13 16:34:23688 const callbackArg = extractCallbackArgument(arguments);
689 // Handle older API:
690 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
691 extensionServer.sendRequest(
692 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37693 },
694
Philip Pfaffe6fd04c42021-06-25 12:31:48695 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04696 return {
697 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
698 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
699 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
700 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
701 };
Jan Schefflerd76b4162021-03-29 07:52:16702 },
Blink Reformat4c46d092018-04-07 15:32:37703 };
704
Philip Pfaffe6fd04c42021-06-25 12:31:48705 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37706 this._id = id;
707
Philip Pfaffe6fd04c42021-06-25 12:31:48708 function dispatchShowEvent(
709 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37710 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34711 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37712 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34713 } else {
Blink Reformat4c46d092018-04-07 15:32:37714 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34715 }
Blink Reformat4c46d092018-04-07 15:32:37716 }
717
718 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48719 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
720
721 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37722 }
723 }
724
Philip Pfaffe6fd04c42021-06-25 12:31:48725 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37726 ExtensionViewImpl.call(this, null);
727 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48728
729 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37730 }
731
Philip Pfaffe6fd04c42021-06-25 12:31:48732 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
733 {__proto__: APIImpl.ExtensionView}) = {
734 createSidebarPane: function(
735 this: APIImpl.PanelWithSidebar, title: string,
736 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37737 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16738 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48739 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37740 }
Philip Pfaffe7523faf2021-06-28 14:23:14741 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48742 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14743 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37744 },
745
Jan Schefflerd76b4162021-03-29 07:52:16746 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37747 };
748
Alex Rudenkoa3850822022-05-24 07:34:22749 function RecorderServicesAPIImpl(this: APIImpl.RecorderExtensions): void {
750 this._plugins = new Map();
751 }
752
753 (RecorderServicesAPIImpl.prototype as
754 Pick<APIImpl.RecorderExtensions, 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'>) = {
755 registerRecorderExtensionPlugin: async function(
Alex Rudenkofba45c52022-06-01 07:32:05756 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, pluginName: string,
Alex Rudenko53dbba42022-06-02 13:01:23757 mediaType: string): Promise<void> {
Alex Rudenkoa3850822022-05-24 07:34:22758 if (this._plugins.has(plugin)) {
759 throw new Error(`Tried to register plugin '${pluginName}' twice`);
760 }
761 const channel = new MessageChannel();
762 const port = channel.port1;
763 this._plugins.set(plugin, port);
764 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.RecorderExtensionRequests>): void => {
765 const {requestId} = data;
766 dispatchMethodCall(data)
767 .then(result => port.postMessage({requestId, result}))
768 .catch(error => port.postMessage({requestId, error: {message: error.message}}));
769 };
770
Alex Rudenko93820552022-06-01 14:10:03771 async function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
Alex Rudenkoa3850822022-05-24 07:34:22772 switch (request.method) {
773 case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
774 return plugin.stringify(request.parameters.recording);
Alex Rudenko2aa04c02022-06-01 13:05:20775 case PrivateAPI.RecorderExtensionPluginCommands.StringifyStep:
776 return plugin.stringifyStep(request.parameters.step);
Alex Rudenko93820552022-06-01 14:10:03777 default:
778 // @ts-expect-error
779 throw new Error(`'${request.method}' is not recognized`);
Alex Rudenkoa3850822022-05-24 07:34:22780 }
781 }
782
783 await new Promise<void>(resolve => {
784 extensionServer.sendRequest(
785 {
786 command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
787 pluginName,
Alex Rudenko53dbba42022-06-02 13:01:23788 mediaType,
Alex Rudenkoa3850822022-05-24 07:34:22789 port: channel.port2,
790 },
791 () => resolve(), [channel.port2]);
792 });
793 },
794
795 unregisterRecorderExtensionPlugin: async function(
796 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin): Promise<void> {
797 const port = this._plugins.get(plugin);
798 if (!port) {
799 throw new Error('Tried to unregister a plugin that was not previously registered');
800 }
801 this._plugins.delete(plugin);
802 port.postMessage({event: PrivateAPI.RecorderExtensionPluginEvents.UnregisteredRecorderExtensionPlugin});
803 port.close();
804 },
805 };
806
Philip Pfaffec5d160e2021-07-20 10:53:32807 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25808 this._plugins = new Map();
809 }
810
Philip Pfaffe6ed01262022-07-06 10:41:39811 (LanguageServicesAPIImpl.prototype as PublicAPI.Chrome.DevTools.LanguageExtensions) = {
Philip Pfaffed662bdf2021-06-25 13:30:32812 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32813 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
814 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
815 if (this._plugins.has(plugin)) {
816 throw new Error(`Tried to register plugin '${pluginName}' twice`);
817 }
818 const channel = new MessageChannel();
819 const port = channel.port1;
820 this._plugins.set(plugin, port);
821 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
822 const {requestId} = data;
823 console.time(`${requestId}: ${data.method}`);
824 dispatchMethodCall(data)
825 .then(result => port.postMessage({requestId, result}))
826 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
827 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
828 };
Philip Pfaffeedad8322020-07-20 10:24:25829
Philip Pfaffec5d160e2021-07-20 10:53:32830 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
831 switch (request.method) {
832 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
833 return plugin.addRawModule(
834 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
835 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
836 return plugin.removeRawModule(request.parameters.rawModuleId);
837 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
838 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
839 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
840 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
841 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
842 return plugin.getScopeInfo(request.parameters.type);
843 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
844 return plugin.listVariablesInScope(request.parameters.rawLocation);
845 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
846 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
847 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
848 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
849 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
850 if ('getInspectableAddress' in plugin) {
851 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02852 }
Philip Pfaffec5d160e2021-07-20 10:53:32853 return Promise.resolve({js: ''});
854 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
855 return plugin.getFunctionInfo(request.parameters.rawLocation);
856 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
857 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
858 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
859 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
860 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
861 if ('getMappedLines' in plugin) {
862 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
863 }
864 return Promise.resolve(undefined);
Philip Pfaffe6ed01262022-07-06 10:41:39865 case PrivateAPI.LanguageExtensionPluginCommands.FormatValue:
Philip Pfaffe889342a2022-07-08 06:18:47866 if ('evaluate' in plugin && plugin.evaluate) {
Philip Pfaffe6ed01262022-07-06 10:41:39867 return plugin.evaluate(
868 request.parameters.expression, request.parameters.context, request.parameters.stopId);
869 }
870 return Promise.resolve(undefined);
871 case PrivateAPI.LanguageExtensionPluginCommands.GetProperties:
Philip Pfaffe889342a2022-07-08 06:18:47872 if ('getProperties' in plugin && plugin.getProperties) {
Philip Pfaffe6ed01262022-07-06 10:41:39873 return plugin.getProperties(request.parameters.objectId);
874 }
Philip Pfaffe889342a2022-07-08 06:18:47875 if (!('evaluate' in plugin &&
876 plugin.evaluate)) { // If evalute is defined but the remote objects methods aren't, that's a bug
Philip Pfaffe6ed01262022-07-06 10:41:39877 return Promise.resolve(undefined);
878 }
879 break;
880 case PrivateAPI.LanguageExtensionPluginCommands.ReleaseObject:
Philip Pfaffe889342a2022-07-08 06:18:47881 if ('releaseObject' in plugin && plugin.releaseObject) {
Philip Pfaffe6ed01262022-07-06 10:41:39882 return plugin.releaseObject(request.parameters.objectId);
883 }
Philip Pfaffe889342a2022-07-08 06:18:47884 if (!('evaluate' in plugin) &&
885 plugin.evaluate) { // If evalute is defined but the remote objects methods aren't, that's a bug
Philip Pfaffe6ed01262022-07-06 10:41:39886 return Promise.resolve(undefined);
887 }
888 break;
Philip Pfaffec5d160e2021-07-20 10:53:32889 }
Philip Pfaffec5d160e2021-07-20 10:53:32890 throw new Error(`Unknown language plugin method ${request.method}`);
891 }
Philip Pfaffeedad8322020-07-20 10:24:25892
Philip Pfaffec5d160e2021-07-20 10:53:32893 await new Promise<void>(resolve => {
894 extensionServer.sendRequest(
895 {
896 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
897 pluginName,
898 port: channel.port2,
899 supportedScriptTypes,
900 },
901 () => resolve(), [channel.port2]);
902 });
903 },
Benedikt Meurer929fc7c2020-11-20 14:21:06904
Philip Pfaffec5d160e2021-07-20 10:53:32905 unregisterLanguageExtensionPlugin: async function(
906 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06907 const port = this._plugins.get(plugin);
908 if (!port) {
909 throw new Error('Tried to unregister a plugin that was not previously registered');
910 }
911 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04912 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06913 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16914 },
Philip Pfaffe6ed01262022-07-06 10:41:39915
916 getWasmLinearMemory: async function(
917 this: APIImpl.LanguageExtensions, offset: number, length: number, stopId: number): Promise<ArrayBuffer> {
918 const result = await new Promise(
919 resolve => extensionServer.sendRequest(
920 {command: PrivateAPI.Commands.GetWasmLinearMemory, offset, length, stopId}, resolve));
921 if (Array.isArray(result)) {
922 return new Uint8Array(result).buffer;
923 }
924 return new ArrayBuffer(0);
925 },
926 getWasmLocal: async function(
927 this: APIImpl.LanguageExtensions, local: number, stopId: number): Promise<PublicAPI.Chrome.DevTools.WasmValue> {
928 return new Promise(
929 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmLocal, local, stopId}, resolve));
930 },
931 getWasmGlobal: async function(this: APIImpl.LanguageExtensions, global: number, stopId: number):
932 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
933 return new Promise(
934 resolve =>
935 extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmGlobal, global, stopId}, resolve));
936 },
937 getWasmOp: async function(this: APIImpl.LanguageExtensions, op: number, stopId: number):
938 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
939 return new Promise(
940 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmOp, op, stopId}, resolve));
941 },
Philip Pfaffeedad8322020-07-20 10:24:25942 };
943
Philip Pfaffe7523faf2021-06-28 14:23:14944 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
945 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
946 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37947 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14948 implConstructor.apply(impl, args);
949 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37950 };
951 }
952
Philip Pfaffe7523faf2021-06-28 14:23:14953 // eslint-disable-next-line @typescript-eslint/no-explicit-any
954 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37955 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14956 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37957 if (!warningGiven) {
958 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
959 warningGiven = true;
960 }
961 return object[newName];
962 }
963 object.__defineGetter__(oldName, getter);
964 }
965
Philip Pfaffe7523faf2021-06-28 14:23:14966 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37967 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14968 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37969 }
970
Philip Pfaffeedad8322020-07-20 10:24:25971 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Alex Rudenkoa3850822022-05-24 07:34:22972 const RecorderServicesAPI = declareInterfaceClass(RecorderServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37973 const Button = declareInterfaceClass(ButtonImpl);
974 const EventSink = declareInterfaceClass(EventSinkImpl);
975 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
976 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12977 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37978 const Request = declareInterfaceClass(RequestImpl);
979 const Resource = declareInterfaceClass(ResourceImpl);
980 const TraceSession = declareInterfaceClass(TraceSessionImpl);
981
Philip Pfaffe6fd04c42021-06-25 12:31:48982 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12983 constructor() {
984 super('elements');
985 }
Blink Reformat4c46d092018-04-07 15:32:37986 }
987
Philip Pfaffe6fd04c42021-06-25 12:31:48988 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12989 constructor() {
990 super('sources');
991 }
Blink Reformat4c46d092018-04-07 15:32:37992 }
993
Philip Pfaffe6fd04c42021-06-25 12:31:48994 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37995 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48996
997 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37998 }
999
Philip Pfaffe6fd04c42021-06-25 12:31:481000 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
1001 {__proto__: APIImpl.ExtensionView}) = {
1002 createStatusBarButton: function(
1003 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
1004 PublicAPI.Chrome.DevTools.Button {
1005 const id = 'button-' + extensionServer.nextObjectId();
1006 extensionServer.sendRequest({
1007 command: PrivateAPI.Commands.CreateToolbarButton,
1008 panel: this._id as string,
1009 id: id,
1010 icon: iconPath,
1011 tooltip: tooltipText,
1012 disabled: Boolean(disabled),
1013 });
Blink Reformat4c46d092018-04-07 15:32:371014
Philip Pfaffe6fd04c42021-06-25 12:31:481015 return new (Constructor(Button))(id);
1016 },
1017
1018 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:341019 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:371020 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341021 }
Blink Reformat4c46d092018-04-07 15:32:371022
Philip Pfaffe6fd04c42021-06-25 12:31:481023 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:371024 },
1025
Jan Schefflerd76b4162021-03-29 07:52:161026 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371027 };
1028
Philip Pfaffe6fd04c42021-06-25 12:31:481029 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371030 ExtensionViewImpl.call(this, id);
1031 }
1032
Philip Pfaffe6fd04c42021-06-25 12:31:481033 (ExtensionSidebarPaneImpl.prototype as
1034 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
1035 {__proto__: APIImpl.ExtensionView}) = {
1036 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
1037 extensionServer.sendRequest(
1038 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:371039 },
1040
Philip Pfaffe6fd04c42021-06-25 12:31:481041 setExpression: function(
1042 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
1043 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:141044 extensionServer.sendRequest(
1045 {
1046 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:481047 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:141048 expression: expression,
1049 rootTitle: rootTitle,
1050 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:481051 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:141052 },
1053 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:371054 },
1055
Philip Pfaffe6fd04c42021-06-25 12:31:481056 setObject: function(
1057 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371058 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:481059 {
1060 command: PrivateAPI.Commands.SetSidebarContent,
1061 id: this._id as string,
1062 expression: jsonObject,
1063 rootTitle: rootTitle,
1064 },
Philip Pfaffe939605d2021-06-25 12:20:041065 callback);
Blink Reformat4c46d092018-04-07 15:32:371066 },
1067
Philip Pfaffe6fd04c42021-06-25 12:31:481068 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
1069 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:371070 },
1071
Jan Schefflerd76b4162021-03-29 07:52:161072 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371073 };
1074
Philip Pfaffe6fd04c42021-06-25 12:31:481075 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371076 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:481077
1078 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:371079 }
1080
Philip Pfaffe6fd04c42021-06-25 12:31:481081 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
1082 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:141083 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041084 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:241085 id: this._id,
1086 icon: iconPath,
1087 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:161088 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:141089 });
Jan Schefflerd76b4162021-03-29 07:52:161090 },
Blink Reformat4c46d092018-04-07 15:32:371091 };
1092
Philip Pfaffe1c827212021-06-25 12:33:201093 function Timeline(this: APIImpl.Timeline): void {
Blink Reformat4c46d092018-04-07 15:32:371094 }
1095
Philip Pfaffe1c827212021-06-25 12:33:201096 (Timeline.prototype as Pick<APIImpl.Timeline, 'addTraceProvider'>) = {
1097 addTraceProvider: function(this: APIImpl.Timeline, categoryName: string, categoryTooltip: string):
1098 APIImpl.TraceProvider {
1099 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
1100 extensionServer.sendRequest({
1101 command: PrivateAPI.Commands.AddTraceProvider,
1102 id: id,
1103 categoryName: categoryName,
1104 categoryTooltip: categoryTooltip,
1105 });
1106
1107 return new (Constructor(TraceProvider))(id);
1108 },
Blink Reformat4c46d092018-04-07 15:32:371109 };
1110
Philip Pfaffe1c827212021-06-25 12:33:201111 function TraceSessionImpl(this: APIImpl.TraceSession, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371112 this._id = id;
1113 }
1114
Philip Pfaffe1c827212021-06-25 12:33:201115 (TraceSessionImpl.prototype as Pick<APIImpl.TraceSession, 'complete'>) = {
Kateryna Prokopenko6fa122c2022-05-06 08:54:471116 complete: function(this: APIImpl.TraceSession, url?: Platform.DevToolsPath.UrlString, timeOffset?: number): void {
Philip Pfaffe7523faf2021-06-28 14:23:141117 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041118 command: PrivateAPI.Commands.CompleteTraceSession,
1119 id: this._id,
Kateryna Prokopenko6fa122c2022-05-06 08:54:471120 url: url || Platform.DevToolsPath.EmptyUrlString,
Philip Pfaffe939605d2021-06-25 12:20:041121 timeOffset: timeOffset || 0,
Philip Pfaffe7523faf2021-06-28 14:23:141122 });
Jan Schefflerd76b4162021-03-29 07:52:161123 },
Blink Reformat4c46d092018-04-07 15:32:371124 };
1125
Philip Pfaffe1c827212021-06-25 12:33:201126 function TraceProvider(this: APIImpl.TraceProvider, id: string): void {
1127 function dispatchRecordingStarted(
1128 this: APIImpl.EventSink<APIImpl.Callable>, message: {arguments: unknown[]}): void {
1129 const sessionId = message.arguments[0] as string;
1130
1131 this._fire(new (Constructor(TraceSession))(sessionId));
Blink Reformat4c46d092018-04-07 15:32:371132 }
1133
Philip Pfaffe1c827212021-06-25 12:33:201134 this.onRecordingStarted =
1135 new (Constructor(EventSink))(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
1136
1137 this.onRecordingStopped = new (Constructor(EventSink))(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:371138 }
1139
Danil Somsikov56210832022-10-05 13:17:581140 function canAccessResource(resource: APIImpl.ResourceData): boolean {
1141 return extensionInfo.allowFileAccess || !resource.url.startsWith('file://');
1142 }
1143
Philip Pfaffeddf60d22021-06-25 12:35:411144 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
1145 function dispatchResourceEvent(
1146 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581147 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1148 if (!canAccessResource(resourceData)) {
1149 return;
1150 }
1151 this._fire(new (Constructor(Resource))(resourceData));
Blink Reformat4c46d092018-04-07 15:32:371152 }
1153
Philip Pfaffeddf60d22021-06-25 12:35:411154 function dispatchResourceContentEvent(
1155 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
1156 message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581157 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1158 if (!canAccessResource(resourceData)) {
1159 return;
1160 }
1161 this._fire(new (Constructor(Resource))(resourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:371162 }
1163
Philip Pfaffeddf60d22021-06-25 12:35:411164 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:041165 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:411166 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:371167 }
1168
Philip Pfaffeddf60d22021-06-25 12:35:411169 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
1170 reload: function(optionsOrUserAgent: {
1171 ignoreCache?: boolean,
1172 injectedScript?: string,
1173 userAgent?: string,
1174 }): void {
Jan Schefflerd76b4162021-03-29 07:52:161175 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:411176 ignoreCache?: boolean,
1177 injectedScript?: string,
1178 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:161179 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:371180 if (typeof optionsOrUserAgent === 'object') {
1181 options = optionsOrUserAgent;
1182 } else if (typeof optionsOrUserAgent === 'string') {
1183 options = {userAgent: optionsOrUserAgent};
1184 console.warn(
1185 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
1186 'Use inspectedWindow.reload({ userAgent: value}) instead.');
1187 }
Philip Pfaffe939605d2021-06-25 12:20:041188 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:371189 },
1190
Philip Pfaffeddf60d22021-06-25 12:35:411191 eval: function(
1192 expression: string,
1193 evaluateOptions: {contextSecurityOrigin?: string, frameURL?: string, useContentScriptContext?: boolean}):
1194 Object |
Jan Schefflerd76b4162021-03-29 07:52:161195 null {
1196 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411197 function callbackWrapper(result: unknown): void {
1198 const {isError, isException, value} = result as {
1199 isError?: boolean,
1200 isException?: boolean, value: unknown,
1201 };
1202 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141203 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161204 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411205 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161206 }
1207 }
Philip Pfaffe7523faf2021-06-28 14:23:141208 extensionServer.sendRequest(
1209 {
1210 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1211 expression: expression,
1212 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1213 },
1214 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161215 return null;
1216 },
Blink Reformat4c46d092018-04-07 15:32:371217
Philip Pfaffeddf60d22021-06-25 12:35:411218 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1219 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1220 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371221 }
Philip Pfaffeddf60d22021-06-25 12:35:411222 function callbackWrapper(resources: unknown): void {
Danil Somsikov56210832022-10-05 13:17:581223 callback && callback((resources as APIImpl.ResourceData[]).map(wrapResource).filter(canAccessResource));
Blink Reformat4c46d092018-04-07 15:32:371224 }
Danil Somsikov56210832022-10-05 13:17:581225 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161226 },
Blink Reformat4c46d092018-04-07 15:32:371227 };
1228
Philip Pfaffe6fd04c42021-06-25 12:31:481229 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Danil Somsikov56210832022-10-05 13:17:581230 if (!canAccessResource) {
1231 throw new Error('Resource access not allowed');
1232 }
Blink Reformat4c46d092018-04-07 15:32:371233 this._url = resourceData.url;
1234 this._type = resourceData.type;
1235 }
1236
Philip Pfaffe6fd04c42021-06-25 12:31:481237 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161238 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481239 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371240 },
1241
Jan Schefflerd76b4162021-03-29 07:52:161242 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481243 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371244 },
1245
Philip Pfaffe6fd04c42021-06-25 12:31:481246 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1247 function callbackWrapper(response: unknown): void {
1248 const {content, encoding} = response as {content: string, encoding: string};
1249 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371250 }
1251
Philip Pfaffe939605d2021-06-25 12:20:041252 extensionServer.sendRequest(
1253 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371254 },
1255
Philip Pfaffe6fd04c42021-06-25 12:31:481256 setContent: function(
1257 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371258 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041259 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481260 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161261 },
Blink Reformat4c46d092018-04-07 15:32:371262 };
1263
Jan Schefflerd76b4162021-03-29 07:52:161264 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371265 return inspectedTabId;
1266 }
1267
Philip Pfaffe7523faf2021-06-28 14:23:141268 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161269 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141270 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521271 // Check if the event should be forwarded.
1272 // This is a workaround for crbug.com/923338.
1273 const focused = document.activeElement;
1274 if (focused) {
Benedikt Meurer5d508f62022-12-06 14:37:381275 const isInput =
1276 focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA' || (focused as HTMLElement).isContentEditable;
Jan Schefflere7d7bb12019-10-24 09:18:521277 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1278 return;
1279 }
1280 }
1281
Joel Einbinder67f28fb2018-08-02 00:33:471282 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341283 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471284 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341285 }
1286 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471287 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341288 }
1289 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471290 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341291 }
1292 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471293 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341294 }
Joel Einbinder67f28fb2018-08-02 00:33:471295 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371296 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341297 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371298 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341299 }
Joel Einbinder67f28fb2018-08-02 00:33:471300 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371301 const requestPayload = {
1302 eventType: event.type,
1303 ctrlKey: event.ctrlKey,
1304 altKey: event.altKey,
1305 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471306 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141307 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371308 keyIdentifier: event.keyIdentifier,
1309 key: event.key,
1310 code: event.code,
1311 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161312 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371313 };
1314 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341315 if (!forwardTimer) {
Tim van der Lippe6bcbe0f2022-01-11 13:10:311316 forwardTimer = window.setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341317 }
Blink Reformat4c46d092018-04-07 15:32:371318 }
1319
Jan Schefflerd76b4162021-03-29 07:52:161320 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371321 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141322 extensionServer.sendRequest(
1323 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371324 keyboardEventRequestQueue = [];
1325 }
1326
1327 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371328
Alex Rudenkoa3850822022-05-24 07:34:221329 function ExtensionServerClient(this: APIImpl.ExtensionServerClient, targetWindow: Window): void {
Blink Reformat4c46d092018-04-07 15:32:371330 this._callbacks = {};
1331 this._handlers = {};
1332 this._lastRequestId = 0;
1333 this._lastObjectId = 0;
1334
1335 this.registerHandler('callback', this._onCallback.bind(this));
1336
1337 const channel = new MessageChannel();
1338 this._port = channel.port1;
1339 this._port.addEventListener('message', this._onMessage.bind(this), false);
1340 this._port.start();
1341
Alex Rudenkoa3850822022-05-24 07:34:221342 targetWindow.postMessage('registerExtension', '*', [channel.port2]);
Blink Reformat4c46d092018-04-07 15:32:371343 }
1344
Philip Pfaffe7523faf2021-06-28 14:23:141345 (ExtensionServerClient.prototype as Pick<
1346 APIImpl.ExtensionServerClient,
1347 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1348 '_onCallback'|'_onMessage'>) = {
Philip Pfaffe6ed01262022-07-06 10:41:391349 sendRequest: function<ResponseT>(
Philip Pfaffe7523faf2021-06-28 14:23:141350 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
Philip Pfaffe6ed01262022-07-06 10:41:391351 callback?: (response: ResponseT) => unknown, transfers?: Transferable[]): void {
Philip Pfaffe7523faf2021-06-28 14:23:141352 if (typeof callback === 'function') {
Philip Pfaffe6ed01262022-07-06 10:41:391353 (message as PrivateAPI.ExtensionServerRequestMessage).requestId =
1354 this._registerCallback(callback as (response: unknown) => unknown);
Philip Pfaffe7523faf2021-06-28 14:23:141355 }
1356 // @ts-expect-error
1357 this._port.postMessage(message, transfers);
1358 },
Blink Reformat4c46d092018-04-07 15:32:371359
Philip Pfaffe7523faf2021-06-28 14:23:141360 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241361 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371362 },
1363
Philip Pfaffe7523faf2021-06-28 14:23:141364 registerHandler: function(
1365 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1366 void {
1367 this._handlers[command] = handler;
1368 },
Blink Reformat4c46d092018-04-07 15:32:371369
Philip Pfaffe7523faf2021-06-28 14:23:141370 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371371 delete this._handlers[command];
1372 },
1373
Philip Pfaffe7523faf2021-06-28 14:23:141374 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371375 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1376 },
1377
Philip Pfaffe7523faf2021-06-28 14:23:141378 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371379 const id = ++this._lastRequestId;
1380 this._callbacks[id] = callback;
1381 return id;
1382 },
1383
Philip Pfaffe7523faf2021-06-28 14:23:141384 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371385 if (request.requestId in this._callbacks) {
1386 const callback = this._callbacks[request.requestId];
1387 delete this._callbacks[request.requestId];
1388 callback(request.result);
1389 }
1390 },
1391
Philip Pfaffe7523faf2021-06-28 14:23:141392 _onMessage: function(
1393 this: APIImpl.ExtensionServerClient,
1394 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371395 const request = event.data;
1396 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341397 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371398 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341399 }
Jan Schefflerd76b4162021-03-29 07:52:161400 },
Blink Reformat4c46d092018-04-07 15:32:371401 };
1402
Philip Pfaffe7523faf2021-06-28 14:23:141403 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371404 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341405 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371406 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341407 }
Jan Schefflerd76b4162021-03-29 07:52:161408 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371409 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141410 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371411 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341412 }
1413 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371414 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341415 }
1416 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371417 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341418 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141419 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371420 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341421 } else {
Blink Reformat4c46d092018-04-07 15:32:371422 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341423 }
Blink Reformat4c46d092018-04-07 15:32:371424 }
1425 }
1426
Alex Rudenkoa3850822022-05-24 07:34:221427 const extensionServer = new (Constructor(ExtensionServerClient))(targetWindowForTest || window.parent);
Philip Pfaffe7523faf2021-06-28 14:23:141428
1429 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371430
1431 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1432
1433 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141434 // @ts-expect-error
1435 chrome.devtools!.inspectedWindow = {};
1436 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1437 // @ts-expect-error
1438 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1439 chrome.devtools!.network = coreAPI.network;
1440 chrome.devtools!.panels = coreAPI.panels;
1441 chrome.devtools!.panels.themeName = themeName;
1442 chrome.devtools!.languageServices = coreAPI.languageServices;
Alex Rudenkoa3850822022-05-24 07:34:221443 chrome.devtools!.recorder = coreAPI.recorder;
Blink Reformat4c46d092018-04-07 15:32:371444
1445 // default to expose experimental APIs for now.
1446 if (extensionInfo.exposeExperimentalAPIs !== false) {
1447 chrome.experimental = chrome.experimental || {};
1448 chrome.experimental.devtools = chrome.experimental.devtools || {};
1449
1450 const properties = Object.getOwnPropertyNames(coreAPI);
1451 for (let i = 0; i < properties.length; ++i) {
1452 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341453 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371454 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341455 }
Blink Reformat4c46d092018-04-07 15:32:371456 }
1457 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1458 }
1459
Tim van der Lippe1d6e57a2019-09-30 11:55:341460 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371461 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341462 }
Blink Reformat4c46d092018-04-07 15:32:371463 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121464};
Blink Reformat4c46d092018-04-07 15:32:371465
Jan Schefflerd76b4162021-03-29 07:52:161466self.buildExtensionAPIInjectedScript = function(
1467 extensionInfo: {
1468 startPage: string,
1469 name: string,
1470 exposeExperimentalAPIs: boolean,
1471 },
1472 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141473 testHook:
1474 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1475 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251476 const argumentsJSON =
1477 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341478 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161479 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341480 }
Philip Pfaffe939605d2021-06-25 12:20:041481 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121482 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371483 '})';
Tim van der Lippe29fab472019-08-15 14:46:481484};