cef架构

CEF架构的概述  
背景: 
CEF:chromium embedded Framework是由Marshall Greenblatt在08年成立的一个开源项目,目的是开发一个基于Google Chromium项目的Web browser控制器。CEF目前支持大多数编程语言和操作系统,并可以轻松的整合新的和已存在的应用。设计的目的也是为了效率/性能和方便使用。基础的框架包括了借助原生库的C/C++接口,这样将主机的应用与chromium和WebKit隔离开来。它提供了浏览器控制和主机应用程序(包括支持自定义插件、协议、JavaScript对象和JavaScript扩展)之间紧密的集成。主机应用程序可以有选择地控制资源加载、导航、菜单、打印等,当利用了相同的性能和Google Chrome浏览器具备的HTML5技术。  
依赖/相关: 
CEF项目依靠一堆其它由第三方维护的项目,主要又以下: 
Chromium:基础,网络堆栈,线程,消息机制,log,进程控制,生成Web browser。 WebKit:提供DOM解析,布局,事件处理,渲染,HTML5JS的API。 V8:JS引擎。 Skia:2D图形库。 
Angle:3D图形转换,和DirectX有关。  
版本: 3个版本: 
 CEF1,单进程工具调用chromium Webkit API  CEF2,多进程工具建立在Chromium browser  CEF3,多进程工具调用Chromium Content API  
通用API用法: 
所有版本的CEF都公开一个简单好用的API(让用户从Chromium和Webkit复杂的代码中分隔开来),详细如下: 
1. 调用CefInitialize()对CEF初始化。 
2. 调用CefRunMessageLoop() or CefDoMessageLoopWork()来在UI消息上处理事务。 
3. 调用CreateBrowser() or CreateBrowserSync()并传递一个CefClient事例来创造一个browser
窗口。 
4. 在程序退出前调用CefShutdown()来关闭CEF。  CEF1 
CEF1使用单进程架构,并直接将Chromium和Webkit整合到客户端应用程序中。单进程的优点包括了建设内存的使用和进一步与客户端应用的耦合。缺点有某些类型的加载内容性能低,和由于同进程中运行Flash插件的崩溃问题。  
CEF1 API用法: 
 CefApp,此接口用来传递到CefInitialize(),和允许应用程序定制全局,如资源加载,代
理。 
 CefClient,此接口用来传递到CefCreateBrowser() or CefCreateBrowserSync(),和充当单独
CEF Browser事例和客户端应用程序的连接,也负责请求和显示处理的接口 




 CefBrowser,公开由浏览器提供的功能。包括前进后退导航,来源检索,加载请求等,
一个CefBrowser可能有一到多个子类的CefFrame对象  
线程注意事项 
CEF1包括UI,IO和FILE线程。 UI线程创建Browser窗口,用来所有与WebKit和V8的交互,IO线程用来处理模式和网络请求。 FILE线程用于应用程序缓存和其他各种活动。  
当使用CEF1时,你应该记住以下线程考虑: 
 不要在UI线程上执行会造成阻塞的操作。这将导致严重的性能问题。 
 如果CefInitialize()通过值为false的CefSettings.multi_threaded_message_loop被调用,那
么UI线程将和主线程一样。 
 所有WebKit和V8互为作用必须在UI线程上进行。因此,有些CEF API函数只能在UI线程上
调用。有相同限制的功能会被相应地记录并关联到CEF的头文件里。  CefPostTask方法可以用来动态同步地进行不同线程里的任务。  
实施细则 
CEF1主要有以下实现类: 
 CefContext 代表全局CEF内容。单个CefContext对象是由CefInitialize()创建,由
CefShutdown()销毁 
 CefProcess 由CefContext创建和管理的CEF线程。 
 BrowserWebKitInit 管理全局WebKit环境作为Chromium WebKit API暴露。 
 WebViewHost 提供本地窗口“wrapper”工具给WebView。这个类扩展了,提供和在某
些平台上弹出部件(如选择菜单)一样的功能,WebWidgetHost。 
 CefBrowserImpl 实现CefBrowser的接口,创建WebViewHost,并提供了但个Browser实例
的粘合代码。 
 BrowserWebViewDelegate 实现WebKit接口,提供CefBrowserImpl和底层的WebView之间
的通信。   
CEF2已经被取消了  CEF3 
CEF3借助Chromium Content API使用和Chromium Web 浏览器一样的多进程架构,相比于单进程的CEF1,他具有更多的优势。  同时支持单进程和多进程模式。 
 更多的代码分析通过Chromium浏览器 
 改进的性能和由于代码路径的支持而减少的损坏  新特性的快速获取 
大多数情况下,CEF3和Chromium浏览器拥有相同的性能和稳定特征。  
API用法 
CEF3的初始化需要考虑多进程。在Windows和Linux上的所有进程享有相同的可执行文件,或选择使用单独的可执行文件的子进程(借助CefSettings.browser_subprocess_path的值)。在Mac OS-X的所有的子进程都必须绑推一个分开的app使用。这是必要的因为在Mac OS-X的子
 


