您的位置:首页 > 其它

CEF3和本地程序交互机制

2014-12-02 20:34 309 查看
CEF中一个页面的框架如下图所示:
 


 

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

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

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

 

 

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

一.C++ call JS:

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

 

示例:

CefRefPtr<CefBrowser> browser = ...;
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
frame->ExecuteJavaScript("alert('ExecuteJavaScript works!');",
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++对象,并将其绑定到特定frame的JS执行环境的window对象上,如此JS代码就可以直接对其读写(属性)或者调用(函数)。

 

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

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

1.1获取CefV8Value形式的window对象

1.2构造数据

1.3绑定到window对象上

 

代码示例:

void MyRenderProcessHandler::OnContextCreated(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
CefRefPtr<CefV8Value> object = context->GetGlobal();// 获取到window
CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");
object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE);
}
2.特别注意:在frame reload的时候,需要重新绑定。frame reload其实就是重新创建了context,需要重新执行绑定过程,这很好理解。

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

 

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

 

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

示例:

void MyRenderProcessHandler::OnWebKitInitialized() {
std::string extensionCode =
"var test;"
"if (!test)"
"  test = {};"
"(function() {"
"  test.myval = 'My Value!';"
"})();";

CefRegisterExtension("v8/test", extensionCode, NULL);
}

 

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

class MyV8Accessor : public CefV8Accessor {
public:
MyV8Accessor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
if (name == "myval") {
// Return the value.
retval = CefV8Value::CreateString(myval_);
return true;
}
return false;
}

virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
if (name == "myval") {
if (value.IsString()) {
myval_ = value.GetStringValue();
} else {
exception = "Invalid value type";
}
return true;
}
return false;
}

CefString myval_;
IMPLEMENT_REFCOUNTING(MyV8Accessor);
};


 

2.函数实现

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

CefRefPtr<CefV8Handler> handler = …;

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

 

//实现自己的CefV8Handler

class MyV8Handler : public CefV8Handler {
public:
MyV8Handler() {}

virtual bool Execute(const CefString& name,
CefRefP
8d1c
tr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
if (name == "myfunc") {
retval = CefV8Value::CreateString("My Value!");
return true;
}
return false;
}

IMPLEMENT_REFCOUNTING(MyV8Handler);
};


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