Chromium Embedded Framework(CEF)は、Google Chromiumをベースにしたオープンソースのフレームワークであり、デスクトップアプリケーション内に高機能なWebブラウザを統合するためのライブラリである。CEF3はマルチプロセスアーキテクチャを採用し、HTML5やJavaScriptなどの最新Web技術をネイティブアプリ内で活用できる。
環境構築とビルド設定
QtプロジェクトにCEFを統合する際には、ランタイムライブラリの整合性に注意が必要である。特にQtがMDd(マルチスレッドDLLデバッグ)でビルドされている場合、CEFも同様の設定でコンパイルしなければならない。必要なファイルは以下の通り:
Resources/ディレクトリ内のcef.pak、devtools_resources.pakなどDebug/またはRelease/ディレクトリ内のDLLファイルout/Debug/lib/以下の静的ライブラリ(libcef.libなど)
Visual Studioでは、プロジェクトのプロパティからインクルードディレクトリ・ライブラリディレクトリを追加し、リンカの「追加の依存ファイル」にCEF関連の.libを記述する。
主要なCEFハンドラクラス
- CefDownloadHandler:ファイルダウンロードイベントを処理。デフォルトでは無効化されているため、
OnBeforeDownloadでcallback->Continue(...)を呼び出す必要がある。 - CefClient:各種ハンドラ(表示、ダウンロード、レンダリングなど)を登録する中心クラス。
- CefDisplayHandler:URL変更やページタイトル更新などのUI関連イベントを捕捉。
- CefRenderProcessHandler:レンダラープロセス側で実行され、V8コンテキスト作成時にJavaScriptオブジェクトを登録可能。
- CefBrowserProcessHandler:ブラウザープロセスの初期化やサブプロセス起動を制御。
Qtウィジェットへの統合手順
QWidgetを継承したカスタムビュークラス(例:QCefWebView)を作成。- アプリケーション起動時にCEFを初期化し、終了時にシャットダウン処理を実行。
- レンダラープロセスで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連携を実現できる。