| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- //! Chrome DevTools Protocol(CDP)通用 helper —— 仅 Windows
- //!
- //! 通过 webview2_com 的 CallDevToolsProtocolMethod 调任意 CDP 命令,
- //! 异步回调用 oneshot 桥成 async/await。当前供:
- //! - capture.rs:截图前的预热脚本 + Page.captureScreenshot
- //! - landing.rs:中间页轮询 div.c-tags 与 Site 链接
- #![cfg(target_os = "windows")]
- use anyhow::{anyhow, Result};
- use serde_json::Value;
- use std::sync::{Arc, Mutex};
- use tauri::Webview;
- use tokio::sync::oneshot;
- use webview2_com::CallDevToolsProtocolMethodCompletedHandler;
- use windows::core::HSTRING;
- /// 调一个 CDP 方法,返回响应 JSON(已 parse 为 serde_json::Value)。
- ///
- /// 失败原因可能来自三处:
- /// 1) with_webview 同步阶段(如 controller 为空)
- /// 2) CDP HRESULT 错误(远端方法不支持或 webview 已卸载)
- /// 3) CDP 响应不是合法 JSON(理论上不会发生)
- pub async fn call_cdp(webview: &Webview, method: &str, params: Value) -> Result<Value> {
- let (tx, rx) = oneshot::channel::<Result<String, String>>();
- let tx = Arc::new(Mutex::new(Some(tx)));
- let method_owned = method.to_string();
- let params_str = serde_json::to_string(¶ms)?;
- let tx_for_native = tx.clone();
- let method_for_native = method_owned.clone();
- webview
- .with_webview(move |platform| {
- let result: Result<()> = (|| {
- let controller = platform.controller();
- let core = unsafe { controller.CoreWebView2()? };
- let method_h: HSTRING = method_for_native.clone().into();
- let params_h: HSTRING = params_str.clone().into();
- let tx_handler = tx_for_native.clone();
- let handler = CallDevToolsProtocolMethodCompletedHandler::create(Box::new(
- move |hr, json_pcwstr| {
- let json_str = json_pcwstr.to_string();
- let res = if hr.is_ok() {
- Ok(json_str)
- } else {
- Err(format!("CDP HRESULT 错误: {}", hr.err().unwrap()))
- };
- if let Ok(mut guard) = tx_handler.lock() {
- if let Some(sender) = guard.take() {
- let _ = sender.send(res);
- }
- }
- Ok(())
- },
- ));
- unsafe {
- core.CallDevToolsProtocolMethod(&method_h, ¶ms_h, &handler)?;
- }
- Ok(())
- })();
- if let Err(e) = result {
- if let Ok(mut guard) = tx_for_native.lock() {
- if let Some(sender) = guard.take() {
- let _ = sender.send(Err(format!("CDP 同步阶段失败: {e}")));
- }
- }
- }
- })
- .map_err(|e| anyhow!("with_webview 调用失败: {e}"))?;
- let raw = rx.await?.map_err(|_| anyhow!("CDP oneshot 通道关闭"))?;
- serde_json::from_str(&raw).map_err(|e| anyhow!("CDP 响应不是合法 JSON: {e}; raw={raw}"))
- }
|