cef结构简介
CMakeLists.txt
Debug
- cef的debug构建,以及平台需要的其他库
include
- cef头文件
libcef_dll
- libcef_dll静态库的源代码,
- 用到cef的C++API的,都必须链接这个库
Release
- cef的release构建,以及平台需要的其他库
Resources
- 构建CEF需要的资源(Windows和Linux)
tests/cefclient
tests/cefsimple
tests/ceftests
C++ Wrapper
- libcef动态库导出的是C的API,将用户和CEF运行代码库隔离开来
- libcef_dll_wrapper,它将libcef导出的CAPI封装在C++API中,然后客户端应用程序链接这个libcef_dll_wrapper库
架构
概述
- cef3使用多个进程
- 处理窗口创建,UI和网络访问的主进程称为“浏览器”进程
- Blink渲染和JavaScript执行在单独的“渲染”进程
- 其他进程根据需要生成
- cef生成的单独进程使用进程间(IPC)进行通信
- cef3中的每个进程都运行着多个线程,如下:
TID_UI
- TID_UI,浏览器进程中的主线程(如果CefSetting.multi_threded_message_loop的值为false),调用了CefInitialize(),则该线程将与主应用程序线程
TID_IO
- 在浏览器进程中用于处理IPC和网络消息
TID_FILE
- 在浏览器进程中用于与文件系统交互(阻塞操作只能在此线程或客户端应用程序创建的CefThread上执行)
TID_FILE_BACKGROUND
- 用于阻止用户不会执行的任务
TID_FILE_USER_VISIBLE
TID_FILE_USER_BLOCKING
TID_PROCESS_LAUNCHER
- 用于启动和终止浏览器进程
TID_RENDERER
- 是渲染进程中的主线程(所有Blink和V8交互都必须在这个线程上进行)
其他
判断当前线程
1 2 3 4 5 6 7 8 9 |
#define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI)); #define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO)); #define CEF_REQUIRE_FILE_BACKGROUND_THREAD() \ DCHECK(CefCurrentlyOn(TID_FILE_BACKGROUND)); #define CEF_REQUIRE_FILE_USER_VISIBLE_THREAD() \ DCHECK(CefCurrentlyOn(TID_FILE_USER_VISIBLE)); #define CEF_REQUIRE_FILE_USER_BLOCKING_THREAD() \ DCHECK(CefCurrentlyOn(TID_FILE_USER_BLOCKING)); #define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER)); |
同步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Include the necessary header. #include "include/base/cef_lock.h" // Class declaration. class MyClass : public CefBaseRefCounted { public: MyClass() : value_(0) {} // Method that may be called on multiple threads. void IncrementValue(); private: // Value that may be accessed on multiple theads. int value_; // Lock used to protect access to |value_|. base::Lock lock_; IMPLEMENT_REFCOUNTING(MyClass); }; // Class implementation. void MyClass::IncrementValue() { // Acquire the lock for the scope of this method. base::AutoLock lock_scope(lock_); // |value_| can now be modified safely. value_++; } |
引用计数
1 2 3 4 5 6 7 8 9 10 11 12 |
class MyClass : public CefBaseRefCounted { public: // Various class methods here... private: // Various class members here... IMPLEMENT_REFCOUNTING(MyClass); // Provides atomic refcounting implementation. }; // References a MyClass instance CefRefPtr<MyClass> my_class = new MyClass(); |
字符串操作
std::string
之间
1 2 3 4 5 6 7 8 9 10 |
std::string str = “Some UTF8 string”; // Equivalent ways of assigning |str| to |cef_str|. Conversion from UTF8 will occur if necessary. CefString cef_str(str); cef_str = str; cef_str.FromString(str); // Equivalent ways of assigning |cef_str| to |str|. Conversion to UTF8 will occur if necessary. str = cef_str; str = cef_str.ToString(); |
std::wstring
之间
1 2 3 4 5 6 7 8 9 10 |
std::wstring str = “Some wide string”; // Equivalent ways of assigning |str| to |cef_str|. Conversion from wide will occur if necessary. CefString cef_str(str); cef_str = str; cef_str.FromWString(str); // Equivalent ways of assigning |cef_str| to |str|. Conversion to wide will occur if necessary. str = cef_str; str = cef_str.ToWString(); |
- ASCII
1 2 3 |
const char* cstr = “Some ASCII string”; CefString cef_str; cef_str.FromASCII(cstr); |
- 某些cef结构体
1 2 3 4 5 6 |
CefSettings settings; const char* path = “/path/to/log.txt”; // Equivalent assignments. CefString(&settings.log_file).FromASCII(path); cef_string_from_ascii(path, strlen(path), &settings.log_file); |
命令行参数
- cef和chromium中的许多功能可以使用命令行参数进行配置
- 要禁用命令行参数的处理,要在
CefSetting
传给CefInitialize
之前将CefSetting
的command_line_args_disabled
设置为true
- 要在主应用程序内指定参数,要实现
CefApp::OnBeforeCommandLineProcessing
- 要在应用程序特定的(非cef和chromium)命令行参数传递给子进程,要实现
CefBrowserProcessHandler::OnBeforeChildProcessLaunch
应用结构
windows
1 2 3 4 5 6 7 8 9 |
Application/ cefclient.exe <= cefclient application executable libcef.dll <= main CEF library icudtl.dat <= unicode support data libEGL.dll, libGLESv2.dll, ... <= accelerated compositing support libraries chrome_100_percent.pak, chrome_200_percent.pak, resources.pak <= non-localized resources and strings snapshot_blob.bin, v8_context_snapshot.bin <= V8 initial snapshot locales/ en-US.pak, ... <= locale-specific resources and strings |
linux
1 2 3 4 5 6 7 8 9 10 11 |
Application/ cefclient <= cefclient application executable chrome-sandbox <= sandbox support binary libcef.so <= main CEF library icudtl.dat <= unicode support data chrome_100_percent.pak, chrome_200_percent.pak, resources.pak <= non-localized resources and strings snapshot_blob.bin, v8_context_snapshot.bin <= V8 initial snapshot locales/ en-US.pak, ... <= locale-specific resources and strings files/ binding.html, ... <= cefclient application resources |
macOS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
cefclient.app/ Contents/ Frameworks/ Chromium Embedded Framework.framework/ Chromium Embedded Framework <= main application library Resources/ chrome_100_percent.pak, chrome_200_percent.pak, resources.pak, ... <= non-localized resources and strings icudtl.dat <= unicode support data snapshot_blob.bin, v8_context_snapshot.bin <= V8 initial snapshot en.lproj/, ... <= locale-specific resources and strings cefclient Helper.app/ Contents/ Info.plist MacOS/ cefclient Helper <= helper executable Pkginfo Info.plist MacOS/ cefclient <= cefclient application executable Pkginfo Resources/ binding.html, ... <= cefclient application resources |
macOS Chromium Embedded Framework.framework
- 是一个无版本框架,包含所有 CEF 二进制文件和资源
macOS cefclient Helper
- 应用程序用于执行具有不同特征的单独进程(渲染器、插件等)
- 它需要有一个单独的应用程序包和 Info.plist 文件
- 他不会在dock里面显示
应用流程
- 提供一个入口点函数,用于初始化 CEF 并运行子进程可执行逻辑或 CEF 消息循环
- 提供CefApp的实现来处理特定于流程的回调
- 提供CefClient的实现来处理特定于浏览器实例的回调
- 调用 CefBrowserHost::CreateBrowser() 创建浏览器实例并使用CefLifeSpanHandler管理浏览器生命周期
入口函数
- CEF3 应用程序将运行多个进程。这些进程可以全部使用相同的可执行文件,也可以为子进程指定单独的可执行文件。该过程的执行从入口点函数开始
- 当启动子进程时,CEF 将使用命令行指定配置信息,该信息必须通过 CefMainArgs 结构传递到 CefExecuteProcess 函数中。CefMainArgs 的定义是特定于平台的。
- Linux和macOS
1 |
CefMainArgs main_args(argc, argv); |
- Windows
1 |
CefMainArgs main_args(hInstance); |
单一可执行文件
- 当作为单个可执行文件运行时,需要入口点函数来区分不同的进程类型。Windows 和 Linux 支持单一可执行结构,但 MacOS 不支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// Program entry-point function. int main(int argc, char* argv[]) { // Structure for passing command-line arguments. // The definition of this structure is platform-specific. CefMainArgs main_args(argc, argv); // Implementation of the CefApp interface. CefRefPtr<MyApp> app(new MyApp); // Execute the sub-process logic, if any. This will either return immediately for the browser // process or block until the sub-process should exit. int exit_code = CefExecuteProcess(main_args, app.get()); if (exit_code >= 0) { // The sub-process terminated, exit now. return exit_code; } // Populate this structure to customize CEF behavior. CefSettings settings; // Initialize CEF in the main process. CefInitialize(main_args, settings, app.get()); // Run the CEF message loop. This will block until CefQuitMessageLoop() is called. CefRunMessageLoop(); // Shut down CEF. CefShutdown(); return 0; } |
- 单独的子进程可执行文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// Program entry-point function. int main(int argc, char* argv[]) { // Load the CEF framework library at runtime instead of linking directly // as required by the macOS sandbox implementation. CefScopedLibraryLoader library_loader; if (!library_loader.LoadInMain()) return 1; // Structure for passing command-line arguments. // The definition of this structure is platform-specific. CefMainArgs main_args(argc, argv); // Implementation of the CefApp interface. CefRefPtr<MyApp> app(new MyApp); // Populate this structure to customize CEF behavior. CefSettings settings; // Specify the path for the sub-process executable. CefString(&settings.browser_subprocess_path).FromASCII(“/path/to/subprocess”); // Initialize CEF in the main process. CefInitialize(main_args, settings, app.get()); // Run the CEF message loop. This will block until CefQuitMessageLoop() is called. CefRunMessageLoop(); // Shut down CEF. CefShutdown(); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Program entry-point function. int main(int argc, char* argv[]) { // Initialize the macOS sandbox for this helper process. CefScopedSandboxContext sandbox_context; if (!sandbox_context.Initialize(argc, argv)) return 1; // Load the CEF framework library at runtime instead of linking directly // as required by the macOS sandbox implementation. CefScopedLibraryLoader library_loader; if (!library_loader.LoadInHelper()) return 1; // Structure for passing command-line arguments. // The definition of this structure is platform-specific. CefMainArgs main_args(argc, argv); // Implementation of the CefApp interface. CefRefPtr<MyApp> app(new MyApp); // Execute the sub-process logic. This will block until the sub-process should exit. return CefExecuteProcess(main_args, app.get()); } |
消息循环集成
- CEF 还可以与现有应用程序消息循环集成,而不是运行自己的消息循环
方法一
- 定期调用
CefDoMessageLoopWork()
而不是调用CefRunMessageLoop()
- 每次调用
CefDoMessageLoopWork()
都会执行 CEF 消息循环的单次迭代。使用这种方法时应小心 - 调用该方法的频率太低会使 CEF 消息循环陷入饥饿并对浏览器性能产生负面影响。过于频繁地调用该方法会对 CPU 使用率产生负面影响。有关高级使用详细信息,请参阅CefBrowserProcessHandler::OnScheduleMessagePumpWork
方法二
- 设置
CefSettings.multi_threaded_message_loop = true
(仅限 Windows 和 Linux) - 这将导致 CEF 在与主应用程序线程不同的线程上运行浏览器 UI 线程
- 使用这种方法,不需要调用 CefDoMessageLoopWork() 和 CefRunMessageLoop()
- CefInitialize() 和 CefShutdown() 仍应在主应用程序线程上调用
- 需要提供自己的机制来与主应用程序线程进行通信(参阅 cefclient_win.cpp 中的消息窗口用法)
Cef设置
- browser_subprocess_path
- 将为子进程启动的单独可执行文件的路径
- multi_threaded_message_loop
- 设置为 true 以使浏览器进程消息循环在单独的线程中运行
- command_line_args_disabled
- 设置为 true 以禁用使用标准 CEF 和 Chromium 命令行参数配置浏览器进程功能
- cache_path
- 缓存数据在磁盘上的存储位置。如果为空,内存缓存将用于某些功能,临时磁盘缓存将用于其他功能。如果指定了缓存路径,HTML5 数据库(例如 localStorage)将仅在会话之间保留
- locale
- 将传递给 Blink 的区域设置字符串。如果为空,将使用默认区域设置“en-US”。在 Linux 上,该值被忽略,其中区域设置是使用环境变量解析确定的,优先顺序为:LANGUAGE、LC_ALL、LC_MESSAGES 和 LANG。也可以使用“lang”命令行开关进行配置
- log_file
- 用于调试日志的目录和文件名。如果为空,则将使用默认名称“debug.log”,并将该文件写入应用程序目录。也可以使用“log-file”命令行开关进行配置
- log_severity
- 日志严重性。仅记录此严重级别或更高级别的消息。还可以使用“log-severity”命令行开关进行配置,其值为“verbose”、“info”、“warning”、“error”、“error-report”或“disable”。
- resources_dir_path
- 资源目录的完全限定路径。如果此值为空,则 cef.pak 和/或 devtools_resources.pak 文件必须位于 Windows/Linux 上的模块目录或 MacOS 上的应用程序包资源目录中。还可以使用“resources-dir-path”命令行开关进行配置。
- locales_dir_path
- 区域设置目录的完全限定路径。如果该值为空,则语言环境目录必须位于模块目录中。在 MacOS 上,此值将被忽略,其中包文件始终从应用程序包资源目录加载。也可以使用“locales-dir-path”命令行开关进行配置。
- remote_debugging_port
- 设置为 1024 到 65535 之间的值以在指定端口上启用远程调试。例如,如果指定 8080,则远程调试 URL 将为 http://localhost:8080。可以从任何 CEF 或 Chrome 浏览器窗口远程调试 CEF。还可以使用“远程调试端口”命令行开关进行配置。
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Linux fork&&守护进程03/30
- ♥ Windows核心编程_必备知识04/27
- ♥ Windows 核心编程 _ 内核对象一06/04
- ♥ Windows 核心编程 _ 内核对象:线程同步二07/30
- ♥ Linux下调试dump记录08/11
- ♥ Linux 进程描述&&相关介绍03/28