cicy-desktop 2.1.365 → 2.1.367
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/main.js +41 -6
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -41,16 +41,51 @@ electronApp.on("session-created", armNoPasskey);
|
|
|
41
41
|
// 得在客机 attach 时把 no-passkey 设成它自己的 preload,否则矩阵格子(全是 webview)里
|
|
42
42
|
// 的 FB 页照样能调 navigator.credentials.get → Windows 弹安全密钥框(实测 2.1.364)。
|
|
43
43
|
// preload 内部用「插 <script> 改主世界」,所以不用动客机的 contextIsolation。
|
|
44
|
-
|
|
44
|
+
// 实测:will-attach-webview 里设 preload、以及 <webview> 元素 preload 属性,在这个
|
|
45
|
+
// Electron + 面板 BrowserView 组合下都被忽略(preload 根本不加载)。唯一可靠的、能在
|
|
46
|
+
// 文档创建前于主世界执行、赢过 FB 页首帧 credentials.get 的办法是 CDP 的
|
|
47
|
+
// Page.addScriptToEvaluateOnNewDocument。给每个 <webview> 客机挂上。
|
|
48
|
+
const NPK_SRC = "(function(){try{"
|
|
49
|
+
+ "if(window.PublicKeyCredential){"
|
|
50
|
+
+ "PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable=function(){return Promise.resolve(false)};"
|
|
51
|
+
+ "PublicKeyCredential.isConditionalMediationAvailable=function(){return Promise.resolve(false)};}"
|
|
52
|
+
+ "if(navigator.credentials&&navigator.credentials.get){"
|
|
53
|
+
+ "var g=navigator.credentials.get.bind(navigator.credentials);"
|
|
54
|
+
+ "navigator.credentials.get=function(o){return (o&&o.publicKey)?"
|
|
55
|
+
+ "Promise.reject(new DOMException('The operation either timed out or was not allowed.','NotAllowedError')):g(o)};}"
|
|
56
|
+
+ "}catch(e){}})();";
|
|
57
|
+
// 通行密钥的 get() 可能从**跨域 iframe**(如 accounts.meta.com,独立进程 OOPIF)或**弹窗**里发起,
|
|
58
|
+
// 只在主目标上 addScript 覆盖不到它们(实测:弹窗写着 accounts.meta.com 的通行密钥,框照弹)。
|
|
59
|
+
// 用 Target.setAutoAttach(flatten) 抓下每一个子目标(子框架/弹窗),对每个子会话也 addScript,
|
|
60
|
+
// 并让它继续向下 auto-attach —— 这样无论哪个 origin、哪层 iframe、哪个弹窗都被覆盖。
|
|
61
|
+
async function armSession(dbg, sessionId) {
|
|
62
|
+
// sendCommand(method, params, sessionId?) —— 根会话 sessionId 传 undefined
|
|
63
|
+
const sid = sessionId || undefined;
|
|
64
|
+
try { await dbg.sendCommand("Page.enable", {}, sid); } catch (_) {}
|
|
65
|
+
try { await dbg.sendCommand("Page.addScriptToEvaluateOnNewDocument", { source: NPK_SRC }, sid); } catch (_) {}
|
|
66
|
+
try { await dbg.sendCommand("Target.setAutoAttach", { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }, sid); } catch (_) {}
|
|
67
|
+
}
|
|
68
|
+
async function armWebviewNoPasskey(wc) {
|
|
45
69
|
try {
|
|
46
|
-
wc.
|
|
70
|
+
if (!wc || wc.isDestroyed() || wc.getType() !== "webview" || wc.__npkArmed) return;
|
|
71
|
+
wc.__npkArmed = true;
|
|
72
|
+
const dbg = wc.debugger;
|
|
73
|
+
if (!dbg.isAttached()) dbg.attach("1.3");
|
|
74
|
+
dbg.on("message", async (_e, method, params, sessionId) => {
|
|
47
75
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
76
|
+
if (method === "Target.attachedToTarget") {
|
|
77
|
+
const sid = params.sessionId;
|
|
78
|
+
await armSession(dbg, sid); // 子目标(iframe/弹窗)也注入并继续向下
|
|
79
|
+
try { await dbg.sendCommand("Runtime.runIfWaitingForDebugger", {}, sid); } catch (_) {}
|
|
80
|
+
}
|
|
51
81
|
} catch (_) {}
|
|
52
82
|
});
|
|
53
|
-
|
|
83
|
+
await armSession(dbg, null); // 主目标
|
|
84
|
+
try { await wc.executeJavaScript(NPK_SRC, true); } catch (_) {} // 当前已加载文档补一发
|
|
85
|
+
} catch (_) { try { wc.__npkArmed = false; } catch (e) {} }
|
|
86
|
+
}
|
|
87
|
+
electronApp.on("web-contents-created", (_e, wc) => {
|
|
88
|
+
try { if (wc.getType() === "webview") armWebviewNoPasskey(wc); } catch (_) {}
|
|
54
89
|
});
|
|
55
90
|
// 默认会话可能在上面这个监听器挂上之前就已经建好了(main.js 里别处也踩过同一个坑,
|
|
56
91
|
// 见启动时那段「默认会话强制直连」的保险),所以 ready 之后再补一次。幂等。
|