< 返回版块

itisl2220 发表于 2023-09-17 10:27

Tags:Tauri,cookie, webview2_com

tauri是和electron一样的跨平台桌面开发框架,其优秀的性能表现和低内存占用以及打包后的体积小等特点,被广大开发者喜欢。 由于tauri团队的核心理念是做一款安全的跨平台框架,所以官方并没有对,webview的cookie获取和操作webview做一些接口的封装。 但是官方给开发者在rust层提供了获取webview句柄的功能 window.with_webview(move |webview| unsafe {}).unwrap(); // 获取窗口的webview句柄 有了这个句柄我们就能对webview进行底层的操作。 下面我们就可以通过这个获取网站的cookie啦,以windows系统为例,在windows系统下,tauri使用的是微软的webview2这个框架,要对webview2进行操作的话我们要用到下面两个rust crate

# 在Cargo.toml中添加 
[dependencies]
windows = "0.39.0"
webview2-com = "0.19.1"

接下来就是获取网页cookie的示范代码

use crate::error::Result;
use tauri::Window;
use webview2_com::{
    take_pwstr, GetCookiesCompletedHandler,
    Microsoft::Web::WebView2::Win32::{ICoreWebView2Cookie, ICoreWebView2_2},
};
use windows::core::{Interface, HSTRING, PWSTR};

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    pub domain: String,
    pub path: String,
}
/**
 * 运行获取cookie
 */
pub async fn get_win_cookie(
    win: &Window,
    url: &'static str, // 要获取cookie的网址
) -> Result<Vec<Cookie>> {
    // 因为操作是一个异步的,咱们使用oneshot::channel来传输数据
    let (done_tx, done_rx) = oneshot::channel::<Vec<Cookie>>();
    win.with_webview(move |webview| unsafe {
        // 获取webview2的com接口
        let core = webview.controller().CoreWebView2().unwrap();
        // 获取webview2的com接口 ICoreWebView2_2
        let core2 = Interface::cast::<ICoreWebView2_2>(&core).unwrap();
        // 将字符串转换为windows系统的宽字符格式应该 WinRT string
        let uri = HSTRING::from(url);
        // 获取浏览器的Cookie的管理模块
        let manager = core2.CookieManager().unwrap();
        // 异步获取cookie
        GetCookiesCompletedHandler::wait_for_async_operation(
            Box::new(move |handler| {
                manager.GetCookies(&uri, &handler)?;
                Ok(())
            }),
            Box::new(move |hresult, list| {
                hresult?;
                match list {
                    Some(list) => {
                        let mut count: u32 = 0;
                        list.Count(&mut count)?;
                        // tracing::info!("count: {}", count);
                        let mut cookies = vec![];
                        for i in 0..count {
                            let cookie: ICoreWebView2Cookie = list.GetValueAtIndex(i)?;
                            let mut name = PWSTR::null();
                            let mut value = PWSTR::null();
                            let mut domain = PWSTR::null();
                            let mut path = PWSTR::null();
                            cookie.Name(&mut name)?;
                            cookie.Value(&mut value)?;
                            cookie.Domain(&mut domain)?;
                            cookie.Path(&mut path)?;
                            cookies.push(Cookie {
                                name: take_pwstr(name),
                                value: take_pwstr(value),
                                domain: take_pwstr(domain),
                                path: take_pwstr(path),
                            });
                        }
                        done_tx.send(cookies).unwrap();
                    }
                    None => {
                        // 没得数据
                    }
                };
                Ok(())
            }),
        )
        .unwrap();
    })
    .unwrap();
    let cookies = done_rx.await.unwrap();
    Ok(cookies)
}

代码比较简陋,有需要的朋友们可以参考一下,微软针对webview2提供了很多接口可以去看一下webview2-com crate的源码。

评论区

写评论
廴壬吉 2023-10-14 09:54

webview2-com = "0.26.0" webview2-com-sys = "0.26.0" windows = "0.51.1" windows-sys = "0.48.0" 全引用了

廴壬吉 2023-10-14 09:53

Interface::cast 这个cast找不到呢

1 共 2 条评论, 1 页