blob: 7a1c04cec0b9d90cc3609f07e096081e229d6dd8 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4/* eslint-disable indent */
5(function(window) {
6
Nikolay Vitkov42be2662023-01-12 15:32:357// DevToolsAPI ----------------------------------------------------------------
Blink Reformat4c46d092018-04-07 15:32:378
Philip Pfaffe2d19bcb2023-06-23 10:55:229/**
10 * @typedef {{runtimeAllowedHosts: !Array<string>, runtimeBlockedHosts: !Array<string>}} ExtensionHostsPolicy
11 */
12/**
13 * @typedef {{startPage: string, name: string, exposeExperimentalAPIs: boolean, hostsPolicy?: ExtensionHostsPolicy}} ExtensionDescriptor
14 */
Nikolay Vitkov42be2662023-01-12 15:32:3515const DevToolsAPIImpl = class {
16 constructor() {
Blink Reformat4c46d092018-04-07 15:32:3717 /**
Nikolay Vitkov42be2662023-01-12 15:32:3518 * @type {number}
Blink Reformat4c46d092018-04-07 15:32:3719 */
Nikolay Vitkov42be2662023-01-12 15:32:3520 this._lastCallId = 0;
Blink Reformat4c46d092018-04-07 15:32:3721
22 /**
Nikolay Vitkov42be2662023-01-12 15:32:3523 * @type {!Object.<number, function(?Object)>}
Blink Reformat4c46d092018-04-07 15:32:3724 */
Nikolay Vitkov42be2662023-01-12 15:32:3525 this._callbacks = {};
Blink Reformat4c46d092018-04-07 15:32:3726
27 /**
Nikolay Vitkov42be2662023-01-12 15:32:3528 * @type {!Array.<!ExtensionDescriptor>}
Blink Reformat4c46d092018-04-07 15:32:3729 */
Nikolay Vitkov42be2662023-01-12 15:32:3530 this._pendingExtensionDescriptors = [];
Blink Reformat4c46d092018-04-07 15:32:3731
32 /**
Philip Pfaffe2d19bcb2023-06-23 10:55:2233 * @type {?function(!ExtensionDescriptor): void}
Blink Reformat4c46d092018-04-07 15:32:3734 */
Nikolay Vitkov42be2662023-01-12 15:32:3535 this._addExtensionCallback = null;
Blink Reformat4c46d092018-04-07 15:32:3736
37 /**
Nikolay Vitkov42be2662023-01-12 15:32:3538 * @type {!Array<string>}
Danil Somsikov1f747672022-02-02 10:44:4439 */
Nikolay Vitkov42be2662023-01-12 15:32:3540 this._originsForbiddenForExtensions = [];
Danil Somsikov1f747672022-02-02 10:44:4441
42 /**
Nikolay Vitkov42be2662023-01-12 15:32:3543 * @type {!Promise<string>}
Danil Somsikov1f747672022-02-02 10:44:4444 */
Nikolay Vitkov42be2662023-01-12 15:32:3545 this._initialTargetIdPromise = new Promise(resolve => {
46 this._setInitialTargetId = resolve;
47 });
Blink Reformat4c46d092018-04-07 15:32:3748 }
49
Nikolay Vitkov42be2662023-01-12 15:32:3550 /**
51 * @param {number} id
52 * @param {?Object} arg
53 */
54 embedderMessageAck(id, arg) {
55 const callback = this._callbacks[id];
56 delete this._callbacks[id];
57 if (callback) {
58 callback(arg);
59 }
60 }
Blink Reformat4c46d092018-04-07 15:32:3761
62 /**
Nikolay Vitkov42be2662023-01-12 15:32:3563 * @param {string} method
64 * @param {!Array.<*>} args
65 * @param {?function(?Object)} callback
66 */
67 sendMessageToEmbedder(method, args, callback) {
68 const callId = ++this._lastCallId;
69 if (callback) {
70 this._callbacks[callId] = callback;
71 }
72 const message = {'id': callId, 'method': method};
73 if (args.length) {
74 message.params = args;
75 }
76 DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
77 }
78
79 /**
80 * @param {string} method
81 * @param {!Array<*>} args
82 */
83 _dispatchOnInspectorFrontendAPI(method, args) {
84 const inspectorFrontendAPI = /** @type {!Object<string, function()>} */ (window['InspectorFrontendAPI']);
85 inspectorFrontendAPI[method].apply(inspectorFrontendAPI, args);
86 }
87
88 // API methods below this line --------------------------------------------
89
90 /**
91 * @param {!Array.<!ExtensionDescriptor>} extensions
92 */
93 addExtensions(extensions) {
94 // Support for legacy front-ends (<M41).
95 if (window['WebInspector'] && window['WebInspector']['addExtensions']) {
96 window['WebInspector']['addExtensions'](extensions);
97 } else {
98 // The addExtensions command is sent as the onload event happens for
99 // DevTools front-end. We should buffer this command until the frontend
100 // is ready for it.
101 if (this._addExtensionCallback) {
102 extensions.forEach(this._addExtensionCallback);
103 } else {
104 this._pendingExtensionDescriptors.push(...extensions);
105 }
106 }
107 }
108
109 /**
110 * @param {!Array<string>} forbiddenOrigins
111 */
112 setOriginsForbiddenForExtensions(forbiddenOrigins) {
113 this._originsForbiddenForExtensions = forbiddenOrigins;
114 }
115
116 /**
117 * @return {!Array<string>}
118 */
119 getOriginsForbiddenForExtensions() {
120 return this._originsForbiddenForExtensions;
121 }
122
123 /**
124 * @param {string} url
125 */
126 appendedToURL(url) {
127 this._dispatchOnInspectorFrontendAPI('appendedToURL', [url]);
128 }
129
130 /**
131 * @param {string} url
132 */
133 canceledSaveURL(url) {
134 this._dispatchOnInspectorFrontendAPI('canceledSaveURL', [url]);
135 }
136
137 contextMenuCleared() {
138 this._dispatchOnInspectorFrontendAPI('contextMenuCleared', []);
139 }
140
141 /**
142 * @param {string} id
143 */
144 contextMenuItemSelected(id) {
145 this._dispatchOnInspectorFrontendAPI('contextMenuItemSelected', [id]);
146 }
147
148 /**
149 * @param {number} count
150 */
151 deviceCountUpdated(count) {
152 this._dispatchOnInspectorFrontendAPI('deviceCountUpdated', [count]);
153 }
154
155 /**
156 * @param {!Adb.Config} config
157 */
158 devicesDiscoveryConfigChanged(config) {
159 this._dispatchOnInspectorFrontendAPI('devicesDiscoveryConfigChanged', [config]);
160 }
161
162 /**
163 * @param {!Adb.PortForwardingStatus} status
164 */
165 devicesPortForwardingStatusChanged(status) {
166 this._dispatchOnInspectorFrontendAPI('devicesPortForwardingStatusChanged', [status]);
167 }
168
169 /**
170 * @param {!Array.<!Adb.Device>} devices
171 */
172 devicesUpdated(devices) {
173 this._dispatchOnInspectorFrontendAPI('devicesUpdated', [devices]);
174 }
175
176 /**
177 * @param {string} message
178 */
179 dispatchMessage(message) {
180 this._dispatchOnInspectorFrontendAPI('dispatchMessage', [message]);
181 }
182
183 /**
184 * @param {string} messageChunk
185 * @param {number} messageSize
186 */
187 dispatchMessageChunk(messageChunk, messageSize) {
188 this._dispatchOnInspectorFrontendAPI('dispatchMessageChunk', [messageChunk, messageSize]);
189 }
190
191 enterInspectElementMode() {
192 this._dispatchOnInspectorFrontendAPI('enterInspectElementMode', []);
193 }
194
195 /**
196 * @param {!{r: number, g: number, b: number, a: number}} color
197 */
198 eyeDropperPickedColor(color) {
199 this._dispatchOnInspectorFrontendAPI('eyeDropperPickedColor', [color]);
200 }
201
202 /**
203 * @param {!Array.<!{fileSystemName: string, rootURL: string, fileSystemPath: string}>} fileSystems
204 */
205 fileSystemsLoaded(fileSystems) {
206 this._dispatchOnInspectorFrontendAPI('fileSystemsLoaded', [fileSystems]);
207 }
208
209 /**
210 * @param {string} fileSystemPath
211 */
212 fileSystemRemoved(fileSystemPath) {
213 this._dispatchOnInspectorFrontendAPI('fileSystemRemoved', [fileSystemPath]);
214 }
215
216 /**
217 * @param {?string} error
218 * @param {?{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} fileSystem
219 */
220 fileSystemAdded(error, fileSystem) {
221 this._dispatchOnInspectorFrontendAPI('fileSystemAdded', [error, fileSystem]);
222 }
223
224 /**
225 * @param {!Array<string>} changedPaths
226 * @param {!Array<string>} addedPaths
227 * @param {!Array<string>} removedPaths
228 */
229 fileSystemFilesChangedAddedRemoved(changedPaths, addedPaths, removedPaths) {
230 // Support for legacy front-ends (<M58)
231 if (window['InspectorFrontendAPI'] && window['InspectorFrontendAPI']['fileSystemFilesChanged']) {
232 this._dispatchOnInspectorFrontendAPI(
233 'fileSystemFilesChanged', [changedPaths.concat(addedPaths).concat(removedPaths)]);
234 } else {
235 this._dispatchOnInspectorFrontendAPI(
236 'fileSystemFilesChangedAddedRemoved', [changedPaths, addedPaths, removedPaths]);
237 }
238 }
239
240 /**
241 * @param {number} requestId
242 * @param {string} fileSystemPath
243 * @param {number} totalWork
244 */
245 indexingTotalWorkCalculated(requestId, fileSystemPath, totalWork) {
246 this._dispatchOnInspectorFrontendAPI('indexingTotalWorkCalculated', [requestId, fileSystemPath, totalWork]);
247 }
248
249 /**
250 * @param {number} requestId
251 * @param {string} fileSystemPath
252 * @param {number} worked
253 */
254 indexingWorked(requestId, fileSystemPath, worked) {
255 this._dispatchOnInspectorFrontendAPI('indexingWorked', [requestId, fileSystemPath, worked]);
256 }
257
258 /**
259 * @param {number} requestId
260 * @param {string} fileSystemPath
261 */
262 indexingDone(requestId, fileSystemPath) {
263 this._dispatchOnInspectorFrontendAPI('indexingDone', [requestId, fileSystemPath]);
264 }
265
266 /**
267 * @param {{type: string, key: string, code: string, keyCode: number, modifiers: number}} event
268 */
269 keyEventUnhandled(event) {
270 event.keyIdentifier = keyCodeToKeyIdentifier(event.keyCode);
271 this._dispatchOnInspectorFrontendAPI('keyEventUnhandled', [event]);
272 }
273
274 /**
275 * @param {function(!ExtensionDescriptor)} callback
276 */
277 setAddExtensionCallback(callback) {
278 this._addExtensionCallback = callback;
279 if (this._pendingExtensionDescriptors.length) {
280 this._pendingExtensionDescriptors.forEach(this._addExtensionCallback);
281 this._pendingExtensionDescriptors = [];
282 }
283 }
284
285 reattachMainTarget() {
286 this._dispatchOnInspectorFrontendAPI('reattachMainTarget', []);
287 }
288
289 /**
290 * @param {boolean} hard
291 */
292 reloadInspectedPage(hard) {
293 this._dispatchOnInspectorFrontendAPI('reloadInspectedPage', [hard]);
294 }
295
296 /**
297 * @param {string} url
298 * @param {number} lineNumber
299 * @param {number} columnNumber
300 */
301 revealSourceLine(url, lineNumber, columnNumber) {
302 this._dispatchOnInspectorFrontendAPI('revealSourceLine', [url, lineNumber, columnNumber]);
303 }
304
305 /**
306 * @param {string} url
307 * @param {string=} fileSystemPath
308 */
309 savedURL(url, fileSystemPath) {
310 this._dispatchOnInspectorFrontendAPI('savedURL', [url, fileSystemPath]);
311 }
312
313 /**
314 * @param {number} requestId
315 * @param {string} fileSystemPath
316 * @param {!Array.<string>} files
317 */
318 searchCompleted(requestId, fileSystemPath, files) {
319 this._dispatchOnInspectorFrontendAPI('searchCompleted', [requestId, fileSystemPath, files]);
320 }
321
322 /**
323 * @param {string} tabId
324 */
325 setInspectedTabId(tabId) {
326 this._inspectedTabIdValue = tabId;
327
328 // Support for legacy front-ends (<M41).
329 if (window['WebInspector'] && window['WebInspector']['setInspectedTabId']) {
330 window['WebInspector']['setInspectedTabId'](tabId);
331 } else {
332 this._dispatchOnInspectorFrontendAPI('setInspectedTabId', [tabId]);
333 }
334 }
335
336 /**
337 * @param {string} targetId
338 */
339 setInitialTargetId(targetId) {
340 this._setInitialTargetId(targetId);
341 }
342
343 /**
344 * @return {string|undefined}
345 */
346 getInspectedTabId() {
347 return this._inspectedTabIdValue;
348 }
349
350 /**
351 * @param {boolean} useSoftMenu
352 */
353 setUseSoftMenu(useSoftMenu) {
354 this._dispatchOnInspectorFrontendAPI('setUseSoftMenu', [useSoftMenu]);
355 }
356
357 /**
358 * @param {string} panelName
359 */
360 showPanel(panelName) {
361 this._dispatchOnInspectorFrontendAPI('showPanel', [panelName]);
362 }
363
364 /**
365 * @param {number} id
366 * @param {string} chunk
367 * @param {boolean} encoded
368 */
369 streamWrite(id, chunk, encoded) {
370 this._dispatchOnInspectorFrontendAPI('streamWrite', [id, encoded ? this._decodeBase64(chunk) : chunk]);
371 }
372
373 /**
374 * @param {string} chunk
Blink Reformat4c46d092018-04-07 15:32:37375 * @return {string}
376 */
Nikolay Vitkov42be2662023-01-12 15:32:35377 _decodeBase64(chunk) {
378 const request = new XMLHttpRequest();
379 request.open('GET', 'data:text/plain;base64,' + chunk, false);
380 request.send(null);
381 if (request.status === 200) {
382 return request.responseText;
Tim van der Lippe1d6e57a2019-09-30 11:55:34383 }
Nikolay Vitkov42be2662023-01-12 15:32:35384 console.error('Error while decoding chunk in streamWrite');
385 return '';
386 }
387};
388
389const DevToolsAPI = new DevToolsAPIImpl();
390window.DevToolsAPI = DevToolsAPI;
391
392// InspectorFrontendHostImpl --------------------------------------------------
393
394/**
395 * Enum for recordPerformanceHistogram
396 * Warning: There is another definition of this enum in the DevTools code
397 * base, keep them in sync:
398 * front_end/core/host/InspectorFrontendHostAPI.ts
399 * @readonly
400 * @enum {string}
401 */
402const EnumeratedHistogram = {
403 ActionTaken: 'DevTools.ActionTaken',
404 BreakpointWithConditionAdded: 'DevTools.BreakpointWithConditionAdded',
405 BreakpointEditDialogRevealedFrom: 'DevTools.BreakpointEditDialogRevealedFrom',
406 CSSHintShown: 'DevTools.CSSHintShown',
407 DeveloperResourceLoaded: 'DevTools.DeveloperResourceLoaded',
408 DeveloperResourceScheme: 'DevTools.DeveloperResourceScheme',
Ergun Erdogmus6f52cb72023-06-01 11:51:51409 ElementsSidebarTabShown: 'DevTools.Elements.SidebarTabShown',
Nikolay Vitkov42be2662023-01-12 15:32:35410 ExperimentDisabled: 'DevTools.ExperimentDisabled',
Changhao Han70cfccd2023-07-24 09:31:14411 ExperimentDisabledAtLaunch: 'DevTools.ExperimentDisabledAtLaunch',
Nikolay Vitkov42be2662023-01-12 15:32:35412 ExperimentEnabled: 'DevTools.ExperimentEnabled',
413 ExperimentEnabledAtLaunch: 'DevTools.ExperimentEnabledAtLaunch',
414 IssueCreated: 'DevTools.IssueCreated',
415 IssuesPanelIssueExpanded: 'DevTools.IssuesPanelIssueExpanded',
416 IssuesPanelOpenedFrom: 'DevTools.IssuesPanelOpenedFrom',
417 IssuesPanelResourceOpened: 'DevTools.IssuesPanelResourceOpened',
418 KeybindSetSettingChanged: 'DevTools.KeybindSetSettingChanged',
419 KeyboardShortcutFired: 'DevTools.KeyboardShortcutFired',
420 Language: 'DevTools.Language',
421 LighthouseModeRun: 'DevTools.LighthouseModeRun',
Adam Raineb50d50e2023-10-12 17:42:50422 LighthouseCategoryUsed: 'DevTools.LighthouseCategoryUsed',
Nikolay Vitkov42be2662023-01-12 15:32:35423 LinearMemoryInspectorRevealedFrom: 'DevTools.LinearMemoryInspector.RevealedFrom',
424 LinearMemoryInspectorTarget: 'DevTools.LinearMemoryInspector.Target',
425 ManifestSectionSelected: 'DevTools.ManifestSectionSelected',
426 PanelClosed: 'DevTools.PanelClosed',
427 PanelShown: 'DevTools.PanelShown',
Randolf Jungd3ea3e62023-04-11 09:10:09428 RecordingAssertion: 'DevTools.RecordingAssertion',
Nikolay Vitkov42be2662023-01-12 15:32:35429 RecordingCodeToggled: 'DevTools.RecordingCodeToggled',
430 RecordingCopiedToClipboard: 'DevTools.RecordingCopiedToClipboard',
431 RecordingEdited: 'DevTools.RecordingEdited',
432 RecordingExported: 'DevTools.RecordingExported',
433 RecordingReplayFinished: 'DevTools.RecordingReplayFinished',
434 RecordingReplaySpeed: 'DevTools.RecordingReplaySpeed',
435 RecordingReplayStarted: 'DevTools.RecordingReplayStarted',
436 RecordingToggled: 'DevTools.RecordingToggled',
437 SidebarPaneShown: 'DevTools.SidebarPaneShown',
Ergun Erdogmus6f52cb72023-06-01 11:51:51438 SourcesSidebarTabShown: 'DevTools.Sources.SidebarTabShown',
Simon Zünddc8c1452023-05-16 09:53:50439 SourcesPanelFileDebugged: 'DevTools.SourcesPanelFileDebugged',
Nikolay Vitkov42be2662023-01-12 15:32:35440 SourcesPanelFileOpened: 'DevTools.SourcesPanelFileOpened',
441 NetworkPanelResponsePreviewOpened: 'DevTools.NetworkPanelResponsePreviewOpened',
442 StyleTextCopied: 'DevTools.StyleTextCopied',
443 SyncSetting: 'DevTools.SyncSetting',
Changhao Hana49f2452023-03-16 10:12:10444 ColorConvertedFrom: 'DevTools.ColorConvertedFrom',
445 ColorPickerOpenedFrom: 'DevTools.ColorPickerOpenedFrom',
446 CSSPropertyDocumentation: 'DevTools.CSSPropertyDocumentation',
Changhao Han2df6fc22023-05-22 09:36:32447 InlineScriptParsed: 'DevTools.InlineScriptParsed',
448 VMInlineScriptTypeShown: 'DevTools.VMInlineScriptShown',
449 BreakpointsRestoredFromStorageCount: 'DevTools.BreakpointsRestoredFromStorageCount',
450 SwatchActivated: 'DevTools.SwatchActivated',
Ergun Erdogmus99c38742023-06-16 08:40:17451 BadgeActivated: 'DevTools.BadgeActivated',
Ergun Erdogmus2ef1c1e2023-08-08 08:34:34452 AnimationPlaybackRateChanged: 'DevTools.AnimationPlaybackRateChanged',
453 AnimationPointDragged: 'DevTools.AnimationPointDragged',
Nikolay Vitkov42be2662023-01-12 15:32:35454};
455
456/**
457 * @implements {InspectorFrontendHostAPI}
458 */
459const InspectorFrontendHostImpl = class {
460 /**
461 * @return {string}
462 */
463 getSelectionBackgroundColor() {
464 return '#6e86ff';
Blink Reformat4c46d092018-04-07 15:32:37465 }
466
Nikolay Vitkov42be2662023-01-12 15:32:35467 /**
468 * @return {string}
469 */
470 getSelectionForegroundColor() {
471 return '#ffffff';
472 }
Blink Reformat4c46d092018-04-07 15:32:37473
Nikolay Vitkov42be2662023-01-12 15:32:35474 /**
475 * @return {string}
476 */
477 getInactiveSelectionBackgroundColor() {
478 return '#c9c8c8';
479 }
Joel Einbinder82b1d8e2018-12-08 01:01:37480
Nikolay Vitkov42be2662023-01-12 15:32:35481 /**
482 * @return {string}
483 */
484 getInactiveSelectionForegroundColor() {
485 return '#323232';
486 }
Joel Einbinder82b1d8e2018-12-08 01:01:37487
Nikolay Vitkov42be2662023-01-12 15:32:35488 /**
489 * @override
490 * @return {string}
491 */
492 platform() {
493 return DevToolsHost.platform();
494 }
Joel Einbinder82b1d8e2018-12-08 01:01:37495
Nikolay Vitkov42be2662023-01-12 15:32:35496 /**
497 * @override
498 */
499 loadCompleted() {
500 DevToolsAPI.sendMessageToEmbedder('loadCompleted', [], null);
501 // Support for legacy (<57) frontends.
502 if (window.Runtime && window.Runtime.queryParam) {
503 const panelToOpen = window.Runtime.queryParam('panel');
504 if (panelToOpen) {
505 window.DevToolsAPI.showPanel(panelToOpen);
Joel Einbinderf55cc942018-10-30 01:59:53506 }
Blink Reformat4c46d092018-04-07 15:32:37507 }
Nikolay Vitkov42be2662023-01-12 15:32:35508 }
Blink Reformat4c46d092018-04-07 15:32:37509
Nikolay Vitkov42be2662023-01-12 15:32:35510 /**
511 * @override
512 */
513 bringToFront() {
514 DevToolsAPI.sendMessageToEmbedder('bringToFront', [], null);
515 }
516
517 /**
518 * @override
519 */
520 closeWindow() {
521 DevToolsAPI.sendMessageToEmbedder('closeWindow', [], null);
522 }
523
524 /**
525 * @override
526 * @param {boolean} isDocked
527 * @param {function()} callback
528 */
529 setIsDocked(isDocked, callback) {
530 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [isDocked], callback);
531 }
532
533 /**
534 * @override
535 * @param {string} trigger
536 * @param {function(!InspectorFrontendHostAPI.ShowSurveyResult): void} callback
537 */
538 showSurvey(trigger, callback) {
539 DevToolsAPI.sendMessageToEmbedder('showSurvey', [trigger], /** @type {function(?Object)} */ (callback));
540 }
541
542 /**
543 * @override
544 * @param {string} trigger
545 * @param {function(!InspectorFrontendHostAPI.CanShowSurveyResult): void} callback
546 */
547 canShowSurvey(trigger, callback) {
548 DevToolsAPI.sendMessageToEmbedder('canShowSurvey', [trigger], /** @type {function(?Object)} */ (callback));
549 }
550
551 /**
552 * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
553 * @override
554 * @param {{x: number, y: number, width: number, height: number}} bounds
555 */
556 setInspectedPageBounds(bounds) {
557 DevToolsAPI.sendMessageToEmbedder('setInspectedPageBounds', [bounds], null);
558 }
559
560 /**
561 * @override
562 */
563 inspectElementCompleted() {
564 DevToolsAPI.sendMessageToEmbedder('inspectElementCompleted', [], null);
565 }
566
567 /**
568 * @override
569 * @param {string} url
570 * @param {string} headers
571 * @param {number} streamId
572 * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult): void} callback
573 */
574 loadNetworkResource(url, headers, streamId, callback) {
575 DevToolsAPI.sendMessageToEmbedder(
576 'loadNetworkResource', [url, headers, streamId], /** @type {function(?Object)} */ (callback));
577 }
578
579 /**
580 * @override
581 * @param {string} name
582 * @param {!{synced: (boolean|undefined)}} options
583 */
584 registerPreference(name, options) {
585 DevToolsAPI.sendMessageToEmbedder('registerPreference', [name, options], null);
586 }
587
588 /**
589 * @override
590 * @param {function(!Object<string, string>)} callback
591 */
592 getPreferences(callback) {
593 DevToolsAPI.sendMessageToEmbedder('getPreferences', [], /** @type {function(?Object)} */ (callback));
594 }
595
596 /**
597 * @override
598 * @param {string} name
599 * @param {function(string)} callback
600 */
601 getPreference(name, callback) {
602 DevToolsAPI.sendMessageToEmbedder('getPreference', [name], /** @type {function(string)} */ (callback));
603 }
604
605 /**
606 * @override
607 * @param {string} name
608 * @param {string} value
609 */
610 setPreference(name, value) {
611 DevToolsAPI.sendMessageToEmbedder('setPreference', [name, value], null);
612 }
613
614 /**
615 * @override
616 * @param {string} name
617 */
618 removePreference(name) {
619 DevToolsAPI.sendMessageToEmbedder('removePreference', [name], null);
620 }
621
622 /**
623 * @override
624 */
625 clearPreferences() {
626 DevToolsAPI.sendMessageToEmbedder('clearPreferences', [], null);
627 }
628
629 /**
630 * @override
631 * @param {!function(!InspectorFrontendHostAPI.SyncInformation):void} callback
632 */
633 getSyncInformation(callback) {
634 DevToolsAPI.sendMessageToEmbedder('getSyncInformation', [], callback);
635 }
636
637 /**
638 * @override
639 * @param {string} origin
640 * @param {string} script
641 */
642 setInjectedScriptForOrigin(origin, script) {
643 DevToolsAPI.sendMessageToEmbedder('registerExtensionsAPI', [origin, script], null);
644 }
645
646 /**
647 * @override
648 * @param {string} url
649 */
650 inspectedURLChanged(url) {
651 DevToolsAPI.sendMessageToEmbedder('inspectedURLChanged', [url], null);
652 }
653
654 /**
655 * @override
656 * @param {string} text
657 */
658 copyText(text) {
659 DevToolsHost.copyText(text);
660 }
661
662 /**
663 * @override
664 * @param {string} url
665 */
666 openInNewTab(url) {
667 DevToolsAPI.sendMessageToEmbedder('openInNewTab', [url], null);
668 }
669
670 /**
671 * @override
672 * @param {string} fileSystemPath
673 */
674 showItemInFolder(fileSystemPath) {
675 DevToolsAPI.sendMessageToEmbedder('showItemInFolder', [fileSystemPath], null);
676 }
677
678 /**
679 * @override
680 * @param {string} url
681 * @param {string} content
682 * @param {boolean} forceSaveAs
683 */
684 save(url, content, forceSaveAs) {
685 DevToolsAPI.sendMessageToEmbedder('save', [url, content, forceSaveAs], null);
686 }
687
688 /**
689 * @override
690 * @param {string} url
691 * @param {string} content
692 */
693 append(url, content) {
694 DevToolsAPI.sendMessageToEmbedder('append', [url, content], null);
695 }
696
697 /**
698 * @override
699 * @param {string} url
700 */
701 close(url) {
702 }
703
704 /**
705 * @override
706 * @param {string} message
707 */
708 sendMessageToBackend(message) {
709 DevToolsAPI.sendMessageToEmbedder('dispatchProtocolMessage', [message], null);
710 }
711
712 /**
713 * @override
Benedikt Meurer3f5c0032023-06-16 11:11:07714 * @param {string} histogramName
715 * @param {number} sample
716 * @param {number} min
717 * @param {number} exclusiveMax
718 * @param {number} bucketSize
719 */
720 recordCountHistogram(histogramName, sample, min, exclusiveMax, bucketSize) {
721 DevToolsAPI.sendMessageToEmbedder(
722 'recordCountHistogram', [histogramName, sample, min, exclusiveMax, bucketSize], null);
723 }
724
725 /**
726 * @override
Nikolay Vitkov42be2662023-01-12 15:32:35727 * @param {!InspectorFrontendHostAPI.EnumeratedHistogram} actionName
728 * @param {number} actionCode
729 * @param {number} bucketSize
730 */
731 recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
732 if (!Object.values(EnumeratedHistogram).includes(actionName)) {
733 return;
734 }
735 DevToolsAPI.sendMessageToEmbedder('recordEnumeratedHistogram', [actionName, actionCode, bucketSize], null);
736 }
737
738 /**
739 * @override
740 * @param {string} histogramName
741 * @param {number} duration
742 */
743 recordPerformanceHistogram(histogramName, duration) {
744 DevToolsAPI.sendMessageToEmbedder('recordPerformanceHistogram', [histogramName, duration], null);
745 }
746
747 /**
748 * @override
749 * @param {string} umaName
750 */
751 recordUserMetricsAction(umaName) {
752 DevToolsAPI.sendMessageToEmbedder('recordUserMetricsAction', [umaName], null);
753 }
754
755 /**
756 * @override
757 */
758 requestFileSystems() {
759 DevToolsAPI.sendMessageToEmbedder('requestFileSystems', [], null);
760 }
761
762 /**
763 * @override
764 * @param {string=} type
765 */
766 addFileSystem(type) {
767 DevToolsAPI.sendMessageToEmbedder('addFileSystem', [type || ''], null);
768 }
769
770 /**
771 * @override
772 * @param {string} fileSystemPath
773 */
774 removeFileSystem(fileSystemPath) {
775 DevToolsAPI.sendMessageToEmbedder('removeFileSystem', [fileSystemPath], null);
776 }
777
778 /**
779 * @override
780 * @param {string} fileSystemId
781 * @param {string} registeredName
782 * @return {?FileSystem}
783 */
784 isolatedFileSystem(fileSystemId, registeredName) {
785 return DevToolsHost.isolatedFileSystem(fileSystemId, registeredName);
786 }
787
788 /**
789 * @override
790 * @param {!FileSystem} fileSystem
791 */
792 upgradeDraggedFileSystemPermissions(fileSystem) {
793 DevToolsHost.upgradeDraggedFileSystemPermissions(fileSystem);
794 }
795
796 /**
797 * @override
798 * @param {number} requestId
799 * @param {string} fileSystemPath
800 * @param {string} excludedFolders
801 */
802 indexPath(requestId, fileSystemPath, excludedFolders) {
803 // |excludedFolders| added in M67. For backward compatibility,
804 // pass empty array.
805 excludedFolders = excludedFolders || '[]';
806 DevToolsAPI.sendMessageToEmbedder('indexPath', [requestId, fileSystemPath, excludedFolders], null);
807 }
808
809 /**
810 * @override
811 * @param {number} requestId
812 */
813 stopIndexing(requestId) {
814 DevToolsAPI.sendMessageToEmbedder('stopIndexing', [requestId], null);
815 }
816
817 /**
818 * @override
819 * @param {number} requestId
820 * @param {string} fileSystemPath
821 * @param {string} query
822 */
823 searchInPath(requestId, fileSystemPath, query) {
824 DevToolsAPI.sendMessageToEmbedder('searchInPath', [requestId, fileSystemPath, query], null);
825 }
826
827 /**
828 * @override
829 * @return {number}
830 */
831 zoomFactor() {
832 return DevToolsHost.zoomFactor();
833 }
834
835 /**
836 * @override
837 */
838 zoomIn() {
839 DevToolsAPI.sendMessageToEmbedder('zoomIn', [], null);
840 }
841
842 /**
843 * @override
844 */
845 zoomOut() {
846 DevToolsAPI.sendMessageToEmbedder('zoomOut', [], null);
847 }
848
849 /**
850 * @override
851 */
852 resetZoom() {
853 DevToolsAPI.sendMessageToEmbedder('resetZoom', [], null);
854 }
855
856 /**
857 * @override
858 * @param {string} shortcuts
859 */
860 setWhitelistedShortcuts(shortcuts) {
861 DevToolsAPI.sendMessageToEmbedder('setWhitelistedShortcuts', [shortcuts], null);
862 }
863
864 /**
865 * @override
866 * @param {boolean} active
867 */
868 setEyeDropperActive(active) {
869 DevToolsAPI.sendMessageToEmbedder('setEyeDropperActive', [active], null);
870 }
871
872 /**
873 * @override
874 * @param {!Array<string>} certChain
875 */
876 showCertificateViewer(certChain) {
877 DevToolsAPI.sendMessageToEmbedder('showCertificateViewer', [JSON.stringify(certChain)], null);
878 }
879
880 /**
881 * Only needed to run Lighthouse on old devtools.
882 * @override
883 * @param {function()} callback
884 */
885 reattach(callback) {
886 DevToolsAPI.sendMessageToEmbedder('reattach', [], callback);
887 }
888
889 /**
890 * @override
891 */
892 readyForTest() {
893 DevToolsAPI.sendMessageToEmbedder('readyForTest', [], null);
894 }
895
896 /**
897 * @override
898 */
899 connectionReady() {
900 DevToolsAPI.sendMessageToEmbedder('connectionReady', [], null);
901 }
902
903 /**
904 * @override
905 * @param {boolean} value
906 */
907 setOpenNewWindowForPopups(value) {
908 DevToolsAPI.sendMessageToEmbedder('setOpenNewWindowForPopups', [value], null);
909 }
910
911 /**
912 * @override
913 * @param {!Adb.Config} config
914 */
915 setDevicesDiscoveryConfig(config) {
916 DevToolsAPI.sendMessageToEmbedder(
917 'setDevicesDiscoveryConfig',
918 [
919 config.discoverUsbDevices, config.portForwardingEnabled, JSON.stringify(config.portForwardingConfig),
920 config.networkDiscoveryEnabled, JSON.stringify(config.networkDiscoveryConfig)
921 ],
922 null);
923 }
924
925 /**
926 * @override
927 * @param {boolean} enabled
928 */
929 setDevicesUpdatesEnabled(enabled) {
930 DevToolsAPI.sendMessageToEmbedder('setDevicesUpdatesEnabled', [enabled], null);
931 }
932
933 /**
934 * @override
935 * @param {string} pageId
936 * @param {string} action
937 */
938 performActionOnRemotePage(pageId, action) {
939 DevToolsAPI.sendMessageToEmbedder('performActionOnRemotePage', [pageId, action], null);
940 }
941
942 /**
943 * @override
944 * @param {string} browserId
945 * @param {string} url
946 */
947 openRemotePage(browserId, url) {
948 DevToolsAPI.sendMessageToEmbedder('openRemotePage', [browserId, url], null);
949 }
950
951 /**
952 * @override
953 */
954 openNodeFrontend() {
955 DevToolsAPI.sendMessageToEmbedder('openNodeFrontend', [], null);
956 }
957
958 /**
959 * @override
960 * @param {number} x
961 * @param {number} y
962 * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
963 * @param {!Document} document
964 */
965 showContextMenuAtPoint(x, y, items, document) {
966 DevToolsHost.showContextMenuAtPoint(x, y, items, document);
967 }
968
969 /**
970 * @override
971 * @return {boolean}
972 */
973 isHostedMode() {
974 return DevToolsHost.isHostedMode();
975 }
976
977 /**
978 * @override
979 * @param {function(!ExtensionDescriptor)} callback
980 */
981 setAddExtensionCallback(callback) {
982 DevToolsAPI.setAddExtensionCallback(callback);
983 }
984
Danil Somsikov9f18cf62023-09-21 11:43:45985 /**
986 * @override
987 * @param {InspectorFrontendHostAPI.ImpressionEvent} impressionEvent
988 */
989 recordImpression(impressionEvent) {
Danil Somsikov609b5862023-10-16 11:16:34990 DevToolsAPI.sendMessageToEmbedder('recordImpression', [impressionEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:45991 }
992
993 /**
994 * @override
995 * @param {InspectorFrontendHostAPI.ClickEvent} clickEvent
996 */
997 recordClick(clickEvent) {
Danil Somsikov609b5862023-10-16 11:16:34998 DevToolsAPI.sendMessageToEmbedder('recordClick', [clickEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:45999 }
1000
1001 /**
1002 * @override
Danil Somsikov5e555eb2023-10-18 13:42:591003 * @param {InspectorFrontendHostAPI.HoverEvent} hoverEvent
1004 */
1005 recordHover(hoverEvent) {
1006 DevToolsAPI.sendMessageToEmbedder('recordHover', [hoverEvent], null);
1007 }
1008
1009 /**
1010 * @override
Danil Somsikov1aca65a2023-10-20 10:22:401011 * @param {InspectorFrontendHostAPI.DragEvent} dragEvent
1012 */
1013 recordDrag(DragEvent) {
1014 DevToolsAPI.sendMessageToEmbedder('recordDrag', [dragEvent], null);
1015 }
1016
1017 /**
1018 * @override
Danil Somsikov9f18cf62023-09-21 11:43:451019 * @param {InspectorFrontendHostAPI.ChangeEvent} changeEvent
1020 */
1021 recordChange(changeEvent) {
Danil Somsikov609b5862023-10-16 11:16:341022 DevToolsAPI.sendMessageToEmbedder('recordChange', [changeEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:451023 }
1024
1025 /**
1026 * @override
1027 * @param {InspectorFrontendHostAPI.KeyDownEvent} keyDownEvent
1028 */
1029 recordKeyDown(keyDownEvent) {
Danil Somsikov609b5862023-10-16 11:16:341030 DevToolsAPI.sendMessageToEmbedder('recordKeyDown', [keyDownEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:451031 }
1032
Nikolay Vitkov42be2662023-01-12 15:32:351033 // Backward-compatible methods below this line --------------------------------------------
1034
1035 /**
1036 * Support for legacy front-ends (<M65).
1037 * @return {boolean}
1038 */
1039 isUnderTest() {
1040 return false;
1041 }
1042
1043 /**
1044 * Support for legacy front-ends (<M50).
1045 * @param {string} message
1046 */
1047 sendFrontendAPINotification(message) {
1048 }
1049
1050 /**
1051 * Support for legacy front-ends (<M41).
1052 * @return {string}
1053 */
1054 port() {
1055 return 'unknown';
1056 }
1057
1058 /**
1059 * Support for legacy front-ends (<M38).
1060 * @param {number} zoomFactor
1061 */
1062 setZoomFactor(zoomFactor) {
1063 }
1064
1065 /**
1066 * Support for legacy front-ends (<M34).
1067 */
1068 sendMessageToEmbedder() {
1069 }
1070
1071 /**
1072 * Support for legacy front-ends (<M34).
1073 * @param {string} dockSide
1074 */
1075 requestSetDockSide(dockSide) {
1076 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [dockSide !== 'undocked'], null);
1077 }
1078
1079 /**
1080 * Support for legacy front-ends (<M34).
1081 * @return {boolean}
1082 */
1083 supportsFileSystems() {
1084 return true;
1085 }
1086
1087 /**
1088 * Support for legacy front-ends (<M44).
1089 * @param {number} actionCode
1090 */
1091 recordActionTaken(actionCode) {
1092 // Do not record actions, as that may crash the DevTools renderer.
1093 }
1094
1095 /**
1096 * Support for legacy front-ends (<M44).
1097 * @param {number} panelCode
1098 */
1099 recordPanelShown(panelCode) {
1100 // Do not record actions, as that may crash the DevTools renderer.
1101 }
1102
1103 /**
1104 * @return {!Promise<string>}
1105 */
1106 initialTargetId() {
1107 return DevToolsAPI._initialTargetIdPromise;
1108 }
Alex Rudenko13d80cf2023-08-24 12:46:561109
1110 /**
1111 * @param {string} request
1112 * @param {function(!InspectorFrontendHostAPI.DoAidaConversationResult): void} cb
1113 */
1114 doAidaConversation(request, cb) {
1115 DevToolsAPI.sendMessageToEmbedder('doAidaConversation', [request], cb);
1116 }
Nikolay Vitkov42be2662023-01-12 15:32:351117};
1118
1119window.InspectorFrontendHost = new InspectorFrontendHostImpl();
1120
1121// DevToolsApp ---------------------------------------------------------------
1122
1123function installObjectObserve() {
1124 /** @type {!Array<string>} */
1125 const properties = [
1126 'advancedSearchConfig',
1127 'auditsPanelSplitViewState',
1128 'auditsSidebarWidth',
1129 'blockedURLs',
1130 'breakpoints',
1131 'cacheDisabled',
1132 'colorFormat',
1133 'consoleHistory',
1134 'consoleTimestampsEnabled',
1135 'cpuProfilerView',
1136 'cssSourceMapsEnabled',
1137 'currentDockState',
1138 'customColorPalette',
1139 'customDevicePresets',
1140 'customEmulatedDeviceList',
1141 'customFormatters',
1142 'customUserAgent',
1143 'databaseTableViewVisibleColumns',
1144 'dataGrid-cookiesTable',
1145 'dataGrid-DOMStorageItemsView',
1146 'debuggerSidebarHidden',
1147 'disablePausedStateOverlay',
1148 'domBreakpoints',
1149 'domWordWrap',
1150 'elementsPanelSplitViewState',
1151 'elementsSidebarWidth',
1152 'emulation.deviceHeight',
1153 'emulation.deviceModeValue',
1154 'emulation.deviceOrientationOverride',
1155 'emulation.deviceScale',
1156 'emulation.deviceScaleFactor',
1157 'emulation.deviceUA',
1158 'emulation.deviceWidth',
1159 'emulation.locationOverride',
1160 'emulation.showDeviceMode',
1161 'emulation.showRulers',
1162 'enableAsyncStackTraces',
1163 'enableIgnoreListing',
1164 'eventListenerBreakpoints',
1165 'fileMappingEntries',
1166 'fileSystemMapping',
1167 'FileSystemViewSidebarWidth',
1168 'fileSystemViewSplitViewState',
1169 'filterBar-consoleView',
1170 'filterBar-networkPanel',
1171 'filterBar-promisePane',
1172 'filterBar-timelinePanel',
1173 'frameViewerHideChromeWindow',
1174 'heapSnapshotRetainersViewSize',
1175 'heapSnapshotSplitViewState',
1176 'hideCollectedPromises',
1177 'hideNetworkMessages',
1178 'highlightNodeOnHoverInOverlay',
1179 'inlineVariableValues',
1180 'Inspector.drawerSplitView',
1181 'Inspector.drawerSplitViewState',
1182 'InspectorView.panelOrder',
1183 'InspectorView.screencastSplitView',
1184 'InspectorView.screencastSplitViewState',
1185 'InspectorView.splitView',
1186 'InspectorView.splitViewState',
1187 'javaScriptDisabled',
1188 'jsSourceMapsEnabled',
1189 'lastActivePanel',
1190 'lastDockState',
1191 'lastSelectedSourcesSidebarPaneTab',
1192 'lastSnippetEvaluationIndex',
1193 'layerDetailsSplitView',
1194 'layerDetailsSplitViewState',
1195 'layersPanelSplitViewState',
1196 'layersShowInternalLayers',
1197 'layersSidebarWidth',
1198 'messageLevelFilters',
1199 'messageURLFilters',
1200 'monitoringXHREnabled',
1201 'navigatorGroupByAuthored',
1202 'navigatorGroupByFolder',
1203 'navigatorHidden',
1204 'networkColorCodeResourceTypes',
1205 'networkConditions',
1206 'networkConditionsCustomProfiles',
1207 'networkHideDataURL',
1208 'networkLogColumnsVisibility',
1209 'networkLogLargeRows',
1210 'networkLogShowOverview',
1211 'networkPanelSplitViewState',
1212 'networkRecordFilmStripSetting',
1213 'networkResourceTypeFilters',
1214 'networkShowPrimaryLoadWaterfall',
1215 'networkSidebarWidth',
1216 'openLinkHandler',
1217 'pauseOnUncaughtException',
1218 'pauseOnCaughtException',
1219 'pauseOnExceptionEnabled',
1220 'preserveConsoleLog',
1221 'prettyPrintInfobarDisabled',
1222 'previouslyViewedFiles',
1223 'profilesPanelSplitViewState',
1224 'profilesSidebarWidth',
1225 'promiseStatusFilters',
1226 'recordAllocationStacks',
1227 'requestHeaderFilterSetting',
1228 'request-info-formData-category-expanded',
1229 'request-info-general-category-expanded',
1230 'request-info-queryString-category-expanded',
1231 'request-info-requestHeaders-category-expanded',
1232 'request-info-requestPayload-category-expanded',
1233 'request-info-responseHeaders-category-expanded',
1234 'resources',
1235 'resourcesLastSelectedItem',
1236 'resourcesPanelSplitViewState',
1237 'resourcesSidebarWidth',
1238 'resourceViewTab',
1239 'savedURLs',
1240 'screencastEnabled',
1241 'scriptsPanelNavigatorSidebarWidth',
1242 'searchInContentScripts',
1243 'selectedAuditCategories',
1244 'selectedColorPalette',
1245 'selectedProfileType',
1246 'shortcutPanelSwitch',
1247 'showAdvancedHeapSnapshotProperties',
1248 'showEventListenersForAncestors',
1249 'showFrameowkrListeners',
1250 'showHeaSnapshotObjectsHiddenProperties',
1251 'showInheritedComputedStyleProperties',
1252 'showMediaQueryInspector',
Nikolay Vitkov42be2662023-01-12 15:32:351253 'showUAShadowDOM',
1254 'showWhitespacesInEditor',
1255 'sidebarPosition',
1256 'skipContentScripts',
1257 'automaticallyIgnoreListKnownThirdPartyScripts',
1258 'skipStackFramesPattern',
1259 'sourceMapInfobarDisabled',
Eric Leeseff8a2a52023-07-11 14:02:281260 'sourceMapSkippedInfobarDisabled',
Nikolay Vitkov42be2662023-01-12 15:32:351261 'sourcesPanelDebuggerSidebarSplitViewState',
1262 'sourcesPanelNavigatorSplitViewState',
1263 'sourcesPanelSplitSidebarRatio',
1264 'sourcesPanelSplitViewState',
1265 'sourcesSidebarWidth',
1266 'standardEmulatedDeviceList',
1267 'StylesPaneSplitRatio',
1268 'stylesPaneSplitViewState',
1269 'textEditorAutocompletion',
1270 'textEditorAutoDetectIndent',
1271 'textEditorBracketMatching',
1272 'textEditorIndent',
1273 'textEditorTabMovesFocus',
1274 'timelineCaptureFilmStrip',
1275 'timelineCaptureLayersAndPictures',
1276 'timelineCaptureMemory',
1277 'timelineCaptureNetwork',
1278 'timeline-details',
1279 'timelineEnableJSSampling',
1280 'timelineOverviewMode',
1281 'timelinePanelDetailsSplitViewState',
1282 'timelinePanelRecorsSplitViewState',
1283 'timelinePanelTimelineStackSplitViewState',
1284 'timelinePerspective',
1285 'timeline-split',
1286 'timelineTreeGroupBy',
1287 'timeline-view',
1288 'timelineViewMode',
1289 'uiTheme',
1290 'watchExpressions',
1291 'WebInspector.Drawer.lastSelectedView',
1292 'WebInspector.Drawer.showOnLoad',
1293 'workspaceExcludedFolders',
1294 'workspaceFolderExcludePattern',
1295 'workspaceInfobarDisabled',
1296 'workspaceMappingInfobarDisabled',
1297 'xhrBreakpoints'
1298 ];
1299
1300 /**
1301 * @this {!{_storage: Object, _name: string}}
1302 */
1303 function settingRemove() {
1304 this._storage[this._name] = undefined;
1305 }
1306
1307 /**
1308 * @param {!Object} object
1309 * @param {function(!Array<!{name: string}>)} observer
1310 */
1311 function objectObserve(object, observer) {
1312 if (window['WebInspector']) {
1313 const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
1314 if (typeof settingPrototype['remove'] === 'function') {
1315 settingPrototype['remove'] = settingRemove;
1316 }
1317 }
1318 /** @type {!Set<string>} */
1319 const changedProperties = new Set();
1320 let scheduled = false;
1321
1322 function scheduleObserver() {
1323 if (scheduled) {
1324 return;
1325 }
1326 scheduled = true;
1327 queueMicrotask(callObserver);
1328 }
1329
1330 function callObserver() {
1331 scheduled = false;
1332 const changes = /** @type {!Array<!{name: string}>} */ ([]);
1333 changedProperties.forEach(function(name) {
1334 changes.push({name: name});
1335 });
1336 changedProperties.clear();
1337 observer.call(null, changes);
1338 }
1339
1340 /** @type {!Map<string, *>} */
1341 const storage = new Map();
1342
1343 /**
1344 * @param {string} property
1345 */
1346 function defineProperty(property) {
1347 if (property in object) {
1348 storage.set(property, object[property]);
1349 delete object[property];
1350 }
1351
1352 Object.defineProperty(object, property, {
Blink Reformat4c46d092018-04-07 15:32:371353 /**
Nikolay Vitkov42be2662023-01-12 15:32:351354 * @return {*}
Blink Reformat4c46d092018-04-07 15:32:371355 */
1356 get: function() {
Nikolay Vitkov42be2662023-01-12 15:32:351357 return storage.get(property);
1358 },
1359
1360 /**
1361 * @param {*} value
1362 */
1363 set: function(value) {
1364 storage.set(property, value);
1365 changedProperties.add(property);
1366 scheduleObserver();
Blink Reformat4c46d092018-04-07 15:32:371367 }
1368 });
1369 }
1370
Nikolay Vitkov42be2662023-01-12 15:32:351371 for (let i = 0; i < properties.length; ++i) {
1372 defineProperty(properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341373 }
Joel Einbinderf55cc942018-10-30 01:59:531374 }
Blink Reformat4c46d092018-04-07 15:32:371375
Nikolay Vitkov42be2662023-01-12 15:32:351376 window.Object.observe = objectObserve;
1377}
1378
1379/** @type {!Map<number, string>} */
1380const staticKeyIdentifiers = new Map([
1381 [0x12, 'Alt'],
1382 [0x11, 'Control'],
1383 [0x10, 'Shift'],
1384 [0x14, 'CapsLock'],
1385 [0x5b, 'Win'],
1386 [0x5c, 'Win'],
1387 [0x0c, 'Clear'],
1388 [0x28, 'Down'],
1389 [0x23, 'End'],
1390 [0x0a, 'Enter'],
1391 [0x0d, 'Enter'],
1392 [0x2b, 'Execute'],
1393 [0x70, 'F1'],
1394 [0x71, 'F2'],
1395 [0x72, 'F3'],
1396 [0x73, 'F4'],
1397 [0x74, 'F5'],
1398 [0x75, 'F6'],
1399 [0x76, 'F7'],
1400 [0x77, 'F8'],
1401 [0x78, 'F9'],
1402 [0x79, 'F10'],
1403 [0x7a, 'F11'],
1404 [0x7b, 'F12'],
1405 [0x7c, 'F13'],
1406 [0x7d, 'F14'],
1407 [0x7e, 'F15'],
1408 [0x7f, 'F16'],
1409 [0x80, 'F17'],
1410 [0x81, 'F18'],
1411 [0x82, 'F19'],
1412 [0x83, 'F20'],
1413 [0x84, 'F21'],
1414 [0x85, 'F22'],
1415 [0x86, 'F23'],
1416 [0x87, 'F24'],
1417 [0x2f, 'Help'],
1418 [0x24, 'Home'],
1419 [0x2d, 'Insert'],
1420 [0x25, 'Left'],
1421 [0x22, 'PageDown'],
1422 [0x21, 'PageUp'],
1423 [0x13, 'Pause'],
1424 [0x2c, 'PrintScreen'],
1425 [0x27, 'Right'],
1426 [0x91, 'Scroll'],
1427 [0x29, 'Select'],
1428 [0x26, 'Up'],
1429 [0x2e, 'U+007F'], // Standard says that DEL becomes U+007F.
1430 [0xb0, 'MediaNextTrack'],
1431 [0xb1, 'MediaPreviousTrack'],
1432 [0xb2, 'MediaStop'],
1433 [0xb3, 'MediaPlayPause'],
1434 [0xad, 'VolumeMute'],
1435 [0xae, 'VolumeDown'],
1436 [0xaf, 'VolumeUp'],
1437]);
1438
1439/**
1440 * @param {number} keyCode
1441 * @return {string}
1442 */
1443function keyCodeToKeyIdentifier(keyCode) {
1444 let result = staticKeyIdentifiers.get(keyCode);
1445 if (result !== undefined) {
1446 return result;
1447 }
1448 result = 'U+';
1449 const hexString = keyCode.toString(16).toUpperCase();
1450 for (let i = hexString.length; i < 4; ++i) {
1451 result += '0';
1452 }
1453 result += hexString;
1454 return result;
1455}
1456
1457function installBackwardsCompatibility() {
1458 const majorVersion = getRemoteMajorVersion();
1459 if (!majorVersion) {
1460 return;
1461 }
1462
1463 /** @type {!Array<string>} */
1464 const styleRules = [];
1465 // Shadow DOM V0 polyfill
1466 if (majorVersion <= 73 && !Element.prototype.createShadowRoot) {
1467 Element.prototype.createShadowRoot = function() {
1468 try {
1469 return this.attachShadow({mode: 'open'});
1470 } catch (e) {
1471 // some elements we use to add shadow roots can no
1472 // longer have shadow roots.
1473 const fakeShadowHost = document.createElement('span');
1474 this.appendChild(fakeShadowHost);
1475 fakeShadowHost.className = 'fake-shadow-host';
1476 return fakeShadowHost.createShadowRoot();
Tim van der Lippe1d6e57a2019-09-30 11:55:341477 }
Nikolay Vitkov42be2662023-01-12 15:32:351478 };
1479
1480 const origAdd = DOMTokenList.prototype.add;
1481 DOMTokenList.prototype.add = function(...tokens) {
1482 if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) {
1483 this._myElement.slot = '.' + tokens[0];
1484 }
1485 return origAdd.apply(this, tokens);
1486 };
1487
1488 const origCreateElement = Document.prototype.createElement;
1489 Document.prototype.createElement = function(tagName, ...rest) {
1490 if (tagName === 'content') {
1491 tagName = 'slot';
1492 }
1493 const element = origCreateElement.call(this, tagName, ...rest);
1494 element.classList._myElement = element;
1495 return element;
1496 };
1497
1498 Object.defineProperty(HTMLSlotElement.prototype, 'select', {
1499 set(selector) {
1500 this.name = selector;
1501 }
1502 });
Joel Einbinderf55cc942018-10-30 01:59:531503 }
1504
Nikolay Vitkov42be2662023-01-12 15:32:351505 // Custom Elements V0 polyfill
1506 if (majorVersion <= 73 && !Document.prototype.hasOwnProperty('registerElement')) {
1507 const fakeRegistry = new Map();
1508 Document.prototype.registerElement = function(typeExtension, options) {
1509 const {prototype, extends: localName} = options;
1510 const document = this;
1511 const callback = function() {
1512 const element = document.createElement(localName || typeExtension);
1513 const skip = new Set(['constructor', '__proto__']);
1514 for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
1515 if (skip.has(key)) {
1516 continue;
1517 }
1518 element[key] = prototype[key];
1519 }
1520 element.setAttribute('is', typeExtension);
1521 if (element['createdCallback']) {
1522 element['createdCallback']();
1523 }
1524 return element;
1525 };
1526 fakeRegistry.set(typeExtension, callback);
1527 return callback;
1528 };
Joel Einbinderf55cc942018-10-30 01:59:531529
Nikolay Vitkov42be2662023-01-12 15:32:351530 const origCreateElement = Document.prototype.createElement;
1531 Document.prototype.createElement = function(tagName, fakeCustomElementType) {
1532 const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
1533 if (fakeConstructor) {
1534 return fakeConstructor();
1535 }
1536 return origCreateElement.call(this, tagName, fakeCustomElementType);
1537 };
1538
1539 // DevTools front-ends mistakenly assume that
1540 // classList.toggle('a', undefined) works as
1541 // classList.toggle('a', false) rather than as
1542 // classList.toggle('a');
1543 const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
1544 DOMTokenList.prototype.toggle = function(token, force) {
1545 if (arguments.length === 1) {
1546 force = !this.contains(token);
1547 }
1548 return originalDOMTokenListToggle.call(this, token, Boolean(force));
Joel Einbinderf55cc942018-10-30 01:59:531549 };
1550 }
1551
Nikolay Vitkov42be2662023-01-12 15:32:351552 if (majorVersion <= 66) {
1553 /** @type {(!function(number, number):Element|undefined)} */
1554 ShadowRoot.prototype.__originalShadowRootElementFromPoint;
1555
1556 if (!ShadowRoot.prototype.__originalShadowRootElementFromPoint) {
1557 ShadowRoot.prototype.__originalShadowRootElementFromPoint = ShadowRoot.prototype.elementFromPoint;
1558 /**
1559 * @param {number} x
1560 * @param {number} y
1561 * @return {Element}
1562 */
1563 ShadowRoot.prototype.elementFromPoint = function(x, y) {
1564 const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
1565 if (this.host && originalResult === this.host) {
1566 return null;
1567 }
1568 return originalResult;
1569 };
1570 }
Blink Reformat4c46d092018-04-07 15:32:371571 }
1572
Nikolay Vitkov42be2662023-01-12 15:32:351573 if (majorVersion <= 53) {
1574 Object.defineProperty(window.KeyboardEvent.prototype, 'keyIdentifier', {
1575 /**
1576 * @return {string}
1577 * @this {KeyboardEvent}
1578 */
1579 get: function() {
1580 return keyCodeToKeyIdentifier(this.keyCode);
1581 }
1582 });
1583 }
Blink Reformat4c46d092018-04-07 15:32:371584
Nikolay Vitkov42be2662023-01-12 15:32:351585 if (majorVersion <= 50) {
1586 installObjectObserve();
1587 }
1588
1589 if (majorVersion <= 71) {
1590 styleRules.push(
1591 '.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
1592 }
1593
1594 if (majorVersion <= 50) {
1595 Event.prototype.deepPath = undefined;
1596 }
1597
1598 if (majorVersion <= 54) {
1599 window.FileError = /** @type {!function (new: FileError) : ?} */ ({
1600 NOT_FOUND_ERR: DOMException.NOT_FOUND_ERR,
1601 ABORT_ERR: DOMException.ABORT_ERR,
1602 INVALID_MODIFICATION_ERR: DOMException.INVALID_MODIFICATION_ERR,
1603 NOT_READABLE_ERR: 0 // No matching DOMException, so code will be 0.
1604 });
1605 }
1606
1607 installExtraStyleRules(styleRules);
1608}
1609
1610/**
1611 * @return {?number}
1612 */
1613function getRemoteMajorVersion() {
1614 try {
1615 const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
1616 if (!remoteVersion) {
1617 return null;
1618 }
1619 const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
1620 return majorVersion;
1621 } catch (e) {
1622 return null;
1623 }
1624}
1625
1626/**
1627 * @param {!Array<string>} styleRules
1628 */
1629function installExtraStyleRules(styleRules) {
1630 if (!styleRules.length) {
1631 return;
1632 }
1633 const styleText = styleRules.join('\n');
1634 document.head.appendChild(createStyleElement(styleText));
1635
1636 const origCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
1637 HTMLElement.prototype.createShadowRoot = function(...args) {
1638 const shadowRoot = origCreateShadowRoot.call(this, ...args);
1639 shadowRoot.appendChild(createStyleElement(styleText));
1640 return shadowRoot;
1641 };
1642}
1643
1644/**
1645 * @param {string} styleText
1646 * @return {!Element}
1647 */
1648function createStyleElement(styleText) {
1649 const style = document.createElement('style');
1650 style.textContent = styleText;
1651 return style;
1652}
1653
1654installBackwardsCompatibility();
Blink Reformat4c46d092018-04-07 15:32:371655})(window);