blob: 8d62dbe622aa7f782c7409831d7365cd1db5113e [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
Philip Pfaffe4b88c662021-06-25 12:30:4732import type * as HAR from '../har/har.js';
Philip Pfaffe7523faf2021-06-28 14:23:1433
Philip Pfaffeddf60d22021-06-25 12:35:4134/* eslint-disable @typescript-eslint/naming-convention,@typescript-eslint/no-non-null-assertion */
Philip Pfaffe939605d2021-06-25 12:20:0435export namespace PrivateAPI {
36 export namespace Panels {
37 export const enum SearchAction {
38 CancelSearch = 'cancelSearch',
39 PerformSearch = 'performSearch',
40 NextSearchResult = 'nextSearchResult',
41 PreviousSearchResult = 'previousSearchResult',
42 }
Tim van der Lippe1d6e57a2019-09-30 11:55:3443 }
Blink Reformat4c46d092018-04-07 15:32:3744
Philip Pfaffe939605d2021-06-25 12:20:0445 export const enum Events {
46 ButtonClicked = 'button-clicked-',
47 PanelObjectSelected = 'panel-objectSelected-',
48 InspectedURLChanged = 'inspected-url-changed',
49 NetworkRequestFinished = 'network-request-finished',
50 OpenResource = 'open-resource',
51 PanelSearch = 'panel-search-',
52 RecordingStarted = 'trace-recording-started-',
53 RecordingStopped = 'trace-recording-stopped-',
54 ResourceAdded = 'resource-added',
55 ResourceContentCommitted = 'resource-content-committed',
56 ViewShown = 'view-shown-',
57 ViewHidden = 'view-hidden,',
58 }
Blink Reformat4c46d092018-04-07 15:32:3759
Philip Pfaffe939605d2021-06-25 12:20:0460 export const enum Commands {
61 AddRequestHeaders = 'addRequestHeaders',
62 AddTraceProvider = 'addTraceProvider',
63 ApplyStyleSheet = 'applyStyleSheet',
64 CompleteTraceSession = 'completeTra.eSession',
65 CreatePanel = 'createPanel',
66 CreateSidebarPane = 'createSidebarPane',
67 CreateToolbarButton = 'createToolbarButton',
68 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
69 ForwardKeyboardEvent = '_forwardKeyboardEvent',
70 GetHAR = 'getHAR',
71 GetPageResources = 'getPageResources',
72 GetRequestContent = 'getRequestContent',
73 GetResourceContent = 'getResourceContent',
74 OpenResource = 'openResource',
75 Reload = 'Reload',
76 Subscribe = 'subscribe',
77 SetOpenResourceHandler = 'setOpenResourceHandler',
78 SetResourceContent = 'setResourceContent',
79 SetSidebarContent = 'setSidebarContent',
80 SetSidebarHeight = 'setSidebarHeight',
81 SetSidebarPage = 'setSidebarPage',
82 ShowPanel = 'showPanel',
83 Unsubscribe = 'unsubscribe',
84 UpdateButton = 'updateButton',
85 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
86 }
Philip Pfaffeedad8322020-07-20 10:24:2587
Philip Pfaffe939605d2021-06-25 12:20:0488 export const enum LanguageExtensionPluginCommands {
89 AddRawModule = 'addRawModule',
90 RemoveRawModule = 'removeRawModule',
91 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
92 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
93 GetScopeInfo = 'getScopeInfo',
94 ListVariablesInScope = 'listVariablesInScope',
95 GetTypeInfo = 'getTypeInfo',
96 GetFormatter = 'getFormatter',
97 GetInspectableAddress = 'getInspectableAddress',
98 GetFunctionInfo = 'getFunctionInfo',
99 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
100 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
101 GetMappedLines = 'getMappedLines',
102 }
Benedikt Meurer929fc7c2020-11-20 14:21:06103
Philip Pfaffe939605d2021-06-25 12:20:04104 export const enum LanguageExtensionPluginEvents {
105 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
106 }
Philip Pfaffed662bdf2021-06-25 13:30:32107
108 export interface EvaluateOptions {
109 frameURL?: string;
110 useContentScriptContext?: boolean;
111 scriptExecutionContext?: string;
112 }
113
Philip Pfaffed662bdf2021-06-25 13:30:32114 type RegisterLanguageExtensionPluginRequest = {
115 command: Commands.RegisterLanguageExtensionPlugin,
116 pluginName: string,
117 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14118 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32119 };
120 type SubscribeRequest = {command: Commands.Subscribe, type: string};
121 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
122 type AddRequestHeadersRequest = {
123 command: Commands.AddRequestHeaders,
124 extensionId: string,
125 headers: {[key: string]: string},
126 };
127 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
128 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
129 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
130 type CreateToolbarButtonRequest = {
131 command: Commands.CreateToolbarButton,
132 id: string,
133 icon: string,
134 panel: string,
135 tooltip?: string,
136 disabled?: boolean,
137 };
138 type UpdateButtonRequest =
139 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
140 type CompleteTraceSessionRequest =
141 {command: Commands.CompleteTraceSession, id: string, url: string, timeOffset: number};
142 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
143 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
144 type SetSidebarContentRequest = {
145 command: Commands.SetSidebarContent,
146 id: string,
147 evaluateOnPage?: boolean, expression: string,
148 rootTitle?: string,
149 evaluateOptions?: EvaluateOptions,
150 };
151 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Philip Pfaffe140e5432021-09-13 16:34:23152 type OpenResourceRequest = {command: Commands.OpenResource, url: string, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32153 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
154 type ReloadRequest = {
155 command: Commands.Reload,
156 options: null|{
157 userAgent?: string,
158 injectedScript?: string,
159 ignoreCache?: boolean,
160 },
161 };
162 type EvaluateOnInspectedPageRequest = {
163 command: Commands.EvaluateOnInspectedPage,
164 expression: string,
165 evaluateOptions?: EvaluateOptions,
166 };
167 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
168 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
169 type SetResourceContentRequest =
170 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
171 type AddTraceProviderRequest =
172 {command: Commands.AddTraceProvider, id: string, categoryName: string, categoryTooltip: string};
173 type ForwardKeyboardEventRequest = {
174 command: Commands.ForwardKeyboardEvent,
175 entries: Array<KeyboardEventInit&{eventType: string}>,
176 };
177 type GetHARRequest = {command: Commands.GetHAR};
178 type GetPageResourcesRequest = {command: Commands.GetPageResources};
179
180 export type ServerRequests = RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|
181 AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|
182 UpdateButtonRequest|CompleteTraceSessionRequest|CreateSidebarPaneRequest|SetSidebarHeightRequest|
183 SetSidebarContentRequest|SetSidebarPageRequest|OpenResourceRequest|SetOpenResourceHandlerRequest|ReloadRequest|
184 EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
185 AddTraceProviderRequest|ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest;
186 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32187
188 type AddRawModuleRequest = {
189 method: LanguageExtensionPluginCommands.AddRawModule,
190 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
191 };
192 type SourceLocationToRawLocationRequest = {
193 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
194 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
195 };
196 type RawLocationToSourceLocationRequest = {
197 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
198 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
199 };
200 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
201 type ListVariablesInScopeRequest = {
202 method: LanguageExtensionPluginCommands.ListVariablesInScope,
203 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
204 };
205 type RemoveRawModuleRequest = {
206 method: LanguageExtensionPluginCommands.RemoveRawModule,
207 parameters: {rawModuleId: string},
208 };
209 type GetTypeInfoRequest = {
210 method: LanguageExtensionPluginCommands.GetTypeInfo,
211 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation},
212 };
213 type GetFormatterRequest = {
214 method: LanguageExtensionPluginCommands.GetFormatter,
215 parameters: {
216 expressionOrField: string|{
217 base: PublicAPI.Chrome.DevTools.EvalBase,
218 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
219 },
220 context: PublicAPI.Chrome.DevTools.RawLocation,
221 },
222 };
223 type GetInspectableAddressRequest = {
224 method: LanguageExtensionPluginCommands.GetInspectableAddress,
225 parameters: {
226 field: {
227 base: PublicAPI.Chrome.DevTools.EvalBase,
228 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
229 },
230 },
231 };
232 type GetFunctionInfoRequest = {
233 method: LanguageExtensionPluginCommands.GetFunctionInfo,
234 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
235 };
236 type GetInlinedFunctionRangesRequest = {
237 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
238 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
239 };
240 type GetInlinedCalleesRangesRequest = {
241 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
242 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
243 };
244 type GetMappedLinesRequest = {
245 method: LanguageExtensionPluginCommands.GetMappedLines,
246 parameters: {rawModuleId: string, sourceFileURL: string},
247 };
248
249 export type LanguageExtensionRequests = AddRawModuleRequest|SourceLocationToRawLocationRequest|
250 RawLocationToSourceLocationRequest|GetScopeInfoRequest|ListVariablesInScopeRequest|RemoveRawModuleRequest|
251 GetTypeInfoRequest|GetFormatterRequest|GetInspectableAddressRequest|GetFunctionInfoRequest|
252 GetInlinedFunctionRangesRequest|GetInlinedCalleesRangesRequest|GetMappedLinesRequest;
Blink Reformat4c46d092018-04-07 15:32:37253}
254
Philip Pfaffe939605d2021-06-25 12:20:04255declare global {
256 interface Window {
257 injectedExtensionAPI:
258 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14259 testHook:
260 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23261 injectedScriptId: number) => void;
Philip Pfaffe939605d2021-06-25 12:20:04262 buildExtensionAPIInjectedScript(
263 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32264 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14265 chrome: PublicAPI.Chrome.DevTools.Chrome;
266 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04267 }
268}
269
270export type ExtensionDescriptor = {
271 startPage: string,
272 name: string,
273 exposeExperimentalAPIs: boolean,
274 exposeWebInspectorNamespace?: boolean,
275};
276
Philip Pfaffe7523faf2021-06-28 14:23:14277namespace APIImpl {
278 export interface InspectorExtensionAPI {
279 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Philip Pfaffe1c827212021-06-25 12:33:20280 timeline: Timeline;
Philip Pfaffe7523faf2021-06-28 14:23:14281 network: PublicAPI.Chrome.DevTools.Network;
282 panels: PublicAPI.Chrome.DevTools.Panels;
283 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
284 }
285
286 export interface ExtensionServerClient {
287 _callbacks: {[key: string]: (response: unknown) => unknown};
288 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
289 _lastRequestId: number;
290 _lastObjectId: number;
291 _port: MessagePort;
292
293 _onCallback(request: unknown): void;
294 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
295 _registerCallback(callback: (response: unknown) => unknown): number;
296 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
297 unregisterHandler(command: string): void;
298 hasHandler(command: string): boolean;
299 sendRequest(request: PrivateAPI.ServerRequests, callback?: ((response: unknown) => unknown), transfers?: unknown[]):
300 void;
301 nextObjectId(): string;
302 }
303
304 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
305 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
306 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28307 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14308 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28309 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14310
311 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
312 _type: string;
313 _listeners: ListenerT[];
314 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
315
316 _fire(..._vararg: Parameters<ListenerT>): void;
317 _dispatch(request: {arguments: unknown[]}): void;
318 }
Philip Pfaffe4b88c662021-06-25 12:30:47319
320 export interface Network extends PublicAPI.Chrome.DevTools.Network {
321 addRequestHeaders(headers: {[key: string]: string}): void;
322 }
323
324 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
325 _id: number;
326 }
Philip Pfaffe6fd04c42021-06-25 12:31:48327
328 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
329 get SearchAction(): {[key: string]: string};
330 applyStyleSheet(styleSheet: string): void;
331 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
332 void;
333 }
334
335 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
336 _id: string|null;
337 }
338
339 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
340 setExpression(
341 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
342 callback?: () => unknown): void;
343 }
344
345 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
346 _hostPanelName: string;
347 }
348
349 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
350 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
351 }
352
353 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
354 show(): void;
355 }
356
357 export interface Button extends PublicAPI.Chrome.DevTools.Button {
358 _id: string;
359 }
360
Philip Pfaffe1c827212021-06-25 12:33:20361 export interface TraceSession {
362 _id: string;
363
364 complete(url?: string, timeOffset?: number): void;
365 }
366
367 export interface TraceProvider {
368 onRecordingStarted: EventSink<(session: TraceSession) => unknown>;
369 onRecordingStopped: EventSink<() => unknown>;
370 }
371
372 export interface Timeline {
373 addTraceProvider(categoryName: string, categoryTooltip: string): TraceProvider;
374 }
375
Philip Pfaffe6fd04c42021-06-25 12:31:48376 export type ResourceData = {url: string, type: string};
377 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
378 _type: string;
379 _url: string;
380
381 get type(): string;
382 }
Philip Pfaffe7523faf2021-06-28 14:23:14383}
Philip Pfaffe939605d2021-06-25 12:20:04384
Tim van der Lippe226fc222019-10-10 12:17:12385self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14386 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
387 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23388 injectedScriptId: number): void {
Jan Schefflerd76b4162021-03-29 07:52:16389 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37390 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16391
Blink Reformat4c46d092018-04-07 15:32:37392 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34393 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37394 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34395 }
Blink Reformat4c46d092018-04-07 15:32:37396 let userAction = false;
397
398 // Here and below, all constructors are private to API implementation.
399 // For a public type Foo, if internal fields are present, these are on
400 // a private FooImpl type, an instance of FooImpl is used in a closure
401 // by Foo consutrctor to re-bind publicly exported members to an instance
402 // of Foo.
403
Philip Pfaffe7523faf2021-06-28 14:23:14404 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
405 this: APIImpl.EventSink<ListenerT>, type: string,
406 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37407 this._type = type;
408 this._listeners = [];
409 this._customDispatch = customDispatch;
410 }
411
412 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14413 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
414 void {
415 if (typeof callback !== 'function') {
416 throw 'addListener: callback is not a function';
417 }
418 if (this._listeners.length === 0) {
419 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
420 }
421 this._listeners.push(callback);
422 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
423 },
Blink Reformat4c46d092018-04-07 15:32:37424
Philip Pfaffe7523faf2021-06-28 14:23:14425 removeListener: function<ListenerT extends APIImpl.Callable>(
426 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37427 const listeners = this._listeners;
428
429 for (let i = 0; i < listeners.length; ++i) {
430 if (listeners[i] === callback) {
431 listeners.splice(i, 1);
432 break;
433 }
434 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34435 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04436 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34437 }
Blink Reformat4c46d092018-04-07 15:32:37438 },
439
Philip Pfaffe7523faf2021-06-28 14:23:14440 _fire: function<ListenerT extends APIImpl.Callable>(
441 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37442 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34443 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14444 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34445 }
Blink Reformat4c46d092018-04-07 15:32:37446 },
447
Philip Pfaffe7523faf2021-06-28 14:23:14448 _dispatch: function<ListenerT extends APIImpl.Callable>(
449 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34450 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37451 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34452 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14453 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34454 }
Jan Schefflerd76b4162021-03-29 07:52:16455 },
Blink Reformat4c46d092018-04-07 15:32:37456 };
457
Philip Pfaffe7523faf2021-06-28 14:23:14458 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
459 ThisParameterType<NewT> {
460 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
461 }
462
Philip Pfaffe7523faf2021-06-28 14:23:14463 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41464 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48465 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47466 this.network = new (Constructor(Network))();
Philip Pfaffe1c827212021-06-25 12:33:20467 this.timeline = new (Constructor(Timeline))();
Philip Pfaffec5d160e2021-07-20 10:53:32468 this.languageServices = new (Constructor(LanguageServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37469 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
470 }
471
Philip Pfaffe4b88c662021-06-25 12:30:47472 function Network(this: APIImpl.Network): void {
473 function dispatchRequestEvent(
474 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
475 message: {arguments: unknown[]}): void {
476 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
477
478 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37479 this._fire(request);
480 }
Philip Pfaffe4b88c662021-06-25 12:30:47481
482 this.onRequestFinished =
483 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37484 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47485
486 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37487 }
488
Philip Pfaffe4b88c662021-06-25 12:30:47489 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
490 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
491 function callbackWrapper(response: unknown): void {
492 const result =
493 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37494 const entries = (result && result.entries) || [];
495 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47496 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37497 delete entries[i]._requestId;
498 }
Philip Pfaffe4b88c662021-06-25 12:30:47499 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37500 }
Philip Pfaffe939605d2021-06-25 12:20:04501 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37502 },
503
Philip Pfaffe4b88c662021-06-25 12:30:47504 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37505 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04506 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16507 },
Blink Reformat4c46d092018-04-07 15:32:37508 };
509
Philip Pfaffe4b88c662021-06-25 12:30:47510 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37511 this._id = id;
512 }
513
Philip Pfaffe4b88c662021-06-25 12:30:47514 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
515 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
516 function callbackWrapper(response: unknown): void {
517 const {content, encoding} = response as {content: string, encoding: string};
518 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37519 }
Philip Pfaffe939605d2021-06-25 12:20:04520 extensionServer.sendRequest(
521 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16522 },
Blink Reformat4c46d092018-04-07 15:32:37523 };
524
Philip Pfaffe6fd04c42021-06-25 12:31:48525 function Panels(this: APIImpl.Panels): void {
526 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37527 elements: new ElementsPanel(),
528 sources: new SourcesPanel(),
529 };
530
Philip Pfaffe6fd04c42021-06-25 12:31:48531 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37532 return panels[name];
533 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34534 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12535 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34536 }
Philip Pfaffe6fd04c42021-06-25 12:31:48537 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04538 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37539 };
540 }
541
Philip Pfaffe6fd04c42021-06-25 12:31:48542 (Panels.prototype as Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'>) = {
543 create: function(
544 title: string, icon: string, page: string,
545 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37546 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48547 extensionServer.sendRequest(
548 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37549 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37550 },
551
Philip Pfaffe6fd04c42021-06-25 12:31:48552 setOpenResourceHandler: function(
553 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04554 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37555
Philip Pfaffe6fd04c42021-06-25 12:31:48556 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37557 // Allow the panel to show itself when handling the event.
558 userAction = true;
559 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48560 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
561 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
Blink Reformat4c46d092018-04-07 15:32:37562 } finally {
563 userAction = false;
564 }
565 }
566
Tim van der Lippe1d6e57a2019-09-30 11:55:34567 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04568 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34569 } else {
Philip Pfaffe939605d2021-06-25 12:20:04570 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34571 }
Blink Reformat4c46d092018-04-07 15:32:37572
573 // 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:34574 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04575 extensionServer.sendRequest(
576 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34577 }
Blink Reformat4c46d092018-04-07 15:32:37578 },
579
Philip Pfaffe140e5432021-09-13 16:34:23580 openResource: function(
581 url: string, lineNumber: number, columnNumber?: number, _callback?: (response: unknown) => unknown): void {
582 const callbackArg = extractCallbackArgument(arguments);
583 // Handle older API:
584 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
585 extensionServer.sendRequest(
586 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37587 },
588
Philip Pfaffe6fd04c42021-06-25 12:31:48589 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04590 return {
591 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
592 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
593 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
594 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
595 };
Jan Schefflerd76b4162021-03-29 07:52:16596 },
Blink Reformat4c46d092018-04-07 15:32:37597 };
598
Philip Pfaffe6fd04c42021-06-25 12:31:48599 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37600 this._id = id;
601
Philip Pfaffe6fd04c42021-06-25 12:31:48602 function dispatchShowEvent(
603 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37604 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34605 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37606 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34607 } else {
Blink Reformat4c46d092018-04-07 15:32:37608 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34609 }
Blink Reformat4c46d092018-04-07 15:32:37610 }
611
612 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48613 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
614
615 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37616 }
617 }
618
Philip Pfaffe6fd04c42021-06-25 12:31:48619 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37620 ExtensionViewImpl.call(this, null);
621 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48622
623 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37624 }
625
Philip Pfaffe6fd04c42021-06-25 12:31:48626 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
627 {__proto__: APIImpl.ExtensionView}) = {
628 createSidebarPane: function(
629 this: APIImpl.PanelWithSidebar, title: string,
630 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37631 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16632 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48633 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37634 }
Philip Pfaffe7523faf2021-06-28 14:23:14635 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48636 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14637 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37638 },
639
Jan Schefflerd76b4162021-03-29 07:52:16640 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37641 };
642
Philip Pfaffec5d160e2021-07-20 10:53:32643 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25644 this._plugins = new Map();
645 }
646
Philip Pfaffec5d160e2021-07-20 10:53:32647 (LanguageServicesAPIImpl.prototype as
648 Pick<APIImpl.LanguageExtensions, 'registerLanguageExtensionPlugin'|'unregisterLanguageExtensionPlugin'>) = {
Philip Pfaffed662bdf2021-06-25 13:30:32649 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32650 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
651 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
652 if (this._plugins.has(plugin)) {
653 throw new Error(`Tried to register plugin '${pluginName}' twice`);
654 }
655 const channel = new MessageChannel();
656 const port = channel.port1;
657 this._plugins.set(plugin, port);
658 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
659 const {requestId} = data;
660 console.time(`${requestId}: ${data.method}`);
661 dispatchMethodCall(data)
662 .then(result => port.postMessage({requestId, result}))
663 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
664 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
665 };
Philip Pfaffeedad8322020-07-20 10:24:25666
Philip Pfaffec5d160e2021-07-20 10:53:32667 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
668 switch (request.method) {
669 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
670 return plugin.addRawModule(
671 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
672 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
673 return plugin.removeRawModule(request.parameters.rawModuleId);
674 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
675 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
676 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
677 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
678 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
679 return plugin.getScopeInfo(request.parameters.type);
680 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
681 return plugin.listVariablesInScope(request.parameters.rawLocation);
682 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
683 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
684 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
685 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
686 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
687 if ('getInspectableAddress' in plugin) {
688 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02689 }
Philip Pfaffec5d160e2021-07-20 10:53:32690 return Promise.resolve({js: ''});
691 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
692 return plugin.getFunctionInfo(request.parameters.rawLocation);
693 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
694 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
695 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
696 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
697 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
698 if ('getMappedLines' in plugin) {
699 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
700 }
701 return Promise.resolve(undefined);
702 }
703 // @ts-expect-error
704 throw new Error(`Unknown language plugin method ${request.method}`);
705 }
Philip Pfaffeedad8322020-07-20 10:24:25706
Philip Pfaffec5d160e2021-07-20 10:53:32707 await new Promise<void>(resolve => {
708 extensionServer.sendRequest(
709 {
710 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
711 pluginName,
712 port: channel.port2,
713 supportedScriptTypes,
714 },
715 () => resolve(), [channel.port2]);
716 });
717 },
Benedikt Meurer929fc7c2020-11-20 14:21:06718
Philip Pfaffec5d160e2021-07-20 10:53:32719 unregisterLanguageExtensionPlugin: async function(
720 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06721 const port = this._plugins.get(plugin);
722 if (!port) {
723 throw new Error('Tried to unregister a plugin that was not previously registered');
724 }
725 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04726 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06727 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16728 },
Philip Pfaffeedad8322020-07-20 10:24:25729 };
730
Philip Pfaffe7523faf2021-06-28 14:23:14731 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
732 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
733 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37734 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14735 implConstructor.apply(impl, args);
736 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37737 };
738 }
739
Philip Pfaffe7523faf2021-06-28 14:23:14740 // eslint-disable-next-line @typescript-eslint/no-explicit-any
741 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37742 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14743 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37744 if (!warningGiven) {
745 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
746 warningGiven = true;
747 }
748 return object[newName];
749 }
750 object.__defineGetter__(oldName, getter);
751 }
752
Philip Pfaffe7523faf2021-06-28 14:23:14753 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37754 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14755 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37756 }
757
Philip Pfaffeedad8322020-07-20 10:24:25758 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37759 const Button = declareInterfaceClass(ButtonImpl);
760 const EventSink = declareInterfaceClass(EventSinkImpl);
761 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
762 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12763 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37764 const Request = declareInterfaceClass(RequestImpl);
765 const Resource = declareInterfaceClass(ResourceImpl);
766 const TraceSession = declareInterfaceClass(TraceSessionImpl);
767
Philip Pfaffe6fd04c42021-06-25 12:31:48768 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12769 constructor() {
770 super('elements');
771 }
Blink Reformat4c46d092018-04-07 15:32:37772 }
773
Philip Pfaffe6fd04c42021-06-25 12:31:48774 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12775 constructor() {
776 super('sources');
777 }
Blink Reformat4c46d092018-04-07 15:32:37778 }
779
Philip Pfaffe6fd04c42021-06-25 12:31:48780 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37781 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48782
783 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37784 }
785
Philip Pfaffe6fd04c42021-06-25 12:31:48786 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
787 {__proto__: APIImpl.ExtensionView}) = {
788 createStatusBarButton: function(
789 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
790 PublicAPI.Chrome.DevTools.Button {
791 const id = 'button-' + extensionServer.nextObjectId();
792 extensionServer.sendRequest({
793 command: PrivateAPI.Commands.CreateToolbarButton,
794 panel: this._id as string,
795 id: id,
796 icon: iconPath,
797 tooltip: tooltipText,
798 disabled: Boolean(disabled),
799 });
Blink Reformat4c46d092018-04-07 15:32:37800
Philip Pfaffe6fd04c42021-06-25 12:31:48801 return new (Constructor(Button))(id);
802 },
803
804 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34805 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:37806 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34807 }
Blink Reformat4c46d092018-04-07 15:32:37808
Philip Pfaffe6fd04c42021-06-25 12:31:48809 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:37810 },
811
Jan Schefflerd76b4162021-03-29 07:52:16812 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37813 };
814
Philip Pfaffe6fd04c42021-06-25 12:31:48815 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37816 ExtensionViewImpl.call(this, id);
817 }
818
Philip Pfaffe6fd04c42021-06-25 12:31:48819 (ExtensionSidebarPaneImpl.prototype as
820 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
821 {__proto__: APIImpl.ExtensionView}) = {
822 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
823 extensionServer.sendRequest(
824 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:37825 },
826
Philip Pfaffe6fd04c42021-06-25 12:31:48827 setExpression: function(
828 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
829 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:14830 extensionServer.sendRequest(
831 {
832 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:48833 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:14834 expression: expression,
835 rootTitle: rootTitle,
836 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:48837 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:14838 },
839 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:37840 },
841
Philip Pfaffe6fd04c42021-06-25 12:31:48842 setObject: function(
843 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37844 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48845 {
846 command: PrivateAPI.Commands.SetSidebarContent,
847 id: this._id as string,
848 expression: jsonObject,
849 rootTitle: rootTitle,
850 },
Philip Pfaffe939605d2021-06-25 12:20:04851 callback);
Blink Reformat4c46d092018-04-07 15:32:37852 },
853
Philip Pfaffe6fd04c42021-06-25 12:31:48854 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
855 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:37856 },
857
Jan Schefflerd76b4162021-03-29 07:52:16858 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37859 };
860
Philip Pfaffe6fd04c42021-06-25 12:31:48861 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37862 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:48863
864 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:37865 }
866
Philip Pfaffe6fd04c42021-06-25 12:31:48867 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
868 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:14869 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04870 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:24871 id: this._id,
872 icon: iconPath,
873 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16874 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:14875 });
Jan Schefflerd76b4162021-03-29 07:52:16876 },
Blink Reformat4c46d092018-04-07 15:32:37877 };
878
Philip Pfaffe1c827212021-06-25 12:33:20879 function Timeline(this: APIImpl.Timeline): void {
Blink Reformat4c46d092018-04-07 15:32:37880 }
881
Philip Pfaffe1c827212021-06-25 12:33:20882 (Timeline.prototype as Pick<APIImpl.Timeline, 'addTraceProvider'>) = {
883 addTraceProvider: function(this: APIImpl.Timeline, categoryName: string, categoryTooltip: string):
884 APIImpl.TraceProvider {
885 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
886 extensionServer.sendRequest({
887 command: PrivateAPI.Commands.AddTraceProvider,
888 id: id,
889 categoryName: categoryName,
890 categoryTooltip: categoryTooltip,
891 });
892
893 return new (Constructor(TraceProvider))(id);
894 },
Blink Reformat4c46d092018-04-07 15:32:37895 };
896
Philip Pfaffe1c827212021-06-25 12:33:20897 function TraceSessionImpl(this: APIImpl.TraceSession, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37898 this._id = id;
899 }
900
Philip Pfaffe1c827212021-06-25 12:33:20901 (TraceSessionImpl.prototype as Pick<APIImpl.TraceSession, 'complete'>) = {
902 complete: function(this: APIImpl.TraceSession, url?: string, timeOffset?: number): void {
Philip Pfaffe7523faf2021-06-28 14:23:14903 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04904 command: PrivateAPI.Commands.CompleteTraceSession,
905 id: this._id,
906 url: url || '',
907 timeOffset: timeOffset || 0,
Philip Pfaffe7523faf2021-06-28 14:23:14908 });
Jan Schefflerd76b4162021-03-29 07:52:16909 },
Blink Reformat4c46d092018-04-07 15:32:37910 };
911
Philip Pfaffe1c827212021-06-25 12:33:20912 function TraceProvider(this: APIImpl.TraceProvider, id: string): void {
913 function dispatchRecordingStarted(
914 this: APIImpl.EventSink<APIImpl.Callable>, message: {arguments: unknown[]}): void {
915 const sessionId = message.arguments[0] as string;
916
917 this._fire(new (Constructor(TraceSession))(sessionId));
Blink Reformat4c46d092018-04-07 15:32:37918 }
919
Philip Pfaffe1c827212021-06-25 12:33:20920 this.onRecordingStarted =
921 new (Constructor(EventSink))(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
922
923 this.onRecordingStopped = new (Constructor(EventSink))(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:37924 }
925
Philip Pfaffeddf60d22021-06-25 12:35:41926 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
927 function dispatchResourceEvent(
928 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
929 this._fire(new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData));
Blink Reformat4c46d092018-04-07 15:32:37930 }
931
Philip Pfaffeddf60d22021-06-25 12:35:41932 function dispatchResourceContentEvent(
933 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
934 message: {arguments: unknown[]}): void {
935 this._fire(
936 new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:37937 }
938
Philip Pfaffeddf60d22021-06-25 12:35:41939 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:04940 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:41941 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:37942 }
943
Philip Pfaffeddf60d22021-06-25 12:35:41944 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
945 reload: function(optionsOrUserAgent: {
946 ignoreCache?: boolean,
947 injectedScript?: string,
948 userAgent?: string,
949 }): void {
Jan Schefflerd76b4162021-03-29 07:52:16950 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:41951 ignoreCache?: boolean,
952 injectedScript?: string,
953 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:16954 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:37955 if (typeof optionsOrUserAgent === 'object') {
956 options = optionsOrUserAgent;
957 } else if (typeof optionsOrUserAgent === 'string') {
958 options = {userAgent: optionsOrUserAgent};
959 console.warn(
960 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
961 'Use inspectedWindow.reload({ userAgent: value}) instead.');
962 }
Philip Pfaffe939605d2021-06-25 12:20:04963 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:37964 },
965
Philip Pfaffeddf60d22021-06-25 12:35:41966 eval: function(
967 expression: string,
968 evaluateOptions: {contextSecurityOrigin?: string, frameURL?: string, useContentScriptContext?: boolean}):
969 Object |
Jan Schefflerd76b4162021-03-29 07:52:16970 null {
971 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:41972 function callbackWrapper(result: unknown): void {
973 const {isError, isException, value} = result as {
974 isError?: boolean,
975 isException?: boolean, value: unknown,
976 };
977 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:14978 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:16979 } else {
Philip Pfaffeddf60d22021-06-25 12:35:41980 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:16981 }
982 }
Philip Pfaffe7523faf2021-06-28 14:23:14983 extensionServer.sendRequest(
984 {
985 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
986 expression: expression,
987 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
988 },
989 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16990 return null;
991 },
Blink Reformat4c46d092018-04-07 15:32:37992
Philip Pfaffeddf60d22021-06-25 12:35:41993 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
994 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
995 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:37996 }
Philip Pfaffeddf60d22021-06-25 12:35:41997 function callbackWrapper(resources: unknown): void {
998 callback && callback((resources as APIImpl.ResourceData[]).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:37999 }
Philip Pfaffe939605d2021-06-25 12:20:041000 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161001 },
Blink Reformat4c46d092018-04-07 15:32:371002 };
1003
Philip Pfaffe6fd04c42021-06-25 12:31:481004 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Blink Reformat4c46d092018-04-07 15:32:371005 this._url = resourceData.url;
1006 this._type = resourceData.type;
1007 }
1008
Philip Pfaffe6fd04c42021-06-25 12:31:481009 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161010 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481011 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371012 },
1013
Jan Schefflerd76b4162021-03-29 07:52:161014 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481015 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371016 },
1017
Philip Pfaffe6fd04c42021-06-25 12:31:481018 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1019 function callbackWrapper(response: unknown): void {
1020 const {content, encoding} = response as {content: string, encoding: string};
1021 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371022 }
1023
Philip Pfaffe939605d2021-06-25 12:20:041024 extensionServer.sendRequest(
1025 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371026 },
1027
Philip Pfaffe6fd04c42021-06-25 12:31:481028 setContent: function(
1029 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371030 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041031 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481032 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161033 },
Blink Reformat4c46d092018-04-07 15:32:371034 };
1035
Jan Schefflerd76b4162021-03-29 07:52:161036 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371037 return inspectedTabId;
1038 }
1039
Philip Pfaffe7523faf2021-06-28 14:23:141040 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161041 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141042 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521043 // Check if the event should be forwarded.
1044 // This is a workaround for crbug.com/923338.
1045 const focused = document.activeElement;
1046 if (focused) {
1047 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
1048 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1049 return;
1050 }
1051 }
1052
Joel Einbinder67f28fb2018-08-02 00:33:471053 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341054 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471055 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341056 }
1057 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471058 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341059 }
1060 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471061 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341062 }
1063 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471064 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341065 }
Joel Einbinder67f28fb2018-08-02 00:33:471066 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371067 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341068 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371069 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341070 }
Joel Einbinder67f28fb2018-08-02 00:33:471071 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371072 const requestPayload = {
1073 eventType: event.type,
1074 ctrlKey: event.ctrlKey,
1075 altKey: event.altKey,
1076 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471077 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141078 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371079 keyIdentifier: event.keyIdentifier,
1080 key: event.key,
1081 code: event.code,
1082 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161083 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371084 };
1085 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341086 if (!forwardTimer) {
Blink Reformat4c46d092018-04-07 15:32:371087 forwardTimer = setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341088 }
Blink Reformat4c46d092018-04-07 15:32:371089 }
1090
Jan Schefflerd76b4162021-03-29 07:52:161091 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371092 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141093 extensionServer.sendRequest(
1094 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371095 keyboardEventRequestQueue = [];
1096 }
1097
1098 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371099
Philip Pfaffe7523faf2021-06-28 14:23:141100 function ExtensionServerClient(this: APIImpl.ExtensionServerClient): void {
Blink Reformat4c46d092018-04-07 15:32:371101 this._callbacks = {};
1102 this._handlers = {};
1103 this._lastRequestId = 0;
1104 this._lastObjectId = 0;
1105
1106 this.registerHandler('callback', this._onCallback.bind(this));
1107
1108 const channel = new MessageChannel();
1109 this._port = channel.port1;
1110 this._port.addEventListener('message', this._onMessage.bind(this), false);
1111 this._port.start();
1112
1113 window.parent.postMessage('registerExtension', '*', [channel.port2]);
1114 }
1115
Philip Pfaffe7523faf2021-06-28 14:23:141116 (ExtensionServerClient.prototype as Pick<
1117 APIImpl.ExtensionServerClient,
1118 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1119 '_onCallback'|'_onMessage'>) = {
1120 sendRequest: function(
1121 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
1122 callback?: (response: unknown) => unknown, transfers?: Transferable[]): void {
1123 if (typeof callback === 'function') {
1124 (message as PrivateAPI.ExtensionServerRequestMessage).requestId = this._registerCallback(callback);
1125 }
1126 // @ts-expect-error
1127 this._port.postMessage(message, transfers);
1128 },
Blink Reformat4c46d092018-04-07 15:32:371129
Philip Pfaffe7523faf2021-06-28 14:23:141130 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241131 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371132 },
1133
Philip Pfaffe7523faf2021-06-28 14:23:141134 registerHandler: function(
1135 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1136 void {
1137 this._handlers[command] = handler;
1138 },
Blink Reformat4c46d092018-04-07 15:32:371139
Philip Pfaffe7523faf2021-06-28 14:23:141140 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371141 delete this._handlers[command];
1142 },
1143
Philip Pfaffe7523faf2021-06-28 14:23:141144 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371145 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1146 },
1147
Philip Pfaffe7523faf2021-06-28 14:23:141148 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371149 const id = ++this._lastRequestId;
1150 this._callbacks[id] = callback;
1151 return id;
1152 },
1153
Philip Pfaffe7523faf2021-06-28 14:23:141154 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371155 if (request.requestId in this._callbacks) {
1156 const callback = this._callbacks[request.requestId];
1157 delete this._callbacks[request.requestId];
1158 callback(request.result);
1159 }
1160 },
1161
Philip Pfaffe7523faf2021-06-28 14:23:141162 _onMessage: function(
1163 this: APIImpl.ExtensionServerClient,
1164 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371165 const request = event.data;
1166 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341167 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371168 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341169 }
Jan Schefflerd76b4162021-03-29 07:52:161170 },
Blink Reformat4c46d092018-04-07 15:32:371171 };
1172
Philip Pfaffe7523faf2021-06-28 14:23:141173 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371174 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341175 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371176 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341177 }
Jan Schefflerd76b4162021-03-29 07:52:161178 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371179 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141180 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371181 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341182 }
1183 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371184 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341185 }
1186 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371187 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341188 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141189 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371190 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341191 } else {
Blink Reformat4c46d092018-04-07 15:32:371192 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341193 }
Blink Reformat4c46d092018-04-07 15:32:371194 }
1195 }
1196
Philip Pfaffe7523faf2021-06-28 14:23:141197 const extensionServer = new (Constructor(ExtensionServerClient))();
1198
1199 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371200
1201 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1202
1203 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141204 // @ts-expect-error
1205 chrome.devtools!.inspectedWindow = {};
1206 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1207 // @ts-expect-error
1208 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1209 chrome.devtools!.network = coreAPI.network;
1210 chrome.devtools!.panels = coreAPI.panels;
1211 chrome.devtools!.panels.themeName = themeName;
1212 chrome.devtools!.languageServices = coreAPI.languageServices;
Blink Reformat4c46d092018-04-07 15:32:371213
1214 // default to expose experimental APIs for now.
1215 if (extensionInfo.exposeExperimentalAPIs !== false) {
1216 chrome.experimental = chrome.experimental || {};
1217 chrome.experimental.devtools = chrome.experimental.devtools || {};
1218
1219 const properties = Object.getOwnPropertyNames(coreAPI);
1220 for (let i = 0; i < properties.length; ++i) {
1221 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341222 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371223 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341224 }
Blink Reformat4c46d092018-04-07 15:32:371225 }
1226 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1227 }
1228
Tim van der Lippe1d6e57a2019-09-30 11:55:341229 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371230 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341231 }
Blink Reformat4c46d092018-04-07 15:32:371232 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121233};
Blink Reformat4c46d092018-04-07 15:32:371234
Jan Schefflerd76b4162021-03-29 07:52:161235self.buildExtensionAPIInjectedScript = function(
1236 extensionInfo: {
1237 startPage: string,
1238 name: string,
1239 exposeExperimentalAPIs: boolean,
1240 },
1241 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141242 testHook:
1243 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1244 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251245 const argumentsJSON =
1246 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341247 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161248 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341249 }
Philip Pfaffe939605d2021-06-25 12:20:041250 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121251 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371252 '})';
Tim van der Lippe29fab472019-08-15 14:46:481253};