feat(browser): 浏览器配置与探测库(internal/capability/browsercfg,纯库零接线)
按 design/28 §2/§3 的「配置不进 .env」口径:读 $DATA_DIR/config/plugins/browser.json (0600 + temp+rename 范式,**不读 env、不加新键**);有头/无头、CDP 端点、profile 目录、 视口/超时/并发(1)/截图上限全部类型化 + 常量默认值;**探测优先级**(本机 Chrome/Chromium 可执行文件 → 已在跑的容器)并返回可分类的「为什么不可用」(供上层如实降级,不假装可用); profile 目录含凭据 ⇒ 0600 + 不进 git/不进上下文的注释与校验。 本片零既有文件改动(不注册工具、不碰 cmd/),接线留 B2。
This commit is contained in:
1 parent
b7fb4dd1c7
commit
29181245ce
9 files changed
+1398
No files matched your search
@@ -0,0 +1,36 @@
|
||||
package browsercfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// testFileInfo 是最小的 fs.FileInfo 实现,让单测能伪造 Stat 的返回,从而不依赖真实装没装浏览器。
|
||||
type testFileInfo struct {
|
||||
mode fs.FileMode
|
||||
dir bool
|
||||
}
|
||||
|
||||
func (f testFileInfo) Name() string { return "browser" }
|
||||
func (f testFileInfo) Size() int64 { return 0 }
|
||||
func (f testFileInfo) Mode() fs.FileMode { return f.mode }
|
||||
func (f testFileInfo) ModTime() time.Time { return time.Time{} }
|
||||
func (f testFileInfo) IsDir() bool { return f.dir }
|
||||
func (f testFileInfo) Sys() any { return nil }
|
||||
|
||||
// executableFileInfo 造一个带执行位的普通文件信息(非 Windows 平台才算「可执行」)。
|
||||
func executableFileInfo() fs.FileInfo { return testFileInfo{mode: 0o755} }
|
||||
|
||||
// noBrowserProber 返回一个「本机没有浏览器、也没有 CDP 端点」的 Prober(全阴性基线)。
|
||||
func noBrowserProber() *Prober {
|
||||
return &Prober{
|
||||
LookPath: func(string) (string, error) { return "", errors.New("not found") },
|
||||
Stat: func(string) (os.FileInfo, error) { return nil, os.ErrNotExist },
|
||||
Getenv: func(string) string { return "" },
|
||||
GOOS: "linux",
|
||||
CheckCDP: func(context.Context, string) error { return errors.New("connection refused") },
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user