blob: b86b13793a9f8a756687c90eeb105b13aa4e1e5a [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 Somsikov9f18cf62023-09-21 11:43:451011 * @param {InspectorFrontendHostAPI.ChangeEvent} changeEvent
1012 */
1013 recordChange(changeEvent) {
Danil Somsikov609b5862023-10-16 11:16:341014 DevToolsAPI.sendMessageToEmbedder('recordChange', [changeEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:451015 }
1016
1017 /**
1018 * @override
1019 * @param {InspectorFrontendHostAPI.KeyDownEvent} keyDownEvent
1020 */
1021 recordKeyDown(keyDownEvent) {
Danil Somsikov609b5862023-10-16 11:16:341022 DevToolsAPI.sendMessageToEmbedder('recordKeyDown', [keyDownEvent], null);
Danil Somsikov9f18cf62023-09-21 11:43:451023 }
1024
Nikolay Vitkov42be2662023-01-12 15:32:351025 // Backward-compatible methods below this line --------------------------------------------
1026
1027 /**
1028 * Support for legacy front-ends (<M65).
1029 * @return {boolean}
1030 */
1031 isUnderTest() {
1032 return false;
1033 }
1034
1035 /**
1036 * Support for legacy front-ends (<M50).
1037 * @param {string} message
1038 */
1039 sendFrontendAPINotification(message) {
1040 }
1041
1042 /**
1043 * Support for legacy front-ends (<M41).
1044 * @return {string}
1045 */
1046 port() {
1047 return 'unknown';
1048 }
1049
1050 /**
1051 * Support for legacy front-ends (<M38).
1052 * @param {number} zoomFactor
1053 */
1054 setZoomFactor(zoomFactor) {
1055 }
1056
1057 /**
1058 * Support for legacy front-ends (<M34).
1059 */
1060 sendMessageToEmbedder() {
1061 }
1062
1063 /**
1064 * Support for legacy front-ends (<M34).
1065 * @param {string} dockSide
1066 */
1067 requestSetDockSide(dockSide) {
1068 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [dockSide !== 'undocked'], null);
1069 }
1070
1071 /**
1072 * Support for legacy front-ends (<M34).
1073 * @return {boolean}
1074 */
1075 supportsFileSystems() {
1076 return true;
1077 }
1078
1079 /**
1080 * Support for legacy front-ends (<M44).
1081 * @param {number} actionCode
1082 */
1083 recordActionTaken(actionCode) {
1084 // Do not record actions, as that may crash the DevTools renderer.
1085 }
1086
1087 /**
1088 * Support for legacy front-ends (<M44).
1089 * @param {number} panelCode
1090 */
1091 recordPanelShown(panelCode) {
1092 // Do not record actions, as that may crash the DevTools renderer.
1093 }
1094
1095 /**
1096 * @return {!Promise<string>}
1097 */
1098 initialTargetId() {
1099 return DevToolsAPI._initialTargetIdPromise;
1100 }
Alex Rudenko13d80cf2023-08-24 12:46:561101
1102 /**
1103 * @param {string} request
1104 * @param {function(!InspectorFrontendHostAPI.DoAidaConversationResult): void} cb
1105 */
1106 doAidaConversation(request, cb) {
1107 DevToolsAPI.sendMessageToEmbedder('doAidaConversation', [request], cb);
1108 }
Nikolay Vitkov42be2662023-01-12 15:32:351109};
1110
1111window.InspectorFrontendHost = new InspectorFrontendHostImpl();
1112
1113// DevToolsApp ---------------------------------------------------------------
1114
1115function installObjectObserve() {
1116 /** @type {!Array<string>} */
1117 const properties = [
1118 'advancedSearchConfig',
1119 'auditsPanelSplitViewState',
1120 'auditsSidebarWidth',
1121 'blockedURLs',
1122 'breakpoints',
1123 'cacheDisabled',
1124 'colorFormat',
1125 'consoleHistory',
1126 'consoleTimestampsEnabled',
1127 'cpuProfilerView',
1128 'cssSourceMapsEnabled',
1129 'currentDockState',
1130 'customColorPalette',
1131 'customDevicePresets',
1132 'customEmulatedDeviceList',
1133 'customFormatters',
1134 'customUserAgent',
1135 'databaseTableViewVisibleColumns',
1136 'dataGrid-cookiesTable',
1137 'dataGrid-DOMStorageItemsView',
1138 'debuggerSidebarHidden',
1139 'disablePausedStateOverlay',
1140 'domBreakpoints',
1141 'domWordWrap',
1142 'elementsPanelSplitViewState',
1143 'elementsSidebarWidth',
1144 'emulation.deviceHeight',
1145 'emulation.deviceModeValue',
1146 'emulation.deviceOrientationOverride',
1147 'emulation.deviceScale',
1148 'emulation.deviceScaleFactor',
1149 'emulation.deviceUA',
1150 'emulation.deviceWidth',
1151 'emulation.locationOverride',
1152 'emulation.showDeviceMode',
1153 'emulation.showRulers',
1154 'enableAsyncStackTraces',
1155 'enableIgnoreListing',
1156 'eventListenerBreakpoints',
1157 'fileMappingEntries',
1158 'fileSystemMapping',
1159 'FileSystemViewSidebarWidth',
1160 'fileSystemViewSplitViewState',
1161 'filterBar-consoleView',
1162 'filterBar-networkPanel',
1163 'filterBar-promisePane',
1164 'filterBar-timelinePanel',
1165 'frameViewerHideChromeWindow',
1166 'heapSnapshotRetainersViewSize',
1167 'heapSnapshotSplitViewState',
1168 'hideCollectedPromises',
1169 'hideNetworkMessages',
1170 'highlightNodeOnHoverInOverlay',
1171 'inlineVariableValues',
1172 'Inspector.drawerSplitView',
1173 'Inspector.drawerSplitViewState',
1174 'InspectorView.panelOrder',
1175 'InspectorView.screencastSplitView',
1176 'InspectorView.screencastSplitViewState',
1177 'InspectorView.splitView',
1178 'InspectorView.splitViewState',
1179 'javaScriptDisabled',
1180 'jsSourceMapsEnabled',
1181 'lastActivePanel',
1182 'lastDockState',
1183 'lastSelectedSourcesSidebarPaneTab',
1184 'lastSnippetEvaluationIndex',
1185 'layerDetailsSplitView',
1186 'layerDetailsSplitViewState',
1187 'layersPanelSplitViewState',
1188 'layersShowInternalLayers',
1189 'layersSidebarWidth',
1190 'messageLevelFilters',
1191 'messageURLFilters',
1192 'monitoringXHREnabled',
1193 'navigatorGroupByAuthored',
1194 'navigatorGroupByFolder',
1195 'navigatorHidden',
1196 'networkColorCodeResourceTypes',
1197 'networkConditions',
1198 'networkConditionsCustomProfiles',
1199 'networkHideDataURL',
1200 'networkLogColumnsVisibility',
1201 'networkLogLargeRows',
1202 'networkLogShowOverview',
1203 'networkPanelSplitViewState',
1204 'networkRecordFilmStripSetting',
1205 'networkResourceTypeFilters',
1206 'networkShowPrimaryLoadWaterfall',
1207 'networkSidebarWidth',
1208 'openLinkHandler',
1209 'pauseOnUncaughtException',
1210 'pauseOnCaughtException',
1211 'pauseOnExceptionEnabled',
1212 'preserveConsoleLog',
1213 'prettyPrintInfobarDisabled',
1214 'previouslyViewedFiles',
1215 'profilesPanelSplitViewState',
1216 'profilesSidebarWidth',
1217 'promiseStatusFilters',
1218 'recordAllocationStacks',
1219 'requestHeaderFilterSetting',
1220 'request-info-formData-category-expanded',
1221 'request-info-general-category-expanded',
1222 'request-info-queryString-category-expanded',
1223 'request-info-requestHeaders-category-expanded',
1224 'request-info-requestPayload-category-expanded',
1225 'request-info-responseHeaders-category-expanded',
1226 'resources',
1227 'resourcesLastSelectedItem',
1228 'resourcesPanelSplitViewState',
1229 'resourcesSidebarWidth',
1230 'resourceViewTab',
1231 'savedURLs',
1232 'screencastEnabled',
1233 'scriptsPanelNavigatorSidebarWidth',
1234 'searchInContentScripts',
1235 'selectedAuditCategories',
1236 'selectedColorPalette',
1237 'selectedProfileType',
1238 'shortcutPanelSwitch',
1239 'showAdvancedHeapSnapshotProperties',
1240 'showEventListenersForAncestors',
1241 'showFrameowkrListeners',
1242 'showHeaSnapshotObjectsHiddenProperties',
1243 'showInheritedComputedStyleProperties',
1244 'showMediaQueryInspector',
Nikolay Vitkov42be2662023-01-12 15:32:351245 'showUAShadowDOM',
1246 'showWhitespacesInEditor',
1247 'sidebarPosition',
1248 'skipContentScripts',
1249 'automaticallyIgnoreListKnownThirdPartyScripts',
1250 'skipStackFramesPattern',
1251 'sourceMapInfobarDisabled',
Eric Leeseff8a2a52023-07-11 14:02:281252 'sourceMapSkippedInfobarDisabled',
Nikolay Vitkov42be2662023-01-12 15:32:351253 'sourcesPanelDebuggerSidebarSplitViewState',
1254 'sourcesPanelNavigatorSplitViewState',
1255 'sourcesPanelSplitSidebarRatio',
1256 'sourcesPanelSplitViewState',
1257 'sourcesSidebarWidth',
1258 'standardEmulatedDeviceList',
1259 'StylesPaneSplitRatio',
1260 'stylesPaneSplitViewState',
1261 'textEditorAutocompletion',
1262 'textEditorAutoDetectIndent',
1263 'textEditorBracketMatching',
1264 'textEditorIndent',
1265 'textEditorTabMovesFocus',
1266 'timelineCaptureFilmStrip',
1267 'timelineCaptureLayersAndPictures',
1268 'timelineCaptureMemory',
1269 'timelineCaptureNetwork',
1270 'timeline-details',
1271 'timelineEnableJSSampling',
1272 'timelineOverviewMode',
1273 'timelinePanelDetailsSplitViewState',
1274 'timelinePanelRecorsSplitViewState',
1275 'timelinePanelTimelineStackSplitViewState',
1276 'timelinePerspective',
1277 'timeline-split',
1278 'timelineTreeGroupBy',
1279 'timeline-view',
1280 'timelineViewMode',
1281 'uiTheme',
1282 'watchExpressions',
1283 'WebInspector.Drawer.lastSelectedView',
1284 'WebInspector.Drawer.showOnLoad',
1285 'workspaceExcludedFolders',
1286 'workspaceFolderExcludePattern',
1287 'workspaceInfobarDisabled',
1288 'workspaceMappingInfobarDisabled',
1289 'xhrBreakpoints'
1290 ];
1291
1292 /**
1293 * @this {!{_storage: Object, _name: string}}
1294 */
1295 function settingRemove() {
1296 this._storage[this._name] = undefined;
1297 }
1298
1299 /**
1300 * @param {!Object} object
1301 * @param {function(!Array<!{name: string}>)} observer
1302 */
1303 function objectObserve(object, observer) {
1304 if (window['WebInspector']) {
1305 const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
1306 if (typeof settingPrototype['remove'] === 'function') {
1307 settingPrototype['remove'] = settingRemove;
1308 }
1309 }
1310 /** @type {!Set<string>} */
1311 const changedProperties = new Set();
1312 let scheduled = false;
1313
1314 function scheduleObserver() {
1315 if (scheduled) {
1316 return;
1317 }
1318 scheduled = true;
1319 queueMicrotask(callObserver);
1320 }
1321
1322 function callObserver() {
1323 scheduled = false;
1324 const changes = /** @type {!Array<!{name: string}>} */ ([]);
1325 changedProperties.forEach(function(name) {
1326 changes.push({name: name});
1327 });
1328 changedProperties.clear();
1329 observer.call(null, changes);
1330 }
1331
1332 /** @type {!Map<string, *>} */
1333 const storage = new Map();
1334
1335 /**
1336 * @param {string} property
1337 */
1338 function defineProperty(property) {
1339 if (property in object) {
1340 storage.set(property, object[property]);
1341 delete object[property];
1342 }
1343
1344 Object.defineProperty(object, property, {
Blink Reformat4c46d092018-04-07 15:32:371345 /**
Nikolay Vitkov42be2662023-01-12 15:32:351346 * @return {*}
Blink Reformat4c46d092018-04-07 15:32:371347 */
1348 get: function() {
Nikolay Vitkov42be2662023-01-12 15:32:351349 return storage.get(property);
1350 },
1351
1352 /**
1353 * @param {*} value
1354 */
1355 set: function(value) {
1356 storage.set(property, value);
1357 changedProperties.add(property);
1358 scheduleObserver();
Blink Reformat4c46d092018-04-07 15:32:371359 }
1360 });
1361 }
1362
Nikolay Vitkov42be2662023-01-12 15:32:351363 for (let i = 0; i < properties.length; ++i) {
1364 defineProperty(properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341365 }
Joel Einbinderf55cc942018-10-30 01:59:531366 }
Blink Reformat4c46d092018-04-07 15:32:371367
Nikolay Vitkov42be2662023-01-12 15:32:351368 window.Object.observe = objectObserve;
1369}
1370
1371/** @type {!Map<number, string>} */
1372const staticKeyIdentifiers = new Map([
1373 [0x12, 'Alt'],
1374 [0x11, 'Control'],
1375 [0x10, 'Shift'],
1376 [0x14, 'CapsLock'],
1377 [0x5b, 'Win'],
1378 [0x5c, 'Win'],
1379 [0x0c, 'Clear'],
1380 [0x28, 'Down'],
1381 [0x23, 'End'],
1382 [0x0a, 'Enter'],
1383 [0x0d, 'Enter'],
1384 [0x2b, 'Execute'],
1385 [0x70, 'F1'],
1386 [0x71, 'F2'],
1387 [0x72, 'F3'],
1388 [0x73, 'F4'],
1389 [0x74, 'F5'],
1390 [0x75, 'F6'],
1391 [0x76, 'F7'],
1392 [0x77, 'F8'],
1393 [0x78, 'F9'],
1394 [0x79, 'F10'],
1395 [0x7a, 'F11'],
1396 [0x7b, 'F12'],
1397 [0x7c, 'F13'],
1398 [0x7d, 'F14'],
1399 [0x7e, 'F15'],
1400 [0x7f, 'F16'],
1401 [0x80, 'F17'],
1402 [0x81, 'F18'],
1403 [0x82, 'F19'],
1404 [0x83, 'F20'],
1405 [0x84, 'F21'],
1406 [0x85, 'F22'],
1407 [0x86, 'F23'],
1408 [0x87, 'F24'],
1409 [0x2f, 'Help'],
1410 [0x24, 'Home'],
1411 [0x2d, 'Insert'],
1412 [0x25, 'Left'],
1413 [0x22, 'PageDown'],
1414 [0x21, 'PageUp'],
1415 [0x13, 'Pause'],
1416 [0x2c, 'PrintScreen'],
1417 [0x27, 'Right'],
1418 [0x91, 'Scroll'],
1419 [0x29, 'Select'],
1420 [0x26, 'Up'],
1421 [0x2e, 'U+007F'], // Standard says that DEL becomes U+007F.
1422 [0xb0, 'MediaNextTrack'],
1423 [0xb1, 'MediaPreviousTrack'],
1424 [0xb2, 'MediaStop'],
1425 [0xb3, 'MediaPlayPause'],
1426 [0xad, 'VolumeMute'],
1427 [0xae, 'VolumeDown'],
1428 [0xaf, 'VolumeUp'],
1429]);
1430
1431/**
1432 * @param {number} keyCode
1433 * @return {string}
1434 */
1435function keyCodeToKeyIdentifier(keyCode) {
1436 let result = staticKeyIdentifiers.get(keyCode);
1437 if (result !== undefined) {
1438 return result;
1439 }
1440 result = 'U+';
1441 const hexString = keyCode.toString(16).toUpperCase();
1442 for (let i = hexString.length; i < 4; ++i) {
1443 result += '0';
1444 }
1445 result += hexString;
1446 return result;
1447}
1448
1449function installBackwardsCompatibility() {
1450 const majorVersion = getRemoteMajorVersion();
1451 if (!majorVersion) {
1452 return;
1453 }
1454
1455 /** @type {!Array<string>} */
1456 const styleRules = [];
1457 // Shadow DOM V0 polyfill
1458 if (majorVersion <= 73 && !Element.prototype.createShadowRoot) {
1459 Element.prototype.createShadowRoot = function() {
1460 try {
1461 return this.attachShadow({mode: 'open'});
1462 } catch (e) {
1463 // some elements we use to add shadow roots can no
1464 // longer have shadow roots.
1465 const fakeShadowHost = document.createElement('span');
1466 this.appendChild(fakeShadowHost);
1467 fakeShadowHost.className = 'fake-shadow-host';
1468 return fakeShadowHost.createShadowRoot();
Tim van der Lippe1d6e57a2019-09-30 11:55:341469 }
Nikolay Vitkov42be2662023-01-12 15:32:351470 };
1471
1472 const origAdd = DOMTokenList.prototype.add;
1473 DOMTokenList.prototype.add = function(...tokens) {
1474 if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) {
1475 this._myElement.slot = '.' + tokens[0];
1476 }
1477 return origAdd.apply(this, tokens);
1478 };
1479
1480 const origCreateElement = Document.prototype.createElement;
1481 Document.prototype.createElement = function(tagName, ...rest) {
1482 if (tagName === 'content') {
1483 tagName = 'slot';
1484 }
1485 const element = origCreateElement.call(this, tagName, ...rest);
1486 element.classList._myElement = element;
1487 return element;
1488 };
1489
1490 Object.defineProperty(HTMLSlotElement.prototype, 'select', {
1491 set(selector) {
1492 this.name = selector;
1493 }
1494 });
Joel Einbinderf55cc942018-10-30 01:59:531495 }
1496
Nikolay Vitkov42be2662023-01-12 15:32:351497 // Custom Elements V0 polyfill
1498 if (majorVersion <= 73 && !Document.prototype.hasOwnProperty('registerElement')) {
1499 const fakeRegistry = new Map();
1500 Document.prototype.registerElement = function(typeExtension, options) {
1501 const {prototype, extends: localName} = options;
1502 const document = this;
1503 const callback = function() {
1504 const element = document.createElement(localName || typeExtension);
1505 const skip = new Set(['constructor', '__proto__']);
1506 for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
1507 if (skip.has(key)) {
1508 continue;
1509 }
1510 element[key] = prototype[key];
1511 }
1512 element.setAttribute('is', typeExtension);
1513 if (element['createdCallback']) {
1514 element['createdCallback']();
1515 }
1516 return element;
1517 };
1518 fakeRegistry.set(typeExtension, callback);
1519 return callback;
1520 };
Joel Einbinderf55cc942018-10-30 01:59:531521
Nikolay Vitkov42be2662023-01-12 15:32:351522 const origCreateElement = Document.prototype.createElement;
1523 Document.prototype.createElement = function(tagName, fakeCustomElementType) {
1524 const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
1525 if (fakeConstructor) {
1526 return fakeConstructor();
1527 }
1528 return origCreateElement.call(this, tagName, fakeCustomElementType);
1529 };
1530
1531 // DevTools front-ends mistakenly assume that
1532 // classList.toggle('a', undefined) works as
1533 // classList.toggle('a', false) rather than as
1534 // classList.toggle('a');
1535 const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
1536 DOMTokenList.prototype.toggle = function(token, force) {
1537 if (arguments.length === 1) {
1538 force = !this.contains(token);
1539 }
1540 return originalDOMTokenListToggle.call(this, token, Boolean(force));
Joel Einbinderf55cc942018-10-30 01:59:531541 };
1542 }
1543
Nikolay Vitkov42be2662023-01-12 15:32:351544 if (majorVersion <= 66) {
1545 /** @type {(!function(number, number):Element|undefined)} */
1546 ShadowRoot.prototype.__originalShadowRootElementFromPoint;
1547
1548 if (!ShadowRoot.prototype.__originalShadowRootElementFromPoint) {
1549 ShadowRoot.prototype.__originalShadowRootElementFromPoint = ShadowRoot.prototype.elementFromPoint;
1550 /**
1551 * @param {number} x
1552 * @param {number} y
1553 * @return {Element}
1554 */
1555 ShadowRoot.prototype.elementFromPoint = function(x, y) {
1556 const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
1557 if (this.host && originalResult === this.host) {
1558 return null;
1559 }
1560 return originalResult;
1561 };
1562 }
Blink Reformat4c46d092018-04-07 15:32:371563 }
1564
Nikolay Vitkov42be2662023-01-12 15:32:351565 if (majorVersion <= 53) {
1566 Object.defineProperty(window.KeyboardEvent.prototype, 'keyIdentifier', {
1567 /**
1568 * @return {string}
1569 * @this {KeyboardEvent}
1570 */
1571 get: function() {
1572 return keyCodeToKeyIdentifier(this.keyCode);
1573 }
1574 });
1575 }
Blink Reformat4c46d092018-04-07 15:32:371576
Nikolay Vitkov42be2662023-01-12 15:32:351577 if (majorVersion <= 50) {
1578 installObjectObserve();
1579 }
1580
1581 if (majorVersion <= 71) {
1582 styleRules.push(
1583 '.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
1584 }
1585
1586 if (majorVersion <= 50) {
1587 Event.prototype.deepPath = undefined;
1588 }
1589
1590 if (majorVersion <= 54) {
1591 window.FileError = /** @type {!function (new: FileError) : ?} */ ({
1592 NOT_FOUND_ERR: DOMException.NOT_FOUND_ERR,
1593 ABORT_ERR: DOMException.ABORT_ERR,
1594 INVALID_MODIFICATION_ERR: DOMException.INVALID_MODIFICATION_ERR,
1595 NOT_READABLE_ERR: 0 // No matching DOMException, so code will be 0.
1596 });
1597 }
1598
1599 installExtraStyleRules(styleRules);
1600}
1601
1602/**
1603 * @return {?number}
1604 */
1605function getRemoteMajorVersion() {
1606 try {
1607 const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
1608 if (!remoteVersion) {
1609 return null;
1610 }
1611 const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
1612 return majorVersion;
1613 } catch (e) {
1614 return null;
1615 }
1616}
1617
1618/**
1619 * @param {!Array<string>} styleRules
1620 */
1621function installExtraStyleRules(styleRules) {
1622 if (!styleRules.length) {
1623 return;
1624 }
1625 const styleText = styleRules.join('\n');
1626 document.head.appendChild(createStyleElement(styleText));
1627
1628 const origCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
1629 HTMLElement.prototype.createShadowRoot = function(...args) {
1630 const shadowRoot = origCreateShadowRoot.call(this, ...args);
1631 shadowRoot.appendChild(createStyleElement(styleText));
1632 return shadowRoot;
1633 };
1634}
1635
1636/**
1637 * @param {string} styleText
1638 * @return {!Element}
1639 */
1640function createStyleElement(styleText) {
1641 const style = document.createElement('style');
1642 style.textContent = styleText;
1643 return style;
1644}
1645
1646installBackwardsCompatibility();
Blink Reformat4c46d092018-04-07 15:32:371647})(window);