default_app.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
  2. import * as path from 'path';
  3. let mainWindow: BrowserWindow | null = null;
  4. // Quit when all windows are closed.
  5. app.on('window-all-closed', () => {
  6. app.quit();
  7. });
  8. function decorateURL (url: string) {
  9. // safely add `?utm_source=default_app
  10. const parsedUrl = new URL(url);
  11. parsedUrl.searchParams.append('utm_source', 'default_app');
  12. return parsedUrl.toString();
  13. }
  14. // Find the shortest path to the electron binary
  15. const absoluteElectronPath = process.execPath;
  16. const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
  17. const electronPath = absoluteElectronPath.length < relativeElectronPath.length
  18. ? absoluteElectronPath
  19. : relativeElectronPath;
  20. const indexPath = path.resolve(app.getAppPath(), 'index.html');
  21. function isTrustedSender (webContents: Electron.WebContents) {
  22. if (webContents !== (mainWindow && mainWindow.webContents)) {
  23. return false;
  24. }
  25. const parsedUrl = new URL(webContents.getURL());
  26. const urlPath = process.platform === 'win32'
  27. // Strip the prefixed "/" that occurs on windows
  28. ? path.resolve(parsedUrl.pathname.substr(1))
  29. : parsedUrl.pathname;
  30. return parsedUrl.protocol === 'file:' && urlPath === indexPath;
  31. }
  32. ipcMain.handle('bootstrap', (event) => {
  33. return isTrustedSender(event.sender) ? electronPath : null;
  34. });
  35. async function createWindow () {
  36. await app.whenReady();
  37. const options: Electron.BrowserWindowConstructorOptions = {
  38. width: 900,
  39. height: 600,
  40. autoHideMenuBar: true,
  41. backgroundColor: '#FFFFFF',
  42. webPreferences: {
  43. preload: path.resolve(__dirname, 'preload.js'),
  44. contextIsolation: true,
  45. sandbox: true,
  46. enableRemoteModule: false
  47. },
  48. useContentSize: true,
  49. show: false
  50. };
  51. if (process.platform === 'linux') {
  52. options.icon = path.join(__dirname, 'icon.png');
  53. }
  54. mainWindow = new BrowserWindow(options);
  55. mainWindow.on('ready-to-show', () => mainWindow!.show());
  56. mainWindow.webContents.on('new-window', (event, url) => {
  57. event.preventDefault();
  58. shell.openExternal(decorateURL(url));
  59. });
  60. mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, done) => {
  61. const parsedUrl = new URL(webContents.getURL());
  62. const options: Electron.MessageBoxOptions = {
  63. title: 'Permission Request',
  64. message: `Allow '${parsedUrl.origin}' to access '${permission}'?`,
  65. buttons: ['OK', 'Cancel'],
  66. cancelId: 1
  67. };
  68. dialog.showMessageBox(mainWindow!, options).then(({ response }) => {
  69. done(response === 0);
  70. });
  71. });
  72. return mainWindow;
  73. }
  74. export const loadURL = async (appUrl: string) => {
  75. mainWindow = await createWindow();
  76. mainWindow.loadURL(appUrl);
  77. mainWindow.focus();
  78. };
  79. export const loadFile = async (appPath: string) => {
  80. mainWindow = await createWindow();
  81. mainWindow.loadFile(appPath);
  82. mainWindow.focus();
  83. };