Chromium和CEF使用V8 JavaScript引擎 作为它们内部的Javascript实现。浏览器中的每一页(Frame)都有它自己的JS上下文,上下文提供一个空间和安全机制来执行页面上的JS代码,CEF为客户应用程序暴露了多个JS特性,其中js扩展可实现js代码调用c++方法
实现:
1、注册一个V8扩展与js代码
void InitExtensionTest() { // Register a V8 extension with the below JavaScript code that calls native // methods implemented in ClientV8ExtensionHandler. std::string code = "var cef;" "if (!cef)" " cef = {};" "if (!cef.test)" " cef.test = {};" "(function() {" " cef.test.__defineGetter__('test_param', function() {" " native function GetTestParam();" " return GetTestParam();" " });" " cef.test.__defineSetter__('test_param', function(b) {" " native function SetTestParam();" " if (b) SetTestParam(b);" " });" " cef.test.test_object = function() {" " native function GetTestObject();" " return GetTestObject();" " };" " cef.test.loadurl = function(val) {" " native function loadurl();" " return loadurl(val);" " };" " cef.test.IndicatorsCloud = function(val1, val2) {" " native function IndicatorsCloud();" " return IndicatorsCloud(val1, val2);" " };" "})();"; CefRegisterExtension("v8/test", code, new ClientV8ExtensionHandler());//code表示的字符串是任意合法的JS代码 }
class ClientV8ExtensionHandler : public CefV8Handler { public: ClientV8ExtensionHandler() : test_param_("An initial string value.") {} virtual ~ClientV8ExtensionHandler() {} // Execute with the specified argument list and return value. Return true if // the method was handled. //该方法继承CefV8Handler必需实现 //功能:判断js调用的本地方法名称,接收参数传递和返回值,实现方法具体功能 virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) { if (name == "SetTestParam") { // Handle the SetTestParam native function by saving the string argument // into the local member. if (arguments.size() != 1 || !arguments[0]->IsString()) return false; test_param_ = arguments[0]->GetStringValue(); return true; } else if (name == "GetTestParam") { // Handle the GetTestParam native function by returning the local member // value. retval = CefV8Value::CreateString(test_param_); return true; } else if (name == "GetTestObject") { // Handle the GetTestObject native function by creating and returning a // new V8 object. retval = CefV8Value::CreateObject(NULL); // Add a string parameter to the new V8 object. retval->SetValue("param", CefV8Value::CreateString( "Retrieving a parameter on a native object succeeded."), V8_PROPERTY_ATTRIBUTE_NONE); // Add a function to the new V8 object. retval->SetValue("GetMessage", CefV8Value::CreateFunction("GetMessage", this), V8_PROPERTY_ATTRIBUTE_NONE); return true; } else if (name == "GetMessage") { // Handle the GetMessage object function by returning a string. retval = CefV8Value::CreateString( "Calling a function on a native object succeeded."); return true; } else if (name == "loadurl") { if (arguments.size() != 1) return false; if (arguments[0]->IsString()) { retval = CefV8Value::CreateString( arguments[0]->GetStringValue()); } return true; } else if (name == "IndicatorsCloud") { if (arguments.size() != 2) return false; if (arguments[0]->IsInt() && arguments[1]->IsString()) { retval = CefV8Value::CreateInt(arguments[0]->GetIntValue()); } return true; } return false; } private: CefString test_param_; IMPLEMENT_REFCOUNTING(ClientV8ExtensionHandler); };
void RunExtensionTest(CefRefPtr<CefBrowser> browser) { std::string html = "<html><body>ClientV8ExtensionHandler says:<br><pre>" "<script language=\"JavaScript\">" "cef.test.test_param =" " 'Assign and retrieve a value succeeded the first time.';" "document.writeln(cef.test.test_param);" "cef.test.test_param =" " 'Assign and retrieve a value succeeded the second time.';" "document.writeln(cef.test.test_param);" "var obj = cef.test.test_object();" "document.writeln(obj.param);" "document.writeln(obj.GetMessage());" "document.writeln(cef.test.loadurl(\"hello world.\"));" "document.writeln(cef.test.IndicatorsCloud(123456789, \"leadsec.\"));" "</script>" "</pre></body></html>"; browser->GetMainFrame()->LoadString(html, "about:blank"); }