import { reactive } from 'vue' import type { ResourceService } from './ResourceService' import type { ApplicationSandboxEngine } from './ApplicationSandboxEngine' import { v4 as uuidv4 } from 'uuid' import { externalAppDiscovery } from './ExternalAppDiscovery' import type { WindowFormService } from '@/services/WindowFormService.ts' /** * 应用状态枚举 */ export enum AppLifecycleState { INSTALLING = 'installing', INSTALLED = 'installed', STARTING = 'starting', RUNNING = 'running', SUSPENDED = 'suspended', STOPPING = 'stopping', STOPPED = 'stopped', UNINSTALLING = 'uninstalling', ERROR = 'error', CRASHED = 'crashed', AVAILABLE = 'available' // 外置应用可用但未注册状态 } /** * 应用清单文件接口 */ export interface AppManifest { id: string name: string version: string description: string author: string homepage?: string icon: string entryPoint: string // 入口文件路径 permissions: string[] minSystemVersion?: string dependencies?: Record window?: { width: number height: number minWidth?: number minHeight?: number maxWidth?: number maxHeight?: number resizable?: boolean center?: boolean } background?: { persistent?: boolean scripts?: string[] } contentSecurity?: { policy?: string allowedDomains?: string[] } } /** * 应用实例接口 */ export interface AppInstance { id: string manifest: AppManifest state: AppLifecycleState windowId?: string sandboxId?: string processId: string installedAt: Date startedAt?: Date lastActiveAt?: Date stoppedAt?: Date errorCount: number crashCount: number memoryUsage: number cpuUsage: number version: string autoStart: boolean persistent: boolean } /** * 应用启动选项 */ export interface AppStartOptions { windowConfig?: { x?: number y?: number width?: number height?: number state?: 'normal' | 'minimized' | 'maximized' } args?: Record background?: boolean } /** * 应用生命周期事件 */ export interface AppLifecycleEvents { onInstalled: (appId: string, manifest: AppManifest) => void onUninstalled: (appId: string) => void onStarted: (appId: string, processId: string) => void onStopped: (appId: string, processId: string) => void onSuspended: (appId: string, processId: string) => void onResumed: (appId: string, processId: string) => void onError: (appId: string, error: Error) => void onCrashed: (appId: string, reason: string) => void onStateChanged: (appId: string, newState: AppLifecycleState, oldState: AppLifecycleState) => void } /** * 应用生命周期管理器 */ export class ApplicationLifecycleManager { private installedApps = reactive(new Map()) private runningProcesses = reactive(new Map()) private appFiles = new Map>() // 应用文件存储 private windowFormService: WindowFormService private resourceService: ResourceService private sandboxEngine: ApplicationSandboxEngine constructor( windowFormService: WindowFormService, resourceService: ResourceService, sandboxEngine: ApplicationSandboxEngine ) { this.windowFormService = windowFormService this.resourceService = resourceService this.sandboxEngine = sandboxEngine } /** * 启动应用 */ async startApp(appId: string, options: AppStartOptions = {}): Promise { let app = this.installedApps.get(appId) console.log('-----------------------------') // 如果应用未安装,检查是否为外置应用 let isExternalApp = false if (!app) { const externalApp = externalAppDiscovery.getApp(appId) if (externalApp) { console.log(`[LifecycleManager] 发现外置应用 ${appId}`) isExternalApp = true // 为外部应用创建临时实例 const now = new Date() app = { id: externalApp.manifest.id, manifest: externalApp.manifest, state: AppLifecycleState.INSTALLED, processId: '', installedAt: now, errorCount: 0, crashCount: 0, memoryUsage: 0, cpuUsage: 0, version: externalApp.manifest.version, autoStart: false, persistent: false } } } if (!app) { throw new Error(`应用 ${appId} 未安装且未发现`) } if (app.state === AppLifecycleState.RUNNING) { throw new Error(`应用 ${appId} 已在运行`) } try { const processId = uuidv4() app.processId = processId this.updateAppState(app, AppLifecycleState.STARTING) // 检查是否为内置应用 let isBuiltInApp = true // 创建窗体(如果不是后台应用) let windowId: string | undefined if (!options.background && !app.manifest.background?.scripts) { const windowConfig = { title: app.manifest.name, width: options.windowConfig?.width || app.manifest.window?.width || 800, height: options.windowConfig?.height || app.manifest.window?.height || 600, x: options.windowConfig?.x, y: options.windowConfig?.y, resizable: app.manifest.window?.resizable !== false, minWidth: app.manifest.window?.minWidth, minHeight: app.manifest.window?.minHeight, maxWidth: app.manifest.window?.maxWidth, maxHeight: app.manifest.window?.maxHeight } const windowInstance = await this.windowFormService.createWindow(appId, windowConfig) windowId = windowInstance.id app.windowId = windowId } // 对于外置应用,需要创建沙箱;内置应用跳过沙箱 if (isExternalApp && !isBuiltInApp) { // 为外置应用创建沙箱 const sandboxConfig = { securityLevel: 2, // HIGH allowScripts: true, allowSameOrigin: false, // 安全考虑:不允许同源访问以防止沙箱逃逸 allowForms: true, networkTimeout: 15000, // 增加超时时间到15秒 csp: app.manifest.contentSecurity?.policy || "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self';" } const sandbox = await this.sandboxEngine.createSandbox( appId, windowId || 'background', sandboxConfig ) app.sandboxId = sandbox.id // 为外置应用加载代码 await this.loadExternalAppInSandbox(app, sandbox.id) } else if (isBuiltInApp) { console.log(`[LifecycleManager] 内置应用 ${appId} 跳过沙箱创建和代码加载`) } else { console.warn(`[LifecycleManager] 未知应用类型: ${appId}`) } // 更新状态 const now = new Date() app.startedAt = now app.lastActiveAt = now this.updateAppState(app, AppLifecycleState.RUNNING) // 添加到运行进程列表 this.runningProcesses.set(processId, app) // 注意:状态变更消息由updateAppState方法自动发送,不需要手动发送 console.log(`应用 ${app.manifest.name} (${appId}) 启动成功,进程ID: ${processId}`) return processId } catch (error) { this.updateAppState(app, AppLifecycleState.ERROR) app.errorCount++ console.error('应用启动失败:', error) throw error } } /** * 停止应用 */ async stopApp(appId: string): Promise { // 首先从已安装应用中查找 let app = this.installedApps.get(appId) // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) if (!app) { for (const runningApp of this.runningProcesses.values()) { if (runningApp.id === appId) { app = runningApp break } } } if (!app) { throw new Error(`应用 ${appId} 未安装或未运行`) } if (app.state !== AppLifecycleState.RUNNING && app.state !== AppLifecycleState.SUSPENDED) { return true } try { this.updateAppState(app, AppLifecycleState.STOPPING) // 销毁沙箱 if (app.sandboxId) { this.sandboxEngine.destroySandbox(app.sandboxId) app.sandboxId = undefined } // 关闭窗体(如果还存在) if (app.windowId) { const window = this.windowFormService.getWindow(app.windowId) if (window) { await this.windowFormService.destroyWindow(app.windowId) } app.windowId = undefined } // 更新状态 app.stoppedAt = new Date() this.updateAppState(app, AppLifecycleState.STOPPED) // 从运行进程列表中移除 if (app.processId) { this.runningProcesses.delete(app.processId) app.processId = '' } // 注意:状态变更消息由updateAppState方法自动发送,不需要手动发送 console.log(`应用 ${appId} 停止成功`) return true } catch (error) { console.error('应用停止失败:', error) return false } } /** * 获取应用信息 */ getApp(appId: string): AppInstance | undefined { return this.installedApps.get(appId) } /** * 获取所有已安装应用 */ getAllApps(): AppInstance[] { return Array.from(this.installedApps.values()) } /** * 获取正在运行的应用 */ getRunningApps(): AppInstance[] { return Array.from(this.runningProcesses.values()) } /** * 检查应用是否正在运行 */ isAppRunning(appId: string): boolean { // 首先从已安装应用中查找 let app = this.installedApps.get(appId) // 如果未找到,从运行进程列表中查找(可能是外部应用的临时实例) if (!app) { for (const runningApp of this.runningProcesses.values()) { if (runningApp.id === appId) { app = runningApp break } } } return app?.state === AppLifecycleState.RUNNING || app?.state === AppLifecycleState.SUSPENDED } /** * 获取应用统计信息 */ getAppStats(appId: string) { const app = this.installedApps.get(appId) if (!app) return null return { state: app.state, errorCount: app.errorCount, crashCount: app.crashCount, memoryUsage: app.memoryUsage, cpuUsage: app.cpuUsage, startedAt: app.startedAt, lastActiveAt: app.lastActiveAt, uptime: app.startedAt ? Date.now() - app.startedAt.getTime() : 0 } } /** * 检查权限 */ private async checkPermissions(permissions: string[]): Promise { for (const permission of permissions) { // 这里可以添加权限检查逻辑 // 目前简单允许所有权限 console.log(`检查权限: ${permission}`) } } /** * 为外置应用加载代码到沙箱 */ private async loadExternalAppInSandbox(app: AppInstance, sandboxId: string): Promise { try { const externalApp = externalAppDiscovery.getApp(app.id) if (!externalApp) { throw new Error('外置应用信息未找到') } // 直接使用外置应用的入口URL const entryUrl = externalApp.entryPath console.log(`[LifecycleManager] 加载外置应用: ${app.id} from ${entryUrl}`) // 在沙箱中加载应用 await this.sandboxEngine.loadApplication(sandboxId, entryUrl) } catch (error) { console.error(`[LifecycleManager] 加载外置应用到沙箱失败:`, error) throw error } } /** * 获取所有可用应用(包括内置和外置) */ getAllAvailableApps(): (AppInstance & { isExternal?: boolean })[] { const apps: (AppInstance & { isExternal?: boolean })[] = [] // 添加已安装的应用 for (const app of this.installedApps.values()) { apps.push(app) } // 添加未注册的外置应用 for (const externalApp of externalAppDiscovery.getDiscoveredApps()) { if (!this.installedApps.has(externalApp.id)) { const appInstance: AppInstance & { isExternal: boolean } = { id: externalApp.manifest.id, manifest: externalApp.manifest, state: AppLifecycleState.AVAILABLE, processId: '', installedAt: externalApp.lastScanned, errorCount: 0, crashCount: 0, memoryUsage: 0, cpuUsage: 0, version: externalApp.manifest.version, autoStart: false, persistent: false, isExternal: true } apps.push(appInstance) } } return apps } /** * 刷新外置应用列表 */ async refreshExternalApps(): Promise { try { await externalAppDiscovery.refresh() console.log('[LifecycleManager] 外置应用列表已刷新') } catch (error) { console.error('[LifecycleManager] 刷新外置应用列表失败:', error) } } /** * 处理应用错误 */ private handleAppError(appId: string, error: Error): void { const app = this.installedApps.get(appId) if (!app) return app.errorCount++ console.error(`应用 ${appId} 发生错误:`, error) } /** * 处理应用崩溃 */ private handleAppCrash(appId: string, reason: string): void { const app = this.installedApps.get(appId) if (!app) return app.crashCount++ this.updateAppState(app, AppLifecycleState.CRASHED) // 清理资源 if (app.processId) { this.runningProcesses.delete(app.processId) } // 注意:状态变更消息由updateAppState方法自动发送,不需要手动发送 console.error(`应用 ${appId} 崩溃: ${reason}`) } /** * 更新应用状态 */ private updateAppState(app: AppInstance, newState: AppLifecycleState): void { const oldState = app.state app.state = newState // 移除事件服务消息发送 // this.eventService.sendMessage('system', 'app-lifecycle', { // type: 'stateChanged', // appId: app.id, // newState, // oldState // }) } }