I have a Chromium Embedded Framework (CEF) application where we want to communicate between the client-JavaScript side to the browser-side. So fare we have the possibility of using a generic message router GenericMessageRouter: The client then executes something like this to send a message to the browser thread:
var request_id = window.cefQuery({
request: 'my_request',
persistent: false,
onSuccess: function(response) {},
onFailure: function(error_code, error_message) {}
});
// which will be receiven by the browser with
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback)
I was wondering what kind of solution would be the best if we want to send bidirectional binary data (serialized data for example with Google Protocol Buffers). So far as I have seen ArrayBuffer
is not reallly supported in CEF which is a bit unfortunate. Can we also misuse the CefString
or is this a bad idea?
Here is the prefect manual https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration
Extensions are like window bindings except they are loaded into the context for every frame and cannot be modified once loaded. The DOM does not exist when an extension is loaded and attempts to access the DOM during extension loading will result in a crash. Extensions are registered using the CefRegisterExtension() function which should be called from the CefRenderProcessHandler::OnWebKitInitialized() method.
JS Functions
CEF supports the creation of JS functions with native implementations. Functions are created using the CefV8Value::CreateFunction() static method that accepts name and CefV8Handler arguments. Functions can only be created and used from within a context (see the "Working with Contexts" section for more information).
CefRefPtr<CefV8Handler> handler = …;
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
An implementation of the CefV8Handler interface that must be provided by the client application.
class MyV8Handler : public CefV8Handler {
public:
MyV8Handler() {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
if (name == "myfunc") {
// Extract argument values
// ...
// Do work
// ...
// Return my string value.
retval = CefV8Value::CreateString("My Value!");
return true;
}
// Function does not exist.
return false;
}
// Provide the reference counting implementation for this class.
IMPLEMENT_REFCOUNTING(MyV8Handler);
};
Functions and Window Binding
Functions can be used to create complex window bindings.
void MyRenderProcessHandler::OnContextCreated(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
// Retrieve the context's window object.
CefRefPtr<CefV8Value> object = context->GetGlobal();
// Create an instance of my CefV8Handler object.
CefRefPtr<CefV8Handler> handler = new MyV8Handler();
// Create the "myfunc" function.
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
// Add the "myfunc" function to the "window" object.
object->SetValue("myfunc", func, V8_PROPERTY_ATTRIBUTE_NONE);
}
Call in JavaScript
<script language="JavaScript">
alert(window.myfunc(myJSON)); // Calls the function "myFunc" and passes the JSON through function argument
</script>
Functions and Extensions
Functions can be used to create complex extensions. Note the use of the "native function" forward declaration which is required when using extensions.
void MyRenderProcessHandler::OnWebKitInitialized() {
// Define the extension contents.
std::string extensionCode =
"var test;"
"if (!test)"
" test = {};"
"(function() {"
" test.myfunc = function(json) {"
" native function myfunc();"
" return myfunc(json);"
" };"
"})();";
// Create an instance of my CefV8Handler object.
CefRefPtr<CefV8Handler> handler = new MyV8Handler();
// Register the extension.
CefRegisterExtension("v8/test", extensionCode, handler);
}
Call in JavaScript
<script language="JavaScript">
alert(test.myfunc(myJSON)); // Calls the function "myFunc" and passes the JSON through function argument
</script>
Google protobuf is not suitable for interops between JS and native functions. Use JSON. JS objects can be transparently serialized to JSON and wise versa.