返回 DeepSeek-Reasonix
host_remote_window.go
根目录 / desktop / host_remote_window.go
1 package main
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "sync"
8 )
9
10 // hostRemoteWindows tracks the remote Serve windows the Electron shell owns on
11 // this process's behalf. Under the shell there is no child process per host:
12 // the shell keeps one BrowserWindow per host key and reports its closure.
13 type hostRemoteWindows struct {
14 mu sync.Mutex
15 open map[string]bool
16 }
17
18 func (b *hostShellBridge) remoteWindows() *hostRemoteWindows {
19 b.remoteMu.Lock()
20 defer b.remoteMu.Unlock()
21 if b.remote == nil {
22 b.remote = &hostRemoteWindows{open: map[string]bool{}}
23 }
24 return b.remote
25 }
26
27 func (b *hostShellBridge) openRemoteWindow(launch remoteWindowLaunch) error {
28 if launch.HostKey == "" {
29 return fmt.Errorf("remote window host key is required")
30 }
31 ctx, cancel := context.WithTimeout(context.Background(), rpcHostWindowTimeout)
32 defer cancel()
33 params := map[string]string{"hostKey": launch.HostKey, "url": launch.URL, "title": launch.Title}
34 if err := b.server.Request(ctx, "host/remoteWindow.open", params, nil); err != nil {
35 return fmt.Errorf("open remote window: %w", err)
36 }
37 windows := b.remoteWindows()
38 windows.mu.Lock()
39 windows.open[launch.HostKey] = true
40 windows.mu.Unlock()
41 return nil
42 }
43
44 func (b *hostShellBridge) closeRemoteWindow(hostKey string) {
45 windows := b.remoteWindows()
46 windows.mu.Lock()
47 present := windows.open[hostKey]
48 delete(windows.open, hostKey)
49 windows.mu.Unlock()
50 if !present {
51 return
52 }
53 ctx, cancel := context.WithTimeout(context.Background(), rpcHostWindowTimeout)
54 defer cancel()
55 _ = b.server.Request(ctx, "host/remoteWindow.close", map[string]string{"hostKey": hostKey}, nil)
56 }
57
58 func (b *hostShellBridge) hasRemoteWindow(hostKey string) bool {
59 windows := b.remoteWindows()
60 windows.mu.Lock()
61 defer windows.mu.Unlock()
62 return windows.open[hostKey]
63 }
64
65 func (b *hostShellBridge) closeAllRemoteWindows() {
66 windows := b.remoteWindows()
67 windows.mu.Lock()
68 keys := make([]string, 0, len(windows.open))
69 for key := range windows.open {
70 keys = append(keys, key)
71 }
72 windows.mu.Unlock()
73 for _, key := range keys {
74 b.closeRemoteWindow(key)
75 }
76 }
77
78 // remoteWindowClosed records a window the user closed in the shell so a later
79 // open creates a fresh window instead of navigating a closed one.
80 func (b *hostShellBridge) remoteWindowClosed(payload json.RawMessage) {
81 var closed struct {
82 HostKey string `json:"hostKey"`
83 }
84 if err := json.Unmarshal(payload, &closed); err != nil || closed.HostKey == "" {
85 return
86 }
87 windows := b.remoteWindows()
88 windows.mu.Lock()
89 delete(windows.open, closed.HostKey)
90 windows.mu.Unlock()
91 }
92
92 lines GO