I do example based on cefclient project.
modify client_renderer.cc, class ClientRenderDelegate implements CefV8Handler's interface Execute.
class ClientRenderDelegate : public ClientAppRenderer::Delegate, CefV8Handler
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
if (name.compare("myfunc") == 0) {
// Return my string value.
retval = CefV8Value::CreateString("My Value!");
return true;
}
else if (name.compare("registercb") == 0) {
if (arguments.size() == 1 && arguments[0]->IsFunction()) {
js_callback_ = arguments[0].get();
js_context_ = CefV8Context::GetCurrentContext();
}
return true;
}
// Function does not exist.
return false;
}
JS call native function
in ClientRenderDelegate OnContextCreated(), register a function named myfun,
// Retrieve the context's window object.
CefRefPtr<CefV8Value> object = context->GetGlobal();
// Create a new V8 string value. See the "Basic JS Types" section below.
CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");
// Add the string to the window object as "window.myval". See the "JS Objects" section below.
object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE);
CefRefPtr<CefV8Handler> myhandler = this;
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", myhandler);
object->SetValue("myfunc", func, V8_PROPERTY_ATTRIBUTE_NONE);
myhandler is ClientRenderDelegate object which inherite CefV8Handler, implements Execucte()
in JS,
<script> /* alert(window.myval); // this is for object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE)
alert(window.myfunc()); </script>*/
native call JS
in ClientRenderDelegate OnContextCreated(), register a function named registercb,
object->SetValue("registercb", CefV8Value::CreateFunction("registercb", myhandler), V8_PROPERTY_ATTRIBUTE_NONE);
define 2 member val,CefRefPtr<CefV8Context> js_context_; CefRefPtr<CefV8Value> js_callback_;
in Execute(), save JS function callback and render context.in JS,
function n2jFunc() { alert("native call js function"); } window.registercb(n2jFunc);
in root_window_win.cc, replace reload button's method,case IDC_NAV_RELOAD: // Reload button if (CefRefPtr<CefBrowser> browser = GetBrowser()) { //browser->Reload(); { // Create the message object. CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("calljs"); // Retrieve the argument list object. CefRefPtr<CefListValue> args = msg->GetArgumentList(); // Populate the argument values. args->SetString(0, "calljs"); args->SetInt(0, 10); // Send the process message to the render process. // Use PID_BROWSER instead when sending a message to the browser process. browser->SendProcessMessage(PID_RENDERER, msg); _cwprintf(L" send mesage calljs to render \n"); } }
Send a message calljs from browser process to render process,in ClientRenderDelegate OnProcessMessageReceived(), run JS function n2jFunc()
const std::string& message_name = message->GetName(); // MessageBox(NULL, L" TEST", L"EditWndProc receive message", MB_OK); if (message_name == "calljs" ) { //browser->GetMainFrame()->ExecuteJavaScript("alert('ExecuteJavaScript works!');", // browser->GetMainFrame()->GetURL(), 0); if (js_callback_) { CefV8ValueList args; CefString str = message->GetArgumentList()->GetString(0); args.push_back(CefV8Value::CreateString(str)); args.push_back(CefV8Value::CreateInt(message->GetArgumentList()->GetInt(1))); js_callback_->ExecuteFunctionWithContext(js_context_, NULL, args); } return true; } return message_router_->OnProcessMessageReceived(browser, source_process, message);