按 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。
37 lines
1.3 KiB
Go
37 lines
1.3 KiB
Go
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") },
|
|
}
|
|
}
|