Chromium Embedded Framework(CEF)は、Google Chromium をベースにしたオープンソースのフレームワークであり、サードパーティアプリケーションにウェブブラウザ機能を埋め込むことを目的としています。CEF3 は Chromium の Content API を利用したマルチプロセスアーキテクチャを採用し、高いパフォーマンスと安定性、GPU アクセラレーション、WebRTC、DevTools リモートデバッグなどの最新 Web 機能をサポートしています。
基本構成とセットアップ
CEF3 はバイナリパッケージまたはソースコードからビルド可能です。バイナリパッケージには各プラットフォーム(Windows、Linux、macOS)向けのヘッダ、ライブラリ、サンプルアプリ(cefclient)、リソースファイルが含まれています。アプリケーション開発は cefclient をベースにカスタマイズするのが一般的です。
コアコンセプト
プロセスモデル
CEF3 は以下のプロセスで構成されます:
- Browser プロセス:UI、ネットワーク、ウィンドウ管理を担当
- Renderer プロセス:HTML/CSS/JavaScript のレンダリングと実行
- サブプロセス:GPU、プラグイン、ユーティリティなど
デフォルトでは単一の実行ファイルが複数プロセスとして起動されますが、CefSettings.browser_subprocess_path を設定することでサブプロセス専用の実行ファイルを指定できます。
スレッドモデル
Browser プロセス内には以下の主要スレッドが存在します:
TID_UI:メイン UI スレッドTID_IO:ネットワークおよび IPC 処理TID_FILE:ファイル I/O
スレッド間通信には CefPostTask() を使用し、現在のスレッド確認には CefCurrentlyOn() を利用します。
メモリ管理
すべての CEF クラスは CefBase を継承し、CefRefPtr による参照カウント方式で管理されます。
class MyClass : public CefBase {
public:
// ...
private:
IMPLEMENT_REFCOUNTING(MyClass);
};
CefRefPtr<MyClass> obj = new MyClass();
文字列処理
CEF は独自の文字列型 CefString を提供し、UTF-8、UTF-16、ワイド文字との相互変換をサポートします。
std::string utf8_str = "Hello";
CefString cef_str(utf8_str); // UTF-8 → CEF 内部形式
std::wstring wstr = cef_str.ToWString(); // CEF → ワイド文字
アプリケーション構造
CEF アプリケーションは以下の要素で構成されます:
CefApp:プロセス全体の初期化とハンドラ提供CefClient:ブラウザインスタンスごとのイベントハンドラCefBrowser/CefFrame:ブラウザ操作インターフェース
エントリポイント例(単一実行ファイル)
int main(int argc, char* argv[]) {
CefMainArgs args(argc, argv);
CefRefPtr<MyApp> app(new MyApp);
int exit_code = CefExecuteProcess(args, app.get());
if (exit_code >= 0) return exit_code;
CefSettings settings;
CefInitialize(args, settings, app.get());
CefRunMessageLoop();
CefShutdown();
return 0;
}
ブラウザライフサイクル管理
CefLifeSpanHandler を実装してブラウザウィンドウの作成・破棄を制御します。
bool MyHandler::DoClose(CefRefPtr<CefBrowser> browser) {
m_bIsClosing = true;
return false; // OS に再度 close イベントを送信
}
void MyHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
if (--m_BrowserCount == 0) {
CefQuitMessageLoop();
}
}
オフスクリーンレンダリング
ネイティブウィンドウを作成せずにピクセルデータを取得するには、CefRenderHandler を実装し、CefWindowInfo::SetAsOffScreen() を呼び出します。
void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
const RectList& dirtyRects, const void* buffer, int width, int height) {
// ピクセルバッファを描画システムに転送
}
プロセス間通信(IPC)
CefProcessMessage を使用して Browser と Renderer プロセス間でメッセージを送受信します。
// Browser → Renderer
auto msg = CefProcessMessage::Create("my_msg");
msg->GetArgumentList()->SetString(0, "data");
browser->SendProcessMessage(PID_RENDERER, msg);
// Renderer → Browser(CefClient::OnProcessMessageReceived で受信)
JavaScript 連携
非同期 JavaScript バインディングには以下の方法があります:
- 汎用メッセージルーター:
cefQuery経由で C++ と通信 - カスタム実装:V8 コンテキストでコールバックを登録し、IPC 経由で結果を返す
ネットワークリクエスト処理
カスタムスキームハンドラ
void MyApp::OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar) {
registrar->AddCustomScheme("myapp", true, false, false);
}
// 初期化時に登録
CefRegisterSchemeHandlerFactory("myapp", "", new MySchemeHandlerFactory());
リクエストインターセプト
CefRequestHandler::GetResourceHandler() をオーバーライドして任意のリクエストを処理できます。
プロキシ設定
コマンドライン引数でプロキシを指定可能:
--proxy-server=socks5://localhost:1080
--proxy-pac-url=http://example.com/proxy.pac
認証が必要な場合は CefRequestHandler::GetAuthCredentials() で資格情報を提供します。