如何在Chrome App中与WebView进行通信?

时间:2015-05-21 07:39:27

标签: javascript google-chrome-extension google-chrome-app cordova-chrome-app

我开发了一个网站,我打算在Chrome浏览器中的网页浏览中显示。这很好。

现在,我想从网站上使用postMessage,将消息从webview发送到包含的Chrome应用程序。这是通过网络视图中的top.postMessage完成的。

我尝试过以下事件监听器:

webView.contentWindow.addEventListener('message', messageHandler);

webView.addEventListener('message', messageHandler);

window.addEventListener('message', messageHandler);

document.addEventListener('message', messageHandler);

我已成功实现以下事件侦听器。所有这些都按预期工作:contentloaddialogconsolemessage

除非我能让这个工作,否则我正在考虑使用consolemessage将消息从webview发送到容器 - 我发现这些消息没有吸引力,我怀疑它在不使用开发者模式时不起作用。

3 个答案:

答案 0 :(得分:6)

webview sample有一个很好的演示,使用postMessage在应用程序和webview中加载的外部页面之间发送消息。

以下是关键代码。

  1. 在应用程序中,收听webview的loadstop事件并向页面发送初始消息。您可以将此邮件限制为特定的域或页面。

    wv1.addEventListener('loadstop', sendInitialMessage);
    
    function sendInitialMessage(e) {
     // only send the message if the page was loaded from googledrive hosting
     e.target.contentWindow.postMessage("initial message", "https://googledrive.com/host/*");
    }
    
  2. 在外部页面中,侦听message事件并保存源和来源。

    window.addEventListener('message', onMessage);
    
    var appWindow, appOrigin;
    
    function onMessage(e) {
     appWindow = e.source;
     appOrigin = e.origin;
    }
    

    然后页面可以使用这些对象将消息发回给应用程序。

    function doSendMessage() {
     if (appWindow && appOrigin) {
      appWindow.postMessage("this is a message from the page!", appOrigin);
     } 
    }
    
  3. 该应用还应该收听message事件,以便从外部页面接收消息。

    window.addEventListener('message', function(e) {
     log("[???] messagereceived: " + e.data);
    });
    

答案 1 :(得分:3)

嵌入式网页无法向应用发布消息的原因是因为嵌入式网页没有对该应用的引用。

top.postMessage 是对该应用的引用。如果您尝试访问同一网页视图中的最顶层框架,top会有效。

为了能够向应用发送消息,网页需要引用该应用。最简单的方法是让应用程序将第一条消息发送到框架 - " hello" -message。

来自应用:

// Initialize communications
webView.contentWindow.postMessage('hello, webpage!', 'https://your.web.page/*');
addEventListener('message', function(e) {

    // I expect this check to work, but I have not tested it.
    if (e.source != webView.contentWindow)
        return;

    // Handle e.data however you want.
});

在网页中:

var messageSource, messageOrigin;
addEventListener('message', function(e) {
    if (!messageSource) {

        /*
         * Once we have a messageSource, we should not allow anybody to change
         * messageSource again
         */

        if (e.data == "hello, webpage!") {

            /*
             * If possible, you should validate the `e.origin` value here. It could 
             * possibly come from somewhere else. However, this is quite safe as it 
             * stands, since there only is a very narrow time window where the app 
             * is open willing to accept the "hello, webpage!" message.
             *
             * Another way of validating, is by having the app wait for the 
             * "hello, host!" message. If that response is not received within a second
             * the app host could simply reload the app.
             */

            messageSource = e.source;
            messageOrigin = e.origin;
            messageSource.postMessage("hello, host!", messageOrigin);
        }
    } else {
        // Handle messages however you like. This will simply respond to every message:
        messageSource.postMessage('Your message: ' + e.data, messageOrigin);
    }
});

答案 2 :(得分:1)

  • 在收录的网页浏览中的访客页面中,使用chrome.runtime.sendMessage()向包含的应用发送消息。

  • 在应用中,使用chrome.runtime.onMessage.addListener()收听这些消息。

请注意,您可以通过这种方式向任何应用发送消息,而不仅仅是包含您的网络视图的应用,但您需要知道应用的ID,并使用onMessageExternal代替{ {1}}。对于包含应用程序,ID是可选的。

此处a working example of this mechanism。它是一个Polymer元素,但这并没有改变机制:onMessage相当于你的访客页面; designerProxy_相当于您的应用。