blob: 815a5da2d1110051e6ca44f2d1fb6d858c1d5be8 [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
7 // DevToolsAPI ----------------------------------------------------------------
8
9 /**
10 * @unrestricted
11 */
12 const DevToolsAPIImpl = class {
13 constructor() {
14 /**
15 * @type {number}
16 */
17 this._lastCallId = 0;
18
19 /**
20 * @type {!Object.<number, function(?Object)>}
21 */
22 this._callbacks = {};
Jeff Fisherac799a52019-06-25 21:47:0623
24 /**
25 * @type {!Array.<!ExtensionDescriptor>}
26 */
27 this._pendingExtensionDescriptors = [];
28
29 /**
30 * @type {?function(!ExtensionDescriptor)}
31 */
32 this._addExtensionCallback = null;
Blink Reformat4c46d092018-04-07 15:32:3733 }
34
35 /**
36 * @param {number} id
37 * @param {?Object} arg
38 */
39 embedderMessageAck(id, arg) {
40 const callback = this._callbacks[id];
41 delete this._callbacks[id];
Tim van der Lippe1d6e57a2019-09-30 11:55:3442 if (callback) {
Blink Reformat4c46d092018-04-07 15:32:3743 callback(arg);
Tim van der Lippe1d6e57a2019-09-30 11:55:3444 }
Blink Reformat4c46d092018-04-07 15:32:3745 }
46
47 /**
48 * @param {string} method
49 * @param {!Array.<*>} args
50 * @param {?function(?Object)} callback
51 */
52 sendMessageToEmbedder(method, args, callback) {
53 const callId = ++this._lastCallId;
Tim van der Lippe1d6e57a2019-09-30 11:55:3454 if (callback) {
Blink Reformat4c46d092018-04-07 15:32:3755 this._callbacks[callId] = callback;
Tim van der Lippe1d6e57a2019-09-30 11:55:3456 }
Blink Reformat4c46d092018-04-07 15:32:3757 const message = {'id': callId, 'method': method};
Tim van der Lippe1d6e57a2019-09-30 11:55:3458 if (args.length) {
Blink Reformat4c46d092018-04-07 15:32:3759 message.params = args;
Tim van der Lippe1d6e57a2019-09-30 11:55:3460 }
Blink Reformat4c46d092018-04-07 15:32:3761 DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
62 }
63
64 /**
65 * @param {string} method
66 * @param {!Array<*>} args
67 */
68 _dispatchOnInspectorFrontendAPI(method, args) {
69 const inspectorFrontendAPI = /** @type {!Object<string, function()>} */ (window['InspectorFrontendAPI']);
70 inspectorFrontendAPI[method].apply(inspectorFrontendAPI, args);
71 }
72
73 // API methods below this line --------------------------------------------
74
75 /**
76 * @param {!Array.<!ExtensionDescriptor>} extensions
77 */
78 addExtensions(extensions) {
79 // Support for legacy front-ends (<M41).
80 if (window['WebInspector'] && window['WebInspector']['addExtensions']) {
81 window['WebInspector']['addExtensions'](extensions);
Jeff Fisherac799a52019-06-25 21:47:0682 } else {
Blink Reformat4c46d092018-04-07 15:32:3783 // The addExtensions command is sent as the onload event happens for
Jeff Fisherac799a52019-06-25 21:47:0684 // DevTools front-end. We should buffer this command until the frontend
85 // is ready for it.
Tim van der Lippe1d6e57a2019-09-30 11:55:3486 if (this._addExtensionCallback) {
Jeff Fisherac799a52019-06-25 21:47:0687 extensions.forEach(this._addExtensionCallback);
Tim van der Lippe1d6e57a2019-09-30 11:55:3488 } else {
Simon Zünd1facecf2020-01-16 08:08:3589 this._pendingExtensionDescriptors.push(...extensions);
Tim van der Lippe1d6e57a2019-09-30 11:55:3490 }
Blink Reformat4c46d092018-04-07 15:32:3791 }
92 }
93
94 /**
95 * @param {string} url
96 */
97 appendedToURL(url) {
98 this._dispatchOnInspectorFrontendAPI('appendedToURL', [url]);
99 }
100
101 /**
102 * @param {string} url
103 */
104 canceledSaveURL(url) {
105 this._dispatchOnInspectorFrontendAPI('canceledSaveURL', [url]);
106 }
107
108 contextMenuCleared() {
109 this._dispatchOnInspectorFrontendAPI('contextMenuCleared', []);
110 }
111
112 /**
113 * @param {string} id
114 */
115 contextMenuItemSelected(id) {
116 this._dispatchOnInspectorFrontendAPI('contextMenuItemSelected', [id]);
117 }
118
119 /**
120 * @param {number} count
121 */
122 deviceCountUpdated(count) {
123 this._dispatchOnInspectorFrontendAPI('deviceCountUpdated', [count]);
124 }
125
126 /**
127 * @param {!Adb.Config} config
128 */
129 devicesDiscoveryConfigChanged(config) {
130 this._dispatchOnInspectorFrontendAPI('devicesDiscoveryConfigChanged', [config]);
131 }
132
133 /**
134 * @param {!Adb.PortForwardingStatus} status
135 */
136 devicesPortForwardingStatusChanged(status) {
137 this._dispatchOnInspectorFrontendAPI('devicesPortForwardingStatusChanged', [status]);
138 }
139
140 /**
141 * @param {!Array.<!Adb.Device>} devices
142 */
143 devicesUpdated(devices) {
144 this._dispatchOnInspectorFrontendAPI('devicesUpdated', [devices]);
145 }
146
147 /**
148 * @param {string} message
149 */
150 dispatchMessage(message) {
151 this._dispatchOnInspectorFrontendAPI('dispatchMessage', [message]);
152 }
153
154 /**
155 * @param {string} messageChunk
156 * @param {number} messageSize
157 */
158 dispatchMessageChunk(messageChunk, messageSize) {
159 this._dispatchOnInspectorFrontendAPI('dispatchMessageChunk', [messageChunk, messageSize]);
160 }
161
162 enterInspectElementMode() {
163 this._dispatchOnInspectorFrontendAPI('enterInspectElementMode', []);
164 }
165
166 /**
167 * @param {!{r: number, g: number, b: number, a: number}} color
168 */
169 eyeDropperPickedColor(color) {
170 this._dispatchOnInspectorFrontendAPI('eyeDropperPickedColor', [color]);
171 }
172
173 /**
174 * @param {!Array.<!{fileSystemName: string, rootURL: string, fileSystemPath: string}>} fileSystems
175 */
176 fileSystemsLoaded(fileSystems) {
177 this._dispatchOnInspectorFrontendAPI('fileSystemsLoaded', [fileSystems]);
178 }
179
180 /**
181 * @param {string} fileSystemPath
182 */
183 fileSystemRemoved(fileSystemPath) {
184 this._dispatchOnInspectorFrontendAPI('fileSystemRemoved', [fileSystemPath]);
185 }
186
187 /**
188 * @param {?string} error
189 * @param {?{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} fileSystem
190 */
191 fileSystemAdded(error, fileSystem) {
192 this._dispatchOnInspectorFrontendAPI('fileSystemAdded', [error, fileSystem]);
193 }
194
195 /**
196 * @param {!Array<string>} changedPaths
197 * @param {!Array<string>} addedPaths
198 * @param {!Array<string>} removedPaths
199 */
200 fileSystemFilesChangedAddedRemoved(changedPaths, addedPaths, removedPaths) {
201 // Support for legacy front-ends (<M58)
202 if (window['InspectorFrontendAPI'] && window['InspectorFrontendAPI']['fileSystemFilesChanged']) {
203 this._dispatchOnInspectorFrontendAPI(
204 'fileSystemFilesChanged', [changedPaths.concat(addedPaths).concat(removedPaths)]);
205 } else {
206 this._dispatchOnInspectorFrontendAPI(
207 'fileSystemFilesChangedAddedRemoved', [changedPaths, addedPaths, removedPaths]);
208 }
209 }
210
211 /**
212 * @param {number} requestId
213 * @param {string} fileSystemPath
214 * @param {number} totalWork
215 */
216 indexingTotalWorkCalculated(requestId, fileSystemPath, totalWork) {
217 this._dispatchOnInspectorFrontendAPI('indexingTotalWorkCalculated', [requestId, fileSystemPath, totalWork]);
218 }
219
220 /**
221 * @param {number} requestId
222 * @param {string} fileSystemPath
223 * @param {number} worked
224 */
225 indexingWorked(requestId, fileSystemPath, worked) {
226 this._dispatchOnInspectorFrontendAPI('indexingWorked', [requestId, fileSystemPath, worked]);
227 }
228
229 /**
230 * @param {number} requestId
231 * @param {string} fileSystemPath
232 */
233 indexingDone(requestId, fileSystemPath) {
234 this._dispatchOnInspectorFrontendAPI('indexingDone', [requestId, fileSystemPath]);
235 }
236
237 /**
238 * @param {{type: string, key: string, code: string, keyCode: number, modifiers: number}} event
239 */
240 keyEventUnhandled(event) {
241 event.keyIdentifier = keyCodeToKeyIdentifier(event.keyCode);
242 this._dispatchOnInspectorFrontendAPI('keyEventUnhandled', [event]);
243 }
244
245 /**
Jeff Fisherac799a52019-06-25 21:47:06246 * @param {function(!ExtensionDescriptor)} callback
247 */
248 setAddExtensionCallback(callback) {
249 this._addExtensionCallback = callback;
250 if (this._pendingExtensionDescriptors.length) {
251 this._pendingExtensionDescriptors.forEach(this._addExtensionCallback);
252 this._pendingExtensionDescriptors = [];
253 }
254 }
255
Adithya Srinivasan7a133d22019-10-09 00:27:48256 reattachMainTarget() {
257 this._dispatchOnInspectorFrontendAPI('reattachMainTarget', []);
258 }
259
Jeff Fisherac799a52019-06-25 21:47:06260 /**
Blink Reformat4c46d092018-04-07 15:32:37261 * @param {boolean} hard
262 */
263 reloadInspectedPage(hard) {
264 this._dispatchOnInspectorFrontendAPI('reloadInspectedPage', [hard]);
265 }
266
267 /**
268 * @param {string} url
269 * @param {number} lineNumber
270 * @param {number} columnNumber
271 */
272 revealSourceLine(url, lineNumber, columnNumber) {
273 this._dispatchOnInspectorFrontendAPI('revealSourceLine', [url, lineNumber, columnNumber]);
274 }
275
276 /**
277 * @param {string} url
278 * @param {string=} fileSystemPath
279 */
280 savedURL(url, fileSystemPath) {
281 this._dispatchOnInspectorFrontendAPI('savedURL', [url, fileSystemPath]);
282 }
283
284 /**
285 * @param {number} requestId
286 * @param {string} fileSystemPath
287 * @param {!Array.<string>} files
288 */
289 searchCompleted(requestId, fileSystemPath, files) {
290 this._dispatchOnInspectorFrontendAPI('searchCompleted', [requestId, fileSystemPath, files]);
291 }
292
293 /**
294 * @param {string} tabId
295 */
296 setInspectedTabId(tabId) {
Tim van der Lippe647e33b2019-11-04 19:02:31297 this._inspectedTabIdValue = tabId;
298
Blink Reformat4c46d092018-04-07 15:32:37299 // Support for legacy front-ends (<M41).
Tim van der Lippe1d6e57a2019-09-30 11:55:34300 if (window['WebInspector'] && window['WebInspector']['setInspectedTabId']) {
Blink Reformat4c46d092018-04-07 15:32:37301 window['WebInspector']['setInspectedTabId'](tabId);
Tim van der Lippe1d6e57a2019-09-30 11:55:34302 } else {
Blink Reformat4c46d092018-04-07 15:32:37303 this._dispatchOnInspectorFrontendAPI('setInspectedTabId', [tabId]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34304 }
Blink Reformat4c46d092018-04-07 15:32:37305 }
306
307 /**
Tim van der Lippe647e33b2019-11-04 19:02:31308 * @return {string|undefined}
309 */
310 getInspectedTabId() {
311 return this._inspectedTabIdValue;
312 }
313
314 /**
Blink Reformat4c46d092018-04-07 15:32:37315 * @param {boolean} useSoftMenu
316 */
317 setUseSoftMenu(useSoftMenu) {
318 this._dispatchOnInspectorFrontendAPI('setUseSoftMenu', [useSoftMenu]);
319 }
320
321 /**
322 * @param {string} panelName
323 */
324 showPanel(panelName) {
325 this._dispatchOnInspectorFrontendAPI('showPanel', [panelName]);
326 }
327
328 /**
329 * @param {number} id
330 * @param {string} chunk
331 * @param {boolean} encoded
332 */
333 streamWrite(id, chunk, encoded) {
334 this._dispatchOnInspectorFrontendAPI('streamWrite', [id, encoded ? this._decodeBase64(chunk) : chunk]);
335 }
336
337 /**
338 * @param {string} chunk
339 * @return {string}
340 */
341 _decodeBase64(chunk) {
342 const request = new XMLHttpRequest();
343 request.open('GET', 'data:text/plain;base64,' + chunk, false);
344 request.send(null);
345 if (request.status === 200) {
346 return request.responseText;
Blink Reformat4c46d092018-04-07 15:32:37347 }
Mathias Bynensf06e8c02020-02-28 13:58:28348 console.error('Error while decoding chunk in streamWrite');
349 return '';
Blink Reformat4c46d092018-04-07 15:32:37350 }
351 };
352
353 const DevToolsAPI = new DevToolsAPIImpl();
354 window.DevToolsAPI = DevToolsAPI;
355
356 // InspectorFrontendHostImpl --------------------------------------------------
357
358 /**
Sigurd Schneiderf8d81c42020-07-02 07:32:58359 * Enum for recordPerformanceHistogram
360 * Warning: There are three definitions of this enum in the DevTools code base, keep them in sync.
361 * @readonly
362 * @enum {string}
363 */
364 const EnumeratedHistogram = {
365 ActionTaken: 'DevTools.ActionTaken',
Jose Leal Chapa1e1d9582020-07-30 18:39:25366 PanelClosed: 'DevTools.PanelClosed',
Sigurd Schneiderf8d81c42020-07-02 07:32:58367 PanelShown: 'DevTools.PanelShown',
368 KeyboardShortcutFired: 'DevTools.KeyboardShortcutFired',
369 IssuesPanelOpenedFrom: 'DevTools.IssuesPanelOpenedFrom',
370 KeybindSetSettingChanged: 'DevTools.KeybindSetSettingChanged',
371 DualScreenDeviceEmulated: 'DevTools.DualScreenDeviceEmulated',
Brandon Goddarded914d12020-07-20 22:30:41372 CSSGridSettings: 'DevTools.CSSGridSettings',
Sigurd Schneiderf8d81c42020-07-02 07:32:58373 };
374
375 /**
Blink Reformat4c46d092018-04-07 15:32:37376 * @implements {InspectorFrontendHostAPI}
377 * @unrestricted
378 */
379 const InspectorFrontendHostImpl = class {
380 /**
Blink Reformat4c46d092018-04-07 15:32:37381 * @return {string}
382 */
383 getSelectionBackgroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02384 return '#6e86ff';
Blink Reformat4c46d092018-04-07 15:32:37385 }
386
387 /**
Blink Reformat4c46d092018-04-07 15:32:37388 * @return {string}
389 */
390 getSelectionForegroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02391 return '#ffffff';
Blink Reformat4c46d092018-04-07 15:32:37392 }
393
394 /**
Blink Reformat4c46d092018-04-07 15:32:37395 * @return {string}
396 */
397 getInactiveSelectionBackgroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02398 return '#c9c8c8';
Blink Reformat4c46d092018-04-07 15:32:37399 }
400
401 /**
Blink Reformat4c46d092018-04-07 15:32:37402 * @return {string}
403 */
404 getInactiveSelectionForegroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02405 return '#323232';
Blink Reformat4c46d092018-04-07 15:32:37406 }
407
408 /**
409 * @override
410 * @return {string}
411 */
412 platform() {
413 return DevToolsHost.platform();
414 }
415
416 /**
417 * @override
418 */
419 loadCompleted() {
420 DevToolsAPI.sendMessageToEmbedder('loadCompleted', [], null);
421 // Support for legacy (<57) frontends.
422 if (window.Runtime && window.Runtime.queryParam) {
423 const panelToOpen = window.Runtime.queryParam('panel');
Tim van der Lippe1d6e57a2019-09-30 11:55:34424 if (panelToOpen) {
Blink Reformat4c46d092018-04-07 15:32:37425 window.DevToolsAPI.showPanel(panelToOpen);
Tim van der Lippe1d6e57a2019-09-30 11:55:34426 }
Blink Reformat4c46d092018-04-07 15:32:37427 }
428 }
429
430 /**
431 * @override
432 */
433 bringToFront() {
434 DevToolsAPI.sendMessageToEmbedder('bringToFront', [], null);
435 }
436
437 /**
438 * @override
439 */
440 closeWindow() {
441 DevToolsAPI.sendMessageToEmbedder('closeWindow', [], null);
442 }
443
444 /**
445 * @override
446 * @param {boolean} isDocked
447 * @param {function()} callback
448 */
449 setIsDocked(isDocked, callback) {
450 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [isDocked], callback);
451 }
452
453 /**
454 * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
455 * @override
456 * @param {{x: number, y: number, width: number, height: number}} bounds
457 */
458 setInspectedPageBounds(bounds) {
459 DevToolsAPI.sendMessageToEmbedder('setInspectedPageBounds', [bounds], null);
460 }
461
462 /**
463 * @override
464 */
465 inspectElementCompleted() {
466 DevToolsAPI.sendMessageToEmbedder('inspectElementCompleted', [], null);
467 }
468
469 /**
470 * @override
471 * @param {string} url
472 * @param {string} headers
473 * @param {number} streamId
474 * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
475 */
476 loadNetworkResource(url, headers, streamId, callback) {
477 DevToolsAPI.sendMessageToEmbedder(
478 'loadNetworkResource', [url, headers, streamId], /** @type {function(?Object)} */ (callback));
479 }
480
481 /**
482 * @override
483 * @param {function(!Object<string, string>)} callback
484 */
485 getPreferences(callback) {
486 DevToolsAPI.sendMessageToEmbedder('getPreferences', [], /** @type {function(?Object)} */ (callback));
487 }
488
489 /**
490 * @override
491 * @param {string} name
492 * @param {string} value
493 */
494 setPreference(name, value) {
495 DevToolsAPI.sendMessageToEmbedder('setPreference', [name, value], null);
496 }
497
498 /**
499 * @override
500 * @param {string} name
501 */
502 removePreference(name) {
503 DevToolsAPI.sendMessageToEmbedder('removePreference', [name], null);
504 }
505
506 /**
507 * @override
508 */
509 clearPreferences() {
510 DevToolsAPI.sendMessageToEmbedder('clearPreferences', [], null);
511 }
512
513 /**
514 * @override
515 * @param {string} origin
516 * @param {string} script
517 */
518 setInjectedScriptForOrigin(origin, script) {
519 DevToolsAPI.sendMessageToEmbedder('registerExtensionsAPI', [origin, script], null);
520 }
521
522 /**
523 * @override
524 * @param {string} url
525 */
526 inspectedURLChanged(url) {
527 DevToolsAPI.sendMessageToEmbedder('inspectedURLChanged', [url], null);
528 }
529
530 /**
531 * @override
532 * @param {string} text
533 */
534 copyText(text) {
535 DevToolsHost.copyText(text);
536 }
537
538 /**
539 * @override
540 * @param {string} url
541 */
542 openInNewTab(url) {
543 DevToolsAPI.sendMessageToEmbedder('openInNewTab', [url], null);
544 }
545
546 /**
547 * @override
548 * @param {string} fileSystemPath
549 */
550 showItemInFolder(fileSystemPath) {
551 DevToolsAPI.sendMessageToEmbedder('showItemInFolder', [fileSystemPath], null);
552 }
553
554 /**
555 * @override
556 * @param {string} url
557 * @param {string} content
558 * @param {boolean} forceSaveAs
559 */
560 save(url, content, forceSaveAs) {
561 DevToolsAPI.sendMessageToEmbedder('save', [url, content, forceSaveAs], null);
562 }
563
564 /**
565 * @override
566 * @param {string} url
567 * @param {string} content
568 */
569 append(url, content) {
570 DevToolsAPI.sendMessageToEmbedder('append', [url, content], null);
571 }
572
573 /**
574 * @override
Pavel Feldmanf1a36ee2018-07-28 16:10:25575 * @param {string} url
576 */
577 close(url) {
578 }
579
580 /**
581 * @override
Blink Reformat4c46d092018-04-07 15:32:37582 * @param {string} message
583 */
584 sendMessageToBackend(message) {
585 DevToolsAPI.sendMessageToEmbedder('dispatchProtocolMessage', [message], null);
586 }
587
588 /**
589 * @override
Sigurd Schneiderf8d81c42020-07-02 07:32:58590 * @param {!InspectorFrontendHostAPI.EnumeratedHistogram} actionName
Blink Reformat4c46d092018-04-07 15:32:37591 * @param {number} actionCode
592 * @param {number} bucketSize
593 */
594 recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
Sigurd Schneiderf8d81c42020-07-02 07:32:58595 if (!Object.values(EnumeratedHistogram).includes(actionName)) {
Blink Reformat4c46d092018-04-07 15:32:37596 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34597 }
Blink Reformat4c46d092018-04-07 15:32:37598 DevToolsAPI.sendMessageToEmbedder('recordEnumeratedHistogram', [actionName, actionCode, bucketSize], null);
599 }
600
601 /**
602 * @override
James Lissiakd2f1a2f2019-03-26 17:36:51603 * @param {string} histogramName
604 * @param {number} duration
605 */
606 recordPerformanceHistogram(histogramName, duration) {
607 DevToolsAPI.sendMessageToEmbedder('recordPerformanceHistogram', [histogramName, duration], null);
608 }
609
610 /**
611 * @override
James Lissiake21c97b2019-04-29 17:36:43612 * @param {string} umaName
613 */
614 recordUserMetricsAction(umaName) {
615 DevToolsAPI.sendMessageToEmbedder('recordUserMetricsAction', [umaName], null);
616 }
617
618 /**
619 * @override
Blink Reformat4c46d092018-04-07 15:32:37620 */
621 requestFileSystems() {
622 DevToolsAPI.sendMessageToEmbedder('requestFileSystems', [], null);
623 }
624
625 /**
626 * @override
627 * @param {string=} type
628 */
629 addFileSystem(type) {
630 DevToolsAPI.sendMessageToEmbedder('addFileSystem', [type || ''], null);
631 }
632
633 /**
634 * @override
635 * @param {string} fileSystemPath
636 */
637 removeFileSystem(fileSystemPath) {
638 DevToolsAPI.sendMessageToEmbedder('removeFileSystem', [fileSystemPath], null);
639 }
640
641 /**
642 * @override
643 * @param {string} fileSystemId
644 * @param {string} registeredName
Tim van der Lipped71c22d2020-03-19 12:29:19645 * @return {?FileSystem}
Blink Reformat4c46d092018-04-07 15:32:37646 */
647 isolatedFileSystem(fileSystemId, registeredName) {
648 return DevToolsHost.isolatedFileSystem(fileSystemId, registeredName);
649 }
650
651 /**
652 * @override
653 * @param {!FileSystem} fileSystem
654 */
655 upgradeDraggedFileSystemPermissions(fileSystem) {
656 DevToolsHost.upgradeDraggedFileSystemPermissions(fileSystem);
657 }
658
659 /**
660 * @override
661 * @param {number} requestId
662 * @param {string} fileSystemPath
663 * @param {string} excludedFolders
664 */
665 indexPath(requestId, fileSystemPath, excludedFolders) {
666 // |excludedFolders| added in M67. For backward compatibility,
667 // pass empty array.
668 excludedFolders = excludedFolders || '[]';
669 DevToolsAPI.sendMessageToEmbedder('indexPath', [requestId, fileSystemPath, excludedFolders], null);
670 }
671
672 /**
673 * @override
674 * @param {number} requestId
675 */
676 stopIndexing(requestId) {
677 DevToolsAPI.sendMessageToEmbedder('stopIndexing', [requestId], null);
678 }
679
680 /**
681 * @override
682 * @param {number} requestId
683 * @param {string} fileSystemPath
684 * @param {string} query
685 */
686 searchInPath(requestId, fileSystemPath, query) {
687 DevToolsAPI.sendMessageToEmbedder('searchInPath', [requestId, fileSystemPath, query], null);
688 }
689
690 /**
691 * @override
692 * @return {number}
693 */
694 zoomFactor() {
695 return DevToolsHost.zoomFactor();
696 }
697
698 /**
699 * @override
700 */
701 zoomIn() {
702 DevToolsAPI.sendMessageToEmbedder('zoomIn', [], null);
703 }
704
705 /**
706 * @override
707 */
708 zoomOut() {
709 DevToolsAPI.sendMessageToEmbedder('zoomOut', [], null);
710 }
711
712 /**
713 * @override
714 */
715 resetZoom() {
716 DevToolsAPI.sendMessageToEmbedder('resetZoom', [], null);
717 }
718
719 /**
720 * @override
721 * @param {string} shortcuts
722 */
723 setWhitelistedShortcuts(shortcuts) {
724 DevToolsAPI.sendMessageToEmbedder('setWhitelistedShortcuts', [shortcuts], null);
725 }
726
727 /**
728 * @override
729 * @param {boolean} active
730 */
731 setEyeDropperActive(active) {
732 DevToolsAPI.sendMessageToEmbedder('setEyeDropperActive', [active], null);
733 }
734
735 /**
736 * @override
737 * @param {!Array<string>} certChain
738 */
739 showCertificateViewer(certChain) {
740 DevToolsAPI.sendMessageToEmbedder('showCertificateViewer', [JSON.stringify(certChain)], null);
741 }
742
743 /**
Connor Clarkca8905e2019-08-23 18:35:10744 * Only needed to run Lighthouse on old devtools.
Blink Reformat4c46d092018-04-07 15:32:37745 * @override
746 * @param {function()} callback
747 */
748 reattach(callback) {
749 DevToolsAPI.sendMessageToEmbedder('reattach', [], callback);
750 }
751
752 /**
753 * @override
754 */
755 readyForTest() {
756 DevToolsAPI.sendMessageToEmbedder('readyForTest', [], null);
757 }
758
759 /**
760 * @override
761 */
762 connectionReady() {
763 DevToolsAPI.sendMessageToEmbedder('connectionReady', [], null);
764 }
765
766 /**
767 * @override
768 * @param {boolean} value
769 */
770 setOpenNewWindowForPopups(value) {
771 DevToolsAPI.sendMessageToEmbedder('setOpenNewWindowForPopups', [value], null);
772 }
773
774 /**
775 * @override
776 * @param {!Adb.Config} config
777 */
778 setDevicesDiscoveryConfig(config) {
779 DevToolsAPI.sendMessageToEmbedder(
780 'setDevicesDiscoveryConfig',
781 [
782 config.discoverUsbDevices, config.portForwardingEnabled, JSON.stringify(config.portForwardingConfig),
783 config.networkDiscoveryEnabled, JSON.stringify(config.networkDiscoveryConfig)
784 ],
785 null);
786 }
787
788 /**
789 * @override
790 * @param {boolean} enabled
791 */
792 setDevicesUpdatesEnabled(enabled) {
793 DevToolsAPI.sendMessageToEmbedder('setDevicesUpdatesEnabled', [enabled], null);
794 }
795
796 /**
797 * @override
798 * @param {string} pageId
799 * @param {string} action
800 */
801 performActionOnRemotePage(pageId, action) {
802 DevToolsAPI.sendMessageToEmbedder('performActionOnRemotePage', [pageId, action], null);
803 }
804
805 /**
806 * @override
807 * @param {string} browserId
808 * @param {string} url
809 */
810 openRemotePage(browserId, url) {
811 DevToolsAPI.sendMessageToEmbedder('openRemotePage', [browserId, url], null);
812 }
813
814 /**
815 * @override
816 */
817 openNodeFrontend() {
818 DevToolsAPI.sendMessageToEmbedder('openNodeFrontend', [], null);
819 }
820
821 /**
822 * @override
823 * @param {number} x
824 * @param {number} y
825 * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
826 * @param {!Document} document
827 */
828 showContextMenuAtPoint(x, y, items, document) {
829 DevToolsHost.showContextMenuAtPoint(x, y, items, document);
830 }
831
832 /**
833 * @override
834 * @return {boolean}
835 */
836 isHostedMode() {
837 return DevToolsHost.isHostedMode();
838 }
839
Jeff Fisherac799a52019-06-25 21:47:06840 /**
841 * @override
842 * @param {function(!ExtensionDescriptor)} callback
843 */
844 setAddExtensionCallback(callback) {
845 DevToolsAPI.setAddExtensionCallback(callback);
846 }
847
Blink Reformat4c46d092018-04-07 15:32:37848 // Backward-compatible methods below this line --------------------------------------------
849
850 /**
851 * Support for legacy front-ends (<M65).
852 * @return {boolean}
853 */
854 isUnderTest() {
855 return false;
856 }
857
858 /**
859 * Support for legacy front-ends (<M50).
860 * @param {string} message
861 */
862 sendFrontendAPINotification(message) {
863 }
864
865 /**
866 * Support for legacy front-ends (<M41).
867 * @return {string}
868 */
869 port() {
870 return 'unknown';
871 }
872
873 /**
874 * Support for legacy front-ends (<M38).
875 * @param {number} zoomFactor
876 */
877 setZoomFactor(zoomFactor) {
878 }
879
880 /**
881 * Support for legacy front-ends (<M34).
882 */
883 sendMessageToEmbedder() {
884 }
885
886 /**
887 * Support for legacy front-ends (<M34).
888 * @param {string} dockSide
889 */
890 requestSetDockSide(dockSide) {
891 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [dockSide !== 'undocked'], null);
892 }
893
894 /**
895 * Support for legacy front-ends (<M34).
896 * @return {boolean}
897 */
898 supportsFileSystems() {
899 return true;
900 }
901
902 /**
Blink Reformat4c46d092018-04-07 15:32:37903 * Support for legacy front-ends (<M44).
904 * @param {number} actionCode
905 */
906 recordActionTaken(actionCode) {
Sigurd Schneider7c3f3a62020-06-30 13:17:44907 // Do not record actions, as that may crash the DevTools renderer.
Blink Reformat4c46d092018-04-07 15:32:37908 }
909
910 /**
911 * Support for legacy front-ends (<M44).
912 * @param {number} panelCode
913 */
914 recordPanelShown(panelCode) {
Sigurd Schneider7c3f3a62020-06-30 13:17:44915 // Do not record actions, as that may crash the DevTools renderer.
Blink Reformat4c46d092018-04-07 15:32:37916 }
917 };
918
919 window.InspectorFrontendHost = new InspectorFrontendHostImpl();
920
921 // DevToolsApp ---------------------------------------------------------------
922
923 function installObjectObserve() {
924 /** @type {!Array<string>} */
925 const properties = [
926 'advancedSearchConfig',
927 'auditsPanelSplitViewState',
928 'auditsSidebarWidth',
929 'blockedURLs',
930 'breakpoints',
931 'cacheDisabled',
932 'colorFormat',
933 'consoleHistory',
934 'consoleTimestampsEnabled',
935 'cpuProfilerView',
936 'cssSourceMapsEnabled',
937 'currentDockState',
938 'customColorPalette',
939 'customDevicePresets',
940 'customEmulatedDeviceList',
941 'customFormatters',
942 'customUserAgent',
943 'databaseTableViewVisibleColumns',
944 'dataGrid-cookiesTable',
945 'dataGrid-DOMStorageItemsView',
946 'debuggerSidebarHidden',
947 'disableDataSaverInfobar',
948 'disablePausedStateOverlay',
949 'domBreakpoints',
950 'domWordWrap',
951 'elementsPanelSplitViewState',
952 'elementsSidebarWidth',
953 'emulation.deviceHeight',
954 'emulation.deviceModeValue',
955 'emulation.deviceOrientationOverride',
956 'emulation.deviceScale',
957 'emulation.deviceScaleFactor',
958 'emulation.deviceUA',
959 'emulation.deviceWidth',
Mathias Bynens4e1cc672020-03-25 06:53:18960 'emulation.locationOverride',
Blink Reformat4c46d092018-04-07 15:32:37961 'emulation.showDeviceMode',
962 'emulation.showRulers',
963 'enableAsyncStackTraces',
964 'eventListenerBreakpoints',
965 'fileMappingEntries',
966 'fileSystemMapping',
967 'FileSystemViewSidebarWidth',
968 'fileSystemViewSplitViewState',
969 'filterBar-consoleView',
970 'filterBar-networkPanel',
971 'filterBar-promisePane',
972 'filterBar-timelinePanel',
973 'frameViewerHideChromeWindow',
974 'heapSnapshotRetainersViewSize',
975 'heapSnapshotSplitViewState',
976 'hideCollectedPromises',
977 'hideNetworkMessages',
978 'highlightNodeOnHoverInOverlay',
Blink Reformat4c46d092018-04-07 15:32:37979 'inlineVariableValues',
980 'Inspector.drawerSplitView',
981 'Inspector.drawerSplitViewState',
982 'InspectorView.panelOrder',
983 'InspectorView.screencastSplitView',
984 'InspectorView.screencastSplitViewState',
985 'InspectorView.splitView',
986 'InspectorView.splitViewState',
987 'javaScriptDisabled',
988 'jsSourceMapsEnabled',
989 'lastActivePanel',
990 'lastDockState',
991 'lastSelectedSourcesSidebarPaneTab',
992 'lastSnippetEvaluationIndex',
993 'layerDetailsSplitView',
994 'layerDetailsSplitViewState',
995 'layersPanelSplitViewState',
996 'layersShowInternalLayers',
997 'layersSidebarWidth',
998 'messageLevelFilters',
999 'messageURLFilters',
1000 'monitoringXHREnabled',
1001 'navigatorGroupByFolder',
1002 'navigatorHidden',
1003 'networkColorCodeResourceTypes',
1004 'networkConditions',
1005 'networkConditionsCustomProfiles',
1006 'networkHideDataURL',
1007 'networkLogColumnsVisibility',
1008 'networkLogLargeRows',
1009 'networkLogShowOverview',
1010 'networkPanelSplitViewState',
1011 'networkRecordFilmStripSetting',
1012 'networkResourceTypeFilters',
1013 'networkShowPrimaryLoadWaterfall',
1014 'networkSidebarWidth',
1015 'openLinkHandler',
1016 'pauseOnCaughtException',
1017 'pauseOnExceptionEnabled',
1018 'preserveConsoleLog',
1019 'prettyPrintInfobarDisabled',
1020 'previouslyViewedFiles',
1021 'profilesPanelSplitViewState',
1022 'profilesSidebarWidth',
1023 'promiseStatusFilters',
1024 'recordAllocationStacks',
1025 'requestHeaderFilterSetting',
1026 'request-info-formData-category-expanded',
1027 'request-info-general-category-expanded',
1028 'request-info-queryString-category-expanded',
1029 'request-info-requestHeaders-category-expanded',
1030 'request-info-requestPayload-category-expanded',
1031 'request-info-responseHeaders-category-expanded',
1032 'resources',
1033 'resourcesLastSelectedItem',
1034 'resourcesPanelSplitViewState',
1035 'resourcesSidebarWidth',
1036 'resourceViewTab',
1037 'savedURLs',
1038 'screencastEnabled',
1039 'scriptsPanelNavigatorSidebarWidth',
1040 'searchInContentScripts',
1041 'selectedAuditCategories',
1042 'selectedColorPalette',
1043 'selectedProfileType',
1044 'shortcutPanelSwitch',
1045 'showAdvancedHeapSnapshotProperties',
1046 'showEventListenersForAncestors',
1047 'showFrameowkrListeners',
1048 'showHeaSnapshotObjectsHiddenProperties',
1049 'showInheritedComputedStyleProperties',
1050 'showMediaQueryInspector',
1051 'showNativeFunctionsInJSProfile',
1052 'showUAShadowDOM',
1053 'showWhitespacesInEditor',
1054 'sidebarPosition',
1055 'skipContentScripts',
1056 'skipStackFramesPattern',
1057 'sourceMapInfobarDisabled',
1058 'sourcesPanelDebuggerSidebarSplitViewState',
1059 'sourcesPanelNavigatorSplitViewState',
1060 'sourcesPanelSplitSidebarRatio',
1061 'sourcesPanelSplitViewState',
1062 'sourcesSidebarWidth',
1063 'standardEmulatedDeviceList',
1064 'StylesPaneSplitRatio',
1065 'stylesPaneSplitViewState',
1066 'textEditorAutocompletion',
1067 'textEditorAutoDetectIndent',
1068 'textEditorBracketMatching',
1069 'textEditorIndent',
Junyi Xiao89142cf2019-04-11 16:01:381070 'textEditorTabMovesFocus',
Blink Reformat4c46d092018-04-07 15:32:371071 'timelineCaptureFilmStrip',
1072 'timelineCaptureLayersAndPictures',
1073 'timelineCaptureMemory',
1074 'timelineCaptureNetwork',
1075 'timeline-details',
1076 'timelineEnableJSSampling',
1077 'timelineOverviewMode',
1078 'timelinePanelDetailsSplitViewState',
1079 'timelinePanelRecorsSplitViewState',
1080 'timelinePanelTimelineStackSplitViewState',
1081 'timelinePerspective',
1082 'timeline-split',
1083 'timelineTreeGroupBy',
1084 'timeline-view',
1085 'timelineViewMode',
1086 'uiTheme',
1087 'watchExpressions',
1088 'WebInspector.Drawer.lastSelectedView',
1089 'WebInspector.Drawer.showOnLoad',
1090 'workspaceExcludedFolders',
1091 'workspaceFolderExcludePattern',
1092 'workspaceInfobarDisabled',
1093 'workspaceMappingInfobarDisabled',
1094 'xhrBreakpoints'
1095 ];
1096
1097 /**
1098 * @this {!{_storage: Object, _name: string}}
1099 */
1100 function settingRemove() {
1101 this._storage[this._name] = undefined;
1102 }
1103
1104 /**
1105 * @param {!Object} object
1106 * @param {function(!Array<!{name: string}>)} observer
1107 */
1108 function objectObserve(object, observer) {
1109 if (window['WebInspector']) {
1110 const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
Tim van der Lippe1d6e57a2019-09-30 11:55:341111 if (typeof settingPrototype['remove'] === 'function') {
Blink Reformat4c46d092018-04-07 15:32:371112 settingPrototype['remove'] = settingRemove;
Tim van der Lippe1d6e57a2019-09-30 11:55:341113 }
Blink Reformat4c46d092018-04-07 15:32:371114 }
1115 /** @type {!Set<string>} */
1116 const changedProperties = new Set();
1117 let scheduled = false;
1118
1119 function scheduleObserver() {
Tim van der Lippe1d6e57a2019-09-30 11:55:341120 if (scheduled) {
Blink Reformat4c46d092018-04-07 15:32:371121 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341122 }
Blink Reformat4c46d092018-04-07 15:32:371123 scheduled = true;
1124 setImmediate(callObserver);
1125 }
1126
1127 function callObserver() {
1128 scheduled = false;
1129 const changes = /** @type {!Array<!{name: string}>} */ ([]);
1130 changedProperties.forEach(function(name) {
1131 changes.push({name: name});
1132 });
1133 changedProperties.clear();
1134 observer.call(null, changes);
1135 }
1136
1137 /** @type {!Map<string, *>} */
1138 const storage = new Map();
1139
1140 /**
1141 * @param {string} property
1142 */
1143 function defineProperty(property) {
1144 if (property in object) {
1145 storage.set(property, object[property]);
1146 delete object[property];
1147 }
1148
1149 Object.defineProperty(object, property, {
1150 /**
1151 * @return {*}
1152 */
1153 get: function() {
1154 return storage.get(property);
1155 },
1156
1157 /**
1158 * @param {*} value
1159 */
1160 set: function(value) {
1161 storage.set(property, value);
1162 changedProperties.add(property);
1163 scheduleObserver();
1164 }
1165 });
1166 }
1167
Tim van der Lippe1d6e57a2019-09-30 11:55:341168 for (let i = 0; i < properties.length; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371169 defineProperty(properties[i]);
Tim van der Lippe1d6e57a2019-09-30 11:55:341170 }
Blink Reformat4c46d092018-04-07 15:32:371171 }
1172
1173 window.Object.observe = objectObserve;
1174 }
1175
1176 /** @type {!Map<number, string>} */
1177 const staticKeyIdentifiers = new Map([
1178 [0x12, 'Alt'],
1179 [0x11, 'Control'],
1180 [0x10, 'Shift'],
1181 [0x14, 'CapsLock'],
1182 [0x5b, 'Win'],
1183 [0x5c, 'Win'],
1184 [0x0c, 'Clear'],
1185 [0x28, 'Down'],
1186 [0x23, 'End'],
1187 [0x0a, 'Enter'],
1188 [0x0d, 'Enter'],
1189 [0x2b, 'Execute'],
1190 [0x70, 'F1'],
1191 [0x71, 'F2'],
1192 [0x72, 'F3'],
1193 [0x73, 'F4'],
1194 [0x74, 'F5'],
1195 [0x75, 'F6'],
1196 [0x76, 'F7'],
1197 [0x77, 'F8'],
1198 [0x78, 'F9'],
1199 [0x79, 'F10'],
1200 [0x7a, 'F11'],
1201 [0x7b, 'F12'],
1202 [0x7c, 'F13'],
1203 [0x7d, 'F14'],
1204 [0x7e, 'F15'],
1205 [0x7f, 'F16'],
1206 [0x80, 'F17'],
1207 [0x81, 'F18'],
1208 [0x82, 'F19'],
1209 [0x83, 'F20'],
1210 [0x84, 'F21'],
1211 [0x85, 'F22'],
1212 [0x86, 'F23'],
1213 [0x87, 'F24'],
1214 [0x2f, 'Help'],
1215 [0x24, 'Home'],
1216 [0x2d, 'Insert'],
1217 [0x25, 'Left'],
1218 [0x22, 'PageDown'],
1219 [0x21, 'PageUp'],
1220 [0x13, 'Pause'],
1221 [0x2c, 'PrintScreen'],
1222 [0x27, 'Right'],
1223 [0x91, 'Scroll'],
1224 [0x29, 'Select'],
1225 [0x26, 'Up'],
1226 [0x2e, 'U+007F'], // Standard says that DEL becomes U+007F.
1227 [0xb0, 'MediaNextTrack'],
1228 [0xb1, 'MediaPreviousTrack'],
1229 [0xb2, 'MediaStop'],
1230 [0xb3, 'MediaPlayPause'],
1231 [0xad, 'VolumeMute'],
1232 [0xae, 'VolumeDown'],
1233 [0xaf, 'VolumeUp'],
1234 ]);
1235
1236 /**
1237 * @param {number} keyCode
1238 * @return {string}
1239 */
1240 function keyCodeToKeyIdentifier(keyCode) {
1241 let result = staticKeyIdentifiers.get(keyCode);
Tim van der Lippe1d6e57a2019-09-30 11:55:341242 if (result !== undefined) {
Blink Reformat4c46d092018-04-07 15:32:371243 return result;
Tim van der Lippe1d6e57a2019-09-30 11:55:341244 }
Blink Reformat4c46d092018-04-07 15:32:371245 result = 'U+';
1246 const hexString = keyCode.toString(16).toUpperCase();
Tim van der Lippe1d6e57a2019-09-30 11:55:341247 for (let i = hexString.length; i < 4; ++i) {
Blink Reformat4c46d092018-04-07 15:32:371248 result += '0';
Tim van der Lippe1d6e57a2019-09-30 11:55:341249 }
Blink Reformat4c46d092018-04-07 15:32:371250 result += hexString;
1251 return result;
1252 }
1253
1254 function installBackwardsCompatibility() {
Joel Einbinderf55cc942018-10-30 01:59:531255 const majorVersion = getRemoteMajorVersion();
Tim van der Lippe1d6e57a2019-09-30 11:55:341256 if (!majorVersion) {
Blink Reformat4c46d092018-04-07 15:32:371257 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341258 }
Blink Reformat4c46d092018-04-07 15:32:371259
Joel Einbinderf55cc942018-10-30 01:59:531260 /** @type {!Array<string>} */
1261 const styleRules = [];
Joel Einbinder82b1d8e2018-12-08 01:01:371262 // Shadow DOM V0 polyfill
1263 if (majorVersion <= 73 && !Element.prototype.createShadowRoot) {
1264 Element.prototype.createShadowRoot = function() {
1265 try {
1266 return this.attachShadow({mode: 'open'});
1267 } catch (e) {
1268 // some elements we use to add shadow roots can no
1269 // longer have shadow roots.
1270 const fakeShadowHost = document.createElement('span');
1271 this.appendChild(fakeShadowHost);
1272 fakeShadowHost.className = 'fake-shadow-host';
1273 return fakeShadowHost.createShadowRoot();
1274 }
1275 };
1276
1277 const origAdd = DOMTokenList.prototype.add;
1278 DOMTokenList.prototype.add = function(...tokens) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341279 if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) {
Joel Einbinder82b1d8e2018-12-08 01:01:371280 this._myElement.slot = '.' + tokens[0];
Tim van der Lippe1d6e57a2019-09-30 11:55:341281 }
Joel Einbinder82b1d8e2018-12-08 01:01:371282 return origAdd.apply(this, tokens);
1283 };
1284
1285 const origCreateElement = Document.prototype.createElement;
1286 Document.prototype.createElement = function(tagName, ...rest) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341287 if (tagName === 'content') {
Joel Einbinder82b1d8e2018-12-08 01:01:371288 tagName = 'slot';
Tim van der Lippe1d6e57a2019-09-30 11:55:341289 }
Joel Einbinder82b1d8e2018-12-08 01:01:371290 const element = origCreateElement.call(this, tagName, ...rest);
1291 element.classList._myElement = element;
1292 return element;
1293 };
1294
1295 Object.defineProperty(HTMLSlotElement.prototype, 'select', {
1296 async set(selector) {
1297 this.name = selector;
1298 }
1299 });
Joel Einbinderb948ebc2018-12-12 02:01:121300
Joel Einbinderb948ebc2018-12-12 02:01:121301 function overrideCreateElementWithClass() {
1302 window.removeEventListener('DOMContentLoaded', overrideCreateElementWithClass);
1303
1304 const origCreateElementWithClass = Document.prototype.createElementWithClass;
1305 Document.prototype.createElementWithClass = function(tagName, className, ...rest) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341306 if (tagName !== 'button' || (className !== 'soft-dropdown' && className !== 'dropdown-button')) {
Joel Einbinderb948ebc2018-12-12 02:01:121307 return origCreateElementWithClass.call(this, tagName, className, ...rest);
Tim van der Lippe1d6e57a2019-09-30 11:55:341308 }
Joel Einbinderb948ebc2018-12-12 02:01:121309 const element = origCreateElementWithClass.call(this, 'div', className, ...rest);
1310 element.tabIndex = 0;
1311 element.role = 'button';
1312 return element;
1313 };
1314 }
Tim van der Lippeffa78622019-09-16 12:07:121315
1316 // Document.prototype.createElementWithClass is a DevTools method, so we
1317 // need to wait for DOMContentLoaded in order to override it.
1318 if (window.document.head &&
Tim van der Lippe1d6e57a2019-09-30 11:55:341319 (window.document.readyState === 'complete' || window.document.readyState === 'interactive')) {
Tim van der Lippeffa78622019-09-16 12:07:121320 overrideCreateElementWithClass();
Tim van der Lippe1d6e57a2019-09-30 11:55:341321 } else {
Tim van der Lippeffa78622019-09-16 12:07:121322 window.addEventListener('DOMContentLoaded', overrideCreateElementWithClass);
Tim van der Lippe1d6e57a2019-09-30 11:55:341323 }
Joel Einbinderb948ebc2018-12-12 02:01:121324 }
1325
1326 // Custom Elements V0 polyfill
Tim van der Lippeffa78622019-09-16 12:07:121327 if (majorVersion <= 73 && !Document.prototype.hasOwnProperty('registerElement')) {
Joel Einbinderb948ebc2018-12-12 02:01:121328 const fakeRegistry = new Map();
1329 Document.prototype.registerElement = function(typeExtension, options) {
1330 const {prototype, extends: localName} = options;
1331 const document = this;
1332 const callback = function() {
1333 const element = document.createElement(localName || typeExtension);
1334 const skip = new Set(['constructor', '__proto__']);
1335 for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341336 if (skip.has(key)) {
Joel Einbinderb948ebc2018-12-12 02:01:121337 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:341338 }
Joel Einbinderb948ebc2018-12-12 02:01:121339 element[key] = prototype[key];
1340 }
1341 element.setAttribute('is', typeExtension);
Tim van der Lippe1d6e57a2019-09-30 11:55:341342 if (element['createdCallback']) {
Joel Einbinderb948ebc2018-12-12 02:01:121343 element['createdCallback']();
Tim van der Lippe1d6e57a2019-09-30 11:55:341344 }
Joel Einbinderb948ebc2018-12-12 02:01:121345 return element;
1346 };
1347 fakeRegistry.set(typeExtension, callback);
1348 return callback;
1349 };
1350
1351 const origCreateElement = Document.prototype.createElement;
1352 Document.prototype.createElement = function(tagName, fakeCustomElementType) {
1353 const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
Tim van der Lippe1d6e57a2019-09-30 11:55:341354 if (fakeConstructor) {
Joel Einbinderb948ebc2018-12-12 02:01:121355 return fakeConstructor();
Tim van der Lippe1d6e57a2019-09-30 11:55:341356 }
Joel Einbinderb948ebc2018-12-12 02:01:121357 return origCreateElement.call(this, tagName, fakeCustomElementType);
Joel Einbinder82b1d8e2018-12-08 01:01:371358 };
Pavel Feldman876d7182018-12-14 00:11:051359
1360 // DevTools front-ends mistakenly assume that
1361 // classList.toggle('a', undefined) works as
1362 // classList.toggle('a', false) rather than as
1363 // classList.toggle('a');
1364 const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
1365 DOMTokenList.prototype.toggle = function(token, force) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341366 if (arguments.length === 1) {
Pavel Feldman876d7182018-12-14 00:11:051367 force = !this.contains(token);
Tim van der Lippe1d6e57a2019-09-30 11:55:341368 }
Pavel Feldman876d7182018-12-14 00:11:051369 return originalDOMTokenListToggle.call(this, token, !!force);
1370 };
Joel Einbinder82b1d8e2018-12-08 01:01:371371 }
Blink Reformat4c46d092018-04-07 15:32:371372
Joel Einbinderf55cc942018-10-30 01:59:531373 if (majorVersion <= 66) {
1374 /** @type {(!function(number, number):Element|undefined)} */
1375 ShadowRoot.prototype.__originalShadowRootElementFromPoint;
1376
1377 if (!ShadowRoot.prototype.__originalShadowRootElementFromPoint) {
1378 ShadowRoot.prototype.__originalShadowRootElementFromPoint = ShadowRoot.prototype.elementFromPoint;
1379 /**
1380 * @param {number} x
1381 * @param {number} y
1382 * @return {Element}
1383 */
1384 ShadowRoot.prototype.elementFromPoint = function(x, y) {
1385 const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
Tim van der Lippe1d6e57a2019-09-30 11:55:341386 if (this.host && originalResult === this.host) {
Joel Einbinderf55cc942018-10-30 01:59:531387 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341388 }
Joel Einbinderf55cc942018-10-30 01:59:531389 return originalResult;
1390 };
1391 }
Blink Reformat4c46d092018-04-07 15:32:371392 }
1393
Joel Einbinderf55cc942018-10-30 01:59:531394 if (majorVersion <= 53) {
Blink Reformat4c46d092018-04-07 15:32:371395 Object.defineProperty(window.KeyboardEvent.prototype, 'keyIdentifier', {
1396 /**
1397 * @return {string}
1398 * @this {KeyboardEvent}
1399 */
1400 get: function() {
1401 return keyCodeToKeyIdentifier(this.keyCode);
1402 }
1403 });
1404 }
1405
Tim van der Lippe1d6e57a2019-09-30 11:55:341406 if (majorVersion <= 50) {
Joel Einbinderf55cc942018-10-30 01:59:531407 installObjectObserve();
Tim van der Lippe1d6e57a2019-09-30 11:55:341408 }
Blink Reformat4c46d092018-04-07 15:32:371409
Joel Einbinderf55cc942018-10-30 01:59:531410 if (majorVersion <= 45) {
1411 /**
1412 * @param {string} property
1413 * @return {!CSSValue|null}
1414 * @this {CSSStyleDeclaration}
1415 */
1416 function getValue(property) {
1417 // Note that |property| comes from another context, so we can't use === here.
1418 // eslint-disable-next-line eqeqeq
1419 if (property == 'padding-left') {
1420 return /** @type {!CSSValue} */ ({
1421 /**
1422 * @return {number}
1423 * @this {!{__paddingLeft: number}}
1424 */
1425 getFloatValue: function() {
1426 return this.__paddingLeft;
1427 },
1428 __paddingLeft: parseFloat(this.paddingLeft)
1429 });
1430 }
1431 throw new Error('getPropertyCSSValue is undefined');
Blink Reformat4c46d092018-04-07 15:32:371432 }
Joel Einbinderf55cc942018-10-30 01:59:531433
1434 window.CSSStyleDeclaration.prototype.getPropertyCSSValue = getValue;
1435
1436 function CSSPrimitiveValue() {
1437 }
1438 CSSPrimitiveValue.CSS_PX = 5;
1439 window.CSSPrimitiveValue = CSSPrimitiveValue;
Blink Reformat4c46d092018-04-07 15:32:371440 }
1441
Tim van der Lippe1d6e57a2019-09-30 11:55:341442 if (majorVersion <= 45) {
Joel Einbinderf55cc942018-10-30 01:59:531443 styleRules.push('* { min-width: 0; min-height: 0; }');
Tim van der Lippe1d6e57a2019-09-30 11:55:341444 }
Blink Reformat4c46d092018-04-07 15:32:371445
Joel Einbinderf55cc942018-10-30 01:59:531446 if (majorVersion <= 51) {
1447 // Support for quirky border-image behavior (<M51), see:
1448 // https://bugs.chromium.org/p/chromium/issues/detail?id=559258
1449 styleRules.push('.cm-breakpoint .CodeMirror-linenumber { border-style: solid !important; }');
1450 styleRules.push(
1451 '.cm-breakpoint.cm-breakpoint-conditional .CodeMirror-linenumber { border-style: solid !important; }');
Blink Reformat4c46d092018-04-07 15:32:371452 }
Christian Biesinger2d1b2e92018-11-06 01:18:251453 if (majorVersion <= 71) {
1454 styleRules.push(
1455 '.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
1456 }
Blink Reformat4c46d092018-04-07 15:32:371457
Tim van der Lippe1d6e57a2019-09-30 11:55:341458 if (majorVersion <= 50) {
Joel Einbinderf55cc942018-10-30 01:59:531459 Event.prototype.deepPath = undefined;
Tim van der Lippe1d6e57a2019-09-30 11:55:341460 }
Blink Reformat4c46d092018-04-07 15:32:371461
Joel Einbinderf55cc942018-10-30 01:59:531462 if (majorVersion <= 54) {
1463 window.FileError = /** @type {!function (new: FileError) : ?} */ ({
1464 NOT_FOUND_ERR: DOMException.NOT_FOUND_ERR,
1465 ABORT_ERR: DOMException.ABORT_ERR,
1466 INVALID_MODIFICATION_ERR: DOMException.INVALID_MODIFICATION_ERR,
1467 NOT_READABLE_ERR: 0 // No matching DOMException, so code will be 0.
1468 });
1469 }
Blink Reformat4c46d092018-04-07 15:32:371470
Joel Einbinderf55cc942018-10-30 01:59:531471 installExtraStyleRules(styleRules);
1472 }
Blink Reformat4c46d092018-04-07 15:32:371473
Joel Einbinderf55cc942018-10-30 01:59:531474 /**
1475 * @return {?number}
1476 */
1477 function getRemoteMajorVersion() {
1478 try {
Joel Einbinder09f48742019-02-28 01:34:421479 const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
Tim van der Lippe1d6e57a2019-09-30 11:55:341480 if (!remoteVersion) {
Joel Einbinderf55cc942018-10-30 01:59:531481 return null;
Tim van der Lippe1d6e57a2019-09-30 11:55:341482 }
Joel Einbinderf55cc942018-10-30 01:59:531483 const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
1484 return majorVersion;
Joel Einbinder31904782018-11-02 20:52:271485 } catch (e) {
Joel Einbinderf55cc942018-10-30 01:59:531486 return null;
1487 }
1488 }
1489
1490 /**
1491 * @param {!Array<string>} styleRules
1492 */
1493 function installExtraStyleRules(styleRules) {
Tim van der Lippe1d6e57a2019-09-30 11:55:341494 if (!styleRules.length) {
Joel Einbinderf55cc942018-10-30 01:59:531495 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:341496 }
Joel Einbinderf55cc942018-10-30 01:59:531497 const styleText = styleRules.join('\n');
1498 document.head.appendChild(createStyleElement(styleText));
1499
1500 const origCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
1501 HTMLElement.prototype.createShadowRoot = function(...args) {
1502 const shadowRoot = origCreateShadowRoot.call(this, ...args);
1503 shadowRoot.appendChild(createStyleElement(styleText));
1504 return shadowRoot;
1505 };
1506 }
1507
1508 /**
1509 * @param {string} styleText
1510 * @return {!Element}
1511 */
1512 function createStyleElement(styleText) {
1513 const style = document.createElement('style');
Joel Einbinderf55cc942018-10-30 01:59:531514 style.textContent = styleText;
1515 return style;
Blink Reformat4c46d092018-04-07 15:32:371516 }
1517
Joel Einbinderb948ebc2018-12-12 02:01:121518 installBackwardsCompatibility();
Blink Reformat4c46d092018-04-07 15:32:371519
Blink Reformat4c46d092018-04-07 15:32:371520})(window);