blob: 3452865cb10b2d8e2aaa1c141a5e02e39d369062 [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',
89 }
Philip Pfaffeedad8322020-07-20 10:24:2590
Philip Pfaffe939605d2021-06-25 12:20:0491 export const enum LanguageExtensionPluginCommands {
92 AddRawModule = 'addRawModule',
93 RemoveRawModule = 'removeRawModule',
94 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
95 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
96 GetScopeInfo = 'getScopeInfo',
97 ListVariablesInScope = 'listVariablesInScope',
98 GetTypeInfo = 'getTypeInfo',
99 GetFormatter = 'getFormatter',
100 GetInspectableAddress = 'getInspectableAddress',
101 GetFunctionInfo = 'getFunctionInfo',
102 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
103 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
104 GetMappedLines = 'getMappedLines',
105 }
Benedikt Meurer929fc7c2020-11-20 14:21:06106
Philip Pfaffe939605d2021-06-25 12:20:04107 export const enum LanguageExtensionPluginEvents {
108 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
109 }
Philip Pfaffed662bdf2021-06-25 13:30:32110
111 export interface EvaluateOptions {
112 frameURL?: string;
113 useContentScriptContext?: boolean;
114 scriptExecutionContext?: string;
115 }
116
Philip Pfaffed662bdf2021-06-25 13:30:32117 type RegisterLanguageExtensionPluginRequest = {
118 command: Commands.RegisterLanguageExtensionPlugin,
119 pluginName: string,
120 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14121 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32122 };
123 type SubscribeRequest = {command: Commands.Subscribe, type: string};
124 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
125 type AddRequestHeadersRequest = {
126 command: Commands.AddRequestHeaders,
127 extensionId: string,
128 headers: {[key: string]: string},
129 };
130 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
131 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
132 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
133 type CreateToolbarButtonRequest = {
134 command: Commands.CreateToolbarButton,
135 id: string,
136 icon: string,
137 panel: string,
138 tooltip?: string,
139 disabled?: boolean,
140 };
141 type UpdateButtonRequest =
142 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
143 type CompleteTraceSessionRequest =
Kateryna Prokopenko6fa122c2022-05-06 08:54:47144 {command: Commands.CompleteTraceSession, id: string, url: Platform.DevToolsPath.UrlString, timeOffset: number};
Philip Pfaffed662bdf2021-06-25 13:30:32145 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
146 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
147 type SetSidebarContentRequest = {
148 command: Commands.SetSidebarContent,
149 id: string,
150 evaluateOnPage?: boolean, expression: string,
151 rootTitle?: string,
152 evaluateOptions?: EvaluateOptions,
153 };
154 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Kateryna Prokopenko9964ab12022-03-23 16:41:49155 type OpenResourceRequest =
156 {command: Commands.OpenResource, url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32157 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
Paul Lewisada689f2022-01-11 12:03:40158 type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32159 type ReloadRequest = {
160 command: Commands.Reload,
161 options: null|{
162 userAgent?: string,
163 injectedScript?: string,
164 ignoreCache?: boolean,
165 },
166 };
167 type EvaluateOnInspectedPageRequest = {
168 command: Commands.EvaluateOnInspectedPage,
169 expression: string,
170 evaluateOptions?: EvaluateOptions,
171 };
172 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
173 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
174 type SetResourceContentRequest =
175 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
176 type AddTraceProviderRequest =
177 {command: Commands.AddTraceProvider, id: string, categoryName: string, categoryTooltip: string};
178 type ForwardKeyboardEventRequest = {
179 command: Commands.ForwardKeyboardEvent,
180 entries: Array<KeyboardEventInit&{eventType: string}>,
181 };
182 type GetHARRequest = {command: Commands.GetHAR};
183 type GetPageResourcesRequest = {command: Commands.GetPageResources};
184
185 export type ServerRequests = RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|
186 AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|
187 UpdateButtonRequest|CompleteTraceSessionRequest|CreateSidebarPaneRequest|SetSidebarHeightRequest|
Paul Lewisada689f2022-01-11 12:03:40188 SetSidebarContentRequest|SetSidebarPageRequest|OpenResourceRequest|SetOpenResourceHandlerRequest|
189 SetThemeChangeHandlerRequest|ReloadRequest|EvaluateOnInspectedPageRequest|GetRequestContentRequest|
190 GetResourceContentRequest|SetResourceContentRequest|AddTraceProviderRequest|ForwardKeyboardEventRequest|
191 GetHARRequest|GetPageResourcesRequest;
Philip Pfaffed662bdf2021-06-25 13:30:32192 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32193
194 type AddRawModuleRequest = {
195 method: LanguageExtensionPluginCommands.AddRawModule,
196 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
197 };
198 type SourceLocationToRawLocationRequest = {
199 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
200 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
201 };
202 type RawLocationToSourceLocationRequest = {
203 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
204 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
205 };
206 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
207 type ListVariablesInScopeRequest = {
208 method: LanguageExtensionPluginCommands.ListVariablesInScope,
209 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
210 };
211 type RemoveRawModuleRequest = {
212 method: LanguageExtensionPluginCommands.RemoveRawModule,
213 parameters: {rawModuleId: string},
214 };
215 type GetTypeInfoRequest = {
216 method: LanguageExtensionPluginCommands.GetTypeInfo,
217 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation},
218 };
219 type GetFormatterRequest = {
220 method: LanguageExtensionPluginCommands.GetFormatter,
221 parameters: {
222 expressionOrField: string|{
223 base: PublicAPI.Chrome.DevTools.EvalBase,
224 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
225 },
226 context: PublicAPI.Chrome.DevTools.RawLocation,
227 },
228 };
229 type GetInspectableAddressRequest = {
230 method: LanguageExtensionPluginCommands.GetInspectableAddress,
231 parameters: {
232 field: {
233 base: PublicAPI.Chrome.DevTools.EvalBase,
234 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
235 },
236 },
237 };
238 type GetFunctionInfoRequest = {
239 method: LanguageExtensionPluginCommands.GetFunctionInfo,
240 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
241 };
242 type GetInlinedFunctionRangesRequest = {
243 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
244 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
245 };
246 type GetInlinedCalleesRangesRequest = {
247 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
248 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
249 };
250 type GetMappedLinesRequest = {
251 method: LanguageExtensionPluginCommands.GetMappedLines,
252 parameters: {rawModuleId: string, sourceFileURL: string},
253 };
254
255 export type LanguageExtensionRequests = AddRawModuleRequest|SourceLocationToRawLocationRequest|
256 RawLocationToSourceLocationRequest|GetScopeInfoRequest|ListVariablesInScopeRequest|RemoveRawModuleRequest|
257 GetTypeInfoRequest|GetFormatterRequest|GetInspectableAddressRequest|GetFunctionInfoRequest|
258 GetInlinedFunctionRangesRequest|GetInlinedCalleesRangesRequest|GetMappedLinesRequest;
Blink Reformat4c46d092018-04-07 15:32:37259}
260
Philip Pfaffe939605d2021-06-25 12:20:04261declare global {
262 interface Window {
263 injectedExtensionAPI:
264 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14265 testHook:
266 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23267 injectedScriptId: number) => void;
Philip Pfaffe939605d2021-06-25 12:20:04268 buildExtensionAPIInjectedScript(
269 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32270 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14271 chrome: PublicAPI.Chrome.DevTools.Chrome;
272 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04273 }
274}
275
276export type ExtensionDescriptor = {
277 startPage: string,
278 name: string,
279 exposeExperimentalAPIs: boolean,
280 exposeWebInspectorNamespace?: boolean,
281};
282
Philip Pfaffe7523faf2021-06-28 14:23:14283namespace APIImpl {
284 export interface InspectorExtensionAPI {
285 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Philip Pfaffe1c827212021-06-25 12:33:20286 timeline: Timeline;
Philip Pfaffe7523faf2021-06-28 14:23:14287 network: PublicAPI.Chrome.DevTools.Network;
288 panels: PublicAPI.Chrome.DevTools.Panels;
289 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
290 }
291
292 export interface ExtensionServerClient {
293 _callbacks: {[key: string]: (response: unknown) => unknown};
294 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
295 _lastRequestId: number;
296 _lastObjectId: number;
297 _port: MessagePort;
298
299 _onCallback(request: unknown): void;
300 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
301 _registerCallback(callback: (response: unknown) => unknown): number;
302 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
303 unregisterHandler(command: string): void;
304 hasHandler(command: string): boolean;
305 sendRequest(request: PrivateAPI.ServerRequests, callback?: ((response: unknown) => unknown), transfers?: unknown[]):
306 void;
307 nextObjectId(): string;
308 }
309
310 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
311 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
312 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28313 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14314 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28315 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14316
317 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
318 _type: string;
319 _listeners: ListenerT[];
320 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
321
322 _fire(..._vararg: Parameters<ListenerT>): void;
323 _dispatch(request: {arguments: unknown[]}): void;
324 }
Philip Pfaffe4b88c662021-06-25 12:30:47325
326 export interface Network extends PublicAPI.Chrome.DevTools.Network {
327 addRequestHeaders(headers: {[key: string]: string}): void;
328 }
329
330 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
331 _id: number;
332 }
Philip Pfaffe6fd04c42021-06-25 12:31:48333
334 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
335 get SearchAction(): {[key: string]: string};
336 applyStyleSheet(styleSheet: string): void;
337 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
338 void;
Paul Lewisada689f2022-01-11 12:03:40339 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48340 }
341
342 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
343 _id: string|null;
344 }
345
346 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
347 setExpression(
348 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
349 callback?: () => unknown): void;
350 }
351
352 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
353 _hostPanelName: string;
354 }
355
356 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
357 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
358 }
359
360 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
361 show(): void;
362 }
363
364 export interface Button extends PublicAPI.Chrome.DevTools.Button {
365 _id: string;
366 }
367
Philip Pfaffe1c827212021-06-25 12:33:20368 export interface TraceSession {
369 _id: string;
370
371 complete(url?: string, timeOffset?: number): void;
372 }
373
374 export interface TraceProvider {
375 onRecordingStarted: EventSink<(session: TraceSession) => unknown>;
376 onRecordingStopped: EventSink<() => unknown>;
377 }
378
379 export interface Timeline {
380 addTraceProvider(categoryName: string, categoryTooltip: string): TraceProvider;
381 }
382
Philip Pfaffe6fd04c42021-06-25 12:31:48383 export type ResourceData = {url: string, type: string};
384 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
385 _type: string;
386 _url: string;
387
388 get type(): string;
389 }
Philip Pfaffe7523faf2021-06-28 14:23:14390}
Philip Pfaffe939605d2021-06-25 12:20:04391
Tim van der Lippe226fc222019-10-10 12:17:12392self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14393 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
394 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23395 injectedScriptId: number): void {
Jan Schefflerd76b4162021-03-29 07:52:16396 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37397 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16398
Blink Reformat4c46d092018-04-07 15:32:37399 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34400 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37401 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34402 }
Blink Reformat4c46d092018-04-07 15:32:37403 let userAction = false;
404
405 // Here and below, all constructors are private to API implementation.
406 // For a public type Foo, if internal fields are present, these are on
407 // a private FooImpl type, an instance of FooImpl is used in a closure
408 // by Foo consutrctor to re-bind publicly exported members to an instance
409 // of Foo.
410
Philip Pfaffe7523faf2021-06-28 14:23:14411 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
412 this: APIImpl.EventSink<ListenerT>, type: string,
413 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37414 this._type = type;
415 this._listeners = [];
416 this._customDispatch = customDispatch;
417 }
418
419 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14420 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
421 void {
422 if (typeof callback !== 'function') {
423 throw 'addListener: callback is not a function';
424 }
425 if (this._listeners.length === 0) {
426 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
427 }
428 this._listeners.push(callback);
429 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
430 },
Blink Reformat4c46d092018-04-07 15:32:37431
Philip Pfaffe7523faf2021-06-28 14:23:14432 removeListener: function<ListenerT extends APIImpl.Callable>(
433 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37434 const listeners = this._listeners;
435
436 for (let i = 0; i < listeners.length; ++i) {
437 if (listeners[i] === callback) {
438 listeners.splice(i, 1);
439 break;
440 }
441 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34442 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04443 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34444 }
Blink Reformat4c46d092018-04-07 15:32:37445 },
446
Philip Pfaffe7523faf2021-06-28 14:23:14447 _fire: function<ListenerT extends APIImpl.Callable>(
448 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37449 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34450 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14451 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34452 }
Blink Reformat4c46d092018-04-07 15:32:37453 },
454
Philip Pfaffe7523faf2021-06-28 14:23:14455 _dispatch: function<ListenerT extends APIImpl.Callable>(
456 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34457 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37458 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34459 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14460 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34461 }
Jan Schefflerd76b4162021-03-29 07:52:16462 },
Blink Reformat4c46d092018-04-07 15:32:37463 };
464
Philip Pfaffe7523faf2021-06-28 14:23:14465 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
466 ThisParameterType<NewT> {
467 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
468 }
469
Philip Pfaffe7523faf2021-06-28 14:23:14470 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41471 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48472 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47473 this.network = new (Constructor(Network))();
Philip Pfaffe1c827212021-06-25 12:33:20474 this.timeline = new (Constructor(Timeline))();
Philip Pfaffec5d160e2021-07-20 10:53:32475 this.languageServices = new (Constructor(LanguageServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37476 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
477 }
478
Philip Pfaffe4b88c662021-06-25 12:30:47479 function Network(this: APIImpl.Network): void {
480 function dispatchRequestEvent(
481 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
482 message: {arguments: unknown[]}): void {
483 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
484
485 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37486 this._fire(request);
487 }
Philip Pfaffe4b88c662021-06-25 12:30:47488
489 this.onRequestFinished =
490 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37491 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47492
493 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37494 }
495
Philip Pfaffe4b88c662021-06-25 12:30:47496 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
497 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
498 function callbackWrapper(response: unknown): void {
499 const result =
500 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37501 const entries = (result && result.entries) || [];
502 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47503 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37504 delete entries[i]._requestId;
505 }
Philip Pfaffe4b88c662021-06-25 12:30:47506 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37507 }
Philip Pfaffe939605d2021-06-25 12:20:04508 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37509 },
510
Philip Pfaffe4b88c662021-06-25 12:30:47511 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37512 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04513 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16514 },
Blink Reformat4c46d092018-04-07 15:32:37515 };
516
Philip Pfaffe4b88c662021-06-25 12:30:47517 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37518 this._id = id;
519 }
520
Philip Pfaffe4b88c662021-06-25 12:30:47521 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
522 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
523 function callbackWrapper(response: unknown): void {
524 const {content, encoding} = response as {content: string, encoding: string};
525 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37526 }
Philip Pfaffe939605d2021-06-25 12:20:04527 extensionServer.sendRequest(
528 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16529 },
Blink Reformat4c46d092018-04-07 15:32:37530 };
531
Philip Pfaffe6fd04c42021-06-25 12:31:48532 function Panels(this: APIImpl.Panels): void {
533 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37534 elements: new ElementsPanel(),
535 sources: new SourcesPanel(),
536 };
537
Philip Pfaffe6fd04c42021-06-25 12:31:48538 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37539 return panels[name];
540 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34541 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12542 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34543 }
Philip Pfaffe6fd04c42021-06-25 12:31:48544 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04545 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37546 };
547 }
548
Paul Lewisada689f2022-01-11 12:03:40549 (Panels.prototype as
550 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48551 create: function(
552 title: string, icon: string, page: string,
553 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37554 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48555 extensionServer.sendRequest(
556 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37557 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37558 },
559
Philip Pfaffe6fd04c42021-06-25 12:31:48560 setOpenResourceHandler: function(
561 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04562 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37563
Philip Pfaffe6fd04c42021-06-25 12:31:48564 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37565 // Allow the panel to show itself when handling the event.
566 userAction = true;
567 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48568 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
569 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
Blink Reformat4c46d092018-04-07 15:32:37570 } finally {
571 userAction = false;
572 }
573 }
574
Tim van der Lippe1d6e57a2019-09-30 11:55:34575 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04576 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34577 } else {
Philip Pfaffe939605d2021-06-25 12:20:04578 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34579 }
Blink Reformat4c46d092018-04-07 15:32:37580
581 // 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:34582 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04583 extensionServer.sendRequest(
584 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34585 }
Blink Reformat4c46d092018-04-07 15:32:37586 },
587
Paul Lewisada689f2022-01-11 12:03:40588 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
589 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
590
591 function callbackWrapper(message: unknown): void {
592 const {themeName} = message as {themeName: string};
593 chrome.devtools.panels.themeName = themeName;
594 callback.call(null, themeName);
595 }
596
597 if (!callback) {
598 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
599 } else {
600 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
601 }
602
603 // Only send command if we either removed an existing handler or added handler and had none before.
604 if (hadHandler === !callback) {
605 extensionServer.sendRequest(
606 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
607 }
608 },
609
Philip Pfaffe140e5432021-09-13 16:34:23610 openResource: function(
Kateryna Prokopenko9964ab12022-03-23 16:41:49611 url: Platform.DevToolsPath.UrlString, lineNumber: number, columnNumber?: number,
612 _callback?: (response: unknown) => unknown): void {
Philip Pfaffe140e5432021-09-13 16:34:23613 const callbackArg = extractCallbackArgument(arguments);
614 // Handle older API:
615 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
616 extensionServer.sendRequest(
617 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37618 },
619
Philip Pfaffe6fd04c42021-06-25 12:31:48620 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04621 return {
622 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
623 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
624 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
625 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
626 };
Jan Schefflerd76b4162021-03-29 07:52:16627 },
Blink Reformat4c46d092018-04-07 15:32:37628 };
629
Philip Pfaffe6fd04c42021-06-25 12:31:48630 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37631 this._id = id;
632
Philip Pfaffe6fd04c42021-06-25 12:31:48633 function dispatchShowEvent(
634 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37635 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34636 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37637 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34638 } else {
Blink Reformat4c46d092018-04-07 15:32:37639 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34640 }
Blink Reformat4c46d092018-04-07 15:32:37641 }
642
643 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48644 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
645
646 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37647 }
648 }
649
Philip Pfaffe6fd04c42021-06-25 12:31:48650 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37651 ExtensionViewImpl.call(this, null);
652 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48653
654 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37655 }
656
Philip Pfaffe6fd04c42021-06-25 12:31:48657 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
658 {__proto__: APIImpl.ExtensionView}) = {
659 createSidebarPane: function(
660 this: APIImpl.PanelWithSidebar, title: string,
661 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37662 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16663 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48664 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37665 }
Philip Pfaffe7523faf2021-06-28 14:23:14666 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48667 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14668 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37669 },
670
Jan Schefflerd76b4162021-03-29 07:52:16671 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37672 };
673
Philip Pfaffec5d160e2021-07-20 10:53:32674 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25675 this._plugins = new Map();
676 }
677
Philip Pfaffec5d160e2021-07-20 10:53:32678 (LanguageServicesAPIImpl.prototype as
679 Pick<APIImpl.LanguageExtensions, 'registerLanguageExtensionPlugin'|'unregisterLanguageExtensionPlugin'>) = {
Philip Pfaffed662bdf2021-06-25 13:30:32680 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32681 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
682 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
683 if (this._plugins.has(plugin)) {
684 throw new Error(`Tried to register plugin '${pluginName}' twice`);
685 }
686 const channel = new MessageChannel();
687 const port = channel.port1;
688 this._plugins.set(plugin, port);
689 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
690 const {requestId} = data;
691 console.time(`${requestId}: ${data.method}`);
692 dispatchMethodCall(data)
693 .then(result => port.postMessage({requestId, result}))
694 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
695 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
696 };
Philip Pfaffeedad8322020-07-20 10:24:25697
Philip Pfaffec5d160e2021-07-20 10:53:32698 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
699 switch (request.method) {
700 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
701 return plugin.addRawModule(
702 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
703 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
704 return plugin.removeRawModule(request.parameters.rawModuleId);
705 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
706 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
707 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
708 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
709 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
710 return plugin.getScopeInfo(request.parameters.type);
711 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
712 return plugin.listVariablesInScope(request.parameters.rawLocation);
713 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
714 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
715 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
716 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
717 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
718 if ('getInspectableAddress' in plugin) {
719 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02720 }
Philip Pfaffec5d160e2021-07-20 10:53:32721 return Promise.resolve({js: ''});
722 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
723 return plugin.getFunctionInfo(request.parameters.rawLocation);
724 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
725 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
726 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
727 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
728 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
729 if ('getMappedLines' in plugin) {
730 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
731 }
732 return Promise.resolve(undefined);
733 }
734 // @ts-expect-error
735 throw new Error(`Unknown language plugin method ${request.method}`);
736 }
Philip Pfaffeedad8322020-07-20 10:24:25737
Philip Pfaffec5d160e2021-07-20 10:53:32738 await new Promise<void>(resolve => {
739 extensionServer.sendRequest(
740 {
741 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
742 pluginName,
743 port: channel.port2,
744 supportedScriptTypes,
745 },
746 () => resolve(), [channel.port2]);
747 });
748 },
Benedikt Meurer929fc7c2020-11-20 14:21:06749
Philip Pfaffec5d160e2021-07-20 10:53:32750 unregisterLanguageExtensionPlugin: async function(
751 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06752 const port = this._plugins.get(plugin);
753 if (!port) {
754 throw new Error('Tried to unregister a plugin that was not previously registered');
755 }
756 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04757 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06758 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16759 },
Philip Pfaffeedad8322020-07-20 10:24:25760 };
761
Philip Pfaffe7523faf2021-06-28 14:23:14762 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
763 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
764 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37765 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14766 implConstructor.apply(impl, args);
767 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37768 };
769 }
770
Philip Pfaffe7523faf2021-06-28 14:23:14771 // eslint-disable-next-line @typescript-eslint/no-explicit-any
772 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37773 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14774 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37775 if (!warningGiven) {
776 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
777 warningGiven = true;
778 }
779 return object[newName];
780 }
781 object.__defineGetter__(oldName, getter);
782 }
783
Philip Pfaffe7523faf2021-06-28 14:23:14784 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37785 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14786 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37787 }
788
Philip Pfaffeedad8322020-07-20 10:24:25789 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37790 const Button = declareInterfaceClass(ButtonImpl);
791 const EventSink = declareInterfaceClass(EventSinkImpl);
792 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
793 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12794 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37795 const Request = declareInterfaceClass(RequestImpl);
796 const Resource = declareInterfaceClass(ResourceImpl);
797 const TraceSession = declareInterfaceClass(TraceSessionImpl);
798
Philip Pfaffe6fd04c42021-06-25 12:31:48799 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12800 constructor() {
801 super('elements');
802 }
Blink Reformat4c46d092018-04-07 15:32:37803 }
804
Philip Pfaffe6fd04c42021-06-25 12:31:48805 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12806 constructor() {
807 super('sources');
808 }
Blink Reformat4c46d092018-04-07 15:32:37809 }
810
Philip Pfaffe6fd04c42021-06-25 12:31:48811 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37812 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48813
814 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37815 }
816
Philip Pfaffe6fd04c42021-06-25 12:31:48817 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
818 {__proto__: APIImpl.ExtensionView}) = {
819 createStatusBarButton: function(
820 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
821 PublicAPI.Chrome.DevTools.Button {
822 const id = 'button-' + extensionServer.nextObjectId();
823 extensionServer.sendRequest({
824 command: PrivateAPI.Commands.CreateToolbarButton,
825 panel: this._id as string,
826 id: id,
827 icon: iconPath,
828 tooltip: tooltipText,
829 disabled: Boolean(disabled),
830 });
Blink Reformat4c46d092018-04-07 15:32:37831
Philip Pfaffe6fd04c42021-06-25 12:31:48832 return new (Constructor(Button))(id);
833 },
834
835 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34836 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:37837 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34838 }
Blink Reformat4c46d092018-04-07 15:32:37839
Philip Pfaffe6fd04c42021-06-25 12:31:48840 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:37841 },
842
Jan Schefflerd76b4162021-03-29 07:52:16843 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37844 };
845
Philip Pfaffe6fd04c42021-06-25 12:31:48846 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37847 ExtensionViewImpl.call(this, id);
848 }
849
Philip Pfaffe6fd04c42021-06-25 12:31:48850 (ExtensionSidebarPaneImpl.prototype as
851 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
852 {__proto__: APIImpl.ExtensionView}) = {
853 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
854 extensionServer.sendRequest(
855 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:37856 },
857
Philip Pfaffe6fd04c42021-06-25 12:31:48858 setExpression: function(
859 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
860 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:14861 extensionServer.sendRequest(
862 {
863 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:48864 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:14865 expression: expression,
866 rootTitle: rootTitle,
867 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:48868 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:14869 },
870 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:37871 },
872
Philip Pfaffe6fd04c42021-06-25 12:31:48873 setObject: function(
874 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37875 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48876 {
877 command: PrivateAPI.Commands.SetSidebarContent,
878 id: this._id as string,
879 expression: jsonObject,
880 rootTitle: rootTitle,
881 },
Philip Pfaffe939605d2021-06-25 12:20:04882 callback);
Blink Reformat4c46d092018-04-07 15:32:37883 },
884
Philip Pfaffe6fd04c42021-06-25 12:31:48885 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
886 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:37887 },
888
Jan Schefflerd76b4162021-03-29 07:52:16889 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37890 };
891
Philip Pfaffe6fd04c42021-06-25 12:31:48892 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37893 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:48894
895 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:37896 }
897
Philip Pfaffe6fd04c42021-06-25 12:31:48898 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
899 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:14900 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04901 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:24902 id: this._id,
903 icon: iconPath,
904 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16905 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:14906 });
Jan Schefflerd76b4162021-03-29 07:52:16907 },
Blink Reformat4c46d092018-04-07 15:32:37908 };
909
Philip Pfaffe1c827212021-06-25 12:33:20910 function Timeline(this: APIImpl.Timeline): void {
Blink Reformat4c46d092018-04-07 15:32:37911 }
912
Philip Pfaffe1c827212021-06-25 12:33:20913 (Timeline.prototype as Pick<APIImpl.Timeline, 'addTraceProvider'>) = {
914 addTraceProvider: function(this: APIImpl.Timeline, categoryName: string, categoryTooltip: string):
915 APIImpl.TraceProvider {
916 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
917 extensionServer.sendRequest({
918 command: PrivateAPI.Commands.AddTraceProvider,
919 id: id,
920 categoryName: categoryName,
921 categoryTooltip: categoryTooltip,
922 });
923
924 return new (Constructor(TraceProvider))(id);
925 },
Blink Reformat4c46d092018-04-07 15:32:37926 };
927
Philip Pfaffe1c827212021-06-25 12:33:20928 function TraceSessionImpl(this: APIImpl.TraceSession, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37929 this._id = id;
930 }
931
Philip Pfaffe1c827212021-06-25 12:33:20932 (TraceSessionImpl.prototype as Pick<APIImpl.TraceSession, 'complete'>) = {
Kateryna Prokopenko6fa122c2022-05-06 08:54:47933 complete: function(this: APIImpl.TraceSession, url?: Platform.DevToolsPath.UrlString, timeOffset?: number): void {
Philip Pfaffe7523faf2021-06-28 14:23:14934 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04935 command: PrivateAPI.Commands.CompleteTraceSession,
936 id: this._id,
Kateryna Prokopenko6fa122c2022-05-06 08:54:47937 url: url || Platform.DevToolsPath.EmptyUrlString,
Philip Pfaffe939605d2021-06-25 12:20:04938 timeOffset: timeOffset || 0,
Philip Pfaffe7523faf2021-06-28 14:23:14939 });
Jan Schefflerd76b4162021-03-29 07:52:16940 },
Blink Reformat4c46d092018-04-07 15:32:37941 };
942
Philip Pfaffe1c827212021-06-25 12:33:20943 function TraceProvider(this: APIImpl.TraceProvider, id: string): void {
944 function dispatchRecordingStarted(
945 this: APIImpl.EventSink<APIImpl.Callable>, message: {arguments: unknown[]}): void {
946 const sessionId = message.arguments[0] as string;
947
948 this._fire(new (Constructor(TraceSession))(sessionId));
Blink Reformat4c46d092018-04-07 15:32:37949 }
950
Philip Pfaffe1c827212021-06-25 12:33:20951 this.onRecordingStarted =
952 new (Constructor(EventSink))(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
953
954 this.onRecordingStopped = new (Constructor(EventSink))(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:37955 }
956
Philip Pfaffeddf60d22021-06-25 12:35:41957 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
958 function dispatchResourceEvent(
959 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
960 this._fire(new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData));
Blink Reformat4c46d092018-04-07 15:32:37961 }
962
Philip Pfaffeddf60d22021-06-25 12:35:41963 function dispatchResourceContentEvent(
964 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
965 message: {arguments: unknown[]}): void {
966 this._fire(
967 new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:37968 }
969
Philip Pfaffeddf60d22021-06-25 12:35:41970 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:04971 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:41972 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:37973 }
974
Philip Pfaffeddf60d22021-06-25 12:35:41975 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
976 reload: function(optionsOrUserAgent: {
977 ignoreCache?: boolean,
978 injectedScript?: string,
979 userAgent?: string,
980 }): void {
Jan Schefflerd76b4162021-03-29 07:52:16981 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:41982 ignoreCache?: boolean,
983 injectedScript?: string,
984 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:16985 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:37986 if (typeof optionsOrUserAgent === 'object') {
987 options = optionsOrUserAgent;
988 } else if (typeof optionsOrUserAgent === 'string') {
989 options = {userAgent: optionsOrUserAgent};
990 console.warn(
991 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
992 'Use inspectedWindow.reload({ userAgent: value}) instead.');
993 }
Philip Pfaffe939605d2021-06-25 12:20:04994 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:37995 },
996
Philip Pfaffeddf60d22021-06-25 12:35:41997 eval: function(
998 expression: string,
999 evaluateOptions: {contextSecurityOrigin?: string, frameURL?: string, useContentScriptContext?: boolean}):
1000 Object |
Jan Schefflerd76b4162021-03-29 07:52:161001 null {
1002 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411003 function callbackWrapper(result: unknown): void {
1004 const {isError, isException, value} = result as {
1005 isError?: boolean,
1006 isException?: boolean, value: unknown,
1007 };
1008 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141009 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161010 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411011 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161012 }
1013 }
Philip Pfaffe7523faf2021-06-28 14:23:141014 extensionServer.sendRequest(
1015 {
1016 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1017 expression: expression,
1018 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1019 },
1020 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161021 return null;
1022 },
Blink Reformat4c46d092018-04-07 15:32:371023
Philip Pfaffeddf60d22021-06-25 12:35:411024 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1025 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1026 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371027 }
Philip Pfaffeddf60d22021-06-25 12:35:411028 function callbackWrapper(resources: unknown): void {
1029 callback && callback((resources as APIImpl.ResourceData[]).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:371030 }
Philip Pfaffe939605d2021-06-25 12:20:041031 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161032 },
Blink Reformat4c46d092018-04-07 15:32:371033 };
1034
Philip Pfaffe6fd04c42021-06-25 12:31:481035 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Blink Reformat4c46d092018-04-07 15:32:371036 this._url = resourceData.url;
1037 this._type = resourceData.type;
1038 }
1039
Philip Pfaffe6fd04c42021-06-25 12:31:481040 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161041 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481042 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371043 },
1044
Jan Schefflerd76b4162021-03-29 07:52:161045 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481046 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371047 },
1048
Philip Pfaffe6fd04c42021-06-25 12:31:481049 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1050 function callbackWrapper(response: unknown): void {
1051 const {content, encoding} = response as {content: string, encoding: string};
1052 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371053 }
1054
Philip Pfaffe939605d2021-06-25 12:20:041055 extensionServer.sendRequest(
1056 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371057 },
1058
Philip Pfaffe6fd04c42021-06-25 12:31:481059 setContent: function(
1060 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371061 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041062 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481063 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161064 },
Blink Reformat4c46d092018-04-07 15:32:371065 };
1066
Jan Schefflerd76b4162021-03-29 07:52:161067 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371068 return inspectedTabId;
1069 }
1070
Philip Pfaffe7523faf2021-06-28 14:23:141071 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161072 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141073 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521074 // Check if the event should be forwarded.
1075 // This is a workaround for crbug.com/923338.
1076 const focused = document.activeElement;
1077 if (focused) {
1078 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
1079 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1080 return;
1081 }
1082 }
1083
Joel Einbinder67f28fb2018-08-02 00:33:471084 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341085 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471086 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341087 }
1088 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471089 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341090 }
1091 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471092 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341093 }
1094 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471095 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341096 }
Joel Einbinder67f28fb2018-08-02 00:33:471097 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371098 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341099 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371100 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341101 }
Joel Einbinder67f28fb2018-08-02 00:33:471102 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371103 const requestPayload = {
1104 eventType: event.type,
1105 ctrlKey: event.ctrlKey,
1106 altKey: event.altKey,
1107 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471108 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141109 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371110 keyIdentifier: event.keyIdentifier,
1111 key: event.key,
1112 code: event.code,
1113 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161114 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371115 };
1116 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341117 if (!forwardTimer) {
Tim van der Lippe6bcbe0f2022-01-11 13:10:311118 forwardTimer = window.setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341119 }
Blink Reformat4c46d092018-04-07 15:32:371120 }
1121
Jan Schefflerd76b4162021-03-29 07:52:161122 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371123 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141124 extensionServer.sendRequest(
1125 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371126 keyboardEventRequestQueue = [];
1127 }
1128
1129 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371130
Philip Pfaffe7523faf2021-06-28 14:23:141131 function ExtensionServerClient(this: APIImpl.ExtensionServerClient): void {
Blink Reformat4c46d092018-04-07 15:32:371132 this._callbacks = {};
1133 this._handlers = {};
1134 this._lastRequestId = 0;
1135 this._lastObjectId = 0;
1136
1137 this.registerHandler('callback', this._onCallback.bind(this));
1138
1139 const channel = new MessageChannel();
1140 this._port = channel.port1;
1141 this._port.addEventListener('message', this._onMessage.bind(this), false);
1142 this._port.start();
1143
1144 window.parent.postMessage('registerExtension', '*', [channel.port2]);
1145 }
1146
Philip Pfaffe7523faf2021-06-28 14:23:141147 (ExtensionServerClient.prototype as Pick<
1148 APIImpl.ExtensionServerClient,
1149 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1150 '_onCallback'|'_onMessage'>) = {
1151 sendRequest: function(
1152 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
1153 callback?: (response: unknown) => unknown, transfers?: Transferable[]): void {
1154 if (typeof callback === 'function') {
1155 (message as PrivateAPI.ExtensionServerRequestMessage).requestId = this._registerCallback(callback);
1156 }
1157 // @ts-expect-error
1158 this._port.postMessage(message, transfers);
1159 },
Blink Reformat4c46d092018-04-07 15:32:371160
Philip Pfaffe7523faf2021-06-28 14:23:141161 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241162 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371163 },
1164
Philip Pfaffe7523faf2021-06-28 14:23:141165 registerHandler: function(
1166 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1167 void {
1168 this._handlers[command] = handler;
1169 },
Blink Reformat4c46d092018-04-07 15:32:371170
Philip Pfaffe7523faf2021-06-28 14:23:141171 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371172 delete this._handlers[command];
1173 },
1174
Philip Pfaffe7523faf2021-06-28 14:23:141175 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371176 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1177 },
1178
Philip Pfaffe7523faf2021-06-28 14:23:141179 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371180 const id = ++this._lastRequestId;
1181 this._callbacks[id] = callback;
1182 return id;
1183 },
1184
Philip Pfaffe7523faf2021-06-28 14:23:141185 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371186 if (request.requestId in this._callbacks) {
1187 const callback = this._callbacks[request.requestId];
1188 delete this._callbacks[request.requestId];
1189 callback(request.result);
1190 }
1191 },
1192
Philip Pfaffe7523faf2021-06-28 14:23:141193 _onMessage: function(
1194 this: APIImpl.ExtensionServerClient,
1195 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371196 const request = event.data;
1197 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341198 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371199 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341200 }
Jan Schefflerd76b4162021-03-29 07:52:161201 },
Blink Reformat4c46d092018-04-07 15:32:371202 };
1203
Philip Pfaffe7523faf2021-06-28 14:23:141204 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371205 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341206 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371207 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341208 }
Jan Schefflerd76b4162021-03-29 07:52:161209 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371210 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141211 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371212 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341213 }
1214 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371215 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341216 }
1217 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371218 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341219 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141220 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371221 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341222 } else {
Blink Reformat4c46d092018-04-07 15:32:371223 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341224 }
Blink Reformat4c46d092018-04-07 15:32:371225 }
1226 }
1227
Philip Pfaffe7523faf2021-06-28 14:23:141228 const extensionServer = new (Constructor(ExtensionServerClient))();
1229
1230 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371231
1232 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1233
1234 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141235 // @ts-expect-error
1236 chrome.devtools!.inspectedWindow = {};
1237 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1238 // @ts-expect-error
1239 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1240 chrome.devtools!.network = coreAPI.network;
1241 chrome.devtools!.panels = coreAPI.panels;
1242 chrome.devtools!.panels.themeName = themeName;
1243 chrome.devtools!.languageServices = coreAPI.languageServices;
Blink Reformat4c46d092018-04-07 15:32:371244
1245 // default to expose experimental APIs for now.
1246 if (extensionInfo.exposeExperimentalAPIs !== false) {
1247 chrome.experimental = chrome.experimental || {};
1248 chrome.experimental.devtools = chrome.experimental.devtools || {};
1249
1250 const properties = Object.getOwnPropertyNames(coreAPI);
1251 for (let i = 0; i < properties.length; ++i) {
1252 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341253 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371254 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341255 }
Blink Reformat4c46d092018-04-07 15:32:371256 }
1257 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1258 }
1259
Tim van der Lippe1d6e57a2019-09-30 11:55:341260 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371261 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341262 }
Blink Reformat4c46d092018-04-07 15:32:371263 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121264};
Blink Reformat4c46d092018-04-07 15:32:371265
Jan Schefflerd76b4162021-03-29 07:52:161266self.buildExtensionAPIInjectedScript = function(
1267 extensionInfo: {
1268 startPage: string,
1269 name: string,
1270 exposeExperimentalAPIs: boolean,
1271 },
1272 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141273 testHook:
1274 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1275 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251276 const argumentsJSON =
1277 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341278 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161279 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341280 }
Philip Pfaffe939605d2021-06-25 12:20:041281 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121282 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371283 '})';
Tim van der Lippe29fab472019-08-15 14:46:481284};