rpc-server.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
  2. import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
  3. import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
  4. import { clipboard } from 'electron/common';
  5. import * as fs from 'fs';
  6. import * as path from 'path';
  7. // Implements window.close()
  8. ipcMainInternal.on(IPC_MESSAGES.BROWSER_WINDOW_CLOSE, function (event) {
  9. if (event.type !== 'frame') return;
  10. const window = event.sender.getOwnerBrowserWindow();
  11. if (window) {
  12. window.close();
  13. }
  14. event.returnValue = null;
  15. });
  16. ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_LAST_WEB_PREFERENCES, function (event) {
  17. if (event.type !== 'frame') return;
  18. return event.sender.getLastWebPreferences();
  19. });
  20. ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO, function (event) {
  21. if (event.type !== 'frame') return;
  22. return event.sender._getProcessMemoryInfo();
  23. });
  24. // Methods not listed in this set are called directly in the renderer process.
  25. const allowedClipboardMethods = (() => {
  26. switch (process.platform) {
  27. case 'darwin':
  28. return new Set(['readFindText', 'writeFindText']);
  29. case 'linux':
  30. return new Set(Object.keys(clipboard));
  31. default:
  32. return new Set();
  33. }
  34. })();
  35. ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, function (event, method: string, ...args: any[]) {
  36. if (!allowedClipboardMethods.has(method)) {
  37. throw new Error(`Invalid method: ${method}`);
  38. }
  39. return (clipboard as any)[method](...args);
  40. });
  41. const getPreloadScriptsFromEvent = (event: ElectronInternal.IpcMainInternalEvent) => {
  42. const session: Electron.Session = event.type === 'service-worker' ? event.session : event.sender.session;
  43. let preloadScripts = session.getPreloadScripts();
  44. if (event.type === 'frame') {
  45. preloadScripts = preloadScripts.filter(script => script.type === 'frame');
  46. const webPrefPreload = event.sender._getPreloadScript();
  47. if (webPrefPreload) preloadScripts.push(webPrefPreload);
  48. } else if (event.type === 'service-worker') {
  49. preloadScripts = preloadScripts.filter(script => script.type === 'service-worker');
  50. } else {
  51. throw new Error(`getPreloadScriptsFromEvent: event.type is invalid (${(event as any).type})`);
  52. }
  53. // TODO(samuelmaddock): Remove filter after Session.setPreloads is fully
  54. // deprecated. The new API will prevent relative paths from being registered.
  55. return preloadScripts.filter(script => path.isAbsolute(script.filePath));
  56. };
  57. const readPreloadScript = async function (script: Electron.PreloadScript): Promise<ElectronInternal.PreloadScript> {
  58. let contents;
  59. let error;
  60. try {
  61. contents = await fs.promises.readFile(script.filePath, 'utf8');
  62. } catch (err) {
  63. if (err instanceof Error) {
  64. error = err;
  65. }
  66. }
  67. return {
  68. ...script,
  69. contents,
  70. error
  71. };
  72. };
  73. ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event) {
  74. const preloadScripts = getPreloadScriptsFromEvent(event);
  75. return {
  76. preloadScripts: await Promise.all(preloadScripts.map(readPreloadScript)),
  77. process: {
  78. arch: process.arch,
  79. platform: process.platform,
  80. env: { ...process.env },
  81. version: process.version,
  82. versions: process.versions,
  83. execPath: process.helperExecPath
  84. }
  85. };
  86. });
  87. ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_NONSANDBOX_LOAD, function (event) {
  88. const preloadScripts = getPreloadScriptsFromEvent(event);
  89. return { preloadPaths: preloadScripts.map(script => script.filePath) };
  90. });
  91. ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
  92. if (event.type !== 'frame') return;
  93. event.sender?.emit('preload-error', event, preloadPath, error);
  94. });