3.1 CEF和JavaScript交互 3.1.1 在CEF执行JavaScript脚本 3.1.2 窗口绑定方式实现CEF设置JavaScript的变量 3.1.3 扩展方式(Extension)实现CEF设置JavaScript的变量 3.1.4 窗口绑定方式实现CEF给JavaScript提供函数 3.1.5 Extension方式实现CEF给JavaScript提供函数
3.1 CEF和JavaScript交互https:///chromiumembedded/cef/wiki/JavaScriptIntegration.md CEF使用的V8 JavaScript 引擎用于内部JavaScript实现,每一个frame都有JS上下文(context),为JS代码执行提供范围和安全。CEF暴露了很多JS特性可以和客户端程序进行交互。 3.1.1 在CEF执行JavaScript脚本应用场景是需要在CEF中拦截一个URL请求,并把它重定向到另外一个URL,可以调用pFrame->ExecuteJavaScript来执行一个JavaScript脚本,实现跳转。当然也可以实现其他应用功能。 CefRefPtr<CefFrame> pFrame = browser->GetMainFrame(); std::string strurl = pFrame->GetURL().ToString(); std::string strname = pFrame->GetName().ToString(); pFrame->GetName().ToString().c_str()); if (pFrame->GetURL() == "https://10.19.141.75/portal/") { pFrame->ExecuteJavaScript("var param= { url:'https://10.19.141.75/ishelf-web/personalCenter' }; \ window.goToApp(param);\ var paramEx = { isExtend:true };\ window.extendScreen(paramEx);\ ", pFrame->GetURL(), 0); } 3.1.2 窗口绑定方式实现CEF设置JavaScript的变量在CEF程序中,创建一个CefV8Value对象,获取上下文的窗口对象,注入窗口对象一个变量值,网页中就可以使用JavaScript获取这个变量值。窗口绑定在CefRenderProcessHandler::OnContextCreated()函数中。是上下文创建响应函数,窗口绑定方式在每次frame重新加载(context创建)时都会加载一遍,CEF程序可以在OnContextCreated()给每一个frame设置不同的变量值。 CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) { // 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); } JavaScript in the frame can then interact with the window bindings.
<script language="JavaScript"> alert(window.myval); // Shows an alert box with "My Value!" </script> 3.1.3 扩展方式(Extension)实现CEF设置JavaScript的变量Extension方式和窗口绑定方式类似,但是Extension方式是为每一个frame加载到上下文context,一旦加载变不能在修改,没有加载之前,DOM是不存在的,尝试范围这个值的DOM会出现崩溃。Extension方式是在CefRenderProcessHandler::OnWebKitInitialized()函数中用CefRegisterExtension() 函数注册的,是在初始化函数中实现的,所以对于每一个frame都是一样的。 void MyRenderProcessHandler::OnWebKitInitialized() { // Define the extension contents. std::string extensionCode = "var test;" "if (!test)" " test = {};" "(function() {" " test.myval = 'My Value!';" "})();";
// Register the extension. CefRegisterExtension("v8/test", extensionCode, NULL); } JS中调用变量值 <script language="JavaScript"> alert(test.myval); // Shows an alert box with "My Value!" </script> 3.1.4 窗口绑定方式实现CEF给JavaScript提供函数(1) 自定义类实现CefV8Handler类,实现Execute接口,JavaScript执行函数后,会将函数名称、参数和返回值引用传递给Execute函数,Execute函数根据函数名去调用函数,函数的具体实现在Execute中,然后执行返回返回值。 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") { // 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); }; (2)将函数名称设置到窗口对象,提供接受调用的handle 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); } (3)JavaScript执行函数调用,就会进入Execute函数,返回返回值,alert会以弹窗形式展示结果。 <script language="JavaScript"> alert(window.myfunc()); // Shows an alert box with "My Value!" </script>
3.1.5 Extension方式实现CEF给JavaScript提供函数JavaScript调用CEF中的函数步骤: (1)实现app类,继承与CefApp,重写OnWebKitInitialized,在OnWebKitInitialized函数内部使用字符串定义函数。CEF调用CefRegisterExtension函数向JavaScript注册函数,并提供处理调用的handler。 //CefClientApp.h class CCefClientApp : public CefApp, public CefBrowserProcessHandler, CefRenderProcessHandler { public: CCefClientApp(); ~CCefClientApp();
//所有的CEF接口 都需要重载GetXXXHandler,并且return this,才会有效 virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }
//===========CefRenderProcessHandler virtual void OnWebKitInitialized() override;
private: CefRefPtr<CCEFV8HandlerEx> v8Handler_; // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(CCefClientApp);
private:
};
//CefClientApp.cpp
void CCefClientApp::OnWebKitInitialized() { //MessageBox(NULL,L"OnWebKitInitialized\n",0,0); std::string app_code = //----------------------------------- //声明JavaScript里要调用的Cpp方法 "var app;" "if (!app)" " app = {};" "(function() {"
// jsInvokeCPlusPlus 实例函数 " app.jsInvokeCPlusPlus = function(v1, v2) {" " native function jsInvokeCPlusPlus();" " return jsInvokeCPlusPlus(v1, v2);" " };"
//函数 " app.jsTransform = function(v1) {" " native function jsTransform();" " return jsTransform(v1);" " };"
"})();";
// Register app extension module
// JavaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找 // 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法 // 假设v8Handler_是CCefClientApp的一个成员变量 //v8Handler_ = new CCEFV8HandlerEx();
CefRegisterExtension("v8/app", app_code, v8Handler_);
} (2)JavaScript调用函数 <html> <script> app.jsInvokeCPlusPlus("123","xyz"); app.jsTransform("hello world"); </script> </html> (3) handler的Execute函数接收调用响应,根据函数名称判断是调用哪个函数,获取参数调用函数。 //CEFV8HandlerEx.h
class public:
public:
private:
public:
};
//CEFV8HandlerEx.cpp
//JS调用C++函数的回调
bool {
} 自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: |
|
来自: 猎狐肥 > 《Chrome_Cef》