blob: 2ae423964b95562d07a4c3723c7af33c9d522008 [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,',
Paul Lewisada689f2022-01-11 12:03:4058 ThemeChange = 'host-theme-change',
Philip Pfaffe939605d2021-06-25 12:20:0459 }
Blink Reformat4c46d092018-04-07 15:32:3760
Philip Pfaffe939605d2021-06-25 12:20:0461 export const enum Commands {
62 AddRequestHeaders = 'addRequestHeaders',
63 AddTraceProvider = 'addTraceProvider',
64 ApplyStyleSheet = 'applyStyleSheet',
65 CompleteTraceSession = 'completeTra.eSession',
66 CreatePanel = 'createPanel',
67 CreateSidebarPane = 'createSidebarPane',
68 CreateToolbarButton = 'createToolbarButton',
69 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
70 ForwardKeyboardEvent = '_forwardKeyboardEvent',
71 GetHAR = 'getHAR',
72 GetPageResources = 'getPageResources',
73 GetRequestContent = 'getRequestContent',
74 GetResourceContent = 'getResourceContent',
75 OpenResource = 'openResource',
76 Reload = 'Reload',
77 Subscribe = 'subscribe',
78 SetOpenResourceHandler = 'setOpenResourceHandler',
Paul Lewisada689f2022-01-11 12:03:4079 SetThemeChangeHandler = 'setThemeChangeHandler',
Philip Pfaffe939605d2021-06-25 12:20:0480 SetResourceContent = 'setResourceContent',
81 SetSidebarContent = 'setSidebarContent',
82 SetSidebarHeight = 'setSidebarHeight',
83 SetSidebarPage = 'setSidebarPage',
84 ShowPanel = 'showPanel',
85 Unsubscribe = 'unsubscribe',
86 UpdateButton = 'updateButton',
87 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
88 }
Philip Pfaffeedad8322020-07-20 10:24:2589
Philip Pfaffe939605d2021-06-25 12:20:0490 export const enum LanguageExtensionPluginCommands {
91 AddRawModule = 'addRawModule',
92 RemoveRawModule = 'removeRawModule',
93 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
94 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
95 GetScopeInfo = 'getScopeInfo',
96 ListVariablesInScope = 'listVariablesInScope',
97 GetTypeInfo = 'getTypeInfo',
98 GetFormatter = 'getFormatter',
99 GetInspectableAddress = 'getInspectableAddress',
100 GetFunctionInfo = 'getFunctionInfo',
101 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
102 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
103 GetMappedLines = 'getMappedLines',
104 }
Benedikt Meurer929fc7c2020-11-20 14:21:06105
Philip Pfaffe939605d2021-06-25 12:20:04106 export const enum LanguageExtensionPluginEvents {
107 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
108 }
Philip Pfaffed662bdf2021-06-25 13:30:32109
110 export interface EvaluateOptions {
111 frameURL?: string;
112 useContentScriptContext?: boolean;
113 scriptExecutionContext?: string;
114 }
115
Philip Pfaffed662bdf2021-06-25 13:30:32116 type RegisterLanguageExtensionPluginRequest = {
117 command: Commands.RegisterLanguageExtensionPlugin,
118 pluginName: string,
119 port: MessagePort,
Philip Pfaffe7523faf2021-06-28 14:23:14120 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
Philip Pfaffed662bdf2021-06-25 13:30:32121 };
122 type SubscribeRequest = {command: Commands.Subscribe, type: string};
123 type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
124 type AddRequestHeadersRequest = {
125 command: Commands.AddRequestHeaders,
126 extensionId: string,
127 headers: {[key: string]: string},
128 };
129 type ApplyStyleSheetRequest = {command: Commands.ApplyStyleSheet, styleSheet: string};
130 type CreatePanelRequest = {command: Commands.CreatePanel, id: string, title: string, page: string};
131 type ShowPanelRequest = {command: Commands.ShowPanel, id: string};
132 type CreateToolbarButtonRequest = {
133 command: Commands.CreateToolbarButton,
134 id: string,
135 icon: string,
136 panel: string,
137 tooltip?: string,
138 disabled?: boolean,
139 };
140 type UpdateButtonRequest =
141 {command: Commands.UpdateButton, id: string, icon?: string, tooltip?: string, disabled?: boolean};
142 type CompleteTraceSessionRequest =
143 {command: Commands.CompleteTraceSession, id: string, url: string, timeOffset: number};
144 type CreateSidebarPaneRequest = {command: Commands.CreateSidebarPane, id: string, panel: string, title: string};
145 type SetSidebarHeightRequest = {command: Commands.SetSidebarHeight, id: string, height: string};
146 type SetSidebarContentRequest = {
147 command: Commands.SetSidebarContent,
148 id: string,
149 evaluateOnPage?: boolean, expression: string,
150 rootTitle?: string,
151 evaluateOptions?: EvaluateOptions,
152 };
153 type SetSidebarPageRequest = {command: Commands.SetSidebarPage, id: string, page: string};
Philip Pfaffe140e5432021-09-13 16:34:23154 type OpenResourceRequest = {command: Commands.OpenResource, url: string, lineNumber: number, columnNumber: number};
Philip Pfaffed662bdf2021-06-25 13:30:32155 type SetOpenResourceHandlerRequest = {command: Commands.SetOpenResourceHandler, handlerPresent: boolean};
Paul Lewisada689f2022-01-11 12:03:40156 type SetThemeChangeHandlerRequest = {command: Commands.SetThemeChangeHandler, handlerPresent: boolean};
Philip Pfaffed662bdf2021-06-25 13:30:32157 type ReloadRequest = {
158 command: Commands.Reload,
159 options: null|{
160 userAgent?: string,
161 injectedScript?: string,
162 ignoreCache?: boolean,
163 },
164 };
165 type EvaluateOnInspectedPageRequest = {
166 command: Commands.EvaluateOnInspectedPage,
167 expression: string,
168 evaluateOptions?: EvaluateOptions,
169 };
170 type GetRequestContentRequest = {command: Commands.GetRequestContent, id: number};
171 type GetResourceContentRequest = {command: Commands.GetResourceContent, url: string};
172 type SetResourceContentRequest =
173 {command: Commands.SetResourceContent, url: string, content: string, commit: boolean};
174 type AddTraceProviderRequest =
175 {command: Commands.AddTraceProvider, id: string, categoryName: string, categoryTooltip: string};
176 type ForwardKeyboardEventRequest = {
177 command: Commands.ForwardKeyboardEvent,
178 entries: Array<KeyboardEventInit&{eventType: string}>,
179 };
180 type GetHARRequest = {command: Commands.GetHAR};
181 type GetPageResourcesRequest = {command: Commands.GetPageResources};
182
183 export type ServerRequests = RegisterLanguageExtensionPluginRequest|SubscribeRequest|UnsubscribeRequest|
184 AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|ShowPanelRequest|CreateToolbarButtonRequest|
185 UpdateButtonRequest|CompleteTraceSessionRequest|CreateSidebarPaneRequest|SetSidebarHeightRequest|
Paul Lewisada689f2022-01-11 12:03:40186 SetSidebarContentRequest|SetSidebarPageRequest|OpenResourceRequest|SetOpenResourceHandlerRequest|
187 SetThemeChangeHandlerRequest|ReloadRequest|EvaluateOnInspectedPageRequest|GetRequestContentRequest|
188 GetResourceContentRequest|SetResourceContentRequest|AddTraceProviderRequest|ForwardKeyboardEventRequest|
189 GetHARRequest|GetPageResourcesRequest;
Philip Pfaffed662bdf2021-06-25 13:30:32190 export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
Philip Pfaffec5d160e2021-07-20 10:53:32191
192 type AddRawModuleRequest = {
193 method: LanguageExtensionPluginCommands.AddRawModule,
194 parameters: {rawModuleId: string, symbolsURL: string|undefined, rawModule: PublicAPI.Chrome.DevTools.RawModule},
195 };
196 type SourceLocationToRawLocationRequest = {
197 method: LanguageExtensionPluginCommands.SourceLocationToRawLocation,
198 parameters: {sourceLocation: PublicAPI.Chrome.DevTools.SourceLocation},
199 };
200 type RawLocationToSourceLocationRequest = {
201 method: LanguageExtensionPluginCommands.RawLocationToSourceLocation,
202 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
203 };
204 type GetScopeInfoRequest = {method: LanguageExtensionPluginCommands.GetScopeInfo, parameters: {type: string}};
205 type ListVariablesInScopeRequest = {
206 method: LanguageExtensionPluginCommands.ListVariablesInScope,
207 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
208 };
209 type RemoveRawModuleRequest = {
210 method: LanguageExtensionPluginCommands.RemoveRawModule,
211 parameters: {rawModuleId: string},
212 };
213 type GetTypeInfoRequest = {
214 method: LanguageExtensionPluginCommands.GetTypeInfo,
215 parameters: {expression: string, context: PublicAPI.Chrome.DevTools.RawLocation},
216 };
217 type GetFormatterRequest = {
218 method: LanguageExtensionPluginCommands.GetFormatter,
219 parameters: {
220 expressionOrField: string|{
221 base: PublicAPI.Chrome.DevTools.EvalBase,
222 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
223 },
224 context: PublicAPI.Chrome.DevTools.RawLocation,
225 },
226 };
227 type GetInspectableAddressRequest = {
228 method: LanguageExtensionPluginCommands.GetInspectableAddress,
229 parameters: {
230 field: {
231 base: PublicAPI.Chrome.DevTools.EvalBase,
232 field: Array<PublicAPI.Chrome.DevTools.FieldInfo>,
233 },
234 },
235 };
236 type GetFunctionInfoRequest = {
237 method: LanguageExtensionPluginCommands.GetFunctionInfo,
238 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
239 };
240 type GetInlinedFunctionRangesRequest = {
241 method: LanguageExtensionPluginCommands.GetInlinedFunctionRanges,
242 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
243 };
244 type GetInlinedCalleesRangesRequest = {
245 method: LanguageExtensionPluginCommands.GetInlinedCalleesRanges,
246 parameters: {rawLocation: PublicAPI.Chrome.DevTools.RawLocation},
247 };
248 type GetMappedLinesRequest = {
249 method: LanguageExtensionPluginCommands.GetMappedLines,
250 parameters: {rawModuleId: string, sourceFileURL: string},
251 };
252
253 export type LanguageExtensionRequests = AddRawModuleRequest|SourceLocationToRawLocationRequest|
254 RawLocationToSourceLocationRequest|GetScopeInfoRequest|ListVariablesInScopeRequest|RemoveRawModuleRequest|
255 GetTypeInfoRequest|GetFormatterRequest|GetInspectableAddressRequest|GetFunctionInfoRequest|
256 GetInlinedFunctionRangesRequest|GetInlinedCalleesRangesRequest|GetMappedLinesRequest;
Blink Reformat4c46d092018-04-07 15:32:37257}
258
Philip Pfaffe939605d2021-06-25 12:20:04259declare global {
260 interface Window {
261 injectedExtensionAPI:
262 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffe7523faf2021-06-28 14:23:14263 testHook:
264 (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23265 injectedScriptId: number) => void;
Philip Pfaffe939605d2021-06-25 12:20:04266 buildExtensionAPIInjectedScript(
267 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
Philip Pfaffed662bdf2021-06-25 13:30:32268 testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
Philip Pfaffe7523faf2021-06-28 14:23:14269 chrome: PublicAPI.Chrome.DevTools.Chrome;
270 webInspector?: APIImpl.InspectorExtensionAPI;
Philip Pfaffe939605d2021-06-25 12:20:04271 }
272}
273
274export type ExtensionDescriptor = {
275 startPage: string,
276 name: string,
277 exposeExperimentalAPIs: boolean,
278 exposeWebInspectorNamespace?: boolean,
279};
280
Philip Pfaffe7523faf2021-06-28 14:23:14281namespace APIImpl {
282 export interface InspectorExtensionAPI {
283 languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
Philip Pfaffe1c827212021-06-25 12:33:20284 timeline: Timeline;
Philip Pfaffe7523faf2021-06-28 14:23:14285 network: PublicAPI.Chrome.DevTools.Network;
286 panels: PublicAPI.Chrome.DevTools.Panels;
287 inspectedWindow: PublicAPI.Chrome.DevTools.InspectedWindow;
288 }
289
290 export interface ExtensionServerClient {
291 _callbacks: {[key: string]: (response: unknown) => unknown};
292 _handlers: {[key: string]: (request: {arguments: unknown[]}) => unknown};
293 _lastRequestId: number;
294 _lastObjectId: number;
295 _port: MessagePort;
296
297 _onCallback(request: unknown): void;
298 _onMessage(event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void;
299 _registerCallback(callback: (response: unknown) => unknown): number;
300 registerHandler(command: string, handler: (request: {arguments: unknown[]}) => unknown): void;
301 unregisterHandler(command: string): void;
302 hasHandler(command: string): boolean;
303 sendRequest(request: PrivateAPI.ServerRequests, callback?: ((response: unknown) => unknown), transfers?: unknown[]):
304 void;
305 nextObjectId(): string;
306 }
307
308 // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
309 // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
310 // resolution and meaningful type inference of arguments break, for example.
Tim van der Lippe269e9ae2021-12-14 13:33:28311 // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
Philip Pfaffe7523faf2021-06-28 14:23:14312 // eslint-disable-next-line @typescript-eslint/no-explicit-any
Tim van der Lippe269e9ae2021-12-14 13:33:28313 export type Callable = (...args: any) => void;
Philip Pfaffe7523faf2021-06-28 14:23:14314
315 export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
316 _type: string;
317 _listeners: ListenerT[];
318 _customDispatch: undefined|((this: EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown);
319
320 _fire(..._vararg: Parameters<ListenerT>): void;
321 _dispatch(request: {arguments: unknown[]}): void;
322 }
Philip Pfaffe4b88c662021-06-25 12:30:47323
324 export interface Network extends PublicAPI.Chrome.DevTools.Network {
325 addRequestHeaders(headers: {[key: string]: string}): void;
326 }
327
328 export interface Request extends PublicAPI.Chrome.DevTools.Request, HAR.Log.EntryDTO {
329 _id: number;
330 }
Philip Pfaffe6fd04c42021-06-25 12:31:48331
332 export interface Panels extends PublicAPI.Chrome.DevTools.Panels {
333 get SearchAction(): {[key: string]: string};
334 applyStyleSheet(styleSheet: string): void;
335 setOpenResourceHandler(callback?: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown):
336 void;
Paul Lewisada689f2022-01-11 12:03:40337 setThemeChangeHandler(callback?: (themeName: string) => unknown): void;
Philip Pfaffe6fd04c42021-06-25 12:31:48338 }
339
340 export interface ExtensionView extends PublicAPI.Chrome.DevTools.ExtensionView {
341 _id: string|null;
342 }
343
344 export interface ExtensionSidebarPane extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionSidebarPane {
345 setExpression(
346 expression: string, rootTitle?: string, evaluteOptions?: PrivateAPI.EvaluateOptions,
347 callback?: () => unknown): void;
348 }
349
350 export interface PanelWithSidebar extends ExtensionView, PublicAPI.Chrome.DevTools.PanelWithSidebar {
351 _hostPanelName: string;
352 }
353
354 export interface LanguageExtensions extends PublicAPI.Chrome.DevTools.LanguageExtensions {
355 _plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
356 }
357
358 export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
359 show(): void;
360 }
361
362 export interface Button extends PublicAPI.Chrome.DevTools.Button {
363 _id: string;
364 }
365
Philip Pfaffe1c827212021-06-25 12:33:20366 export interface TraceSession {
367 _id: string;
368
369 complete(url?: string, timeOffset?: number): void;
370 }
371
372 export interface TraceProvider {
373 onRecordingStarted: EventSink<(session: TraceSession) => unknown>;
374 onRecordingStopped: EventSink<() => unknown>;
375 }
376
377 export interface Timeline {
378 addTraceProvider(categoryName: string, categoryTooltip: string): TraceProvider;
379 }
380
Philip Pfaffe6fd04c42021-06-25 12:31:48381 export type ResourceData = {url: string, type: string};
382 export interface Resource extends PublicAPI.Chrome.DevTools.Resource {
383 _type: string;
384 _url: string;
385
386 get type(): string;
387 }
Philip Pfaffe7523faf2021-06-28 14:23:14388}
Philip Pfaffe939605d2021-06-25 12:20:04389
Tim van der Lippe226fc222019-10-10 12:17:12390self.injectedExtensionAPI = function(
Philip Pfaffe7523faf2021-06-28 14:23:14391 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
392 testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
Philip Pfaffe140e5432021-09-13 16:34:23393 injectedScriptId: number): void {
Jan Schefflerd76b4162021-03-29 07:52:16394 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37395 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16396
Blink Reformat4c46d092018-04-07 15:32:37397 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34398 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37399 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34400 }
Blink Reformat4c46d092018-04-07 15:32:37401 let userAction = false;
402
403 // Here and below, all constructors are private to API implementation.
404 // For a public type Foo, if internal fields are present, these are on
405 // a private FooImpl type, an instance of FooImpl is used in a closure
406 // by Foo consutrctor to re-bind publicly exported members to an instance
407 // of Foo.
408
Philip Pfaffe7523faf2021-06-28 14:23:14409 function EventSinkImpl<ListenerT extends APIImpl.Callable>(
410 this: APIImpl.EventSink<ListenerT>, type: string,
411 customDispatch?: (this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37412 this._type = type;
413 this._listeners = [];
414 this._customDispatch = customDispatch;
415 }
416
417 EventSinkImpl.prototype = {
Philip Pfaffe7523faf2021-06-28 14:23:14418 addListener: function<ListenerT extends APIImpl.Callable>(this: APIImpl.EventSink<ListenerT>, callback: ListenerT):
419 void {
420 if (typeof callback !== 'function') {
421 throw 'addListener: callback is not a function';
422 }
423 if (this._listeners.length === 0) {
424 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
425 }
426 this._listeners.push(callback);
427 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
428 },
Blink Reformat4c46d092018-04-07 15:32:37429
Philip Pfaffe7523faf2021-06-28 14:23:14430 removeListener: function<ListenerT extends APIImpl.Callable>(
431 this: APIImpl.EventSink<ListenerT>, callback: ListenerT): void {
Blink Reformat4c46d092018-04-07 15:32:37432 const listeners = this._listeners;
433
434 for (let i = 0; i < listeners.length; ++i) {
435 if (listeners[i] === callback) {
436 listeners.splice(i, 1);
437 break;
438 }
439 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34440 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04441 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34442 }
Blink Reformat4c46d092018-04-07 15:32:37443 },
444
Philip Pfaffe7523faf2021-06-28 14:23:14445 _fire: function<ListenerT extends APIImpl.Callable>(
446 this: APIImpl.EventSink<ListenerT>, ..._vararg: Parameters<ListenerT>): void {
Blink Reformat4c46d092018-04-07 15:32:37447 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34448 for (let i = 0; i < listeners.length; ++i) {
Philip Pfaffe7523faf2021-06-28 14:23:14449 listeners[i].apply(null, Array.from(arguments));
Tim van der Lippe1d6e57a2019-09-30 11:55:34450 }
Blink Reformat4c46d092018-04-07 15:32:37451 },
452
Philip Pfaffe7523faf2021-06-28 14:23:14453 _dispatch: function<ListenerT extends APIImpl.Callable>(
454 this: APIImpl.EventSink<ListenerT>, request: {arguments: unknown[]}): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34455 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37456 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34457 } else {
Philip Pfaffe7523faf2021-06-28 14:23:14458 this._fire.apply(this, request.arguments as Parameters<ListenerT>);
Tim van der Lippe1d6e57a2019-09-30 11:55:34459 }
Jan Schefflerd76b4162021-03-29 07:52:16460 },
Blink Reformat4c46d092018-04-07 15:32:37461 };
462
Philip Pfaffe7523faf2021-06-28 14:23:14463 function Constructor<NewT extends APIImpl.Callable>(ctor: NewT): new (...args: Parameters<NewT>) =>
464 ThisParameterType<NewT> {
465 return ctor as unknown as new (...args: Parameters<NewT>) => ThisParameterType<NewT>;
466 }
467
Philip Pfaffe7523faf2021-06-28 14:23:14468 function InspectorExtensionAPI(this: APIImpl.InspectorExtensionAPI): void {
Philip Pfaffeddf60d22021-06-25 12:35:41469 this.inspectedWindow = new (Constructor(InspectedWindow))();
Philip Pfaffe6fd04c42021-06-25 12:31:48470 this.panels = new (Constructor(Panels))();
Philip Pfaffe4b88c662021-06-25 12:30:47471 this.network = new (Constructor(Network))();
Philip Pfaffe1c827212021-06-25 12:33:20472 this.timeline = new (Constructor(Timeline))();
Philip Pfaffec5d160e2021-07-20 10:53:32473 this.languageServices = new (Constructor(LanguageServicesAPI))();
Blink Reformat4c46d092018-04-07 15:32:37474 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
475 }
476
Philip Pfaffe4b88c662021-06-25 12:30:47477 function Network(this: APIImpl.Network): void {
478 function dispatchRequestEvent(
479 this: APIImpl.EventSink<(request: PublicAPI.Chrome.DevTools.Request) => unknown>,
480 message: {arguments: unknown[]}): void {
481 const request = message.arguments[1] as APIImpl.Request & {__proto__: APIImpl.Request};
482
483 request.__proto__ = new (Constructor(Request))(message.arguments[0] as number);
Blink Reformat4c46d092018-04-07 15:32:37484 this._fire(request);
485 }
Philip Pfaffe4b88c662021-06-25 12:30:47486
487 this.onRequestFinished =
488 new (Constructor(EventSink))(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37489 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe4b88c662021-06-25 12:30:47490
491 this.onNavigated = new (Constructor(EventSink))(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37492 }
493
Philip Pfaffe4b88c662021-06-25 12:30:47494 (Network.prototype as Pick<APIImpl.Network, 'getHAR'|'addRequestHeaders'>) = {
495 getHAR: function(this: PublicAPI.Chrome.DevTools.Network, callback?: (harLog: Object) => unknown): void {
496 function callbackWrapper(response: unknown): void {
497 const result =
498 response as ({entries: Array<HAR.Log.EntryDTO&{__proto__?: APIImpl.Request, _requestId?: number}>});
Blink Reformat4c46d092018-04-07 15:32:37499 const entries = (result && result.entries) || [];
500 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe4b88c662021-06-25 12:30:47501 entries[i].__proto__ = new (Constructor(Request))(entries[i]._requestId as number);
Blink Reformat4c46d092018-04-07 15:32:37502 delete entries[i]._requestId;
503 }
Philip Pfaffe4b88c662021-06-25 12:30:47504 callback && callback(result as Object);
Blink Reformat4c46d092018-04-07 15:32:37505 }
Philip Pfaffe939605d2021-06-25 12:20:04506 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37507 },
508
Philip Pfaffe4b88c662021-06-25 12:30:47509 addRequestHeaders: function(headers: {[key: string]: string}): void {
Blink Reformat4c46d092018-04-07 15:32:37510 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04511 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16512 },
Blink Reformat4c46d092018-04-07 15:32:37513 };
514
Philip Pfaffe4b88c662021-06-25 12:30:47515 function RequestImpl(this: APIImpl.Request, id: number): void {
Blink Reformat4c46d092018-04-07 15:32:37516 this._id = id;
517 }
518
Philip Pfaffe4b88c662021-06-25 12:30:47519 (RequestImpl.prototype as Pick<APIImpl.Request, 'getContent'>) = {
520 getContent: function(this: APIImpl.Request, callback?: (content: string, encoding: string) => unknown): void {
521 function callbackWrapper(response: unknown): void {
522 const {content, encoding} = response as {content: string, encoding: string};
523 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:37524 }
Philip Pfaffe939605d2021-06-25 12:20:04525 extensionServer.sendRequest(
526 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16527 },
Blink Reformat4c46d092018-04-07 15:32:37528 };
529
Philip Pfaffe6fd04c42021-06-25 12:31:48530 function Panels(this: APIImpl.Panels): void {
531 const panels: {[key: string]: ElementsPanel|SourcesPanel} = {
Blink Reformat4c46d092018-04-07 15:32:37532 elements: new ElementsPanel(),
533 sources: new SourcesPanel(),
534 };
535
Philip Pfaffe6fd04c42021-06-25 12:31:48536 function panelGetter(name: string): ElementsPanel|SourcesPanel {
Blink Reformat4c46d092018-04-07 15:32:37537 return panels[name];
538 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34539 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12540 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34541 }
Philip Pfaffe6fd04c42021-06-25 12:31:48542 this.applyStyleSheet = function(styleSheet: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04543 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37544 };
545 }
546
Paul Lewisada689f2022-01-11 12:03:40547 (Panels.prototype as
548 Pick<APIImpl.Panels, 'create'|'setOpenResourceHandler'|'openResource'|'SearchAction'|'setThemeChangeHandler'>) = {
Philip Pfaffe6fd04c42021-06-25 12:31:48549 create: function(
550 title: string, icon: string, page: string,
551 callback: (panel: PublicAPI.Chrome.DevTools.ExtensionPanel) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37552 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe6fd04c42021-06-25 12:31:48553 extensionServer.sendRequest(
554 {command: PrivateAPI.Commands.CreatePanel, id, title, page},
Philip Pfaffe3abccb42021-09-14 09:18:37555 callback && ((): unknown => callback.call(this, new (Constructor(ExtensionPanel))(id))));
Blink Reformat4c46d092018-04-07 15:32:37556 },
557
Philip Pfaffe6fd04c42021-06-25 12:31:48558 setOpenResourceHandler: function(
559 callback: (resource: PublicAPI.Chrome.DevTools.Resource, lineNumber: number) => unknown): void {
Philip Pfaffe939605d2021-06-25 12:20:04560 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37561
Philip Pfaffe6fd04c42021-06-25 12:31:48562 function callbackWrapper(message: unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37563 // Allow the panel to show itself when handling the event.
564 userAction = true;
565 try {
Philip Pfaffe6fd04c42021-06-25 12:31:48566 const {resource, lineNumber} = message as {resource: APIImpl.ResourceData, lineNumber: number};
567 callback.call(null, new (Constructor(Resource))(resource), lineNumber);
Blink Reformat4c46d092018-04-07 15:32:37568 } finally {
569 userAction = false;
570 }
571 }
572
Tim van der Lippe1d6e57a2019-09-30 11:55:34573 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04574 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34575 } else {
Philip Pfaffe939605d2021-06-25 12:20:04576 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34577 }
Blink Reformat4c46d092018-04-07 15:32:37578
579 // 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:34580 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04581 extensionServer.sendRequest(
582 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34583 }
Blink Reformat4c46d092018-04-07 15:32:37584 },
585
Paul Lewisada689f2022-01-11 12:03:40586 setThemeChangeHandler: function(callback: (themeName: string) => unknown): void {
587 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.ThemeChange);
588
589 function callbackWrapper(message: unknown): void {
590 const {themeName} = message as {themeName: string};
591 chrome.devtools.panels.themeName = themeName;
592 callback.call(null, themeName);
593 }
594
595 if (!callback) {
596 extensionServer.unregisterHandler(PrivateAPI.Events.ThemeChange);
597 } else {
598 extensionServer.registerHandler(PrivateAPI.Events.ThemeChange, callbackWrapper);
599 }
600
601 // Only send command if we either removed an existing handler or added handler and had none before.
602 if (hadHandler === !callback) {
603 extensionServer.sendRequest(
604 {command: PrivateAPI.Commands.SetThemeChangeHandler, 'handlerPresent': Boolean(callback)});
605 }
606 },
607
Philip Pfaffe140e5432021-09-13 16:34:23608 openResource: function(
609 url: string, lineNumber: number, columnNumber?: number, _callback?: (response: unknown) => unknown): void {
610 const callbackArg = extractCallbackArgument(arguments);
611 // Handle older API:
612 const columnNumberArg = typeof columnNumber === 'number' ? columnNumber : 0;
613 extensionServer.sendRequest(
614 {command: PrivateAPI.Commands.OpenResource, url, lineNumber, columnNumber: columnNumberArg}, callbackArg);
Blink Reformat4c46d092018-04-07 15:32:37615 },
616
Philip Pfaffe6fd04c42021-06-25 12:31:48617 get SearchAction(): {[key: string]: string} {
Philip Pfaffe939605d2021-06-25 12:20:04618 return {
619 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
620 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
621 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
622 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
623 };
Jan Schefflerd76b4162021-03-29 07:52:16624 },
Blink Reformat4c46d092018-04-07 15:32:37625 };
626
Philip Pfaffe6fd04c42021-06-25 12:31:48627 function ExtensionViewImpl(this: APIImpl.ExtensionView, id: string|null): void {
Blink Reformat4c46d092018-04-07 15:32:37628 this._id = id;
629
Philip Pfaffe6fd04c42021-06-25 12:31:48630 function dispatchShowEvent(
631 this: APIImpl.EventSink<(window?: Window) => unknown>, message: {arguments: unknown[]}): void {
Blink Reformat4c46d092018-04-07 15:32:37632 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34633 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37634 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34635 } else {
Blink Reformat4c46d092018-04-07 15:32:37636 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34637 }
Blink Reformat4c46d092018-04-07 15:32:37638 }
639
640 if (id) {
Philip Pfaffe6fd04c42021-06-25 12:31:48641 this.onShown = new (Constructor(EventSink))(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
642
643 this.onHidden = new (Constructor(EventSink))(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37644 }
645 }
646
Philip Pfaffe6fd04c42021-06-25 12:31:48647 function PanelWithSidebarImpl(this: APIImpl.PanelWithSidebar, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37648 ExtensionViewImpl.call(this, null);
649 this._hostPanelName = hostPanelName;
Philip Pfaffe6fd04c42021-06-25 12:31:48650
651 this.onSelectionChanged = new (Constructor(EventSink))(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37652 }
653
Philip Pfaffe6fd04c42021-06-25 12:31:48654 (PanelWithSidebarImpl.prototype as Pick<APIImpl.PanelWithSidebar, 'createSidebarPane'>&
655 {__proto__: APIImpl.ExtensionView}) = {
656 createSidebarPane: function(
657 this: APIImpl.PanelWithSidebar, title: string,
658 callback?: (pane: PublicAPI.Chrome.DevTools.ExtensionSidebarPane) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37659 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Jan Schefflerd76b4162021-03-29 07:52:16660 function callbackWrapper(): void {
Philip Pfaffe6fd04c42021-06-25 12:31:48661 callback && callback(new (Constructor(ExtensionSidebarPane))(id));
Blink Reformat4c46d092018-04-07 15:32:37662 }
Philip Pfaffe7523faf2021-06-28 14:23:14663 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48664 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id, title},
Philip Pfaffe7523faf2021-06-28 14:23:14665 callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37666 },
667
Jan Schefflerd76b4162021-03-29 07:52:16668 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37669 };
670
Philip Pfaffec5d160e2021-07-20 10:53:32671 function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
Philip Pfaffeedad8322020-07-20 10:24:25672 this._plugins = new Map();
673 }
674
Philip Pfaffec5d160e2021-07-20 10:53:32675 (LanguageServicesAPIImpl.prototype as
676 Pick<APIImpl.LanguageExtensions, 'registerLanguageExtensionPlugin'|'unregisterLanguageExtensionPlugin'>) = {
Philip Pfaffed662bdf2021-06-25 13:30:32677 registerLanguageExtensionPlugin: async function(
Philip Pfaffec5d160e2021-07-20 10:53:32678 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, pluginName: string,
679 supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes): Promise<void> {
680 if (this._plugins.has(plugin)) {
681 throw new Error(`Tried to register plugin '${pluginName}' twice`);
682 }
683 const channel = new MessageChannel();
684 const port = channel.port1;
685 this._plugins.set(plugin, port);
686 port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.LanguageExtensionRequests>): void => {
687 const {requestId} = data;
688 console.time(`${requestId}: ${data.method}`);
689 dispatchMethodCall(data)
690 .then(result => port.postMessage({requestId, result}))
691 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
692 .finally(() => console.timeEnd(`${requestId}: ${data.method}`));
693 };
Philip Pfaffeedad8322020-07-20 10:24:25694
Philip Pfaffec5d160e2021-07-20 10:53:32695 function dispatchMethodCall(request: PrivateAPI.LanguageExtensionRequests): Promise<unknown> {
696 switch (request.method) {
697 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
698 return plugin.addRawModule(
699 request.parameters.rawModuleId, request.parameters.symbolsURL, request.parameters.rawModule);
700 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
701 return plugin.removeRawModule(request.parameters.rawModuleId);
702 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
703 return plugin.sourceLocationToRawLocation(request.parameters.sourceLocation);
704 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
705 return plugin.rawLocationToSourceLocation(request.parameters.rawLocation);
706 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
707 return plugin.getScopeInfo(request.parameters.type);
708 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
709 return plugin.listVariablesInScope(request.parameters.rawLocation);
710 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
711 return plugin.getTypeInfo(request.parameters.expression, request.parameters.context);
712 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
713 return plugin.getFormatter(request.parameters.expressionOrField, request.parameters.context);
714 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
715 if ('getInspectableAddress' in plugin) {
716 return plugin.getInspectableAddress(request.parameters.field);
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02717 }
Philip Pfaffec5d160e2021-07-20 10:53:32718 return Promise.resolve({js: ''});
719 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
720 return plugin.getFunctionInfo(request.parameters.rawLocation);
721 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
722 return plugin.getInlinedFunctionRanges(request.parameters.rawLocation);
723 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
724 return plugin.getInlinedCalleesRanges(request.parameters.rawLocation);
725 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
726 if ('getMappedLines' in plugin) {
727 return plugin.getMappedLines(request.parameters.rawModuleId, request.parameters.sourceFileURL);
728 }
729 return Promise.resolve(undefined);
730 }
731 // @ts-expect-error
732 throw new Error(`Unknown language plugin method ${request.method}`);
733 }
Philip Pfaffeedad8322020-07-20 10:24:25734
Philip Pfaffec5d160e2021-07-20 10:53:32735 await new Promise<void>(resolve => {
736 extensionServer.sendRequest(
737 {
738 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
739 pluginName,
740 port: channel.port2,
741 supportedScriptTypes,
742 },
743 () => resolve(), [channel.port2]);
744 });
745 },
Benedikt Meurer929fc7c2020-11-20 14:21:06746
Philip Pfaffec5d160e2021-07-20 10:53:32747 unregisterLanguageExtensionPlugin: async function(
748 this: APIImpl.LanguageExtensions, plugin: PublicAPI.Chrome.DevTools.LanguageExtensionPlugin): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06749 const port = this._plugins.get(plugin);
750 if (!port) {
751 throw new Error('Tried to unregister a plugin that was not previously registered');
752 }
753 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04754 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06755 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16756 },
Philip Pfaffeedad8322020-07-20 10:24:25757 };
758
Philip Pfaffe7523faf2021-06-28 14:23:14759 function declareInterfaceClass<ImplT extends APIImpl.Callable>(implConstructor: ImplT): (
760 this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>) => void {
761 return function(this: ThisParameterType<ImplT>, ...args: Parameters<ImplT>): void {
Blink Reformat4c46d092018-04-07 15:32:37762 const impl = {__proto__: implConstructor.prototype};
Philip Pfaffe7523faf2021-06-28 14:23:14763 implConstructor.apply(impl, args);
764 populateInterfaceClass(this as {[key: string]: unknown}, impl);
Blink Reformat4c46d092018-04-07 15:32:37765 };
766 }
767
Philip Pfaffe7523faf2021-06-28 14:23:14768 // eslint-disable-next-line @typescript-eslint/no-explicit-any
769 function defineDeprecatedProperty(object: any, className: string, oldName: string, newName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37770 let warningGiven = false;
Philip Pfaffe7523faf2021-06-28 14:23:14771 function getter(): unknown {
Blink Reformat4c46d092018-04-07 15:32:37772 if (!warningGiven) {
773 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
774 warningGiven = true;
775 }
776 return object[newName];
777 }
778 object.__defineGetter__(oldName, getter);
779 }
780
Philip Pfaffe7523faf2021-06-28 14:23:14781 function extractCallbackArgument(args: IArguments): ((...args: unknown[]) => unknown)|undefined {
Blink Reformat4c46d092018-04-07 15:32:37782 const lastArgument = args[args.length - 1];
Philip Pfaffe7523faf2021-06-28 14:23:14783 return typeof lastArgument === 'function' ? lastArgument as (...args: unknown[]) => unknown : undefined;
Blink Reformat4c46d092018-04-07 15:32:37784 }
785
Philip Pfaffeedad8322020-07-20 10:24:25786 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37787 const Button = declareInterfaceClass(ButtonImpl);
788 const EventSink = declareInterfaceClass(EventSinkImpl);
789 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
790 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12791 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37792 const Request = declareInterfaceClass(RequestImpl);
793 const Resource = declareInterfaceClass(ResourceImpl);
794 const TraceSession = declareInterfaceClass(TraceSessionImpl);
795
Philip Pfaffe6fd04c42021-06-25 12:31:48796 class ElementsPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12797 constructor() {
798 super('elements');
799 }
Blink Reformat4c46d092018-04-07 15:32:37800 }
801
Philip Pfaffe6fd04c42021-06-25 12:31:48802 class SourcesPanel extends (Constructor(PanelWithSidebarClass)) {
Tim van der Lippeffa78622019-09-16 12:07:12803 constructor() {
804 super('sources');
805 }
Blink Reformat4c46d092018-04-07 15:32:37806 }
807
Philip Pfaffe6fd04c42021-06-25 12:31:48808 function ExtensionPanelImpl(this: APIImpl.ExtensionPanel, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37809 ExtensionViewImpl.call(this, id);
Philip Pfaffe6fd04c42021-06-25 12:31:48810
811 this.onSearch = new (Constructor(EventSink))(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37812 }
813
Philip Pfaffe6fd04c42021-06-25 12:31:48814 (ExtensionPanelImpl.prototype as Pick<APIImpl.ExtensionPanel, 'createStatusBarButton'|'show'>&
815 {__proto__: APIImpl.ExtensionView}) = {
816 createStatusBarButton: function(
817 this: APIImpl.ExtensionPanel, iconPath: string, tooltipText: string, disabled: boolean):
818 PublicAPI.Chrome.DevTools.Button {
819 const id = 'button-' + extensionServer.nextObjectId();
820 extensionServer.sendRequest({
821 command: PrivateAPI.Commands.CreateToolbarButton,
822 panel: this._id as string,
823 id: id,
824 icon: iconPath,
825 tooltip: tooltipText,
826 disabled: Boolean(disabled),
827 });
Blink Reformat4c46d092018-04-07 15:32:37828
Philip Pfaffe6fd04c42021-06-25 12:31:48829 return new (Constructor(Button))(id);
830 },
831
832 show: function(this: APIImpl.ExtensionPanel): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34833 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:37834 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34835 }
Blink Reformat4c46d092018-04-07 15:32:37836
Philip Pfaffe6fd04c42021-06-25 12:31:48837 extensionServer.sendRequest({command: PrivateAPI.Commands.ShowPanel, id: this._id as string});
Blink Reformat4c46d092018-04-07 15:32:37838 },
839
Jan Schefflerd76b4162021-03-29 07:52:16840 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37841 };
842
Philip Pfaffe6fd04c42021-06-25 12:31:48843 function ExtensionSidebarPaneImpl(this: APIImpl.ExtensionSidebarPane, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37844 ExtensionViewImpl.call(this, id);
845 }
846
Philip Pfaffe6fd04c42021-06-25 12:31:48847 (ExtensionSidebarPaneImpl.prototype as
848 Pick<APIImpl.ExtensionSidebarPane, 'setHeight'|'setExpression'|'setObject'|'setPage'>&
849 {__proto__: APIImpl.ExtensionView}) = {
850 setHeight: function(this: APIImpl.ExtensionSidebarPane, height: string): void {
851 extensionServer.sendRequest(
852 {command: PrivateAPI.Commands.SetSidebarHeight, id: this._id as string, height: height});
Blink Reformat4c46d092018-04-07 15:32:37853 },
854
Philip Pfaffe6fd04c42021-06-25 12:31:48855 setExpression: function(
856 this: APIImpl.ExtensionSidebarPane, expression: string, rootTitle: string,
857 evaluateOptions?: PrivateAPI.EvaluateOptions, _callback?: () => unknown): void {
Philip Pfaffe7523faf2021-06-28 14:23:14858 extensionServer.sendRequest(
859 {
860 command: PrivateAPI.Commands.SetSidebarContent,
Philip Pfaffe6fd04c42021-06-25 12:31:48861 id: this._id as string,
Philip Pfaffe7523faf2021-06-28 14:23:14862 expression: expression,
863 rootTitle: rootTitle,
864 evaluateOnPage: true,
Philip Pfaffe6fd04c42021-06-25 12:31:48865 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : {}),
Philip Pfaffe7523faf2021-06-28 14:23:14866 },
867 extractCallbackArgument(arguments));
Blink Reformat4c46d092018-04-07 15:32:37868 },
869
Philip Pfaffe6fd04c42021-06-25 12:31:48870 setObject: function(
871 this: APIImpl.ExtensionSidebarPane, jsonObject: string, rootTitle?: string, callback?: () => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:37872 extensionServer.sendRequest(
Philip Pfaffe6fd04c42021-06-25 12:31:48873 {
874 command: PrivateAPI.Commands.SetSidebarContent,
875 id: this._id as string,
876 expression: jsonObject,
877 rootTitle: rootTitle,
878 },
Philip Pfaffe939605d2021-06-25 12:20:04879 callback);
Blink Reformat4c46d092018-04-07 15:32:37880 },
881
Philip Pfaffe6fd04c42021-06-25 12:31:48882 setPage: function(this: APIImpl.ExtensionSidebarPane, page: string): void {
883 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id as string, page: page});
Blink Reformat4c46d092018-04-07 15:32:37884 },
885
Jan Schefflerd76b4162021-03-29 07:52:16886 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37887 };
888
Philip Pfaffe6fd04c42021-06-25 12:31:48889 function ButtonImpl(this: APIImpl.Button, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37890 this._id = id;
Philip Pfaffe6fd04c42021-06-25 12:31:48891
892 this.onClicked = new (Constructor(EventSink))(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:37893 }
894
Philip Pfaffe6fd04c42021-06-25 12:31:48895 (ButtonImpl.prototype as Pick<APIImpl.Button, 'update'>) = {
896 update: function(this: APIImpl.Button, iconPath?: string, tooltipText?: string, disabled?: boolean): void {
Philip Pfaffe7523faf2021-06-28 14:23:14897 extensionServer.sendRequest({
Philip Pfaffe939605d2021-06-25 12:20:04898 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:24899 id: this._id,
900 icon: iconPath,
901 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16902 disabled: Boolean(disabled),
Philip Pfaffe7523faf2021-06-28 14:23:14903 });
Jan Schefflerd76b4162021-03-29 07:52:16904 },
Blink Reformat4c46d092018-04-07 15:32:37905 };
906
Philip Pfaffe1c827212021-06-25 12:33:20907 function Timeline(this: APIImpl.Timeline): void {
Blink Reformat4c46d092018-04-07 15:32:37908 }
909
Philip Pfaffe1c827212021-06-25 12:33:20910 (Timeline.prototype as Pick<APIImpl.Timeline, 'addTraceProvider'>) = {
911 addTraceProvider: function(this: APIImpl.Timeline, categoryName: string, categoryTooltip: string):
912 APIImpl.TraceProvider {
913 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
914 extensionServer.sendRequest({
915 command: PrivateAPI.Commands.AddTraceProvider,
916 id: id,
917 categoryName: categoryName,
918 categoryTooltip: categoryTooltip,
919 });
920
921 return new (Constructor(TraceProvider))(id);
922 },
Blink Reformat4c46d092018-04-07 15:32:37923 };
924
Philip Pfaffe1c827212021-06-25 12:33:20925 function TraceSessionImpl(this: APIImpl.TraceSession, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37926 this._id = id;
927 }
928
Philip Pfaffe1c827212021-06-25 12:33:20929 (TraceSessionImpl.prototype as Pick<APIImpl.TraceSession, 'complete'>) = {
930 complete: function(this: APIImpl.TraceSession, 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
Philip Pfaffe1c827212021-06-25 12:33:20940 function TraceProvider(this: APIImpl.TraceProvider, id: string): void {
941 function dispatchRecordingStarted(
942 this: APIImpl.EventSink<APIImpl.Callable>, message: {arguments: unknown[]}): void {
943 const sessionId = message.arguments[0] as string;
944
945 this._fire(new (Constructor(TraceSession))(sessionId));
Blink Reformat4c46d092018-04-07 15:32:37946 }
947
Philip Pfaffe1c827212021-06-25 12:33:20948 this.onRecordingStarted =
949 new (Constructor(EventSink))(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
950
951 this.onRecordingStopped = new (Constructor(EventSink))(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:37952 }
953
Philip Pfaffeddf60d22021-06-25 12:35:41954 function InspectedWindow(this: PublicAPI.Chrome.DevTools.InspectedWindow): void {
955 function dispatchResourceEvent(
956 this: APIImpl.EventSink<(resource: APIImpl.Resource) => unknown>, message: {arguments: unknown[]}): void {
957 this._fire(new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData));
Blink Reformat4c46d092018-04-07 15:32:37958 }
959
Philip Pfaffeddf60d22021-06-25 12:35:41960 function dispatchResourceContentEvent(
961 this: APIImpl.EventSink<(resource: APIImpl.Resource, content: string) => unknown>,
962 message: {arguments: unknown[]}): void {
963 this._fire(
964 new (Constructor(Resource))(message.arguments[0] as APIImpl.ResourceData), message.arguments[1] as string);
Blink Reformat4c46d092018-04-07 15:32:37965 }
966
Philip Pfaffeddf60d22021-06-25 12:35:41967 this.onResourceAdded = new (Constructor(EventSink))(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
Philip Pfaffe939605d2021-06-25 12:20:04968 this.onResourceContentCommitted =
Philip Pfaffeddf60d22021-06-25 12:35:41969 new (Constructor(EventSink))(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:37970 }
971
Philip Pfaffeddf60d22021-06-25 12:35:41972 (InspectedWindow.prototype as Pick<PublicAPI.Chrome.DevTools.InspectedWindow, 'reload'|'eval'|'getResources'>) = {
973 reload: function(optionsOrUserAgent: {
974 ignoreCache?: boolean,
975 injectedScript?: string,
976 userAgent?: string,
977 }): void {
Jan Schefflerd76b4162021-03-29 07:52:16978 let options: {
Philip Pfaffeddf60d22021-06-25 12:35:41979 ignoreCache?: boolean,
980 injectedScript?: string,
981 userAgent?: string,
Jan Schefflerd76b4162021-03-29 07:52:16982 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:37983 if (typeof optionsOrUserAgent === 'object') {
984 options = optionsOrUserAgent;
985 } else if (typeof optionsOrUserAgent === 'string') {
986 options = {userAgent: optionsOrUserAgent};
987 console.warn(
988 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
989 'Use inspectedWindow.reload({ userAgent: value}) instead.');
990 }
Philip Pfaffe939605d2021-06-25 12:20:04991 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:37992 },
993
Philip Pfaffeddf60d22021-06-25 12:35:41994 eval: function(
995 expression: string,
996 evaluateOptions: {contextSecurityOrigin?: string, frameURL?: string, useContentScriptContext?: boolean}):
997 Object |
Jan Schefflerd76b4162021-03-29 07:52:16998 null {
999 const callback = extractCallbackArgument(arguments);
Philip Pfaffeddf60d22021-06-25 12:35:411000 function callbackWrapper(result: unknown): void {
1001 const {isError, isException, value} = result as {
1002 isError?: boolean,
1003 isException?: boolean, value: unknown,
1004 };
1005 if (isError || isException) {
Philip Pfaffe7523faf2021-06-28 14:23:141006 callback && callback(undefined, result);
Jan Schefflerd76b4162021-03-29 07:52:161007 } else {
Philip Pfaffeddf60d22021-06-25 12:35:411008 callback && callback(value);
Jan Schefflerd76b4162021-03-29 07:52:161009 }
1010 }
Philip Pfaffe7523faf2021-06-28 14:23:141011 extensionServer.sendRequest(
1012 {
1013 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
1014 expression: expression,
1015 evaluateOptions: (typeof evaluateOptions === 'object' ? evaluateOptions : undefined),
1016 },
1017 callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161018 return null;
1019 },
Blink Reformat4c46d092018-04-07 15:32:371020
Philip Pfaffeddf60d22021-06-25 12:35:411021 getResources: function(callback?: (resources: PublicAPI.Chrome.DevTools.Resource[]) => unknown): void {
1022 function wrapResource(resourceData: APIImpl.ResourceData): APIImpl.Resource {
1023 return new (Constructor(Resource))(resourceData);
Blink Reformat4c46d092018-04-07 15:32:371024 }
Philip Pfaffeddf60d22021-06-25 12:35:411025 function callbackWrapper(resources: unknown): void {
1026 callback && callback((resources as APIImpl.ResourceData[]).map(wrapResource));
Blink Reformat4c46d092018-04-07 15:32:371027 }
Philip Pfaffe939605d2021-06-25 12:20:041028 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:161029 },
Blink Reformat4c46d092018-04-07 15:32:371030 };
1031
Philip Pfaffe6fd04c42021-06-25 12:31:481032 function ResourceImpl(this: APIImpl.Resource, resourceData: APIImpl.ResourceData): void {
Blink Reformat4c46d092018-04-07 15:32:371033 this._url = resourceData.url;
1034 this._type = resourceData.type;
1035 }
1036
Philip Pfaffe6fd04c42021-06-25 12:31:481037 (ResourceImpl.prototype as Pick<APIImpl.Resource, 'url'|'type'|'getContent'|'setContent'>) = {
Jan Schefflerd76b4162021-03-29 07:52:161038 get url(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481039 return (this as APIImpl.Resource)._url;
Blink Reformat4c46d092018-04-07 15:32:371040 },
1041
Jan Schefflerd76b4162021-03-29 07:52:161042 get type(): string {
Philip Pfaffe6fd04c42021-06-25 12:31:481043 return (this as APIImpl.Resource)._type;
Blink Reformat4c46d092018-04-07 15:32:371044 },
1045
Philip Pfaffe6fd04c42021-06-25 12:31:481046 getContent: function(this: APIImpl.Resource, callback?: (content: string, encoding: string) => unknown): void {
1047 function callbackWrapper(response: unknown): void {
1048 const {content, encoding} = response as {content: string, encoding: string};
1049 callback && callback(content, encoding);
Blink Reformat4c46d092018-04-07 15:32:371050 }
1051
Philip Pfaffe939605d2021-06-25 12:20:041052 extensionServer.sendRequest(
1053 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:371054 },
1055
Philip Pfaffe6fd04c42021-06-25 12:31:481056 setContent: function(
1057 this: APIImpl.Resource, content: string, commit: boolean, callback: (error?: Object) => unknown): void {
Blink Reformat4c46d092018-04-07 15:32:371058 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:041059 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
Philip Pfaffe6fd04c42021-06-25 12:31:481060 callback as (response: unknown) => unknown);
Jan Schefflerd76b4162021-03-29 07:52:161061 },
Blink Reformat4c46d092018-04-07 15:32:371062 };
1063
Jan Schefflerd76b4162021-03-29 07:52:161064 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:371065 return inspectedTabId;
1066 }
1067
Philip Pfaffe7523faf2021-06-28 14:23:141068 let keyboardEventRequestQueue: KeyboardEventInit&{eventType: string}[] = [];
Jan Schefflerd76b4162021-03-29 07:52:161069 let forwardTimer: number|null = null;
Philip Pfaffe7523faf2021-06-28 14:23:141070 function forwardKeyboardEvent(event: KeyboardEvent): void {
Jan Schefflere7d7bb12019-10-24 09:18:521071 // Check if the event should be forwarded.
1072 // This is a workaround for crbug.com/923338.
1073 const focused = document.activeElement;
1074 if (focused) {
1075 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
1076 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
1077 return;
1078 }
1079 }
1080
Joel Einbinder67f28fb2018-08-02 00:33:471081 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:341082 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471083 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:341084 }
1085 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471086 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:341087 }
1088 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471089 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:341090 }
1091 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:471092 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:341093 }
Joel Einbinder67f28fb2018-08-02 00:33:471094 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:371095 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:341096 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:371097 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341098 }
Joel Einbinder67f28fb2018-08-02 00:33:471099 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:371100 const requestPayload = {
1101 eventType: event.type,
1102 ctrlKey: event.ctrlKey,
1103 altKey: event.altKey,
1104 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:471105 shiftKey: event.shiftKey,
Philip Pfaffe7523faf2021-06-28 14:23:141106 // @ts-expect-error keyIdentifier is a deprecated non-standard property that typescript doesn't know about.
Blink Reformat4c46d092018-04-07 15:32:371107 keyIdentifier: event.keyIdentifier,
1108 key: event.key,
1109 code: event.code,
1110 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:161111 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:371112 };
1113 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:341114 if (!forwardTimer) {
Blink Reformat4c46d092018-04-07 15:32:371115 forwardTimer = setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:341116 }
Blink Reformat4c46d092018-04-07 15:32:371117 }
1118
Jan Schefflerd76b4162021-03-29 07:52:161119 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:371120 forwardTimer = null;
Philip Pfaffe7523faf2021-06-28 14:23:141121 extensionServer.sendRequest(
1122 {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue});
Blink Reformat4c46d092018-04-07 15:32:371123 keyboardEventRequestQueue = [];
1124 }
1125
1126 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:371127
Philip Pfaffe7523faf2021-06-28 14:23:141128 function ExtensionServerClient(this: APIImpl.ExtensionServerClient): void {
Blink Reformat4c46d092018-04-07 15:32:371129 this._callbacks = {};
1130 this._handlers = {};
1131 this._lastRequestId = 0;
1132 this._lastObjectId = 0;
1133
1134 this.registerHandler('callback', this._onCallback.bind(this));
1135
1136 const channel = new MessageChannel();
1137 this._port = channel.port1;
1138 this._port.addEventListener('message', this._onMessage.bind(this), false);
1139 this._port.start();
1140
1141 window.parent.postMessage('registerExtension', '*', [channel.port2]);
1142 }
1143
Philip Pfaffe7523faf2021-06-28 14:23:141144 (ExtensionServerClient.prototype as Pick<
1145 APIImpl.ExtensionServerClient,
1146 'sendRequest'|'hasHandler'|'registerHandler'|'unregisterHandler'|'nextObjectId'|'_registerCallback'|
1147 '_onCallback'|'_onMessage'>) = {
1148 sendRequest: function(
1149 this: APIImpl.ExtensionServerClient, message: PrivateAPI.ServerRequests,
1150 callback?: (response: unknown) => unknown, transfers?: Transferable[]): void {
1151 if (typeof callback === 'function') {
1152 (message as PrivateAPI.ExtensionServerRequestMessage).requestId = this._registerCallback(callback);
1153 }
1154 // @ts-expect-error
1155 this._port.postMessage(message, transfers);
1156 },
Blink Reformat4c46d092018-04-07 15:32:371157
Philip Pfaffe7523faf2021-06-28 14:23:141158 hasHandler: function(this: APIImpl.ExtensionServerClient, command: string): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:241159 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:371160 },
1161
Philip Pfaffe7523faf2021-06-28 14:23:141162 registerHandler: function(
1163 this: APIImpl.ExtensionServerClient, command: string, handler: (request: {arguments: unknown[]}) => unknown):
1164 void {
1165 this._handlers[command] = handler;
1166 },
Blink Reformat4c46d092018-04-07 15:32:371167
Philip Pfaffe7523faf2021-06-28 14:23:141168 unregisterHandler: function(this: APIImpl.ExtensionServerClient, command: string): void {
Blink Reformat4c46d092018-04-07 15:32:371169 delete this._handlers[command];
1170 },
1171
Philip Pfaffe7523faf2021-06-28 14:23:141172 nextObjectId: function(this: APIImpl.ExtensionServerClient): string {
Blink Reformat4c46d092018-04-07 15:32:371173 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
1174 },
1175
Philip Pfaffe7523faf2021-06-28 14:23:141176 _registerCallback: function(this: APIImpl.ExtensionServerClient, callback: (response: unknown) => unknown): number {
Blink Reformat4c46d092018-04-07 15:32:371177 const id = ++this._lastRequestId;
1178 this._callbacks[id] = callback;
1179 return id;
1180 },
1181
Philip Pfaffe7523faf2021-06-28 14:23:141182 _onCallback: function(this: APIImpl.ExtensionServerClient, request: {requestId: number, result: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371183 if (request.requestId in this._callbacks) {
1184 const callback = this._callbacks[request.requestId];
1185 delete this._callbacks[request.requestId];
1186 callback(request.result);
1187 }
1188 },
1189
Philip Pfaffe7523faf2021-06-28 14:23:141190 _onMessage: function(
1191 this: APIImpl.ExtensionServerClient,
1192 event: MessageEvent<{command: string, requestId: number, arguments: unknown[]}>): void {
Blink Reformat4c46d092018-04-07 15:32:371193 const request = event.data;
1194 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:341195 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:371196 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:341197 }
Jan Schefflerd76b4162021-03-29 07:52:161198 },
Blink Reformat4c46d092018-04-07 15:32:371199 };
1200
Philip Pfaffe7523faf2021-06-28 14:23:141201 function populateInterfaceClass(interfaze: {[key: string]: unknown}, implementation: {[key: string]: unknown}): void {
Blink Reformat4c46d092018-04-07 15:32:371202 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341203 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:371204 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341205 }
Jan Schefflerd76b4162021-03-29 07:52:161206 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:371207 // Traverse prototype chain until we find the owner.
Philip Pfaffe7523faf2021-06-28 14:23:141208 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__ as {[key: string]: unknown}) {
Blink Reformat4c46d092018-04-07 15:32:371209 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:341210 }
1211 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:371212 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341213 }
1214 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371215 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:341216 } else if (typeof descriptor.get === 'function') {
Philip Pfaffe7523faf2021-06-28 14:23:141217 // @ts-expect-error
Blink Reformat4c46d092018-04-07 15:32:371218 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:341219 } else {
Blink Reformat4c46d092018-04-07 15:32:371220 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:341221 }
Blink Reformat4c46d092018-04-07 15:32:371222 }
1223 }
1224
Philip Pfaffe7523faf2021-06-28 14:23:141225 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};