devtools_compatibility.js 41 KB

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