package browser import ( "context" "errors" "fmt" "strings" "chub/internal/domain" ) const ( ProfileSourceMessageWindow = "browser_message_window" ProfileSourceLock = "browser_lock" ProfileSourceStaleLock = "stale_lock" ProfileSourceStalePID = "stale_pid" ProfileSourceUnknown = "unknown" ) var ErrIdentityUnavailable = errors.New("browser process identity is unavailable") type ProcessIdentity struct { PID int Executable string CommandLine string UserDataDir string } type ProcessInspector interface { Inspect(context.Context, int) (ProcessIdentity, error) Alive(context.Context, int) (bool, error) } type ExternalProfileInspector interface { InspectProfile(context.Context, domain.BrowserKind, string, int) (ProfileUse, error) } type RuntimeInspector struct { process ProcessInspector profiles ExternalProfileInspector } func NewRuntimeInspector(process ProcessInspector, profiles ExternalProfileInspector) *RuntimeInspector { return &RuntimeInspector{process: process, profiles: profiles} } func (i *RuntimeInspector) InspectProcess(ctx context.Context, pid int) (ProcessIdentity, error) { if i == nil || i.process == nil { return ProcessIdentity{}, ErrIdentityUnavailable } return i.process.Inspect(ctx, pid) } func (i *RuntimeInspector) InspectProfile(ctx context.Context, kind domain.BrowserKind, userDataDir string, historicalPID int) (ProfileUse, error) { if i == nil || i.profiles == nil { return ProfileUse{}, ErrIdentityUnavailable } return i.profiles.InspectProfile(ctx, kind, userDataDir, historicalPID) } func expectedExecutableName(kind domain.BrowserKind) string { if kind == domain.BrowserEdge { return "msedge.exe" } return "chrome.exe" } func executableMatchesKind(path string, kind domain.BrowserKind) bool { return strings.EqualFold(pathBase(path), expectedExecutableName(kind)) } func pathBase(path string) string { path = strings.TrimRight(path, `\\/`) if index := strings.LastIndexAny(path, `\\/`); index >= 0 { return path[index+1:] } return path } func unsupportedError() error { return fmt.Errorf("%w: Windows process inspection is unavailable", ErrIdentityUnavailable) }