inspector.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. 'use strict'
  2. const { getRemote, potentiallyRemoteRequire } = require('@electron/internal/renderer/remote')
  3. window.onload = function () {
  4. // Use menu API to show context menu.
  5. window.InspectorFrontendHost.showContextMenuAtPoint = createMenu
  6. // correct for Chromium returning undefined for filesystem
  7. window.Persistence.FileSystemWorkspaceBinding.completeURL = completeURL
  8. // Use dialog API to override file chooser dialog.
  9. window.UI.createFileSelectorElement = createFileSelectorElement
  10. }
  11. // Extra / is needed as a result of MacOS requiring absolute paths
  12. function completeURL (project, path) {
  13. project = 'file:///'
  14. return `${project}${path}`
  15. }
  16. window.confirm = function (message, title) {
  17. const dialog = getRemote('dialog')
  18. if (title == null) {
  19. title = ''
  20. }
  21. return !dialog.showMessageBox({
  22. message: message,
  23. title: title,
  24. buttons: ['OK', 'Cancel'],
  25. cancelId: 1
  26. })
  27. }
  28. const convertToMenuTemplate = function (items) {
  29. return items.map(function (item) {
  30. const transformed = item.type === 'subMenu' ? {
  31. type: 'submenu',
  32. label: item.label,
  33. enabled: item.enabled,
  34. submenu: convertToMenuTemplate(item.subItems)
  35. } : item.type === 'separator' ? {
  36. type: 'separator'
  37. } : item.type === 'checkbox' ? {
  38. type: 'checkbox',
  39. label: item.label,
  40. enabled: item.enabled,
  41. checked: item.checked
  42. } : {
  43. type: 'normal',
  44. label: item.label,
  45. enabled: item.enabled
  46. }
  47. if (item.id != null) {
  48. transformed.click = function () {
  49. window.DevToolsAPI.contextMenuItemSelected(item.id)
  50. return window.DevToolsAPI.contextMenuCleared()
  51. }
  52. }
  53. return transformed
  54. })
  55. }
  56. const createMenu = function (x, y, items) {
  57. const Menu = getRemote('Menu')
  58. let template = convertToMenuTemplate(items)
  59. if (useEditMenuItems(x, y, template)) {
  60. template = getEditMenuItems()
  61. }
  62. const menu = Menu.buildFromTemplate(template)
  63. // The menu is expected to show asynchronously.
  64. setTimeout(function () {
  65. const getCurrentWindow = getRemote('getCurrentWindow')
  66. menu.popup({ window: getCurrentWindow() })
  67. })
  68. }
  69. const useEditMenuItems = function (x, y, items) {
  70. return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) {
  71. return element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA' || element.isContentEditable
  72. })
  73. }
  74. const getEditMenuItems = function () {
  75. return [
  76. {
  77. role: 'undo'
  78. },
  79. {
  80. role: 'redo'
  81. },
  82. {
  83. type: 'separator'
  84. },
  85. {
  86. role: 'cut'
  87. },
  88. {
  89. role: 'copy'
  90. },
  91. {
  92. role: 'paste'
  93. },
  94. {
  95. role: 'pasteAndMatchStyle'
  96. },
  97. {
  98. role: 'delete'
  99. },
  100. {
  101. role: 'selectAll'
  102. }
  103. ]
  104. }
  105. const showFileChooserDialog = function (callback) {
  106. const dialog = getRemote('dialog')
  107. const files = dialog.showOpenDialog({})
  108. if (files != null) {
  109. callback(pathToHtml5FileObject(files[0]))
  110. }
  111. }
  112. const pathToHtml5FileObject = function (path) {
  113. const fs = potentiallyRemoteRequire('fs')
  114. const blob = new Blob([fs.readFileSync(path)])
  115. blob.name = path
  116. return blob
  117. }
  118. const createFileSelectorElement = function (callback) {
  119. const fileSelectorElement = document.createElement('span')
  120. fileSelectorElement.style.display = 'none'
  121. fileSelectorElement.click = showFileChooserDialog.bind(this, callback)
  122. return fileSelectorElement
  123. }