Browser与Render进程
从cefsimple開始吧,cefsimple_win.cc中的wWinMain函数中调用了CefExecuteProcess()方法来检測是否要启动其他的子进程。此处的CefExecuteProcess是在libcef_dll_wrapper.cc中的,它内部又调用了cef_execute_process方法(libcef_dll.cc),cef_execute_process又调用了libcef/browser/context.cc文件内实现的CefExecuteProcess方法。这种方法代码例如以下:
int CefExecuteProcess(const CefMainArgs& args,CefRefPtr<CefApp> application,void* windows_sandbox_info) {base::CommandLine command_line(base::CommandLine::NO_PROGRAM);#if defined(OS_WIN)command_line.ParseFromString(::GetCommandLineW());#elsecommand_line.InitFromArgv(args.argc, args.argv);#endif// Wait for the debugger as early in process initialization as possible.if (command_line.HasSwitch(switches::kWaitForDebugger))base::debug::WaitForDebugger(60, true);// If no process type is specified then it represents the browser process and// we do nothing.std::string process_type =command_line.GetSwitchValueASCII(switches::kProcessType);if (process_type.empty())return -1;CefMainDelegate main_delegate(application);// Execute the secondary process.#if defined(OS_WIN)sandbox::SandboxInterfaceInfo sandbox_info = {0};if (windows_sandbox_info == NULL) {content::InitializeSandboxInfo(&sandbox_info);windows_sandbox_info = &sandbox_info;}content::ContentMainParams params(&main_delegate);params.instance = args.instance;params.sandbox_info =static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);return content::ContentMain(params);#elsecontent::ContentMainParams params(&main_delegate);params.argc = args.argc;params.argv = const_cast<const char**>(args.argv);return content::ContentMain(params);#endif
它分析了命令行參数,提取”type”參数。假设为空。说明是Browser进程,返回-1。这样一路回溯到wWinMain方法里,然后開始创建Browser进程相关的内容。
假设”type”參数不为空,做一些推断,最后调用了content::ContentMain方法,直到这种方法结束。子进程随之结束。
content::ContentMain方法再追溯下去,就到了chromium的代码里了。在chromium/src/content/app/content_main.cc文件里。
详细我们不分析了,感兴趣的能够去看看。
分析了CefExecuteProcess方法我们知道,Browser进程在cefsimple_win.cc内调用了CefExecuteProcess之后做了进一步的配置,这个是在simple_app.cc内完毕的,详细就是SimpleApp::OnContextInitialized()这种方法。代码例如以下:
void SimpleApp::OnContextInitialized() {CEF_REQUIRE_UI_THREAD();CefWindowInfo window_info;window_info.SetAsPopup(NULL, "cefsimple");// SimpleHandler implements browser-level callbacks.CefRefPtr<SimpleHandler> handler(new SimpleHandler());// Specify CEF browser settings here.CefBrowserSettings browser_settings;std::string url;CefRefPtr<CefCommandLine> command_line =CefCommandLine::GetGlobalCommandLine();url = command_line->GetSwitchValue("url");if (url.empty())url = "http://www.google.com";CefBrowserHost::CreateBrowser(window_info, handler.get(), url,browser_settings, NULL);}
能够看到。这里创建SimpleHandler,并传递给CefBrowserHost::CreateBrowser去使用。
如今我们清楚了,Browser进程,须要CefApp(SimpleApp实现了这个接口)和CefClient(SimpleHandler实现了这个接口)。而Renderer进程仅仅要CefApp。
另外,CEF还定义了CefBrowserProcessHandler和CefRenderProcessHandler两个接口,分别来处理Browser进程和Render进程的个性化的通知。
因此,Browser进程的App一般还须要实现CefBrowserProcessHandler接口,Renderer进程的App一般还须要实现CefRenderProcessHandler接口。这里https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage有详细说明。
像cefsimple这个演示样例中的SimpeApp,没有实现CefRenderProcessHandler接口,没有针对Renderer进程做特别处理,所以当它作为Render进程时。会缺失一部分功能。
比方JS与Native代码交互,这正是我们想要的。
假设要实现JS与Native代码交互,最好分开实现Browser进程须要的CefApp和Render进程须要的CefApp。
像以下这样:
class ClientAppRenderer : public CefApp,public CefRenderProcessHandler{...}class ClientAppBrowser : public CefApp,public CefBrowserProcessHandler{...}
当我们实现了CefRenderProcessHandler接口,就能够在其OnContextCreated()方法中获取到CefFrame相应的window对象。在它上面绑定一些JS函数或对象。然后JS代码里就能够通过window对象訪问。假设是函数。就会调用到我们实现的CefV8Handler接口的Execute方法。
第二种实现JS与Native交互的方式,是在实现CefRenderProcessHandler的OnWebKitInitialized()方法时导出JS扩展,详细參考https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md,有详细说明。
cef_js_integration项目
cef_js_integration是非常easy的演示样例。用来演示JS与Native的交互。它在一个项目内实现了ClientAppBrowser、ClientAppRenderer、ClientAppOther三种CefApp。分别相应Browser、Render及其他类别的三种进程。
JS和Native代码的交互发生在Render进程。App须要继承CefRenderProcessHandler来整合JS相关功能。因此在应用在启动时做了进程类型推断。依据不同的进程类型创建不同的CefApp。
这个演示样例演示了三种JS交互方式(參见https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md):
- 在native代码中通过CefFrame::ExecuteJavaScript()来运行JavaScript代码
- 将函数或对象绑定到CefFrame相应的window对象上。JS代码通过window对象訪问native代码导出的函数或对象
- 使用CefRegisterExtension()注冊JS扩展,JS直接訪问注冊到JS Context中的对象
这个项目參考了cefsimple、cefclient,还有https://github.com/acristoffers/CEF3SimpleSample,终于它比cefsimple复杂一点,比cefclient简单非常多。
本文深入解析了CEF(Chromium Embedded Framework)的进程机制,包括Browser与Render进程的启动流程,以及如何在不同进程中配置CefApp。特别关注了JS与Native代码的交互方法,介绍了通过CefRenderProcessHandler接口实现的多种交互方式。
1431

被折叠的 条评论
为什么被折叠?



