返回 DeepSeek-Reasonix
browserControlHost.ts
根目录 / desktop / electron / src / main / browserControlHost.ts
1 import { existsSync } from "node:fs";
2 import {
3 applyBrowserSessionPolicy,
4 clearBrowserCache,
5 clearBrowserData,
6 type BrowserControlStore,
7 type BrowserSession,
8 } from "./browserControl.js";
9 import {
10 ChromeImportError,
11 defaultRunCommand,
12 findChromeProfiles,
13 importChromeCookies,
14 chromeProfileRoot,
15 type ChromeImportDeps,
16 type CookieSink,
17 } from "./chromeImport.js";
18 import type { Logger } from "./log.js";
19 import type { ChromeImportOutcome, BrowserControlState } from "../shared/ipc.js";
20
21 export interface BrowserControlHostDeps {
22 store: BrowserControlStore;
23 sharedSession(): BrowserSession & { cookies: CookieSink };
24 log: Logger;
25 platform: NodeJS.Platform;
26 home: string;
27 env: NodeJS.ProcessEnv;
28 run?(command: string, args: string[]): Promise<string>;
29 list(path: string): string[];
30 onControlEnabled(enabled: boolean): void;
31 }
32
33 // The renderer-facing surface: settings state plus the one-shot actions that
34 // only make sense against the browser partition.
35 export interface BrowserControlApi {
36 state(): BrowserControlState;
37 setControlEnabled(enabled: boolean): Promise<BrowserControlState>;
38 setIgnoreCertificateErrors(enabled: boolean): Promise<BrowserControlState>;
39 clearCache(): Promise<void>;
40 clearAllData(): Promise<void>;
41 importChromeLogin(): Promise<ChromeImportOutcome>;
42 }
43
44 export class BrowserControlHost implements BrowserControlApi {
45 private readonly sessions = new Map<string, BrowserSession>();
46
47 constructor(private readonly deps: BrowserControlHostDeps) {}
48
49 state(): BrowserControlState {
50 return this.deps.store.current;
51 }
52
53 // Every guest partition is the built-in browser, so the certificate policy
54 // follows each one as it appears; the app window never goes through here.
55 trackSession(partition: string, session: BrowserSession): void {
56 this.sessions.set(partition, session);
57 applyBrowserSessionPolicy(session, this.deps.store.current.ignoreCertificateErrors);
58 }
59
60 async setControlEnabled(enabled: boolean): Promise<BrowserControlState> {
61 const state = await this.deps.store.setControlEnabled(enabled);
62 this.deps.log.info(`browser control enabled=${state.controlEnabled}`);
63 this.deps.onControlEnabled(state.controlEnabled);
64 return state;
65 }
66
67 async setIgnoreCertificateErrors(enabled: boolean): Promise<BrowserControlState> {
68 const state = await this.deps.store.setIgnoreCertificateErrors(enabled);
69 for (const session of this.sessions.values()) applyBrowserSessionPolicy(session, state.ignoreCertificateErrors);
70 this.deps.log.info(`browser certificate verification relaxed=${state.ignoreCertificateErrors}`);
71 return state;
72 }
73
74 async clearCache(): Promise<void> {
75 await clearBrowserCache(this.deps.sharedSession());
76 this.deps.log.info("browser cache cleared");
77 }
78
79 async clearAllData(): Promise<void> {
80 await clearBrowserData(this.deps.sharedSession());
81 this.deps.log.info("browser data cleared");
82 }
83
84 async importChromeLogin(): Promise<ChromeImportOutcome> {
85 const root = chromeProfileRoot(this.deps.platform, this.deps.home, this.deps.env);
86 if (!existsSync(root)) {
87 this.deps.log.warn(`chrome import: no Chrome data at ${root}`);
88 return { ok: false, reason: "chrome-missing" };
89 }
90 const profiles = findChromeProfiles(root, this.deps.list);
91 if (profiles.length === 0) {
92 this.deps.log.warn(`chrome import: no profile with cookies under ${root}`);
93 return { ok: false, reason: "profile-not-found" };
94 }
95 const deps: ChromeImportDeps = {
96 platform: this.deps.platform,
97 home: this.deps.home,
98 env: this.deps.env,
99 cookies: this.deps.sharedSession().cookies,
100 run: this.deps.run ?? defaultRunCommand,
101 log: this.deps.log,
102 };
103 try {
104 const summary = await importChromeCookies(deps, root, profiles);
105 return { ok: true, ...summary };
106 } catch (error) {
107 const reason = error instanceof ChromeImportError ? error.code : "cookies-unreadable";
108 this.deps.log.warn(`chrome import failed (${reason}): ${error instanceof Error ? error.message : String(error)}`);
109 return { ok: false, reason };
110 }
111 }
112 }
113
113 lines TYPESCRIPT