Sending information from Chromium Embedded (Javascript) to a containing C++ application

joshua-anderson picture joshua-anderson · Sep 21, 2013 · Viewed 8.4k times · Source

After checking out the Chromium Embedded Framework example I have a question. I need native interaction with the embedded part of my window. However, in the CEF example, all I saw was the c++ sending messages to the browser, not the other way around. I was wondering if there is any way to send a message from JavaScript from c++, like in the way of a function.

What I am looking for is something like this. I have a button in my webpage that when clicked. I would like to minimize the window. Is there any way to call some c++ from JavaScript in CEF?

Answer

mickeymicks picture mickeymicks · Jan 16, 2014

If anyone needs an example, here's one way i did it:

  1. Determine the custom 'protocol' you wish to use here's an example as a macro string #define PROTO_MYAPPCOMMAND "myapp://"

  2. On your custom CefApp class (the one inheriting from CefApp), also inherit from CefRenderProcessHandler.

  3. implement the OnBeforeNavigation() function:

    //declare (i.e. in header) 
    virtual bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser, 
        CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, 
        NavigationType navigation_type, bool is_redirect)  OVERRIDE; 
    
    //implementation 
    bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, 
        CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, 
        NavigationType navigation_type, bool is_redirect)
    {
        CefString cefval = request->GetURL(); 
        CString csval = cefval.c_str(); 
    
        if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0)
        {
            //process the command here 
    
            //this is a command and not really intended for navigation 
            return true; 
        }
    
        return false; //true cancels navigation, false allows it 
    }
    

Here's an example of adding an 'exit' app button:

in cpp

    #define STR_COMMANDAPPEXIT _T("command.appexit")
    bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, NavigationType navigation_type, bool is_redirect)
    {
        CefString cefval = request->GetURL(); 
        CString csval = cefval.c_str(); 

        if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0)
        {
            CString command = url; 
            command.Replace(PROTO_MYAPPCOMMAND, _T("")); 

            if (command.Find(STR_COMMANDAPPEXIT, 0) == 0) 
            {
                ::PostMessage(hwnd, WM_CLOSE, NULL, NULL); 
            }

            //this is a command and not really intended for navigation 
            return true; 
        }

        return false; //true cancels navigation, false allows it 
    }

also created a js utility file for all the operations to simplify calling them

    var MYHOST = MYHOST || {};
    /// Exit the Application (host app) 
    MYHOST.ExitApp = function() {
        window.location = 'myapp://command.appexit';
    };

in the pages js (i.e. in a button/div click)

    <div class="exitbutton" onclick="MYHOST.ExitApp();">Exit</div>

If you need to pass in parameters, just append them in the url in the js and parse the string in the cpp, like this:

    MYHOST.DoSomething = function() {
        window.location = 'myapp://command.dosomething?param1=' + value1 + "&param2=" + value2 + "&param3=" + value3;
    };

note: i've simplified the code but please do add the validations etc

Hope this helps!