在使用CEF3作為框架開發過程中,實現WebSockets、XMLHttpRequest、JS與本地客戶端交互等功能時,需要在渲染(Render)進程和瀏覽(Browser)進程中傳遞消息。CEF3在這個方面進行了很好的封裝,普通用戶只需要了解幾個接口和函數就可以實現進程間消息傳遞。根據個人的開發經驗和理解,以cefclient為例子總結下CEF3消息的傳遞機制,有不正確之處,請賜教!
一般通過指定的CefBrowser實例,調用CefBrowser::SendProcessMessage()方法。由於CefBrowser 與CefFrame對象同時存在於browser與render進程中,所以不管在渲染(Render)進程還是瀏覽(Browser)進程中,都能調用到SendProcessMessage()方法。SendProcessMessage()有兩個參數,進程標識CefProcessId與需要傳遞的消息CefProcessMessage。
CefProcessId是一個枚舉常量,具體代表的意義不解釋,看如下所示代碼:
typedef enum { /// // Browser process. /// PID_BROWSER, /// // Renderer process. /// PID_RENDERER, } cef_process_id_t;
CefProcessMessage是一個管理所需傳遞消息的類,包含消息名稱和消息內容。見下邊代碼示例:
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(CefString("xiaoximingcheng")); //設置消息名稱 //檢索參數列表對象(Retrieve the argument list object.) CefRefPtr<CefListValue> args = message->GetArgumentList(); CefString message_cont; //設置消息內容 args->SetString(0, message_cont); args->SetInt(0, 10)
進程間傳遞消息,都要通過GetArgumentList獲取和Set*(SetString、SetInt)來設置。所有render進程提供利用相同的消息傳遞方式:通過browser進程中的CefBrowserProcessHandler::OnRenderProcessThreadCreated()將消息傳遞給render進程中的CefRenderProcessHandler::OnRenderThreadCreated()。
從browser進程發到render進程的消息,被CefRenderProcessHandler::OnProcessMessageReceived()接收,從render進程發到browser進程的消息,被CefBrowserProcessHandler::OnProcessMessageReceived()接收。見下圖:
發送消息的過程前通過關聯消息和frame ID(通過CefFrame::GetIdentifier()獲取),接收消息進程在接收后,通過CefBrowser::GetFrame()獲取Frame相關信息,從而讓Frame和消息對應起來,讓每個Frame可以處理自己消息。
// Helper macros for splitting and combining the int64 frame ID value. #define MAKE_INT64(int_low, int_high) \ ((int64) (((int) (int_low)) | ((int64) ((int) (int_high))) << 32)) #define LOW_INT(int64_val) ((int) (int64_val)) #define HIGH_INT(int64_val) ((int) (((int64) (int64_val) >> 32) & 0xFFFFFFFFL)) // Sending the frame ID. const int64 frame_id = frame->GetIdentifier(); args->SetInt(0, LOW_INT(frame_id)); args->SetInt(1, HIGH_INT(frame_id)); // Receiving the frame ID. const int64 frame_id = MAKE_INT64(args->GetInt(0), args->GetInt(1)); CefRefPtr<CefFrame> frame = browser->GetFrame(frame_id);