blob: 75ba64f8212775d686513cd365f852872eadd581 [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
34/* eslint-disable @typescript-eslint/no-explicit-any,@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};
152 type OpenResourceRequest = {command: Commands.OpenResource, url: string, lineNumber: number};
153 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,
261 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;
280 network: PublicAPI.Chrome.DevTools.Network;
281 panels: PublicAPI.Chrome.DevTools.Panels;
282 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
283 }
284
285 export interface ExtensionServerClient {
286 _callbacks: {[key: string]: (response: unknown) => unknown};
287 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
288 _lastRequestId: number;
289 _lastObjectId: number;
290 _port: MessagePort;
291
292 _onCallback(request: unknown): void;
293 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
294 _registerCallback(callback: (response: unknown) => unknown): number;
295 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
296 unregisterHandler(command: string): void;
297 hasHandler(command: string): boolean;
298 sendRequest(request: PrivateAPI.ServerRequests, callback?: ((response: unknown) => unknown), transfers?: unknown[]):
299 void;
300 nextObjectId(): string;
301 }
302
303 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
304 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
305 // resolution and meaningful type inference of arguments break, for example.
306 // eslint-disable-next-line @typescript-eslint/no-explicit-any
307 export type Callable = (...args: any) => any;
308
309 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
310 _type: string;
311 _listeners: ListenerT[];
312 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
313
314 _fire(..._vararg: Parameters<ListenerT>): void;
315 _dispatch(request: {arguments: unknown[]}): void;
316 }
Philip Pfaffe4b88c662021-06-25 12:30:47317
318 export interface Network extends PublicAPI.Chrome.DevTools.Network {
319 addRequestHeaders(headers: {[key: string]: string}): void;
320 }
321
322 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
323 _id: number;
324 }
Philip Pfaffe6fd04c42021-06-25 12:31:48325
326 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
327 get SearchAction(): {[key: string]: string};
328 applyStyleSheet(styleSheet: string): void;
329 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
330 void;
331 }
332
333 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
334 _id: string|null;
335 }
336
337 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
338 setExpression(
339 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
340 callback?: () => unknown): void;
341 }
342
343 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
344 _hostPanelName: string;
345 }
346
347 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
348 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
349 }
350
351 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
352 show(): void;
353 }
354
355 export interface Button extends PublicAPI.Chrome.DevTools.Button {
356 _id: string;
357 }
358
359 export type ResourceData = {url: string, type: string};
360 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
361 _type: string;
362 _url: string;
363
364 get type(): string;
365 }
Philip Pfaffe7523faf2021-06-28 14:23:14366}
Philip Pfaffe939605d2021-06-25 12:20:04367
Tim van der Lippe226fc222019-10-10 12:17:12368self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14369 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
370 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
371 injectedScriptId: number): void {
Jan Schefflerd76b4162021-03-29 07:52:16372 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37373 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16374
Blink Reformat4c46d092018-04-07 15:32:37375 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34376 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37377 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34378 }
Blink Reformat4c46d092018-04-07 15:32:37379 let userAction = false;
380
381 // Here and below, all constructors are private to API implementation.
382 // For a public type Foo, if internal fields are present, these are on
383 // a private FooImpl type, an instance of FooImpl is used in a closure
384 // by Foo consutrctor to re-bind publicly exported members to an instance
385 // of Foo.
386
Philip Pfaffe7523faf2021-06-28 14:23:14387 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
388 this: APIImpl.EventSink<ListenerT>, type: string,
389 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37390 this._type = type;
391 this._listeners = [];
392 this._customDispatch = customDispatch;
393 }
394
395 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14396 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
397 void {
398 if (typeof callback !== 'function') {
399 throw 'addListener: callback is not a function';
400 }
401 if (this._listeners.length === 0) {
402 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
403 }
404 this._listeners.push(callback);
405 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
406 },
Blink Reformat4c46d092018-04-07 15:32:37407
Jan Schefflerd76b4162021-03-29 07:52:16408
Philip Pfaffe7523faf2021-06-28 14:23:14409 removeListener: function<ListenerT extends APIImpl.Callable>(
410 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37411 const listeners = this._listeners;
412
413 for (let i = 0; i < listeners.length; ++i) {
414 if (listeners[i] === callback) {
415 listeners.splice(i, 1);
416 break;
417 }
418 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34419 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04420 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34421 }
Blink Reformat4c46d092018-04-07 15:32:37422 },
423
Jan Schefflerd76b4162021-03-29 07:52:16424
Philip Pfaffe7523faf2021-06-28 14:23:14425 _fire: function<ListenerT extends APIImpl.Callable>(
426 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37427 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34428 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14429 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34430 }
Blink Reformat4c46d092018-04-07 15:32:37431 },
432
Jan Schefflerd76b4162021-03-29 07:52:16433
Philip Pfaffe7523faf2021-06-28 14:23:14434 _dispatch: function<ListenerT extends APIImpl.Callable>(
435 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34436 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37437 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34438 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14439 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34440 }
Jan Schefflerd76b4162021-03-29 07:52:16441 },
Blink Reformat4c46d092018-04-07 15:32:37442 };
443
Philip Pfaffe7523faf2021-06-28 14:23:14444 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
445 ThisParameterType<NewT> {
446 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
447 }
448
Blink Reformat4c46d092018-04-07 15:32:37449 /**
450 * @constructor
451 */
Jan Schefflerd76b4162021-03-29 07:52:16452
Philip Pfaffe7523faf2021-06-28 14:23:14453 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffe939605d2021-06-25 12:20:04454 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37455 this.inspectedWindow = new InspectedWindow();
Philip Pfaffe6fd04c42021-06-25 12:31:48456 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47457 this.network = new (Constructor(Network))();
Philip Pfaffe939605d2021-06-25 12:20:04458 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37459 this.timeline = new Timeline();
Philip Pfaffec5d160e2021-07-20 10:53:32460 this.languageServices = new (Constructor(LanguageServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37461 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
462 }
463
464 /**
465 * @constructor
466 */
Jan Schefflerd76b4162021-03-29 07:52:16467
Philip Pfaffe4b88c662021-06-25 12:30:47468 function Network(this: APIImpl.Network): void {
469 function dispatchRequestEvent(
470 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
471 message: {arguments: unknown[]}): void {
472 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
473
474 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37475 this._fire(request);
476 }
Philip Pfaffe4b88c662021-06-25 12:30:47477
478 this.onRequestFinished =
479 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37480 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47481
482 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37483 }
484
Philip Pfaffe4b88c662021-06-25 12:30:47485 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
486 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
487 function callbackWrapper(response: unknown): void {
488 const result =
489 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37490 const entries = (result && result.entries) || [];
491 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47492 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37493 delete entries[i]._requestId;
494 }
Philip Pfaffe4b88c662021-06-25 12:30:47495 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37496 }
Philip Pfaffe939605d2021-06-25 12:20:04497 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37498 },
499
Philip Pfaffe4b88c662021-06-25 12:30:47500 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37501 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04502 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16503 },
Blink Reformat4c46d092018-04-07 15:32:37504 };
505
Philip Pfaffe4b88c662021-06-25 12:30:47506 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37507 this._id = id;
508 }
509
Philip Pfaffe4b88c662021-06-25 12:30:47510 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
511 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
512 function callbackWrapper(response: unknown): void {
513 const {content, encoding} = response as {content: string, encoding: string};
514 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37515 }
Philip Pfaffe939605d2021-06-25 12:20:04516 extensionServer.sendRequest(
517 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16518 },
Blink Reformat4c46d092018-04-07 15:32:37519 };
520
521 /**
522 * @constructor
523 */
Philip Pfaffe6fd04c42021-06-25 12:31:48524 function Panels(this: APIImpl.Panels): void {
525 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37526 elements: new ElementsPanel(),
527 sources: new SourcesPanel(),
528 };
529
Philip Pfaffe6fd04c42021-06-25 12:31:48530 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37531 return panels[name];
532 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34533 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12534 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34535 }
Philip Pfaffe6fd04c42021-06-25 12:31:48536 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04537 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37538 };
539 }
540
Philip Pfaffe6fd04c42021-06-25 12:31:48541 (Panels.prototype as Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'>) = {
542 create: function(
543 title: string, icon: string, page: string,
544 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37545 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48546 extensionServer.sendRequest(
547 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
548 callback && callback.bind(this, new (Constructor(ExtensionPanel))(id)));
Blink Reformat4c46d092018-04-07 15:32:37549 },
550
Philip Pfaffe6fd04c42021-06-25 12:31:48551 setOpenResourceHandler: function(
552 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04553 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37554
Philip Pfaffe6fd04c42021-06-25 12:31:48555 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37556 // Allow the panel to show itself when handling the event.
557 userAction = true;
558 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48559 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
560 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
Blink Reformat4c46d092018-04-07 15:32:37561 } finally {
562 userAction = false;
563 }
564 }
565
Tim van der Lippe1d6e57a2019-09-30 11:55:34566 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04567 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34568 } else {
Philip Pfaffe939605d2021-06-25 12:20:04569 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34570 }
Blink Reformat4c46d092018-04-07 15:32:37571
572 // 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:34573 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04574 extensionServer.sendRequest(
575 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34576 }
Blink Reformat4c46d092018-04-07 15:32:37577 },
578
Philip Pfaffe6fd04c42021-06-25 12:31:48579 openResource: function(url: string, lineNumber: number, callback?: (response: unknown) => unknown): void {
580 extensionServer.sendRequest({command: PrivateAPI.Commands.OpenResource, url, lineNumber}, callback);
Blink Reformat4c46d092018-04-07 15:32:37581 },
582
Philip Pfaffe6fd04c42021-06-25 12:31:48583 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04584 return {
585 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
586 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
587 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
588 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
589 };
Jan Schefflerd76b4162021-03-29 07:52:16590 },
Blink Reformat4c46d092018-04-07 15:32:37591 };
592
593 /**
594 * @constructor
595 */
Philip Pfaffe6fd04c42021-06-25 12:31:48596 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37597 this._id = id;
598
Philip Pfaffe6fd04c42021-06-25 12:31:48599 function dispatchShowEvent(
600 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37601 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34602 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37603 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34604 } else {
Blink Reformat4c46d092018-04-07 15:32:37605 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34606 }
Blink Reformat4c46d092018-04-07 15:32:37607 }
608
609 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48610 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
611
612 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37613 }
614 }
615
616 /**
617 * @constructor
618 * @extends {ExtensionViewImpl}
Blink Reformat4c46d092018-04-07 15:32:37619 */
Philip Pfaffe6fd04c42021-06-25 12:31:48620 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37621 ExtensionViewImpl.call(this, null);
622 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48623
624 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37625 }
626
Philip Pfaffe6fd04c42021-06-25 12:31:48627 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
628 {__proto__: APIImpl.ExtensionView}) = {
629 createSidebarPane: function(
630 this: APIImpl.PanelWithSidebar, title: string,
631 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37632 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16633 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48634 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37635 }
Philip Pfaffe7523faf2021-06-28 14:23:14636 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48637 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14638 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37639 },
640
Jan Schefflerd76b4162021-03-29 07:52:16641 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37642 };
643
Philip Pfaffeedad8322020-07-20 10:24:25644 /**
645 * @constructor
646 */
Philip Pfaffec5d160e2021-07-20 10:53:32647 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Benedikt Meurer929fc7c2020-11-20 14:21:06648 /** @type {!Map<*, !MessagePort>} */
Philip Pfaffeedad8322020-07-20 10:24:25649 this._plugins = new Map();
650 }
651
Philip Pfaffec5d160e2021-07-20 10:53:32652 (LanguageServicesAPIImpl.prototype as
653 Pick<APIImpl.LanguageExtensions, 'registerLanguageExtensionPlugin'|'unregisterLanguageExtensionPlugin'>) = {
Philip Pfaffed662bdf2021-06-25 13:30:32654 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32655 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
656 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
657 if (this._plugins.has(plugin)) {
658 throw new Error(`Tried to register plugin '${pluginName}' twice`);
659 }
660 const channel = new MessageChannel();
661 const port = channel.port1;
662 this._plugins.set(plugin, port);
663 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
664 const {requestId} = data;
665 console.time(`${requestId}: ${data.method}`);
666 dispatchMethodCall(data)
667 .then(result => port.postMessage({requestId, result}))
668 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
669 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
670 };
Philip Pfaffeedad8322020-07-20 10:24:25671
Philip Pfaffec5d160e2021-07-20 10:53:32672 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
673 switch (request.method) {
674 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
675 return plugin.addRawModule(
676 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
677 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
678 return plugin.removeRawModule(request.parameters.rawModuleId);
679 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
680 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
681 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
682 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
683 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
684 return plugin.getScopeInfo(request.parameters.type);
685 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
686 return plugin.listVariablesInScope(request.parameters.rawLocation);
687 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
688 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
689 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
690 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
691 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
692 if ('getInspectableAddress' in plugin) {
693 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02694 }
Philip Pfaffec5d160e2021-07-20 10:53:32695 return Promise.resolve({js: ''});
696 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
697 return plugin.getFunctionInfo(request.parameters.rawLocation);
698 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
699 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
700 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
701 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
702 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
703 if ('getMappedLines' in plugin) {
704 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
705 }
706 return Promise.resolve(undefined);
707 }
708 // @ts-expect-error
709 throw new Error(`Unknown language plugin method ${request.method}`);
710 }
Philip Pfaffeedad8322020-07-20 10:24:25711
Philip Pfaffec5d160e2021-07-20 10:53:32712 await new Promise<void>(resolve => {
713 extensionServer.sendRequest(
714 {
715 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
716 pluginName,
717 port: channel.port2,
718 supportedScriptTypes,
719 },
720 () => resolve(), [channel.port2]);
721 });
722 },
Benedikt Meurer929fc7c2020-11-20 14:21:06723
Philip Pfaffec5d160e2021-07-20 10:53:32724 unregisterLanguageExtensionPlugin: async function(
725 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06726 const port = this._plugins.get(plugin);
727 if (!port) {
728 throw new Error('Tried to unregister a plugin that was not previously registered');
729 }
730 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04731 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06732 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16733 },
Philip Pfaffeedad8322020-07-20 10:24:25734 };
735
Philip Pfaffe7523faf2021-06-28 14:23:14736 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
737 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
738 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37739 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14740 implConstructor.apply(impl, args);
741 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37742 };
743 }
744
Philip Pfaffe7523faf2021-06-28 14:23:14745 // eslint-disable-next-line @typescript-eslint/no-explicit-any
746 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37747 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14748 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37749 if (!warningGiven) {
750 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
751 warningGiven = true;
752 }
753 return object[newName];
754 }
755 object.__defineGetter__(oldName, getter);
756 }
757
Philip Pfaffe7523faf2021-06-28 14:23:14758 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37759 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14760 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37761 }
762
Philip Pfaffeedad8322020-07-20 10:24:25763 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37764 const Button = declareInterfaceClass(ButtonImpl);
765 const EventSink = declareInterfaceClass(EventSinkImpl);
766 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
767 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12768 /**
769 * @constructor
770 * @param {string} hostPanelName
771 */
772 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37773 const Request = declareInterfaceClass(RequestImpl);
774 const Resource = declareInterfaceClass(ResourceImpl);
775 const TraceSession = declareInterfaceClass(TraceSessionImpl);
776
Philip Pfaffe6fd04c42021-06-25 12:31:48777
778 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12779 constructor() {
780 super('elements');
781 }
Blink Reformat4c46d092018-04-07 15:32:37782 }
783
Philip Pfaffe6fd04c42021-06-25 12:31:48784
785 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12786 constructor() {
787 super('sources');
788 }
Blink Reformat4c46d092018-04-07 15:32:37789 }
790
Blink Reformat4c46d092018-04-07 15:32:37791 /**
792 * @constructor
793 * @extends {ExtensionViewImpl}
794 */
Philip Pfaffe6fd04c42021-06-25 12:31:48795 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37796 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48797
798 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37799 }
800
Philip Pfaffe6fd04c42021-06-25 12:31:48801 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
802 {__proto__: APIImpl.ExtensionView}) = {
803 createStatusBarButton: function(
804 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
805 PublicAPI.Chrome.DevTools.Button {
806 const id = 'button-' + extensionServer.nextObjectId();
807 extensionServer.sendRequest({
808 command: PrivateAPI.Commands.CreateToolbarButton,
809 panel: this._id as string,
810 id: id,
811 icon: iconPath,
812 tooltip: tooltipText,
813 disabled: Boolean(disabled),
814 });
Blink Reformat4c46d092018-04-07 15:32:37815
Philip Pfaffe6fd04c42021-06-25 12:31:48816 return new (Constructor(Button))(id);
817 },
818
819 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34820 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:37821 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34822 }
Blink Reformat4c46d092018-04-07 15:32:37823
Philip Pfaffe6fd04c42021-06-25 12:31:48824 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:37825 },
826
Jan Schefflerd76b4162021-03-29 07:52:16827 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37828 };
829
830 /**
831 * @constructor
832 * @extends {ExtensionViewImpl}
833 */
Philip Pfaffe6fd04c42021-06-25 12:31:48834 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37835 ExtensionViewImpl.call(this, id);
836 }
837
Philip Pfaffe6fd04c42021-06-25 12:31:48838 (ExtensionSidebarPaneImpl.prototype as
839 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
840 {__proto__: APIImpl.ExtensionView}) = {
841 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
842 extensionServer.sendRequest(
843 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:37844 },
845
Philip Pfaffe6fd04c42021-06-25 12:31:48846 setExpression: function(
847 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
848 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:14849 extensionServer.sendRequest(
850 {
851 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:48852 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:14853 expression: expression,
854 rootTitle: rootTitle,
855 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:48856 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:14857 },
858 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:37859 },
860
Philip Pfaffe6fd04c42021-06-25 12:31:48861 setObject: function(
862 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37863 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48864 {
865 command: PrivateAPI.Commands.SetSidebarContent,
866 id: this._id as string,
867 expression: jsonObject,
868 rootTitle: rootTitle,
869 },
Philip Pfaffe939605d2021-06-25 12:20:04870 callback);
Blink Reformat4c46d092018-04-07 15:32:37871 },
872
Philip Pfaffe6fd04c42021-06-25 12:31:48873 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
874 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:37875 },
876
Jan Schefflerd76b4162021-03-29 07:52:16877 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37878 };
879
880 /**
881 * @constructor
882 */
Philip Pfaffe6fd04c42021-06-25 12:31:48883 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37884 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:48885
886 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:37887 }
888
Philip Pfaffe6fd04c42021-06-25 12:31:48889 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
890 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:14891 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04892 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:24893 id: this._id,
894 icon: iconPath,
895 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16896 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:14897 });
Jan Schefflerd76b4162021-03-29 07:52:16898 },
Blink Reformat4c46d092018-04-07 15:32:37899 };
900
901 /**
902 * @constructor
903 */
Jan Schefflerd76b4162021-03-29 07:52:16904 function Timeline(): void {
Blink Reformat4c46d092018-04-07 15:32:37905 }
906
907 Timeline.prototype = {
Philip Pfaffe939605d2021-06-25 12:20:04908 // @ts-ignore
Jan Schefflerd76b4162021-03-29 07:52:16909 addTraceProvider: function(categoryName: string, categoryTooltip: string): TraceProvider {
Blink Reformat4c46d092018-04-07 15:32:37910 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
Philip Pfaffe939605d2021-06-25 12:20:04911 extensionServer.sendRequest({
912 command: PrivateAPI.Commands.AddTraceProvider,
913 id: id,
914 categoryName: categoryName,
915 categoryTooltip: categoryTooltip,
916 });
917 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37918 return new TraceProvider(id);
Jan Schefflerd76b4162021-03-29 07:52:16919 },
Blink Reformat4c46d092018-04-07 15:32:37920 };
921
922 /**
923 * @constructor
Blink Reformat4c46d092018-04-07 15:32:37924 */
Philip Pfaffe939605d2021-06-25 12:20:04925 function TraceSessionImpl(this: any, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37926 this._id = id;
927 }
928
929 TraceSessionImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16930 complete: function(url?: string, timeOffset?: number): void {
Philip Pfaffe7523faf2021-06-28 14:23:14931 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04932 command: PrivateAPI.Commands.CompleteTraceSession,
933 id: this._id,
934 url: url || '',
935 timeOffset: timeOffset || 0,
Philip Pfaffe7523faf2021-06-28 14:23:14936 });
Jan Schefflerd76b4162021-03-29 07:52:16937 },
Blink Reformat4c46d092018-04-07 15:32:37938 };
939
940 /**
941 * @constructor
Blink Reformat4c46d092018-04-07 15:32:37942 */
Jan Schefflerd76b4162021-03-29 07:52:16943 function TraceProvider(id: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04944 function dispatchRecordingStarted(this: any, message: any): void {
Blink Reformat4c46d092018-04-07 15:32:37945 const sessionId = message.arguments[0];
Philip Pfaffe939605d2021-06-25 12:20:04946 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37947 this._fire(new TraceSession(sessionId));
948 }
949
Philip Pfaffe939605d2021-06-25 12:20:04950 // @ts-ignore
951 this.onRecordingStarted = new EventSink(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
952 // @ts-ignore
953 this.onRecordingStopped = new EventSink(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:37954 }
955
956 /**
957 * @constructor
958 */
Philip Pfaffe939605d2021-06-25 12:20:04959 function InspectedWindow(this: any): void {
960 function dispatchResourceEvent(this: any, message: any): void {
961 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37962 this._fire(new Resource(message.arguments[0]));
963 }
964
Philip Pfaffe939605d2021-06-25 12:20:04965 function dispatchResourceContentEvent(this: any, message: any): void {
966 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37967 this._fire(new Resource(message.arguments[0]), message.arguments[1]);
968 }
969
Philip Pfaffe939605d2021-06-25 12:20:04970 // @ts-ignore
971 this.onResourceAdded = new EventSink(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
972 this.onResourceContentCommitted =
973 // @ts-ignore
974 new EventSink(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:37975 }
976
977 InspectedWindow.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16978 reload: function(optionsOrUserAgent: any): void {
979 let options: {
980 userAgent: string,
981 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:37982 if (typeof optionsOrUserAgent === 'object') {
983 options = optionsOrUserAgent;
984 } else if (typeof optionsOrUserAgent === 'string') {
985 options = {userAgent: optionsOrUserAgent};
986 console.warn(
987 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
988 'Use inspectedWindow.reload({ userAgent: value}) instead.');
989 }
Philip Pfaffe939605d2021-06-25 12:20:04990 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:37991 },
992
Jan Schefflerd76b4162021-03-29 07:52:16993 eval: function(expression: any, evaluateOptions: any): Object |
994 null {
995 const callback = extractCallbackArgument(arguments);
996 function callbackWrapper(result: any): void {
997 if (result.isError || result.isException) {
Philip Pfaffe7523faf2021-06-28 14:23:14998 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:16999 } else {
Philip Pfaffe7523faf2021-06-28 14:23:141000 callback && callback(result.value);
Jan Schefflerd76b4162021-03-29 07:52:161001 }
1002 }
Philip Pfaffe7523faf2021-06-28 14:23:141003 extensionServer.sendRequest(
1004 {
1005 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1006 expression: expression,
1007 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1008 },
1009 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161010 return null;
1011 },
Blink Reformat4c46d092018-04-07 15:32:371012
Jan Schefflerd76b4162021-03-29 07:52:161013 getResources: function(callback: any): void {
1014 function wrapResource(resourceData: any): any {
Philip Pfaffe939605d2021-06-25 12:20:041015 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:371016 return new Resource(resourceData);
1017 }
Jan Schefflerd76b4162021-03-29 07:52:161018 function callbackWrapper(resources: any): void {
Blink Reformat4c46d092018-04-07 15:32:371019 callback(resources.map(wrapResource));
1020 }
Philip Pfaffe939605d2021-06-25 12:20:041021 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161022 },
Blink Reformat4c46d092018-04-07 15:32:371023 };
1024
1025 /**
1026 * @constructor
1027 */
Philip Pfaffe6fd04c42021-06-25 12:31:481028 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Blink Reformat4c46d092018-04-07 15:32:371029 this._url = resourceData.url;
1030 this._type = resourceData.type;
1031 }
1032
Philip Pfaffe6fd04c42021-06-25 12:31:481033 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161034 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481035 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371036 },
1037
Jan Schefflerd76b4162021-03-29 07:52:161038 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481039 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371040 },
1041
Philip Pfaffe6fd04c42021-06-25 12:31:481042 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1043 function callbackWrapper(response: unknown): void {
1044 const {content, encoding} = response as {content: string, encoding: string};
1045 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371046 }
1047
Philip Pfaffe939605d2021-06-25 12:20:041048 extensionServer.sendRequest(
1049 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371050 },
1051
Philip Pfaffe6fd04c42021-06-25 12:31:481052 setContent: function(
1053 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371054 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041055 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481056 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161057 },
Blink Reformat4c46d092018-04-07 15:32:371058 };
1059
Jan Schefflerd76b4162021-03-29 07:52:161060 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371061 return inspectedTabId;
1062 }
1063
Philip Pfaffe7523faf2021-06-28 14:23:141064 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161065 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141066 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521067 // Check if the event should be forwarded.
1068 // This is a workaround for crbug.com/923338.
1069 const focused = document.activeElement;
1070 if (focused) {
1071 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
1072 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1073 return;
1074 }
1075 }
1076
Joel Einbinder67f28fb2018-08-02 00:33:471077 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341078 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471079 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341080 }
1081 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471082 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341083 }
1084 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471085 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341086 }
1087 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471088 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341089 }
Joel Einbinder67f28fb2018-08-02 00:33:471090 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371091 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341092 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371093 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341094 }
Joel Einbinder67f28fb2018-08-02 00:33:471095 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371096 const requestPayload = {
1097 eventType: event.type,
1098 ctrlKey: event.ctrlKey,
1099 altKey: event.altKey,
1100 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471101 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141102 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371103 keyIdentifier: event.keyIdentifier,
1104 key: event.key,
1105 code: event.code,
1106 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161107 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371108 };
1109 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341110 if (!forwardTimer) {
Blink Reformat4c46d092018-04-07 15:32:371111 forwardTimer = setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341112 }
Blink Reformat4c46d092018-04-07 15:32:371113 }
1114
Jan Schefflerd76b4162021-03-29 07:52:161115 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371116 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141117 extensionServer.sendRequest(
1118 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371119 keyboardEventRequestQueue = [];
1120 }
1121
1122 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371123
1124 /**
1125 * @constructor
1126 */
Philip Pfaffe7523faf2021-06-28 14:23:141127 function ExtensionServerClient(this: APIImpl.ExtensionServerClient): void {
Blink Reformat4c46d092018-04-07 15:32:371128 this._callbacks = {};
1129 this._handlers = {};
1130 this._lastRequestId = 0;
1131 this._lastObjectId = 0;
1132
1133 this.registerHandler('callback', this._onCallback.bind(this));
1134
1135 const channel = new MessageChannel();
1136 this._port = channel.port1;
1137 this._port.addEventListener('message', this._onMessage.bind(this), false);
1138 this._port.start();
1139
1140 window.parent.postMessage('registerExtension', '*', [channel.port2]);
1141 }
1142
Philip Pfaffe7523faf2021-06-28 14:23:141143 (ExtensionServerClient.prototype as Pick<
1144 APIImpl.ExtensionServerClient,
1145 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1146 '_onCallback'|'_onMessage'>) = {
1147 sendRequest: function(
1148 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
1149 callback?: (response: unknown) => unknown, transfers?: Transferable[]): void {
1150 if (typeof callback === 'function') {
1151 (message as PrivateAPI.ExtensionServerRequestMessage).requestId = this._registerCallback(callback);
1152 }
1153 // @ts-expect-error
1154 this._port.postMessage(message, transfers);
1155 },
Blink Reformat4c46d092018-04-07 15:32:371156
Philip Pfaffe7523faf2021-06-28 14:23:141157 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241158 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371159 },
1160
Philip Pfaffe7523faf2021-06-28 14:23:141161 registerHandler: function(
1162 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1163 void {
1164 this._handlers[command] = handler;
1165 },
Blink Reformat4c46d092018-04-07 15:32:371166
Philip Pfaffe7523faf2021-06-28 14:23:141167 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371168 delete this._handlers[command];
1169 },
1170
Philip Pfaffe7523faf2021-06-28 14:23:141171 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371172 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1173 },
1174
Philip Pfaffe7523faf2021-06-28 14:23:141175 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371176 const id = ++this._lastRequestId;
1177 this._callbacks[id] = callback;
1178 return id;
1179 },
1180
Philip Pfaffe7523faf2021-06-28 14:23:141181 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371182 if (request.requestId in this._callbacks) {
1183 const callback = this._callbacks[request.requestId];
1184 delete this._callbacks[request.requestId];
1185 callback(request.result);
1186 }
1187 },
1188
Philip Pfaffe7523faf2021-06-28 14:23:141189 _onMessage: function(
1190 this: APIImpl.ExtensionServerClient,
1191 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371192 const request = event.data;
1193 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341194 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371195 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341196 }
Jan Schefflerd76b4162021-03-29 07:52:161197 },
Blink Reformat4c46d092018-04-07 15:32:371198 };
1199
Philip Pfaffe7523faf2021-06-28 14:23:141200 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371201 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341202 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371203 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341204 }
Jan Schefflerd76b4162021-03-29 07:52:161205 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371206 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141207 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371208 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341209 }
1210 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371211 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341212 }
1213 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371214 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341215 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141216 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371217 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341218 } else {
Blink Reformat4c46d092018-04-07 15:32:371219 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341220 }
Blink Reformat4c46d092018-04-07 15:32:371221 }
1222 }
1223
Philip Pfaffe7523faf2021-06-28 14:23:141224
1225 const extensionServer = new (Constructor(ExtensionServerClient))();
1226
1227 const coreAPI = new (Constructor(InspectorExtensionAPI))();
Blink Reformat4c46d092018-04-07 15:32:371228
1229 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
1230
1231 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
Philip Pfaffe7523faf2021-06-28 14:23:141232 // @ts-expect-error
1233 chrome.devtools!.inspectedWindow = {};
1234 Object.defineProperty(chrome.devtools!.inspectedWindow, 'tabId', {get: getTabId});
1235 // @ts-expect-error
1236 chrome.devtools!.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
1237 chrome.devtools!.network = coreAPI.network;
1238 chrome.devtools!.panels = coreAPI.panels;
1239 chrome.devtools!.panels.themeName = themeName;
1240 chrome.devtools!.languageServices = coreAPI.languageServices;
Blink Reformat4c46d092018-04-07 15:32:371241
1242 // default to expose experimental APIs for now.
1243 if (extensionInfo.exposeExperimentalAPIs !== false) {
1244 chrome.experimental = chrome.experimental || {};
1245 chrome.experimental.devtools = chrome.experimental.devtools || {};
1246
1247 const properties = Object.getOwnPropertyNames(coreAPI);
1248 for (let i = 0; i < properties.length; ++i) {
1249 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341250 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371251 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341252 }
Blink Reformat4c46d092018-04-07 15:32:371253 }
1254 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
1255 }
1256
Tim van der Lippe1d6e57a2019-09-30 11:55:341257 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:371258 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:341259 }
Blink Reformat4c46d092018-04-07 15:32:371260 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:121261};
Blink Reformat4c46d092018-04-07 15:32:371262
Jan Schefflerd76b4162021-03-29 07:52:161263self.buildExtensionAPIInjectedScript = function(
1264 extensionInfo: {
1265 startPage: string,
1266 name: string,
1267 exposeExperimentalAPIs: boolean,
1268 },
1269 inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:141270 testHook:
1271 ((extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown)|
1272 undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:251273 const argumentsJSON =
1274 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:341275 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:161276 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:341277 }
Philip Pfaffe939605d2021-06-25 12:20:041278 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:121279 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:371280 '})';
Tim van der Lippe29fab472019-08-15 14:46:481281};