javascriptc#chromium-embeddedcefglue

Call .NET from JavaScript using CefGlue / CEF3


There is an existing solution for CefGlue: Call .Net from javascript in CefSharp 1 - wpf

I want exactly this, but for CefGlue: I want to communicate with the App using JavaScript. So when I click a button in my HTML site, I want the application to handle this (for example: start a tcp server).

I tried to register an own CefV8Handler but without success, the Execute function on the handler is never called. Here is what I do right now

    protected override void OnWebKitInitialized()
    {
        Console.WriteLine("Registering testy extension");
        Xilium.CefGlue.CefRuntime.RegisterExtension("testy", "var testy;if (!testy)testy = {};(function() {testy.hello = function() {};})();", new V8Handler());
        base.OnWebKitInitialized();
    }

My V8Handler code looks as follows:

public class V8Handler : Xilium.CefGlue.CefV8Handler
{

    protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
    {

        if (name == "testy")
            Console.WriteLine("CALLED TESTY");
        else
            Console.WriteLine("CALLED SOMETHING WEIRED ({0})", name);

        returnValue = CefV8Value.CreateNull();
        exception = null;
        return true;

    }

}

I'm in multiprocess mode, no console window shows "CALLED TESTY" nor "CALLED SOMETHING WEIRED".


Solution

  • Found a solution for that. The trick is to create a CefV8Value (CreateFunction) and assign it to a V8Handler. Then assign this value to the global context. This is what it looks like:

    internal class RenderProcessHandler : CefRenderProcessHandler
    {
    
        protected override void OnContextCreated(CefBrowser browser, CefFrame frame, CefV8Context context)
        {
            CefV8Value global = context.GetGlobal();
            CefV8Value func = CefV8Value.CreateFunction("magic", new V8Handler());
            global.SetValue("magic", func, CefV8PropertyAttribute.None);
            base.OnContextCreated(browser, frame, context);
        }
    
    }
    

    Another problem came up: it was called in the renderer process, but I required the callback in the browser process. In the CefV8Handlers execute function i did this:

    var browser = CefV8Context.GetCurrentContext().GetBrowser();
    browser.SendProcessMessage(CefProcessId.Browser, CefProcessMessage.Create("ipc-js." + name));
    

    This way I can retrive the message in the OnProcessMessageReceived function in the CefClient implementation.