blob: e34a33419e8cfe5f9fa645a081513764420ab8f4 [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
Jan Schefflerd76b4162021-03-29 07:52:1631// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
32/* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/naming-convention */
Philip Pfaffe939605d2021-06-25 12:20:0433export namespace PrivateAPI {
34 export namespace Panels {
35 export const enum SearchAction {
36 CancelSearch = 'cancelSearch',
37 PerformSearch = 'performSearch',
38 NextSearchResult = 'nextSearchResult',
39 PreviousSearchResult = 'previousSearchResult',
40 }
Tim van der Lippe1d6e57a2019-09-30 11:55:3441 }
Blink Reformat4c46d092018-04-07 15:32:3742
Philip Pfaffe939605d2021-06-25 12:20:0443 export const enum Events {
44 ButtonClicked = 'button-clicked-',
45 PanelObjectSelected = 'panel-objectSelected-',
46 InspectedURLChanged = 'inspected-url-changed',
47 NetworkRequestFinished = 'network-request-finished',
48 OpenResource = 'open-resource',
49 PanelSearch = 'panel-search-',
50 RecordingStarted = 'trace-recording-started-',
51 RecordingStopped = 'trace-recording-stopped-',
52 ResourceAdded = 'resource-added',
53 ResourceContentCommitted = 'resource-content-committed',
54 ViewShown = 'view-shown-',
55 ViewHidden = 'view-hidden,',
56 }
Blink Reformat4c46d092018-04-07 15:32:3757
Philip Pfaffe939605d2021-06-25 12:20:0458 export const enum Commands {
59 AddRequestHeaders = 'addRequestHeaders',
60 AddTraceProvider = 'addTraceProvider',
61 ApplyStyleSheet = 'applyStyleSheet',
62 CompleteTraceSession = 'completeTra.eSession',
63 CreatePanel = 'createPanel',
64 CreateSidebarPane = 'createSidebarPane',
65 CreateToolbarButton = 'createToolbarButton',
66 EvaluateOnInspectedPage = 'evaluateOnInspectedPage',
67 ForwardKeyboardEvent = '_forwardKeyboardEvent',
68 GetHAR = 'getHAR',
69 GetPageResources = 'getPageResources',
70 GetRequestContent = 'getRequestContent',
71 GetResourceContent = 'getResourceContent',
72 OpenResource = 'openResource',
73 Reload = 'Reload',
74 Subscribe = 'subscribe',
75 SetOpenResourceHandler = 'setOpenResourceHandler',
76 SetResourceContent = 'setResourceContent',
77 SetSidebarContent = 'setSidebarContent',
78 SetSidebarHeight = 'setSidebarHeight',
79 SetSidebarPage = 'setSidebarPage',
80 ShowPanel = 'showPanel',
81 Unsubscribe = 'unsubscribe',
82 UpdateButton = 'updateButton',
83 RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
84 }
Philip Pfaffeedad8322020-07-20 10:24:2585
Philip Pfaffe939605d2021-06-25 12:20:0486 export const enum LanguageExtensionPluginCommands {
87 AddRawModule = 'addRawModule',
88 RemoveRawModule = 'removeRawModule',
89 SourceLocationToRawLocation = 'sourceLocationToRawLocation',
90 RawLocationToSourceLocation = 'rawLocationToSourceLocation',
91 GetScopeInfo = 'getScopeInfo',
92 ListVariablesInScope = 'listVariablesInScope',
93 GetTypeInfo = 'getTypeInfo',
94 GetFormatter = 'getFormatter',
95 GetInspectableAddress = 'getInspectableAddress',
96 GetFunctionInfo = 'getFunctionInfo',
97 GetInlinedFunctionRanges = 'getInlinedFunctionRanges',
98 GetInlinedCalleesRanges = 'getInlinedCalleesRanges',
99 GetMappedLines = 'getMappedLines',
100 }
Benedikt Meurer929fc7c2020-11-20 14:21:06101
Philip Pfaffe939605d2021-06-25 12:20:04102 export const enum LanguageExtensionPluginEvents {
103 UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
104 }
Blink Reformat4c46d092018-04-07 15:32:37105}
106
Philip Pfaffe939605d2021-06-25 12:20:04107declare global {
108 interface Window {
109 injectedExtensionAPI:
110 (extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
111 testHook: (server: any, api: any) => unknown, injectedScriptId: number) => void;
112 buildExtensionAPIInjectedScript(
113 extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
114 testHook: (server: any, api: any) => unknown): string;
115 chrome?: any;
116 webInspector?: any;
117 }
118}
119
120export type ExtensionDescriptor = {
121 startPage: string,
122 name: string,
123 exposeExperimentalAPIs: boolean,
124 exposeWebInspectorNamespace?: boolean,
125};
126
127
Tim van der Lippe226fc222019-10-10 12:17:12128self.injectedExtensionAPI = function(
Jan Schefflerd76b4162021-03-29 07:52:16129 extensionInfo: any, inspectedTabId: string, themeName: string, keysToForward: number[],
130 testHook: (arg0: Object, arg1: Object) => any, injectedScriptId: number): void {
131 const keysToForwardSet = new Set<number>(keysToForward);
Blink Reformat4c46d092018-04-07 15:32:37132 const chrome = window.chrome || {};
Jan Schefflerd76b4162021-03-29 07:52:16133
Blink Reformat4c46d092018-04-07 15:32:37134 const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
Tim van der Lippe1d6e57a2019-09-30 11:55:34135 if (devtools_descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37136 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34137 }
Blink Reformat4c46d092018-04-07 15:32:37138 let userAction = false;
139
140 // Here and below, all constructors are private to API implementation.
141 // For a public type Foo, if internal fields are present, these are on
142 // a private FooImpl type, an instance of FooImpl is used in a closure
143 // by Foo consutrctor to re-bind publicly exported members to an instance
144 // of Foo.
145
Jan Schefflerd76b4162021-03-29 07:52:16146 // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/naming-convention
Philip Pfaffe939605d2021-06-25 12:20:04147 function EventSinkImpl(this: any, type: any, customDispatch: any): void {
Blink Reformat4c46d092018-04-07 15:32:37148 this._type = type;
149 this._listeners = [];
150 this._customDispatch = customDispatch;
151 }
152
153 EventSinkImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16154
155 addListener: function(callback: any): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34156 if (typeof callback !== 'function') {
Blink Reformat4c46d092018-04-07 15:32:37157 throw 'addListener: callback is not a function';
Tim van der Lippe1d6e57a2019-09-30 11:55:34158 }
159 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04160 extensionServer.sendRequest({command: PrivateAPI.Commands.Subscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34161 }
Blink Reformat4c46d092018-04-07 15:32:37162 this._listeners.push(callback);
163 extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
164 },
165
Jan Schefflerd76b4162021-03-29 07:52:16166
167 removeListener: function(callback: any): void {
Blink Reformat4c46d092018-04-07 15:32:37168 const listeners = this._listeners;
169
170 for (let i = 0; i < listeners.length; ++i) {
171 if (listeners[i] === callback) {
172 listeners.splice(i, 1);
173 break;
174 }
175 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34176 if (this._listeners.length === 0) {
Philip Pfaffe939605d2021-06-25 12:20:04177 extensionServer.sendRequest({command: PrivateAPI.Commands.Unsubscribe, type: this._type});
Tim van der Lippe1d6e57a2019-09-30 11:55:34178 }
Blink Reformat4c46d092018-04-07 15:32:37179 },
180
Jan Schefflerd76b4162021-03-29 07:52:16181
182 _fire: function _(_vararg: any): void {
Blink Reformat4c46d092018-04-07 15:32:37183 const listeners = this._listeners.slice();
Tim van der Lippe1d6e57a2019-09-30 11:55:34184 for (let i = 0; i < listeners.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:37185 listeners[i].apply(null, arguments);
Tim van der Lippe1d6e57a2019-09-30 11:55:34186 }
Blink Reformat4c46d092018-04-07 15:32:37187 },
188
Jan Schefflerd76b4162021-03-29 07:52:16189
190 _dispatch: function(request: any): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34191 if (this._customDispatch) {
Blink Reformat4c46d092018-04-07 15:32:37192 this._customDispatch.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34193 } else {
Blink Reformat4c46d092018-04-07 15:32:37194 this._fire.apply(this, request.arguments);
Tim van der Lippe1d6e57a2019-09-30 11:55:34195 }
Jan Schefflerd76b4162021-03-29 07:52:16196 },
Blink Reformat4c46d092018-04-07 15:32:37197 };
198
199 /**
200 * @constructor
201 */
Jan Schefflerd76b4162021-03-29 07:52:16202
Philip Pfaffe939605d2021-06-25 12:20:04203 function InspectorExtensionAPI(this: any): void {
204 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37205 this.inspectedWindow = new InspectedWindow();
Philip Pfaffe939605d2021-06-25 12:20:04206 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37207 this.panels = new Panels();
Philip Pfaffe939605d2021-06-25 12:20:04208 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37209 this.network = new Network();
Philip Pfaffe939605d2021-06-25 12:20:04210 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37211 this.timeline = new Timeline();
Philip Pfaffe939605d2021-06-25 12:20:04212 // @ts-ignore
Philip Pfaffeedad8322020-07-20 10:24:25213 this.languageServices = new LanguageServicesAPI();
Blink Reformat4c46d092018-04-07 15:32:37214 defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
215 }
216
217 /**
218 * @constructor
219 */
Jan Schefflerd76b4162021-03-29 07:52:16220
Philip Pfaffe939605d2021-06-25 12:20:04221 function Network(this: any): void {
222 function dispatchRequestEvent(this: any, message: any): void {
Blink Reformat4c46d092018-04-07 15:32:37223 const request = message.arguments[1];
Philip Pfaffe939605d2021-06-25 12:20:04224 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37225 request.__proto__ = new Request(message.arguments[0]);
226 this._fire(request);
227 }
Philip Pfaffe939605d2021-06-25 12:20:04228 // @ts-ignore
229 this.onRequestFinished = new EventSink(PrivateAPI.Events.NetworkRequestFinished, dispatchRequestEvent);
Blink Reformat4c46d092018-04-07 15:32:37230 defineDeprecatedProperty(this, 'network', 'onFinished', 'onRequestFinished');
Philip Pfaffe939605d2021-06-25 12:20:04231 // @ts-ignore
232 this.onNavigated = new EventSink(PrivateAPI.Events.InspectedURLChanged);
Blink Reformat4c46d092018-04-07 15:32:37233 }
234
235 Network.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16236 getHAR: function(callback: any): void {
237 function callbackWrapper(result: any): void {
Blink Reformat4c46d092018-04-07 15:32:37238 const entries = (result && result.entries) || [];
239 for (let i = 0; i < entries.length; ++i) {
Philip Pfaffe939605d2021-06-25 12:20:04240 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37241 entries[i].__proto__ = new Request(entries[i]._requestId);
242 delete entries[i]._requestId;
243 }
244 callback(result);
245 }
Philip Pfaffe939605d2021-06-25 12:20:04246 extensionServer.sendRequest({command: PrivateAPI.Commands.GetHAR}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37247 },
248
Jan Schefflerd76b4162021-03-29 07:52:16249 addRequestHeaders: function(headers: any): void {
Blink Reformat4c46d092018-04-07 15:32:37250 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04251 {command: PrivateAPI.Commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname});
Jan Schefflerd76b4162021-03-29 07:52:16252 },
Blink Reformat4c46d092018-04-07 15:32:37253 };
254
Philip Pfaffe939605d2021-06-25 12:20:04255 function RequestImpl(this: any, id: any): void {
Blink Reformat4c46d092018-04-07 15:32:37256 this._id = id;
257 }
258
259 RequestImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16260 getContent: function(callback: any): void {
261 function callbackWrapper(response: any): void {
Blink Reformat4c46d092018-04-07 15:32:37262 callback(response.content, response.encoding);
263 }
Philip Pfaffe939605d2021-06-25 12:20:04264 extensionServer.sendRequest(
265 {command: PrivateAPI.Commands.GetRequestContent, id: this._id}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16266 },
Blink Reformat4c46d092018-04-07 15:32:37267 };
268
269 /**
270 * @constructor
271 */
Philip Pfaffe939605d2021-06-25 12:20:04272 function Panels(this: any): void {
273 const panels: {[key: string]: any} = {
Blink Reformat4c46d092018-04-07 15:32:37274 elements: new ElementsPanel(),
275 sources: new SourcesPanel(),
276 };
277
Jan Schefflerd76b4162021-03-29 07:52:16278 function panelGetter(name: any): any {
Blink Reformat4c46d092018-04-07 15:32:37279 return panels[name];
280 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34281 for (const panel in panels) {
Tim van der Lippeffa78622019-09-16 12:07:12282 Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
Tim van der Lippe1d6e57a2019-09-30 11:55:34283 }
Jan Schefflerd76b4162021-03-29 07:52:16284 this.applyStyleSheet = function(styleSheet: any): void {
Philip Pfaffe939605d2021-06-25 12:20:04285 extensionServer.sendRequest({command: PrivateAPI.Commands.ApplyStyleSheet, styleSheet: styleSheet});
Blink Reformat4c46d092018-04-07 15:32:37286 };
287 }
288
289 Panels.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16290 create: function(title: any, icon: any, page: any, callback: any): void {
Blink Reformat4c46d092018-04-07 15:32:37291 const id = 'extension-panel-' + extensionServer.nextObjectId();
Philip Pfaffe939605d2021-06-25 12:20:04292 const request = {command: PrivateAPI.Commands.CreatePanel, id: id, title: title, icon: icon, page: page};
293 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37294 extensionServer.sendRequest(request, callback && callback.bind(this, new ExtensionPanel(id)));
295 },
296
Jan Schefflerd76b4162021-03-29 07:52:16297 setOpenResourceHandler: function(callback: any): void {
Philip Pfaffe939605d2021-06-25 12:20:04298 const hadHandler = extensionServer.hasHandler(PrivateAPI.Events.OpenResource);
Blink Reformat4c46d092018-04-07 15:32:37299
Jan Schefflerd76b4162021-03-29 07:52:16300 function callbackWrapper(message: any): void {
Blink Reformat4c46d092018-04-07 15:32:37301 // Allow the panel to show itself when handling the event.
302 userAction = true;
303 try {
Philip Pfaffe939605d2021-06-25 12:20:04304 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37305 callback.call(null, new Resource(message.resource), message.lineNumber);
306 } finally {
307 userAction = false;
308 }
309 }
310
Tim van der Lippe1d6e57a2019-09-30 11:55:34311 if (!callback) {
Philip Pfaffe939605d2021-06-25 12:20:04312 extensionServer.unregisterHandler(PrivateAPI.Events.OpenResource);
Tim van der Lippe1d6e57a2019-09-30 11:55:34313 } else {
Philip Pfaffe939605d2021-06-25 12:20:04314 extensionServer.registerHandler(PrivateAPI.Events.OpenResource, callbackWrapper);
Tim van der Lippe1d6e57a2019-09-30 11:55:34315 }
Blink Reformat4c46d092018-04-07 15:32:37316
317 // 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:34318 if (hadHandler === !callback) {
Philip Pfaffe939605d2021-06-25 12:20:04319 extensionServer.sendRequest(
320 {command: PrivateAPI.Commands.SetOpenResourceHandler, 'handlerPresent': Boolean(callback)});
Tim van der Lippe1d6e57a2019-09-30 11:55:34321 }
Blink Reformat4c46d092018-04-07 15:32:37322 },
323
Jan Schefflerd76b4162021-03-29 07:52:16324 openResource: function(url: any, lineNumber: any, callback: any): void {
Philip Pfaffe939605d2021-06-25 12:20:04325 extensionServer.sendRequest(
326 {command: PrivateAPI.Commands.OpenResource, 'url': url, 'lineNumber': lineNumber}, callback);
Blink Reformat4c46d092018-04-07 15:32:37327 },
328
Jan Schefflerd76b4162021-03-29 07:52:16329 get SearchAction(): any {
Philip Pfaffe939605d2021-06-25 12:20:04330 return {
331 CancelSearch: PrivateAPI.Panels.SearchAction.CancelSearch,
332 PerformSearch: PrivateAPI.Panels.SearchAction.PerformSearch,
333 NextSearchResult: PrivateAPI.Panels.SearchAction.NextSearchResult,
334 PreviousSearchResult: PrivateAPI.Panels.SearchAction.PreviousSearchResult,
335 };
Jan Schefflerd76b4162021-03-29 07:52:16336 },
Blink Reformat4c46d092018-04-07 15:32:37337 };
338
339 /**
340 * @constructor
341 */
Philip Pfaffe939605d2021-06-25 12:20:04342 function ExtensionViewImpl(this: any, id: any): void {
Blink Reformat4c46d092018-04-07 15:32:37343 this._id = id;
344
Philip Pfaffe939605d2021-06-25 12:20:04345 function dispatchShowEvent(this: any, message: any): void {
Blink Reformat4c46d092018-04-07 15:32:37346 const frameIndex = message.arguments[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:34347 if (typeof frameIndex === 'number') {
Blink Reformat4c46d092018-04-07 15:32:37348 this._fire(window.parent.frames[frameIndex]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34349 } else {
Blink Reformat4c46d092018-04-07 15:32:37350 this._fire();
Tim van der Lippe1d6e57a2019-09-30 11:55:34351 }
Blink Reformat4c46d092018-04-07 15:32:37352 }
353
354 if (id) {
Philip Pfaffe939605d2021-06-25 12:20:04355 // @ts-ignore
356 this.onShown = new EventSink(PrivateAPI.Events.ViewShown + id, dispatchShowEvent);
357 // @ts-ignore
358 this.onHidden = new EventSink(PrivateAPI.Events.ViewHidden + id);
Blink Reformat4c46d092018-04-07 15:32:37359 }
360 }
361
362 /**
363 * @constructor
364 * @extends {ExtensionViewImpl}
Blink Reformat4c46d092018-04-07 15:32:37365 */
Philip Pfaffe939605d2021-06-25 12:20:04366 function PanelWithSidebarImpl(this: any, hostPanelName: string): void {
Blink Reformat4c46d092018-04-07 15:32:37367 ExtensionViewImpl.call(this, null);
368 this._hostPanelName = hostPanelName;
Philip Pfaffe939605d2021-06-25 12:20:04369 // @ts-ignore
370 this.onSelectionChanged = new EventSink(PrivateAPI.Events.PanelObjectSelected + hostPanelName);
Blink Reformat4c46d092018-04-07 15:32:37371 }
372
373 PanelWithSidebarImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16374 createSidebarPane: function(title: any, callback: any): void {
Blink Reformat4c46d092018-04-07 15:32:37375 const id = 'extension-sidebar-' + extensionServer.nextObjectId();
Philip Pfaffe939605d2021-06-25 12:20:04376 const request =
377 {command: PrivateAPI.Commands.CreateSidebarPane, panel: this._hostPanelName, id: id, title: title};
Jan Schefflerd76b4162021-03-29 07:52:16378 function callbackWrapper(): void {
Philip Pfaffe939605d2021-06-25 12:20:04379 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37380 callback(new ExtensionSidebarPane(id));
381 }
382 extensionServer.sendRequest(request, callback && callbackWrapper);
383 },
384
Jan Schefflerd76b4162021-03-29 07:52:16385 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37386 };
387
Philip Pfaffeedad8322020-07-20 10:24:25388 /**
389 * @constructor
390 */
Philip Pfaffe939605d2021-06-25 12:20:04391 function LanguageServicesAPIImpl(this: any): void {
Benedikt Meurer929fc7c2020-11-20 14:21:06392 /** @type {!Map<*, !MessagePort>} */
Philip Pfaffeedad8322020-07-20 10:24:25393 this._plugins = new Map();
394 }
395
396 LanguageServicesAPIImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16397 registerLanguageExtensionPlugin: async function(plugin: any, pluginName: string, supportedScriptTypes: {
398 language: string,
399 symbol_types: string[],
400 }): Promise<void> {
Philip Pfaffeedad8322020-07-20 10:24:25401 if (this._plugins.has(plugin)) {
Benedikt Meurer929fc7c2020-11-20 14:21:06402 throw new Error(`Tried to register plugin '${pluginName}' twice`);
Philip Pfaffeedad8322020-07-20 10:24:25403 }
404 const channel = new MessageChannel();
405 const port = channel.port1;
406 this._plugins.set(plugin, port);
Jan Schefflerd76b4162021-03-29 07:52:16407 port.onmessage = ({data: {requestId, method, parameters}}: MessageEvent<any>): void => {
Benedikt Meurer99b14a92020-12-09 07:44:07408 console.time(`${requestId}: ${method}`);
Philip Pfaffeedad8322020-07-20 10:24:25409 dispatchMethodCall(method, parameters)
410 .then(result => port.postMessage({requestId, result}))
Benedikt Meurer99b14a92020-12-09 07:44:07411 .catch(error => port.postMessage({requestId, error: {message: error.message}}))
412 .finally(() => console.timeEnd(`${requestId}: ${method}`));
Philip Pfaffeedad8322020-07-20 10:24:25413 };
414
Jan Schefflerd76b4162021-03-29 07:52:16415 function dispatchMethodCall(method: string, parameters: any): Promise<any> {
Philip Pfaffeedad8322020-07-20 10:24:25416 switch (method) {
Philip Pfaffe939605d2021-06-25 12:20:04417 case PrivateAPI.LanguageExtensionPluginCommands.AddRawModule:
Philip Pfaffeedad8322020-07-20 10:24:25418 return plugin.addRawModule(parameters.rawModuleId, parameters.symbolsURL, parameters.rawModule);
Philip Pfaffe939605d2021-06-25 12:20:04419 case PrivateAPI.LanguageExtensionPluginCommands.RemoveRawModule:
Philip Pfaffeedad8322020-07-20 10:24:25420 return plugin.removeRawModule(parameters.rawModuleId);
Philip Pfaffe939605d2021-06-25 12:20:04421 case PrivateAPI.LanguageExtensionPluginCommands.SourceLocationToRawLocation:
Philip Pfaffeedad8322020-07-20 10:24:25422 return plugin.sourceLocationToRawLocation(parameters.sourceLocation);
Philip Pfaffe939605d2021-06-25 12:20:04423 case PrivateAPI.LanguageExtensionPluginCommands.RawLocationToSourceLocation:
Philip Pfaffeedad8322020-07-20 10:24:25424 return plugin.rawLocationToSourceLocation(parameters.rawLocation);
Philip Pfaffe939605d2021-06-25 12:20:04425 case PrivateAPI.LanguageExtensionPluginCommands.GetScopeInfo:
Benedikt Meurer723d5432020-10-09 09:02:42426 return plugin.getScopeInfo(parameters.type);
Philip Pfaffe939605d2021-06-25 12:20:04427 case PrivateAPI.LanguageExtensionPluginCommands.ListVariablesInScope:
Philip Pfaffeedad8322020-07-20 10:24:25428 return plugin.listVariablesInScope(parameters.rawLocation);
Philip Pfaffe939605d2021-06-25 12:20:04429 case PrivateAPI.LanguageExtensionPluginCommands.GetTypeInfo:
Philip Pfaffe480fa882020-10-22 09:38:36430 return plugin.getTypeInfo(parameters.expression, parameters.context);
Philip Pfaffe939605d2021-06-25 12:20:04431 case PrivateAPI.LanguageExtensionPluginCommands.GetFormatter:
Philip Pfaffe480fa882020-10-22 09:38:36432 return plugin.getFormatter(parameters.expressionOrField, parameters.context);
Philip Pfaffe939605d2021-06-25 12:20:04433 case PrivateAPI.LanguageExtensionPluginCommands.GetInspectableAddress:
Kim-Anh Tran8fd7d6f2021-01-28 11:07:02434 if ('getInspectableAddress' in plugin) {
435 return plugin.getInspectableAddress(parameters.field);
436 }
437 return Promise.resolve({js: ''});
Philip Pfaffe939605d2021-06-25 12:20:04438 case PrivateAPI.LanguageExtensionPluginCommands.GetFunctionInfo:
Eric Leese5aaa2222020-10-01 11:49:35439 return plugin.getFunctionInfo(parameters.rawLocation);
Philip Pfaffe939605d2021-06-25 12:20:04440 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedFunctionRanges:
Eric Leese553115e2020-10-19 12:09:04441 return plugin.getInlinedFunctionRanges(parameters.rawLocation);
Philip Pfaffe939605d2021-06-25 12:20:04442 case PrivateAPI.LanguageExtensionPluginCommands.GetInlinedCalleesRanges:
Eric Leese553115e2020-10-19 12:09:04443 return plugin.getInlinedCalleesRanges(parameters.rawLocation);
Philip Pfaffe939605d2021-06-25 12:20:04444 case PrivateAPI.LanguageExtensionPluginCommands.GetMappedLines:
Philip Pfaffe7e36e272020-12-09 15:23:04445 if ('getMappedLines' in plugin) {
446 return plugin.getMappedLines(parameters.rawModuleId, parameters.sourceFileURL);
447 }
448 return Promise.resolve(undefined);
Philip Pfaffeedad8322020-07-20 10:24:25449 }
450 throw new Error(`Unknown language plugin method ${method}`);
451 }
452
Philip Pfaffe939605d2021-06-25 12:20:04453 await new Promise<void>(resolve => {
Benedikt Meurer929fc7c2020-11-20 14:21:06454 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04455 {
456 command: PrivateAPI.Commands.RegisterLanguageExtensionPlugin,
457 pluginName,
458 port: channel.port2,
459 supportedScriptTypes,
460 },
Benedikt Meurer929fc7c2020-11-20 14:21:06461 () => resolve(), [channel.port2]);
462 });
463 },
464
Jan Schefflerd76b4162021-03-29 07:52:16465 unregisterLanguageExtensionPlugin: async function(plugin: any): Promise<void> {
Benedikt Meurer929fc7c2020-11-20 14:21:06466 const port = this._plugins.get(plugin);
467 if (!port) {
468 throw new Error('Tried to unregister a plugin that was not previously registered');
469 }
470 this._plugins.delete(plugin);
Philip Pfaffe939605d2021-06-25 12:20:04471 port.postMessage({event: PrivateAPI.LanguageExtensionPluginEvents.UnregisteredLanguageExtensionPlugin});
Benedikt Meurer929fc7c2020-11-20 14:21:06472 port.close();
Jan Schefflerd76b4162021-03-29 07:52:16473 },
Philip Pfaffeedad8322020-07-20 10:24:25474 };
475
Jan Schefflerd76b4162021-03-29 07:52:16476 function declareInterfaceClass(implConstructor: any): (...args: any[]) => void {
Philip Pfaffe939605d2021-06-25 12:20:04477 return function(this: any): void {
Blink Reformat4c46d092018-04-07 15:32:37478 const impl = {__proto__: implConstructor.prototype};
479 implConstructor.apply(impl, arguments);
480 populateInterfaceClass(this, impl);
481 };
482 }
483
Jan Schefflerd76b4162021-03-29 07:52:16484 function defineDeprecatedProperty(object: any, className: any, oldName: any, newName: any): void {
Blink Reformat4c46d092018-04-07 15:32:37485 let warningGiven = false;
Jan Schefflerd76b4162021-03-29 07:52:16486 function getter(): any {
Blink Reformat4c46d092018-04-07 15:32:37487 if (!warningGiven) {
488 console.warn(className + '.' + oldName + ' is deprecated. Use ' + className + '.' + newName + ' instead');
489 warningGiven = true;
490 }
491 return object[newName];
492 }
493 object.__defineGetter__(oldName, getter);
494 }
495
Jan Schefflerd76b4162021-03-29 07:52:16496 function extractCallbackArgument(args: any): any {
Blink Reformat4c46d092018-04-07 15:32:37497 const lastArgument = args[args.length - 1];
498 return typeof lastArgument === 'function' ? lastArgument : undefined;
499 }
500
Philip Pfaffeedad8322020-07-20 10:24:25501 const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
Blink Reformat4c46d092018-04-07 15:32:37502 const Button = declareInterfaceClass(ButtonImpl);
503 const EventSink = declareInterfaceClass(EventSinkImpl);
504 const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
505 const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
Tim van der Lippeffa78622019-09-16 12:07:12506 /**
507 * @constructor
508 * @param {string} hostPanelName
509 */
510 const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
Blink Reformat4c46d092018-04-07 15:32:37511 const Request = declareInterfaceClass(RequestImpl);
512 const Resource = declareInterfaceClass(ResourceImpl);
513 const TraceSession = declareInterfaceClass(TraceSessionImpl);
514
Philip Pfaffe939605d2021-06-25 12:20:04515 // @ts-ignore
Tim van der Lippeffa78622019-09-16 12:07:12516 class ElementsPanel extends PanelWithSidebarClass {
517 constructor() {
518 super('elements');
519 }
Blink Reformat4c46d092018-04-07 15:32:37520 }
521
Philip Pfaffe939605d2021-06-25 12:20:04522 // @ts-ignore
Tim van der Lippeffa78622019-09-16 12:07:12523 class SourcesPanel extends PanelWithSidebarClass {
524 constructor() {
525 super('sources');
526 }
Blink Reformat4c46d092018-04-07 15:32:37527 }
528
Blink Reformat4c46d092018-04-07 15:32:37529 /**
530 * @constructor
531 * @extends {ExtensionViewImpl}
532 */
Philip Pfaffe939605d2021-06-25 12:20:04533 function ExtensionPanelImpl(this: any, id: any): void {
Blink Reformat4c46d092018-04-07 15:32:37534 ExtensionViewImpl.call(this, id);
Philip Pfaffe939605d2021-06-25 12:20:04535 // @ts-ignore
536 this.onSearch = new EventSink(PrivateAPI.Events.PanelSearch + id);
Blink Reformat4c46d092018-04-07 15:32:37537 }
538
539 ExtensionPanelImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16540 createStatusBarButton: function(iconPath: any, tooltipText: any, disabled: any): Object {
Blink Reformat4c46d092018-04-07 15:32:37541 const id = 'button-' + extensionServer.nextObjectId();
542 const request = {
Philip Pfaffe939605d2021-06-25 12:20:04543 command: PrivateAPI.Commands.CreateToolbarButton,
Blink Reformat4c46d092018-04-07 15:32:37544 panel: this._id,
545 id: id,
546 icon: iconPath,
547 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16548 disabled: Boolean(disabled),
Blink Reformat4c46d092018-04-07 15:32:37549 };
550 extensionServer.sendRequest(request);
Philip Pfaffe939605d2021-06-25 12:20:04551 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37552 return new Button(id);
553 },
554
Jan Schefflerd76b4162021-03-29 07:52:16555 show: function(): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34556 if (!userAction) {
Blink Reformat4c46d092018-04-07 15:32:37557 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34558 }
Blink Reformat4c46d092018-04-07 15:32:37559
Philip Pfaffe939605d2021-06-25 12:20:04560 const request = {command: PrivateAPI.Commands.ShowPanel, id: this._id};
Blink Reformat4c46d092018-04-07 15:32:37561 extensionServer.sendRequest(request);
562 },
563
Jan Schefflerd76b4162021-03-29 07:52:16564 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37565 };
566
567 /**
568 * @constructor
569 * @extends {ExtensionViewImpl}
570 */
Philip Pfaffe939605d2021-06-25 12:20:04571 function ExtensionSidebarPaneImpl(this: any, id: any): void {
Blink Reformat4c46d092018-04-07 15:32:37572 ExtensionViewImpl.call(this, id);
573 }
574
575 ExtensionSidebarPaneImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16576 setHeight: function(height: any): void {
Philip Pfaffe939605d2021-06-25 12:20:04577 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarHeight, id: this._id, height: height});
Blink Reformat4c46d092018-04-07 15:32:37578 },
579
Jan Schefflerd76b4162021-03-29 07:52:16580 setExpression: function(expression: any, rootTitle: any, evaluateOptions: any): void {
Blink Reformat4c46d092018-04-07 15:32:37581 const request = {
Philip Pfaffe939605d2021-06-25 12:20:04582 command: PrivateAPI.Commands.SetSidebarContent,
Blink Reformat4c46d092018-04-07 15:32:37583 id: this._id,
584 expression: expression,
585 rootTitle: rootTitle,
586 evaluateOnPage: true,
Philip Pfaffe939605d2021-06-25 12:20:04587 evaluateOptions: undefined,
Blink Reformat4c46d092018-04-07 15:32:37588 };
Tim van der Lippe1d6e57a2019-09-30 11:55:34589 if (typeof evaluateOptions === 'object') {
Blink Reformat4c46d092018-04-07 15:32:37590 request.evaluateOptions = evaluateOptions;
Tim van der Lippe1d6e57a2019-09-30 11:55:34591 }
Blink Reformat4c46d092018-04-07 15:32:37592 extensionServer.sendRequest(request, extractCallbackArgument(arguments));
593 },
594
Jan Schefflerd76b4162021-03-29 07:52:16595 setObject: function(jsonObject: any, rootTitle: any, callback: any): void {
Blink Reformat4c46d092018-04-07 15:32:37596 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04597 {command: PrivateAPI.Commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle},
598 callback);
Blink Reformat4c46d092018-04-07 15:32:37599 },
600
Jan Schefflerd76b4162021-03-29 07:52:16601 setPage: function(page: any): void {
Philip Pfaffe939605d2021-06-25 12:20:04602 extensionServer.sendRequest({command: PrivateAPI.Commands.SetSidebarPage, id: this._id, page: page});
Blink Reformat4c46d092018-04-07 15:32:37603 },
604
Jan Schefflerd76b4162021-03-29 07:52:16605 __proto__: ExtensionViewImpl.prototype,
Blink Reformat4c46d092018-04-07 15:32:37606 };
607
608 /**
609 * @constructor
610 */
Philip Pfaffe939605d2021-06-25 12:20:04611 function ButtonImpl(this: any, id: any): void {
Blink Reformat4c46d092018-04-07 15:32:37612 this._id = id;
Philip Pfaffe939605d2021-06-25 12:20:04613 // @ts-ignore
614 this.onClicked = new EventSink(PrivateAPI.Events.ButtonClicked + id);
Blink Reformat4c46d092018-04-07 15:32:37615 }
616
617 ButtonImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16618 update: function(iconPath: any, tooltipText: any, disabled: any): void {
Tim van der Lipped7cfd142021-01-07 12:17:24619 const request = {
Philip Pfaffe939605d2021-06-25 12:20:04620 command: PrivateAPI.Commands.UpdateButton,
Tim van der Lipped7cfd142021-01-07 12:17:24621 id: this._id,
622 icon: iconPath,
623 tooltip: tooltipText,
Jan Schefflerd76b4162021-03-29 07:52:16624 disabled: Boolean(disabled),
Tim van der Lipped7cfd142021-01-07 12:17:24625 };
Blink Reformat4c46d092018-04-07 15:32:37626 extensionServer.sendRequest(request);
Jan Schefflerd76b4162021-03-29 07:52:16627 },
Blink Reformat4c46d092018-04-07 15:32:37628 };
629
630 /**
631 * @constructor
632 */
Jan Schefflerd76b4162021-03-29 07:52:16633 function Timeline(): void {
Blink Reformat4c46d092018-04-07 15:32:37634 }
635
636 Timeline.prototype = {
Philip Pfaffe939605d2021-06-25 12:20:04637 // @ts-ignore
Jan Schefflerd76b4162021-03-29 07:52:16638 addTraceProvider: function(categoryName: string, categoryTooltip: string): TraceProvider {
Blink Reformat4c46d092018-04-07 15:32:37639 const id = 'extension-trace-provider-' + extensionServer.nextObjectId();
Philip Pfaffe939605d2021-06-25 12:20:04640 extensionServer.sendRequest({
641 command: PrivateAPI.Commands.AddTraceProvider,
642 id: id,
643 categoryName: categoryName,
644 categoryTooltip: categoryTooltip,
645 });
646 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37647 return new TraceProvider(id);
Jan Schefflerd76b4162021-03-29 07:52:16648 },
Blink Reformat4c46d092018-04-07 15:32:37649 };
650
651 /**
652 * @constructor
Blink Reformat4c46d092018-04-07 15:32:37653 */
Philip Pfaffe939605d2021-06-25 12:20:04654 function TraceSessionImpl(this: any, id: string): void {
Blink Reformat4c46d092018-04-07 15:32:37655 this._id = id;
656 }
657
658 TraceSessionImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16659 complete: function(url?: string, timeOffset?: number): void {
Philip Pfaffe939605d2021-06-25 12:20:04660 const request = {
661 command: PrivateAPI.Commands.CompleteTraceSession,
662 id: this._id,
663 url: url || '',
664 timeOffset: timeOffset || 0,
665 };
Blink Reformat4c46d092018-04-07 15:32:37666 extensionServer.sendRequest(request);
Jan Schefflerd76b4162021-03-29 07:52:16667 },
Blink Reformat4c46d092018-04-07 15:32:37668 };
669
670 /**
671 * @constructor
Blink Reformat4c46d092018-04-07 15:32:37672 */
Jan Schefflerd76b4162021-03-29 07:52:16673 function TraceProvider(id: string): void {
Philip Pfaffe939605d2021-06-25 12:20:04674 function dispatchRecordingStarted(this: any, message: any): void {
Blink Reformat4c46d092018-04-07 15:32:37675 const sessionId = message.arguments[0];
Philip Pfaffe939605d2021-06-25 12:20:04676 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37677 this._fire(new TraceSession(sessionId));
678 }
679
Philip Pfaffe939605d2021-06-25 12:20:04680 // @ts-ignore
681 this.onRecordingStarted = new EventSink(PrivateAPI.Events.RecordingStarted + id, dispatchRecordingStarted);
682 // @ts-ignore
683 this.onRecordingStopped = new EventSink(PrivateAPI.Events.RecordingStopped + id);
Blink Reformat4c46d092018-04-07 15:32:37684 }
685
686 /**
687 * @constructor
688 */
Philip Pfaffe939605d2021-06-25 12:20:04689 function InspectedWindow(this: any): void {
690 function dispatchResourceEvent(this: any, message: any): void {
691 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37692 this._fire(new Resource(message.arguments[0]));
693 }
694
Philip Pfaffe939605d2021-06-25 12:20:04695 function dispatchResourceContentEvent(this: any, message: any): void {
696 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37697 this._fire(new Resource(message.arguments[0]), message.arguments[1]);
698 }
699
Philip Pfaffe939605d2021-06-25 12:20:04700 // @ts-ignore
701 this.onResourceAdded = new EventSink(PrivateAPI.Events.ResourceAdded, dispatchResourceEvent);
702 this.onResourceContentCommitted =
703 // @ts-ignore
704 new EventSink(PrivateAPI.Events.ResourceContentCommitted, dispatchResourceContentEvent);
Blink Reformat4c46d092018-04-07 15:32:37705 }
706
707 InspectedWindow.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16708 reload: function(optionsOrUserAgent: any): void {
709 let options: {
710 userAgent: string,
711 }|null = null;
Blink Reformat4c46d092018-04-07 15:32:37712 if (typeof optionsOrUserAgent === 'object') {
713 options = optionsOrUserAgent;
714 } else if (typeof optionsOrUserAgent === 'string') {
715 options = {userAgent: optionsOrUserAgent};
716 console.warn(
717 'Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. ' +
718 'Use inspectedWindow.reload({ userAgent: value}) instead.');
719 }
Philip Pfaffe939605d2021-06-25 12:20:04720 extensionServer.sendRequest({command: PrivateAPI.Commands.Reload, options: options});
Blink Reformat4c46d092018-04-07 15:32:37721 },
722
Jan Schefflerd76b4162021-03-29 07:52:16723 eval: function(expression: any, evaluateOptions: any): Object |
724 null {
725 const callback = extractCallbackArgument(arguments);
726 function callbackWrapper(result: any): void {
727 if (result.isError || result.isException) {
728 callback(undefined, result);
729 } else {
730 callback(result.value);
731 }
732 }
Philip Pfaffe939605d2021-06-25 12:20:04733 const request = {
734 command: PrivateAPI.Commands.EvaluateOnInspectedPage,
735 expression: expression,
736 evaluateOptions: undefined,
737 };
Jan Schefflerd76b4162021-03-29 07:52:16738 if (typeof evaluateOptions === 'object') {
739 request.evaluateOptions = evaluateOptions;
740 }
741 extensionServer.sendRequest(request, callback && callbackWrapper);
742 return null;
743 },
Blink Reformat4c46d092018-04-07 15:32:37744
Jan Schefflerd76b4162021-03-29 07:52:16745 getResources: function(callback: any): void {
746 function wrapResource(resourceData: any): any {
Philip Pfaffe939605d2021-06-25 12:20:04747 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37748 return new Resource(resourceData);
749 }
Jan Schefflerd76b4162021-03-29 07:52:16750 function callbackWrapper(resources: any): void {
Blink Reformat4c46d092018-04-07 15:32:37751 callback(resources.map(wrapResource));
752 }
Philip Pfaffe939605d2021-06-25 12:20:04753 extensionServer.sendRequest({command: PrivateAPI.Commands.GetPageResources}, callback && callbackWrapper);
Jan Schefflerd76b4162021-03-29 07:52:16754 },
Blink Reformat4c46d092018-04-07 15:32:37755 };
756
757 /**
758 * @constructor
759 */
Philip Pfaffe939605d2021-06-25 12:20:04760 function ResourceImpl(this: any, resourceData: any): void {
Blink Reformat4c46d092018-04-07 15:32:37761 this._url = resourceData.url;
762 this._type = resourceData.type;
763 }
764
765 ResourceImpl.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16766 get url(): string {
Blink Reformat4c46d092018-04-07 15:32:37767 return this._url;
768 },
769
Jan Schefflerd76b4162021-03-29 07:52:16770 get type(): string {
Blink Reformat4c46d092018-04-07 15:32:37771 return this._type;
772 },
773
Jan Schefflerd76b4162021-03-29 07:52:16774 getContent: function(callback: any): void {
775 function callbackWrapper(response: any): void {
Blink Reformat4c46d092018-04-07 15:32:37776 callback(response.content, response.encoding);
777 }
778
Philip Pfaffe939605d2021-06-25 12:20:04779 extensionServer.sendRequest(
780 {command: PrivateAPI.Commands.GetResourceContent, url: this._url}, callback && callbackWrapper);
Blink Reformat4c46d092018-04-07 15:32:37781 },
782
Jan Schefflerd76b4162021-03-29 07:52:16783 setContent: function(content: any, commit: any, callback: any): void {
Blink Reformat4c46d092018-04-07 15:32:37784 extensionServer.sendRequest(
Philip Pfaffe939605d2021-06-25 12:20:04785 {command: PrivateAPI.Commands.SetResourceContent, url: this._url, content: content, commit: commit},
786 callback);
Jan Schefflerd76b4162021-03-29 07:52:16787 },
Blink Reformat4c46d092018-04-07 15:32:37788 };
789
Jan Schefflerd76b4162021-03-29 07:52:16790 function getTabId(): string {
Blink Reformat4c46d092018-04-07 15:32:37791 return inspectedTabId;
792 }
793
Jan Schefflerd76b4162021-03-29 07:52:16794 let keyboardEventRequestQueue: any[] = [];
795 let forwardTimer: number|null = null;
796 function forwardKeyboardEvent(event: any): void {
Jan Schefflere7d7bb12019-10-24 09:18:52797 // Check if the event should be forwarded.
798 // This is a workaround for crbug.com/923338.
799 const focused = document.activeElement;
800 if (focused) {
801 const isInput = focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
802 if (isInput && !(event.ctrlKey || event.altKey || event.metaKey)) {
803 return;
804 }
805 }
806
Joel Einbinder67f28fb2018-08-02 00:33:47807 let modifiers = 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34808 if (event.shiftKey) {
Joel Einbinder67f28fb2018-08-02 00:33:47809 modifiers |= 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34810 }
811 if (event.ctrlKey) {
Joel Einbinder67f28fb2018-08-02 00:33:47812 modifiers |= 2;
Tim van der Lippe1d6e57a2019-09-30 11:55:34813 }
814 if (event.altKey) {
Joel Einbinder67f28fb2018-08-02 00:33:47815 modifiers |= 4;
Tim van der Lippe1d6e57a2019-09-30 11:55:34816 }
817 if (event.metaKey) {
Joel Einbinder67f28fb2018-08-02 00:33:47818 modifiers |= 8;
Tim van der Lippe1d6e57a2019-09-30 11:55:34819 }
Joel Einbinder67f28fb2018-08-02 00:33:47820 const num = (event.keyCode & 255) | (modifiers << 8);
Blink Reformat4c46d092018-04-07 15:32:37821 // We only care about global hotkeys, not about random text
Tim van der Lippe1d6e57a2019-09-30 11:55:34822 if (!keysToForwardSet.has(num)) {
Blink Reformat4c46d092018-04-07 15:32:37823 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34824 }
Joel Einbinder67f28fb2018-08-02 00:33:47825 event.preventDefault();
Blink Reformat4c46d092018-04-07 15:32:37826 const requestPayload = {
827 eventType: event.type,
828 ctrlKey: event.ctrlKey,
829 altKey: event.altKey,
830 metaKey: event.metaKey,
Joel Einbinder67f28fb2018-08-02 00:33:47831 shiftKey: event.shiftKey,
Blink Reformat4c46d092018-04-07 15:32:37832 keyIdentifier: event.keyIdentifier,
833 key: event.key,
834 code: event.code,
835 location: event.location,
Jan Schefflerd76b4162021-03-29 07:52:16836 keyCode: event.keyCode,
Blink Reformat4c46d092018-04-07 15:32:37837 };
838 keyboardEventRequestQueue.push(requestPayload);
Tim van der Lippe1d6e57a2019-09-30 11:55:34839 if (!forwardTimer) {
Blink Reformat4c46d092018-04-07 15:32:37840 forwardTimer = setTimeout(forwardEventQueue, 0);
Tim van der Lippe1d6e57a2019-09-30 11:55:34841 }
Blink Reformat4c46d092018-04-07 15:32:37842 }
843
Jan Schefflerd76b4162021-03-29 07:52:16844 function forwardEventQueue(): void {
Blink Reformat4c46d092018-04-07 15:32:37845 forwardTimer = null;
Philip Pfaffe939605d2021-06-25 12:20:04846 const request = {command: PrivateAPI.Commands.ForwardKeyboardEvent, entries: keyboardEventRequestQueue};
Blink Reformat4c46d092018-04-07 15:32:37847 extensionServer.sendRequest(request);
848 keyboardEventRequestQueue = [];
849 }
850
851 document.addEventListener('keydown', forwardKeyboardEvent, false);
Blink Reformat4c46d092018-04-07 15:32:37852
853 /**
854 * @constructor
855 */
Philip Pfaffe939605d2021-06-25 12:20:04856 function ExtensionServerClient(this: any): void {
Blink Reformat4c46d092018-04-07 15:32:37857 this._callbacks = {};
858 this._handlers = {};
859 this._lastRequestId = 0;
860 this._lastObjectId = 0;
861
862 this.registerHandler('callback', this._onCallback.bind(this));
863
864 const channel = new MessageChannel();
865 this._port = channel.port1;
866 this._port.addEventListener('message', this._onMessage.bind(this), false);
867 this._port.start();
868
869 window.parent.postMessage('registerExtension', '*', [channel.port2]);
870 }
871
872 ExtensionServerClient.prototype = {
Jan Schefflerd76b4162021-03-29 07:52:16873 sendRequest: function(message: Object, callback?: (() => any), transfers?: any[]): void {
Tim van der Lippe1d6e57a2019-09-30 11:55:34874 if (typeof callback === 'function') {
Philip Pfaffe939605d2021-06-25 12:20:04875 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37876 message.requestId = this._registerCallback(callback);
Tim van der Lippe1d6e57a2019-09-30 11:55:34877 }
Philip Pfaffeedad8322020-07-20 10:24:25878 this._port.postMessage(message, transfers);
Blink Reformat4c46d092018-04-07 15:32:37879 },
880
Jan Schefflerd76b4162021-03-29 07:52:16881 hasHandler: function(command: any): boolean {
Tim van der Lipped7cfd142021-01-07 12:17:24882 return Boolean(this._handlers[command]);
Blink Reformat4c46d092018-04-07 15:32:37883 },
884
Jan Schefflerd76b4162021-03-29 07:52:16885 registerHandler: function(command: any, handler: any): void {
Blink Reformat4c46d092018-04-07 15:32:37886 this._handlers[command] = handler;
887 },
888
Jan Schefflerd76b4162021-03-29 07:52:16889 unregisterHandler: function(command: any): void {
Blink Reformat4c46d092018-04-07 15:32:37890 delete this._handlers[command];
891 },
892
Jan Schefflerd76b4162021-03-29 07:52:16893 nextObjectId: function(): string {
Blink Reformat4c46d092018-04-07 15:32:37894 return injectedScriptId.toString() + '_' + ++this._lastObjectId;
895 },
896
Jan Schefflerd76b4162021-03-29 07:52:16897 _registerCallback: function(callback: any): number {
Blink Reformat4c46d092018-04-07 15:32:37898 const id = ++this._lastRequestId;
899 this._callbacks[id] = callback;
900 return id;
901 },
902
Jan Schefflerd76b4162021-03-29 07:52:16903 _onCallback: function(request: any): void {
Blink Reformat4c46d092018-04-07 15:32:37904 if (request.requestId in this._callbacks) {
905 const callback = this._callbacks[request.requestId];
906 delete this._callbacks[request.requestId];
907 callback(request.result);
908 }
909 },
910
Jan Schefflerd76b4162021-03-29 07:52:16911 _onMessage: function(event: any): void {
Blink Reformat4c46d092018-04-07 15:32:37912 const request = event.data;
913 const handler = this._handlers[request.command];
Tim van der Lippe1d6e57a2019-09-30 11:55:34914 if (handler) {
Blink Reformat4c46d092018-04-07 15:32:37915 handler.call(this, request);
Tim van der Lippe1d6e57a2019-09-30 11:55:34916 }
Jan Schefflerd76b4162021-03-29 07:52:16917 },
Blink Reformat4c46d092018-04-07 15:32:37918 };
919
Jan Schefflerd76b4162021-03-29 07:52:16920 function populateInterfaceClass(interfaze: any, implementation: any): void {
Blink Reformat4c46d092018-04-07 15:32:37921 for (const member in implementation) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34922 if (member.charAt(0) === '_') {
Blink Reformat4c46d092018-04-07 15:32:37923 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34924 }
Jan Schefflerd76b4162021-03-29 07:52:16925 let descriptor: (PropertyDescriptor|undefined)|null = null;
Blink Reformat4c46d092018-04-07 15:32:37926 // Traverse prototype chain until we find the owner.
Tim van der Lippe1d6e57a2019-09-30 11:55:34927 for (let owner = implementation; owner && !descriptor; owner = owner.__proto__) {
Blink Reformat4c46d092018-04-07 15:32:37928 descriptor = Object.getOwnPropertyDescriptor(owner, member);
Tim van der Lippe1d6e57a2019-09-30 11:55:34929 }
930 if (!descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37931 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34932 }
933 if (typeof descriptor.value === 'function') {
Blink Reformat4c46d092018-04-07 15:32:37934 interfaze[member] = descriptor.value.bind(implementation);
Tim van der Lippe1d6e57a2019-09-30 11:55:34935 } else if (typeof descriptor.get === 'function') {
Blink Reformat4c46d092018-04-07 15:32:37936 interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
Tim van der Lippe1d6e57a2019-09-30 11:55:34937 } else {
Blink Reformat4c46d092018-04-07 15:32:37938 Object.defineProperty(interfaze, member, descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:34939 }
Blink Reformat4c46d092018-04-07 15:32:37940 }
941 }
942
Philip Pfaffe939605d2021-06-25 12:20:04943 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37944 const extensionServer = new ExtensionServerClient();
Philip Pfaffe939605d2021-06-25 12:20:04945 // @ts-ignore
Blink Reformat4c46d092018-04-07 15:32:37946 const coreAPI = new InspectorExtensionAPI();
947
948 Object.defineProperty(chrome, 'devtools', {value: {}, enumerable: true});
949
950 // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
951 chrome.devtools.inspectedWindow = {};
Tim van der Lippeffa78622019-09-16 12:07:12952 Object.defineProperty(chrome.devtools.inspectedWindow, 'tabId', {get: getTabId});
Blink Reformat4c46d092018-04-07 15:32:37953 chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
954 chrome.devtools.network = coreAPI.network;
955 chrome.devtools.panels = coreAPI.panels;
956 chrome.devtools.panels.themeName = themeName;
Philip Pfaffe939605d2021-06-25 12:20:04957 chrome.devtools.languageServices = coreAPI.languageServices;
Blink Reformat4c46d092018-04-07 15:32:37958
959 // default to expose experimental APIs for now.
960 if (extensionInfo.exposeExperimentalAPIs !== false) {
961 chrome.experimental = chrome.experimental || {};
962 chrome.experimental.devtools = chrome.experimental.devtools || {};
963
964 const properties = Object.getOwnPropertyNames(coreAPI);
965 for (let i = 0; i < properties.length; ++i) {
966 const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34967 if (descriptor) {
Blink Reformat4c46d092018-04-07 15:32:37968 Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
Tim van der Lippe1d6e57a2019-09-30 11:55:34969 }
Blink Reformat4c46d092018-04-07 15:32:37970 }
971 chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
972 }
973
Tim van der Lippe1d6e57a2019-09-30 11:55:34974 if (extensionInfo.exposeWebInspectorNamespace) {
Blink Reformat4c46d092018-04-07 15:32:37975 window.webInspector = coreAPI;
Tim van der Lippe1d6e57a2019-09-30 11:55:34976 }
Blink Reformat4c46d092018-04-07 15:32:37977 testHook(extensionServer, coreAPI);
Tim van der Lippe226fc222019-10-10 12:17:12978};
Blink Reformat4c46d092018-04-07 15:32:37979
Jan Schefflerd76b4162021-03-29 07:52:16980self.buildExtensionAPIInjectedScript = function(
981 extensionInfo: {
982 startPage: string,
983 name: string,
984 exposeExperimentalAPIs: boolean,
985 },
986 inspectedTabId: string, themeName: string, keysToForward: number[],
987 testHook: ((arg0: Object, arg1: Object) => any)|undefined): string {
Philip Pfaffeedad8322020-07-20 10:24:25988 const argumentsJSON =
989 [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
Tim van der Lippe1d6e57a2019-09-30 11:55:34990 if (!testHook) {
Jan Schefflerd76b4162021-03-29 07:52:16991 testHook = (): void => {};
Tim van der Lippe1d6e57a2019-09-30 11:55:34992 }
Philip Pfaffe939605d2021-06-25 12:20:04993 return '(function(injectedScriptId){ ' +
Tim van der Lippe226fc222019-10-10 12:17:12994 '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
Blink Reformat4c46d092018-04-07 15:32:37995 '})';
Tim van der Lippe29fab472019-08-15 14:46:48996};