blob: f678096684bdd466a023b483ae041b6bad8516ad [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Philip Pfaffe7523faf2021-06-28 14:23:1431import type * as PublicAPI from '../../../extension-api/ExtensionAPI'; // eslint-disable-line rulesdir/es_modules_import
Andrés Olivaresd8507932023-12-27 08:59:2832import type * as Platform from '../../core/platform/platform.js';
Philip Pfaffe4b88c662021-06-25 12:30:4733import type * as HAR from '../har/har.js';
Philip Pfaffe7523faf2021-06-28 14:23:1434
Philip Pfaffeddf60d22021-06-25 12:35:4135/* eslint-disable @typescript-eslint/naming-convention,@typescript-eslint/no-non-null-assertion */
Philip Pfaffe939605d2021-06-25 12:20:0436export namespace PrivateAPI {
37 export namespace Panels {
38 export const enum SearchAction {
39 CancelSearch = 'cancelSearch',
40 PerformSearch = 'performSearch',
41 NextSearchResult = 'nextSearchResult',
42 PreviousSearchResult = 'previousSearchResult',
43 }
Tim van der Lippe1d6e57a2019-09-30 11:55:3444 }
Blink Reformat4c46d092018-04-07 15:32:3745
Philip Pfaffe939605d2021-06-25 12:20:0446 export const enum Events {
47 ButtonClicked = 'button-clicked-',
48 PanelObjectSelected = 'panel-objectSelected-',
49 InspectedURLChanged = 'inspected-url-changed',
50 NetworkRequestFinished = 'network-request-finished',
51 OpenResource = 'open-resource',
52 PanelSearch = 'panel-search-',
Philip Pfaffe939605d2021-06-25 12:20:0453 ResourceAdded = 'resource-added',
54 ResourceContentCommitted = 'resource-content-committed',
55 ViewShown = 'view-shown-',
56 ViewHidden = 'view-hidden,',
Paul Lewisada689f2022-01-11 12:03:4057 ThemeChange = 'host-theme-change',
Philip Pfaffe939605d2021-06-25 12:20:0458 }
Blink Reformat4c46d092018-04-07 15:32:3759
Philip Pfaffe939605d2021-06-25 12:20:0460 export const enum Commands {
61 AddRequestHeaders = 'addRequestHeaders',
Philip Pfaffe939605d2021-06-25 12:20:0462 ApplyStyleSheet = 'applyStyleSheet',
Philip Pfaffe939605d2021-06-25 12:20:0463 CreatePanel = 'createPanel',
64 CreateSidebarPane = 'createSidebarPane',
65 CreateToolbarButton = 'createToolbarButton',
66 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
67 ForwardKeyboardEvent = '_forwardKeyboardEvent',
68 GetHAR = 'getHAR',
69 GetPageResources = 'getPageResources',
70 GetRequestContent = 'getRequestContent',
71 GetResourceContent = 'getResourceContent',
72 OpenResource = 'openResource',
73 Reload = 'Reload',
74 Subscribe = 'subscribe',
75 SetOpenResourceHandler = 'setOpenResourceHandler',
Paul Lewisada689f2022-01-11 12:03:4076 SetThemeChangeHandler = 'setThemeChangeHandler',
Philip Pfaffe939605d2021-06-25 12:20:0477 SetResourceContent = 'setResourceContent',
78 SetSidebarContent = 'setSidebarContent',
79 SetSidebarHeight = 'setSidebarHeight',
80 SetSidebarPage = 'setSidebarPage',
81 ShowPanel = 'showPanel',
82 Unsubscribe = 'unsubscribe',
83 UpdateButton = 'updateButton',
84 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
Philip Pfaffe6ed01262022-07-06 10:41:3985 GetWasmLinearMemory = 'getWasmLinearMemory',
86 GetWasmLocal = 'getWasmLocal',
87 GetWasmGlobal = 'getWasmGlobal',
88 GetWasmOp = 'getWasmOp',
Alex Rudenkoa3850822022-05-24 07:34:2289 RegisterRecorderExtensionPlugin = 'registerRecorderExtensionPlugin',
Alex Rudenko0b8b8882023-01-17 12:21:4990 CreateRecorderView = 'createRecorderView',
91 ShowRecorderView = 'showRecorderView',
Philip Pfaffe939605d2021-06-25 12:20:0492 }
Philip Pfaffeedad8322020-07-20 10:24:2593
Philip Pfaffe939605d2021-06-25 12:20:0494 export const enum LanguageExtensionPluginCommands {
95 AddRawModule = 'addRawModule',
96 RemoveRawModule = 'removeRawModule',
97 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
98 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
99 GetScopeInfo = 'getScopeInfo',
100 ListVariablesInScope = 'listVariablesInScope',
101 GetTypeInfo = 'getTypeInfo',
102 GetFormatter = 'getFormatter',
103 GetInspectableAddress = 'getInspectableAddress',
104 GetFunctionInfo = 'getFunctionInfo',
105 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
106 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
107 GetMappedLines = 'getMappedLines',
Philip Pfaffe6ed01262022-07-06 10:41:39108 FormatValue = 'formatValue',
109 GetProperties = 'getProperties',
110 ReleaseObject = 'releaseObject',
Philip Pfaffe939605d2021-06-25 12:20:04111 }
Benedikt Meurer929fc7c2020-11-20 14:21:06112
Philip Pfaffe939605d2021-06-25 12:20:04113 export const enum LanguageExtensionPluginEvents {
114 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
115 }
Philip Pfaffed662bdf2021-06-25 13:30:32116
Alex Rudenkoa3850822022-05-24 07:34:22117 export const enum RecorderExtensionPluginCommands {
118 Stringify = 'stringify',
Alex Rudenko2aa04c02022-06-01 13:05:20119 StringifyStep = 'stringifyStep',
Alex Rudenko0b8b8882023-01-17 12:21:49120 Replay = 'replay',
Alex Rudenkoa3850822022-05-24 07:34:22121 }
122
123 export const enum RecorderExtensionPluginEvents {
124 UnregisteredRecorderExtensionPlugin = 'unregisteredRecorderExtensionPlugin',
125 }
126
Philip Pfaffed662bdf2021-06-25 13:30:32127 export interface EvaluateOptions {
128 frameURL?: string;
129 useContentScriptContext?: boolean;
130 scriptExecutionContext?: string;
131 }
132
Philip Pfaffed662bdf2021-06-25 13:30:32133 type RegisterLanguageExtensionPluginRequest = {
134 command: Commands.RegisterLanguageExtensionPlugin,
135 pluginName: string,
136 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14137 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32138 };
Alex Rudenko0b8b8882023-01-17 12:21:49139 export type RecordingExtensionPluginCapability = 'export'|'replay';
Alex Rudenkoa3850822022-05-24 07:34:22140 type RegisterRecorderExtensionPluginRequest = {
141 command: Commands.RegisterRecorderExtensionPlugin,
142 pluginName: string,
Alex Rudenko0b8b8882023-01-17 12:21:49143 mediaType?: string, capabilities: RecordingExtensionPluginCapability[], port: MessagePort,
144 };
145 type CreateRecorderViewRequest = {
146 command: Commands.CreateRecorderView,
147 id: string,
148 title: string,
149 pagePath: string,
150 };
151 type ShowRecorderViewRequest = {
152 command: Commands.ShowRecorderView,
153 id: string,
Alex Rudenkoa3850822022-05-24 07:34:22154 };
Philip Pfaffed662bdf2021-06-25 13:30:32155 type SubscribeRequest = {command: Commands.Subscribe, type: string};
156 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
157 type AddRequestHeadersRequest = {
158 command: Commands.AddRequestHeaders,
159 extensionId: string,
160 headers: {[key: string]: string},
161 };
162 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
163 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
164 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
165 type CreateToolbarButtonRequest = {
166 command: Commands.CreateToolbarButton,
167 id: string,
168 icon: string,
169 panel: string,
170 tooltip?: string,
171 disabled?: boolean,
172 };
173 type UpdateButtonRequest =
174 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32175 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
176 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
177 type SetSidebarContentRequest = {
178 command: Commands.SetSidebarContent,
179 id: string,
180 evaluateOnPage?: boolean, expression: string,
181 rootTitle?: string,
182 evaluateOptions?: EvaluateOptions,
183 };
184 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Kateryna Prokopenko9964ab12022-03-23 16:41:49185 type OpenResourceRequest =
186 {command: Commands.OpenResource, url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32187 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
Paul Lewisada689f2022-01-11 12:03:40188 type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32189 type ReloadRequest = {
190 command: Commands.Reload,
191 options: null|{
192 userAgent?: string,
193 injectedScript?: string,
194 ignoreCache?: boolean,
195 },
196 };
197 type EvaluateOnInspectedPageRequest = {
198 command: Commands.EvaluateOnInspectedPage,
199 expression: string,
200 evaluateOptions?: EvaluateOptions,
201 };
202 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
203 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
204 type SetResourceContentRequest =
205 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32206 type ForwardKeyboardEventRequest = {
207 command: Commands.ForwardKeyboardEvent,
208 entries: Array<KeyboardEventInit&{eventType: string}>,
209 };
210 type GetHARRequest = {command: Commands.GetHAR};
Danil Somsikov56210832022-10-05 13:17:58211 type GetPageResourcesRequest = {command: Commands.GetPageResources};
Philip Pfaffe6ed01262022-07-06 10:41:39212 type GetWasmLinearMemoryRequest = {
213 command: Commands.GetWasmLinearMemory,
214 offset: number,
215 length: number,
216 stopId: unknown,
217 };
218 type GetWasmLocalRequest = {
219 command: Commands.GetWasmLocal,
220 local: number,
221 stopId: unknown,
222 };
223 type GetWasmGlobalRequest = {
224 command: Commands.GetWasmGlobal,
225 global: number,
226 stopId: unknown,
227 };
228 type GetWasmOpRequest = {command: Commands.GetWasmOp, op: number, stopId: unknown};
Philip Pfaffed662bdf2021-06-25 13:30:32229
Alex Rudenko0b8b8882023-01-17 12:21:49230 export type ServerRequests = ShowRecorderViewRequest|CreateRecorderViewRequest|RegisterRecorderExtensionPluginRequest|
231 RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|AddRequestHeadersRequest|
232 ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|UpdateButtonRequest|
Andrés Olivaresd8507932023-12-27 08:59:28233 CreateSidebarPaneRequest|SetSidebarHeightRequest|SetSidebarContentRequest|SetSidebarPageRequest|
234 OpenResourceRequest|SetOpenResourceHandlerRequest|SetThemeChangeHandlerRequest|ReloadRequest|
235 EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
236 ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest|GetWasmLinearMemoryRequest|GetWasmLocalRequest|
237 GetWasmGlobalRequest|GetWasmOpRequest;
Philip Pfaffed662bdf2021-06-25 13:30:32238 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32239
240 type AddRawModuleRequest = {
241 method: LanguageExtensionPluginCommands.AddRawModule,
242 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
243 };
244 type SourceLocationToRawLocationRequest = {
245 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
246 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
247 };
248 type RawLocationToSourceLocationRequest = {
249 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
250 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
251 };
252 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
253 type ListVariablesInScopeRequest = {
254 method: LanguageExtensionPluginCommands.ListVariablesInScope,
255 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
256 };
257 type RemoveRawModuleRequest = {
258 method: LanguageExtensionPluginCommands.RemoveRawModule,
259 parameters: {rawModuleId: string},
260 };
Philip Pfaffec5d160e2021-07-20 10:53:32261 type GetFunctionInfoRequest = {
262 method: LanguageExtensionPluginCommands.GetFunctionInfo,
263 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
264 };
265 type GetInlinedFunctionRangesRequest = {
266 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
267 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
268 };
269 type GetInlinedCalleesRangesRequest = {
270 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
271 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
272 };
273 type GetMappedLinesRequest = {
274 method: LanguageExtensionPluginCommands.GetMappedLines,
275 parameters: {rawModuleId: string, sourceFileURL: string},
276 };
Philip Pfaffe6ed01262022-07-06 10:41:39277 type FormatValueRequest = {
278 method: LanguageExtensionPluginCommands.FormatValue,
279 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation, stopId: number},
280 };
281 type GetPropertiesRequest = {
282 method: LanguageExtensionPluginCommands.GetProperties,
283 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
284 };
285 type ReleaseObjectRequest = {
286 method: LanguageExtensionPluginCommands.ReleaseObject,
287 parameters: {objectId: PublicAPI.Chrome.DevTools.RemoteObjectId},
288 };
Philip Pfaffec5d160e2021-07-20 10:53:32289
Philip Pfaffe6ed01262022-07-06 10:41:39290 export type LanguageExtensionRequests =
291 AddRawModuleRequest|SourceLocationToRawLocationRequest|RawLocationToSourceLocationRequest|GetScopeInfoRequest|
Philip Pfaffe8a3d59b2023-05-04 11:26:00292 ListVariablesInScopeRequest|RemoveRawModuleRequest|GetFunctionInfoRequest|GetInlinedFunctionRangesRequest|
Philip Pfaffe6ed01262022-07-06 10:41:39293 GetInlinedCalleesRangesRequest|GetMappedLinesRequest|FormatValueRequest|GetPropertiesRequest|ReleaseObjectRequest;
Alex Rudenkoa3850822022-05-24 07:34:22294
295 type StringifyRequest = {
296 method: RecorderExtensionPluginCommands.Stringify,
297 parameters: {recording: Record<string, unknown>},
298 };
299
Alex Rudenko2aa04c02022-06-01 13:05:20300 type StringifyStepRequest = {
301 method: RecorderExtensionPluginCommands.StringifyStep,
302 parameters: {step: Record<string, unknown>},
303 };
304
Alex Rudenko0b8b8882023-01-17 12:21:49305 type ReplayRequest = {
306 method: RecorderExtensionPluginCommands.Replay,
307 parameters: {recording: Record<string, unknown>},
308 };
309
310 export type RecorderExtensionRequests = StringifyRequest|StringifyStepRequest|ReplayRequest;
Blink Reformat4c46d092018-04-07 15:32:37311}
312
Philip Pfaffe939605d2021-06-25 12:20:04313declare global {
314 interface Window {
315 injectedExtensionAPI:
316 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14317 testHook:
318 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22319 injectedScriptId: number, targetWindow?: Window) => void;
Philip Pfaffe939605d2021-06-25 12:20:04320 buildExtensionAPIInjectedScript(
321 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32322 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14323 chrome: PublicAPI.Chrome.DevTools.Chrome;
324 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04325 }
326}
327
328export type ExtensionDescriptor = {
329 startPage: string,
330 name: string,
331 exposeExperimentalAPIs: boolean,
332 exposeWebInspectorNamespace?: boolean,
Danil Somsikov28cfaf32022-09-27 15:36:55333 allowFileAccess?: boolean,
Philip Pfaffe939605d2021-06-25 12:20:04334};
335
Philip Pfaffe7523faf2021-06-28 14:23:14336namespace APIImpl {
337 export interface InspectorExtensionAPI {
338 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Alex Rudenkoa3850822022-05-24 07:34:22339 recorder: PublicAPI.Chrome.DevTools.RecorderExtensions;
Philip Pfaffe7523faf2021-06-28 14:23:14340 network: PublicAPI.Chrome.DevTools.Network;
341 panels: PublicAPI.Chrome.DevTools.Panels;
342 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
343 }
344
345 export interface ExtensionServerClient {
346 _callbacks: {[key: string]: (response: unknown) => unknown};
347 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
348 _lastRequestId: number;
349 _lastObjectId: number;
350 _port: MessagePort;
351
352 _onCallback(request: unknown): void;
353 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
354 _registerCallback(callback: (response: unknown) => unknown): number;
355 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
356 unregisterHandler(command: string): void;
357 hasHandler(command: string): boolean;
Philip Pfaffe6ed01262022-07-06 10:41:39358 sendRequest<ResponseT>(
359 request: PrivateAPI.ServerRequests, callback?: ((response: ResponseT) => unknown), transfers?: unknown[]): void;
Philip Pfaffe7523faf2021-06-28 14:23:14360 nextObjectId(): string;
361 }
362
Benedikt Meurercfc8cd62024-01-17 10:08:28363 export type Callable = (...args: any[]) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14364
365 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
366 _type: string;
367 _listeners: ListenerT[];
368 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
369
370 _fire(..._vararg: Parameters<ListenerT>): void;
371 _dispatch(request: {arguments: unknown[]}): void;
372 }
Philip Pfaffe4b88c662021-06-25 12:30:47373
374 export interface Network extends PublicAPI.Chrome.DevTools.Network {
375 addRequestHeaders(headers: {[key: string]: string}): void;
376 }
377
378 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
379 _id: number;
380 }
Philip Pfaffe6fd04c42021-06-25 12:31:48381
382 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
383 get SearchAction(): {[key: string]: string};
384 applyStyleSheet(styleSheet: string): void;
385 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
386 void;
Paul Lewisada689f2022-01-11 12:03:40387 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48388 }
389
390 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
391 _id: string|null;
392 }
393
394 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
395 setExpression(
396 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
397 callback?: () => unknown): void;
398 }
399
400 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
401 _hostPanelName: string;
402 }
403
404 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
405 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
406 }
407
Alex Rudenkoa3850822022-05-24 07:34:22408 export interface RecorderExtensions extends PublicAPI.Chrome.DevTools.RecorderExtensions {
409 _plugins: Map<PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, MessagePort>;
410 }
411
Philip Pfaffe6fd04c42021-06-25 12:31:48412 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
413 show(): void;
414 }
415
Alex Rudenko0b8b8882023-01-17 12:21:49416 export interface RecorderView extends ExtensionView, PublicAPI.Chrome.DevTools.RecorderView {}
417
Philip Pfaffe6fd04c42021-06-25 12:31:48418 export interface Button extends PublicAPI.Chrome.DevTools.Button {
419 _id: string;
420 }
421
Philip Pfaffe6fd04c42021-06-25 12:31:48422 export type ResourceData = {url: string, type: string};
423 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
424 _type: string;
425 _url: string;
426
427 get type(): string;
428 }
Philip Pfaffe7523faf2021-06-28 14:23:14429}
Philip Pfaffe939605d2021-06-25 12:20:04430
Tim van der Lippe226fc222019-10-10 12:17:12431self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14432 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
433 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Alex Rudenkoa3850822022-05-24 07:34:22434 injectedScriptId: number, targetWindowForTest?: Window): void {
Jan Schefflerd76b4162021-03-29 07:52:16435 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37436 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16437
Blink Reformat4c46d092018-04-07 15:32:37438 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34439 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37440 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34441 }
Blink Reformat4c46d092018-04-07 15:32:37442 let userAction = false;
Alex Rudenko0b8b8882023-01-17 12:21:49443 let userRecorderAction = false;
Blink Reformat4c46d092018-04-07 15:32:37444
445 // Here and below, all constructors are private to API implementation.
446 // For a public type Foo, if internal fields are present, these are on
447 // a private FooImpl type, an instance of FooImpl is used in a closure
448 // by Foo consutrctor to re-bind publicly exported members to an instance
449 // of Foo.
450
Philip Pfaffe7523faf2021-06-28 14:23:14451 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
452 this: APIImpl.EventSink<ListenerT>, type: string,
453 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37454 this._type = type;
455 this._listeners = [];
456 this._customDispatch = customDispatch;
457 }
458
459 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14460 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
461 void {
462 if (typeof callback !== 'function') {
463 throw 'addListener: callback is not a function';
464 }
465 if (this._listeners.length === 0) {
466 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
467 }
468 this._listeners.push(callback);
469 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
470 },
Blink Reformat4c46d092018-04-07 15:32:37471
Philip Pfaffe7523faf2021-06-28 14:23:14472 removeListener: function<ListenerT extends APIImpl.Callable>(
473 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37474 const listeners = this._listeners;
475
476 for (let i = 0; i < listeners.length; ++i) {
477 if (listeners[i] === callback) {
478 listeners.splice(i, 1);
479 break;
480 }
481 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34482 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04483 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34484 }
Blink Reformat4c46d092018-04-07 15:32:37485 },
486
Philip Pfaffe7523faf2021-06-28 14:23:14487 _fire: function<ListenerT extends APIImpl.Callable>(
488 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37489 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34490 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14491 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34492 }
Blink Reformat4c46d092018-04-07 15:32:37493 },
494
Philip Pfaffe7523faf2021-06-28 14:23:14495 _dispatch: function<ListenerT extends APIImpl.Callable>(
496 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34497 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37498 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34499 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14500 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34501 }
Jan Schefflerd76b4162021-03-29 07:52:16502 },
Blink Reformat4c46d092018-04-07 15:32:37503 };
504
Philip Pfaffe7523faf2021-06-28 14:23:14505 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
506 ThisParameterType<NewT> {
507 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
508 }
509
Philip Pfaffe7523faf2021-06-28 14:23:14510 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41511 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48512 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47513 this.network = new (Constructor(Network))();
Philip Pfaffec5d160e2021-07-20 10:53:32514 this.languageServices = new (Constructor(LanguageServicesAPI))();
Alex Rudenkoa3850822022-05-24 07:34:22515 this.recorder = new (Constructor(RecorderServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37516 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
517 }
518
Philip Pfaffe4b88c662021-06-25 12:30:47519 function Network(this: APIImpl.Network): void {
520 function dispatchRequestEvent(
521 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
522 message: {arguments: unknown[]}): void {
523 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
524
525 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37526 this._fire(request);
527 }
Philip Pfaffe4b88c662021-06-25 12:30:47528
529 this.onRequestFinished =
530 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37531 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47532
533 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37534 }
535
Philip Pfaffe4b88c662021-06-25 12:30:47536 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
537 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
538 function callbackWrapper(response: unknown): void {
539 const result =
540 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37541 const entries = (result && result.entries) || [];
542 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47543 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37544 delete entries[i]._requestId;
545 }
Philip Pfaffe4b88c662021-06-25 12:30:47546 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37547 }
Philip Pfaffe939605d2021-06-25 12:20:04548 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37549 },
550
Philip Pfaffe4b88c662021-06-25 12:30:47551 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37552 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04553 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16554 },
Blink Reformat4c46d092018-04-07 15:32:37555 };
556
Philip Pfaffe4b88c662021-06-25 12:30:47557 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37558 this._id = id;
559 }
560
Philip Pfaffe4b88c662021-06-25 12:30:47561 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
562 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
563 function callbackWrapper(response: unknown): void {
564 const {content, encoding} = response as {content: string, encoding: string};
565 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37566 }
Philip Pfaffe939605d2021-06-25 12:20:04567 extensionServer.sendRequest(
568 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16569 },
Blink Reformat4c46d092018-04-07 15:32:37570 };
571
Philip Pfaffe6fd04c42021-06-25 12:31:48572 function Panels(this: APIImpl.Panels): void {
573 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37574 elements: new ElementsPanel(),
575 sources: new SourcesPanel(),
576 };
577
Philip Pfaffe6fd04c42021-06-25 12:31:48578 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37579 return panels[name];
580 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34581 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12582 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34583 }
Philip Pfaffe6fd04c42021-06-25 12:31:48584 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04585 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37586 };
587 }
588
Paul Lewisada689f2022-01-11 12:03:40589 (Panels.prototype as
590 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48591 create: function(
592 title: string, icon: string, page: string,
593 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37594 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48595 extensionServer.sendRequest(
596 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37597 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37598 },
599
Philip Pfaffe6fd04c42021-06-25 12:31:48600 setOpenResourceHandler: function(
601 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04602 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37603
Philip Pfaffe6fd04c42021-06-25 12:31:48604 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37605 // Allow the panel to show itself when handling the event.
606 userAction = true;
607 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48608 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
Danil Somsikov56210832022-10-05 13:17:58609 if (canAccessResource(resource)) {
610 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
611 }
Blink Reformat4c46d092018-04-07 15:32:37612 } finally {
613 userAction = false;
614 }
615 }
616
Tim van der Lippe1d6e57a2019-09-30 11:55:34617 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04618 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34619 } else {
Philip Pfaffe939605d2021-06-25 12:20:04620 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34621 }
Blink Reformat4c46d092018-04-07 15:32:37622
623 // 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:34624 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04625 extensionServer.sendRequest(
626 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34627 }
Blink Reformat4c46d092018-04-07 15:32:37628 },
629
Paul Lewisada689f2022-01-11 12:03:40630 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
631 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
632
633 function callbackWrapper(message: unknown): void {
634 const {themeName} = message as {themeName: string};
635 chrome.devtools.panels.themeName = themeName;
636 callback.call(null, themeName);
637 }
638
639 if (!callback) {
640 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
641 } else {
642 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
643 }
644
645 // Only send command if we either removed an existing handler or added handler and had none before.
646 if (hadHandler === !callback) {
647 extensionServer.sendRequest(
648 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
649 }
650 },
651
Philip Pfaffe140e5432021-09-13 16:34:23652 openResource: function(
Kateryna Prokopenko9964ab12022-03-23 16:41:49653 url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber?: number,
654 _callback?: (response: unknown) => unknown): void {
Philip Pfaffe140e5432021-09-13 16:34:23655 const callbackArg = extractCallbackArgument(arguments);
656 // Handle older API:
657 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
658 extensionServer.sendRequest(
659 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37660 },
661
Philip Pfaffe6fd04c42021-06-25 12:31:48662 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04663 return {
664 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
665 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
666 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
667 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
668 };
Jan Schefflerd76b4162021-03-29 07:52:16669 },
Blink Reformat4c46d092018-04-07 15:32:37670 };
671
Philip Pfaffe6fd04c42021-06-25 12:31:48672 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37673 this._id = id;
674
Philip Pfaffe6fd04c42021-06-25 12:31:48675 function dispatchShowEvent(
676 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37677 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34678 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37679 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34680 } else {
Blink Reformat4c46d092018-04-07 15:32:37681 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34682 }
Blink Reformat4c46d092018-04-07 15:32:37683 }
684
685 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48686 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
687
688 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37689 }
690 }
691
Philip Pfaffe6fd04c42021-06-25 12:31:48692 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37693 ExtensionViewImpl.call(this, null);
694 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48695
696 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37697 }
698
Philip Pfaffe6fd04c42021-06-25 12:31:48699 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
700 {__proto__: APIImpl.ExtensionView}) = {
701 createSidebarPane: function(
702 this: APIImpl.PanelWithSidebar, title: string,
703 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37704 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16705 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48706 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37707 }
Philip Pfaffe7523faf2021-06-28 14:23:14708 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48709 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14710 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37711 },
712
Jan Schefflerd76b4162021-03-29 07:52:16713 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37714 };
715
Alex Rudenkoa3850822022-05-24 07:34:22716 function RecorderServicesAPIImpl(this: APIImpl.RecorderExtensions): void {
717 this._plugins = new Map();
718 }
719
Alex Rudenko0b8b8882023-01-17 12:21:49720 async function registerRecorderExtensionPluginImpl(
721 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, pluginName: string,
722 mediaType?: string): Promise<void> {
723 if (this._plugins.has(plugin)) {
724 throw new Error(`Tried to register plugin '${pluginName}' twice`);
725 }
726 const channel = new MessageChannel();
727 const port = channel.port1;
728 this._plugins.set(plugin, port);
729 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.RecorderExtensionRequests>): void => {
730 const {requestId} = data;
731 dispatchMethodCall(data)
732 .then(result => port.postMessage({requestId, result}))
733 .catch(error => port.postMessage({requestId, error: {message: error.message}}));
734 };
735
736 async function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
737 switch (request.method) {
738 case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
739 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionExportPlugin)
740 .stringify(request.parameters.recording);
741 case PrivateAPI.RecorderExtensionPluginCommands.StringifyStep:
742 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionExportPlugin)
743 .stringifyStep(request.parameters.step);
744 case PrivateAPI.RecorderExtensionPluginCommands.Replay:
745 try {
746 userAction = true;
747 userRecorderAction = true;
748 return (plugin as PublicAPI.Chrome.DevTools.RecorderExtensionReplayPlugin)
749 .replay(request.parameters.recording);
750 } finally {
751 userAction = false;
752 userRecorderAction = false;
753 }
754 default:
755 // @ts-expect-error
756 throw new Error(`'${request.method}' is not recognized`);
Alex Rudenkoa3850822022-05-24 07:34:22757 }
Alex Rudenko0b8b8882023-01-17 12:21:49758 }
Alex Rudenkoa3850822022-05-24 07:34:22759
Alex Rudenko0b8b8882023-01-17 12:21:49760 const capabilities: PrivateAPI.RecordingExtensionPluginCapability[] = [];
Alex Rudenkoa3850822022-05-24 07:34:22761
Alex Rudenko0b8b8882023-01-17 12:21:49762 if ('stringify' in plugin && 'stringifyStep' in plugin) {
763 capabilities.push('export');
764 }
Alex Rudenkoa3850822022-05-24 07:34:22765
Alex Rudenko0b8b8882023-01-17 12:21:49766 if ('replay' in plugin) {
767 capabilities.push('replay');
768 }
769
770 await new Promise<void>(resolve => {
771 extensionServer.sendRequest(
772 {
773 command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
774 pluginName,
775 mediaType,
776 capabilities,
777 port: channel.port2,
778 },
779 () => resolve(), [channel.port2]);
780 });
781 }
782
783 (RecorderServicesAPIImpl.prototype as Pick<
784 APIImpl.RecorderExtensions,
785 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'|'createView'>) = {
786 registerRecorderExtensionPlugin: registerRecorderExtensionPluginImpl,
Alex Rudenkoa3850822022-05-24 07:34:22787 unregisterRecorderExtensionPlugin: async function(
788 this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin): Promise<void> {
789 const port = this._plugins.get(plugin);
790 if (!port) {
791 throw new Error('Tried to unregister a plugin that was not previously registered');
792 }
793 this._plugins.delete(plugin);
794 port.postMessage({event: PrivateAPI.RecorderExtensionPluginEvents.UnregisteredRecorderExtensionPlugin});
795 port.close();
796 },
Alex Rudenko0b8b8882023-01-17 12:21:49797 createView: async function(this: APIImpl.RecorderExtensions, title: string, pagePath: string):
798 Promise<PublicAPI.Chrome.DevTools.RecorderView> {
799 const id = 'recorder-extension-view-' + extensionServer.nextObjectId();
800 await new Promise(resolve => {
801 extensionServer.sendRequest(
802 {command: PrivateAPI.Commands.CreateRecorderView, id, title, pagePath}, resolve);
803 });
804 return new (Constructor(RecorderView))(id);
805 },
Alex Rudenkoa3850822022-05-24 07:34:22806 };
807
Philip Pfaffec5d160e2021-07-20 10:53:32808 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25809 this._plugins = new Map();
810 }
811
Philip Pfaffe6ed01262022-07-06 10:41:39812 (LanguageServicesAPIImpl.prototype as PublicAPI.Chrome.DevTools.LanguageExtensions) = {
Philip Pfaffed662bdf2021-06-25 13:30:32813 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32814 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
815 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
816 if (this._plugins.has(plugin)) {
817 throw new Error(`Tried to register plugin '${pluginName}' twice`);
818 }
819 const channel = new MessageChannel();
820 const port = channel.port1;
821 this._plugins.set(plugin, port);
822 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
823 const {requestId} = data;
824 console.time(`${requestId}: ${data.method}`);
825 dispatchMethodCall(data)
826 .then(result => port.postMessage({requestId, result}))
827 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
828 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
829 };
Philip Pfaffeedad8322020-07-20 10:24:25830
Philip Pfaffec5d160e2021-07-20 10:53:32831 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
832 switch (request.method) {
833 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
834 return plugin.addRawModule(
835 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
836 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
837 return plugin.removeRawModule(request.parameters.rawModuleId);
838 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
839 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
840 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
841 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
842 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
843 return plugin.getScopeInfo(request.parameters.type);
844 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
845 return plugin.listVariablesInScope(request.parameters.rawLocation);
Philip Pfaffec5d160e2021-07-20 10:53:32846 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
847 return plugin.getFunctionInfo(request.parameters.rawLocation);
848 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
849 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
850 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
851 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
852 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
853 if ('getMappedLines' in plugin) {
854 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
855 }
856 return Promise.resolve(undefined);
Philip Pfaffe6ed01262022-07-06 10:41:39857 case PrivateAPI.LanguageExtensionPluginCommands.FormatValue:
Philip Pfaffe889342a2022-07-08 06:18:47858 if ('evaluate' in plugin && plugin.evaluate) {
Philip Pfaffe6ed01262022-07-06 10:41:39859 return plugin.evaluate(
860 request.parameters.expression, request.parameters.context, request.parameters.stopId);
861 }
862 return Promise.resolve(undefined);
863 case PrivateAPI.LanguageExtensionPluginCommands.GetProperties:
Philip Pfaffe889342a2022-07-08 06:18:47864 if ('getProperties' in plugin && plugin.getProperties) {
Philip Pfaffe6ed01262022-07-06 10:41:39865 return plugin.getProperties(request.parameters.objectId);
866 }
Philip Pfaffe889342a2022-07-08 06:18:47867 if (!('evaluate' in plugin &&
868 plugin.evaluate)) { // If evalute is defined but the remote objects methods aren't, that's a bug
Philip Pfaffe6ed01262022-07-06 10:41:39869 return Promise.resolve(undefined);
870 }
871 break;
872 case PrivateAPI.LanguageExtensionPluginCommands.ReleaseObject:
Philip Pfaffe889342a2022-07-08 06:18:47873 if ('releaseObject' in plugin && plugin.releaseObject) {
Philip Pfaffe6ed01262022-07-06 10:41:39874 return plugin.releaseObject(request.parameters.objectId);
875 }
Philip Pfaffe6ed01262022-07-06 10:41:39876 break;
Philip Pfaffec5d160e2021-07-20 10:53:32877 }
Philip Pfaffec5d160e2021-07-20 10:53:32878 throw new Error(`Unknown language plugin method ${request.method}`);
879 }
Philip Pfaffeedad8322020-07-20 10:24:25880
Philip Pfaffec5d160e2021-07-20 10:53:32881 await new Promise<void>(resolve => {
882 extensionServer.sendRequest(
883 {
884 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
885 pluginName,
886 port: channel.port2,
887 supportedScriptTypes,
888 },
889 () => resolve(), [channel.port2]);
890 });
891 },
Benedikt Meurer929fc7c2020-11-20 14:21:06892
Philip Pfaffec5d160e2021-07-20 10:53:32893 unregisterLanguageExtensionPlugin: async function(
894 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06895 const port = this._plugins.get(plugin);
896 if (!port) {
897 throw new Error('Tried to unregister a plugin that was not previously registered');
898 }
899 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04900 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06901 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16902 },
Philip Pfaffe6ed01262022-07-06 10:41:39903
904 getWasmLinearMemory: async function(
905 this: APIImpl.LanguageExtensions, offset: number, length: number, stopId: number): Promise<ArrayBuffer> {
906 const result = await new Promise(
907 resolve => extensionServer.sendRequest(
908 {command: PrivateAPI.Commands.GetWasmLinearMemory, offset, length, stopId}, resolve));
909 if (Array.isArray(result)) {
910 return new Uint8Array(result).buffer;
911 }
912 return new ArrayBuffer(0);
913 },
914 getWasmLocal: async function(
915 this: APIImpl.LanguageExtensions, local: number, stopId: number): Promise<PublicAPI.Chrome.DevTools.WasmValue> {
916 return new Promise(
917 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmLocal, local, stopId}, resolve));
918 },
919 getWasmGlobal: async function(this: APIImpl.LanguageExtensions, global: number, stopId: number):
920 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
921 return new Promise(
922 resolve =>
923 extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmGlobal, global, stopId}, resolve));
924 },
925 getWasmOp: async function(this: APIImpl.LanguageExtensions, op: number, stopId: number):
926 Promise<PublicAPI.Chrome.DevTools.WasmValue> {
927 return new Promise(
928 resolve => extensionServer.sendRequest({command: PrivateAPI.Commands.GetWasmOp, op, stopId}, resolve));
929 },
Philip Pfaffeedad8322020-07-20 10:24:25930 };
931
Philip Pfaffe7523faf2021-06-28 14:23:14932 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
933 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
934 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37935 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14936 implConstructor.apply(impl, args);
937 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37938 };
939 }
940
Philip Pfaffe7523faf2021-06-28 14:23:14941 // eslint-disable-next-line @typescript-eslint/no-explicit-any
942 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37943 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14944 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37945 if (!warningGiven) {
946 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
947 warningGiven = true;
948 }
949 return object[newName];
950 }
951 object.__defineGetter__(oldName, getter);
952 }
953
Philip Pfaffe7523faf2021-06-28 14:23:14954 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37955 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14956 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37957 }
958
Philip Pfaffeedad8322020-07-20 10:24:25959 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Alex Rudenkoa3850822022-05-24 07:34:22960 const RecorderServicesAPI = declareInterfaceClass(RecorderServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37961 const Button = declareInterfaceClass(ButtonImpl);
962 const EventSink = declareInterfaceClass(EventSinkImpl);
963 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
Alex Rudenko0b8b8882023-01-17 12:21:49964 const RecorderView = declareInterfaceClass(RecorderViewImpl);
Blink Reformat4c46d092018-04-07 15:32:37965 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12966 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37967 const Request = declareInterfaceClass(RequestImpl);
968 const Resource = declareInterfaceClass(ResourceImpl);
Blink Reformat4c46d092018-04-07 15:32:37969
Philip Pfaffe6fd04c42021-06-25 12:31:48970 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12971 constructor() {
972 super('elements');
973 }
Blink Reformat4c46d092018-04-07 15:32:37974 }
975
Philip Pfaffe6fd04c42021-06-25 12:31:48976 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12977 constructor() {
978 super('sources');
979 }
Blink Reformat4c46d092018-04-07 15:32:37980 }
981
Philip Pfaffe6fd04c42021-06-25 12:31:48982 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37983 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48984
985 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37986 }
987
Philip Pfaffe6fd04c42021-06-25 12:31:48988 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
989 {__proto__: APIImpl.ExtensionView}) = {
990 createStatusBarButton: function(
991 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
992 PublicAPI.Chrome.DevTools.Button {
993 const id = 'button-' + extensionServer.nextObjectId();
994 extensionServer.sendRequest({
995 command: PrivateAPI.Commands.CreateToolbarButton,
996 panel: this._id as string,
997 id: id,
998 icon: iconPath,
999 tooltip: tooltipText,
1000 disabled: Boolean(disabled),
1001 });
Blink Reformat4c46d092018-04-07 15:32:371002
Philip Pfaffe6fd04c42021-06-25 12:31:481003 return new (Constructor(Button))(id);
1004 },
1005
1006 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:341007 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:371008 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341009 }
Blink Reformat4c46d092018-04-07 15:32:371010
Philip Pfaffe6fd04c42021-06-25 12:31:481011 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:371012 },
1013
Jan Schefflerd76b4162021-03-29 07:52:161014 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371015 };
1016
Alex Rudenko0b8b8882023-01-17 12:21:491017 function RecorderViewImpl(this: APIImpl.RecorderView, id: string): void {
1018 ExtensionViewImpl.call(this, id);
1019 }
1020
1021 (RecorderViewImpl.prototype as Pick<APIImpl.RecorderView, 'show'>& {__proto__: APIImpl.ExtensionView}) = {
1022 show: function(this: APIImpl.RecorderView): void {
1023 if (!userAction || !userRecorderAction) {
1024 return;
1025 }
1026
1027 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowRecorderView, id: this._id as string});
1028 },
1029
1030 __proto__: ExtensionViewImpl.prototype,
1031 };
1032
Philip Pfaffe6fd04c42021-06-25 12:31:481033 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371034 ExtensionViewImpl.call(this, id);
1035 }
1036
Philip Pfaffe6fd04c42021-06-25 12:31:481037 (ExtensionSidebarPaneImpl.prototype as
1038 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
1039 {__proto__: APIImpl.ExtensionView}) = {
1040 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
1041 extensionServer.sendRequest(
1042 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:371043 },
1044
Philip Pfaffe6fd04c42021-06-25 12:31:481045 setExpression: function(
1046 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
1047 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:141048 extensionServer.sendRequest(
1049 {
1050 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:481051 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:141052 expression: expression,
1053 rootTitle: rootTitle,
1054 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:481055 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:141056 },
1057 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:371058 },
1059
Philip Pfaffe6fd04c42021-06-25 12:31:481060 setObject: function(
1061 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371062 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:481063 {
1064 command: PrivateAPI.Commands.SetSidebarContent,
1065 id: this._id as string,
1066 expression: jsonObject,
1067 rootTitle: rootTitle,
1068 },
Philip Pfaffe939605d2021-06-25 12:20:041069 callback);
Blink Reformat4c46d092018-04-07 15:32:371070 },
1071
Philip Pfaffe6fd04c42021-06-25 12:31:481072 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
1073 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:371074 },
1075
Jan Schefflerd76b4162021-03-29 07:52:161076 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:371077 };
1078
Philip Pfaffe6fd04c42021-06-25 12:31:481079 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:371080 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:481081
1082 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:371083 }
1084
Philip Pfaffe6fd04c42021-06-25 12:31:481085 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
1086 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:141087 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:041088 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:241089 id: this._id,
1090 icon: iconPath,
1091 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:161092 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:141093 });
Jan Schefflerd76b4162021-03-29 07:52:161094 },
Blink Reformat4c46d092018-04-07 15:32:371095 };
1096
Danil Somsikov56210832022-10-05 13:17:581097 function canAccessResource(resource: APIImpl.ResourceData): boolean {
Danil Somsikovb2e37052023-03-24 12:50:431098 try {
1099 return extensionInfo.allowFileAccess || (new URL(resource.url)).protocol !== 'file:';
1100 } catch (e) {
1101 return false;
1102 }
Danil Somsikov56210832022-10-05 13:17:581103 }
1104
Philip Pfaffeddf60d22021-06-25 12:35:411105 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
1106 function dispatchResourceEvent(
1107 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581108 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1109 if (!canAccessResource(resourceData)) {
1110 return;
1111 }
1112 this._fire(new (Constructor(Resource))(resourceData));
Blink Reformat4c46d092018-04-07 15:32:371113 }
1114
Philip Pfaffeddf60d22021-06-25 12:35:411115 function dispatchResourceContentEvent(
1116 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
1117 message: {arguments: unknown[]}): void {
Danil Somsikov56210832022-10-05 13:17:581118 const resourceData = message.arguments[0] as APIImpl.ResourceData;
1119 if (!canAccessResource(resourceData)) {
1120 return;
1121 }
1122 this._fire(new (Constructor(Resource))(resourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:371123 }
1124
Philip Pfaffeddf60d22021-06-25 12:35:411125 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:041126 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:411127 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:371128 }
1129
Philip Pfaffeddf60d22021-06-25 12:35:411130 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
1131 reload: function(optionsOrUserAgent: {
1132 ignoreCache?: boolean,
1133 injectedScript?: string,
1134 userAgent?: string,
1135 }): void {
Jan Schefflerd76b4162021-03-29 07:52:161136 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:411137 ignoreCache?: boolean,
1138 injectedScript?: string,
1139 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:161140 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:371141 if (typeof optionsOrUserAgent === 'object') {
1142 options = optionsOrUserAgent;
1143 } else if (typeof optionsOrUserAgent === 'string') {
1144 options = {userAgent: optionsOrUserAgent};
1145 console.warn(
1146 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
1147 'Use inspectedWindow.reload({ userAgent: value}) instead.');
1148 }
Philip Pfaffe939605d2021-06-25 12:20:041149 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:371150 },
1151
Philip Pfaffeddf60d22021-06-25 12:35:411152 eval: function(
1153 expression: string,
Benedikt Meurer6428bce2023-09-15 10:47:331154 evaluateOptions: {scriptExecutionContext?: string, frameURL?: string, useContentScriptContext?: boolean}):
Philip Pfaffeddf60d22021-06-25 12:35:411155 Object |
Jan Schefflerd76b4162021-03-29 07:52:161156 null {
1157 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411158 function callbackWrapper(result: unknown): void {
1159 const {isError, isException, value} = result as {
1160 isError?: boolean,
1161 isException?: boolean, value: unknown,
1162 };
1163 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141164 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161165 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411166 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161167 }
1168 }
Philip Pfaffe7523faf2021-06-28 14:23:141169 extensionServer.sendRequest(
1170 {
1171 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1172 expression: expression,
1173 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1174 },
1175 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161176 return null;
1177 },
Blink Reformat4c46d092018-04-07 15:32:371178
Philip Pfaffeddf60d22021-06-25 12:35:411179 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1180 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1181 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371182 }
Philip Pfaffeddf60d22021-06-25 12:35:411183 function callbackWrapper(resources: unknown): void {
Danil Somsikovf8035f02023-07-17 14:05:411184 callback && callback((resources as APIImpl.ResourceData[]).filter(canAccessResource).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:371185 }
Danil Somsikov56210832022-10-05 13:17:581186 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161187 },
Blink Reformat4c46d092018-04-07 15:32:371188 };
1189
Philip Pfaffe6fd04c42021-06-25 12:31:481190 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Danil Somsikovf8035f02023-07-17 14:05:411191 if (!canAccessResource(resourceData)) {
Danil Somsikov56210832022-10-05 13:17:581192 throw new Error('Resource access not allowed');
1193 }
Blink Reformat4c46d092018-04-07 15:32:371194 this._url = resourceData.url;
1195 this._type = resourceData.type;
1196 }
1197
Philip Pfaffe6fd04c42021-06-25 12:31:481198 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161199 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481200 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371201 },
1202
Jan Schefflerd76b4162021-03-29 07:52:161203 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481204 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371205 },
1206
Philip Pfaffe6fd04c42021-06-25 12:31:481207 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1208 function callbackWrapper(response: unknown): void {
1209 const {content, encoding} = response as {content: string, encoding: string};
1210 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371211 }
1212
Philip Pfaffe939605d2021-06-25 12:20:041213 extensionServer.sendRequest(
1214 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371215 },
1216
Philip Pfaffe6fd04c42021-06-25 12:31:481217 setContent: function(
1218 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371219 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041220 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481221 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161222 },
Blink Reformat4c46d092018-04-07 15:32:371223 };
1224
Jan Schefflerd76b4162021-03-29 07:52:161225 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371226 return inspectedTabId;
1227 }
1228
Philip Pfaffe7523faf2021-06-28 14:23:141229 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161230 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141231 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521232 // Check if the event should be forwarded.
1233 // This is a workaround for crbug.com/923338.
1234 const focused = document.activeElement;
1235 if (focused) {
Benedikt Meurer5d508f62022-12-06 14:37:381236 const isInput =
1237 focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA' || (focused as HTMLElement).isContentEditable;
Jan Schefflere7d7bb12019-10-24 09:18:521238 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1239 return;
1240 }
1241 }
1242
Joel Einbinder67f28fb2018-08-02 00:33:471243 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341244 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471245 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341246 }
1247 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471248 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341249 }
1250 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471251 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341252 }
1253 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471254 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341255 }
Joel Einbinder67f28fb2018-08-02 00:33:471256 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371257 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341258 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371259 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341260 }
Joel Einbinder67f28fb2018-08-02 00:33:471261 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371262 const requestPayload = {
1263 eventType: event.type,
1264 ctrlKey: event.ctrlKey,
1265 altKey: event.altKey,
1266 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471267 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141268 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371269 keyIdentifier: event.keyIdentifier,
1270 key: event.key,
1271 code: event.code,
1272 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161273 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371274 };
1275 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341276 if (!forwardTimer) {
Tim van der Lippe6bcbe0f2022-01-11 13:10:311277 forwardTimer = window.setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341278 }
Blink Reformat4c46d092018-04-07 15:32:371279 }
1280
Jan Schefflerd76b4162021-03-29 07:52:161281 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371282 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141283 extensionServer.sendRequest(
1284 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371285 keyboardEventRequestQueue = [];
1286 }
1287
1288 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371289
Alex Rudenkoa3850822022-05-24 07:34:221290 function ExtensionServerClient(this: APIImpl.ExtensionServerClient, targetWindow: Window): void {
Blink Reformat4c46d092018-04-07 15:32:371291 this._callbacks = {};
1292 this._handlers = {};
1293 this._lastRequestId = 0;
1294 this._lastObjectId = 0;
1295
1296 this.registerHandler('callback', this._onCallback.bind(this));
1297
1298 const channel = new MessageChannel();
1299 this._port = channel.port1;
1300 this._port.addEventListener('message', this._onMessage.bind(this), false);
1301 this._port.start();
1302
Alex Rudenkoa3850822022-05-24 07:34:221303 targetWindow.postMessage('registerExtension', '*', [channel.port2]);
Blink Reformat4c46d092018-04-07 15:32:371304 }
1305
Philip Pfaffe7523faf2021-06-28 14:23:141306 (ExtensionServerClient.prototype as Pick<
1307 APIImpl.ExtensionServerClient,
1308 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1309 '_onCallback'|'_onMessage'>) = {
Philip Pfaffe6ed01262022-07-06 10:41:391310 sendRequest: function<ResponseT>(
Philip Pfaffe7523faf2021-06-28 14:23:141311 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
Philip Pfaffe6ed01262022-07-06 10:41:391312 callback?: (response: ResponseT) => unknown, transfers?: Transferable[]): void {
Philip Pfaffe7523faf2021-06-28 14:23:141313 if (typeof callback === 'function') {
Philip Pfaffe6ed01262022-07-06 10:41:391314 (message as PrivateAPI.ExtensionServerRequestMessage).requestId =
1315 this._registerCallback(callback as (response: unknown) => unknown);
Philip Pfaffe7523faf2021-06-28 14:23:141316 }
1317 // @ts-expect-error
1318 this._port.postMessage(message, transfers);
1319 },
Blink Reformat4c46d092018-04-07 15:32:371320
Philip Pfaffe7523faf2021-06-28 14:23:141321 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241322 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371323 },
1324
Philip Pfaffe7523faf2021-06-28 14:23:141325 registerHandler: function(
1326 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1327 void {
1328 this._handlers[command] = handler;
1329 },
Blink Reformat4c46d092018-04-07 15:32:371330
Philip Pfaffe7523faf2021-06-28 14:23:141331 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371332 delete this._handlers[command];
1333 },
1334
Philip Pfaffe7523faf2021-06-28 14:23:141335 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371336 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1337 },
1338
Philip Pfaffe7523faf2021-06-28 14:23:141339 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371340 const id = ++this._lastRequestId;
1341 this._callbacks[id] = callback;
1342 return id;
1343 },
1344
Philip Pfaffe7523faf2021-06-28 14:23:141345 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371346 if (request.requestId in this._callbacks) {
1347 const callback = this._callbacks[request.requestId];
1348 delete this._callbacks[request.requestId];
1349 callback(request.result);
1350 }
1351 },
1352
Philip Pfaffe7523faf2021-06-28 14:23:141353 _onMessage: function(
1354 this: APIImpl.ExtensionServerClient,
1355 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371356 const request = event.data;
1357 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341358 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371359 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341360 }
Jan Schefflerd76b4162021-03-29 07:52:161361 },
Blink Reformat4c46d092018-04-07 15:32:371362 };
1363
Philip Pfaffe7523faf2021-06-28 14:23:141364 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371365 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341366 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371367 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341368 }
Jan Schefflerd76b4162021-03-29 07:52:161369 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371370 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141371 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371372 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341373 }
1374 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371375 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341376 }
1377 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371378 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341379 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141380 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371381 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341382 } else {
Blink Reformat4c46d092018-04-07 15:32:371383 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341384 }
Blink Reformat4c46d092018-04-07 15:32:371385 }
1386 }
1387
Alex Rudenkoa3850822022-05-24 07:34:221388 const extensionServer = new (Constructor(ExtensionServerClient))(targetWindowForTest || window.parent);
Philip Pfaffe7523faf2021-06-28 14:23:141389
1390 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371391
1392 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1393
1394 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141395 // @ts-expect-error
1396 chrome.devtools!.inspectedWindow = {};
1397 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1398 // @ts-expect-error
1399 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1400 chrome.devtools!.network = coreAPI.network;
1401 chrome.devtools!.panels = coreAPI.panels;
1402 chrome.devtools!.panels.themeName = themeName;
1403 chrome.devtools!.languageServices = coreAPI.languageServices;
Alex Rudenkoa3850822022-05-24 07:34:221404 chrome.devtools!.recorder = coreAPI.recorder;
Blink Reformat4c46d092018-04-07 15:32:371405
1406 // default to expose experimental APIs for now.
1407 if (extensionInfo.exposeExperimentalAPIs !== false) {
1408 chrome.experimental = chrome.experimental || {};
1409 chrome.experimental.devtools = chrome.experimental.devtools || {};
1410
1411 const properties = Object.getOwnPropertyNames(coreAPI);
1412 for (let i = 0; i < properties.length; ++i) {
1413 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341414 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371415 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341416 }
Blink Reformat4c46d092018-04-07 15:32:371417 }
1418 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1419 }
1420
Tim van der Lippe1d6e57a2019-09-30 11:55:341421 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371422 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341423 }
Blink Reformat4c46d092018-04-07 15:32:371424 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121425};
Blink Reformat4c46d092018-04-07 15:32:371426
Jan Schefflerd76b4162021-03-29 07:52:161427self.buildExtensionAPIInjectedScript = function(
1428 extensionInfo: {
1429 startPage: string,
1430 name: string,
1431 exposeExperimentalAPIs: boolean,
1432 },
1433 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141434 testHook:
1435 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1436 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251437 const argumentsJSON =
1438 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341439 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161440 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341441 }
Philip Pfaffe939605d2021-06-25 12:20:041442 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121443 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371444 '})';
Tim van der Lippe29fab472019-08-15 14:46:481445};