CEF:注册JS回调

匿名 (未验证) 提交于 2019-12-02 23:42:01

前面我们学习了C++和JS的基本交互。例如C++调用js。

browser->GetMainFrame()->ExecuteJavaScript(js, L"", 0); 

但是在实际应用过程中可能我们事先并不知道函数原型,而是使用的函数指针来回调结果。例如:

do_event(call_back,parama1,parama2,....paramaN) 

此时需要使用CEF::ExecuteFunction 和ExecuteFunctionWithContext()方法执行JS函数。ExecuteFunction()方法只允许用在V8中,且V8在“使用上下文”所描述的上下文中。ExecuteFunctionWithContext()方法允许应用程序指定即将执行的上下文。

下面我们将实现一个最简单的回调模型:注册+回调。

步骤:

  1. CefV8Handler实现register
  2. 保存Callback的上下文
  3. 进入上下文调用回调
  4. 执行完退出上下文
//Render进程注册回调函数 void CRenderApp::OnWebKitInitialized() { 	CEF_REQUIRE_RENDERER_THREAD();  	// Define the extension contents. 	std::string extensionCode = 		"var MyMath;" 		"if (!MyMath)"//如果没有MyMath对象,则定义一个MyMath对象 		"  MyMath = {};" 		"(function() {" 		"  MyMath.register = function(call_back) {"//定义一个MyMath的add函数 		"    native function register(call_back);" 		"    return register(call_back);"//add在CefV8Handler具体实现 		"  };" 		"  MyMath.hellow = 'Hello JS!';"//定义一个MyMath的成员变量 		"})();";  	CefRefPtr<CefV8Handler> add_handler = new CJSHandler(this); 	// Register the extension. 	CefRegisterExtension("v8/test", extensionCode, add_handler); } 
//实现注册函数 bool CJSHandler::Execute(const CefString& name, 	CefRefPtr<CefV8Value> object, 	const CefV8ValueList& arguments, 	CefRefPtr<CefV8Value>& retval, 	CefString& exception) { 	//callback register 	if (name == "register") 	{ 		if (arguments.size() == 1 && arguments[0]->IsFunction()) 		{ 			CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext(); 			CefRefPtr<CefV8Value> call_back = arguments[0]; 			//由于这里只是一个demo,所以把funcid固定为1,如果存在多个注册回调函数,请维护funcid和callback的关系 			//if (m_render_app) 			//	m_render_app->AddCallBack(1, context, call_back);  			//调用回调,进入上下文 			context->Enter();  			CefV8ValueList call_arguments; 			call_arguments.push_back(CefV8Value::CreateString(_T("hellow word"))); 			//调用回调函数,回调参数 			call_back->ExecuteFunction(NULL, call_arguments);  			//退出上下文 			context->Exit(); 			return true; 		} 	}  	// 	return false; } 

结果:

当然我这里事实是最简单的一个demo,在实际过程中我们应该将call_back和call_context保存起来,当结果处理完成之后执行回调。

typedef std::map<int32, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > > CallbackMap; 

正常的工作流程:

  1. 注册=》添加回调到map(map存在render进程中)
  2. js触发事件(事件投递到Browser进程处理或者自己直接处理)
  3. 处理完成(如果投递到Browser进程处理,则处理完成之后投递到Render进程)调用回调
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("test"); browser->SendProcessMessage 

参考文档:
https://github.com/fanfeilong/cefutil/tree/master/doc
https://github.com/fanfeilong/cefutil/blob/master/doc/content_register_v8_extension.md

文章来源: https://blog.csdn.net/CAir2/article/details/91576805
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!