main.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { app, BrowserWindow, session, ipcMain } from 'electron';
  2. import { fileURLToPath } from 'url';
  3. import path from 'path';
  4. import { exec } from 'child_process';
  5. import { promisify } from 'util';
  6. const execAsync = promisify(exec);
  7. const __filename = fileURLToPath(import.meta.url);
  8. const __dirname = path.dirname(__filename);
  9. const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
  10. // 设置内容安全策略(CSP),防止 XSS 攻击
  11. function setContentSecurityPolicy() {
  12. session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
  13. const csp = isDev
  14. ? "default-src 'self'; script-src 'self' 'unsafe-inline' http://localhost:*; style-src 'self' 'unsafe-inline'; connect-src 'self' http://localhost:* ws://localhost:*; img-src 'self' data: https: blob:; font-src 'self' data:; worker-src 'self' blob:;"
  15. : "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data: https:; font-src 'self' data:;";
  16. const responseHeaders = Object.assign({}, details.responseHeaders);
  17. responseHeaders['Content-Security-Policy'] = [csp];
  18. callback({ responseHeaders });
  19. });
  20. }
  21. // 创建主窗口,根据环境加载不同内容源
  22. function createWindow() {
  23. const mainWindow = new BrowserWindow({
  24. width: 1200,
  25. height: 800,
  26. webPreferences: {
  27. preload: path.join(__dirname, 'preload.cjs'),
  28. nodeIntegration: false,
  29. contextIsolation: true
  30. }
  31. });
  32. if (isDev) {
  33. mainWindow.loadURL('http://localhost:5173');
  34. mainWindow.webContents.openDevTools();
  35. } else {
  36. mainWindow.loadFile(path.join(__dirname, 'dist/index.html'));
  37. }
  38. }
  39. // 获取已连接的 ADB 设备列表
  40. async function getADBDevices() {
  41. try {
  42. const { stdout } = await execAsync('adb devices');
  43. const lines = stdout.split('\n').slice(1);
  44. const devices = [];
  45. for (const line of lines) {
  46. const parts = line.trim().split(/\s+/);
  47. if (parts.length >= 2 && parts[0] && parts[1] === 'device') {
  48. devices.push({
  49. id: parts[0],
  50. status: parts[1]
  51. });
  52. }
  53. }
  54. return devices;
  55. } catch (error) {
  56. console.error('获取设备列表失败:', error);
  57. return [];
  58. }
  59. }
  60. // IPC 处理程序:获取 ADB 设备列表
  61. ipcMain.handle('get-adb-devices', async () => {
  62. return await getADBDevices();
  63. });
  64. // IPC 处理程序:连接 ADB 设备
  65. ipcMain.handle('connect-adb-device', async (event, ipPort) => {
  66. try {
  67. await execAsync(`adb connect ${ipPort}`);
  68. return { success: true };
  69. } catch (error) {
  70. console.error('连接设备失败:', error);
  71. return { success: false, error: error.message };
  72. }
  73. });
  74. // 应用启动逻辑:设置 CSP、创建窗口、监听激活事件
  75. app.whenReady().then(() => {
  76. setContentSecurityPolicy();
  77. createWindow();
  78. app.on('activate', () => {
  79. if (BrowserWindow.getAllWindows().length === 0) {
  80. createWindow();
  81. }
  82. });
  83. });
  84. // 应用关闭逻辑:macOS 保持运行,其他平台退出
  85. app.on('window-all-closed', () => {
  86. if (process.platform !== 'darwin') {
  87. app.quit();
  88. }
  89. });