blob: ff6cc6df0e9b6e2b486222e0a62aa1a973f78c69 [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];
42 if (callback)
43 callback(arg);
44 }
45
46 /**
47 * @param {string} method
48 * @param {!Array.<*>} args
49 * @param {?function(?Object)} callback
50 */
51 sendMessageToEmbedder(method, args, callback) {
52 const callId = ++this._lastCallId;
53 if (callback)
54 this._callbacks[callId] = callback;
55 const message = {'id': callId, 'method': method};
56 if (args.length)
57 message.params = args;
58 DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
59 }
60
61 /**
62 * @param {string} method
63 * @param {!Array<*>} args
64 */
65 _dispatchOnInspectorFrontendAPI(method, args) {
66 const inspectorFrontendAPI = /** @type {!Object<string, function()>} */ (window['InspectorFrontendAPI']);
67 inspectorFrontendAPI[method].apply(inspectorFrontendAPI, args);
68 }
69
70 // API methods below this line --------------------------------------------
71
72 /**
73 * @param {!Array.<!ExtensionDescriptor>} extensions
74 */
75 addExtensions(extensions) {
76 // Support for legacy front-ends (<M41).
77 if (window['WebInspector'] && window['WebInspector']['addExtensions']) {
78 window['WebInspector']['addExtensions'](extensions);
Jeff Fisherac799a52019-06-25 21:47:0679 } else {
Blink Reformat4c46d092018-04-07 15:32:3780 // The addExtensions command is sent as the onload event happens for
Jeff Fisherac799a52019-06-25 21:47:0681 // DevTools front-end. We should buffer this command until the frontend
82 // is ready for it.
83 if (this._addExtensionCallback)
84 extensions.forEach(this._addExtensionCallback);
85 else
86 this._pendingExtensionDescriptors.pushAll(extensions);
Blink Reformat4c46d092018-04-07 15:32:3787 }
88 }
89
90 /**
91 * @param {string} url
92 */
93 appendedToURL(url) {
94 this._dispatchOnInspectorFrontendAPI('appendedToURL', [url]);
95 }
96
97 /**
98 * @param {string} url
99 */
100 canceledSaveURL(url) {
101 this._dispatchOnInspectorFrontendAPI('canceledSaveURL', [url]);
102 }
103
104 contextMenuCleared() {
105 this._dispatchOnInspectorFrontendAPI('contextMenuCleared', []);
106 }
107
108 /**
109 * @param {string} id
110 */
111 contextMenuItemSelected(id) {
112 this._dispatchOnInspectorFrontendAPI('contextMenuItemSelected', [id]);
113 }
114
115 /**
116 * @param {number} count
117 */
118 deviceCountUpdated(count) {
119 this._dispatchOnInspectorFrontendAPI('deviceCountUpdated', [count]);
120 }
121
122 /**
123 * @param {!Adb.Config} config
124 */
125 devicesDiscoveryConfigChanged(config) {
126 this._dispatchOnInspectorFrontendAPI('devicesDiscoveryConfigChanged', [config]);
127 }
128
129 /**
130 * @param {!Adb.PortForwardingStatus} status
131 */
132 devicesPortForwardingStatusChanged(status) {
133 this._dispatchOnInspectorFrontendAPI('devicesPortForwardingStatusChanged', [status]);
134 }
135
136 /**
137 * @param {!Array.<!Adb.Device>} devices
138 */
139 devicesUpdated(devices) {
140 this._dispatchOnInspectorFrontendAPI('devicesUpdated', [devices]);
141 }
142
143 /**
144 * @param {string} message
145 */
146 dispatchMessage(message) {
147 this._dispatchOnInspectorFrontendAPI('dispatchMessage', [message]);
148 }
149
150 /**
151 * @param {string} messageChunk
152 * @param {number} messageSize
153 */
154 dispatchMessageChunk(messageChunk, messageSize) {
155 this._dispatchOnInspectorFrontendAPI('dispatchMessageChunk', [messageChunk, messageSize]);
156 }
157
158 enterInspectElementMode() {
159 this._dispatchOnInspectorFrontendAPI('enterInspectElementMode', []);
160 }
161
162 /**
163 * @param {!{r: number, g: number, b: number, a: number}} color
164 */
165 eyeDropperPickedColor(color) {
166 this._dispatchOnInspectorFrontendAPI('eyeDropperPickedColor', [color]);
167 }
168
169 /**
170 * @param {!Array.<!{fileSystemName: string, rootURL: string, fileSystemPath: string}>} fileSystems
171 */
172 fileSystemsLoaded(fileSystems) {
173 this._dispatchOnInspectorFrontendAPI('fileSystemsLoaded', [fileSystems]);
174 }
175
176 /**
177 * @param {string} fileSystemPath
178 */
179 fileSystemRemoved(fileSystemPath) {
180 this._dispatchOnInspectorFrontendAPI('fileSystemRemoved', [fileSystemPath]);
181 }
182
183 /**
184 * @param {?string} error
185 * @param {?{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} fileSystem
186 */
187 fileSystemAdded(error, fileSystem) {
188 this._dispatchOnInspectorFrontendAPI('fileSystemAdded', [error, fileSystem]);
189 }
190
191 /**
192 * @param {!Array<string>} changedPaths
193 * @param {!Array<string>} addedPaths
194 * @param {!Array<string>} removedPaths
195 */
196 fileSystemFilesChangedAddedRemoved(changedPaths, addedPaths, removedPaths) {
197 // Support for legacy front-ends (<M58)
198 if (window['InspectorFrontendAPI'] && window['InspectorFrontendAPI']['fileSystemFilesChanged']) {
199 this._dispatchOnInspectorFrontendAPI(
200 'fileSystemFilesChanged', [changedPaths.concat(addedPaths).concat(removedPaths)]);
201 } else {
202 this._dispatchOnInspectorFrontendAPI(
203 'fileSystemFilesChangedAddedRemoved', [changedPaths, addedPaths, removedPaths]);
204 }
205 }
206
207 /**
208 * @param {number} requestId
209 * @param {string} fileSystemPath
210 * @param {number} totalWork
211 */
212 indexingTotalWorkCalculated(requestId, fileSystemPath, totalWork) {
213 this._dispatchOnInspectorFrontendAPI('indexingTotalWorkCalculated', [requestId, fileSystemPath, totalWork]);
214 }
215
216 /**
217 * @param {number} requestId
218 * @param {string} fileSystemPath
219 * @param {number} worked
220 */
221 indexingWorked(requestId, fileSystemPath, worked) {
222 this._dispatchOnInspectorFrontendAPI('indexingWorked', [requestId, fileSystemPath, worked]);
223 }
224
225 /**
226 * @param {number} requestId
227 * @param {string} fileSystemPath
228 */
229 indexingDone(requestId, fileSystemPath) {
230 this._dispatchOnInspectorFrontendAPI('indexingDone', [requestId, fileSystemPath]);
231 }
232
233 /**
234 * @param {{type: string, key: string, code: string, keyCode: number, modifiers: number}} event
235 */
236 keyEventUnhandled(event) {
237 event.keyIdentifier = keyCodeToKeyIdentifier(event.keyCode);
238 this._dispatchOnInspectorFrontendAPI('keyEventUnhandled', [event]);
239 }
240
241 /**
Jeff Fisherac799a52019-06-25 21:47:06242 * @param {function(!ExtensionDescriptor)} callback
243 */
244 setAddExtensionCallback(callback) {
245 this._addExtensionCallback = callback;
246 if (this._pendingExtensionDescriptors.length) {
247 this._pendingExtensionDescriptors.forEach(this._addExtensionCallback);
248 this._pendingExtensionDescriptors = [];
249 }
250 }
251
252 /**
Blink Reformat4c46d092018-04-07 15:32:37253 * @param {boolean} hard
254 */
255 reloadInspectedPage(hard) {
256 this._dispatchOnInspectorFrontendAPI('reloadInspectedPage', [hard]);
257 }
258
259 /**
260 * @param {string} url
261 * @param {number} lineNumber
262 * @param {number} columnNumber
263 */
264 revealSourceLine(url, lineNumber, columnNumber) {
265 this._dispatchOnInspectorFrontendAPI('revealSourceLine', [url, lineNumber, columnNumber]);
266 }
267
268 /**
269 * @param {string} url
270 * @param {string=} fileSystemPath
271 */
272 savedURL(url, fileSystemPath) {
273 this._dispatchOnInspectorFrontendAPI('savedURL', [url, fileSystemPath]);
274 }
275
276 /**
277 * @param {number} requestId
278 * @param {string} fileSystemPath
279 * @param {!Array.<string>} files
280 */
281 searchCompleted(requestId, fileSystemPath, files) {
282 this._dispatchOnInspectorFrontendAPI('searchCompleted', [requestId, fileSystemPath, files]);
283 }
284
285 /**
286 * @param {string} tabId
287 */
288 setInspectedTabId(tabId) {
289 // Support for legacy front-ends (<M41).
290 if (window['WebInspector'] && window['WebInspector']['setInspectedTabId'])
291 window['WebInspector']['setInspectedTabId'](tabId);
292 else
293 this._dispatchOnInspectorFrontendAPI('setInspectedTabId', [tabId]);
294 }
295
296 /**
297 * @param {boolean} useSoftMenu
298 */
299 setUseSoftMenu(useSoftMenu) {
300 this._dispatchOnInspectorFrontendAPI('setUseSoftMenu', [useSoftMenu]);
301 }
302
303 /**
304 * @param {string} panelName
305 */
306 showPanel(panelName) {
307 this._dispatchOnInspectorFrontendAPI('showPanel', [panelName]);
308 }
309
310 /**
311 * @param {number} id
312 * @param {string} chunk
313 * @param {boolean} encoded
314 */
315 streamWrite(id, chunk, encoded) {
316 this._dispatchOnInspectorFrontendAPI('streamWrite', [id, encoded ? this._decodeBase64(chunk) : chunk]);
317 }
318
319 /**
320 * @param {string} chunk
321 * @return {string}
322 */
323 _decodeBase64(chunk) {
324 const request = new XMLHttpRequest();
325 request.open('GET', 'data:text/plain;base64,' + chunk, false);
326 request.send(null);
327 if (request.status === 200) {
328 return request.responseText;
329 } else {
330 console.error('Error while decoding chunk in streamWrite');
331 return '';
332 }
333 }
334 };
335
336 const DevToolsAPI = new DevToolsAPIImpl();
337 window.DevToolsAPI = DevToolsAPI;
338
339 // InspectorFrontendHostImpl --------------------------------------------------
340
341 /**
342 * @implements {InspectorFrontendHostAPI}
343 * @unrestricted
344 */
345 const InspectorFrontendHostImpl = class {
346 /**
Blink Reformat4c46d092018-04-07 15:32:37347 * @return {string}
348 */
349 getSelectionBackgroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02350 return '#6e86ff';
Blink Reformat4c46d092018-04-07 15:32:37351 }
352
353 /**
Blink Reformat4c46d092018-04-07 15:32:37354 * @return {string}
355 */
356 getSelectionForegroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02357 return '#ffffff';
Blink Reformat4c46d092018-04-07 15:32:37358 }
359
360 /**
Blink Reformat4c46d092018-04-07 15:32:37361 * @return {string}
362 */
363 getInactiveSelectionBackgroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02364 return '#c9c8c8';
Blink Reformat4c46d092018-04-07 15:32:37365 }
366
367 /**
Blink Reformat4c46d092018-04-07 15:32:37368 * @return {string}
369 */
370 getInactiveSelectionForegroundColor() {
Pavel Feldman33b40912018-12-22 01:08:02371 return '#323232';
Blink Reformat4c46d092018-04-07 15:32:37372 }
373
374 /**
375 * @override
376 * @return {string}
377 */
378 platform() {
379 return DevToolsHost.platform();
380 }
381
382 /**
383 * @override
384 */
385 loadCompleted() {
386 DevToolsAPI.sendMessageToEmbedder('loadCompleted', [], null);
387 // Support for legacy (<57) frontends.
388 if (window.Runtime && window.Runtime.queryParam) {
389 const panelToOpen = window.Runtime.queryParam('panel');
390 if (panelToOpen)
391 window.DevToolsAPI.showPanel(panelToOpen);
392 }
393 }
394
395 /**
396 * @override
397 */
398 bringToFront() {
399 DevToolsAPI.sendMessageToEmbedder('bringToFront', [], null);
400 }
401
402 /**
403 * @override
404 */
405 closeWindow() {
406 DevToolsAPI.sendMessageToEmbedder('closeWindow', [], null);
407 }
408
409 /**
410 * @override
411 * @param {boolean} isDocked
412 * @param {function()} callback
413 */
414 setIsDocked(isDocked, callback) {
415 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [isDocked], callback);
416 }
417
418 /**
419 * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
420 * @override
421 * @param {{x: number, y: number, width: number, height: number}} bounds
422 */
423 setInspectedPageBounds(bounds) {
424 DevToolsAPI.sendMessageToEmbedder('setInspectedPageBounds', [bounds], null);
425 }
426
427 /**
428 * @override
429 */
430 inspectElementCompleted() {
431 DevToolsAPI.sendMessageToEmbedder('inspectElementCompleted', [], null);
432 }
433
434 /**
435 * @override
436 * @param {string} url
437 * @param {string} headers
438 * @param {number} streamId
439 * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
440 */
441 loadNetworkResource(url, headers, streamId, callback) {
442 DevToolsAPI.sendMessageToEmbedder(
443 'loadNetworkResource', [url, headers, streamId], /** @type {function(?Object)} */ (callback));
444 }
445
446 /**
447 * @override
448 * @param {function(!Object<string, string>)} callback
449 */
450 getPreferences(callback) {
451 DevToolsAPI.sendMessageToEmbedder('getPreferences', [], /** @type {function(?Object)} */ (callback));
452 }
453
454 /**
455 * @override
456 * @param {string} name
457 * @param {string} value
458 */
459 setPreference(name, value) {
460 DevToolsAPI.sendMessageToEmbedder('setPreference', [name, value], null);
461 }
462
463 /**
464 * @override
465 * @param {string} name
466 */
467 removePreference(name) {
468 DevToolsAPI.sendMessageToEmbedder('removePreference', [name], null);
469 }
470
471 /**
472 * @override
473 */
474 clearPreferences() {
475 DevToolsAPI.sendMessageToEmbedder('clearPreferences', [], null);
476 }
477
478 /**
479 * @override
480 * @param {string} origin
481 * @param {string} script
482 */
483 setInjectedScriptForOrigin(origin, script) {
484 DevToolsAPI.sendMessageToEmbedder('registerExtensionsAPI', [origin, script], null);
485 }
486
487 /**
488 * @override
489 * @param {string} url
490 */
491 inspectedURLChanged(url) {
492 DevToolsAPI.sendMessageToEmbedder('inspectedURLChanged', [url], null);
493 }
494
495 /**
496 * @override
497 * @param {string} text
498 */
499 copyText(text) {
500 DevToolsHost.copyText(text);
501 }
502
503 /**
504 * @override
505 * @param {string} url
506 */
507 openInNewTab(url) {
508 DevToolsAPI.sendMessageToEmbedder('openInNewTab', [url], null);
509 }
510
511 /**
512 * @override
513 * @param {string} fileSystemPath
514 */
515 showItemInFolder(fileSystemPath) {
516 DevToolsAPI.sendMessageToEmbedder('showItemInFolder', [fileSystemPath], null);
517 }
518
519 /**
520 * @override
521 * @param {string} url
522 * @param {string} content
523 * @param {boolean} forceSaveAs
524 */
525 save(url, content, forceSaveAs) {
526 DevToolsAPI.sendMessageToEmbedder('save', [url, content, forceSaveAs], null);
527 }
528
529 /**
530 * @override
531 * @param {string} url
532 * @param {string} content
533 */
534 append(url, content) {
535 DevToolsAPI.sendMessageToEmbedder('append', [url, content], null);
536 }
537
538 /**
539 * @override
Pavel Feldmanf1a36ee2018-07-28 16:10:25540 * @param {string} url
541 */
542 close(url) {
543 }
544
545 /**
546 * @override
Blink Reformat4c46d092018-04-07 15:32:37547 * @param {string} message
548 */
549 sendMessageToBackend(message) {
550 DevToolsAPI.sendMessageToEmbedder('dispatchProtocolMessage', [message], null);
551 }
552
553 /**
554 * @override
555 * @param {string} actionName
556 * @param {number} actionCode
557 * @param {number} bucketSize
558 */
559 recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
560 // Support for M49 frontend.
561 if (actionName === 'DevTools.DrawerShown')
562 return;
563 DevToolsAPI.sendMessageToEmbedder('recordEnumeratedHistogram', [actionName, actionCode, bucketSize], null);
564 }
565
566 /**
567 * @override
James Lissiakd2f1a2f2019-03-26 17:36:51568 * @param {string} histogramName
569 * @param {number} duration
570 */
571 recordPerformanceHistogram(histogramName, duration) {
572 DevToolsAPI.sendMessageToEmbedder('recordPerformanceHistogram', [histogramName, duration], null);
573 }
574
575 /**
576 * @override
James Lissiake21c97b2019-04-29 17:36:43577 * @param {string} umaName
578 */
579 recordUserMetricsAction(umaName) {
580 DevToolsAPI.sendMessageToEmbedder('recordUserMetricsAction', [umaName], null);
581 }
582
583 /**
584 * @override
Blink Reformat4c46d092018-04-07 15:32:37585 */
586 requestFileSystems() {
587 DevToolsAPI.sendMessageToEmbedder('requestFileSystems', [], null);
588 }
589
590 /**
591 * @override
592 * @param {string=} type
593 */
594 addFileSystem(type) {
595 DevToolsAPI.sendMessageToEmbedder('addFileSystem', [type || ''], null);
596 }
597
598 /**
599 * @override
600 * @param {string} fileSystemPath
601 */
602 removeFileSystem(fileSystemPath) {
603 DevToolsAPI.sendMessageToEmbedder('removeFileSystem', [fileSystemPath], null);
604 }
605
606 /**
607 * @override
608 * @param {string} fileSystemId
609 * @param {string} registeredName
610 * @return {?DOMFileSystem}
611 */
612 isolatedFileSystem(fileSystemId, registeredName) {
613 return DevToolsHost.isolatedFileSystem(fileSystemId, registeredName);
614 }
615
616 /**
617 * @override
618 * @param {!FileSystem} fileSystem
619 */
620 upgradeDraggedFileSystemPermissions(fileSystem) {
621 DevToolsHost.upgradeDraggedFileSystemPermissions(fileSystem);
622 }
623
624 /**
625 * @override
626 * @param {number} requestId
627 * @param {string} fileSystemPath
628 * @param {string} excludedFolders
629 */
630 indexPath(requestId, fileSystemPath, excludedFolders) {
631 // |excludedFolders| added in M67. For backward compatibility,
632 // pass empty array.
633 excludedFolders = excludedFolders || '[]';
634 DevToolsAPI.sendMessageToEmbedder('indexPath', [requestId, fileSystemPath, excludedFolders], null);
635 }
636
637 /**
638 * @override
639 * @param {number} requestId
640 */
641 stopIndexing(requestId) {
642 DevToolsAPI.sendMessageToEmbedder('stopIndexing', [requestId], null);
643 }
644
645 /**
646 * @override
647 * @param {number} requestId
648 * @param {string} fileSystemPath
649 * @param {string} query
650 */
651 searchInPath(requestId, fileSystemPath, query) {
652 DevToolsAPI.sendMessageToEmbedder('searchInPath', [requestId, fileSystemPath, query], null);
653 }
654
655 /**
656 * @override
657 * @return {number}
658 */
659 zoomFactor() {
660 return DevToolsHost.zoomFactor();
661 }
662
663 /**
664 * @override
665 */
666 zoomIn() {
667 DevToolsAPI.sendMessageToEmbedder('zoomIn', [], null);
668 }
669
670 /**
671 * @override
672 */
673 zoomOut() {
674 DevToolsAPI.sendMessageToEmbedder('zoomOut', [], null);
675 }
676
677 /**
678 * @override
679 */
680 resetZoom() {
681 DevToolsAPI.sendMessageToEmbedder('resetZoom', [], null);
682 }
683
684 /**
685 * @override
686 * @param {string} shortcuts
687 */
688 setWhitelistedShortcuts(shortcuts) {
689 DevToolsAPI.sendMessageToEmbedder('setWhitelistedShortcuts', [shortcuts], null);
690 }
691
692 /**
693 * @override
694 * @param {boolean} active
695 */
696 setEyeDropperActive(active) {
697 DevToolsAPI.sendMessageToEmbedder('setEyeDropperActive', [active], null);
698 }
699
700 /**
701 * @override
702 * @param {!Array<string>} certChain
703 */
704 showCertificateViewer(certChain) {
705 DevToolsAPI.sendMessageToEmbedder('showCertificateViewer', [JSON.stringify(certChain)], null);
706 }
707
708 /**
Connor Clarkca8905e2019-08-23 18:35:10709 * Only needed to run Lighthouse on old devtools.
Blink Reformat4c46d092018-04-07 15:32:37710 * @override
711 * @param {function()} callback
712 */
713 reattach(callback) {
714 DevToolsAPI.sendMessageToEmbedder('reattach', [], callback);
715 }
716
717 /**
718 * @override
719 */
720 readyForTest() {
721 DevToolsAPI.sendMessageToEmbedder('readyForTest', [], null);
722 }
723
724 /**
725 * @override
726 */
727 connectionReady() {
728 DevToolsAPI.sendMessageToEmbedder('connectionReady', [], null);
729 }
730
731 /**
732 * @override
733 * @param {boolean} value
734 */
735 setOpenNewWindowForPopups(value) {
736 DevToolsAPI.sendMessageToEmbedder('setOpenNewWindowForPopups', [value], null);
737 }
738
739 /**
740 * @override
741 * @param {!Adb.Config} config
742 */
743 setDevicesDiscoveryConfig(config) {
744 DevToolsAPI.sendMessageToEmbedder(
745 'setDevicesDiscoveryConfig',
746 [
747 config.discoverUsbDevices, config.portForwardingEnabled, JSON.stringify(config.portForwardingConfig),
748 config.networkDiscoveryEnabled, JSON.stringify(config.networkDiscoveryConfig)
749 ],
750 null);
751 }
752
753 /**
754 * @override
755 * @param {boolean} enabled
756 */
757 setDevicesUpdatesEnabled(enabled) {
758 DevToolsAPI.sendMessageToEmbedder('setDevicesUpdatesEnabled', [enabled], null);
759 }
760
761 /**
762 * @override
763 * @param {string} pageId
764 * @param {string} action
765 */
766 performActionOnRemotePage(pageId, action) {
767 DevToolsAPI.sendMessageToEmbedder('performActionOnRemotePage', [pageId, action], null);
768 }
769
770 /**
771 * @override
772 * @param {string} browserId
773 * @param {string} url
774 */
775 openRemotePage(browserId, url) {
776 DevToolsAPI.sendMessageToEmbedder('openRemotePage', [browserId, url], null);
777 }
778
779 /**
780 * @override
781 */
782 openNodeFrontend() {
783 DevToolsAPI.sendMessageToEmbedder('openNodeFrontend', [], null);
784 }
785
786 /**
787 * @override
788 * @param {number} x
789 * @param {number} y
790 * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
791 * @param {!Document} document
792 */
793 showContextMenuAtPoint(x, y, items, document) {
794 DevToolsHost.showContextMenuAtPoint(x, y, items, document);
795 }
796
797 /**
798 * @override
799 * @return {boolean}
800 */
801 isHostedMode() {
802 return DevToolsHost.isHostedMode();
803 }
804
Jeff Fisherac799a52019-06-25 21:47:06805 /**
806 * @override
807 * @param {function(!ExtensionDescriptor)} callback
808 */
809 setAddExtensionCallback(callback) {
810 DevToolsAPI.setAddExtensionCallback(callback);
811 }
812
Blink Reformat4c46d092018-04-07 15:32:37813 // Backward-compatible methods below this line --------------------------------------------
814
815 /**
816 * Support for legacy front-ends (<M65).
817 * @return {boolean}
818 */
819 isUnderTest() {
820 return false;
821 }
822
823 /**
824 * Support for legacy front-ends (<M50).
825 * @param {string} message
826 */
827 sendFrontendAPINotification(message) {
828 }
829
830 /**
831 * Support for legacy front-ends (<M41).
832 * @return {string}
833 */
834 port() {
835 return 'unknown';
836 }
837
838 /**
839 * Support for legacy front-ends (<M38).
840 * @param {number} zoomFactor
841 */
842 setZoomFactor(zoomFactor) {
843 }
844
845 /**
846 * Support for legacy front-ends (<M34).
847 */
848 sendMessageToEmbedder() {
849 }
850
851 /**
852 * Support for legacy front-ends (<M34).
853 * @param {string} dockSide
854 */
855 requestSetDockSide(dockSide) {
856 DevToolsAPI.sendMessageToEmbedder('setIsDocked', [dockSide !== 'undocked'], null);
857 }
858
859 /**
860 * Support for legacy front-ends (<M34).
861 * @return {boolean}
862 */
863 supportsFileSystems() {
864 return true;
865 }
866
867 /**
Blink Reformat4c46d092018-04-07 15:32:37868 * Support for legacy front-ends (<M44).
869 * @param {number} actionCode
870 */
871 recordActionTaken(actionCode) {
872 this.recordEnumeratedHistogram('DevTools.ActionTaken', actionCode, 100);
873 }
874
875 /**
876 * Support for legacy front-ends (<M44).
877 * @param {number} panelCode
878 */
879 recordPanelShown(panelCode) {
880 this.recordEnumeratedHistogram('DevTools.PanelShown', panelCode, 20);
881 }
882 };
883
884 window.InspectorFrontendHost = new InspectorFrontendHostImpl();
885
886 // DevToolsApp ---------------------------------------------------------------
887
888 function installObjectObserve() {
889 /** @type {!Array<string>} */
890 const properties = [
891 'advancedSearchConfig',
892 'auditsPanelSplitViewState',
893 'auditsSidebarWidth',
894 'blockedURLs',
895 'breakpoints',
896 'cacheDisabled',
897 'colorFormat',
898 'consoleHistory',
899 'consoleTimestampsEnabled',
900 'cpuProfilerView',
901 'cssSourceMapsEnabled',
902 'currentDockState',
903 'customColorPalette',
904 'customDevicePresets',
905 'customEmulatedDeviceList',
906 'customFormatters',
907 'customUserAgent',
908 'databaseTableViewVisibleColumns',
909 'dataGrid-cookiesTable',
910 'dataGrid-DOMStorageItemsView',
911 'debuggerSidebarHidden',
912 'disableDataSaverInfobar',
913 'disablePausedStateOverlay',
914 'domBreakpoints',
915 'domWordWrap',
916 'elementsPanelSplitViewState',
917 'elementsSidebarWidth',
918 'emulation.deviceHeight',
919 'emulation.deviceModeValue',
920 'emulation.deviceOrientationOverride',
921 'emulation.deviceScale',
922 'emulation.deviceScaleFactor',
923 'emulation.deviceUA',
924 'emulation.deviceWidth',
925 'emulation.geolocationOverride',
926 'emulation.showDeviceMode',
927 'emulation.showRulers',
928 'enableAsyncStackTraces',
929 'eventListenerBreakpoints',
930 'fileMappingEntries',
931 'fileSystemMapping',
932 'FileSystemViewSidebarWidth',
933 'fileSystemViewSplitViewState',
934 'filterBar-consoleView',
935 'filterBar-networkPanel',
936 'filterBar-promisePane',
937 'filterBar-timelinePanel',
938 'frameViewerHideChromeWindow',
939 'heapSnapshotRetainersViewSize',
940 'heapSnapshotSplitViewState',
941 'hideCollectedPromises',
942 'hideNetworkMessages',
943 'highlightNodeOnHoverInOverlay',
944 'highResolutionCpuProfiling',
945 'inlineVariableValues',
946 'Inspector.drawerSplitView',
947 'Inspector.drawerSplitViewState',
948 'InspectorView.panelOrder',
949 'InspectorView.screencastSplitView',
950 'InspectorView.screencastSplitViewState',
951 'InspectorView.splitView',
952 'InspectorView.splitViewState',
953 'javaScriptDisabled',
954 'jsSourceMapsEnabled',
955 'lastActivePanel',
956 'lastDockState',
957 'lastSelectedSourcesSidebarPaneTab',
958 'lastSnippetEvaluationIndex',
959 'layerDetailsSplitView',
960 'layerDetailsSplitViewState',
961 'layersPanelSplitViewState',
962 'layersShowInternalLayers',
963 'layersSidebarWidth',
964 'messageLevelFilters',
965 'messageURLFilters',
966 'monitoringXHREnabled',
967 'navigatorGroupByFolder',
968 'navigatorHidden',
969 'networkColorCodeResourceTypes',
970 'networkConditions',
971 'networkConditionsCustomProfiles',
972 'networkHideDataURL',
973 'networkLogColumnsVisibility',
974 'networkLogLargeRows',
975 'networkLogShowOverview',
976 'networkPanelSplitViewState',
977 'networkRecordFilmStripSetting',
978 'networkResourceTypeFilters',
979 'networkShowPrimaryLoadWaterfall',
980 'networkSidebarWidth',
981 'openLinkHandler',
982 'pauseOnCaughtException',
983 'pauseOnExceptionEnabled',
984 'preserveConsoleLog',
985 'prettyPrintInfobarDisabled',
986 'previouslyViewedFiles',
987 'profilesPanelSplitViewState',
988 'profilesSidebarWidth',
989 'promiseStatusFilters',
990 'recordAllocationStacks',
991 'requestHeaderFilterSetting',
992 'request-info-formData-category-expanded',
993 'request-info-general-category-expanded',
994 'request-info-queryString-category-expanded',
995 'request-info-requestHeaders-category-expanded',
996 'request-info-requestPayload-category-expanded',
997 'request-info-responseHeaders-category-expanded',
998 'resources',
999 'resourcesLastSelectedItem',
1000 'resourcesPanelSplitViewState',
1001 'resourcesSidebarWidth',
1002 'resourceViewTab',
1003 'savedURLs',
1004 'screencastEnabled',
1005 'scriptsPanelNavigatorSidebarWidth',
1006 'searchInContentScripts',
1007 'selectedAuditCategories',
1008 'selectedColorPalette',
1009 'selectedProfileType',
1010 'shortcutPanelSwitch',
1011 'showAdvancedHeapSnapshotProperties',
1012 'showEventListenersForAncestors',
1013 'showFrameowkrListeners',
1014 'showHeaSnapshotObjectsHiddenProperties',
1015 'showInheritedComputedStyleProperties',
1016 'showMediaQueryInspector',
1017 'showNativeFunctionsInJSProfile',
1018 'showUAShadowDOM',
1019 'showWhitespacesInEditor',
1020 'sidebarPosition',
1021 'skipContentScripts',
1022 'skipStackFramesPattern',
1023 'sourceMapInfobarDisabled',
1024 'sourcesPanelDebuggerSidebarSplitViewState',
1025 'sourcesPanelNavigatorSplitViewState',
1026 'sourcesPanelSplitSidebarRatio',
1027 'sourcesPanelSplitViewState',
1028 'sourcesSidebarWidth',
1029 'standardEmulatedDeviceList',
1030 'StylesPaneSplitRatio',
1031 'stylesPaneSplitViewState',
1032 'textEditorAutocompletion',
1033 'textEditorAutoDetectIndent',
1034 'textEditorBracketMatching',
1035 'textEditorIndent',
Junyi Xiao89142cf2019-04-11 16:01:381036 'textEditorTabMovesFocus',
Blink Reformat4c46d092018-04-07 15:32:371037 'timelineCaptureFilmStrip',
1038 'timelineCaptureLayersAndPictures',
1039 'timelineCaptureMemory',
1040 'timelineCaptureNetwork',
1041 'timeline-details',
1042 'timelineEnableJSSampling',
1043 'timelineOverviewMode',
1044 'timelinePanelDetailsSplitViewState',
1045 'timelinePanelRecorsSplitViewState',
1046 'timelinePanelTimelineStackSplitViewState',
1047 'timelinePerspective',
1048 'timeline-split',
1049 'timelineTreeGroupBy',
1050 'timeline-view',
1051 'timelineViewMode',
1052 'uiTheme',
1053 'watchExpressions',
1054 'WebInspector.Drawer.lastSelectedView',
1055 'WebInspector.Drawer.showOnLoad',
1056 'workspaceExcludedFolders',
1057 'workspaceFolderExcludePattern',
1058 'workspaceInfobarDisabled',
1059 'workspaceMappingInfobarDisabled',
1060 'xhrBreakpoints'
1061 ];
1062
1063 /**
1064 * @this {!{_storage: Object, _name: string}}
1065 */
1066 function settingRemove() {
1067 this._storage[this._name] = undefined;
1068 }
1069
1070 /**
1071 * @param {!Object} object
1072 * @param {function(!Array<!{name: string}>)} observer
1073 */
1074 function objectObserve(object, observer) {
1075 if (window['WebInspector']) {
1076 const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
1077 if (typeof settingPrototype['remove'] === 'function')
1078 settingPrototype['remove'] = settingRemove;
1079 }
1080 /** @type {!Set<string>} */
1081 const changedProperties = new Set();
1082 let scheduled = false;
1083
1084 function scheduleObserver() {
1085 if (scheduled)
1086 return;
1087 scheduled = true;
1088 setImmediate(callObserver);
1089 }
1090
1091 function callObserver() {
1092 scheduled = false;
1093 const changes = /** @type {!Array<!{name: string}>} */ ([]);
1094 changedProperties.forEach(function(name) {
1095 changes.push({name: name});
1096 });
1097 changedProperties.clear();
1098 observer.call(null, changes);
1099 }
1100
1101 /** @type {!Map<string, *>} */
1102 const storage = new Map();
1103
1104 /**
1105 * @param {string} property
1106 */
1107 function defineProperty(property) {
1108 if (property in object) {
1109 storage.set(property, object[property]);
1110 delete object[property];
1111 }
1112
1113 Object.defineProperty(object, property, {
1114 /**
1115 * @return {*}
1116 */
1117 get: function() {
1118 return storage.get(property);
1119 },
1120
1121 /**
1122 * @param {*} value
1123 */
1124 set: function(value) {
1125 storage.set(property, value);
1126 changedProperties.add(property);
1127 scheduleObserver();
1128 }
1129 });
1130 }
1131
1132 for (let i = 0; i < properties.length; ++i)
1133 defineProperty(properties[i]);
1134 }
1135
1136 window.Object.observe = objectObserve;
1137 }
1138
1139 /** @type {!Map<number, string>} */
1140 const staticKeyIdentifiers = new Map([
1141 [0x12, 'Alt'],
1142 [0x11, 'Control'],
1143 [0x10, 'Shift'],
1144 [0x14, 'CapsLock'],
1145 [0x5b, 'Win'],
1146 [0x5c, 'Win'],
1147 [0x0c, 'Clear'],
1148 [0x28, 'Down'],
1149 [0x23, 'End'],
1150 [0x0a, 'Enter'],
1151 [0x0d, 'Enter'],
1152 [0x2b, 'Execute'],
1153 [0x70, 'F1'],
1154 [0x71, 'F2'],
1155 [0x72, 'F3'],
1156 [0x73, 'F4'],
1157 [0x74, 'F5'],
1158 [0x75, 'F6'],
1159 [0x76, 'F7'],
1160 [0x77, 'F8'],
1161 [0x78, 'F9'],
1162 [0x79, 'F10'],
1163 [0x7a, 'F11'],
1164 [0x7b, 'F12'],
1165 [0x7c, 'F13'],
1166 [0x7d, 'F14'],
1167 [0x7e, 'F15'],
1168 [0x7f, 'F16'],
1169 [0x80, 'F17'],
1170 [0x81, 'F18'],
1171 [0x82, 'F19'],
1172 [0x83, 'F20'],
1173 [0x84, 'F21'],
1174 [0x85, 'F22'],
1175 [0x86, 'F23'],
1176 [0x87, 'F24'],
1177 [0x2f, 'Help'],
1178 [0x24, 'Home'],
1179 [0x2d, 'Insert'],
1180 [0x25, 'Left'],
1181 [0x22, 'PageDown'],
1182 [0x21, 'PageUp'],
1183 [0x13, 'Pause'],
1184 [0x2c, 'PrintScreen'],
1185 [0x27, 'Right'],
1186 [0x91, 'Scroll'],
1187 [0x29, 'Select'],
1188 [0x26, 'Up'],
1189 [0x2e, 'U+007F'], // Standard says that DEL becomes U+007F.
1190 [0xb0, 'MediaNextTrack'],
1191 [0xb1, 'MediaPreviousTrack'],
1192 [0xb2, 'MediaStop'],
1193 [0xb3, 'MediaPlayPause'],
1194 [0xad, 'VolumeMute'],
1195 [0xae, 'VolumeDown'],
1196 [0xaf, 'VolumeUp'],
1197 ]);
1198
1199 /**
1200 * @param {number} keyCode
1201 * @return {string}
1202 */
1203 function keyCodeToKeyIdentifier(keyCode) {
1204 let result = staticKeyIdentifiers.get(keyCode);
1205 if (result !== undefined)
1206 return result;
1207 result = 'U+';
1208 const hexString = keyCode.toString(16).toUpperCase();
1209 for (let i = hexString.length; i < 4; ++i)
1210 result += '0';
1211 result += hexString;
1212 return result;
1213 }
1214
1215 function installBackwardsCompatibility() {
Joel Einbinderf55cc942018-10-30 01:59:531216 const majorVersion = getRemoteMajorVersion();
1217 if (!majorVersion)
Blink Reformat4c46d092018-04-07 15:32:371218 return;
1219
Joel Einbinderf55cc942018-10-30 01:59:531220 /** @type {!Array<string>} */
1221 const styleRules = [];
Joel Einbinder82b1d8e2018-12-08 01:01:371222 // Shadow DOM V0 polyfill
1223 if (majorVersion <= 73 && !Element.prototype.createShadowRoot) {
1224 Element.prototype.createShadowRoot = function() {
1225 try {
1226 return this.attachShadow({mode: 'open'});
1227 } catch (e) {
1228 // some elements we use to add shadow roots can no
1229 // longer have shadow roots.
1230 const fakeShadowHost = document.createElement('span');
1231 this.appendChild(fakeShadowHost);
1232 fakeShadowHost.className = 'fake-shadow-host';
1233 return fakeShadowHost.createShadowRoot();
1234 }
1235 };
1236
1237 const origAdd = DOMTokenList.prototype.add;
1238 DOMTokenList.prototype.add = function(...tokens) {
1239 if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header'))
1240 this._myElement.slot = '.' + tokens[0];
1241 return origAdd.apply(this, tokens);
1242 };
1243
1244 const origCreateElement = Document.prototype.createElement;
1245 Document.prototype.createElement = function(tagName, ...rest) {
1246 if (tagName === 'content')
1247 tagName = 'slot';
1248 const element = origCreateElement.call(this, tagName, ...rest);
1249 element.classList._myElement = element;
1250 return element;
1251 };
1252
1253 Object.defineProperty(HTMLSlotElement.prototype, 'select', {
1254 async set(selector) {
1255 this.name = selector;
1256 }
1257 });
Joel Einbinderb948ebc2018-12-12 02:01:121258
1259 // Document.prototype.createElementWithClass is a DevTools method, so we
1260 // need to wait for DOMContentLoaded in order to override it.
1261 if (window.document.head &&
1262 (window.document.readyState === 'complete' || window.document.readyState === 'interactive'))
1263 overrideCreateElementWithClass();
1264 else
1265 window.addEventListener('DOMContentLoaded', overrideCreateElementWithClass);
1266
1267 function overrideCreateElementWithClass() {
1268 window.removeEventListener('DOMContentLoaded', overrideCreateElementWithClass);
1269
1270 const origCreateElementWithClass = Document.prototype.createElementWithClass;
1271 Document.prototype.createElementWithClass = function(tagName, className, ...rest) {
1272 if (tagName !== 'button' || (className !== 'soft-dropdown' && className !== 'dropdown-button'))
1273 return origCreateElementWithClass.call(this, tagName, className, ...rest);
1274 const element = origCreateElementWithClass.call(this, 'div', className, ...rest);
1275 element.tabIndex = 0;
1276 element.role = 'button';
1277 return element;
1278 };
1279 }
1280 }
1281
1282 // Custom Elements V0 polyfill
1283 if (majorVersion <= 73 && !Document.prototype.registerElement) {
1284 const fakeRegistry = new Map();
1285 Document.prototype.registerElement = function(typeExtension, options) {
1286 const {prototype, extends: localName} = options;
1287 const document = this;
1288 const callback = function() {
1289 const element = document.createElement(localName || typeExtension);
1290 const skip = new Set(['constructor', '__proto__']);
1291 for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
1292 if (skip.has(key))
1293 continue;
1294 element[key] = prototype[key];
1295 }
1296 element.setAttribute('is', typeExtension);
1297 if (element['createdCallback'])
1298 element['createdCallback']();
1299 return element;
1300 };
1301 fakeRegistry.set(typeExtension, callback);
1302 return callback;
1303 };
1304
1305 const origCreateElement = Document.prototype.createElement;
1306 Document.prototype.createElement = function(tagName, fakeCustomElementType) {
1307 const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
1308 if (fakeConstructor)
1309 return fakeConstructor();
1310 return origCreateElement.call(this, tagName, fakeCustomElementType);
Joel Einbinder82b1d8e2018-12-08 01:01:371311 };
Pavel Feldman876d7182018-12-14 00:11:051312
1313 // DevTools front-ends mistakenly assume that
1314 // classList.toggle('a', undefined) works as
1315 // classList.toggle('a', false) rather than as
1316 // classList.toggle('a');
1317 const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
1318 DOMTokenList.prototype.toggle = function(token, force) {
1319 if (arguments.length === 1)
1320 force = !this.contains(token);
1321 return originalDOMTokenListToggle.call(this, token, !!force);
1322 };
Joel Einbinder82b1d8e2018-12-08 01:01:371323 }
Blink Reformat4c46d092018-04-07 15:32:371324
Joel Einbinderf55cc942018-10-30 01:59:531325 if (majorVersion <= 66) {
1326 /** @type {(!function(number, number):Element|undefined)} */
1327 ShadowRoot.prototype.__originalShadowRootElementFromPoint;
1328
1329 if (!ShadowRoot.prototype.__originalShadowRootElementFromPoint) {
1330 ShadowRoot.prototype.__originalShadowRootElementFromPoint = ShadowRoot.prototype.elementFromPoint;
1331 /**
1332 * @param {number} x
1333 * @param {number} y
1334 * @return {Element}
1335 */
1336 ShadowRoot.prototype.elementFromPoint = function(x, y) {
1337 const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
1338 if (this.host && originalResult === this.host)
1339 return null;
1340 return originalResult;
1341 };
1342 }
Blink Reformat4c46d092018-04-07 15:32:371343 }
1344
Joel Einbinderf55cc942018-10-30 01:59:531345 if (majorVersion <= 53) {
Blink Reformat4c46d092018-04-07 15:32:371346 Object.defineProperty(window.KeyboardEvent.prototype, 'keyIdentifier', {
1347 /**
1348 * @return {string}
1349 * @this {KeyboardEvent}
1350 */
1351 get: function() {
1352 return keyCodeToKeyIdentifier(this.keyCode);
1353 }
1354 });
1355 }
1356
Joel Einbinderf55cc942018-10-30 01:59:531357 if (majorVersion <= 50)
1358 installObjectObserve();
Blink Reformat4c46d092018-04-07 15:32:371359
Joel Einbinderf55cc942018-10-30 01:59:531360 if (majorVersion <= 45) {
1361 /**
1362 * @param {string} property
1363 * @return {!CSSValue|null}
1364 * @this {CSSStyleDeclaration}
1365 */
1366 function getValue(property) {
1367 // Note that |property| comes from another context, so we can't use === here.
1368 // eslint-disable-next-line eqeqeq
1369 if (property == 'padding-left') {
1370 return /** @type {!CSSValue} */ ({
1371 /**
1372 * @return {number}
1373 * @this {!{__paddingLeft: number}}
1374 */
1375 getFloatValue: function() {
1376 return this.__paddingLeft;
1377 },
1378 __paddingLeft: parseFloat(this.paddingLeft)
1379 });
1380 }
1381 throw new Error('getPropertyCSSValue is undefined');
Blink Reformat4c46d092018-04-07 15:32:371382 }
Joel Einbinderf55cc942018-10-30 01:59:531383
1384 window.CSSStyleDeclaration.prototype.getPropertyCSSValue = getValue;
1385
1386 function CSSPrimitiveValue() {
1387 }
1388 CSSPrimitiveValue.CSS_PX = 5;
1389 window.CSSPrimitiveValue = CSSPrimitiveValue;
Blink Reformat4c46d092018-04-07 15:32:371390 }
1391
Joel Einbinderf55cc942018-10-30 01:59:531392 if (majorVersion <= 45)
1393 styleRules.push('* { min-width: 0; min-height: 0; }');
Blink Reformat4c46d092018-04-07 15:32:371394
Joel Einbinderf55cc942018-10-30 01:59:531395 if (majorVersion <= 51) {
1396 // Support for quirky border-image behavior (<M51), see:
1397 // https://bugs.chromium.org/p/chromium/issues/detail?id=559258
1398 styleRules.push('.cm-breakpoint .CodeMirror-linenumber { border-style: solid !important; }');
1399 styleRules.push(
1400 '.cm-breakpoint.cm-breakpoint-conditional .CodeMirror-linenumber { border-style: solid !important; }');
Blink Reformat4c46d092018-04-07 15:32:371401 }
Christian Biesinger2d1b2e92018-11-06 01:18:251402 if (majorVersion <= 71) {
1403 styleRules.push(
1404 '.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
1405 }
Blink Reformat4c46d092018-04-07 15:32:371406
Joel Einbinderf55cc942018-10-30 01:59:531407 if (majorVersion <= 50)
1408 Event.prototype.deepPath = undefined;
Blink Reformat4c46d092018-04-07 15:32:371409
Joel Einbinderf55cc942018-10-30 01:59:531410 if (majorVersion <= 54) {
1411 window.FileError = /** @type {!function (new: FileError) : ?} */ ({
1412 NOT_FOUND_ERR: DOMException.NOT_FOUND_ERR,
1413 ABORT_ERR: DOMException.ABORT_ERR,
1414 INVALID_MODIFICATION_ERR: DOMException.INVALID_MODIFICATION_ERR,
1415 NOT_READABLE_ERR: 0 // No matching DOMException, so code will be 0.
1416 });
1417 }
Blink Reformat4c46d092018-04-07 15:32:371418
Joel Einbinderf55cc942018-10-30 01:59:531419 installExtraStyleRules(styleRules);
1420 }
Blink Reformat4c46d092018-04-07 15:32:371421
Joel Einbinderf55cc942018-10-30 01:59:531422 /**
1423 * @return {?number}
1424 */
1425 function getRemoteMajorVersion() {
1426 try {
Joel Einbinder09f48742019-02-28 01:34:421427 const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
Joel Einbinderf55cc942018-10-30 01:59:531428 if (!remoteVersion)
1429 return null;
1430 const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
1431 return majorVersion;
Joel Einbinder31904782018-11-02 20:52:271432 } catch (e) {
Joel Einbinderf55cc942018-10-30 01:59:531433 return null;
1434 }
1435 }
1436
1437 /**
1438 * @param {!Array<string>} styleRules
1439 */
1440 function installExtraStyleRules(styleRules) {
1441 if (!styleRules.length)
1442 return;
1443 const styleText = styleRules.join('\n');
1444 document.head.appendChild(createStyleElement(styleText));
1445
1446 const origCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
1447 HTMLElement.prototype.createShadowRoot = function(...args) {
1448 const shadowRoot = origCreateShadowRoot.call(this, ...args);
1449 shadowRoot.appendChild(createStyleElement(styleText));
1450 return shadowRoot;
1451 };
1452 }
1453
1454 /**
1455 * @param {string} styleText
1456 * @return {!Element}
1457 */
1458 function createStyleElement(styleText) {
1459 const style = document.createElement('style');
1460 style.type = 'text/css';
1461 style.textContent = styleText;
1462 return style;
Blink Reformat4c46d092018-04-07 15:32:371463 }
1464
Joel Einbinderb948ebc2018-12-12 02:01:121465 installBackwardsCompatibility();
Blink Reformat4c46d092018-04-07 15:32:371466
Blink Reformat4c46d092018-04-07 15:32:371467})(window);