From 40b8c2e91cc72006cfab23d26c396eb5568e221b Mon Sep 17 00:00:00 2001 From: lanterngamescn Date: Thu, 25 Jun 2026 18:43:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A1=E5=88=92=E8=BF=9B=E5=BA=A6=EF=BC=9AM2?= =?UTF-8?q?=20=E5=AE=8C=E6=88=90=E3=80=81R-02(V2=20file://=20=E8=B7=A8?= =?UTF-8?q?=E5=9F=9F)=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 01_任务分解WBS:M2 标记完成(13 任务),新增 M2 任务明细块与决策/偏差记录 - 03_风险登记册:R-02 关闭(setPathAllowingUniversalAccess 方案 + 真机复测 OK) - 框架 §7.3:file:// 跨域改为已验证的具体方案(setPathAllowingUniversalAccess),保留 onInterceptRequest 回退 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/设计文档/Plan/01_任务分解WBS.md | 27 ++++++++++++++++++- docs/设计文档/Plan/03_风险登记册.md | 2 +- .../TSGame_HarmonyOS框架设计与开发指南.md | 9 +++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/设计文档/Plan/01_任务分解WBS.md b/docs/设计文档/Plan/01_任务分解WBS.md index aad55c0..7bd2383 100644 --- a/docs/设计文档/Plan/01_任务分解WBS.md +++ b/docs/设计文档/Plan/01_任务分解WBS.md @@ -14,7 +14,7 @@ |---|---|---| | **M0** 脚手架 + 契约类型 | ☑ 完成 | 7 任务全完成并真机/模拟器验证 | | **M1** 桥引擎 | ☑ 完成 | 8 任务全完成;**V1 真机通过**、桥核心单测覆盖 87.3% | -| **M2** 容器 + 启动 + 资源 | ☐ 未开始 | 含 V2 阻塞性验证 | +| **M2** 容器 + 启动 + 资源 | ☑ 完成 | 13 任务全完成;**V2 真机通过(R-02 关闭)**、VersionResolver 单测覆盖 81.8%;T-M2-12 机制已验证(真实远程大厅待服务端可用时终验) | | **M3** 本期能力 | ☐ 未开始 | — | | **M4** 通用网页容器 | ☐ 未开始 | — | | **M5** 性能与加固 | ☐ 未开始 | — | @@ -43,6 +43,31 @@ - ☑ T-M1-08 桥引擎单测:15 用例全通过,桥核心覆盖率 87.3%(≥80%); 运行方式 = scripts/test.sh(DevEco hvigorw 本地单测,已解决 R-18) +**M2 任务明细(全部 ☑)**: + +- ☑ T-M2-01 平台存储/文件:KvStore(preferences)、FileSystem(fileIo 增删读写/列目录/拷贝内置 rawfile) +- ☑ T-M2-02 网络/下载:HttpClient(GET 禁缓存)、Downloader(http 流式写盘+进度) +- ☑ T-M2-03 解压:Unzipper(zlib.decompressFile)。**偏差**:下载/解压用原生异步 API 即满足"UI 不阻塞", + 独立 TaskScheduler(TaskPool) 推迟到 M5 真有 CPU 密集任务(MD5)时再加,避免投机性死代码 +- ☑ T-M2-04 权限/上传:PermissionGuard(用时申请,沙箱文件免存储权限)、LocalUploadServer(骨架,TCP 服务 M3 落地) +- ☑ T-M2-05 ConfigManager:本地 rawfile/app_config.json + 远程拉取/校验(<30 阻断)/二级 url + 决策 +- ☑ T-M2-06 VersionResolver:纯函数两棵树后层覆盖;单测 8 用例全通过,覆盖率 81.8%(≥80%) +- ☑ T-M2-07 ResourceManager:路径规范、内置包拷贝解压、version.xml 解析、远程 zip 下载/删旧/解压、版本比较 +- ☑ T-M2-09 AppDataInjector:加载前写 app_data.js(§6 全局变量同名同义) +- ☑ T-M2-11 StartupOrchestrator:INIT→…→ENTER_HALL 状态机,远程失败降级本地、showmessage 阻断 +- ☑ T-M2-13 能力插件框架骨架:CapabilityProvider/Context/Registrar + 组装根 buildCapabilities() + 样板 +- ☑ T-M2-10 BridgeGameContainer 完整化:Registrar 注册能力、首次 100% 推 appservice/setPostUrl、清理、入口 URL +- ☑ **T-M2-08 V2 阻塞性验证真机通过**:file:// fetch/XHR 首测被 CORS 拦截,用 + `setPathAllowingUniversalAccess` 放开资源根跨域(对 H5 透明)后复测 OK;R-02 关闭 +- ☑ T-M2-12 集成联调:用内置测试大厅(gamehall_builtin.zip)端到端验证全链路(启动→资源→app_data→ + file:// 加载→跨域 fetch→桥双向)真机通过。**真实远程大厅** H5 需服务端/网络可用时做终验 + +**M2 期间确立的项目决策/偏差**: +- file:// 跨域采用 `WebviewController.setPathAllowingUniversalAccess([filesDir/tsgames])`(官方"本地资源跨域"方案),优于通用 onInterceptRequest 代理。 +- 沙箱路径简化:弃用 Android 的 `<包名>/<时间戳>` 多级目录,用固定 `filesDir/tsgames/`(§5.1 许可,对 H5 无影响)。 +- 启动期不申请敏感权限(沙箱文件免存储权限;定位/电话等由 M3 Provider 用时申请),仅声明 INTERNET。 +- 内置 `gamehall_builtin.zip` 为 M2 测试大厅(含 V2 验证页),真实大厅由远程 zip 生产下发;M3 用真实 Provider 替换 EchoSampleProvider。 + **M0 期间确立的项目决策(超出原计划的补充)**: - 包名 `com.lobby.daoqi`;横屏项目,`module.json5` 配 `auto_rotation_landscape`(横屏两朝向跟随旋转、不进竖屏,H5 显式方向控制保留)。 - ArkTS 验证用 `devecocli build`(其 CompileArkTS 为权威编译器);deveco-mcp 的 LSP check 因 70s 索引 / 20s 超时不可用。 diff --git a/docs/设计文档/Plan/03_风险登记册.md b/docs/设计文档/Plan/03_风险登记册.md index 990bb74..e52d753 100644 --- a/docs/设计文档/Plan/03_风险登记册.md +++ b/docs/设计文档/Plan/03_风险登记册.md @@ -7,7 +7,7 @@ | ID | 风险 | 概率 | 影响 | 触发信号 | 缓解 / 应对 | 负责人 | |---|---|---|---|---|---|---| | **R-01** | **`yy://` 自定义 scheme 的 iframe 导航不被 `onLoadIntercept` 捕获**(桥不通) | 中 | 高(阻断全局) | T-M1-07 验证失败 | 前置到 M1 最先验证;回退:`onInterceptRequest`+`WebSchemeHandler` 注册 `yy` scheme;或改桥 JS 走 `javaScriptProxy.postMessage`(对 H5 透明)。三方案均零改 H5 | 桥/技术负责人 | -| **R-02** | **`file://` 页面跨域受限**,H5 的 XHR/fetch 取本地资源失败 | 中 | 高(大厅/子游戏白屏) | T-M2-08 验证失败 | 前置到 M2;回退:自定义协议/`onInterceptRequest` 接管本地资源(框架 §7.3)。必要时把首页改用自定义 scheme 加载 | 台/桥 | +| **R-02 ✅关闭** | **`file://` 页面跨域受限**,H5 的 XHR/fetch 取本地资源失败 | 中 | 高(大厅/子游戏白屏) | T-M2-08 验证失败 | **已关闭(2026-06-25)**:T-M2-08 首测确被 CORS 拦截(origin 'null',file 不在允许跨域 scheme);采用官方方案 `WebviewController.setPathAllowingUniversalAccess([filesDir/tsgames])` 放开资源根跨域,对 H5 透明(仍 file:// 加载)。模拟器复测 fetch/XHR OK。比 onInterceptRequest 代理更简、无需逐请求拦截 | 台/桥 | | **R-03** | `MessageCodec` 转义与 lzyzsd 不一致,含特殊字符的 data 解析错位 | 中 | 中 | 含引号/反斜杠/中文的分享文案、JSON data 解析异常 | 单测以 Android 端样例做字节级对照;复用库 JS 原文件 | 桥 | | **R-04** | **线程问题**:能力回调在非 UI 线程调 `runJavaScript` 崩溃/丢消息 | 中 | 高 | 定位/支付/传感器回调偶发崩溃 | 强制 UI 线程守卫(框架 §5.5);能力回传统一经桥(emitter/UIContext) | 桥 | | **R-05** | **TaskPool Sendable 约束**导致下载/解压回调传参编译/运行失败 | 中 | 中 | `@Concurrent` 报 Sendable 错 | 仅传 Sendable + emitter 回传(§9.1);路径在 UI 线程取好传字符串 | 台 | diff --git a/docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md b/docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md index 26b24a6..f83199f 100644 --- a/docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md +++ b/docs/设计文档/TSGame_HarmonyOS框架设计与开发指南.md @@ -535,9 +535,14 @@ export struct GenericWebContainer { - `settings` 的 6 方法、`getWebdata`/`gamebackkeydown`/`backgameData` 三个直调函数严格照《契约规范》§11.3。 - **回传上层**:用路由返回值或 `emitter` 事件把 `data` 投递回打开它的 Bridge 容器,由后者 `callHandler('getWebdata', data)`(复刻 Android 结果码 101 语义)。 -### 7.3 file:// 跨域 +### 7.3 file:// 跨域(V2 已验证,2026-06-25) -H5 以 `file://` 加载并请求本地/远程资源。HarmonyOS 侧采用官方"Web 页面跨域解决方案":用 `onInterceptRequest` 自定义本地资源响应,或为本地页配置自定义协议/响应头,避免 file 同源限制。**对 H5 透明**。 +H5 以 `file://` 加载并请求本地资源时,ArkWeb 默认按 CORS 拦截(file 页面 origin 为 `null`,且 `file` 不在允许跨域的 scheme 列表)——**T-M2-08 真机首测确认了这一拦截**(`Access to fetch ... blocked by CORS policy`)。 + +**采用的解决方案(落地、对 H5 透明)**:在 `onControllerAttached` 调用 +`WebviewController.setPathAllowingUniversalAccess([/tsgames])`,把资源根加入"允许跨域访问"白名单——该路径下的 `file://` 资源即放开同源限制,H5 的 XHR/fetch 正常工作。约束:路径须为 `filesDir`/`resourceDir` 子目录、与用户文件隔离;一旦设置,`file` 协议仅限访问白名单内资源(覆盖 `fileAccess` 行为)。 + +> 此方案比通用的 `onInterceptRequest`/`WebSchemeHandler` 代理更简(无需逐请求拦截、无需改首页 scheme),是 HarmonyOS 官方《Web 页面跨域解决方案·本地资源跨域》的推荐做法。若未来遇白名单不可用的边缘场景,仍可回退 `onInterceptRequest` 自定义响应。**对 H5 始终零改动**。 ### 7.4 屏幕方向(横屏项目)