window.postMessage VS window.chrome.webview.postMessage

window.postMessage VS window.chrome.webview.postMessage

window.postMessagewindow.chrome.webview.postMessage 有何不同?

我在 WebView2 的上下文中使用它(在 .NET/WPF 应用程序中)。我们正在 WebView2 中加载第三方网页。该网页触发 window.postMessage 并包含我们需要捕获的某些数据。根据 documentation,WebView2 在加载页面触发 window.chrome.webview.postMessage 时引发 WebMessageReceived 事件,这是正确的。另一方面,它似乎不尊重 window.postMessage(没有 WebMessageReceived 被解雇)。

这是两个不同的 API 吗?哪一个是标准的(如 HTML5)?我如何才能在我的 .NET 应用程序中捕获 window.postMessage 事件,因为我无法要求第三方网站更改其代码以使用 window.chrome.webview.postMessage.

chrome.webview.postMessage method is a WebView2 specific JavaScript function that allows web content to send messages to the host app via the CoreWebView2.WebMessageReceived event. It is patterned after the HTML standard window.postMessage DOM API 除了 chrome.webview.postMessage 将消息发布到主机应用程序和 window.postMessage 之间的巨大差异之外,还有一些不同之处向其他 windows:

发帖
window.postMessage(message, targetOrigin, [transfer]);
window.chrome.webview.postMessage(message);

差异

消息参数

它们都将 message 对象作为第一个参数,按值传递给目标。消息由 window.postMessage 使用 Structured Clone Algorithm (SCA) 序列化,而 window.chrome.webview.postMessage 使用 JSON。两者之间最大的区别是SCA可以处理消息对象中的引用循环,而JSON会抛出。

原点参数

window.postMessage 方法用于向其他 windows 发送消息,并且存在 window 可能不在正确来源并且不允许接收消息的风险数据。 origin 参数允许调用者指定允许接收数据的来源。

在 WebView2 的情况下,没有这样的参数,因为消息被发送到本质上受信任的主机应用程序(它是受信任的,因为它托管 Web 内容并且能够检查用户数据文件夹,注入脚本等)。

传递参数

window.postMessage 的可选传输参数允许将特定类型的 JavaScript 对象移动到目标 window。这包括诸如消息端口和大量数据之类的东西。

WebView2 当前不支持此方案,同样 chrome.webview.postMessage 也没有此参数。

转发到chrome.webview.postMessage

如果你想将 window.postMessage 消息发送到主机应用程序,最简单的方法是订阅目标 window

的 window.onmessage 事件
window.addEventListener("message", e => {
    if (shouldForwardToWebView2(e)) {
        window.chrome.webview.postMessage(e.data);
    }
});

如果您无法订阅该事件,您也可以填充 window.postMessage 方法:

const originalPostMessage = window.postMessage.bind(window);
window.postMessage = function (message, origin, transfer) {
    if (shouldForwardToWebView2(message)) {
        window.chrome.webview.postMessage(message);
    }
    originalPostMessage(message, origin, transfer);
};

填充这样的方法比较棘手,因为此填充代码中的任何错误都可能破坏任何尝试使用 postMessage 的东西,这与事件处理程序不同,后者的故障范围仅限于该事件处理程序。

在任何一种情况下,您都可能希望过滤转发到 WebView2 的消息,以确保您不会从其他库或来源发送不相关的消息,您不希望发送数据以限制攻击面。

此外,这仅在您要转发到 WebView2 的消息不依赖于 transfer 时有效。