60 lines
2.9 KiB
JavaScript
60 lines
2.9 KiB
JavaScript
// 技术验证:Electron 内嵌 WebContentsView + 远程调试端口,供 browser-use 通过 CDP 接管。
|
||
// 运行:npx electron spike/embed/main.js
|
||
const { app, BrowserWindow, WebContentsView, session, protocol, net } = require("electron");
|
||
const path = require("path");
|
||
const { pathToFileURL } = require("url");
|
||
|
||
// 界面页走自定义协议 app://ui/...:file:// 没有主机名,会被 browser-use 的安全看门狗当成非法标签页关掉
|
||
protocol.registerSchemesAsPrivileged([{ scheme: "app", privileges: { standard: true, secure: true, supportFetchAPI: true } }]);
|
||
|
||
const CDP_PORT = process.env.SPIKE_CDP_PORT || "9333";
|
||
app.commandLine.appendSwitch("remote-debugging-port", CDP_PORT);
|
||
app.commandLine.appendSwitch("remote-allow-origins", "*");
|
||
|
||
app.whenReady().then(() => {
|
||
protocol.handle("app", (request) => {
|
||
const url = new URL(request.url);
|
||
const rel = url.pathname === "/" ? "index.html" : url.pathname.replace(/^\/+/, "");
|
||
return net.fetch(pathToFileURL(path.join(__dirname, rel)).toString());
|
||
});
|
||
const win = new BrowserWindow({
|
||
width: 1280,
|
||
height: 820,
|
||
title: "embed-spike",
|
||
webPreferences: { contextIsolation: true, nodeIntegration: false },
|
||
});
|
||
win.loadURL("app://ui/index.html");
|
||
|
||
const part = session.fromPartition("persist:spike-view");
|
||
const view = new WebContentsView({
|
||
webPreferences: { session: part, contextIsolation: true, nodeIntegration: false, sandbox: true },
|
||
});
|
||
win.contentView.addChildView(view);
|
||
const layout = () => {
|
||
const [w, h] = win.getContentSize();
|
||
view.setBounds({ x: Math.round(w * 0.36), y: 56, width: Math.round(w * 0.64), height: h - 56 });
|
||
};
|
||
win.on("resize", layout);
|
||
layout();
|
||
view.webContents.loadURL("about:blank");
|
||
win.on("close", () => console.log("[win] close requested"));
|
||
win.on("closed", () => console.log("[win] closed"));
|
||
view.webContents.on("destroyed", () => console.log("[view] destroyed"));
|
||
win.webContents.on("did-navigate", (_e, url) => console.log("[ui] did-navigate", url));
|
||
|
||
view.webContents.on("did-navigate", (_e, url) => console.log("[view] did-navigate", url));
|
||
view.webContents.on("did-navigate-in-page", (_e, url) => console.log("[view] in-page", url));
|
||
view.webContents.setWindowOpenHandler(({ url }) => {
|
||
console.log("[view] window.open blocked", url);
|
||
return { action: "deny" };
|
||
});
|
||
app.on("browser-window-created", () => console.log("[app] browser-window-created; total", BrowserWindow.getAllWindows().length));
|
||
app.on("web-contents-created", (_e, wc) => console.log("[app] web-contents-created type", wc.getType()));
|
||
setInterval(() => {
|
||
console.log("[hb] windows", BrowserWindow.getAllWindows().length, "| view url", view.webContents.getURL(), "| title", view.webContents.getTitle());
|
||
}, 5000);
|
||
console.log("[spike] ready; CDP http://127.0.0.1:" + CDP_PORT + "/json");
|
||
});
|
||
|
||
app.on("window-all-closed", () => app.quit());
|