import { reactive } from 'vue' import type { WindowService } from './WindowService' import type { ResourceService } from './ResourceService' import type { EventCommunicationService } from './EventCommunicationService' import type { ApplicationSandboxEngine } from './ApplicationSandboxEngine' import { v4 as uuidv4 } from 'uuid' import { externalAppDiscovery } from './ExternalAppDiscovery' /** * 应用状态枚举 */ 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 AppPackage { manifest: AppManifest files: Map // 文件路径到内容的映射 signature?: string // 数字签名 checksum: string // 校验和 } /** * 应用启动选项 */ 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 windowService: WindowService private resourceService: ResourceService private eventService: EventCommunicationService private sandboxEngine: ApplicationSandboxEngine constructor( windowService: WindowService, resourceService: ResourceService, eventService: EventCommunicationService, sandboxEngine: ApplicationSandboxEngine, ) { this.windowService = windowService this.resourceService = resourceService this.eventService = eventService this.sandboxEngine = sandboxEngine this.setupEventListeners() this.loadInstalledApps() // 外部应用发现已由 SystemServiceIntegration 统一管理,无需重复初始化 } /** * 安装应用 */ async installApp(appPackage: AppPackage): Promise { const { manifest, files, checksum } = appPackage const appId = manifest.id try { // 检查应用是否已安装 if (this.installedApps.has(appId)) { throw new Error(`应用 ${appId} 已安装`) } // 验证清单文件 this.validateManifest(manifest) // 验证校验和 if (!this.verifyChecksum(files, checksum)) { throw new Error('应用包校验失败') } // 检查权限 await this.checkPermissions(manifest.permissions) const now = new Date() const appInstance: AppInstance = { id: appId, manifest, state: AppLifecycleState.INSTALLING, processId: '', installedAt: now, errorCount: 0, crashCount: 0, memoryUsage: 0, cpuUsage: 0, version: manifest.version, autoStart: false, persistent: manifest.background?.persistent || false, } // 更新状态 this.updateAppState(appInstance, AppLifecycleState.INSTALLING) this.installedApps.set(appId, appInstance) // 存储应用文件 this.appFiles.set(appId, files) // 保存到本地存储 await this.saveAppToStorage(appInstance) // 更新状态为已安装 this.updateAppState(appInstance, AppLifecycleState.INSTALLED) this.eventService.sendMessage('system', 'app-lifecycle', { type: 'installed', appId, manifest, }) console.log(`应用 ${manifest.name} (${appId}) 安装成功`) return appId } catch (error) { // 清理安装失败的应用 this.installedApps.delete(appId) this.appFiles.delete(appId) console.error('应用安装失败:', error) throw error } } /** * 卸载应用 */ async uninstallApp(appId: string): Promise { const app = this.installedApps.get(appId) if (!app) { throw new Error(`应用 ${appId} 未安装`) } try { // 如果应用正在运行,先停止 if (app.state === AppLifecycleState.RUNNING || app.state === AppLifecycleState.SUSPENDED) { await this.stopApp(appId) } this.updateAppState(app, AppLifecycleState.UNINSTALLING) // 清理应用数据 await this.resourceService.clearStorage(appId) await this.resourceService.revokeAllPermissions(appId) // 删除应用文件 this.appFiles.delete(appId) // 从存储中删除 await this.removeAppFromStorage(appId) // 从已安装列表中移除 this.installedApps.delete(appId) this.eventService.sendMessage('system', 'app-lifecycle', { type: 'uninstalled', appId, }) console.log(`应用 ${appId} 卸载成功`) return true } catch (error) { console.error('应用卸载失败:', error) throw error } } /** * 启动应用 */ async startApp(appId: string, options: AppStartOptions = {}): Promise { let app = this.installedApps.get(appId) // 如果应用未安装,检查是否为外置应用 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 = false try { const { AppRegistry } = await import('../apps/AppRegistry') const appRegistry = AppRegistry.getInstance() isBuiltInApp = appRegistry.hasApp(appId) } catch (error) { console.warn('无法导入 AppRegistry') } // 检查是否为外置应用(仅当不是内置应用时) // 修复:移除重复的变量声明,使用已声明的isExternalApp变量 if (!isBuiltInApp && !isExternalApp) { isExternalApp = externalAppDiscovery.hasApp(appId) } // 创建窗体(如果不是后台应用) 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.windowService.createWindow(appId, windowConfig) windowId = windowInstance.id app.windowId = windowId // 对于内置应用,需要在窗口内容区域挂载 AppRenderer 组件 if (isBuiltInApp) { await this.mountBuiltInApp(appId, windowInstance) } // 对于内置应用,不需要等待窗口DOM元素渲染 if (!isBuiltInApp) { // 稍等片刻确保窗口DOM元素已经渲染完成 await new Promise((resolve) => setTimeout(resolve, 100)) } } // 对于外置应用,需要创建沙箱;内置应用跳过沙箱 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.windowService.getWindow(app.windowId) if (window) { await this.windowService.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 } } /** * 暂停应用 */ async suspendApp(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 || app.state !== AppLifecycleState.RUNNING) { return false } try { // 暂停沙箱 if (app.sandboxId) { this.sandboxEngine.suspendSandbox(app.sandboxId) } // 最小化窗体 if (app.windowId) { this.windowService.minimizeWindow(app.windowId) } this.updateAppState(app, AppLifecycleState.SUSPENDED) // 注意:状态变更消息由updateAppState方法自动发送,不需要手动发送 console.log(`应用 ${appId} 已暂停`) return true } catch (error) { console.error('应用暂停失败:', error) return false } } /** * 恢复应用 */ async resumeApp(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 || app.state !== AppLifecycleState.SUSPENDED) { return false } try { // 恢复沙箱 if (app.sandboxId) { this.sandboxEngine.resumeSandbox(app.sandboxId) } // 恢复窗体 if (app.windowId) { this.windowService.restoreWindow(app.windowId) } app.lastActiveAt = new Date() this.updateAppState(app, AppLifecycleState.RUNNING) // 注意:状态变更消息由updateAppState方法自动发送,不需要手动发送 console.log(`应用 ${appId} 已恢复`) return true } catch (error) { console.error('应用恢复失败:', error) return false } } /** * 重启应用 */ async restartApp(appId: string, options?: AppStartOptions): Promise { await this.stopApp(appId) // 等待一小段时间确保完全停止 await new Promise((resolve) => setTimeout(resolve, 1000)) return this.startApp(appId, options) } /** * 获取应用信息 */ 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, } } // 私有方法 /** * 为内置应用挂载 AppRenderer 组件 */ private async mountBuiltInApp(appId: string, windowInstance: any): Promise { try { // 动态导入 Vue 和 AppRenderer const { createApp } = await import('vue') const AppRenderer = (await import('../ui/components/AppRenderer.vue')).default console.log(`[LifecycleManager] 为内置应用 ${appId} 创建 AppRenderer 组件`) const app = createApp({ components: { AppRenderer }, template: ``, }) // 提供系统服务(使用当前实例所在的系统服务) app.provide('systemService', { getWindowService: () => this.windowService, getResourceService: () => this.resourceService, getEventService: () => this.eventService, getSandboxEngine: () => this.sandboxEngine, getLifecycleManager: () => this, }) // 挂载到窗口内容区域 const contentArea = windowInstance.element?.querySelector('.window-content') if (contentArea) { app.mount(contentArea) console.log(`[LifecycleManager] AppRenderer 组件已挂载到窗口 ${windowInstance.id}`) } else { throw new Error('未找到窗口内容区域') } } catch (error) { console.error(`内置应用 ${appId} 挂载失败:`, error) throw error } } /** * 验证应用清单文件 */ private validateManifest(manifest: AppManifest): void { const required = ['id', 'name', 'version', 'entryPoint'] for (const field of required) { if (!manifest[field as keyof AppManifest]) { throw new Error(`清单文件缺少必需字段: ${field}`) } } // 验证版本格式 if (!/^\d+\.\d+\.\d+/.test(manifest.version)) { throw new Error('版本号格式不正确,应为 x.y.z 格式') } // 验证应用ID格式 if (!/^[a-zA-Z0-9._-]+$/.test(manifest.id)) { throw new Error('应用ID格式不正确') } } /** * 验证校验和 */ private verifyChecksum(files: Map, expectedChecksum: string): boolean { // 简化实现,实际应用中应使用更强的哈希算法 let content = '' for (const [path, data] of files.entries()) { content += path + (typeof data === 'string' ? data : data.size) } const actualChecksum = this.safeBase64Encode(content).slice(0, 32) return actualChecksum === expectedChecksum } /** * 安全的 Base64 编码,支持 Unicode 字符 */ private safeBase64Encode(str: string): string { try { // 使用 encodeURIComponent + atob 来处理 Unicode 字符 return btoa( encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) { return String.fromCharCode(parseInt(p1, 16)) }), ) } catch (error) { // 如果还是失败,使用简单的哈希算法 let hash = 0 for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i) hash = (hash << 5) - hash + char hash = hash & hash // 转换为32位整数 } return Math.abs(hash).toString(36) } } /** * 检查权限 */ private async checkPermissions(permissions: string[]): Promise { for (const permission of permissions) { // 这里可以添加权限检查逻辑 // 目前简单允许所有权限 console.log(`检查权限: ${permission}`) } } /** * 在沙箱中加载应用 */ private async loadAppInSandbox(app: AppInstance, sandboxId: string): Promise { const appFiles = this.appFiles.get(app.id) if (!appFiles) { throw new Error('应用文件不存在') } const entryFile = appFiles.get(app.manifest.entryPoint) if (!entryFile) { throw new Error('入口文件不存在') } // 创建应用URL const entryUrl = this.createAppUrl(app.id, app.manifest.entryPoint, entryFile) // 在沙箱中加载应用 await this.sandboxEngine.loadApplication(sandboxId, entryUrl) } /** * 创建应用文件URL */ private createAppUrl(appId: string, filePath: string, content: Blob | string): string { let blob: Blob if (typeof content === 'string') { // 确保使用UTF-8编码创建Blob const contentType = this.getContentType(filePath) const utf8ContentType = contentType.includes('charset') ? contentType : `${contentType}; charset=utf-8` blob = new Blob([content], { type: utf8ContentType }) } else { blob = content } return URL.createObjectURL(blob) } /** * 获取文件内容类型 */ private getContentType(filePath: string): string { const ext = filePath.split('.').pop()?.toLowerCase() switch (ext) { case 'html': return 'text/html; charset=utf-8' case 'js': return 'application/javascript; charset=utf-8' case 'css': return 'text/css; charset=utf-8' case 'json': return 'application/json; charset=utf-8' case 'png': return 'image/png' case 'jpg': case 'jpeg': return 'image/jpeg' case 'svg': return 'image/svg+xml; charset=utf-8' default: return 'text/plain; charset=utf-8' } } /** * 保存应用到存储 */ private async saveAppToStorage(app: AppInstance): Promise { const appData = { id: app.id, manifest: app.manifest, installedAt: app.installedAt.toISOString(), version: app.version, autoStart: app.autoStart, persistent: app.persistent, } await this.resourceService.setStorage('system', `apps.${app.id}`, appData) } /** * 从存储中删除应用 */ private async removeAppFromStorage(appId: string): Promise { await this.resourceService.removeStorage('system', `apps.${appId}`) } /** * 初始化外置应用发现(已由 SystemServiceIntegration 统一管理) * 这个方法保留用于未来可能的扩展,但不再重复启动发现服务 */ private async initializeExternalAppDiscovery(): Promise { try { console.log('[LifecycleManager] 外置应用发现服务已由系统服务集成统一管理') // 可以在这里添加应用生命周期管理器特有的外置应用监听逻辑 // 例如监听外置应用的注册/卸载事件 } catch (error) { console.error('[LifecycleManager] 初始化外置应用监听失败:', error) } } // 已移除:外部应用不再需要注册到 installedApps 中 // 外部应用在启动时会创建临时实例 /** * 为外置应用加载代码到沙箱 */ 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 async loadInstalledApps(): Promise { try { // 从存储中加载应用列表 const appsData = (await this.resourceService.getStorage('system', 'apps')) || {} for (const [appId, appData] of Object.entries(appsData as Record)) { if (appData && typeof appData === 'object') { const app: AppInstance = { id: appId, manifest: appData.manifest, state: AppLifecycleState.STOPPED, processId: '', installedAt: new Date(appData.installedAt), errorCount: 0, crashCount: 0, memoryUsage: 0, cpuUsage: 0, version: appData.version, autoStart: appData.autoStart || false, persistent: appData.persistent || false, } this.updateAppState(app, AppLifecycleState.INSTALLED) this.installedApps.set(appId, app) } } console.log(`已加载 ${this.installedApps.size} 个已安装应用`) } catch (error) { console.error('加载已安装应用失败:', error) } } /** * 设置事件监听器 */ private setupEventListeners(): void { // 监听沙箱状态变化 this.eventService.subscribe('system', 'sandbox-state-change', (message) => { const { sandboxId, newState } = message.payload // 查找对应的应用 for (const app of this.installedApps.values()) { if (app.sandboxId === sandboxId) { if (newState === 'error') { this.handleAppError(app.id, new Error('沙箱错误')) } else if (newState === 'destroyed') { this.handleAppCrash(app.id, '沙箱被销毁') } break } } }) // 监听性能告警 this.eventService.subscribe('system', 'performance-alert', (message) => { const { sandboxId, type, usage, limit } = message.payload for (const app of this.installedApps.values()) { if (app.sandboxId === sandboxId) { if (type === 'memory') { app.memoryUsage = usage } else if (type === 'cpu') { app.cpuUsage = usage } console.warn(`应用 ${app.id} ${type} 使用量 ${usage} 超过限制 ${limit}`) break } } }) } /** * 处理应用错误 */ private handleAppError(appId: string, error: Error): void { const app = this.installedApps.get(appId) if (!app) return app.errorCount++ this.eventService.sendMessage('system', 'app-lifecycle', { type: 'error', appId, error: error.message, }) 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, }) } }