QtアプリケーションへのCEFによるWebブラウザ埋め込み

Chromium Embedded Framework(CEF)は、Google Chromiumをベースにしたオープンソースのフレームワークであり、デスクトップアプリケーション内に高機能なWebブラウザを統合するためのライブラリである。CEF3はマルチプロセスアーキテクチャを採用し、HTML5やJavaScriptなどの最新Web技術をネイティブアプリ内で活用できる。

環境構築とビルド設定

QtプロジェクトにCEFを統合する際には、ランタイムライブラリの整合性に注意が必要である。特にQtがMDd(マルチスレッドDLLデバッグ)でビルドされている場合、CEFも同様の設定でコンパイルしなければならない。必要なファイルは以下の通り:

  • Resources/ディレクトリ内のcef.pakdevtools_resources.pakなど
  • Debug/またはRelease/ディレクトリ内のDLLファイル
  • out/Debug/lib/以下の静的ライブラリ(libcef.libなど)

Visual Studioでは、プロジェクトのプロパティからインクルードディレクトリ・ライブラリディレクトリを追加し、リンカの「追加の依存ファイル」にCEF関連の.libを記述する。

主要なCEFハンドラクラス

  • CefDownloadHandler:ファイルダウンロードイベントを処理。デフォルトでは無効化されているため、OnBeforeDownloadcallback->Continue(...)を呼び出す必要がある。
  • CefClient:各種ハンドラ(表示、ダウンロード、レンダリングなど)を登録する中心クラス。
  • CefDisplayHandler:URL変更やページタイトル更新などのUI関連イベントを捕捉。
  • CefRenderProcessHandler:レンダラープロセス側で実行され、V8コンテキスト作成時にJavaScriptオブジェクトを登録可能。
  • CefBrowserProcessHandler:ブラウザープロセスの初期化やサブプロセス起動を制御。

Qtウィジェットへの統合手順

  1. QWidgetを継承したカスタムビュークラス(例: QCefWebView)を作成。
  2. アプリケーション起動時にCEFを初期化し、終了時にシャットダウン処理を実行。
  3. レンダラープロセスでV8コンテキストが作成されたタイミングで、JavaScriptから呼び出せるネイティブ関数を登録。

初期化コード例

// cefclient.cpp
int CefInit(int &argc, char **argv) {
    CefMainArgs main_args(GetModuleHandle(NULL));
    CefRefPtr<ClientApp> app = new ClientApp();

    int exit_code = CefExecuteProcess(main_args, app.get(), nullptr);
    if (exit_code >= 0) return exit_code;

    CefSettings settings;
    settings.multi_threaded_message_loop = true;
    settings.no_sandbox = true;
    settings.single_process = true;
    settings.remote_debugging_port = 8088;

    CefInitialize(main_args, settings, app.get(), nullptr);
    g_handler = new ClientHandler();
    return -1;
}

void CefQuit() {
    CefShutdown();
}

カスタムWebViewクラスの実装

// qcefwebview.h
class QCefWebView : public QWidget,
                    public ClientHandler::Listener,
                    public ClientApp::RenderDelegate {
    Q_OBJECT
public:
    void load(const QUrl& url);
    QVariant evaluateJavaScript(const QString& script);

signals:
    void titleChanged(QString title);
    void urlChanged(QUrl url);
    void jsMessage(QString name, QVariantList args);

protected:
    // ClientHandler::Listener
    void OnAddressChange(const QString& url) override;
    void OnTitleChange(const QString& title) override;
    void OnMessageEvent(MessageEvent* e) override;

    // ClientApp::RenderDelegate
    void OnContextCreated(CefRefPtr<CefApp> app,
                          CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
                          CefRefPtr<CefV8Context> context) override;
};

V8オブジェクト登録例

// qcefwebview.cpp
void QCefWebView::OnContextCreated(CefRefPtr<CefApp> app,
                                   CefRefPtr<CefBrowser> browser,
                                   CefRefPtr<CefFrame> frame,
                                   CefRefPtr<CefV8Context> context) {
    CefRefPtr<CefV8Value> global = context->GetGlobal();

    // JavaScriptから呼び出せる関数を登録
    CefRefPtr<CefV8Handler> handler = new CefMapV8Handler(g_appHandler);
    CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("ExecuteRequestOrder", handler);
    global->SetValue("ExecuteRequestOrder", func, V8_PROPERTY_ATTRIBUTE_NONE);
}

このようにして、Qtアプリケーション内にCEFベースのWebビューを埋め込み、双方向のJavaScript連携を実現できる。

タグ: Qt CEF Chromium Embedded Framework C++ Web Integration

8月5日 18:31 投稿