Electron webview 的 setWindowOpenHandler 在打开新窗口时根本不会被调用

Electron webview's setWindowOpenHandler is not called at all when opening a new window

提问人:klados 提问时间:5/8/2023 最后编辑:klados 更新时间:5/9/2023 访问量:507

问:

我的 Electron (v22.3.6) 应用程序使用标签。<webview>

Web 视图位于带有标签的“main.html”渲染器进程中。<webview>

而 'main.html' 由 ,一个变量,在主进程中加载。mainWindowBrowserWindow

代码片段:

主 .html

<webview id="wv" src="inner.html"></webview>

内部 .html

<a href="https://example.com/">New window link inside inner.html</a>

主 .js

let winOpts = {
    ...
    webPreferences: {
        plugins: false,
        nodeIntegration: false,
        nodeIntegrationInWorker: false,
        webviewTag: true,
        sandbox: false, // to use some components
        enableRemoteModule: false,
        contextIsolation: true,
        disableBlinkFeatures: "Auxclick",
        webSecurity: true,
        preload: "preload.js"
    }    
};

mainWindow = new BrowserWindow(winOpts);
mainWindow.webContents.setWindowOpenHandler((handler) => {
    //NOT CALLED AT ALL
    return {
        action: "allow"
    };
});

mainWindow.loadFile("main.html");

问题:

当我单击“inner.html”中的链接时, 什么也没发生。甚至 DevTools 中的“控制台”也不显示任何内容。 “点击”行为似乎没有触发任何内容。<a href="newsite">link</a>

Scheme

在上图中, 点击“主链接”成功调用 . 单击“内部链接”不执行任何操作。既不打开新窗口也不调用 .setWindowOpenHandlersetWindowOpenHandler

总而言之,“_blank”目标链接在 . 未调用。<webview>BrowserWindowsetWindowOpenHandler

JavaScript ReactJS网页 视图 Electron Chromium

评论

0赞 Erik J 5/8/2023
你需要打电话给某个地方。(在上面的代码中,您还同时使用了 和 ,请确保先修复该问题。mainWindow.show()mainWindowmainWin
0赞 klados 5/9/2023
@ErikJ谢谢。这是一个错别字。 对于函数?导致mainWindow工作正常。mainWindow.show()setWindowOpenHandler
0赞 Erik J 5/9/2023
好的,那没关系,我只是在你发布的代码中没有看到调用。Electron 文档指出“webview 标签本质上是一个自定义元素,使用影子 DOM 将 iframe 元素包装在其中”,所以我想这就是它不起作用的原因。调用的不是嵌入 Web 视图的 webContents。它将有自己单独的 webContents。我想您需要将一些消息从嵌入式 webview 发布到其父级才能正常工作。show()mainWindow.webContentssetWindowOpenHandler
0赞 klados 5/9/2023
@ErikJ 是的,这可能就是该函数不是由 触发的原因。因此,在这种情况下,我需要一个解决方案,以便在“新窗口”即将打开时从主进程“消息”到主进程。我在 中找不到任何替代方案。此外,在渲染器进程中找不到合适的。webviewwebviewwebContentswebviewaddEventListner

答:

2赞 klados 5/9/2023 #1

了解如何:

  1. <webview>应该和喜欢allowpopups<webview allowpopups></webview>

  2. 在“主进程”中,应该有一个新生成的监听器。并且,将 附加到该侦听器函数中的 's。webContentssetWindowOpenHandlerwebviewwebContents

    app.on('web-contents-created', (e, wc) => {
        // wc: webContents of <webview> is now under control
        wc.setWindowOpenHandler((handler) => {
            return {action : "deny"}; // deny or allow
        });
    });

解释:

  1. setWindowOpenHandler仅适用于 。webContents
  2. webview的应从主进程访问。webContents
  3. 没有直接访问渲染器进程的方法,也不需要为此使用预加载脚本。webContents
  4. app.on('web-contents-created')当在渲染器进程中生成新的窗口时,可以检测新的,并且非常负责监视新窗口链接(target=“_blank”或window.open)。webContentswebviewwebContents

无需任何易受安全攻击的设置。

评论

0赞 swyx 8/9/2023
经过长时间的互联网搜索,这终于对我有用了。谢谢!