Interaction between C ++ and JavaScript in libCEF

Source: Internet
Author: User

Interaction between C ++ and JavaScript in libCEF
Preface

The previous article introduced the example of how CEF embedded chrome kernel browser in WIN32 program: http://blog.csdn.net/mfcing/article/details/43973377

This section describes the interaction between JS script functions on the web page and C ++ code after the browser is embedded. For example, playing on a webpage in a music player, downloading resources in the client Resource Center ......

 

JS calls C ++ Functions

First, we need to rewrite the OnContextCreated interface of CefRenderProcessHandler. Why? To learn how to use the CEF library, you must carefully read the watch section in his header file:

 

  // Called immediately after the V8 context for a frame has been created. To  // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()  // method. V8 handles can only be accessed from the thread on which they are  // created. A task runner for posting tasks on the associated thread can be  // retrieved via the CefV8Context::GetTaskRunner() method.  ///  /*--cef()--*/  virtual void OnContextCreated(CefRefPtr
 
   browser,                                CefRefPtr
  
    frame,                                CefRefPtr
   
     context) {}
   
  
 
This interface is actually called After chrome V8 engine is created. here we need to associate the functions called in JS with the execution functions of C ++, in this way, JS can "execute" C ++ code.

 

All our functions are defined in the window object (I don't know if this is called an object in JS). GetGlobal needs to get this object according to the gaze.

My code is as follows:

 

CefRefPtr
 
   window = context->GetGlobal();CefRefPtr
  
    myV8Acc = new CCefV8Accessor;CefRefPtr
   
     val = CefV8Value::CreateString(L"Application");CefString cefException;myV8Acc->Set(L"name", window, val, cefException);CefRefPtr
    
      pObjApp = CefV8Value::CreateObject(myV8Acc);window->SetValue(L"Application", pObjApp, V8_PROPERTY_ATTRIBUTE_NONE);CefRefPtr
     
       myV8handle = new CCefV8Handler();CefRefPtr
      
        myFun = CefV8Value::CreateFunction(L"SetAppState", myV8handle);static_cast
       
        (myV8handle.get())->AddFun(L"SetAppState", &CChromeJsCallback::JsSetAppState);pObjApp->SetValue(L"SetAppState", myFun, V8_PROPERTY_ATTRIBUTE_NONE);myFun = CefV8Value::CreateFunction(L"OneClickInstall", myV8handle);static_cast
        
         (myV8handle.get())->AddFun(L"OneClickInstall", &CChromeJsCallback::JsOneKeyInstall);pObjApp->SetValue(L"OneClickInstall", myFun, V8_PROPERTY_ATTRIBUTE_NONE);myFun = CefV8Value::CreateFunction(L"DownLoadFile", myV8handle);static_cast
         
          (myV8handle.get())->AddFun(L"DownLoadFile", &CChromeJsCallback::JsDownloadFile);pObjApp->SetValue(L"DownLoadFile", myFun, V8_PROPERTY_ATTRIBUTE_NONE);
         
        
       
      
     
    
   
  
 

All JS functions are on window. Application. Therefore, you must create an Application object on the window object. CefV8Value: CreateObject is used to create an object. The CefV8Value class is very important in JS processing. It is necessary to take a good look at the gaze in the header file. the gaze of CEF is quite detailed.

 

 

The process of creating function objects and binding JS functions to C ++ function pointers is described in detail.

 

CefRefPtr
 
   myV8handle = new CCefV8Handler();CefRefPtr
  
    myFun = CefV8Value::CreateFunction(L"SetAppState", myV8handle);static_cast
   
    (myV8handle.get())->AddFun(L"SetAppState", &CChromeJsCallback::JsSetAppState);pObjApp->SetValue(L"SetAppState", myFun, V8_PROPERTY_ATTRIBUTE_NONE);
   
  
 

Create a V8 Object Pointer, but the new one is a CCefV8Handler, which needs to be extended by yourself. I did this:

 

 

// Define the JS callback function pointer typedef bool (* JS_CALLBACK_FUN) (const CefV8ValueList &, CefRefPtr
 
  
&); Typedef map
  
   
FunctionMap; class CCefV8Handler: public CefV8Handler {public: CCefV8Handler (); virtual bool Execute (const CefString & name, CefRefPtr
   
    
Object, \ const CefV8ValueList & arguments, CefRefPtr
    
     
& Retval, CefString & exception); bool AddFun (const CefString & strName, JS_CALLBACK_FUN pFun); private: FunctionMapm_fun; // Include the default reference counting implementation. Handler (CCefV8Handler );};
    
   
  
 

 

 

CCefV8Handler::CCefV8Handler(){}bool CCefV8Handler::Execute( const CefString& name, CefRefPtr
 
   object, \const CefV8ValueList& arguments, CefRefPtr
  
   & retval, CefString& exception ){FunctionMap::iterator itor = m_fun.find(name);if ( itor == m_fun.end() )return false;itor->second(arguments, retval);return true;}bool CCefV8Handler::AddFun( const CefString& strName, JS_CALLBACK_FUN pFun ){if ( strName.empty() )return false;m_fun.insert(std::pair
   
    (strName, pFun));return true;}
   
  
 


 


AddFun is a self-added function that stores a function and the corresponding callback address in this V8 object. Therefore, a member variable typedef map is used. FunctionMap: when calling a function, the V8 engine has an interface Execute. Here we call the function name to find it in map and find its corresponding callback address to call the function, this is the process of JS Calling C ++.

 

In the code above, we added three functions SetAppState, OneClickInstall, and DownLoadFile to the window. application object.

 

In C ++ Code, these three functions are written as follows:

 

// JS function, which calls static boolJsSetAppState (const CefV8ValueList & argList, CefRefPtr
  
   
& RetValue); static boolJsOneKeyInstall (const CefV8ValueList & argList, CefRefPtr
   
    
& RetValue); static boolJsDownloadFile (const CefV8ValueList & argList, CefRefPtr
    
     
& RetValue );
    
   
  

