fix: persist scanned browser cores

This commit is contained in:
Yoreh
2026-06-27 11:56:48 +08:00
parent 7bc1ecaa7a
commit 021b5e8380
2 changed files with 142 additions and 3 deletions
+84
View File
@@ -0,0 +1,84 @@
package backend
import (
"ant-chrome/backend/internal/browser"
"ant-chrome/backend/internal/config"
"os"
"path/filepath"
"testing"
)
type browserCoreDAOStub struct {
list []browser.Core
}
func (s *browserCoreDAOStub) List() ([]browser.Core, error) {
return append([]browser.Core{}, s.list...), nil
}
func (s *browserCoreDAOStub) Upsert(core browser.Core) error {
for i := range s.list {
if s.list[i].CoreId == core.CoreId {
s.list[i] = core
return nil
}
}
s.list = append(s.list, core)
return nil
}
func (s *browserCoreDAOStub) Delete(coreId string) error {
next := s.list[:0]
for _, core := range s.list {
if core.CoreId != coreId {
next = append(next, core)
}
}
s.list = next
return nil
}
func (s *browserCoreDAOStub) SetDefault(coreId string) error {
for i := range s.list {
s.list[i].IsDefault = s.list[i].CoreId == coreId
}
return nil
}
func TestBrowserCoreScanRegistersDetectedCoreInDAO(t *testing.T) {
root := t.TempDir()
coreDir := filepath.Join(root, "chrome", "chromium-148")
exePath := filepath.Join(coreDir, filepath.FromSlash(browser.CoreExecutableCandidates()[0]))
if err := os.MkdirAll(filepath.Dir(exePath), 0o755); err != nil {
t.Fatalf("创建测试内核目录失败: %v", err)
}
if err := os.WriteFile(exePath, []byte("stub"), 0o755); err != nil {
t.Fatalf("写入测试内核可执行文件失败: %v", err)
}
cfg := config.DefaultConfig()
cfg.Browser.Cores = nil
app := NewApp(root)
app.config = cfg
app.browserMgr = browser.NewManager(cfg, root)
dao := &browserCoreDAOStub{}
app.browserMgr.CoreDAO = dao
cores := app.BrowserCoreScan()
if len(dao.list) != 1 {
t.Fatalf("扫描后应写入 DAO 1 个内核,got=%d", len(dao.list))
}
if dao.list[0].CoreId != "core-chromium-148" {
t.Fatalf("内核 ID 不符合预期: got=%q", dao.list[0].CoreId)
}
if dao.list[0].CorePath != filepath.Join("chrome", "chromium-148") {
t.Fatalf("内核路径不符合预期: got=%q", dao.list[0].CorePath)
}
if !dao.list[0].IsDefault {
t.Fatal("首个扫描到的内核应设为默认")
}
if len(cores) != 1 || cores[0].CoreId != dao.list[0].CoreId {
t.Fatalf("扫描返回列表未包含新内核: %+v", cores)
}
}
+58 -3
View File
@@ -9,6 +9,7 @@ import (
"net"
"os"
"path/filepath"
"strings"
"time"
"github.com/google/uuid"
@@ -58,7 +59,7 @@ func (a *App) ensureDefaultCores() {
log := logger.New("Browser")
// 扫描 chrome/ 目录,无论配置是否已有内核都执行一次,确保新增子目录被发现
detected := a.scanChromeDir("chrome")
detected := a.scanChromeDir(a.browserCoreRoot())
if len(a.config.Browser.Cores) == 0 {
// 配置为空:直接用扫描结果,或兜底写一个占位
@@ -100,9 +101,8 @@ func (a *App) ensureDefaultCores() {
func (a *App) autoDetectCores() {
log := logger.New("Browser")
// ensureDefaultCores 已完成扫描注册,这里只做路径有效性日志。
cores := a.scanAndRegisterCores()
// SQLite 模式下以内核表为准,避免与 config.yaml 历史条目不一致。
cores := a.config.Browser.Cores
if a.browserMgr != nil {
cores = a.browserMgr.ListCores()
}
@@ -116,6 +116,61 @@ func (a *App) autoDetectCores() {
}
}
func (a *App) browserCoreRoot() string {
if a != nil && a.config != nil {
if root := strings.TrimSpace(a.config.Browser.CoreRoot); root != "" {
return root
}
}
return "chrome"
}
func (a *App) scanAndRegisterCores() []browser.Core {
log := logger.New("Browser")
detected := a.scanChromeDir(a.browserCoreRoot())
if len(detected) == 0 || a.browserMgr == nil {
return detected
}
existing := a.browserMgr.ListCores()
knownPaths := make(map[string]struct{}, len(existing))
hasDefault := false
for _, core := range existing {
knownPaths[normalizeCorePathForCompare(core.CorePath)] = struct{}{}
if core.IsDefault {
hasDefault = true
}
}
for _, core := range detected {
if _, ok := knownPaths[normalizeCorePathForCompare(core.CorePath)]; ok {
continue
}
core.IsDefault = !hasDefault
if err := a.browserMgr.SaveCore(browser.CoreInput{
CoreId: core.CoreId,
CoreName: core.CoreName,
CorePath: core.CorePath,
IsDefault: core.IsDefault,
}); err != nil {
log.Warn("自动注册内核失败", logger.F("core_id", core.CoreId), logger.F("path", core.CorePath), logger.F("error", err.Error()))
continue
}
log.Info("发现新内核,已注册", logger.F("core_id", core.CoreId), logger.F("path", core.CorePath))
knownPaths[normalizeCorePathForCompare(core.CorePath)] = struct{}{}
hasDefault = hasDefault || core.IsDefault
}
return a.browserMgr.ListCores()
}
func normalizeCorePathForCompare(path string) string {
path = strings.TrimSpace(path)
if path == "" {
return ""
}
return filepath.ToSlash(filepath.Clean(path))
}
// scanChromeDir 扫描指定目录,将包含浏览器可执行文件的子文件夹识别为内核。
// 如果目录本身包含可执行文件(旧版单内核结构),则直接返回该目录作为内核。
func (a *App) scanChromeDir(chromeRoot string) []browser.Core {