libcef-框架架构中概念介绍-Client应用程序-浏览器生命周期(四)

文章目录

    • 1.应用程序
    • 2.客户端
    • 3.浏览器生命周期
    • 4.作者答疑

1.应用程序

  该CefApp接口提供对特定接口回调。重要的回调包括:

  • OnBeforeCommandLineProcessing提供了以编程方式设置命令行参数的机会。有关更多信息,请参阅“命令行参数”部分。
  • OnRegisterCustomSchemes提供注册自定义方案的机会。有关更多信息,请参阅“请求处理”部分。
  • GetBrowserProcessHandler返回特定于浏览器进程的功能的处理程序,包括 OnContextInitialized() 方法。
  • GetRenderProcessHandler返回特定于渲染过程的功能的处理程序。这包括与 JavaScript 相关的回调和处理消息。有关更多信息,请参阅JavaScriptIntegration Wiki 页面和“进程间通信”部分。

  一个示例 CefApp 实现可以在cefsimple/simple_app.h和cefsimple/simple_app.cc 中看到。

2.客户端

  该CefClient接口提供对浏览器的实例特有的回调。单个 CefClient 实例可以在任意数量的浏览器之间共享。重要的回调包括:

  • 浏览器生命周期、上下文菜单、对话框、显示通知、拖动事件、焦点事件、键盘事件等处理程序。大多数处理程序是可选的。有关不实现特定处理程序的副作用(如果有),请参阅 cef_client.h 中的文档。
  • OnProcessMessageReceived在从渲染进程接收到 IPC 消息时调用。有关更多信息,请参阅“进程间通信”部分。

  一个示例 CefClient 实现可以在cefsimple/simple_handler.h和cefsimple/simple_handler.cc 中看到。

3.浏览器生命周期

  浏览器生命周期从调用 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<MyClient> client(new MyClient);

// Create the browser asynchronously. Initially loads the Google URL.
CefBrowserHost::CreateBrowser(info, client.get(), “http://www.google.com”, settings, NULL);

  CefLifeSpanHandler类提供了一些必要的管理浏览器寿命的回调。以下是相关方法和成员的摘录。

class MyClient : public CefClient,
    public CefLifeSpanHandler,
    ...
{
    // CefClient methods.
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE
    {
        return this;
    }

    // CefLifeSpanHandler methods.
    void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
    bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
    void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;

    // Member accessors.
    CefRefPtr<CefBrowser> GetBrower()
    {
        return m_Browser;
    }
    bool IsClosing()
    {
        return m_bIsClosing;
    }

private:
    CefRefPtr<CefBrowser> m_Browser;
    int m_BrowserId;
    int m_BrowserCount;
    bool m_bIsClosing;

    IMPLEMENT_REFCOUNTING(MyClient);
};

  OnAfterCreated() 方法将在浏览器对象创建后立即调用。宿主应用程序可以使用此方法来保持对主浏览器对象的引用。

void MyClient::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
    // Must be executed on the UI thread.
    REQUIRE_UI_THREAD();

    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++;
}

  要销毁浏览器,请调用 CefBrowserHost::CloseBrowser()。

// 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);

  如果浏览器是另一个窗口的父窗口,则关闭事件可能源自该父窗口的 OS 函数(例如,通过单击父窗口上的 X)。然后父窗口需要调用 CloseBrowser(false) 并等待第二个操作系统关闭事件以指示浏览器已允许关闭。如果关闭被 JavaScript ‘onbeforeunload’ 事件处理程序或 DoClose() 回调取消,则不会发送第二个操作系统关闭事件。请注意以下示例中的 IsClosing() 检查——它将为第一个 OS 关闭事件返回 false,为第二个(在调用 DoClose 之后)返回 true。在 Windows 上的父窗口 WndProc 中处理:

case WM_CLOSE:
if (g_handler.get() && !g_handler->IsClosing())
{
    CefRefPtr<CefBrowser> 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;
}

  在 Linux 上处理“delete_event”信号:

gboolean delete_event(GtkWidget *widget, GdkEvent *event, GtkWindow *window)
{
    if (g_handler.get() && !g_handler->IsClosing())
    {
        CefRefPtr<CefBrowser> 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 TRUE;
        }
    }

    // Allow the close.
    return FALSE;
}

  在 OS X 上关闭更复杂。请参阅cefsimple/cefsimple_mac.mm中的注释以全面了解关闭在该平台上的工作原理。DoClose() 方法设置 m_bIsClosing 标志并返回 false 以发送第二个操作系统关闭事件。

bool MyClient::DoClose(CefRefPtr<CefBrowser> browser)
{
    // Must be executed on the UI thread.
    REQUIRE_UI_THREAD();

    // 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())
    {
        // 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() 的调用。确保在 OnBeforeClose() 回调中释放对浏览器对象的任何引用。

void MyHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
    // Must be executed on the UI thread.
    REQUIRE_UI_THREAD();

    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();
    }
}

  有关每个平台上完整的工作示例,请参阅 cefclient 应用程序。

4.作者答疑


  如有疑问,请留言。

你可能感兴趣的:(Chromium,libcef,框架架构中概念介绍,应用程序,客户端,浏览器生命周期)