免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務建站與企業(yè)官網(wǎng)運營的一線實戰(zhàn)洞察。

VS2010 MFC嵌入CEF3 90.6.0:編譯鏈、消息泵與JS互調(diào)避坑

VS2010 MFC嵌入CEF3 90.6.0:編譯鏈、消息泵與JS互調(diào)避坑 簡介面向 C/MFC 桌面開發(fā)者與需要內(nèi)嵌瀏覽器能力的混合應用團隊這套工程資料圍繞 Visual Studio 2010 與 CEF3 90.6.0演示把 Chromium Web 視圖嵌入 MFC 窗口并建立 JavaScript 與 C 交互鏈路適合具備一定 MFC、Win32 消息循環(huán)和 C 基礎的中高級開發(fā)者參考。壓縮包共 629 個文件、約 457.22MB以 h 頭文件、pak 運行時資源、dll、lib、cpp、obj/tlog 等構(gòu)建中間文件為主并帶有解決方案與項目配置可輔助完成環(huán)境搭建、依賴引入、編譯鏈接及運行排錯。已有 1558 人學習說明該組合在實際項目中仍有參考需求。讀者可從中了解 CEF 子進程與多線程消息循環(huán)配置、MFC 窗口尺寸與繪制同步、JS 調(diào)用 C 的注冊與回調(diào)處理思路以及 Debug/Release 產(chǎn)物組織方式工程雖以示例形式呈現(xiàn)但足以作為 VS2010 下 CEF3 集成與調(diào)試的對照模板幫助縮短從零配置到可運行的時間。1. 為什么是 90.6.0 這個版本嵌入 MFC 的現(xiàn)實起點CEF3 90.6.0 屬于 Chromium 90 分支的正式二進制分發(fā)版把它塞進 vs2010 的 MFC 工程本質(zhì)是拿 2021 年的瀏覽器內(nèi)核去接 2010 年的窗口框架。老上位機、工控 HMI、醫(yī)療設備界面這類項目升級 IDE 的成本極高但前端頁面又必須跑現(xiàn)代 ES 語法于是「新內(nèi)核 老殼」的組合就成了剛需。真正要解決的無非三件事瀏覽器子窗口怎么掛到 MFC 的 View 或?qū)υ捒蛏?、消息泵歸誰泵、JS 與 C 之間怎么互調(diào)而不互相拖死。這套東西適合還在維護 VS2010 工程的 C 開發(fā)者新手能照第 3、4 章把流程跑通熟手可以直接跳到第 2 章看編譯鏈選型和第 5 章的翻車記錄。2. 編譯鏈先理清VS2010 編不動 CEF 90 的頭文件怎么辦動手之前必須接受一個事實CEF 90 的 C 頭文件用了override、std::unique_ptr、可變參數(shù)模板這些 VS2010 編不過的語法。這不是配置問題是編譯器能力問題。硬啃只有兩條路——要么放棄 VS2010要么在編譯鏈上做切分。切分的核心依據(jù)是 libcef 的導出邊界。2.1 先看清 libcef 的導出邊界C ABI 才是能跨編譯器的部分libcef.dll 對外暴露的符號是cef_*這一批 C 函數(shù)簽名里只有基礎類型、指針和結(jié)構(gòu)體指針沒有 STL 容器、沒有 C 類、沒有異常。這條 C ABI 是穩(wěn)定的任何版本的 MSVC 都能鏈接它包括 VS2010。真正編不過的是include/cef_client.h、include/cef_v8.h這些 C 封裝頭以及l(fā)ibcef_dll_wrapper這個靜態(tài)庫。wrapper 的作用是把 C 結(jié)構(gòu)體包裝成CefRefPtrCefClient那樣的 C 類它本身必須跟 libcef.dll 用同一套頭文件編譯所以它只能用 VS2019 編。于是路線就清楚了wrapper 和所有 CEF 相關(guān)的 C 代碼封進一個中間層 DLL用 VS2019 編譯VS2010 的 MFC 工程只 include 自己寫的純 C 頭文件通過LoadLibrary/ 導入庫調(diào)用???DLL 邊界只傳HWND、int、const char*、void*這幾類 POD 類型絕不傳std::string、CefRefPtr、std::function這樣兩套運行庫VS2010 的 msvcr100 和 VS2019 的 vcruntime140同時存在于一個進程里也不會打架。還有一種備選是直接 includeinclude/capi/下那套純 C 頭文件在 VS2010 里手動實現(xiàn)引用計數(shù)和回調(diào)函數(shù)表。這條路能走通但cef_client_t的每個回調(diào)都要自己填函數(shù)指針一個瀏覽器實例的光標、下載、生命周期回調(diào)填下來接近兩百行樣板代碼維護成本高。除非你的構(gòu)建環(huán)境完全禁止引入 VS2019否則不建議。CEF 二進制包里需要落地的文件并不多但一個都不能少文件/目錄放置位置作用漏了會怎樣libcef.dllexe 同級內(nèi)核本體啟動直接失敗libcef.lib鏈接目錄導入庫鏈接期報 LNK2019libcef_dll_wrapper.lib鏈接目錄C 封裝層同上icudtl.datexe 同級ICU 數(shù)據(jù)頁面中文亂碼或崩潰locales/*.pakexe 同級 locales語言資源界面文案回退英文cef.pak / cef_100_percent.pakexe 同級內(nèi)核資源白屏或渲染異常natives_blob.bin / v8_context_snapshot.binexe 同級V8 快照JS 引擎初始化失敗2.2 用 VS2019 編一個 C 接口中間層 DLL中間層對外只暴露五個函數(shù)夠用了初始化、創(chuàng)建瀏覽器、銷毀瀏覽器、執(zhí)行 JS、取窗口句柄。頭文件長這樣/* mycef_bridge.h —— 純 CVS2010 可以直接 include */ #ifndef MYCEF_BRIDGE_H #define MYCEF_BRIDGE_H #ifdef MYCEF_EXPORTS #define MYCEF_API __declspec(dllexport) #else #define MYCEF_API __declspec(dllimport) #endif #ifdef __cplusplus extern C { #endif /* 返回值0 成功非 0 失敗 */ MYCEF_API int MyCef_Init(void* hInstance, const char* subProcessPath, const char* cacheDir, const char* logFile, int debugPort); /* 在 parentHwnd 內(nèi)創(chuàng)建瀏覽器rect 傳客戶區(qū)大小 */ MYCEF_API int MyCef_CreateBrowser(void* parentHwnd, int x, int y, int w, int h, const char* urlUtf8); /* 主線程定時器里調(diào)每 10~30ms 一次 */ MYCEF_API void MyCef_DoMessageLoopWork(void); /* 窗口尺寸變化 */ MYCEF_API void MyCef_Resize(int w, int h); /* 執(zhí)行 JSjsUtf8 為 UTF-8 編碼腳本文本 */ MYCEF_API int MyCef_ExecuteJavaScript(const char* jsUtf8); /* 關(guān)閉瀏覽器并釋放必須在主線程調(diào)返回后再調(diào) MyCef_Shutdown */ MYCEF_API int MyCef_CloseBrowser(void); MYCEF_API void MyCef_Shutdown(void); /* 原生事件回調(diào)由中間層在 browser 進程 UI 線程回調(diào)MFC 側(cè)自行 PostMessage 回主線程 */ typedef void (*MyCef_NativeEventHandler)(const char* cmdUtf8, const char* jsonUtf8, int queryId); MYCEF_API void MyCef_SetNativeHandler(MyCef_NativeEventHandler handler); #ifdef __cplusplus } #endif #endif初始化那段的實現(xiàn)要點在參數(shù)取舍上// bridge.cpp —— 用 VS2019 編譯鏈接 libcef.lib libcef_dll_wrapper.lib MYCEF_API int MyCef_Init(void* hInstance, const char* subProcessPath, const char* cacheDir, const char* logFile, int debugPort) { CefMainArgs mainArgs((HINSTANCE)hInstance); // 傳 exe 的模塊句柄不是 dll 的 CefSettings settings; settings.no_sandbox true; // 老工程常帶第三方注入關(guān)沙箱最省事 settings.multi_threaded_message_loop false; // 關(guān)鍵消息泵交給 MFC 主線程 settings.windowless_rendering_enabled false; // 走原生子窗口不做離屏 settings.log_severity LOGSEVERITY_INFO; settings.remote_debugging_port debugPort; // 8321方便開 DevTools 查 JS CefString(settings.locale) zh-CN; if (cacheDir) CefString(settings.cache_path) cacheDir; if (logFile) CefString(settings.log_file) logFile; if (subProcessPath) CefString(settings.browser_subprocess_path) subProcessPath; CefEnableHighDPISupport(); // 必須在 Initialize 之前 if (!CefInitialize(mainArgs, settings, nullptr, nullptr)) return -1; return 0; }settings.no_sandbox true這一行在老項目里幾乎是必選項因為很多上位機會加載加密狗驅(qū)動、注入式監(jiān)控模塊沙箱一起來子進程就直接被殺。代價是安全性下降內(nèi)網(wǎng)設備可以接受公網(wǎng)產(chǎn)品要重新評估。multi_threaded_message_loop false是整套方案的樞紐。設成 true 意味著 CEF 自己起一條 UI 線程跑CefRunMessageLoop()那條循環(huán)和 MFC 的CWinThread::Run()是兩條獨立的GetMessage循環(huán)誰先拿到消息全靠運氣MFC 的模態(tài)對話框、菜單、快捷鍵會大面積失靈。設成 false 后CEF 的所有 UI 線程工作都靠主線程主動調(diào)用CefDoMessageLoopWork()驅(qū)動控制權(quán)完全在 MFC 手上。編譯 wrapper 用官方二進制包自帶的 CMake 工程:: 在 cef_binary 的 cmake 目錄下注意必須是 Win32跟 VS2010 工程位寬一致 set CEF_ROOTD:\sdk\cef_binary_90_6_0_windows32 cmake -G Visual Studio 16 2019 -A Win32 -DCMAKE_BUILD_TYPERelease .. cmake --build . --config Release --target libcef_dll_wrapper-A Win32不能省。VS2010 的工程基本都是 x86拿 x64 的 wrapper 去鏈接會一路 LNK1112 / LNK2038。構(gòu)建完成后把libcef_dll_wrapper.lib和自己的mycef_bridge.dll一起放進輸出目錄。注意中間層 DLL 和 MFC 主程序的運行庫配置/MD 或 /MT不必一致但中間層內(nèi)部的 wrapper 和 bridge 必須一致否則CefRefPtr的引用計數(shù)會在兩個堆之間來回跑退出時必崩。2.3 VS2010 側(cè)工程配置只認自己的頭文件和導入庫VS2010 工程這邊要做的只有四件事全在項目屬性里。第一附加包含目錄加mycef_bridge.h所在路徑不要加 CEF 的include/。這一步是防止有人手滑#include cef_client.h加了就會觸發(fā)幾百行 C11 報錯把真正的問題淹掉。第二附加庫目錄指向mycef_bridge.lib附加依賴項寫mycef_bridge.lib。如果暫時沒有導入庫用LoadLibraryGetProcAddress也行只是函數(shù)指針表要自己維護。第三調(diào)試工作目錄設成 exe 輸出目錄并在生成后事件里把libcef.dll、icudtl.dat、*.pak、locales/、*.bin拷過去。CEF 的資源文件路徑是相對 exe 目錄找的用 VS 調(diào)試時工作目錄不對就會白屏。第四InitInstance最開始加子進程分流這一步漏了會直接導致渲染進程起不來BOOL CMyApp::InitInstance() { // 子進程分流必須放在任何 MFC 初始化之前 HINSTANCE hInst AfxGetInstanceHandle(); CefMainArgs mainArgs(hInst); // 中間層暴露一個探測函數(shù)返回 0 說明當前是子進程立刻退出 int exitCode MyCef_ExecuteProcess(hInst); if (exitCode 0) return FALSE; // ... 正常 MFC 初始化 ... return CWinApp::InitInstance(); }MyCef_ExecuteProcess內(nèi)部就是CefExecuteProcess(mainArgs, nullptr, nullptr)。這個函數(shù)會檢查命令行里的--typerenderer之類的參數(shù)是子進程就直接進 CEF 自己的循環(huán)返回時進程該退出了是主進程則返回 -1繼續(xù)往下走。子進程的 exe 路徑默認就是主 exe所以 CEF 會用同一個可執(zhí)行文件反復啟動自己。如果你的主 exe 名字被改過、或者裝在帶空格的路徑下就要顯式設browser_subprocess_path指向一個專門的subprocess.exe否則會出現(xiàn)「主窗口出來了但頁面永遠白屏」的經(jīng)典現(xiàn)象。3. 把瀏覽器窗口塞進 MFC窗口句柄、尺寸與消息泵中間層通了之后剩下的活是把瀏覽器子窗口掛到 MFC 的客戶區(qū)里并讓主線程的消息泵既伺候 MFC 又伺候 CEF。這一段出問題的表現(xiàn)通常很直觀窗口位置不對、拖動時白屏、頁面點了沒反應。3.1 SetAsChild 與 CefWindowInfo 的父子關(guān)系CEF 在 Windows 上的默認渲染模式是原生子窗口CefWindowInfo::SetAsChild就是給內(nèi)核指定一個父 HWND 和一個初始矩形。這個父窗口通常取CView的m_hWnd或者對話框上預留的一個靜態(tài)控件。// bridge.cpp MYCEF_API int MyCef_CreateBrowser(void* parentHwnd, int x, int y, int w, int h, const char* urlUtf8) { if (!g_client) return -2; CefWindowInfo info; info.SetAsChild((HWND)parentHwnd, CefRect(x, y, w, h)); // 坐標相對父窗口客戶區(qū) CefBrowserSettings bs; bs.background_color 0xFFFFFFFF; // 白底避免加載中透出黑色 bs.javascript_access_clipboard STATE_DISABLED; CefRefPtrCefRequestContext ctx CefRequestContext::GetGlobalContext(); bool ok CefBrowserHost::CreateBrowser(info, g_client.get(), CefString(urlUtf8), bs, nullptr, ctx); return ok ? 0 : -3; }CefRect里的坐標是相對父窗口客戶區(qū)的不是屏幕坐標傳錯了瀏覽器窗口會跑到屏幕左上角。父窗口如果是對話框上的靜態(tài)控件記得把靜態(tài)控件的SS_NOTIFY打開、ID 設成非IDC_STATIC否則拿不到有效 HWND。瀏覽器創(chuàng)建是異步的CreateBrowser返回 true 只代表請求入隊成功。真正的 HWND 在CefLifeSpanHandler::OnAfterCreated里才拿得到void MyClient::OnAfterCreated(CefRefPtrCefBrowser browser) { m_browser browser; // 保存 CefRefPtr HWND child browser-GetHost()-GetWindowHandle(); // 此刻才是有效 HWND ::ShowWindow(child, SW_SHOW); }這個順序不能反。在CreateBrowser之后立刻GetWindowHandle()拿到的是 NULL后面所有::SetWindowPos都會靜默失敗表現(xiàn)出來就是「瀏覽器已經(jīng)加載完成但界面上什么都看不見」。3.2 消息循環(huán)選型CefDoMessageLoopWork 定時泵multi_threaded_message_loop false之后CEF 的內(nèi)部任務渲染合成、IPC 處理、定時器全都排隊等著被泵。泵的方式就是用 MFC 的SetTimer定期調(diào)CefDoMessageLoopWork()。// MainFrm.cpp int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) -1) return -1; MyCef_Init(AfxGetInstanceHandle(), nullptr, .\\cache, .\\cef.log, 8321); MyCef_CreateBrowser(m_viewHwnd, 0, 0, m_clientW, m_clientH, http://127.0.0.1/index.html); // 10~30ms 一次低于 10ms 會明顯吃 CPU高于 33ms 滾動會卡 SetTimer(TIMER_CEF_PUMP, 10, NULL); return 0; } void CMainFrame::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent TIMER_CEF_PUMP) { MyCef_DoMessageLoopWork(); // 內(nèi)部調(diào)用 CefDoMessageLoopWork() return; // 不要再往下傳避免重復處理 } CFrameWnd::OnTimer(nIDEvent); }定時器精度取 10ms 是個經(jīng)驗值。CEF 官方注釋里明確寫著CefDoMessageLoopWork調(diào)用過于頻繁會拖慢渲染線程而 33ms約 30fps在拖拽窗口時又會明顯掉幀。10~16ms 在多數(shù)工控機上能兼顧流暢度和 CPU 占用但如果目標機器是低功耗嵌入式主板建議先跑 33ms 看效果再往下調(diào)。還有一條更精細的路是external_message_pump true加CefBrowserProcessHandler::OnScheduleMessagePumpWork(int64 delay_ms)由 CEF 反過來告訴你「多久之后需要泵一次」這樣空閑時完全不占 CPU。缺點是回調(diào)發(fā)生在 CEF 內(nèi)部線程需要用PostMessage轉(zhuǎn)到主線程再泵多一層間接。項目對 CPU 占用敏感時可以換成這套。3.3 尺寸同步、DPI 與關(guān)閉時序父窗口大小變了瀏覽器子窗口不會自動跟。WM_SIZE里要做兩件事通知 CEF 尺寸變了以及真正SetWindowPos。void CMyView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); if (cx 0 || cy 0) return; MyCef_Resize(cx, cy); // 內(nèi)部browser-GetHost()-WasResized(); } // bridge.cpp 里的實現(xiàn) MYCEF_API void MyCef_Resize(int w, int h) { if (!g_browser) return; HWND hwnd g_browser-GetHost()-GetWindowHandle(); if (hwnd) ::SetWindowPos(hwnd, NULL, 0, 0, w, h, SWP_NOZORDER | SWP_NOACTIVATE); g_browser-GetHost()-WasResized(); // 通知內(nèi)核重新布局渲染表面 }SetWindowPos和WasResized兩個都要調(diào)。只調(diào)前者子窗口尺寸對了但渲染表面還是舊的頁面右側(cè)會出現(xiàn)一條沒刷新的黑邊只調(diào)后者渲染表面重排了但窗口還是老尺寸內(nèi)容會被裁掉。高 DPI 屏上還要在CefInitialize之前調(diào)CefEnableHighDPISupport()并且在 MFC 側(cè)的 manifest 里聲明dpiAware。兩邊不一致的話125% 縮放下瀏覽器子窗口會偏到右下角越拖越歪。關(guān)閉時序是最容易踩雷的地方正確順序是// 1. 主窗口 OnClose 里先讓瀏覽器自己關(guān) MyCef_CloseBrowser(); // browser-GetHost()-CloseBrowser(true)參數(shù) true 表示強制 // 2. 在 CefLifeSpanHandler::OnBeforeClose 里把 CefRefPtr 置空并停泵 void MyClient::OnBeforeClose(CefRefPtrCefBrowser browser) { ::KillTimer(g_mainHwnd, TIMER_CEF_PUMP); m_browser nullptr; // 最后一個引用在這里釋放 } // 3. MFC 退出前調(diào) CefShutdown() void CMyApp::CleanUp() { MyCef_Shutdown(); // 內(nèi)部 CefShutdown() CWinApp::CleanUp(); }CloseBrowser(true)的true表示不走onbeforeunload確認直接關(guān)。如果頁面里有未保存的表單需要攔截改傳false并在 JS 里監(jiān)聽beforeunload但老項目里這么做往往導致窗口關(guān)不掉用戶只能殺進程。4. JS 與 C 雙向調(diào)用V8Handler 與 MessageRouter 的邊界JS 調(diào) C 有兩種寫法很多人第一反應是CefV8Handler因為它寫起來最像「注冊一個函數(shù)」那么簡單。但它有個致命的進程邊界問題搞不清楚就會出現(xiàn)「代碼明明執(zhí)行了界面紋絲不動」。4.1 CefV8Handler 能做什么、不能做什么CefV8Handler是掛在 V8 上下文里的原生函數(shù)。在CefRenderProcessHandler::OnContextCreated里往全局對象上掛一個函數(shù)名頁面里就能window.nativeCall(...)直接調(diào)。void MyRenderApp::OnContextCreated(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, CefRefPtrCefV8Context context) { CefRefPtrCefV8Value global context-GetGlobal(); CefRefPtrCefV8Value fn CefV8Value::CreateFunction(nativeCall, new MyV8Handler()); global-SetValue(nativeCall, fn, V8_PROPERTY_ATTRIBUTE_NONE); } // V8 handler bool MyV8Handler::Execute(const CefString name, CefRefPtrCefV8Value object, const CefV8ValueList arguments, CefRefPtrCefV8Value retval, CefString exception) { if (name nativeCall arguments.size() 2) { std::string cmd arguments[0]-GetStringValue().ToString(); std::string payload arguments[1]-GetStringValue().ToString(); // 關(guān)鍵這段代碼跑在 renderer 進程不能碰 MFC 的 HWND CefRefPtrCefProcessMessage msg CefProcessMessage::Create(native_call); msg-GetArgumentList()-SetString(0, cmd); msg-GetArgumentList()-SetString(1, payload); CefRefPtrCefBrowser browser CefV8Context::GetCurrentContext()-GetBrowser(); browser-GetMainFrame()-SendProcessMessage(PID_BROWSER, msg); return true; } exception bad arguments; return false; }問題就出在那行注釋上。CEF 默認是多進程模型頁面 JS 在 renderer 子進程里跑Execute回調(diào)也在 renderer 進程的 V8 線程執(zhí)行。那一刻你手里只有CefRefPtrMFC 的窗口句柄、CWnd*、成員變量統(tǒng)統(tǒng)在另一個進程的地址空間里直接拿來用輕則無效重則崩潰。想在 UI 上生效就必須像上面那樣SendProcessMessage把消息打到 browser 進程再在CefClient::OnProcessMessageReceived里收bool MyClient::OnProcessMessageReceived(CefRefPtrCefBrowser browser, CefProcessId source_process, CefRefPtrCefProcessMessage message) { if (message-GetName() native_call) { std::string cmd message-GetArgumentList()-GetString(0).ToString(); std::string payload message-GetArgumentList()-GetString(1).ToString(); // 這里在 browser 進程的 UI 線程可以安全地把結(jié)果 PostMessage 給 MFC 窗口 ::PostMessage(g_mainHwnd, WM_NATIVE_CALL, (WPARAM)new std::string(cmd), (LPARAM)new std::string(payload)); return true; } return false; }這條鏈路能跑通但缺了「返回值」——Execute里沒法同步等到 browser 進程處理完再retval-SetString(...)。異步返回值要靠再發(fā)一條消息回 renderer 進程代碼量翻倍。所以只要涉及「調(diào)完要拿結(jié)果」就換下一條路。注意OnProcessMessageReceived的簽名在不同小版本之間有過增減早期版本沒有frame參數(shù)改版本時先看cef_client.h里的聲明別照抄網(wǎng)上的舊代碼。4.2 CefMessageRouter 打通 JS 到 MFC 的完整鏈路CefMessageRouter是 CEF 自帶的請求-響應通道既解決跨進程又自帶回調(diào)和取消機制。它分兩部分renderer 側(cè)負責在頁面里注入cefQuery函數(shù)browser 側(cè)負責收請求并回調(diào)業(yè)務代碼。browser 進程側(cè)建 router// MyClient 構(gòu)造時 CefMessageRouterConfig config; config.js_query_function cefQuery; // 頁面里調(diào)用的函數(shù)名 config.js_cancel_function cefQueryCancel; // 取消函數(shù)名 m_router CefMessageRouterBrowserSide::Create(config); m_router-AddHandler(new MyQueryHandler(), true); // true 表示第一個匹配的 handler 生效然后在CefClient的幾個回調(diào)里逐一轉(zhuǎn)發(fā)少轉(zhuǎn)發(fā)一個查詢就可能永遠不回調(diào)bool MyClient::OnProcessMessageReceived(CefRefPtrCefBrowser browser, CefProcessId source_process, CefRefPtrCefProcessMessage message) { return m_router-OnProcessMessageReceived(browser, message); } bool MyClient::OnBeforeBrowse(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, CefRefPtrCefRequest request, bool user_gesture, bool is_redirect) { m_router-OnBeforeBrowse(browser, frame); // 頁面跳轉(zhuǎn)時清掉掛起的查詢 return false; } void MyClient::OnRenderProcessTerminated(CefRefPtrCefBrowser browser, TerminationStatus status) { m_router-OnRenderProcessTerminated(browser); // 渲染進程崩了要重置狀態(tài) }renderer 側(cè)同樣要轉(zhuǎn)發(fā)一次bool MyRenderApp::OnProcessMessageReceived(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, CefProcessId source_process, CefRefPtrCefProcessMessage message) { return m_renderRouter-OnProcessMessageReceived(browser, frame, source_process, message); }業(yè)務 handler 才是真正干活的class MyQueryHandler : public CefMessageRouterBrowserSide::Handler { public: bool OnQuery(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, int64 query_id, const CefString request, bool persistent, CefRefPtrCallback callback) override { std::string req request.ToString(); // 建議前端統(tǒng)一傳 JSON 字符串 std::string cmd, data; if (!ParseJson(req, cmd, data)) { callback-Failure(-1, bad json); return true; } std::string result; bool ok DispatchToMfc(cmd, data, result); // 這里可以直接調(diào) MFC 成員 if (ok) callback-Success(result); else callback-Failure(-2, handler failed); return true; } };OnQuery跑在 browser 進程的 UI 線程上DispatchToMfc里可以直接訪問全局的CMainFrame*、調(diào)UpdateData、往數(shù)據(jù)庫寫記錄沒有任何跨進程問題。返回值通過callback-Success(...)同步回給頁面的onSuccess。persistent參數(shù)決定這是一次性查詢還是長連接。傳 true 時Callback不釋放可以多次Success適合做「C 主動推送狀態(tài)」傳 false默認就是一問一答用完即焚。前端調(diào)用長這樣注意request里盡量別塞裸字符串統(tǒng)一 JSONfunction callNative(cmd, data) { return new Promise(function (resolve, reject) { window.cefQuery({ request: JSON.stringify({ cmd: cmd, data: data }), onSuccess: function (response) { try { resolve(JSON.parse(response)); } catch (e) { resolve(response); } }, onFailure: function (code, msg) { reject(new Error(code : msg)); } }); }); } // 用法 callNative(readConfig, { key: baudRate }).then(function (r) { console.log(baudRate , r.value); });4.3 C 主動調(diào) JSJSON 序列化與線程約束反方向簡單一些CefFrame::ExecuteJavaScript就夠但有兩個約束必須遵守。第一只能在 browser 進程的 UI 線程調(diào)用。browser-GetMainFrame()在 renderer 進程里返回的是空殼調(diào)了不報錯但什么也不會發(fā)生。第二參數(shù)必須序列化成 JSON 再嵌進腳本字符串直接拼字符串是血淚經(jīng)驗的重災區(qū)void CallJs(const std::string eventName, const std::string jsonPayload) { if (!g_browser) return; CefRefPtrCefFrame frame g_browser-GetMainFrame(); if (!frame) return; // 轉(zhuǎn)義單引號避免 JSON 里的 把腳本字符串提前截斷 std::string safe jsonPayload; ReplaceAll(safe, \\, \\\\); ReplaceAll(safe, , \\); ReplaceAll(safe, \n, \\n); std::string js if(window.onNativeEvent){window.onNativeEvent( eventName , JSON.parse( safe ));}; frame-ExecuteJavaScript(js, frame-GetURL(), 0); }ExecuteJavaScript的第二個參數(shù)是腳本來源 URL用于 DevTools 里定位錯誤傳frame-GetURL()就能在 Sources 面板里看到這段注入代碼的出處第三個參數(shù)是起始行號一般填 0。中文參數(shù)最容易翻車。CefString在 Windows 內(nèi)部是 UTF-16ExecuteJavaScript接受的CefString用 UTF-8 構(gòu)造時要注意源字符串本身的編碼。如果 MFC 那邊拿到的是CString寬字符先WideCharToMultiByte(CP_UTF8, ...)再交出去中間任何一次用CP_ACP轉(zhuǎn)換都會把中文變成問號。如果 C 側(cè)是高頻推送比如每秒幾十幀的設備狀態(tài)ExecuteJavaScript會累積大量待執(zhí)行腳本頁面直接卡死。常見做法是在 C 側(cè)做節(jié)流攢 100ms 一次性推一個數(shù)組過去或者干脆走cefQuery的persistent模式反向給頁面發(fā)。5. 避坑與排查這套組合最容易翻車的五個點VS2010 CEF 90 這個組合橫跨兩代編譯器和十幾年的框架演進出問題的表現(xiàn)往往和真實原因隔著好幾層。下面五條是按我修過的實際現(xiàn)象排序的。5.1 啟動階段白屏、閃退、子進程缺失現(xiàn)象一主窗口出來了瀏覽器區(qū)域一片白日志里出現(xiàn)Failed to create a valid render process或The CEF renderer process is not running。原因基本鎖定在子進程分流。CefExecuteProcess沒有在InitInstance最開頭調(diào)用或者調(diào)用了但返回值處理錯了——子進程跑完CefExecuteProcess之后必須立刻返回不能再往下走 MFC 的初始化流程否則子進程會把自己當成主程序去加載主窗口、去讀配置文件然后在某個空指針上崩掉。解決方式是把分流代碼提到InitInstance的第一行并且用return FALSE而不是return exitCode。同時確認browser_subprocess_path指向的 exe 確實存在、路徑里沒有會被 shell 解釋的字符。排查時打開settings.log_severity LOGSEVERITY_INFO并設log_file子進程啟動的每一行參數(shù)都會寫進日志?,F(xiàn)象二程序啟動幾百毫秒后直接退出Windows 事件查看器里記錄0xc0000135找不到 DLL。原因不在 libcef.dll而在它依賴的 VC 運行庫。CEF 90 的 Windows 二進制是 VS2019 編的依賴vcruntime140.dll/msvcp140.dll。目標機器上只裝了 VS2010 的運行庫msvcr100.dlllibcef.dll 加載時就會失敗。解決是打包時把vcruntime140.dll、msvcp140.dll、vcruntime140_1.dll一起放進 exe 目錄或者給裝機腳本加一步 VC 2015-2022 運行庫安裝。這一步在內(nèi)網(wǎng)離線部署時特別容易被漏掉因為開發(fā)機上通常早裝過了。5.2 運行與退出階段查詢卡死、關(guān)窗崩潰、進程殘留現(xiàn)象三頁面里點了按鈕cefQuery的onSuccess和onFailure都不觸發(fā)控制臺沒有任何報錯頁面就像什么也沒發(fā)生。原因通常是有多個網(wǎng)絡請求同時發(fā)起其中某個 handler 返回了false且沒有調(diào)用callback。OnQuery的返回值語義很容易被誤解返回true表示「這個 handler 認領了這次查詢一定會調(diào) callback」返回false表示「我不處理交給下一個 handler」。如果一個 handler 既沒調(diào) callback 又返回了true路由就會一直等著后續(xù)查詢也全部排在它后面。排查手法是在OnQuery入口打一行日志、在每個分支打一行日志確認哪條路徑?jīng)]有落到Success或Failure上。另一個高發(fā)點是OnBeforeBrowse忘了轉(zhuǎn)發(fā)給 router頁面一旦發(fā)生跳轉(zhuǎn)之前掛起的查詢就變成了孤兒?,F(xiàn)象四點了主窗口的關(guān)閉按鈕界面消失了但任務管理器里進程還掛著再啟動一個實例就報端口占用或緩存目錄被鎖。原因是CefShutdown沒有等到所有瀏覽器真正關(guān)閉就被調(diào)用或者根本沒調(diào)。CloseBrowser(true)只是發(fā)起關(guān)閉請求OnBeforeClose之后內(nèi)核才會釋放資源。如果 MFC 的OnClose里直接PostQuitMessage消息循環(huán)停了CEF 的關(guān)閉流程永遠走不完進程自然退不掉。解決順序是OnClose里調(diào)CloseBrowser(true)→ 在OnBeforeClose里停定時器、置空CefRefPtr→ 再讓窗口銷毀 → 在CWinApp::CleanUp里調(diào)CefShutdown()。中間可以用一個標志位攔住重復關(guān)閉防止用戶連點。現(xiàn)象五程序退出時偶爾彈「內(nèi)存不能為 written」崩潰棧落在libcef.dll里調(diào)試符號一塌糊涂。典型原因是中間層 DLL 的導出函數(shù)返回了 C 對象或者CefRefPtr跨越了 DLL 邊界。兩套運行庫各自維護自己的堆一個進程里new出來的對象在另一個堆里delete堆管理器直接判定越界。檢查方式是看mycef_bridge.h里有沒有出現(xiàn)std::string、class、CefRefPtr這些類型。有就改成const char*intvoid*字符串在邊界上按 UTF-8 拷貝一份。另一條隱蔽路徑是CefRefPtr作為靜態(tài)變量的初始化順序問題——DLL 卸載時靜態(tài)對象析構(gòu)此時 libcef 可能已經(jīng) Shutdown引用計數(shù)操作會踩到已釋放的內(nèi)存。把全局CefRefPtr改成一個裸指針CefRefPtr*在OnAfterCreated里new、在OnBeforeClose里delete順序可控得多。6. 交付前的自檢把 JS 橋接做成可回歸的驗證用例代碼跑通和能交付是兩件事。這套組合涉及兩個進程、兩套運行庫、三層調(diào)用邊界靠手工點幾下確認「看著能用」遲早出事。我一般會在工程里放一個selftest.html把橋接的每條路徑都覆蓋一遍裝到目標機器上先跑這個頁面。頁面里做三件事。第一探測 CEF 版本和進程 ID確認內(nèi)核真的起來了// selftest.html —— 橋接自檢頁 (async function () { const info await callNative(sys.info, {}); console.log(cef_version info.cef_version); // 形如 90.6.0gc... console.log(render_pid info.render_pid); // 與主進程 pid 不同即為多進程正常 document.getElementById(ver).textContent info.cef_version; })();第二覆蓋四類邊界數(shù)據(jù)空字符串、含單引號雙引號的字符串、中文、超過 1KB 的長字符串。每一類都做一次往返比對前后是否一致。中文這一項要專門盯著因為所有亂碼都出在CP_ACP和CP_UTF8混用上正常輸入法打幾個字就能暴露。第三驗證異常路徑調(diào)一個不存在的命令確認onFailure收到的是自定義錯誤碼而不是超時連續(xù)發(fā) 100 個查詢確認全部有回調(diào)且沒有互相串號。最后一項能揪出 handler 返回值寫錯的隱患比看代碼靠譜。參數(shù)上還有兩個容易忽略的檢查點。remote_debugging_port在發(fā)布版本里要關(guān)掉或者綁定到127.0.0.1否則同網(wǎng)段任何人都能連上 DevTools 執(zhí)行任意腳本cache_path要指向可寫的用戶目錄而不是 exe 目錄裝在Program Files下時寫緩存會失敗頁面表現(xiàn)是本地存儲全丟、登錄態(tài)每次重開都掉。還有個小技巧值得加進自檢在OnBeforeClose里主動KillTimer并且把 Do本文還有配套的精品資源點擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
五区毛片七区毛片| 99热这里都是精品| 天天射影院| 深爱五月日韩| 五月 丁香 欧美| 免费观看日韩成人av| 九九热免费视频| 丁香久久AV| 日本欧美啪啪| 99热8在线| 成人在线精品| 婷婷五月丁香91| 亚洲无码成人性爰网| 久久刺激网| 5月丁香综合图区| 亚州色婷婷| 色综合开心五月深爱五月| 五月亭亭色| 99久久网站| 免费在线观看av网站| 五月丁香激情婷婷| 久久婷婷五月天激情四射| 国产Va视频| 丁香花成人区| 婷婷色在线播放| 99在线精品免费视频| 日本视频99| 性99网站| 六月丁香色婷婷| 五月丁香婷成人网| 色婷婷深爱五月| 99欧州偷拍视频| 丁香社92视频| 精品久久婷婷| 99热新网址| 成人 九九九九| 亚洲岛国电影| se.久久视频在线观看| 99思思在线视频| 97碰碰碰| 成人婷99最新| 激情深爱综合| 婷婷狠狠五月综合| 色五狠狠| 久色| 超碰成人电影| 久久97| 91超碰人人操| 久九男女天堂| 日韩小视频在线99| 91chinese在线| 激情綜合網址| 丁香五月在线视频| 久久久久人妻精选| 色99色| 五月丁香婷婷AV| 人妻操逼视频| 色色射| 日韩999| 色色色色色色色色色色色色色97| 亚洲一级AV在线免费播放| 激情精品久久| 九九碰九九爱97超碰| 人人干99| 婷婷激情五月综合丁| 五月丁香网中文字幕| 丁香五月天欧美| 五月丁香婷婷激激激综合网色播| 亚洲人人操| 色色日本欧美| 国产亚洲成AV人片在线观黄桃| 国产又粗又大又爽又黄| 婷婷激情综合色五月久久91| 激情综合五月| 成人性爱无码| 日韩操人| 色综合婷婷99| 四色永久成人网站| 99热这里只有免费精品| 久久婷婷网| 特黄三级片| 激情五月六月婷婷综合啪啪| 99色在线| 精品一区久热| .操區COm| 噜噜噜久久| 另类图片天天影视在线观看| 91在线观看九区| 成人在线视频一区| 久久奄也去色色网站| 伊人狠狠干| 性热视频99精品| 开心激情网五月天| www.激情com| 五月婷婷无码| 少妇性按摩无码中文A片| 九九五月天| 开心五月天激情网| 91九色国产在线| 99热这只有| 五月婷婷色五月| 人人干av| 97视频91| www.色婷婷.com| 丁香五月天堂| 亚洲天堂啪啪| 激情五月天com| 国产精产国品一二三在观看| 色色五月天网站| 五月婷婷深爱六月| 色婷婷成人做爰A片免费看网站| 99丝袜精品视频网站| AV电影在线播放| 国语精品探花| 日韩av手机在线观看| 婷婷色在线播放| 激情校园 亚洲| 亚洲天堂爱爱| 五月丁香六月综合基地| 26UUU欧美激情一区二区| 99热超碰| 亚洲精99| JAPANRCEP老熟妇乱子伦视频| 五月丁香久| 六月婷婷九月丁香亚洲综合| 五月婷婷玖玖综合玖玖爱| 99,色| 激情久久肏屄视频| 大香蕉网站,大香蕉综合| 天天五月天综合网址| 欧美 日韩 人妻 高清 中文| 久热2025无码| 开心五月天激情网| 5月色亭亭视频| 天天狠天天叉| 丁香六月天AV| 性做爰1一7伦| 婷婷五月天美女视频| 图片区 小说区 区 亚洲五月 | A网在线欧洲| 色婷婷五月在线| 九月婷婷综合网| 五月天激情视频网站| 欧美成人精品A片免费一区99| 99热综合在线| 欧美三级巜人妻互换| 激情六月丁香综合| 伊人激情AV一区二区三区| 思恩热国产视频右线观看| 婷婷九月综合| 亚洲艹网| 五月丁香婷婷成人网| 看婷婷五月天网| 超碰人人草| 色情丁香五月婷婷精品| 亚洲超碰在线| 久久99成人性爱高清视频| .精品久久久麻豆国产精品| 色五月激情问网站| 色操综合| 色哟哟精品| 超碰色婷婷| 99亚洲视频| 丁香九月综合激情| 婷婷导航| 伊人五月天在线| 美腿丝袜AV天堂网| 超碰免费在线| 成年人99热| 激情婷婷五月丁香啪啪啪| 婷婷五月花西瓜| 五月婷婷亚洲色图| 五月丁香六月激情欧美综合| 亚洲五月丁| 久久婷婷五月综合色欧美| 婷婷深爱网| 超碰免费观看| 激情五月婷婷综合| 色综合综合网| 色婷久久| 嫩草哈哈操| 99热这里只有精品免费观看| 久久99热这里只有精品首| 99热伊人| 极品另类| 天天色,天天操,天天射| 强伦轩人妻一区二区电影| www.色五月| 青青操绿aaa一区日v| 无码视频国内精品久久久| 五月丁香另类网| 婷婷丁香社区| 色噜噜狠狠色综无码久久合欧美| 婷婷六月色| 丁香综合婷婷开心激情网| 一起草AV| 九九香蕉网| 婷婷激情区| 婷婷色片| 丁香五月激动深爱欧美| www.色五月| 激情五月婷婷综合视频| 成人短视频在线| 强辱丰满人妻HD中文字幕| 五月丁香综合网| 99开心五月五月丁香激情| 日韩在线观看网址| 亚洲综合激情五月久久| 婷婷综合激情| 五月婷婷手机在线| 五月综合婷婷网| 综合www色| 一本道在线电影| 婷婷五月天电影网| 婷婷五月免费在线| 激情婷婷五月天伊人在线观看| 熟女国产在线一区二区三区四区| 免费视频WWW在线观看网站| 六月丁香五月婷婷| 日韩99精品| 俺来也综合网精品一区| 91超级碰在线视频| 视频1区2区| 亚洲精品又粗又大又爽A片 | 亚洲综合99| 99精品在线观看视频| 包操45分钟网站| 99精品国产在热久久婷婷| 另类小说五月天| 婷婷五月香蕉| 成人AV在线电影| 99视频这里只有精品10| 天天摸人人摸| 夜夜爽天天日| 婷婷五月天综合色| 开心五月色婷婷综合开心网| 五月天婷爱综合| 99操| 99热精在线九九久久保| 包操45分钟网站| 大香蕉五月天婷婷| 99亚色色色| 久久久性爱网| 国产精品久久..4399| 97人人看一| 日美三级| 久久新地此| 精品国产a| 欧美熟女视频 色婷婷| 无码激情AAAAA片-区区| 热思思九九| 少妇AB又爽又紧无码网站| 激情综合网五月天| 午夜天堂一区人妻| 婷婷丁香九色| 亚洲视频久久| 丁香九月婷| 91色操| 日本色99| 婷婷色五月综合丁香| 伊人五月天综合网| 五月丁香六月激情网| 极品 少妇 内射| 色婷婷成人在线| 视频免费精品免费精品免费精品免费精品免费精品免费精品免费99 | 另类图片五月天婷婷| 日本97人人| 超碰97在线观看免费| 亚洲精品a成人在线播放| 日木WWW视频| 91九色最新视频| 成人 在线观看国产| 中文字幕日本最新乱码视频| 久热在线观看视频9| AV在线不卡网站| 婷婷色情五月| 五月婷婷丁香啪啪| VfJxEwPH| 久热伊人| 亚洲成人丁香花| 久久蜜臀婷婷| 淫视馆aV二区一区| 色综合网综合| 中文字幕视频在线播放| 日韩少妇内射免费播放| 91好好热日本在线| 天堂婷婷五月在线| 成人丁香婷婷| 五月天久久久| 十区av| 色五月色五天色情网| 五月综合亚洲色| 亚洲狠狠婷婷综合久久久| 色五月成人在线| 日本天天操| 91 九色 熟女| 久久久久久久久久久jjjj| 丁香婷婷性久久| 婷婷色色五月| 人妻精品一区二区三区| 无码少妇高潮喷水A片免费| 96精品国产综合久久久久久| 色99网| 可以免费观看的av| 亚洲无码黄色| 欧洲高清免费久久| 久久五月天婷婷| 激情综合色婷婷啪啪五月天| 那里有AV网址| WWW,五月| 99啪视频在线观看| 久久成人综合五月天| 色五月av| 欧美一级a | 六月色婷婷综合影视| 色婷婷XXXXX| 六月久久狠狠| 热91久| 亚洲在线操| www.热99热| 婷婷涩五月| 亚洲激情四谢| 丁香五月aV| 色狠狠色| 婷婷五月综合久久中文字幕| 五月精品| 久久九九re热| 99日这里只有精品| 婷婷五月色综合香五月| 极品人妻videosss人妻| 色色色综合网| 色六月天天激情综合网| www.超碰| 婷婷久久综合久| 丁香五月婷婷在线观看| 人人操人人妻| 丰满女老板BD高清A片| 性爱人人网| 丁香五月激情澎湃一区| 午夜少妇在线观看视频| 色之综合网| 久久激情五月天| 大香婷婷| 性按摩玩人妻HD中文字幕| 99热免费精品| 五月天网站亭亭| 国产成人精品一区二区三区视频| www,8050,午夜三级| 五月综合色| www.久久色.com| 五月精品免费XXX| 俺也去色| 丁香五月婷婷骚视屏| 中文字幕无码人妻少妇免费视频| 亚洲婷婷丁香五月天激情小说| 亚洲操操操| 99黄色性生活| 五月婷婷综合在线| 26uuuavcom| 99色在线| 欧美69久成人做爰视频| 色婷婷婷综合五月天| 色5月婷婷| 亚洲精品乱码久久久久久按摩观| 激情色播| 五月天社区狠狠| BlACKEDRAW视频一区二区| 色婷婷九月综合| 国产在线网| yazhouzonghesese| 久久一级免费黄色片| 婷婷五月天在线综合| 9 9热这里有精品| 日本狠狠色| 成人电影在线免费试看| 大香蕉久| 操逼棍操逼| 欧美日韩精品一区二区三区钱| VfJxEwPH| 亚洲美女高潮久久久久久69| A久久| 很操日本7| 五月天小说激情| 久热这里只有精品6| 涩九九九九| 大香蕉手机视频| 热久久思思热思思| 丁香五夜激情四射夜夜夜| 色欲一二三| 五月天丁香| 另类小说五月天| 色婷婷六月| 一区二区三区四区无码| 久久精品99久久| 99人人干| 五月婷婷丁香大陆免费| 色婷五月丁香久亚洲| 久久久五月天婷婷| 九九热在线视频观看| 这里只有精9| 97涩婷婷婷婷基地| 综合激情站| 青青草日本亚洲| 啪啪操超碰| 91蜜桃婷婷狠狠久久综合9色| 丁香欧美| 五月婷婷干干干| 99在线视频观看| av在线观看网站| 婷婷丁香午夜综合影视| 日韩淑女人妻luan伦激情精品一区二| 亚洲妇女熟BBW| 思思精品视频| 伊人在线婷婷草| 婷婷五月综合啪| 日韩成人精品中文字幕| 丁香婷婷五月六月久久| 99青青草| 白天AV月月| 婷婷九月亚洲| 操操熟女| 亚洲成人影视在线| 丁香五月影院| 久久精典| 六月色婷婷| 激情婷婷五月色| 五月激情视频| 丁香婷婷色九月| 狠狠爱青青草| 欧美顶级少妇做爰HD| 久久综合丁香| 天天做天天爱| 五月天激情小说欧美激情| 婷婷天天舔| 变态另类9| 91女人18毛片水多国产| 五月婷婷久久大片| 色五月激情五月| 久久九色| 99ri在线| 婷婷五月丁香基地| 九九久久精品| 狠狠干婷婷| 久婷五月| 五月丁香网站| 射久久丁香五月| 日日夜夜爽爽| 六月色国内综合| 成人色站,在线视频,看片-SS1AV| 欧美成性色| 亚洲操逼片| 操逼巨乳91| 九月婷婷综合色干| 五月天另类小说久久小说网| 欧洲综合一区| 丁香五月激情啪啪综合| 丁香五月天天久久综合小说| 大香蕉色婷婷伊人在线| 激情综合网激情五月婷婷| 成人无码精品1区2区3区免费看| 思思热视频在线| 九九热黄色| 成人片在线播放| 日本高清久| 五月婷婷激情性爱| 婷婷久草| 中文字幕无码人妻少妇免费视频| 日日干四虎| 久久性爱99国产| 色婷婷在线电影| 全部老头和老太XXXXX| 粉嫩AV久久一区二区三区| 精国产品一区二区三区A片| 亚洲无码99| 涩涩五月天| 国产精产国品一二三在观看| 超碰只有精品在线| 青青色com久久| 久久五月天激情婷婷| 色很久综合| 射琪琪| 久热69| 婷婷色播婷婷| 五月激情网五月综合网| 噜噜精品| 99热这里只有精品免费| www.9操| 久碰久| 五月婷在线影院| 综合五月婷婷| 人人操超踫| 五月天婷婷色综合| 97色色色| 综合久久8| 97在线视频人妻九色| 69热在线| 激情深爱五月| 色色色色色色网| www.9操| 色色色色色五月| 天天开心天天色| 色婷婷AV五月天| 亚洲日日日| 大香网伊人久久综合| 性av| 色婷婷免费观看| 天色综合网站| 殴美日比视频| 九久久九精品视频| 一起草av| 久久婷婷五月天蜜桃| 99精品在线观看| 色综合激情图区| 香蕉大综综综合久久| 久久五月天合网| 99热在线这里| 婷婷97狠狠成人网站| 久久九九re热| 天天激情夜夜干| 狠狠干狠狠干| www.99.色| 精品婷婷| 婷婷五月天亚洲| 久热大香蕉| 色婷婷玖玖影院| 伦乱美欧| 中文无码婷婷| 久操人| 五月天色综合服务平台| 久热无码| 五月激情网站| 五月婷婷激情综合网 | 婷婷久久综| http://www.com久久久精品一区| 欧美日综合| 成人五月天视频| 久久久人妻人伦| 五月激情六月婷婷| 日韩色色色色| 色婷婷国色天香综合| 久碰婷婷视频| 精品一区二区三区三区| 国产成人va在线| 狠狠五月天| 九九自拍网| 国产午夜一区二区三区| 午夜微拍福利| 人人做人人看人人摸| 激情深爱五月天| 99在线免费视频| 婷婷丁香五月激情| 97自拍视频网| 丁香成人色情五月天| 99热只有| 丁香五月婷婷呀| 五月天另类小说| 五月激情婷婷综合| 亚洲婷婷91丁香| 久久9热| 色色色色热| 9久热在线精品| 天天干天天操| 一级性爱大片| 这里只有精品视频| 91丨九色丨熟女丰满| 久久婷婷五月综合| 99热99久久| 色色色地址| 久婷久婷激情肉| 婷婷六月色开 | 亚洲爆乳无码精品AAA片蜜桃| 97干在线| 国产精品18久久久| 亚洲综合丁香婷婷六月天| 五月婷婷激情综合| 婷婷激情五月综合在线视频| 最新国产AV| 五月婷婷综合久久| 五月天停婷基地| 第四色五月婷婷| 久久久久亚洲AV无码网影音先锋| 任你搞网站| 五月丁香综合中文| 国产成人+综合亚洲+天堂| 九九AV| WWW·天天操·视频?| 伊人91| 第四色婷婷五月| 99干在线视频| 日本操碰碰| 丁香色六月| 精品无码久久久久久久久| 99色在线观看| 丁香六月婷婷综合啪啪| 色久天| 色月视频| 99久久五月丁香野外| 91欧美日韩综合| 操操操av| 亚洲AVwwwwwww| 99啪啪视频| 五月天久久婷婷婷| 色五月中文字幕| 婷婷六月久久综合导航| 精品成人无码A片观看香草视频 | 99九九在线| 99激情| 99久久九九| 96精品久久久久久久久| 91男女视频在线观看| 久久婷婷五月综合| a网站免费观看| 九九热手机在线视频| 五月丁香久久综合色| 五月丁香色婷婷| 婷婷情色激情| 激情五月深爱五月| 光棍影院日韩精品| 无码激情AAAAA片-区区| 五月婷婷狠狠干| 色五月婷婷在线视频| 九九99在线| 婷婷五月丁香五月| 五月丁香大相交| 日韩AV色色色| 亚洲色五月| 五月天婷婷激情四射综合| 日日夜夜婷婷| 婷婷久久综合| 人人做天天爱| ...婷婷国产成人亚洲日韩| 日韩精品电影| 97超碰免费超级在线观看| 99精品在线观看视频| 亚洲天堂AAA| 黄网免费看| AV亚洲在线| 五月婷婷啪啪| 99九无网码| 五月丁香六月婷婷婷婷| 五月天激情偷拍| 久久总和99| 婷婷WWW久久| 五月天色狠狠| 99精品视频偷拍| 99热伊人综合| 激情操逼婷婷| 中文幕无线码中文字蜜桃| 天天操B| 裸体美女丁香五月天。| 五月情涩综合婷婷| 五月婷丁香在线视频在线| 东京热免费视频| 婷婷久久内射| 超碰中文字幕在线| 丁香六月亚洲| www.婷婷五月.com| 久综合4| 亚洲熟妇AV乱码在线观看| 亚洲精品午夜国产va久久成人| 五月婷婷视频| 免费亚洲婷婷| 爱婷婷都市激情| 日日夜夜天天综合| 99色色色色| 婷婷干五月综合在线播放| 久久婷婷五月激情网站| 色色色.com| 丁香五月婷婷成人综合| 五月婷婷 六月丁香| 婷婷激情五月天7| 日本老女人黄页在线播放| 色婷婷欧美| 色色色国产| 最新色色五月天| 亚洲天堂大香蕉| 五月婷婷久久大香蕉| 色婷婷啪啪啪啪啪啪| 久色88| 久久精品99久久久久久| 色综合区| 丁香五月天天| 婷婷基地五月色| 日本成人小说婷婷六月| 色情五月停停丁香| 五月天久久网站| 亚洲另类婷婷综合| 这里只有精品久久| 99久久精品免费精品国产_国产精品久久久久久_国产在线|日韩_久久国产精品电影 | 丁香五月影院| 日本天天综合| 亚洲国产色色| 婷婷色导航| 91超碰在线观看| 99激情视频| 黄桃AV无码免费一区二区三区| 99精品国产在热久久| 亚洲成人网址在线观看| 婷婷五月天久久综合88| 五月婷婷久久综合| 亚洲日韩26uuu| 丁香五月婷中字幕| 五月婷婷久久久| 天天操夜夜操| 色婷婷成人久久| 99色视频在线观看最新| 99成人精品六| 爱草人视频| 久久激情视频| 色五月噜噜| 91综合国免费久入| 人人操A| 99综合自拍| 亚洲日韩一页精品发布| 九九久久免费视频44| 激情五月天色| 色五月婷婷色五月| 五月激情影视| 玖玖玖婷婷婷| 九九成人高清视频| 天天摸天天透天天舔| 97色色色| 丁香五月九九| 九九99视频精品| 亚洲国产精品VA在线看黑人| 五月天开心网| 天堂中文国产| 五月婷婷网站| 国产日韩欧美性爱| 青青草原伊人网| 丁香五月骚喷水视频| 9热精品| 五月婷婷操操| 思思热闹这里只有精品| 狠狠色五月天| 婷婷丁香五月天之开心少妇| 久久丁香五月综合六月激情红杏视频| 九九免费视频| 99久久国产宗和精品1上映| 超碰91人人操| 天天天综合网| 蜜桃婷婷丁香综合久久开心亚洲| www.99色| 大香蕉五月婷婷| 99热这里只要精品免费| 粉嫩AV久久一区二区三区| 人人操人人操919999| 久久久久久五月天| 疯狂做受XXXX高潮A片动画| 久久人人超| 六月色播| 丁香色色五月| 丁香五月综合在线播放| 大香蕉综合网| 色婷婷久久| 久久婷婷五月天激情四射| 大香久久综合网| 99精彩视频在线观看| 九九激情| 婷婷色导航| √天堂资源在线人妻熟女| 99热观看| 无码任你操| 91丨九色丨国产| 我爱va亚洲va52| 少妇人妻人伦A片| 亚洲五月天色| 99视频在线精品免费观看2| www.97碰碰com| 99无码| 九九综合网色全集 | 丁香婷婷六月激情综合| 成人综合网站| 免费精品66| 婷婷丁香六月| anquye伊人| 婷婷中文字幕| 成人片久久网站| 久久亚洲婷婷| 五月视频日本免费观看| 97色吧| 丁香5月啪啪| 午夜天天精品视频| 婷婷丁香综合成人| 野外99热| 婷婷欧美激情综合| 久激情网| 天天日日夜夜| 色婷婷五月天天天天天天天天天| 98国产精品综合一区二区三区| 六月香五月婷| 色综合久久久综合久久网| 思思w99| 亚洲日本三级片| 精品久久艹| 激情九月天天天天婷婷| 4399成人黄A片| 婷婷欧美偷拍综合| 91久久精品国产91性色TV| 青草激情在线| 97久久五月丁香婷婷| 99re视频在线播放| 开心五月天私房婷婷| 国产精品久久久久久妇女6080| 六月婷婷色宗合| 九 九九九AV| 亚洲无码11| 欧美在线视频99| 拍真实国产伦偷精品| 五月丁香六月综合激情网| 九九久99免费视频| 五月色丁香| 国产亚洲色婷婷99精品| 天天综合天综合久久网| 六月色婷婷| 日韩色色网| 丁香五月天久久| 激情五月天婷婷| 九九九精品视频免费观看| 日韩黄色中文字幕| 91九色精品| 99热99热在线观看| 色色丁香色五月| 狠狠操狠狠操AV| 久久婷婷五月综合色丁香| 婷婷网影院| 五月婷在线| 99热亚洲精品| 如何安全看伊人婷婷| 五月婷婷电影院| 玖玖综合玖玖| 五月婷婷六月丁香| 久热只有这里精品| 在线色色| 丁香婷婷五月综合欧美另类| www.色婷婷| 狠狠插日日干撸| 久久综合九九| 亚洲天堂九九九| 99热在线播放| 五月丁香成人小说| 欧美韩日AAA网站| 九月丁香婷婷| 无码 色| 丁香六月婷婷综合欧美| 亚洲日本韩国| 国产在线中文字幕| 亚洲视频伍月婷婷| 99热久久这里只有精品| 婷婷五月天激情电影| 苗黎美女四级成人版一级二级毛片| 久热91精品| 性天天中文网| 4399在线观看免费高清电视剧| 婷婷伊人綜合| 久久婷婷丁香花综合网| 五月激情六月丁香| 婷婷婷久久久| 丁香六月婷婷综合啪啪| 色婷婷婷婷成人网| 六月婷婷色综合| 热久69| 婷婷丁香大香蕉| 图片区 小说区 区 亚洲五月| 九九热九九| 五月婷婷丁香五月 | 99热这| 色婷婷激情视频| 99 频99热国里只有精品| 啪啪综合| 182TV大香蕉| 五月亭久久无码视频| 99在线视频操999| 欧美性猛交99久久久久99按摩| 综合五月婷婷| 91日韩在线| 丁香大香蕉| 亚州操操| 热热99爱爱| 97色精品视频| 丁香六月婷婷色XXXX| 亚洲精品V天堂中文字幕| 日本色婷婷| 久久久久人妻精品| 综合色播| 婷婷综合网站| 操一区| 国产成人综合网| AV性爱在线| 六月婷婷色| 开心激情站| 激情综合五| 久久思思热| 无遮挡国产高潮视频免费观看| 可以看的av| 六月丁丁香| 粉嫩AV久久一区二区三区| 91操人| 熟女人妻视频| 色图亚洲91| 久久婷婷网址| 丁香色影院| 岛国操B不卡在线| 射琪琪| 丁香六月色婷婷| 丁香五月天无码AV| 五月视频日本免费观看| 天天狠狠色噜噜| 性生活视频98791| 色五月天成人| 99久在线精品| 91色色色| 久久您您综合网| 五月婷婷丁香五月| 久久免费操| 性色欲情 网站| 亚洲爱爱无码婷婷色五月| 精品皮股午夜AV| 色色色色热| 丁香婷婷网| 亚洲国产精品VA在线看黑人| 亚洲av电影网站| 色9月| 久婷婷五月丁香在线观看| 99在线视频在线观看| 婷婷激情小说| 五月天色色色| 影音先锋美国A| 五月丁香毛片| VA五月激情在线| 狠狠干五码| 免费97碰碰| 九九在线精品| 精品国产a| 在线中文av| 狠狠操狠狠狠| 丁香五月开心亚洲| 天天干天天干天天干| 97操女视频| 九九久久精品| 狠色色狠网| 99热精品在线| 蒲京久久无码视频| 国产精品久久..4399| 婷婷五月天伊人网在线观看视频| 99色视频在线| 亚洲va综合va国产va中文| 日本大逼91| 九九视频免费| 涩综合婷婷| 久草婷婷| 婷婷激情人妻| 手机激情网| 大香蕉五月丁香| 天堂美国久久| 天天日天天舔天天摸| 牛牛碰免费| 欧美性爱五月天| 六月色婷婷综合影视| 亚洲色爽| 亚洲成人AV在线观看| 97日本在线播放| 99婷婷| 色无码| 人妻激情久久| 五月色婷婷亚洲 | 欧美性爱五月天| 无码激情AAAAA片-区区| 超碰免费人妻| 婷婷五月天综合久久| 精品一二三区久久AAA片| 99热爱爱干干日| 五月婷视屏在线观看| 亚洲中文字幕在线观看| 综合色五月| 天天摸天天做天天爱天天爽| 99视频| 五月天天天综合| 99热综合网| 97人人操人| 99热九九在线| 婷婷色影院| 五月丁香免费视频| 激情无码网| 九九综合88| 婷婷五月天激情五月天网站| 人妻丰满精品一区二区A片| 色五月丁香五月| 九九热re99re6在线精品| 涩玖玖免费视频| 婷婷五月天性| 日欧一片内射VA在线影院| 激情五月丁香婷婷夜夜操| 五月天综合激情网| 五月天另类图片区99| 这里只有精品网| 激情98色婷婷五| 色婷婷伦理| 四川BBB搡BBB搡多人乱亂| 亚洲丁香五月综合| 五月婷婷丁香| 婷婷欧美偷拍综合| 午夜色婷婷| 俺也去在线久久精品23欧美综合视频网站,丰满人妻一区二区三区在线视频53,丰满 | 久婷久婷激情肉| 天天天天天天操| 伊人影院久久网| 久久五月天激情| www九月婷婷| 婷婷狠狠干| 色婷婷亚洲在线观看| 夜夜夜夜撸夜夜操| 九九激情视频| 婷婷久久色| 十区AV| 色噜噜狠狠色综合成人网| 欧美三日本三级少妇三99| 99综合一区| 99久久网站| 狠狠干夜夜干| 激情com| 国产做A爰片毛片A片美国| www.久久五月天.com| 欧洲电影在线观看免费版英语版 | 亚洲天码视频www蛋播视频| 日本在线观看aaa 99| 色香欲综合| 欧美日韩国产伦精品日韩人妻一| 成人精品人妻| 亚洲丁香花色| 中文字幕无码人妻少妇免费视频 | 最新日本A片| 午夜成人片400| 婷婷五月天干干| 啪色综合| 天天拍天天操| 六月丁香婷婷色69| 久久青草国| 99精品久久久久久久婷婷| 96精品久久久久久久久| 性色欲情 网站| 精品欧美性爱超级爽| 玖玖资源站中文| 激情久久肏屄视频| 久热免费视频| 综合色激情| 97超碰人人操| 三年高清大片免费观看国语| 另类激情五月天| 五月丁香激情婷婷| 久久xx| 直接看的AV| 九九热精品| 久草丁香婷婷1024| 久久婷婷内射| 婷五月丁香| 丁香五月大香蕉AV| 91精品久久久久久综合五月天| 色五月丁香在线| 色女人久久| 无码激情AAAAA片-区区| 激情五月天偷拍综合网| 婷婷五月天中文字幕.| 亚洲精品第一国产综合亚AV| 大香蕉伊人99| 插插五月天| 色玖玖综合网| 欧美性爱丁香五月| 五月丁香啪啪网| 五月婷丁香亚洲| 日本熟妇精品99| 天久综合91综合首页| 亚洲在线操| 丁香五月天综合网| 九九AV| 99在线小视频| 在线观看国产高清视频免费网站 | 五月婷婷啪| 99爱免费在线观看| 大香蕉婷婷五月| 精品久9| AV电影在线播放| 激情五月天婷婷| 色婷婷激情视频| 天天干,天天舔| av无码电影| 激情涩播| 99re6久热只有精品6在线直播| 久久九九热视频| 无码激情精品色婷婷久久久久| 婷婷九九| 综合网网欲色| 9热超碰| 九九性视频| 色色丁香婷婷| 亚洲第一综合| 丁香五月婷婷欧美成人色图| 五月丁香啪啪啪免费看| 97人凄人人操人人爽| 成片免费观看大全| 青青操绿aaa一区日v| 国产老熟妇亲子乱对白| 99热99日天天干| 99在线精品免费视频| 久久人妻久久| 色域五月婷婷丁香| 久久九九色| 99成人小视频| 婷婷五月丁香伊人网| 人妻射精AV| 亚洲综合视频网| 丁香婷婷午夜| 色婷婷成人久久| 成人精品免费在线观看| 少妇被下春药玩弄A片| 99热国产这里只有精品| 大香蕉九操| 新激情五月天天在线网| 丁香色五月婷婷| 玖玖资源站蜜臀| 五月婷婷激情四月| 五月婷婷欲色| 人人看人人要| 婷婷综合在线观看视频| 美女要搞搞天天搞搞搞网站| 日本的α片xxxwww| 开心深爱五月天| av 一区三区四区| 天天日天天狠狠操| 五月丁香六月婷婷,婷| 婷婷六月丁香在线| 色五月丁香五月五月婷婷| 婷婷免费精品视频| WWW.激情| 国产99精品免费视频| 五月婷婷丁香深深爱| 国产亚洲色婷婷99精品| 五月激情五月丁香| 久热这里只有精品在线观看| 婷婷激情五月天综合| 久久久久婷婷五月热综合| 亚洲 精品 综合 精品| 婷婷五月色影视先锋| 五月天婷婷久久综合| 夜夜操天天爽| 九九热免费| 无码99| 超碰免费人妻| 综合五月婷婷| 第九色区av天堂| 久久婷婷七月丁香| 久久99免费视频| 欧美三级黄色片久久| 五月激情综合网| 丁香五月婷婷久久久| 综合视频五月| 九九99视频| 97热在线精品| 色色色免费视频| 欧美槡BBBB槡BBB少妇| 一本色道久久综合狠狠躁一二三| 91怕怕网| 色丁香五月天| 五婷婷六月合| 综合激情深爱| 99久超碰| 丁香五月社区| 五月刺激丁香月综合| 神马欧美精| 色婷婷中文字母五月丁香| 婷婷之六月丁香| 丁香五月综合| 久操热| 亚洲啪| 丁香五月婷婷激情网| 婷婷激情综合色五月久久,色婷婷丁香花,丁香婷婷五月情天,久久婷婷五月综合色 | 久久婷婷色| 97色色综合| 人人摸人人摸| 激情五月婷婷视频| av无码电影| 精品无码色| 五月天久久婷婷| 99色视频在线| 另类国产欧美视频| 婷婷四色五月| 五月丁香六月婷婷婷婷| 久久总和99| 色欧美一级| 免费黄色AV| 久久这里有精品99| 丁香五月综合婷婷| 《亚洲操B久久免费在线观看,亚洲操B久久在线播放》在线播放 - 高清资源 - 97 | 99九九99九九九视频精彩| 蜜桃人妻无码AV天堂三区| 激情AV中文| 天天色综合色| 性色婷婷| 99国产99| 丁香六月婷婷| 亚洲va在线∨a天堂va欧美va| 精品人妻久久久久久| 精品导航在线x不卡| 亚洲色婷婷色| 丁XX 成人| 丁香五月天AV在线 | 99热在线观看| 婷综合| 日本久久爱| 另类小说五月天| 色综合久久44| 色五月激情| 最近免费中文字幕大全高清大全1| 热五月婷婷| 五月婷婷 激情五月| 性一交一乱一交A片久| 日韩综合久久| 丁香色婷婷五月天| wwwav大香蕉| 激情综合播播| 精品在线网站| 久久码久久无清| 五月天久久www| 六月丁香啪啪| 五夜婷婷| 丁香五月婷婷五月天| 亚洲182在线观看| 婷婷在线操| 激情综合网五月婷婷| 亚洲免费观看高清完整版AV线| 久久这里只有欧美| 99国产精品白浆在线观看免费 | 色婷婷综合亚洲| 六月丁香啪| 婷婷日日天天| 国产成人片| 国产噜一噜天天噜| 99精品在线观看| 久99视频在线观看| 999久久久国产精品| 一区=区操屄高清大全av| http://www.lingjunshare.com/ | 国产人妻777人伦精品HD| 亚洲AV免费在线| 97干网站| 中文字幕,综合,91| 日本色婷婷| www.99热这里精品| 天天干夜夜想| 婷婷日韩| 九九爱激情| 97干在线免费| 激情网婷婷婷| 丁香五月伊人| 婷婷五月色丁香在线看| 日韩限制级大尺度黑料泄密大尺度视频一区二区在线观看 | 日本精品人妻无码77777| 色色色精品无码区| AA片在线观看视频在线播放| 色五月涩涩婷婷蜜桃| 婷婷五月丁香五月| 激情五月天婷婷免费观看| 成人片在线播放| 免费色色色| 日本色色影片| 色婷婷激情五月天|