How to communicate with WebView in a Chrome app?

I developed a website that I intend to display inside a webview in a Chrome app. It works great.

Now I want to use postMessage from the site, send messages from a web browser and to the containing Chrome application. This is done using top.postMessage inside the web view.

I tried the following event listeners:

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

I successfully executed the following event listeners. All of them work as expected: contentload , dialog and consolemessage .

If I can't get this to work, I am considering using consolemessage to send messages from the web view to the container - something I find unattractive, and I suspect that this will not work if you are not using developer mode.

+1
source share
3 answers

The reason the embedded webpage cannot send messages to the application is because the embedded webpage does not have a link to the application.

top.postMessage does not apply to the application. top will work if you are trying to access the topmost frame within a single web view.

To send messages to the application, the web page needs a link to the application. The easiest way to do this is to force the application to send the first message to the frame - a hello message.

From the app:

 // 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. }); 

On the web page:

 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
source

In the webview example, there is a good demonstration of using postMessage to send messages between the application and the external page loaded into the webview.

Here are the key code snippets.

  • In the application, listen to the loadstop event of the web browser and send the original message to the page. You can restrict this message to specific domains or pages.

     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/*"); } 
  • On the external page, listen for the message event and save the source and source.

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

    The page can then use these objects to send a message back to the application.

     function doSendMessage() { if (appWindow && appOrigin) { appWindow.postMessage("this is a message from the page!", appOrigin); } } 
  • The application must also listen for the message event to receive messages from an external page.

     window.addEventListener('message', function(e) { log("[???] messagereceived: " + e.data); }); 
+1
source
  • On the guest page inside the contained web browser, use chrome.runtime.sendMessage() to send messages to the containing application.

  • In the application, use chrome.runtime.onMessage.addListener() to listen to these messages.

Please note that you can send any application this way, not just the one that contains your onMessageExternal , but you need to know the application ID for this and use onMessageExternal instead of onMessage . For the containing application, an identifier is optional.

Here is a working example of this mechanism . This is a Polymer element, but this does not change the mechanism: designerProxy_ is the equivalent of your guest page; registerDesignerProxyListener_ is the equivalent of your application.

+1
source

Source: https://habr.com/ru/post/1200294/


All Articles