进程必须有一个不同的Info.plist文件。  
CefExecuteProcess()函数是负责执行子过程的逻辑。它检查“类型”的命令行标志来决定目前正在执行的进程类型。如果被browser进程调用(识别为没有“类型”的命令行值)它会立即返回一个为-1值。如果被调用且认为是次级进程,它会阻塞直到该进程应该退出,然后返回进程的退出代码。如果执行browser进程,应用程序会继续在标准进程初始化,被描述为“通用API的用法”部分。将cef_app.h理解为一个完成的的功能初始化和用法的描述。将Wcefclient_win.cpp wWinMain功能视作一个窗口例程。  
“单进程”命令行标志或者CefSettings.single_process的值可用在一个单一的进程中运行CEF3。这是有用于调试目的,但不建议用于生产。  
下面是主要CEF3接口和它们的用途的概述: 
 CefApp,此接口用来传递到CefInitialize(),和允许应用程序定制全局,如资源加载,代
理。一些功能是由所有进程共享的,有些必须实现浏览器的过程中,必须在渲染过程中执行。见详情头文件的意见。 
 CefClient,此接口用来传递到CefCreateBrowser() or CefCreateBrowserSync(),和充当单独
CEF Browser事例和客户端应用程序的连接,也负责请求和显示处理的接口。请求处理,显示处理等额外的接口,通过这个接口暴露。 
 CefBrowser,公开由浏览器提供的功能。包括前进后退导航,来源检索,加载请求等,
一个CefBrowser可能有一到多个子类的CefFrame对象。在一个特定的过程或一个特定的线程必须调用一些方法,所以仔细阅读文档。 
 CefBrowserHost - 公开有关运行browser进程中唯一可用的browser窗口的功能。例如,
检索本地父窗口句柄,或销毁browser窗口。 
 CefRenderProcessHandler - 公开WebKit和V8对渲染进程中应用程序的集成能力。通过
CefApp返回此对象的一个实例。    
实施细则CEF3主要有以下实现类: 
 CefMainDelegate 实现通用进程的引导逻辑。 
 CefContentClient 实现所有进程中共同的Content API回调。 
 CefContext 代表全局CEF内容在browser进程中。单个CefContext对象由CefInitialize()创
建并由CefShutdown()销毁。 
 CefBrowserMainParts 实现browser进程中的引导逻辑。 
 CefContentBrowserClient 实现browser进程的ContentAPI回调。 
 CefBrowserHostImpl 实现在browser进程中CefBrowser和CefBrowserHost的接口。提供粘
合代码和工具的借口来和RenderViewHost通信。 
 CefContentRendererClient 实现渲染进程中的ContentAPI回调。 
 CefBrowserImpl 实现渲染进程中的CefBrowser接口。提供粘合代码和工具的借口来和

RenderView通信。 


cef 是一个基于google chromiun的简单的框架。 它主要是作为一个内嵌浏览器嵌入到客户端应用程序中。

可以再 http://cefbuilds.com 下载最新的编译版本。

总体框架预览

  1. CEF 使用了多进程。主进程是“browser”进程。 而子进程是由rederes, plugins, GPU, 等组件创建。
  2. 在ECF的所有进程中,都可以有多线程。CEF提供了函数和接口在不同的线程中来传递任务。
  3. 一些回调方法和函数只能在特定线程和进程中使用。在使用API之前请确保仔细阅读注释。

源代码

cefsimple 工程初始化CEF并创建了一个简单的浏览器窗口。

  1. 系统在入口点函数中(man或者wWinMain)函数中开启browser进程
  2. 入口点函数:

    1. 创建SimpleApp的实例,在这个类中保存process-level callbacks.
    2. 初始化CEF并开启消息循环。
  3. 当CEF初始化完毕以后, SimpleApp::OnContextInitialized()会被调用。在这个方法中:

    1. 创建一个单例的SimpleHandler
    2. 由CefBrowserHost::CreateBrowserSync()创建一个浏览器窗口
  4. 所有的浏览器共享同一个在SimpleHandler。SimpleHandler负责定制浏览器的行为并保存browser-related callbacks(loading状态,标题行为等)
  5. 当浏览器窗口被关闭的时候, SimpleHandler::OnBeforeClose() 被调用。当所有浏览器窗口被关闭,CEF消息循环退出。

可以看下如下代码:

int APIENTRY wWinMain(HINSTANCE hInstance
				  , HINSTANCE hPrevInstance
				  , LPTSTR lpCmdLine
				  , int nCmdShow)
{
	CefMainArgs args(hInstance);

	CefRefPtr<MySimpleApp> app(new MySimpleApp);

	int exitCode = CefExecuteProcess(args, app, NULL);
	if(exitCode >= 0) return exitCode;
	CefSettings settings;
	CefInitialize(args, settings, app, NULL);

	CefRunMessageLoop();
	CefShutdown();
	return 0;
}

