I'm looking at using WebView2 to create a browser with some custom functionality. This is something I've been trying to do in both CEFSharp and GeckoFX for sometime now without success.
Essentially, I'm trying to build a desktop browser that will allow me to debug TV Applications conforming to the HbbTV/Oipf standard on my windows desktop due to the difficulty involved in doing this remotely against a real TV set.
The exact API I have to implement can be found documented here: https://www.oipf.tv/web-spec/volume5.html if anyone is interested, but for the purposes of this question, I'm just going to concentrate on one of the basic API calls "isObjectSupported" which is part of the "oipfObjectFactory" static global window object.
This call, returns a bool that is either true/false informing the caller that the mime type string passed to it is or is-not supported by the device running the application.
Right now, the only way I seem to be able to get that data passed to my C# app and for and for my C# app to respond to the browser, is to use
window.chrome.webview.postMessage({type: "isObjectSupported", mime: mimeType});
in Javascript, and respond with:
webView.CoreWebView2.PostWebMessageAsString("true"); // or "false"
in C#
In an async fashion, this all works great, but the apps using the implemented function call in the API extension will NOT be calling isObjectSupported in an async way. That is, they won't be awaiting, and they will expect the first return they see to be the answer to the function called.
The HbbTV specification was defined before browsers started to get clever with things like async/await, so in the actual TV's themselves most of them run something like Opera for TV's V4x.0
In order fro me to implement the API calls correctly, I essentially need to be able to provide a JavaScript shim that does the following:
1) Send the mime string to my C# code.
2) Spins in a loop until a message event is received back from the C# code.
3) Decodes the message and returns the result.
Item 2 however as we know cannot be done in JavaScript without holding up the single threaded loop that it all runs on, which in turn would hold up 3 and deadlock.
And there seems no way I can send the message and wait on the result.
I can't make the exposed API async either, as that will cause a promise to be returned, which the caller will not be expecting (or even know how to deal with) and will so just assume a true response (As I've already tried)
What would work perfectly would be something along the lines of:
function isObjectSupported(mimeType)
{
result = window.chrome.webview.postMessage({type: "isObjectSupported", mime: mimeType}).waitForReply();
var actualResult = parse(result);
return actualResult;
}
or some other way of calling say:
result = window.chrome.webview.isObjectSupported("blah...");
which would automatically find and call
public bool isObjectSupported(mime){ ... return true; }
in the C# code in the app itself.
I had hoped that
webView.CoreWebView2.AddHostObjectToScript("oipfObjectFactory", new oipfObjectFactory());
would have worked, but all I get no matter what I try is "System.ArgumentException: value does not fall within the expected range".
Ideally we would be able to add objects with both public properties and public methods and have them appear in the global object, then we could just build out the extensions in pure C#
It is partially possible to do this using CEFSharp, but you either only get properties, or methods, not both, and since some of the more complex API's in the specification return a mix of methods and properties CEFSharp has been a non starter.
So, in summary: is there a way I can do this synchronous call in WebView2 that I've not noticed in the doc's or is there a way we can make the coll to postmessage and wait on the result so that I can at least try to build the functionality out in a JS shim/polyfill.