app.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import * as fs from 'fs';
  2. import { Menu } from 'electron/main';
  3. import * as deprecate from '@electron/internal/common/deprecate';
  4. const bindings = process._linkedBinding('electron_browser_app');
  5. const commandLine = process._linkedBinding('electron_common_command_line');
  6. const { app } = bindings;
  7. // Only one app object permitted.
  8. export default app;
  9. let dockMenu: Electron.Menu | null = null;
  10. // Properties.
  11. const nativeASGetter = app.isAccessibilitySupportEnabled;
  12. const nativeASSetter = app.setAccessibilitySupportEnabled;
  13. Object.defineProperty(app, 'accessibilitySupportEnabled', {
  14. get: () => nativeASGetter.call(app),
  15. set: (enabled) => nativeASSetter.call(app, enabled)
  16. });
  17. const nativeBCGetter = app.getBadgeCount;
  18. const nativeBCSetter = app.setBadgeCount;
  19. Object.defineProperty(app, 'badgeCount', {
  20. get: () => nativeBCGetter.call(app),
  21. set: (count) => nativeBCSetter.call(app, count)
  22. });
  23. const nativeNGetter = app.getName;
  24. const nativeNSetter = app.setName;
  25. Object.defineProperty(app, 'name', {
  26. get: () => nativeNGetter.call(app),
  27. set: (name) => nativeNSetter.call(app, name)
  28. });
  29. Object.assign(app, {
  30. commandLine: {
  31. hasSwitch: (theSwitch: string) => commandLine.hasSwitch(String(theSwitch)),
  32. getSwitchValue: (theSwitch: string) => commandLine.getSwitchValue(String(theSwitch)),
  33. appendSwitch: (theSwitch: string, value?: string) => commandLine.appendSwitch(String(theSwitch), typeof value === 'undefined' ? value : String(value)),
  34. appendArgument: (arg: string) => commandLine.appendArgument(String(arg)),
  35. removeSwitch: (theSwitch: string) => commandLine.removeSwitch(String(theSwitch))
  36. } as Electron.CommandLine
  37. });
  38. // we define this here because it'd be overly complicated to
  39. // do in native land
  40. Object.defineProperty(app, 'applicationMenu', {
  41. get () {
  42. return Menu.getApplicationMenu();
  43. },
  44. set (menu: Electron.Menu | null) {
  45. return Menu.setApplicationMenu(menu);
  46. }
  47. });
  48. // The native implementation is not provided on non-windows platforms
  49. app.setAppUserModelId = app.setAppUserModelId || (() => {});
  50. if (process.platform === 'darwin') {
  51. const setDockMenu = app.dock!.setMenu;
  52. app.dock!.setMenu = (menu) => {
  53. dockMenu = menu;
  54. setDockMenu(menu);
  55. };
  56. app.dock!.getMenu = () => dockMenu;
  57. }
  58. if (process.platform === 'linux') {
  59. const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m;
  60. const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m;
  61. const getStatus = (pid: number) => {
  62. try {
  63. return fs.readFileSync(`/proc/${pid}/status`, 'utf8');
  64. } catch {
  65. return '';
  66. }
  67. };
  68. const getEntry = (file: string, pattern: RegExp) => {
  69. const match = file.match(pattern);
  70. return match ? parseInt(match[1], 10) : 0;
  71. };
  72. const getProcessMemoryInfo = (pid: number) => {
  73. const file = getStatus(pid);
  74. return {
  75. workingSetSize: getEntry(file, patternVmRSS),
  76. peakWorkingSetSize: getEntry(file, patternVmHWM)
  77. };
  78. };
  79. const nativeFn = app.getAppMetrics;
  80. app.getAppMetrics = () => {
  81. const metrics = nativeFn.call(app);
  82. for (const metric of metrics) {
  83. metric.memory = getProcessMemoryInfo(metric.pid);
  84. }
  85. return metrics;
  86. };
  87. }
  88. // Routes the events to webContents.
  89. const events = ['certificate-error', 'select-client-certificate'];
  90. for (const name of events) {
  91. app.on(name as 'certificate-error', (event, webContents, ...args: any[]) => {
  92. webContents.emit(name, event, ...args);
  93. });
  94. }
  95. // Deprecation.
  96. deprecate.event(app, 'gpu-process-crashed', 'child-process-gone', () => {
  97. // the old event is still emitted by App::OnGpuProcessCrashed()
  98. return undefined;
  99. });
  100. deprecate.event(app, 'renderer-process-crashed', 'render-process-gone', (event: Electron.Event, webContents: Electron.WebContents, details: Electron.RenderProcessGoneDetails) => {
  101. return [event, webContents, details.reason === 'killed'];
  102. });