main.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Deprecated APIs are still supported and should be tested.
  2. process.throwDeprecation = false;
  3. const electron = require('electron');
  4. const { app, BrowserWindow, dialog, ipcMain, session } = electron;
  5. try {
  6. require('fs').rmdirSync(app.getPath('userData'), { recursive: true });
  7. } catch (e) {
  8. console.warn('Warning: couldn\'t clear user data directory:', e);
  9. }
  10. const fs = require('fs');
  11. const path = require('path');
  12. const util = require('util');
  13. const v8 = require('v8');
  14. const argv = require('yargs')
  15. .boolean('ci')
  16. .array('files')
  17. .string('g').alias('g', 'grep')
  18. .boolean('i').alias('i', 'invert')
  19. .argv;
  20. let window = null;
  21. v8.setFlagsFromString('--expose_gc');
  22. app.commandLine.appendSwitch('js-flags', '--expose_gc');
  23. app.commandLine.appendSwitch('ignore-certificate-errors');
  24. app.commandLine.appendSwitch('disable-renderer-backgrounding');
  25. // Disable security warnings (the security warnings test will enable them)
  26. process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = true;
  27. // Accessing stdout in the main process will result in the process.stdout
  28. // throwing UnknownSystemError in renderer process sometimes. This line makes
  29. // sure we can reproduce it in renderer process.
  30. // eslint-disable-next-line
  31. process.stdout
  32. // Access console to reproduce #3482.
  33. // eslint-disable-next-line
  34. console
  35. ipcMain.on('message', function (event, ...args) {
  36. event.sender.send('message', ...args);
  37. });
  38. ipcMain.handle('get-modules', () => Object.keys(electron));
  39. ipcMain.handle('get-temp-dir', () => app.getPath('temp'));
  40. ipcMain.handle('ping', () => null);
  41. // Write output to file if OUTPUT_TO_FILE is defined.
  42. const outputToFile = process.env.OUTPUT_TO_FILE;
  43. const print = function (_, method, args) {
  44. const output = util.format.apply(null, args);
  45. if (outputToFile) {
  46. fs.appendFileSync(outputToFile, output + '\n');
  47. } else {
  48. console[method](output);
  49. }
  50. };
  51. ipcMain.on('console-call', print);
  52. ipcMain.on('process.exit', function (event, code) {
  53. process.exit(code);
  54. });
  55. ipcMain.on('eval', function (event, script) {
  56. event.returnValue = eval(script) // eslint-disable-line
  57. });
  58. ipcMain.on('echo', function (event, msg) {
  59. event.returnValue = msg;
  60. });
  61. process.removeAllListeners('uncaughtException');
  62. process.on('uncaughtException', function (error) {
  63. console.error(error, error.stack);
  64. process.exit(1);
  65. });
  66. global.nativeModulesEnabled = !process.env.ELECTRON_SKIP_NATIVE_MODULE_TESTS;
  67. app.on('window-all-closed', function () {
  68. app.quit();
  69. });
  70. app.on('gpu-process-crashed', (event, killed) => {
  71. console.log(`GPU process crashed (killed=${killed})`);
  72. });
  73. app.on('renderer-process-crashed', (event, contents, killed) => {
  74. console.log(`webContents ${contents.id} crashed: ${contents.getURL()} (killed=${killed})`);
  75. });
  76. app.whenReady().then(async function () {
  77. await session.defaultSession.clearCache();
  78. await session.defaultSession.clearStorageData();
  79. // Test if using protocol module would crash.
  80. electron.protocol.registerStringProtocol('test-if-crashes', function () {});
  81. window = new BrowserWindow({
  82. title: 'Electron Tests',
  83. show: false,
  84. width: 800,
  85. height: 600,
  86. webPreferences: {
  87. backgroundThrottling: false,
  88. nodeIntegration: true,
  89. webviewTag: true,
  90. contextIsolation: false,
  91. nativeWindowOpen: false
  92. }
  93. });
  94. window.loadFile('static/index.html', {
  95. query: {
  96. grep: argv.grep,
  97. invert: argv.invert ? 'true' : '',
  98. files: argv.files ? argv.files.join(',') : undefined
  99. }
  100. });
  101. window.on('unresponsive', function () {
  102. const chosen = dialog.showMessageBox(window, {
  103. type: 'warning',
  104. buttons: ['Close', 'Keep Waiting'],
  105. message: 'Window is not responsing',
  106. detail: 'The window is not responding. Would you like to force close it or just keep waiting?'
  107. });
  108. if (chosen === 0) window.destroy();
  109. });
  110. window.webContents.on('crashed', function () {
  111. console.error('Renderer process crashed');
  112. process.exit(1);
  113. });
  114. });
  115. ipcMain.on('prevent-next-will-attach-webview', (event) => {
  116. event.sender.once('will-attach-webview', event => event.preventDefault());
  117. });
  118. ipcMain.on('disable-node-on-next-will-attach-webview', (event, id) => {
  119. event.sender.once('will-attach-webview', (event, webPreferences, params) => {
  120. params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'c.html')}`;
  121. webPreferences.nodeIntegration = false;
  122. });
  123. });
  124. ipcMain.on('disable-preload-on-next-will-attach-webview', (event, id) => {
  125. event.sender.once('will-attach-webview', (event, webPreferences, params) => {
  126. params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'webview-stripped-preload.html')}`;
  127. delete webPreferences.preload;
  128. delete webPreferences.preloadURL;
  129. });
  130. });
  131. ipcMain.on('handle-uncaught-exception', (event, message) => {
  132. suspendListeners(process, 'uncaughtException', (error) => {
  133. event.returnValue = error.message;
  134. });
  135. fs.readFile(__filename, () => {
  136. throw new Error(message);
  137. });
  138. });
  139. ipcMain.on('handle-unhandled-rejection', (event, message) => {
  140. suspendListeners(process, 'unhandledRejection', (error) => {
  141. event.returnValue = error.message;
  142. });
  143. fs.readFile(__filename, () => {
  144. Promise.reject(new Error(message));
  145. });
  146. });
  147. // Suspend listeners until the next event and then restore them
  148. const suspendListeners = (emitter, eventName, callback) => {
  149. const listeners = emitter.listeners(eventName);
  150. emitter.removeAllListeners(eventName);
  151. emitter.once(eventName, (...args) => {
  152. emitter.removeAllListeners(eventName);
  153. listeners.forEach((listener) => {
  154. emitter.on(eventName, listener);
  155. });
  156. // eslint-disable-next-line standard/no-callback-literal
  157. callback(...args);
  158. });
  159. };