VCefV8ValueList is a list of parameters. Its definition is typedef std: vector. > CefV8ValueList, retValue is of course the return value of the function, and some JS needs to handle it according to the return value.

 

Note: The CEF can use the single-process and multi-process modes. In my program, the multi-process mode is used. Therefore, the execution of the V8 engine is in the rendering engine, do not try to process the interface directly here. The interface process and the rendering process are separated. If the data is used, the shared memory is used, and the interface updates and sends messages.

 

C ++ calls JS Functions

C ++ is much easier to call JS functions, because CEF has interfaces that can directly use CefFrame: ExecuteJavaScript. Let's take a look at the notes:

 

  // Execute a string of JavaScript code in this frame. The |script_url|  // parameter is the URL where the script in question can be found, if any.  // The renderer may request this URL to show the developer the source of the  // error.  The |start_line| parameter is the base line number to use for error  // reporting.  ///  /*--cef(optional_param=script_url)--*/  virtual void ExecuteJavaScript(const CefString& code,                                 const CefString& script_url,                                 int start_line) =0;

First, we need to obtain the main framework object in our browser. The code is a JS function and a string of input parameters. The URL can be directly ignored.

 

 

void CChromeBrowserUI::ExecuteJavascript( const wstring& strCode ){if ( m_pWebBrowser.get() ){CefRefPtr
   
     frame = m_pWebBrowser->GetMainFrame();if ( frame.get() ){CefString strCode(strCode.c_str()), strUrl(L"");frame->ExecuteJavaScript(strCode, strUrl, 0);}}}
   
Note: function names and parameter names must be separated by single quotes.

 

My string formatting section:

 

CString strJsCode;strJsCode.Format(L"setInstallStatus('%s','%s','%d');", lpData->strId.c_str(), strStatus, nPercent);

In this way, C ++ can call JS functions and input corresponding parameters.

 

To sum up using CEF, it is best to carefully read the notes in the header file, which is very detailed.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.