window.postMessage VS window.chrome.webview.postMessage

Posted

技术标签:

【中文标题】window.postMessage VS window.chrome.webview.postMessage【英文标题】: 【发布时间】:2021-10-24 17:27:58 【问题描述】:

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

【问题讨论】:

developer.mozilla.org/en-US/docs/Web/API/Window/postMessage 【参考方案1】:

chrome.webview.postMessage method 是 WebView2 特定的 javascript 函数,它允许 Web 内容通过 CoreWebView2.WebMessageReceived 事件将消息发送到主机应用程序。它以 HTML 标准 window.postMessage DOM API 为模式,但除了 chrome.webview.postMessage 将消息发布到主机应用程序和 window.postMessage 将消息发布到其他窗口的巨大差异之外,还有一些不同之处:

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 方法用于向其他窗口发布消息,存在该窗口可能不在正确的来源上并且不允许接收消息数据的风险。 origin 参数允许调用者指定允许接收数据的来源。

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

传递参数

window.postMessage 的可选传输参数允许将特定类型的 JavaScript 对象移动到目标窗口。这包括消息端口和大型数据数组等内容。

WebView2 目前不支持这种场景,同样 chrome.webview.postMessage 也没有这个参数。

转发到 chrome.webview.postMessage

如果您想将 window.postMessage 消息发送到宿主应用程序,最简单的方法是订阅目标窗口的 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 时才有效。

【讨论】:

以上是关于window.postMessage VS window.chrome.webview.postMessage的主要内容,如果未能解决你的问题,请参考以下文章

跨域通信--Window.postMessage()

HTML5中window.postMessage,在两个页面之间的数据传递

使用 window.postMessage 发送敏感数据是不是安全?

Internet Explorer 11 中的 window.postMessage 是不是有最大长度限制?

window.postMessage解决跨域

在 Swift WKWebView 中捕获 window.postMessage