相关类说明
CefBrowserHost: 该类在浏览器窗口来看代表了 browser 进程,同时也暴露了与浏览器窗口相关的接口,该类的方法只能在 browser 进程中调用,但可以在 browser 进程的任意线程中被调用。
///
// Create a new browser window using the window parameters specified by
// |windowInfo|. All values will be copied internally and the actual window
// will be created on the UI thread. If |request_context| is empty the
// global request context will be used. This method can be called on any
// browser process thread and will not block.
///
/*--cef(optional_param=client,optional_param=url,
optional_param=request_context)--*/
static bool CreateBrowser(const CefWindowInfo& windowInfo,
CefRefPtr client,
const CefString& url,
const CefBrowserSettings& settings,
CefRefPtr request_context);
///
// Create a new browser window using the window parameters specified by
// |windowInfo|. If |request_context| is empty the global request context
// will be used. This method can only be called on the browser process UI
// thread.
///
/*--cef(optional_param=client,optional_param=url,
optional_param=request_context)--*/
static CefRefPtr CreateBrowserSync(
const CefWindowInfo& windowInfo,
CefRefPtr client,
const CefString& url,
const CefBrowserSettings& settings,
CefRefPtr request_context);
CefBrowser: 该类代表一个浏览器对象,在 browser 进程中该类的方法可以被任意线程调用。在 render 进程中只能在主线程被调用。
CefFrame: 表示浏览器窗口中的一个 frame,在 browser 进程中该类的方法可以被任意线程调用(简单理解就是 Frame 标识一个页面,通过该类开发者可以加载某一URL 或者一段 HTML 代码,获取页面的源码和文本,URL,V8 执行上下文,访问页面中的 DOM)
执行CefBrowserHost::CreateBrowser()创建一个browser实例,使用CefLifeSpanHandler管理browser对象生命周期。
Browser生命周期
- Browser创建
Browser生命周期从执行 CefBrowserHost::CreateBrowser() 或者 CefBrowserHost::CreateBrowserSync() 开始。可以在CefBrowserProcessHandler::OnContextInitialized() 回调或者特殊平台例如windows的WM_CREATE 中方便的执行业务逻辑。
// Information about the window that will be created including parenting, size, etc.
// The definition of this structure is platform-specific.
// 定义的结构体与平台相关
CefWindowInfo info;
// On Windows for example...
info.SetAsChild(parent_hwnd, client_rect);
// Customize this structure to control browser behavior.
CefBrowserSettings settings;
// CefClient implementation.
CefRefPtr client(new MyClient);
// Create the browser asynchronously. Initially loads the Google URL.
CefBrowserHost::CreateBrowser(info, client.get(), “http://www.google.com”, settings);
The CefLifeSpanHandler class provides the callbacks necessary for managing browser life span. Below is an extract of the relevant methods and members.
CefLifeSpanHandler 类提供管理 browser生合周期必需的回调。以下为相关方法和成员。
class MyClient : public CefClient,
public CefLifeSpanHandler,
... {
// CefClient methods.
virtual CefRefPtr GetLifeSpanHandler() OVERRIDE {
return this;
}
// CefLifeSpanHandler methods.
void OnAfterCreated(CefRefPtr browser) OVERRIDE;
bool DoClose(CefRefPtr browser) OVERRIDE;
void OnBeforeClose(CefRefPtr browser) OVERRIDE;
// Member accessors.
CefRefPtr GetBrower() { return m_Browser; }
bool IsClosing() { return m_bIsClosing; }
private:
CefRefPtr m_Browser;
int m_BrowserId;
int m_BrowserCount;
bool m_bIsClosing;
IMPLEMENT_REFCOUNTING(MyHandler);
IMPLEMENT_LOCKING(MyHandler);
};
当browser对象创建后OnAfterCreated() 方法立即执行。宿主程序可以用这个方法来保持对browser对象的引用。
void MyClient::OnAfterCreated(CefRefPtr browser) {
// Must be executed on the UI thread.
REQUIRE_UI_THREAD();
// Protect data members from access on multiple threads.
AutoLock lock_scope(this);
if (!m_Browser.get()) {
// Keep a reference to the main browser.
m_Browser = browser;
m_BrowserId = browser->GetIdentifier();
}
// Keep track of how many browsers currently exist.
m_BrowserCount++;
}
Browser销毁
执行CefBrowserHost::CloseBrowser()销毁browser对象。// Notify the browser window that we would like to close it. This will result in a call to // MyHandler::DoClose() if the JavaScript 'onbeforeunload' event handler allows it. browser->GetHost()->CloseBrowser(false);
browser对象的关闭事件来源于他的父窗口的关闭方法(比如,在父窗口上点击X控钮。)。父窗口需要调用 CloseBrowser(false) 并且等待操作系统的第二个关闭事件来决定是否允许关闭。如果在JavaScript 'onbeforeunload'事件处理或者 DoClose()回调中取消了关闭操作,则操作系统的第二个关闭事件可能不会发送。注意一下面示例中对IsCloseing()的判断-它在第一个关闭事件中返回false,在第二个关闭事件中返回true(当 DoCloase 被调用后)。
Windows平台下,在父窗口的WndProc里处理WM_ClOSE消息:
case WM_CLOSE:
if (g_handler.get() && !g_handler->IsClosing()) {
CefRefPtr browser = g_handler->GetBrowser();
if (browser.get()) {
// Notify the browser window that we would like to close it. This will result in a call to
// MyHandler::DoClose() if the JavaScript 'onbeforeunload' event handler allows it.
browser->GetHost()->CloseBrowser(false);
// Cancel the close.
return 0;
}
}
// Allow the close.
break;
case WM_DESTROY:
// Quitting CEF is handled in MyHandler::OnBeforeClose().
return 0;
}
DoClose方法设置m_blsClosing 标志位为true,并返回false以再次发送操作系统的关闭事件。
bool MyClient::DoClose(CefRefPtr browser) {
// Must be executed on the UI thread.
REQUIRE_UI_THREAD();
// Protect data members from access on multiple threads.
AutoLock lock_scope(this);
// Closing the main window requires special handling. See the DoClose()
// documentation in the CEF header for a detailed description of this
// process.
if (m_BrowserId == browser->GetIdentifier()) {
// Notify the browser that the parent window is about to close.
browser->GetHost()->ParentWindowWillClose();
// Set a flag to indicate that the window close should be allowed.
m_bIsClosing = true;
}
// Allow the close. For windowed browsers this will result in the OS close
// event being sent.
return false;
}
当操作系统捕捉到第二次关闭事件,它才会允许父窗口真正关闭。该动作会先触发OnBeforeClose()回调,请在该回调里释放所有对浏览器对象的引用。
void MyHandler::OnBeforeClose(CefRefPtr browser) {
// Must be executed on the UI thread.
REQUIRE_UI_THREAD();
// Protect data members from access on multiple threads.
AutoLock lock_scope(this);
if (m_BrowserId == browser->GetIdentifier()) {
// Free the browser pointer so that the browser can be destroyed.
m_Browser = NULL;
}
if (--m_BrowserCount == 0) {
// All browser windows have closed. Quit the application message loop.
CefQuitMessageLoop();
}
}