Closed RichardSteele closed 2 years ago
Thanks @RichardSteele! We'd need to come up with a way to ensure that the developer considers the iframe content trusted. When you say relationship between iframe and parent do you mean how many iframes deep it is, or do you mean if it has a matching or non-matching origin? Can you talk about your app a bit and how you are using postMessage & remote object?
Our client application integrates various third-party web applications using Microsoft's IE-based WebBrowser control. The control is customized via internet feature control keys to be "as modern" as possible. Unfortunately but understandably, some of our (potential) partners are unwilling to support IE11 (any longer).
There are two ways a web application can interact with our client. The second way is to use window.external
. By implementing IDocHostUIHandler::GetExternal
, we are able to provide a rich interface to our client.
One of those web applications enables external sources to interact with it by hosting iframes and providing them with a JavaScript framework. "Our" iframe uses window.external
to communicate with our client. It would be great to use window.chrome.webview.remoteObjects
or window.chrome.webview.postMessage
for this purpose.
Right now, I use window.parent.postMessage
to notify an event handler in the parent (added via ICoreWebView2::ExecuteScript
) which simply relays to window.chrome.webview.remoteObjects
or window.chrome.webview.postMessage
.
So, by relationship between an iframe and its parent I mean ther mismatching origins. As long as an iframe isn't sandboxed, window.external
is still available and it would be great to have a corresponding functionality in WebView2.
Hey all - we have enabled this functionality in an experimental API as part of 1.0.865-prerelease SDK package. Please take a look and give it a try: API Spec ICoreWebView2ExperimentalFrame type add_FrameCreated event
@champnic thanks for this, is there a way to send a postMessageAsJson from the c# component to the frame rather than it going to the main window? I have the situation where we are hosting a third party web application in our WebView2 control that then loads our web application within an iframe. We need to be able to send messages from the c# component to the iframe and receive messages back, and I have got the messages being sent back working fine using window.chrome.webview.postMessage. If I use the CoreViewView2.PostWebMessageAsJson then it goes to the main window rather than the iframe.
By the looks of the docs, the simplest way would be to add your own object with AddHostObjectToScript and communicate through that.
@ukandrewc the docs show that will work for the web being able to communicate back to the c# host but doesn't show how that would work the other way. I am trying to get it so that when I call the object from c# it will trigger something to happen within the javascript. If it wasn't for the iframe then I would be using:
window.chrome.webview.addEventListener("message", async (event) => { await handleHostRequest(event.data.type, event.data.payload); });
You'd need to add a JS receiver function from AddScriptToExecuteOnDocumentCreatedAsync (Which now adds to iframes) and communicate with that.
@ukandrewc Sorry if I am not getting it but in the sample on the getting started page https://docs.microsoft.com/en-us/microsoft-edge/webview2/get-started/winforms#step-8---communication-between-host-and-web-content it shows executing a script to handle the messages as await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(event.data));");
however I am already doing that in my application. My issue is how do I send the messages to the iframe so that the event listener is called?
If you have an example that would be very much appreciated.
@johnsharland77 Sorry, that could be my mistake. Just a bit caught up in stuff at the moment, but will look at it later.
@ukandrewc thank you for your help and time. I have worked out how to do it now thanks to your pointers.
In my c# code I am injecting some javascript to post messages to the frame that has my app in it
var javascript = new System.Text.StringBuilder();
javascript.Append("if(window.chrome.webview){");
javascript.Append(" window.chrome.webview.addEventListener(\"message\", async(event) => {");
javascript.Append(" for (let index = 0; index < window.frames.length; index++)");
javascript.Append(" {");
javascript.Append(" const frame = window.frames[index];");
javascript.Append(" frame.postMessage(event.data, \"myurl\");");
javascript.Append(" }");
javascript.Append(" });");
javascript.Append("};");
await webViewHost.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(javascript.ToString());
and then in my app I use the window.addEventListener to subscribe to the messages:
window.addEventListener("message", async (event) => {
if (event !== undefined) {
...
}
});
@johnsharland77 That's good, I could initially see a way, then got bogged down in another issue and couldn't remember what I had first thought of ;-)
PS: Have a look at this to save all that appending.
@johnsharland77 Sorry I should have been clearer - the postMessage part of this work is still in progress, but we do intend to have the ability to send messages directly to an iframe.
@champnic Do you mean your team plans to support direct communication between c++ and iframe? We have similar requirement, it will be better if we can avoid using main frame as proxy between c++ and iframe.
We do have plans for direct communication between C++ and iframe, using both postMessage and ExecuteScript - I'm just not sure what the timeline is yet for that work.
This support is now available in 1.0.1083-prerelease+: https://docs.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2frame.postwebmessageasjson?view=webview2-dotnet-1.0.1083-prerelease
Thanks!
Is the window.chrome.webview.postMessage supposed to be working for iframes? I think I did everything right but I'm just not receiving any WebMessages. Here's what I did -
I debugged the JS side and I'm not seeing any problems, the script has the postMessage interface available, and it sends the message with no apparent problem. I debugged the .NET side and I get the FrameCreated event and I register for WebMessagres with no apparent problem.
Eventually, I used the following workaround to look up the target function in JS, would love to know of any downside
(() => {win = window; while (win.parent != win) win = win.parent; return win.chrome.webview.postMessage;})"
window.chrome.webview
is undefined within an iframe. This prevents iframes from communicating with the host through objects added byICoreWebView2::AddRemoteObject
or by callingwindow.chrome.webview.postMessage
. Instead, I have to resort towindow.parent.chrome.webview
orwindow.parent.postMessage
depending on the relationship between an iframe and its parent.AB#25546101