Skip to content

Commit acec65c

Browse files
authored
🐛 外部接入:隐身(split)进程不再连接 sctl,避免与普通进程每 2 秒互相顶替 (#1819)
split 模式下隐身进程与普通进程共用 chrome.storage.local 里的配对密钥和脚本, 两者都连 sctl daemon 时,daemon 只保留一条 ScriptCat 连接,被顶掉的一方 2 秒后重连 又顶掉另一方,日志和审计缓冲区被 handshake.ok 刷满(scriptscat/sctl#14)。 隐身进程不再启动连接,也不接受配对。
1 parent d993ae5 commit acec65c

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

‎src/app/service/service_worker/external_access/controller.test.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,34 @@ describe("ExternalAccessController(外部接入 · 扁平信任)", () => {
9292
expect(connectClient.connect).toHaveBeenCalledWith({ url: DEFAULT_URL, auth: { mode: "session", key: "abc123" } });
9393
});
9494

95+
describe("隐身(split)进程", () => {
96+
// split 模式下隐身进程与普通进程共用 chrome.storage.local 里的密钥和脚本,它再连一次只会与普通进程互相顶替(sctl#14)。
97+
const extension = chrome.extension as unknown as { inIncognitoContext: boolean };
98+
99+
beforeEach(() => {
100+
extension.inIncognitoContext = true;
101+
});
102+
103+
afterEach(() => {
104+
extension.inIncognitoContext = false;
105+
});
106+
107+
it("已启用且已接入时启动也不拨号,状态保持 disabled", async () => {
108+
systemConfig.setExternalAccessEnabled(true);
109+
const controller = await initEnrolled("abc123", "cid");
110+
expect(connectClient.connect).not.toHaveBeenCalled();
111+
expect(controller.getStatus().status).toBe("disabled");
112+
});
113+
114+
it("enroll(code) 不以配对模式拨号", async () => {
115+
const controller = makeController();
116+
await controller.initialize();
117+
await controller.enroll("PAIR-CODE");
118+
expect(connectClient.connect).not.toHaveBeenCalled();
119+
expect(controller.getStatus().status).toBe("disabled");
120+
});
121+
});
122+
95123
it("enroll(code) 以配对模式拨号", async () => {
96124
const controller = makeController();
97125
await controller.initialize();

‎src/app/service/service_worker/external_access/controller.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export class ExternalAccessController {
5555
this.group.on("paired", (payload: { key: string }) => this.onEnrolled(payload.key));
5656
this.group.on("disconnected", () => this.onDisconnected());
5757

58+
// split 模式下隐身进程与普通进程共用 chrome.storage.local 里的密钥和脚本,由普通进程代表这份安装连接 sctl;
59+
// 隐身进程再连只会与普通进程互相顶替(sctl#14)。
60+
if (chrome.extension.inIncognitoContext) return;
61+
5862
this.systemConfig.addListener("external_access_enabled", (enabled) => {
5963
if (enabled) {
6064
void this.connect();
@@ -90,6 +94,7 @@ export class ExternalAccessController {
9094
// pairing mode with C; on success the daemon ships a fresh long-term key K, which offscreen
9195
// decrypts and relays back via `onEnrolled`.
9296
async enroll(code: string): Promise<void> {
97+
if (chrome.extension.inIncognitoContext) return;
9398
this.active = true;
9499
this.setStatus("connecting");
95100
const url = await this.systemConfig.getExternalAccessUrl();

0 commit comments

Comments
 (0)