feat: notify when managed browsers exit

This commit is contained in:
QiuSW
2026-07-25 18:23:33 +08:00
parent f5b5e95223
commit eeaf4c7826
9 changed files with 647 additions and 92 deletions
+18 -3
View File
@@ -112,6 +112,8 @@ func runWindow(logger *slog.Logger) {
cdp := browser.NewCDPInspector()
externalProfiles := browser.NewWindowsProfileInspector()
proxies := newProxyDirectory()
exitMonitor := newManagedExitMonitor(shell.ReportManagedExit, window.Invalidate)
defer exitMonitor.Close()
shell.OnStartInstance(instanceStarter{
launcher: launcher,
resolver: discoverer,
@@ -120,8 +122,9 @@ func runWindow(logger *slog.Logger) {
remoteDebug: cdp,
portAllocator: cdp,
proxyResolver: proxies,
monitor: exitMonitor,
}.Start, window.Invalidate)
shell.OnStopInstance(instanceStopper{launcher: launcher, managedProfiles: launcher}.Stop, window.Invalidate)
shell.OnStopInstance(instanceStopper{launcher: launcher, managedProfiles: launcher, monitor: exitMonitor}.Stop, window.Invalidate)
shell.OnRefreshInstances(instanceStatusRefresher{
managedProfiles: launcher,
externalProfiles: externalProfiles,
@@ -274,11 +277,12 @@ type profileStopper interface {
type instanceStopper struct {
launcher profileStopper
managedProfiles managedProfileInspector
monitor managedExitObserver
waitTimeout time.Duration
waitInterval time.Duration
}
func (s instanceStopper) Stop(ctx context.Context, row ui.InstanceRow) error {
func (s instanceStopper) Stop(ctx context.Context, row ui.InstanceRow, launchGeneration uint64) error {
if row.Status != "运行中" && row.Status != "运行中(调试不可用)" {
return errors.New("实例当前不是可停止的 Chub 托管状态")
}
@@ -298,7 +302,14 @@ func (s instanceStopper) Stop(ctx context.Context, row ui.InstanceRow) error {
if use.Source != "chub_registry" || (row.PID > 0 && use.PID > 0 && row.PID != use.PID) {
return domain.ErrIdentityMismatch
}
expected := false
if s.monitor != nil {
expected = s.monitor.ExpectStop(row.ID, launchGeneration, row.PID)
}
if err := s.launcher.StopProfile(ctx, row.UserDataDir, false); err != nil {
if expected {
s.monitor.ClearExpectedStop(row.ID, launchGeneration, row.PID)
}
return err
}
timeout := s.waitTimeout
@@ -342,6 +353,7 @@ type instanceStarter struct {
remoteDebug browser.RemoteDebugEndpointInspector
portAllocator browser.RemoteDebugPortAllocator
proxyResolver proxyServerResolver
monitor managedExitObserver
}
type instanceStatusRefresher struct {
@@ -428,7 +440,7 @@ func (s instanceStatusRefresher) refreshOne(ctx context.Context, row ui.Instance
return result
}
func (s instanceStarter) Start(ctx context.Context, row ui.InstanceRow, settings ui.SettingsState) (ui.InstanceStartOutcome, error) {
func (s instanceStarter) Start(ctx context.Context, row ui.InstanceRow, settings ui.SettingsState, launchGeneration uint64) (ui.InstanceStartOutcome, error) {
kind, err := browserKind(row.Browser)
if err != nil {
return ui.InstanceStartOutcome{}, err
@@ -496,6 +508,9 @@ func (s instanceStarter) Start(ctx context.Context, row ui.InstanceRow, settings
if err != nil {
return ui.InstanceStartOutcome{}, err
}
if s.monitor != nil {
s.monitor.Watch(row.ID, launchGeneration, handle)
}
endpointCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
endpoint, endpointErr := s.remoteDebug.WaitForRemoteDebugPort(endpointCtx, kind, port)