main.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Disable use of deprecated functions.
  2. process.throwDeprecation = true
  3. const electron = require('electron')
  4. const app = electron.app
  5. const crashReporter = electron.crashReporter
  6. const ipcMain = electron.ipcMain
  7. const dialog = electron.dialog
  8. const BrowserWindow = electron.BrowserWindow
  9. const protocol = electron.protocol
  10. const webContents = electron.webContents
  11. const v8 = require('v8')
  12. const Coverage = require('electabul').Coverage
  13. const fs = require('fs')
  14. const path = require('path')
  15. const url = require('url')
  16. const util = require('util')
  17. var argv = require('yargs')
  18. .boolean('ci')
  19. .string('g').alias('g', 'grep')
  20. .boolean('i').alias('i', 'invert')
  21. .argv
  22. var window = null
  23. process.port = 0 // will be used by crash-reporter spec.
  24. v8.setFlagsFromString('--expose_gc')
  25. app.commandLine.appendSwitch('js-flags', '--expose_gc')
  26. app.commandLine.appendSwitch('ignore-certificate-errors')
  27. app.commandLine.appendSwitch('disable-renderer-backgrounding')
  28. // Accessing stdout in the main process will result in the process.stdout
  29. // throwing UnknownSystemError in renderer process sometimes. This line makes
  30. // sure we can reproduce it in renderer process.
  31. process.stdout
  32. // Access console to reproduce #3482.
  33. console
  34. ipcMain.on('message', function (event, ...args) {
  35. event.sender.send('message', ...args)
  36. })
  37. // Set productName so getUploadedReports() uses the right directory in specs
  38. if (process.platform !== 'darwin') {
  39. crashReporter.productName = 'Zombies'
  40. }
  41. // Write output to file if OUTPUT_TO_FILE is defined.
  42. const outputToFile = process.env.OUTPUT_TO_FILE
  43. const print = function (_, args) {
  44. let output = util.format.apply(null, args)
  45. if (outputToFile) {
  46. fs.appendFileSync(outputToFile, output + '\n')
  47. } else {
  48. console.error(output)
  49. }
  50. }
  51. ipcMain.on('console.log', print)
  52. ipcMain.on('console.error', print)
  53. ipcMain.on('process.exit', function (event, code) {
  54. process.exit(code)
  55. })
  56. ipcMain.on('eval', function (event, script) {
  57. event.returnValue = eval(script) // eslint-disable-line
  58. })
  59. ipcMain.on('echo', function (event, msg) {
  60. event.returnValue = msg
  61. })
  62. const coverage = new Coverage({
  63. outputPath: path.join(__dirname, '..', '..', 'out', 'coverage')
  64. })
  65. coverage.setup()
  66. ipcMain.on('get-main-process-coverage', function (event) {
  67. event.returnValue = global.__coverage__ || null
  68. })
  69. global.isCi = !!argv.ci
  70. if (global.isCi) {
  71. process.removeAllListeners('uncaughtException')
  72. process.on('uncaughtException', function (error) {
  73. console.error(error, error.stack)
  74. process.exit(1)
  75. })
  76. }
  77. // Register app as standard scheme.
  78. global.standardScheme = 'app'
  79. protocol.registerStandardSchemes([global.standardScheme], { secure: true })
  80. app.on('window-all-closed', function () {
  81. app.quit()
  82. })
  83. app.on('ready', function () {
  84. // Test if using protocol module would crash.
  85. electron.protocol.registerStringProtocol('test-if-crashes', function () {})
  86. // Send auto updater errors to window to be verified in specs
  87. electron.autoUpdater.on('error', function (error) {
  88. window.send('auto-updater-error', error.message)
  89. })
  90. window = new BrowserWindow({
  91. title: 'Electron Tests',
  92. show: !global.isCi,
  93. width: 800,
  94. height: 600,
  95. webPreferences: {
  96. backgroundThrottling: false
  97. }
  98. })
  99. window.loadURL(url.format({
  100. pathname: path.join(__dirname, '/index.html'),
  101. protocol: 'file',
  102. query: {
  103. grep: argv.grep,
  104. invert: argv.invert ? 'true' : ''
  105. }
  106. }))
  107. window.on('unresponsive', function () {
  108. var chosen = dialog.showMessageBox(window, {
  109. type: 'warning',
  110. buttons: ['Close', 'Keep Waiting'],
  111. message: 'Window is not responsing',
  112. detail: 'The window is not responding. Would you like to force close it or just keep waiting?'
  113. })
  114. if (chosen === 0) window.destroy()
  115. })
  116. // For session's download test, listen 'will-download' event in browser, and
  117. // reply the result to renderer for verifying
  118. var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf')
  119. ipcMain.on('set-download-option', function (event, needCancel, preventDefault, filePath = downloadFilePath) {
  120. window.webContents.session.once('will-download', function (e, item) {
  121. window.webContents.send('download-created',
  122. item.getState(),
  123. item.getURLChain(),
  124. item.getMimeType(),
  125. item.getReceivedBytes(),
  126. item.getTotalBytes(),
  127. item.getFilename(),
  128. item.getSavePath())
  129. if (preventDefault) {
  130. e.preventDefault()
  131. const url = item.getURL()
  132. const filename = item.getFilename()
  133. setImmediate(function () {
  134. try {
  135. item.getURL()
  136. } catch (err) {
  137. window.webContents.send('download-error', url, filename, err.message)
  138. }
  139. })
  140. } else {
  141. if (item.getState() === 'interrupted' && !needCancel) {
  142. item.resume()
  143. } else {
  144. item.setSavePath(filePath)
  145. }
  146. item.on('done', function (e, state) {
  147. window.webContents.send('download-done',
  148. state,
  149. item.getURL(),
  150. item.getMimeType(),
  151. item.getReceivedBytes(),
  152. item.getTotalBytes(),
  153. item.getContentDisposition(),
  154. item.getFilename(),
  155. item.getSavePath(),
  156. item.getURLChain(),
  157. item.getLastModifiedTime(),
  158. item.getETag())
  159. })
  160. if (needCancel) item.cancel()
  161. }
  162. })
  163. event.returnValue = 'done'
  164. })
  165. ipcMain.on('prevent-next-input-event', (event, key, id) => {
  166. webContents.fromId(id).once('before-input-event', (event, input) => {
  167. if (key === input.key) event.preventDefault()
  168. })
  169. })
  170. ipcMain.on('executeJavaScript', function (event, code, hasCallback) {
  171. if (hasCallback) {
  172. window.webContents.executeJavaScript(code, (result) => {
  173. window.webContents.send('executeJavaScript-response', result)
  174. }).then((result) => {
  175. window.webContents.send('executeJavaScript-promise-response', result)
  176. }).catch((err) => {
  177. window.webContents.send('executeJavaScript-promise-error', err)
  178. })
  179. } else {
  180. window.webContents.executeJavaScript(code)
  181. event.returnValue = 'success'
  182. }
  183. })
  184. })
  185. ipcMain.on('set-client-certificate-option', function (event, skip) {
  186. app.once('select-client-certificate', function (event, webContents, url, list, callback) {
  187. event.preventDefault()
  188. if (skip) {
  189. callback()
  190. } else {
  191. ipcMain.on('client-certificate-response', function (event, certificate) {
  192. callback(certificate)
  193. })
  194. window.webContents.send('select-client-certificate', webContents.id, list)
  195. }
  196. })
  197. event.returnValue = 'done'
  198. })
  199. ipcMain.on('close-on-will-navigate', (event, id) => {
  200. const contents = event.sender
  201. const window = BrowserWindow.fromId(id)
  202. window.webContents.once('will-navigate', (event, input) => {
  203. window.close()
  204. contents.send('closed-on-will-navigate')
  205. })
  206. })
  207. ipcMain.on('create-window-with-options-cycle', (event) => {
  208. // This can't be done over remote since cycles are already
  209. // nulled out at the IPC layer
  210. const foo = {}
  211. foo.bar = foo
  212. foo.baz = {
  213. hello: {
  214. world: true
  215. }
  216. }
  217. foo.baz2 = foo.baz
  218. const window = new BrowserWindow({show: false, foo: foo})
  219. event.returnValue = window.id
  220. })
  221. ipcMain.on('prevent-next-new-window', (event, id) => {
  222. webContents.fromId(id).once('new-window', event => event.preventDefault())
  223. })