2026-07-10 15:49:47 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-585
|
|
|
|
|
|
title: Chrome 路径自动检测(注册表+标准目录,Chrome-only,仅空/失效才填)+ ⑤「自动检测」按钮
|
|
|
|
|
|
phase: 7
|
|
|
|
|
|
deps: [T-557]
|
|
|
|
|
|
status: TODO
|
|
|
|
|
|
created: 2026-07-10
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
2026-07-10 16:10:15 +08:00
|
|
|
|
`chrome_path` 默认硬编码 `C:\Program Files\Google\Chrome\Application\chrome.exe`(`appconfig.py:74`),对**用户级安装**(`%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`,免管理员安装,很常见)、`Program Files (x86)` 会失效。非标准盘的**正常安装版**通常可由 Windows 注册表定位;任意目录的便携版不应扫描整盘,继续由 T-557「选择...」手动指定。小白遇到路径不存在只能手动翻 `chrome.exe`,是"开箱即用"要消灭的摩擦。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
|
|
|
|
|
|
产品原则对齐(运营日常零配置 + 逃生口 + 反馈):**自动检测填路径(小白无感)+ 保留手动「选择...」(逃生口)+ 检测结果给反馈(不做看不见的决定)**。
|
|
|
|
|
|
|
|
|
|
|
|
## 方案(改哪个文件、改成什么)
|
|
|
|
|
|
|
2026-07-10 16:10:15 +08:00
|
|
|
|
### 检测与有效性函数(`app/chrome.py`,可 mock、跨平台不崩)
|
|
|
|
|
|
- 新增 `detect_chrome_path() -> str`,按可靠性顺序返回第一个**归一化后确实存在**的 Chrome 可执行路径;无结果返回 `""`:
|
|
|
|
|
|
1. Windows App Paths:优先 `HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe`(当前用户安装),再 `HKLM` 同键;每个 hive 都尝试 64 位、32 位注册表视图,读取默认值。`winreg` 仅 Windows 导入/调用,平台不支持、键不存在或读取失败时静默跳过。
|
|
|
|
|
|
2. 标准目录兜底:`%ProgramFiles%\Google\Chrome\Application\chrome.exe`、`%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe`、`%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`。
|
|
|
|
|
|
3. 都没有则返回空字符串。
|
|
|
|
|
|
- 所有候选路径先去除成对引号、展开 `%环境变量%` / `~`、转绝对路径,再 `os.path.isfile` 验证;不返回带启动参数、不存在的注册表值或目录路径。
|
|
|
|
|
|
- 新增内部可复用的“已配置路径是否有效”判断:绝对/相对文件路径按上述归一化校验;仅文件名 `chrome.exe` 时也允许 `shutil.which()` 从 PATH 解析成功,避免把历史上实际可启动的配置误覆盖。
|
|
|
|
|
|
- **Chrome-only**:只从上述 `chrome.exe` App Paths/目录/PATH 候选取值,不检测、不返回 Edge、Chromium 等浏览器。
|
|
|
|
|
|
- 注册表读取和文件探测需可 mock;Linux/WSL 不导入或依赖真实 `winreg`,仍可测试目录/PATH 兜底。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
|
|
|
|
|
|
### 启动自动填(仅空/失效才填,不覆盖有效设置)
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- `appconfig.DEFAULT_CONFIG["chrome_path"]` 改为空字符串,不再把不存在的 Program Files 路径写入新用户配置。
|
|
|
|
|
|
- 在 `prepare_data_dir()` 与强制升级检查之后、创建 `MainWindow` 之前加载配置:若 `chrome_path` 为空或“已配置路径是否有效”返回否,则调 `detect_chrome_path()`;命中后写入**归一化绝对路径**并通过既有 `appconfig.save_config()` 持久化。
|
|
|
|
|
|
- 自动填服务须返回“是否改动、最终配置、用户可见消息”,让 GUI 入口将同一份配置传给 `MainWindow`;不把检测逻辑塞进 `load_config()`,避免任意配置读取都隐式访问注册表或写文件。
|
|
|
|
|
|
- **绝不覆盖有效的已设路径**(便携版/自定义绝对路径或可从 PATH 启动的 `chrome.exe`);检测不到时不写配置、不阻断启动。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
|
|
|
|
|
|
### ⑤设置「自动检测」按钮 + 反馈
|
|
|
|
|
|
- `app/gui/tabs/settings.py`:Chrome 路径行在「选择...」旁加「自动检测」按钮,点击调 `detect_chrome_path()`:
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 命中 → 填入 `chrome_path_edit` 并提示「已自动定位 Chrome:<路径>」;通过既有文本变更机制标记“未保存更改”,**不直接写 `config.json`**,由用户点击「保存设置」后持久化。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- 未命中 → 提示「未找到 Chrome,请点『选择...』手动指定,或先安装 Chrome」(指路,不是死胡同)。
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 未命中时不清空用户当前输入值;既有 T-557「选择...」不改。
|
|
|
|
|
|
- 启动自动填命中时,在 `MainWindow` 构造完成后写状态栏「已自动定位 Chrome:<路径>」,确保不会被初始“就绪”覆盖;启动不弹窗、不因未检测到 Chrome 而阻断。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
|
|
|
|
|
|
### 文档同步
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- `docs/04-architecture.md`(Chrome 启动/路径来源、启动自动填边界)、`docs/troubleshooting.md`(Chrome 找不到的排查改为先点“自动检测”再手动选择)。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 新配置默认 `chrome_path=""`,不会写入不存在的硬编码路径。
|
|
|
|
|
|
- `detect_chrome_path()`:mock HKCU/HKLM(含注册表视图)返回某路径且文件存在 → 返回归一化绝对路径;注册表无 → 落到标准目录,命中 `%LOCALAPPDATA%` fixture → 返回该路径;带引号/环境变量的注册表值能识别;全无 → 返回 `""`。
|
|
|
|
|
|
- 非 Windows/`winreg` 不可用 → 不抛异常,仍可走目录/PATH 兜底;不真读注册表于测试。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- 只返回 Chrome,不返回 Edge/Chromium(构造 Edge 存在但 Chrome 不存在的场景,断言返回 `""` 或不误取 Edge)。
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 启动自动填:`chrome_path` 为空 → 检测命中后写入;指向不存在文件 → 覆盖为检测结果;已设且文件存在、或 `chrome.exe` 可由 PATH 解析 → 不改(断言不覆盖);未检测到时不写配置、不阻断启动。
|
|
|
|
|
|
- 启动命中后的状态栏保留“已自动定位 Chrome”;初始“就绪”不覆盖该消息。
|
|
|
|
|
|
- ⑤「自动检测」按钮:命中填入、标记未保存并给成功提示;未命中给指路提示、不清空原值,也不写配置。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- 既有 T-557「选择...」手动选择不回归。
|
|
|
|
|
|
- 验证命令(unittest,不引入 pytest):
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- `py -3.10 -m unittest tests.test_chrome tests.test_appconfig tests.test_gui`
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- `python -m ruff check app tests main.py`
|
|
|
|
|
|
- `py -3.10 -m compileall app main.py`
|
|
|
|
|
|
- `py -3.10 -m unittest discover -s tests`
|
|
|
|
|
|
- `git diff --check`
|
|
|
|
|
|
|
|
|
|
|
|
## 边界(不改什么)
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 不扫描其它盘或用户目录来猜测便携版;便携版继续由用户点「选择...」指定。
|
|
|
|
|
|
- 不覆盖用户已设且有效的 `chrome_path`(便携版/自定义路径/PATH 逃生口)。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- 不检测/不自动使用 Edge、Chromium 等非 Chrome 浏览器。
|
|
|
|
|
|
- 不改 `chrome.py` 启动/CDP 逻辑本身、`chrome_user_data_dir`、端口分配。
|
2026-07-10 16:10:15 +08:00
|
|
|
|
- 不真读注册表于测试(mock);不引入新第三方依赖;不把注册表读取或配置写入放进通用 `load_config()`。
|
2026-07-10 15:49:47 +08:00
|
|
|
|
- 不改 ①采集/②生成/③更新/DB/AI/cmhub。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
|
|
|
|
|
(做完在这里写:改了什么文件、跑了什么验证命令及结果、遇到的阻塞、关键决策。)
|