cefsimple_win.cc
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include <windows.h>
#include "include/cef_sandbox_win.h"
#include "tests/cefsimple/simple_app.h"
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
// to the CMake command-line to disable use of the sandbox.
// Uncomment this line to manually enable sandbox support.
// #define CEF_USE_SANDBOX 1
#if defined(CEF_USE_SANDBOX)
// The cef_sandbox.lib static library may not link successfully with all VS
// versions.
#pragma comment(lib, "cef_sandbox.lib")
#endif
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Enable High-DPI support on Windows 7 or newer.
CefEnableHighDPISupport();
void* sandbox_info = nullptr;
#if defined(CEF_USE_SANDBOX)
// Manage the life span of the sandbox information object. This is necessary
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
CefScopedSandboxInfo scoped_sandbox;
sandbox_info = scoped_sandbox.sandbox_info();
#endif
// Provide CEF with command-line arguments.
CefMainArgs main_args(hInstance);
// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
// Specify CEF global settings here.
CefSettings settings;
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif
// SimpleApp implements application-level callbacks for the browser process.
// It will create the first browser instance in OnContextInitialized() after
// CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.
CefRunMessageLoop();
// Shut down CEF.
CefShutdown();
return 0;
}
在CefExecuteProcess中:
CEF_GLOBAL int CefExecuteProcess(const CefMainArgs& args,
CefRefPtr<CefApp> application,
void* windows_sandbox_info) {
const char* api_hash = cef_api_hash(0);
if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
// The libcef API hash does not match the current header API hash.
NOTREACHED();
return 0;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: application, windows_sandbox_info
// Execute
int _retval = cef_execute_process(&args, CefAppCppToC::Wrap(application),
windows_sandbox_info);
// Return type: simple
return _retval;
}
调用了cef_execute_process:
// This function should be called from the application entry point function to
// execute a secondary process. It can be used to run secondary processes from
// the browser client executable (default behavior) or from a separate
// executable specified by the CefSettings.browser_subprocess_path value. If
// called for the browser process (identified by no "type" command-line value)
// it will return immediately with a value of -1. If called for a recognized
// secondary process it will block until the process should exit and then return
// the process exit code. The |application| parameter may be NULL. The
// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see
// cef_sandbox_win.h for details).
///
CEF_EXPORT int cef_execute_process(const struct _cef_main_args_t* args,
cef_app_t* application,
void* windows_sandbox_info);
CefInitialize:
CEF_GLOBAL bool CefInitialize(const CefMainArgs& args,
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info) {
const char* api_hash = cef_api_hash(0);
if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
// The libcef API hash does not match the current header API hash.
NOTREACHED();
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: application, windows_sandbox_info
// Execute
int _retval = cef_initialize(
&args, &settings, CefAppCppToC::Wrap(application), windows_sandbox_info);
// Return type: bool
return _retval ? true : false;
}
其中调用:
// This function should be called on the main application thread to initialize
// the CEF browser process. The |application| parameter may be NULL. A return
// value of true (1) indicates that it succeeded and false (0) indicates that it
// failed. The |windows_sandbox_info| parameter is only used on Windows and may
// be NULL (see cef_sandbox_win.h for details).
///
CEF_EXPORT int cef_initialize(const struct _cef_main_args_t* args,
const struct _cef_settings_t* settings,
cef_app_t* application,
void* windows_sandbox_info);
cef_app.h中重要的接口:
//用于检测是当前进程是否是浏览器进程(main入口函数调用)
int CefExecuteProcess(const CefMainArgs& args, CefRefPtr<CefApp> application, void* windows_sandbox_info);
//主线程里面初始化Cef 浏览器进程信息
bool CefInitialize(const CefMainArgs& args,const CefSettings& settings,CefRefPtr<CefApp> application, void* windows_sandbox_info);
//浏览器进程退出的时候调用
void CefShutdown();
//在CefInitialize之后调用,建议使用CefRunMessageLoop替代CefDoMessageLoopWork,
如果使用此函数那么将会回调CefBrowserProcessHandler::OnScheduleMessagePumpWork()
void CefDoMessageLoopWork();
//运行Cef 消息环,如果调用CefQuitMessageLoop则退出消息环
void CefRunMessageLoop();
//通知cef消息环退出
void CefQuitMessageLoop();
//调用windows Api进入模态消息环之前设置为true,退出模态消息环的时候设置为false,例如TrackPopupMenu
void CefSetOSModalLoop(bool osModalLoop);
//启用高DPI支持
void CefEnableHighDPISupport();
CefApp类
/*--cef(source=client,no_debugct_check)--*/
class CefApp : public virtual CefBaseRefCounted {
public:
///
// Provides an opportunity to view and/or modify command-line arguments before
// processing by CEF and Chromium. The |process_type| value will be empty for
// the browser process. Do not keep a reference to the CefCommandLine object
// passed to this method. The CefSettings.command_line_args_disabled value
// can be used to start with an empty command-line object. Any values
// specified in CefSettings that equate to command-line arguments will be set
// before this method is called. Be cautious when using this method to modify
// command-line arguments for non-browser processes as this may result in
// undefined behavior including crashes.
///
/*--cef(optional_param=process_type)--*/
提供修改命令行参数的机会
virtual void OnBeforeCommandLineProcessing(
const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) {}
///
// Provides an opportunity to register custom schemes. Do not keep a reference
// to the |registrar| object. This method is called on the main thread for
// each process and the registered schemes should be the same across all
// processes.
///
/*--cef()--*/
提供修改注册用户主题的机会
virtual void OnRegisterCustomSchemes(
CefRawPtr<CefSchemeRegistrar> registrar) {}
///
// Return the handler for resource bundle events. If
// CefSettings.pack_loading_disabled is true a handler must be returned. If no
// handler is returned resources will be loaded from pack files. This method
// is called by the browser and render processes on multiple threads.
///
/*--cef()--*/
资源包Handler
virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler() {
return nullptr;
}
///
// Return the handler for functionality specific to the browser process. This
// method is called on multiple threads in the browser process.
///
/*--cef()--*/
浏览器进程Handler
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
return nullptr;
}
///
// Return the handler for functionality specific to the render process. This
// method is called on the render process main thread.
///
/*--cef()--*/
//渲染进程Handler
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() {
return nullptr;
}
};
#endif // CEF_INCLUDE_CEF_APP_H_
CefApp 类分析:
virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler() ;
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() ;
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler();
需要处理对应的Handler,我们则需要继承当前Handler类,并且在该函数里面返回this,当然具体需要继承哪些Handler我们根据业务需求然后查看对应的Handler事件,实际处理。
// Implement application-level callbacks for the browser process.
class SimpleApp : public CefApp, public CefBrowserProcessHandler {
public:
SimpleApp();
// CefApp methods:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
OVERRIDE {
return this;
}
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() OVERRIDE;
private:
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleApp);
};
#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
在SimpleApp中,继承CefApp,重写了GetBrowserProcessHandler,因此继承了CefBrowserProcessHandler类:.,重写GetBrowserProcessHandler()返回this。然后在重写CefBrowserProcessHandler的事件OnContextInitialized这个函数做一些浏览器的创建工作。当我们调用CefInitialize初始化Cef浏览器进程信息的时候,该触发OnContextInitialized。
// Class used to implement browser process callbacks. The methods of this class
// will be called on the browser process main thread unless otherwise indicated.
///
/*--cef(source=client,no_debugct_check)--*/
class CefBrowserProcessHandler : public virtual CefBaseRefCounted {
public:
///
// Called on the browser process UI thread immediately after the CEF context
// has been initialized.
///
/*--cef()--*/
virtual void OnContextInitialized() {}
///
// Called before a child process is launched. Will be called on the browser
// process UI thread when launching a render process and on the browser
// process IO thread when launching a GPU or plugin process. Provides an
// opportunity to modify the child process command line. Do not keep a
// reference to |command_line| outside of this method.
///
/*--cef()--*/
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {}
///
// Called on the browser process IO thread after the main thread has been
// created for a new render process. Provides an opportunity to specify extra
// information that will be passed to
// CefRenderProcessHandler::OnRenderThreadCreated() in the render process. Do
// not keep a reference to |extra_info| outside of this method.
///
/*--cef()--*/
virtual void OnRenderProcessThreadCreated(
CefRefPtr<CefListValue> extra_info) {}
///
// Return the handler for printing on Linux. If a print handler is not
// provided then printing will not be supported on the Linux platform.
///
/*--cef()--*/
virtual CefRefPtr<CefPrintHandler> GetPrintHandler() { return nullptr; }
///
// Called from any thread when work has been scheduled for the browser process
// main (UI) thread. This callback is used in combination with CefSettings.
// external_message_pump and CefDoMessageLoopWork() in cases where the CEF
// message loop must be integrated into an existing application message loop
// (see additional comments and warnings on CefDoMessageLoopWork). This
// callback should schedule a CefDoMessageLoopWork() call to happen on the
// main (UI) thread. |delay_ms| is the requested delay in milliseconds. If
// |delay_ms| is <= 0 then the call should happen reasonably soon. If
// |delay_ms| is > 0 then the call should be scheduled to happen after the
// specified delay and any currently pending scheduled call should be
// cancelled.
///
/*--cef()--*/
virtual void OnScheduleMessagePumpWork(int64 delay_ms) {}
};
#endif // CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_
OnContextInitialized则是根据命令行参数创建浏览器显示内容。此时一个简单的CefDemo基本完成。但是这个Demo并没有处理任何事件,只是简简单单的显示了一个网页而已。但是我们在操作的时候发现窗口的标题会随着我们访问的网页不同而变化,所以我们需要关注Cef事件通知,即CefClient。
void SimpleApp::OnContextInitialized() {
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
#if defined(OS_WIN) || defined(OS_LINUX)
// Create the browser using the Views framework if "--use-views" is specified
// via the command-line. Otherwise, create the browser using the native
// platform framework. The Views framework is currently only supported on
// Windows and Linux.
const bool use_views = command_line->HasSwitch("use-views");
#else
const bool use_views = false;
#endif
// SimpleHandler implements browser-level callbacks.
CefRefPtr<SimpleHandler> handler(new SimpleHandler(use_views));
// Specify CEF browser settings here.
CefBrowserSettings browser_settings;
std::string url;
// Check if a "--url=" value was provided via the command-line. If so, use
// that instead of the default URL.
url = command_line->GetSwitchValue("url");
if (url.empty())
url = "http://www.baidu.com";
if (use_views) {
// Create the BrowserView.
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
handler, url, browser_settings, nullptr, nullptr,
new SimpleBrowserViewDelegate());
// Create the Window. It will show itself after creation.
CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
} else {
// Information used when creating the native window.
CefWindowInfo window_info;
#if defined(OS_WIN)
// On Windows we need to specify certain flags that will be passed to
// CreateWindowEx().
window_info.SetAsPopup(NULL, "cefsimple");
#endif
// Create the first browser window.
CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
nullptr, nullptr);
}
}
SimpleHandler:
class SimpleHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler {
public:
explicit SimpleHandler(bool use_views);
~SimpleHandler();
// Provide access to the single global instance of this object.
static SimpleHandler* GetInstance();
// CefClient methods:处理浏览器标题发生变化事件
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) OVERRIDE;
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);
bool IsClosing() const { return is_closing_; }
private:
// Platform-specific implementation.
void PlatformTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title);
// True if the application is using the Views framework.
const bool use_views_;
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list<CefRefPtr<CefBrowser>> BrowserList;
BrowserList browser_list_;
bool is_closing_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleHandler);
};
首先,SimpleHandler继承了CefClient:
/*--cef(source=client,no_debugct_check)--*/
class CefClient : public virtual CefBaseRefCounted {
public:
///
// Return the handler for audio rendering events.
///
/*--cef()--*/
virtual CefRefPtr<CefAudioHandler> GetAudioHandler() { return nullptr; }
///
// Return the handler for context menus. If no handler is provided the default
// implementation will be used.
///
/*--cef()--*/
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() {
return nullptr;
}
///
// Return the handler for dialogs. If no handler is provided the default
// implementation will be used.
///
/*--cef()--*/
virtual CefRefPtr<CefDialogHandler> GetDialogHandler() { return nullptr; }
///
// Return the handler for browser display state events.
///
/*--cef()--*/
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() { return nullptr; }
///
// Return the handler for download events. If no handler is returned downloads
// will not be allowed.
///
/*--cef()--*/
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() { return nullptr; }
///
// Return the handler for drag events.
///
/*--cef()--*/
virtual CefRefPtr<CefDragHandler> GetDragHandler() { return nullptr; }
///
// Return the handler for find result events.
///
/*--cef()--*/
virtual CefRefPtr<CefFindHandler> GetFindHandler() { return nullptr; }
///
// Return the handler for focus events.
///
/*--cef()--*/
virtual CefRefPtr<CefFocusHandler> GetFocusHandler() { return nullptr; }
///
// Return the handler for JavaScript dialogs. If no handler is provided the
// default implementation will be used.
///
/*--cef()--*/
virtual CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() { return nullptr; }
///
// Return the handler for keyboard events.
///
/*--cef()--*/
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() { return nullptr; }
///
// Return the handler for browser life span events.
///
/*--cef()--*/
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() { return nullptr; }
///
// Return the handler for browser load status events.
///
/*--cef()--*/
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() { return nullptr; }
///
// Return the handler for off-screen rendering events.
///
/*--cef()--*/
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() { return nullptr; }
///
// Return the handler for browser request events.
///
/*--cef()--*/
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() { return nullptr; }
///
// Called when a new message is received from a different process. Return true
// if the message was handled or false otherwise. Do not keep a reference to
// or attempt to access the message outside of this callback.
///
/*--cef()--*/
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
return false;
}
};
和CefApp的 原理相同,CefClient::GetxxxHandler的返回对象继承,所以我们在实现SimpleHandler的时候只需要关注事件,然后从该对应的Handler继承,处理对应的回调即可
SimpleHandler继承了CefDisplayHandler,CefLifeSpanHandler,CefLoadHandler 三个事件,并且处理了三个事件中的浏览器创建事件(CefLifeSpanHandler )、浏览器标题发生改变事件(CefDisplayHandler )、网页加载错误事件(CefLoadHandler )。例如标题发生改变的时候我们只需要在OnTitleChange里面SetWindowText就可以切换窗口标题了。此时一个简短的Demo分析完成。
Cef需要重写的对象:
CefApp:主要处理浏览器本身相关事件,具体事件参考头文件。
CefClient:主要处理了浏览器网页之间的事件,具体事件参考头文件。