blob: b7f326734b92501b86ba52f5fa3d9561e4cbb17a [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};
206 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,
347};
348
Philip Pfaffe7523faf2021-06-28 14:23:14349namespace APIImpl {
350 export interface InspectorExtensionAPI {
351 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Alex Rudenkoa3850822022-05-24 07:34:22352 recorder: PublicAPI.Chrome.DevTools.RecorderExtensions;
Philip Pfaffe1c827212021-06-25 12:33:20353 timeline: Timeline;
Philip Pfaffe7523faf2021-06-28 14:23:14354 network: PublicAPI.Chrome.DevTools.Network;
355 panels: PublicAPI.Chrome.DevTools.Panels;
356 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
357 }
358
359 export interface ExtensionServerClient {
360 _callbacks: {[key: string]: (response: unknown) => unknown};
361 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
362 _lastRequestId: number;
363 _lastObjectId: number;
364 _port: MessagePort;
365
366 _onCallback(request: unknown): void;
367 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
368 _registerCallback(callback: (response: unknown) => unknown): number;
369 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
370 unregisterHandler(command: string): void;
371 hasHandler(command: string): boolean;
Philip Pfaffe6ed01262022-07-06 10:41:39372 sendRequest<ResponseT>(
373 request: PrivateAPI.ServerRequests, callback?: ((response: ResponseT) => unknown), transfers?: unknown[]): void;
Philip Pfaffe7523faf2021-06-28 14:23:14374 nextObjectId(): string;
375 }
376
377 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
378 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
379 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28380 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14381 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28382 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14383
384 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
385 _type: string;
386 _listeners: ListenerT[];
387 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
388
389 _fire(..._vararg: Parameters<ListenerT>): void;
390 _dispatch(request: {arguments: unknown[]}): void;
391 }
Philip Pfaffe4b88c662021-06-25 12:30:47392
393 export interface Network extends PublicAPI.Chrome.DevTools.Network {
394 addRequestHeaders(headers: {[key: string]: string}): void;
395 }
396
397 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
398 _id: number;
399 }
Philip Pfaffe6fd04c42021-06-25 12:31:48400
401 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
402 get SearchAction(): {[key: string]: string};
403 applyStyleSheet(styleSheet: string): void;
404 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
405 void;
Paul Lewisada689f2022-01-11 12:03:40406 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48407 }
408
409 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
410 _id: string|null;
411 }
412
413 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
414 setExpression(
415 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
416 callback?: () => unknown): void;
417 }
418
419 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
420 _hostPanelName: string;
421 }
422
423 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
424 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
425 }
426
Alex Rudenkoa3850822022-05-24 07:34:22427 export interface RecorderExtensions extends PublicAPI.Chrome.DevTools.RecorderExtensions {
428 _plugins: Map<PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, MessagePort>;
429 }
430
Philip Pfaffe6fd04c42021-06-25 12:31:48431 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
432 show(): void;
433 }
434
435 export interface Button extends PublicAPI.Chrome.DevTools.Button {
436 _id: string;
437 }
438
Philip Pfaffe1c827212021-06-25 12:33:20439 export interface TraceSession {
440 _id: string;
441
442 complete(url?: string, timeOffset?: number): void;
443 }
444
445 export interface TraceProvider {
446 onRecordingStarted: EventSink<(session: TraceSession) => unknown>;
447 onRecordingStopped: EventSink<() => unknown>;
448 }
449
450 export interface Timeline {
451 addTraceProvider(categoryName: string, categoryTooltip: string): TraceProvider;
452 }
453
Philip Pfaffe6fd04c42021-06-25 12:31:48454 export type ResourceData = {url: string, type: string};
455 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
456 _type: string;
457 _url: string;
458
459 get type(): string;
460 }
Philip Pfaffe7523faf2021-06-28 14:23:14461}
Philip Pfaffe939605d2021-06-25 12:20:04462
Tim van der Lippe226fc222019-10-10 12:17:12463self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14464 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
465 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22466 injectedScriptId: number, targetWindowForTest?: Window): void {
Jan Schefflerd76b4162021-03-29 07:52:16467 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37468 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16469
Blink Reformat4c46d092018-04-07 15:32:37470 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34471 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37472 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34473 }
Blink Reformat4c46d092018-04-07 15:32:37474 let userAction = false;
475
476 // Here and below, all constructors are private to API implementation.
477 // For a public type Foo, if internal fields are present, these are on
478 // a private FooImpl type, an instance of FooImpl is used in a closure
479 // by Foo consutrctor to re-bind publicly exported members to an instance
480 // of Foo.
481
Philip Pfaffe7523faf2021-06-28 14:23:14482 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
483 this: APIImpl.EventSink<ListenerT>, type: string,
484 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37485 this._type = type;
486 this._listeners = [];
487 this._customDispatch = customDispatch;
488 }
489
490 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14491 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
492 void {
493 if (typeof callback !== 'function') {
494 throw 'addListener: callback is not a function';
495 }
496 if (this._listeners.length === 0) {
497 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
498 }
499 this._listeners.push(callback);
500 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
501 },
Blink Reformat4c46d092018-04-07 15:32:37502
Philip Pfaffe7523faf2021-06-28 14:23:14503 removeListener: function<ListenerT extends APIImpl.Callable>(
504 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37505 const listeners = this._listeners;
506
507 for (let i = 0; i < listeners.length; ++i) {
508 if (listeners[i] === callback) {
509 listeners.splice(i, 1);
510 break;
511 }
512 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34513 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04514 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34515 }
Blink Reformat4c46d092018-04-07 15:32:37516 },
517
Philip Pfaffe7523faf2021-06-28 14:23:14518 _fire: function<ListenerT extends APIImpl.Callable>(
519 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37520 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34521 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14522 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34523 }
Blink Reformat4c46d092018-04-07 15:32:37524 },
525
Philip Pfaffe7523faf2021-06-28 14:23:14526 _dispatch: function<ListenerT extends APIImpl.Callable>(
527 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34528 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37529 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34530 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14531 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34532 }
Jan Schefflerd76b4162021-03-29 07:52:16533 },
Blink Reformat4c46d092018-04-07 15:32:37534 };
535
Philip Pfaffe7523faf2021-06-28 14:23:14536 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
537 ThisParameterType<NewT> {
538 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
539 }
540
Philip Pfaffe7523faf2021-06-28 14:23:14541 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41542 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48543 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47544 this.network = new (Constructor(Network))();
Philip Pfaffe1c827212021-06-25 12:33:20545 this.timeline = new (Constructor(Timeline))();
Philip Pfaffec5d160e2021-07-20 10:53:32546 this.languageServices = new (Constructor(LanguageServicesAPI))();
Alex Rudenkoa3850822022-05-24 07:34:22547 this.recorder = new (Constructor(RecorderServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37548 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
549 }
550
Philip Pfaffe4b88c662021-06-25 12:30:47551 function Network(this: APIImpl.Network): void {
552 function dispatchRequestEvent(
553 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
554 message: {arguments: unknown[]}): void {
555 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
556
557 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37558 this._fire(request);
559 }
Philip Pfaffe4b88c662021-06-25 12:30:47560
561 this.onRequestFinished =
562 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37563 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47564
565 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37566 }
567
Philip Pfaffe4b88c662021-06-25 12:30:47568 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
569 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
570 function callbackWrapper(response: unknown): void {
571 const result =
572 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37573 const entries = (result && result.entries) || [];
574 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47575 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37576 delete entries[i]._requestId;
577 }
Philip Pfaffe4b88c662021-06-25 12:30:47578 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37579 }
Philip Pfaffe939605d2021-06-25 12:20:04580 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37581 },
582
Philip Pfaffe4b88c662021-06-25 12:30:47583 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37584 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04585 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16586 },
Blink Reformat4c46d092018-04-07 15:32:37587 };
588
Philip Pfaffe4b88c662021-06-25 12:30:47589 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37590 this._id = id;
591 }
592
Philip Pfaffe4b88c662021-06-25 12:30:47593 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
594 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
595 function callbackWrapper(response: unknown): void {
596 const {content, encoding} = response as {content: string, encoding: string};
597 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37598 }
Philip Pfaffe939605d2021-06-25 12:20:04599 extensionServer.sendRequest(
600 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16601 },
Blink Reformat4c46d092018-04-07 15:32:37602 };
603
Philip Pfaffe6fd04c42021-06-25 12:31:48604 function Panels(this: APIImpl.Panels): void {
605 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37606 elements: new ElementsPanel(),
607 sources: new SourcesPanel(),
608 };
609
Philip Pfaffe6fd04c42021-06-25 12:31:48610 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37611 return panels[name];
612 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34613 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12614 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34615 }
Philip Pfaffe6fd04c42021-06-25 12:31:48616 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04617 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37618 };
619 }
620
Paul Lewisada689f2022-01-11 12:03:40621 (Panels.prototype as
622 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48623 create: function(
624 title: string, icon: string, page: string,
625 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37626 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48627 extensionServer.sendRequest(
628 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37629 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37630 },
631
Philip Pfaffe6fd04c42021-06-25 12:31:48632 setOpenResourceHandler: function(
633 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04634 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37635
Philip Pfaffe6fd04c42021-06-25 12:31:48636 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37637 // Allow the panel to show itself when handling the event.
638 userAction = true;
639 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48640 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
641 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
Blink Reformat4c46d092018-04-07 15:32:37642 } finally {
643 userAction = false;
644 }
645 }
646
Tim van der Lippe1d6e57a2019-09-30 11:55:34647 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04648 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34649 } else {
Philip Pfaffe939605d2021-06-25 12:20:04650 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34651 }
Blink Reformat4c46d092018-04-07 15:32:37652
653 // 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:34654 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04655 extensionServer.sendRequest(
656 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34657 }
Blink Reformat4c46d092018-04-07 15:32:37658 },
659
Paul Lewisada689f2022-01-11 12:03:40660 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
661 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
662
663 function callbackWrapper(message: unknown): void {
664 const {themeName} = message as {themeName: string};
665 chrome.devtools.panels.themeName = themeName;
666 callback.call(null, themeName);
667 }
668
669 if (!callback) {
670 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
671 } else {
672 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
673 }
674
675 // Only send command if we either removed an existing handler or added handler and had none before.
676 if (hadHandler === !callback) {
677 extensionServer.sendRequest(
678 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
679 }
680 },
681
Philip Pfaffe140e5432021-09-13 16:34:23682 openResource: function(
Kateryna Prokopenko9964ab12022-03-23 16:41:49683 url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber?: number,
684 _callback?: (response: unknown) => unknown): void {
Philip Pfaffe140e5432021-09-13 16:34:23685 const callbackArg = extractCallbackArgument(arguments);
686 // Handle older API:
687 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
688 extensionServer.sendRequest(
689 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37690 },
691
Philip Pfaffe6fd04c42021-06-25 12:31:48692 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04693 return {
694 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
695 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
696 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
697 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
698 };
Jan Schefflerd76b4162021-03-29 07:52:16699 },
Blink Reformat4c46d092018-04-07 15:32:37700 };
701
Philip Pfaffe6fd04c42021-06-25 12:31:48702 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37703 this._id = id;
704
Philip Pfaffe6fd04c42021-06-25 12:31:48705 function dispatchShowEvent(
706 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37707 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34708 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37709 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34710 } else {
Blink Reformat4c46d092018-04-07 15:32:37711 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34712 }
Blink Reformat4c46d092018-04-07 15:32:37713 }
714
715 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48716 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
717
718 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37719 }
720 }
721
Philip Pfaffe6fd04c42021-06-25 12:31:48722 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37723 ExtensionViewImpl.call(this, null);
724 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48725
726 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37727 }
728
Philip Pfaffe6fd04c42021-06-25 12:31:48729 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
730 {__proto__: APIImpl.ExtensionView}) = {
731 createSidebarPane: function(
732 this: APIImpl.PanelWithSidebar, title: string,
733 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37734 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16735 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48736 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37737 }
Philip Pfaffe7523faf2021-06-28 14:23:14738 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48739 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14740 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37741 },
742
Jan Schefflerd76b4162021-03-29 07:52:16743 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37744 };
745
Alex Rudenkoa3850822022-05-24 07:34:22746 function RecorderServicesAPIImpl(this: APIImpl.RecorderExtensions): void {
747 this._plugins = new Map();
748 }
749
750 (RecorderServicesAPIImpl.prototype as
751 Pick<APIImpl.RecorderExtensions, 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'>) = {
752 registerRecorderExtensionPlugin: async function(
Alex Rudenkofba45c52022-06-01 07:32:05753 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, pluginName: string,
Alex Rudenko53dbba42022-06-02 13:01:23754 mediaType: string): Promise<void> {
Alex Rudenkoa3850822022-05-24 07:34:22755 if (this._plugins.has(plugin)) {
756 throw new Error(`Tried to register plugin '${pluginName}' twice`);
757 }
758 const channel = new MessageChannel();
759 const port = channel.port1;
760 this._plugins.set(plugin, port);
761 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.RecorderExtensionRequests>): void => {
762 const {requestId} = data;
763 dispatchMethodCall(data)
764 .then(result => port.postMessage({requestId, result}))
765 .catch(error => port.postMessage({requestId, error: {message: error.message}}));
766 };
767
Alex Rudenko93820552022-06-01 14:10:03768 async function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
Alex Rudenkoa3850822022-05-24 07:34:22769 switch (request.method) {
770 case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
771 return plugin.stringify(request.parameters.recording);
Alex Rudenko2aa04c02022-06-01 13:05:20772 case PrivateAPI.RecorderExtensionPluginCommands.StringifyStep:
773 return plugin.stringifyStep(request.parameters.step);
Alex Rudenko93820552022-06-01 14:10:03774 default:
775 // @ts-expect-error
776 throw new Error(`'${request.method}' is not recognized`);
Alex Rudenkoa3850822022-05-24 07:34:22777 }
778 }
779
780 await new Promise<void>(resolve => {
781 extensionServer.sendRequest(
782 {
783 command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
784 pluginName,
Alex Rudenko53dbba42022-06-02 13:01:23785 mediaType,
Alex Rudenkoa3850822022-05-24 07:34:22786 port: channel.port2,
787 },
788 () => resolve(), [channel.port2]);
789 });
790 },
791
792 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 },
802 };
803
Philip Pfaffec5d160e2021-07-20 10:53:32804 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25805 this._plugins = new Map();
806 }
807
Philip Pfaffe6ed01262022-07-06 10:41:39808 (LanguageServicesAPIImpl.prototype as PublicAPI.Chrome.DevTools.LanguageExtensions) = {
Philip Pfaffed662bdf2021-06-25 13:30:32809 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32810 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
811 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
812 if (this._plugins.has(plugin)) {
813 throw new Error(`Tried to register plugin '${pluginName}' twice`);
814 }
815 const channel = new MessageChannel();
816 const port = channel.port1;
817 this._plugins.set(plugin, port);
818 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
819 const {requestId} = data;
820 console.time(`${requestId}: ${data.method}`);
821 dispatchMethodCall(data)
822 .then(result => port.postMessage({requestId, result}))
823 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
824 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
825 };
Philip Pfaffeedad8322020-07-20 10:24:25826
Philip Pfaffec5d160e2021-07-20 10:53:32827 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
828 switch (request.method) {
829 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
830 return plugin.addRawModule(
831 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
832 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
833 return plugin.removeRawModule(request.parameters.rawModuleId);
834 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
835 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
836 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
837 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
838 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
839 return plugin.getScopeInfo(request.parameters.type);
840 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
841 return plugin.listVariablesInScope(request.parameters.rawLocation);
842 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
843 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
844 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
845 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
846 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
847 if ('getInspectableAddress' in plugin) {
848 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02849 }
Philip Pfaffec5d160e2021-07-20 10:53:32850 return Promise.resolve({js: ''});
851 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 Pfaffe889342a2022-07-08 06:18:47881 if (!('evaluate' in plugin) &&
882 plugin.evaluate) { // If evalute is defined but the remote objects methods aren't, that's a bug
Philip Pfaffe6ed01262022-07-06 10:41:39883 return Promise.resolve(undefined);
884 }
885 break;
Philip Pfaffec5d160e2021-07-20 10:53:32886 }
Philip Pfaffec5d160e2021-07-20 10:53:32887 throw new Error(`Unknown language plugin method ${request.method}`);
888 }
Philip Pfaffeedad8322020-07-20 10:24:25889
Philip Pfaffec5d160e2021-07-20 10:53:32890 await new Promise<void>(resolve => {
891 extensionServer.sendRequest(
892 {
893 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
894 pluginName,
895 port: channel.port2,
896 supportedScriptTypes,
897 },
898 () => resolve(), [channel.port2]);
899 });
900 },
Benedikt Meurer929fc7c2020-11-20 14:21:06901
Philip Pfaffec5d160e2021-07-20 10:53:32902 unregisterLanguageExtensionPlugin: async function(
903 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06904 const port = this._plugins.get(plugin);
905 if (!port) {
906 throw new Error('Tried to unregister a plugin that was not previously registered');
907 }
908 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04909 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06910 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16911 },
Philip Pfaffe6ed01262022-07-06 10:41:39912
913 getWasmLinearMemory: async function(
914 this: APIImpl.LanguageExtensions, offset: number, length: number, stopId: number): Promise<ArrayBuffer> {
915 const result = await new Promise(
916 resolve => extensionServer.sendRequest(
917 {command: PrivateAPI.Commands.GetWasmLinearMemory, offset, length, stopId}, resolve));
918 if (Array.isArray(result)) {
919 return new Uint8Array(result).buffer;
920 }
921 return new ArrayBuffer(0);
922 },
923 getWasmLocal: async function(
924 this: APIImpl.LanguageExtensions, local: number, stopId: number): Promise<PublicAPI.Chrome.DevTools.WasmValue> {
925 return new Promise(
926 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmLocal, local, stopId}, resolve));
927 },
928 getWasmGlobal: async function(this: APIImpl.LanguageExtensions, global: number, stopId: number):
929 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
930 return new Promise(
931 resolve =>
932 extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmGlobal, global, stopId}, resolve));
933 },
934 getWasmOp: async function(this: APIImpl.LanguageExtensions, op: number, stopId: number):
935 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
936 return new Promise(
937 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmOp, op, stopId}, resolve));
938 },
Philip Pfaffeedad8322020-07-20 10:24:25939 };
940
Philip Pfaffe7523faf2021-06-28 14:23:14941 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
942 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
943 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37944 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14945 implConstructor.apply(impl, args);
946 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37947 };
948 }
949
Philip Pfaffe7523faf2021-06-28 14:23:14950 // eslint-disable-next-line @typescript-eslint/no-explicit-any
951 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37952 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14953 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37954 if (!warningGiven) {
955 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
956 warningGiven = true;
957 }
958 return object[newName];
959 }
960 object.__defineGetter__(oldName, getter);
961 }
962
Philip Pfaffe7523faf2021-06-28 14:23:14963 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37964 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14965 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37966 }
967
Philip Pfaffeedad8322020-07-20 10:24:25968 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Alex Rudenkoa3850822022-05-24 07:34:22969 const RecorderServicesAPI = declareInterfaceClass(RecorderServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37970 const Button = declareInterfaceClass(ButtonImpl);
971 const EventSink = declareInterfaceClass(EventSinkImpl);
972 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
973 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12974 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37975 const Request = declareInterfaceClass(RequestImpl);
976 const Resource = declareInterfaceClass(ResourceImpl);
977 const TraceSession = declareInterfaceClass(TraceSessionImpl);
978
Philip Pfaffe6fd04c42021-06-25 12:31:48979 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12980 constructor() {
981 super('elements');
982 }
Blink Reformat4c46d092018-04-07 15:32:37983 }
984
Philip Pfaffe6fd04c42021-06-25 12:31:48985 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12986 constructor() {
987 super('sources');
988 }
Blink Reformat4c46d092018-04-07 15:32:37989 }
990
Philip Pfaffe6fd04c42021-06-25 12:31:48991 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37992 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48993
994 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37995 }
996
Philip Pfaffe6fd04c42021-06-25 12:31:48997 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
998 {__proto__: APIImpl.ExtensionView}) = {
999 createStatusBarButton: function(
1000 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
1001 PublicAPI.Chrome.DevTools.Button {
1002 const id = 'button-' + extensionServer.nextObjectId();
1003 extensionServer.sendRequest({
1004 command: PrivateAPI.Commands.CreateToolbarButton,
1005 panel: this._id as string,
1006 id: id,
1007 icon: iconPath,
1008 tooltip: tooltipText,
1009 disabled: Boolean(disabled),
1010 });
Blink Reformat4c46d092018-04-07 15:32:371011
Philip Pfaffe6fd04c42021-06-25 12:31:481012 return new (Constructor(Button))(id);
1013 },
1014
1015 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:341016 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:371017 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341018 }
Blink Reformat4c46d092018-04-07 15:32:371019
Philip Pfaffe6fd04c42021-06-25 12:31:481020 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:371021 },
1022
Jan Schefflerd76b4162021-03-29 07:52:161023 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371024 };
1025
Philip Pfaffe6fd04c42021-06-25 12:31:481026 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371027 ExtensionViewImpl.call(this, id);
1028 }
1029
Philip Pfaffe6fd04c42021-06-25 12:31:481030 (ExtensionSidebarPaneImpl.prototype as
1031 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
1032 {__proto__: APIImpl.ExtensionView}) = {
1033 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
1034 extensionServer.sendRequest(
1035 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:371036 },
1037
Philip Pfaffe6fd04c42021-06-25 12:31:481038 setExpression: function(
1039 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
1040 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:141041 extensionServer.sendRequest(
1042 {
1043 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:481044 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:141045 expression: expression,
1046 rootTitle: rootTitle,
1047 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:481048 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:141049 },
1050 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:371051 },
1052
Philip Pfaffe6fd04c42021-06-25 12:31:481053 setObject: function(
1054 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371055 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:481056 {
1057 command: PrivateAPI.Commands.SetSidebarContent,
1058 id: this._id as string,
1059 expression: jsonObject,
1060 rootTitle: rootTitle,
1061 },
Philip Pfaffe939605d2021-06-25 12:20:041062 callback);
Blink Reformat4c46d092018-04-07 15:32:371063 },
1064
Philip Pfaffe6fd04c42021-06-25 12:31:481065 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
1066 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:371067 },
1068
Jan Schefflerd76b4162021-03-29 07:52:161069 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371070 };
1071
Philip Pfaffe6fd04c42021-06-25 12:31:481072 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371073 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:481074
1075 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:371076 }
1077
Philip Pfaffe6fd04c42021-06-25 12:31:481078 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
1079 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:141080 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041081 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:241082 id: this._id,
1083 icon: iconPath,
1084 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:161085 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:141086 });
Jan Schefflerd76b4162021-03-29 07:52:161087 },
Blink Reformat4c46d092018-04-07 15:32:371088 };
1089
Philip Pfaffe1c827212021-06-25 12:33:201090 function Timeline(this: APIImpl.Timeline): void {
Blink Reformat4c46d092018-04-07 15:32:371091 }
1092
Philip Pfaffe1c827212021-06-25 12:33:201093 (Timeline.prototype as Pick<APIImpl.Timeline, 'addTraceProvider'>) = {
1094 addTraceProvider: function(this: APIImpl.Timeline, categoryName: string, categoryTooltip: string):
1095 APIImpl.TraceProvider {
1096 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
1097 extensionServer.sendRequest({
1098 command: PrivateAPI.Commands.AddTraceProvider,
1099 id: id,
1100 categoryName: categoryName,
1101 categoryTooltip: categoryTooltip,
1102 });
1103
1104 return new (Constructor(TraceProvider))(id);
1105 },
Blink Reformat4c46d092018-04-07 15:32:371106 };
1107
Philip Pfaffe1c827212021-06-25 12:33:201108 function TraceSessionImpl(this: APIImpl.TraceSession, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371109 this._id = id;
1110 }
1111
Philip Pfaffe1c827212021-06-25 12:33:201112 (TraceSessionImpl.prototype as Pick<APIImpl.TraceSession, 'complete'>) = {
Kateryna Prokopenko6fa122c2022-05-06 08:54:471113 complete: function(this: APIImpl.TraceSession, url?: Platform.DevToolsPath.UrlString, timeOffset?: number): void {
Philip Pfaffe7523faf2021-06-28 14:23:141114 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041115 command: PrivateAPI.Commands.CompleteTraceSession,
1116 id: this._id,
Kateryna Prokopenko6fa122c2022-05-06 08:54:471117 url: url || Platform.DevToolsPath.EmptyUrlString,
Philip Pfaffe939605d2021-06-25 12:20:041118 timeOffset: timeOffset || 0,
Philip Pfaffe7523faf2021-06-28 14:23:141119 });
Jan Schefflerd76b4162021-03-29 07:52:161120 },
Blink Reformat4c46d092018-04-07 15:32:371121 };
1122
Philip Pfaffe1c827212021-06-25 12:33:201123 function TraceProvider(this: APIImpl.TraceProvider, id: string): void {
1124 function dispatchRecordingStarted(
1125 this: APIImpl.EventSink<APIImpl.Callable>, message: {arguments: unknown[]}): void {
1126 const sessionId = message.arguments[0] as string;
1127
1128 this._fire(new (Constructor(TraceSession))(sessionId));
Blink Reformat4c46d092018-04-07 15:32:371129 }
1130
Philip Pfaffe1c827212021-06-25 12:33:201131 this.onRecordingStarted =
1132 new (Constructor(EventSink))(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
1133
1134 this.onRecordingStopped = new (Constructor(EventSink))(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:371135 }
1136
Philip Pfaffeddf60d22021-06-25 12:35:411137 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
1138 function dispatchResourceEvent(
1139 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
1140 this._fire(new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData));
Blink Reformat4c46d092018-04-07 15:32:371141 }
1142
Philip Pfaffeddf60d22021-06-25 12:35:411143 function dispatchResourceContentEvent(
1144 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
1145 message: {arguments: unknown[]}): void {
1146 this._fire(
1147 new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:371148 }
1149
Philip Pfaffeddf60d22021-06-25 12:35:411150 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:041151 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:411152 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:371153 }
1154
Philip Pfaffeddf60d22021-06-25 12:35:411155 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
1156 reload: function(optionsOrUserAgent: {
1157 ignoreCache?: boolean,
1158 injectedScript?: string,
1159 userAgent?: string,
1160 }): void {
Jan Schefflerd76b4162021-03-29 07:52:161161 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:411162 ignoreCache?: boolean,
1163 injectedScript?: string,
1164 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:161165 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:371166 if (typeof optionsOrUserAgent === 'object') {
1167 options = optionsOrUserAgent;
1168 } else if (typeof optionsOrUserAgent === 'string') {
1169 options = {userAgent: optionsOrUserAgent};
1170 console.warn(
1171 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
1172 'Use inspectedWindow.reload({ userAgent: value}) instead.');
1173 }
Philip Pfaffe939605d2021-06-25 12:20:041174 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:371175 },
1176
Philip Pfaffeddf60d22021-06-25 12:35:411177 eval: function(
1178 expression: string,
1179 evaluateOptions: {contextSecurityOrigin?: string, frameURL?: string, useContentScriptContext?: boolean}):
1180 Object |
Jan Schefflerd76b4162021-03-29 07:52:161181 null {
1182 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411183 function callbackWrapper(result: unknown): void {
1184 const {isError, isException, value} = result as {
1185 isError?: boolean,
1186 isException?: boolean, value: unknown,
1187 };
1188 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141189 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161190 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411191 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161192 }
1193 }
Philip Pfaffe7523faf2021-06-28 14:23:141194 extensionServer.sendRequest(
1195 {
1196 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1197 expression: expression,
1198 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1199 },
1200 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161201 return null;
1202 },
Blink Reformat4c46d092018-04-07 15:32:371203
Philip Pfaffeddf60d22021-06-25 12:35:411204 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1205 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1206 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371207 }
Philip Pfaffeddf60d22021-06-25 12:35:411208 function callbackWrapper(resources: unknown): void {
1209 callback && callback((resources as APIImpl.ResourceData[]).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:371210 }
Philip Pfaffe939605d2021-06-25 12:20:041211 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161212 },
Blink Reformat4c46d092018-04-07 15:32:371213 };
1214
Philip Pfaffe6fd04c42021-06-25 12:31:481215 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Blink Reformat4c46d092018-04-07 15:32:371216 this._url = resourceData.url;
1217 this._type = resourceData.type;
1218 }
1219
Philip Pfaffe6fd04c42021-06-25 12:31:481220 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161221 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481222 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371223 },
1224
Jan Schefflerd76b4162021-03-29 07:52:161225 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481226 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371227 },
1228
Philip Pfaffe6fd04c42021-06-25 12:31:481229 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1230 function callbackWrapper(response: unknown): void {
1231 const {content, encoding} = response as {content: string, encoding: string};
1232 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371233 }
1234
Philip Pfaffe939605d2021-06-25 12:20:041235 extensionServer.sendRequest(
1236 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371237 },
1238
Philip Pfaffe6fd04c42021-06-25 12:31:481239 setContent: function(
1240 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371241 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041242 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481243 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161244 },
Blink Reformat4c46d092018-04-07 15:32:371245 };
1246
Jan Schefflerd76b4162021-03-29 07:52:161247 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371248 return inspectedTabId;
1249 }
1250
Philip Pfaffe7523faf2021-06-28 14:23:141251 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161252 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141253 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521254 // Check if the event should be forwarded.
1255 // This is a workaround for crbug.com/923338.
1256 const focused = document.activeElement;
1257 if (focused) {
1258 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
1259 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1260 return;
1261 }
1262 }
1263
Joel Einbinder67f28fb2018-08-02 00:33:471264 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341265 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471266 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341267 }
1268 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471269 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341270 }
1271 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471272 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341273 }
1274 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471275 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341276 }
Joel Einbinder67f28fb2018-08-02 00:33:471277 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371278 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341279 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371280 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341281 }
Joel Einbinder67f28fb2018-08-02 00:33:471282 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371283 const requestPayload = {
1284 eventType: event.type,
1285 ctrlKey: event.ctrlKey,
1286 altKey: event.altKey,
1287 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471288 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141289 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371290 keyIdentifier: event.keyIdentifier,
1291 key: event.key,
1292 code: event.code,
1293 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161294 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371295 };
1296 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341297 if (!forwardTimer) {
Tim van der Lippe6bcbe0f2022-01-11 13:10:311298 forwardTimer = window.setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341299 }
Blink Reformat4c46d092018-04-07 15:32:371300 }
1301
Jan Schefflerd76b4162021-03-29 07:52:161302 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371303 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141304 extensionServer.sendRequest(
1305 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371306 keyboardEventRequestQueue = [];
1307 }
1308
1309 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371310
Alex Rudenkoa3850822022-05-24 07:34:221311 function ExtensionServerClient(this: APIImpl.ExtensionServerClient, targetWindow: Window): void {
Blink Reformat4c46d092018-04-07 15:32:371312 this._callbacks = {};
1313 this._handlers = {};
1314 this._lastRequestId = 0;
1315 this._lastObjectId = 0;
1316
1317 this.registerHandler('callback', this._onCallback.bind(this));
1318
1319 const channel = new MessageChannel();
1320 this._port = channel.port1;
1321 this._port.addEventListener('message', this._onMessage.bind(this), false);
1322 this._port.start();
1323
Alex Rudenkoa3850822022-05-24 07:34:221324 targetWindow.postMessage('registerExtension', '*', [channel.port2]);
Blink Reformat4c46d092018-04-07 15:32:371325 }
1326
Philip Pfaffe7523faf2021-06-28 14:23:141327 (ExtensionServerClient.prototype as Pick<
1328 APIImpl.ExtensionServerClient,
1329 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1330 '_onCallback'|'_onMessage'>) = {
Philip Pfaffe6ed01262022-07-06 10:41:391331 sendRequest: function<ResponseT>(
Philip Pfaffe7523faf2021-06-28 14:23:141332 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
Philip Pfaffe6ed01262022-07-06 10:41:391333 callback?: (response: ResponseT) => unknown, transfers?: Transferable[]): void {
Philip Pfaffe7523faf2021-06-28 14:23:141334 if (typeof callback === 'function') {
Philip Pfaffe6ed01262022-07-06 10:41:391335 (message as PrivateAPI.ExtensionServerRequestMessage).requestId =
1336 this._registerCallback(callback as (response: unknown) => unknown);
Philip Pfaffe7523faf2021-06-28 14:23:141337 }
1338 // @ts-expect-error
1339 this._port.postMessage(message, transfers);
1340 },
Blink Reformat4c46d092018-04-07 15:32:371341
Philip Pfaffe7523faf2021-06-28 14:23:141342 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241343 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371344 },
1345
Philip Pfaffe7523faf2021-06-28 14:23:141346 registerHandler: function(
1347 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1348 void {
1349 this._handlers[command] = handler;
1350 },
Blink Reformat4c46d092018-04-07 15:32:371351
Philip Pfaffe7523faf2021-06-28 14:23:141352 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371353 delete this._handlers[command];
1354 },
1355
Philip Pfaffe7523faf2021-06-28 14:23:141356 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371357 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1358 },
1359
Philip Pfaffe7523faf2021-06-28 14:23:141360 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371361 const id = ++this._lastRequestId;
1362 this._callbacks[id] = callback;
1363 return id;
1364 },
1365
Philip Pfaffe7523faf2021-06-28 14:23:141366 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371367 if (request.requestId in this._callbacks) {
1368 const callback = this._callbacks[request.requestId];
1369 delete this._callbacks[request.requestId];
1370 callback(request.result);
1371 }
1372 },
1373
Philip Pfaffe7523faf2021-06-28 14:23:141374 _onMessage: function(
1375 this: APIImpl.ExtensionServerClient,
1376 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371377 const request = event.data;
1378 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341379 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371380 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341381 }
Jan Schefflerd76b4162021-03-29 07:52:161382 },
Blink Reformat4c46d092018-04-07 15:32:371383 };
1384
Philip Pfaffe7523faf2021-06-28 14:23:141385 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371386 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341387 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371388 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341389 }
Jan Schefflerd76b4162021-03-29 07:52:161390 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371391 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141392 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371393 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341394 }
1395 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371396 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341397 }
1398 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371399 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341400 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141401 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371402 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341403 } else {
Blink Reformat4c46d092018-04-07 15:32:371404 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341405 }
Blink Reformat4c46d092018-04-07 15:32:371406 }
1407 }
1408
Alex Rudenkoa3850822022-05-24 07:34:221409 const extensionServer = new (Constructor(ExtensionServerClient))(targetWindowForTest || window.parent);
Philip Pfaffe7523faf2021-06-28 14:23:141410
1411 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371412
1413 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1414
1415 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141416 // @ts-expect-error
1417 chrome.devtools!.inspectedWindow = {};
1418 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1419 // @ts-expect-error
1420 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1421 chrome.devtools!.network = coreAPI.network;
1422 chrome.devtools!.panels = coreAPI.panels;
1423 chrome.devtools!.panels.themeName = themeName;
1424 chrome.devtools!.languageServices = coreAPI.languageServices;
Alex Rudenkoa3850822022-05-24 07:34:221425 chrome.devtools!.recorder = coreAPI.recorder;
Blink Reformat4c46d092018-04-07 15:32:371426
1427 // default to expose experimental APIs for now.
1428 if (extensionInfo.exposeExperimentalAPIs !== false) {
1429 chrome.experimental = chrome.experimental || {};
1430 chrome.experimental.devtools = chrome.experimental.devtools || {};
1431
1432 const properties = Object.getOwnPropertyNames(coreAPI);
1433 for (let i = 0; i < properties.length; ++i) {
1434 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341435 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371436 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341437 }
Blink Reformat4c46d092018-04-07 15:32:371438 }
1439 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1440 }
1441
Tim van der Lippe1d6e57a2019-09-30 11:55:341442 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371443 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341444 }
Blink Reformat4c46d092018-04-07 15:32:371445 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121446};
Blink Reformat4c46d092018-04-07 15:32:371447
Jan Schefflerd76b4162021-03-29 07:52:161448self.buildExtensionAPIInjectedScript = function(
1449 extensionInfo: {
1450 startPage: string,
1451 name: string,
1452 exposeExperimentalAPIs: boolean,
1453 },
1454 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141455 testHook:
1456 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1457 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251458 const argumentsJSON =
1459 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341460 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161461 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341462 }
Philip Pfaffe939605d2021-06-25 12:20:041463 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121464 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371465 '})';
Tim van der Lippe29fab472019-08-15 14:46:481466};