Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Custom user-agent #4284

Closed
xcodebuild opened this issue Jun 7, 2022 · 16 comments
Closed

[feat] Custom user-agent #4284

xcodebuild opened this issue Jun 7, 2022 · 16 comments

Comments

@xcodebuild
Copy link

Describe the problem

Default user-agent is Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) while Safari is Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15.

No browser/version in user-agent make many website treat tauri as out-of-date browser. See #3519 for example.

Describe the solution you'd like

Provide a rust API to set custom user-agent. Or at least use a modern browser user-agent.

Alternatives considered

No response

Additional context

No response

@FabianLars
Copy link
Sponsor Member

FabianLars commented Jun 7, 2022

Since this most likely won't make it into v1, here's how you can do it on the latest tauri version:

window.with_webview(|webview| {
    #[cfg(windows)]
    unsafe {
        use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings2;
        use windows::core::Interface;

        let settings: ICoreWebView2Settings2 = webview
            .controller()
            .CoreWebView2()
            .unwrap()
            .Settings()
            .unwrap()
            .cast()
            .unwrap();

        settings
            .SetUserAgent("my custom user agent".to_string())
            .unwrap();
    }

    #[cfg(target_os = "linux")]
    {
        use webkit2gtk::{WebViewExt, SettingsExt};
        let webview = webview.inner();
        let settings = webview.settings().unwrap();
        settings.set_user_agent(Some("my user agent"));
    }

    // untested
    #[cfg(target_os = "macos")]
    unsafe {
        use objc::msg_send;
        use objc_foundation::{NSString, INSString};
        let () = msg_send![webview.inner(), setCustomUserAgent: NSString::from_str("my custom user agent")];
    }
});

@JonasKruckenberg
Copy link
Contributor

Since this most likely won't make it into v1, here's how you can do it on the latest tauri version:

It's definitely not making it into v1

@FabianLars
Copy link
Sponsor Member

Well the wry api was audited as far as i can see, and that was enough for other things 🤷 That's why i now always go with "most likely", "probably", etc., because i was wrong a couple of times already 😂

@xcodebuild
Copy link
Author

Works like a charm

@ZhelinCheng
Copy link

window.with_webview(|webview| {
    #[cfg(windows)]
    unsafe {
        use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings2;
        use windows::core::Interface;

        let settings: ICoreWebView2Settings2 = webview
            .controller()
            .CoreWebView2()
            .unwrap()
            .Settings()
            .unwrap()
            .cast()
            .unwrap();

        settings
            .SetUserAgent("my custom user agent".to_string())
            .unwrap();
    }

    #[cfg(target_os = "linux")]
    {
        use webkit2gtk::{WebViewExt, SettingsExt};
        let webview = webview.inner();
        let settings = webview.settings().unwrap();
        settings.set_user_agent(Some("my user agent"));
    }

    // untested
    #[cfg(target_os = "macos")]
    unsafe {
        use objc::msg_send;
        use objc_foundation::{NSString, INSString};
        let () = msg_send![webview.inner(), setCustomUserAgent: NSString::from_str("my custom user agent")];
    }
});

Where to write?

@elanzini
Copy link

elanzini commented Jul 31, 2022

I have included like this in my project:

tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![
      my_function,
    ])
    .setup(|app| {
      let window = WindowBuilder::new(
        app,
        "main-window".to_string(),
        tauri::WindowUrl::App("index.html".into()),
      )
      .build()?;
      window.with_webview(|webview| {
        #[cfg(windows)]
        unsafe {
          use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings2;
          use windows::core::Interface;

          let settings: ICoreWebView2Settings2 = webview
              .controller()
              .CoreWebView2()
              .unwrap()
              .Settings()
              .unwrap()
              .cast()
              .unwrap();

          settings
              .SetUserAgent("Chrome".to_string())
              .unwrap();
          }
      });
      Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");

And included the following in my Cargo.toml:

# for webview
[dependencies]
webview2-com = "0.18.0"

# for windows::core
[dependencies.windows]
version = "0.39.0"
features = [
    "Data_Xml_Dom",
    "Win32_Foundation",
    "Win32_Security",
    "Win32_System_Threading",
    "Win32_UI_WindowsAndMessaging",
]

And I am getting this error:

error[E0599]: no method named `cast` found for struct `webview2_com_sys::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings` in the current scope
   --> src\main.rs:108:16
    |
108 |               .cast()
    |                ^^^^ method not found in `webview2_com_sys::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings`
    |

I also tried downgrading to webview2-com = "0.16.0" use in wry but no luck with that either.

@icidasset
Copy link

@elanzini You have to use the same versions as Tauri does. I got it to work with webview2-com version 0.16.0 and windows version 0.37.0, see: https://github.com/tauri-apps/wry/blob/3c77cb98e4b2449b9b8cd3a992b7202b87bb43bf/Cargo.toml#L59

@eghernqvist
Copy link

On the last part:

settings
    .SetUserAgent("my custom user agent".to_string())
    .unwrap();

I'm getting below error:

error[E0277]: the trait bound `PCWSTR: From<String>` is not satisfied
     --> src\main.rs:39:39
      |
39    |                         .SetUserAgent("my custom user agent".to_string())
      |                          ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `PCWSTR`
      |                          |
      |                          required by a bound introduced by this call
      |
      = help: the following other types implement trait `From<T>`:
                <PCWSTR as From<&HSTRING>>
                <PCWSTR as From<Option<PCWSTR>>>
      = note: required because of the requirements on the impl of `Into<PCWSTR>` for `String`
note: required by a bound in `ICoreWebView2Settings2::SetUserAgent`
     --> C:\Users\egher\.cargo\registry\src\github.com-1ecc6299db9ec823\webview2-com-sys-0.19.0\src\Microsoft\Web\WebView2\Win32\mod.rs:21162:13
      |
21162 |         P0: ::std::convert::Into<::windows::core::PCWSTR>,
      |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ICoreWebView2Settings2::SetUserAgent`

Using tauri 1.1.0 and same versions of webview2-com and windows as specified in Cargo.lock, namely 0.19.1 for the former and 0.39.0 for the latter. Any ideas what I am doing wrong?

@FabianLars
Copy link
Sponsor Member

The snippet above was written for windows 0.37 and webview2-com 0.16. It's definitely possible that something changed in the new versions that broke the script.

@FabianLars
Copy link
Sponsor Member

I'm on the run right now so I can't show code examples, but it looks like you can use the new w macro from the windows crate if the user agent is known upfront. Something like .SetUserAgent(w!("my user agent").unwrap())

For runtime strings it's a bit tricky and needs some ugly functions (or a crate idk), but that's something I can't show on my phone...

@eghernqvist
Copy link

eghernqvist commented Sep 16, 2022

I'm on the run right now so I can't show code examples, but it looks like you can use the new w macro from the windows crate if the user agent is known upfront. Something like .SetUserAgent(w!("my user agent").unwrap())

For runtime strings it's a bit tricky and needs some ugly functions (or a crate idk), but that's something I can't show on my phone...

That worked.
I also got it working with below code, using my 1 day long Rust experience I'm surprised it actually worked:

let s = "Hello";

let mut v: Vec<u16> = s.encode_utf16().collect();
v.push(0);
let agent: PCWSTR = PCWSTR::from_raw(v.as_ptr());

settings.SetUserAgent(agent).unwrap();

Yours is slightly cleaner 😅
Thanks for the help!

@FabianLars
Copy link
Sponsor Member

This is basically what we use in wry 👍 and also what I had in mind for runtime Strings (it's probably not the actual name, but what I mean is a string you don't know the content of at compile time)

@ArrowAced
Copy link

I'm on the latest tauri on linux and cannot find any up-to-date instructions for this. How do you do this on the latest version?

@FabianLars
Copy link
Sponsor Member

@ArrowAced It's not released yet but will be part of v1.2

@EtzBetz
Copy link

EtzBetz commented Dec 29, 2022

v1.2 is released, can this be found anywhere or was it delayed and i need to rely on the "manual" solution?

@icidasset
Copy link

@EtzBetz It's userAgent in the Tauri config https://tauri.app/v1/api/config#windowconfig and user_agent on the WindowBuilder https://docs.rs/tauri/1.2.3/tauri/window/struct.WindowBuilder.html#method.user_agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants