CEF3和本地程序交互机制

13 篇文章 0 订阅
CEF 中一个页面的框架如下图所示:

 

 

CefBrowser:一个普通的浏览器页面(HTML

CefFrame:每一个页面都由至少一个frame组成,最顶层的为mainframe

contextJS执行环境,每个frame都有自己独立的contextCEF中使用V8JavaScriptEngine解析和执行JS代码

 

 

后端和前端的通信分为两个部分:

一.C++ call JS

由框架图可以知道,后端执行JS的实质是:在特定的frame上执行JS代码片段

 

示例:

[cpp]  view plain  copy
  1. CefRefPtr<CefBrowser> browser = ...;  
  2. CefRefPtr<CefFrame> frame = browser->GetMainFrame();  
  3. frame->ExecuteJavaScript("alert('ExecuteJavaScript works!');",  
  4.     frame->GetURL(), 0);  

可以得知,C++执行JS的通用流程为:

1.获取页面引用

2.获取目标frame引用

3.在目标frame上调用ExecuteJavaScript执行JS

 

槽点:函数ExecuteJavaScript的返回值为空,函数中也没有其他形式获取JS执行的返回值。那么JS的返回值如何获取?

 

二.JS call C++

C++JS对象的映射关系:

 

CefValue表示JS环境中的一个对象,其可以表示JS中所有变量,切其自身可以嵌套。特别重要的一点,前端的window对象在后端也是一个CefV8Value,并且可以通过CefV8Context取到它。

 

JS调用C++的实质是:以CefV8Value的形式包装C++对象,并将其绑定到特定frameJS执行环境的window对象上,如此JS代码就可以直接对其读写(属性)或者调用(函数)。

 

A. window binding,将自定义数据绑定到JS context的window对象上

1.在回调CefRenderProcessHandler的OnContextCreated()中注册。注册过程:

1.1获取CefV8Value形式的window对象

1.2构造数据

1.3绑定到window对象上

 

代码示例:

[cpp]  view plain  copy
  1. void MyRenderProcessHandler::OnContextCreated(  
  2.     CefRefPtr<CefBrowser> browser,  
  3.     CefRefPtr<CefFrame> frame,  
  4.     CefRefPtr<CefV8Context> context) {  
  5.   CefRefPtr<CefV8Value> object = context->GetGlobal();// 获取到window  
  6.   CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");  
  7.   object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE);  
  8. }  

2.特别注意:在frame reload的时候,需要重新绑定。frame reload其实就是重新创建了context,需要重新执行绑定过程,这很好理解。

3.CefV8Value的setValue方法就是将数据绑定到对象上

 

B.extensions,将预定义的JS代码注册到context中,并且一旦注册,不可修改。这种方式威力很弱,我想只会在特殊的场景下选它。

 

在CefRenderProcessHandler的回调OnWebKitInitialized()中执行注册

示例:

[cpp]  view plain  copy
  1. void MyRenderProcessHandler::OnWebKitInitialized() {  
  2.     std::string extensionCode =   
  3.     "var test;"  
  4.     "if (!test)"  
  5.     "  test = {};"  
  6.     "(function() {"  
  7.     "  test.myval = 'My Value!';"  
  8.     "})();";  
  9.   
  10.   
  11.   CefRegisterExtension("v8/test", extensionCode, NULL);  
  12. }  

 

C.数据构造

1. JS基本类型,CEF支持创建基本JS数据类型,比如undefined, null, bool, int, double, date and string。使用静态函数CefV8Value::Create*()

2.JS数组,CefV8Value::CreateArray()

3.JS对象,CefV8Value::CreateObject(NULL)

4.JS function, CefV8Value::CreateFunction();

 

D.属性读写和函数实现

1.对象读写

创建CefV8Value时,关联一个CefV8Accessor,并实现它的get和set,示例:

 

//创建时关联CefV8Accessor

CefRefPtr<CefV8Accessor> accessor = …;
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);

 

//实现自己的CefV8Accessor

[cpp]  view plain  copy
  1. class MyV8Accessor : public CefV8Accessor {  
  2. public:  
  3.   MyV8Accessor() {}  
  4.   virtual bool Get(const CefString& name,  
  5.                    const CefRefPtr<CefV8Value> object,  
  6.                    CefRefPtr<CefV8Value>& retval,  
  7.                    CefString& exception) OVERRIDE {  
  8.     if (name == "myval") {  
  9.       // Return the value.  
  10.       retval = CefV8Value::CreateString(myval_);  
  11.       return true;  
  12.     }  
  13.     return false;  
  14.   }  
  15.   
  16.   virtual bool Set(const CefString& name,  
  17.                    const CefRefPtr<CefV8Value> object,  
  18.                    const CefRefPtr<CefV8Value> value,  
  19.                    CefString& exception) OVERRIDE {  
  20.     if (name == "myval") {  
  21.       if (value.IsString()) {  
  22.         myval_ = value.GetStringValue();  
  23.       } else {  
  24.         exception = "Invalid value type";  
  25.       }  
  26.       return true;  
  27.     }  
  28.     return false;  
  29.   }  
  30.   
  31.   CefString myval_;  
  32.   IMPLEMENT_REFCOUNTING(MyV8Accessor);  
  33. };  


 

2.函数实现

创建函数时,绑定自己实现的CefV8Handler,示例:

CefRefPtr<CefV8Handler> handler = …;
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);

 

//实现自己的CefV8Handler

[cpp]  view plain  copy
  1. class MyV8Handler : public CefV8Handler {  
  2. public:  
  3.   MyV8Handler() {}  
  4.   
  5.   virtual bool Execute(const CefString& name,  
  6.                        CefRefPtr<CefV8Value> object,  
  7.                        const CefV8ValueList& arguments,  
  8.                        CefRefPtr<CefV8Value>& retval,  
  9.                        CefString& exception) OVERRIDE {  
  10.     if (name == "myfunc") {  
  11.       retval = CefV8Value::CreateString("My Value!");  
  12.       return true;  
  13.     }  
  14.     return false;  
  15.   }  
  16.   
  17.   IMPLEMENT_REFCOUNTING(MyV8Handler);  
  18. };  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值