此时进程开启,但是没有任何窗口, 如果我们需要建立窗口需要如下

CefWindowInfo winInfo;
winInfo.SetAsPopup(NULL, "myCefSimple");

CefBrowserSettings browser_settings;

CefRefPtr<CefClient> client(new MySimpleClient());
std::string url = "file:///D:/project/github/cptf/resource/binding.html";

CefBrowserHost::CreateBrowser(winInfo
	, client.get()
	, url
	, browser_settings
	, NULL);

这样就显示出来窗口了。
但是我们发现在关闭的时候进程没有关掉, 所以我们要做如下动作。

class MySimpleClient : public CefClient
				, public CefLifeSpanHandler


void MySimpleClient::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
	CEF_REQUIRE_UI_THREAD();

	CefQuitMessageLoop();
}

总结

App和Client是CEF中最重要的两个类。CefExecuteProcess 和 CefInitialize 是建立app的两个最重要方法。
而CreateBrowser 是创建浏览器窗口的最重要方法。




Cef支持各种语言和多种操作系统。在设计的时候充分考虑了性能和易用性。cef核心功能提供了c和c++的接口。cef提供了和主程序之间的通信能力(利用 custom plugins, protocols,javascrpit object 和 javascript extensions)。主应用程序可以选择性的使用控制 资源的加载,切换, context menus, printing等。

依赖

  1. chromium
  2. webkit
  3. v8
  4. skia
  5. angle

线程注意事项

CEF线程有如下几种

typedef enum {
	TID_UI,
	TID_DB,
	TID_FILE,

TID_FILE_USER_BLOCKING,
TID_PROCESS_LAUNCHER,
TID_CACHE,
TID_IO,
TID_RENDERER,
} cef_thread_id_t;

在使用线程的时候需要注意如下几点:

  1. 千万不要阻塞UI线程
  2. UI线程会任务是主线程,当 CefSettings.multi_threaded_message_loop = false的时候。
  3. 所有的webkit和V8的交互必须用 TID_RENDERER线程
  4. CefPostTask 方法可以再不同线程中进行异步调用

接口

  1. CefApp,此接口用来传递到CefInitialize(),和允许应用程序定制全局,如资源加载,代理。这些功能是由所有进程共享的,有些必须实现浏览器的过程中,必须在渲染过程中执行。见详情头文件的注释。
  2. CefClient,此接口用来传递到CefCreateBrowser() or CefCreateBrowserSync(),和充当单独CEF Browser事例和客户端应用程序的连接,也负责请求和显示处理的接口。请求处理,显示处理等额外的接口,通过这个接口暴露。
  3. CefBrowser,公开由浏览器提供的功能。包括前进后退导航,来源检索,加载请求等,一个CefBrowser可能有一到多个子类的CefFrame对象。在一个特定的过程或一个特定的线程必须调用一些方法,所以仔细阅读文档。
  4. CefBrowserHost - 公开有关运行browser进程中唯一可用的browser窗口的功能。例如,检索本地父窗口句柄,或销毁browser窗口。
    CefRenderProcessHandler - 公开WebKit和V8对渲染进程中应用程序的集成能力。通过CefApp返回此对象的一个​​实例。

进程注意事项

CEF3使用了很多不同的进程:

  1. Broser process- 这个进程可以认为是应该程序的主进程,当调用CefInitialize()的时候建立
  2. Render process- web容器(webkit和v8)在此进程中执行
  3. plugin process- 插件(如 Flash)
  4. GPU process-GPU渲染进程
  5. Utility process- 各种其他任务在这个进程中跑。

所有关于chrome 进程的资料可以在这里这里找到。

CefBrowser 和 CefFrame 在browser和render进程中都存在,并且传递一系列callbacks。 CefProcessMessage能够在browser进中利用CefBrowser::SendProcessMessage 函数发出, 并且在CefClient::OnProcessMessageRecieved 和CefRenderProcessHandler::OnProcessMessageRecieved 接收。

重要的细节

CEF3 有如下几个比较重要的类:

  • CefMainDelegate - 用于普通进程的逻辑过程
  • CefContentClient- 在普通进程 展现Content Api的回调。
  • CefContext-在browser进程中,展现全局的CEF上下文。 一个单独的CefContext对象时由CefInitialize()建立,有CefShutdown销毁。
  • CefBrowserMainParts- browser 进程的逻辑
  • CefContentBrowserClient-在browser 进程展现Content Api的回调。
  • CefBrowserHostImpl-是CefBrowserHost 的实现
  • CefContentRendererClient- 在render 进程中展现Content Api的回调
  • CefBrowserImpl- CefBrowser的实现者
分类:  C++


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值