tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
83.67k stars 2.51k forks source link

[bug] Tauri 2.0 window.url() in on_webview_ready returns an empty URL on Windows #9027

Closed martpie closed 6 months ago

martpie commented 7 months ago

Describe the bug

I have a small plugin that navigates to a certain URL hash based on some configuration saved by the user, the plugin roughly look like the following:

/**
 * Set the default view on application load based on user preference
 */
pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::<R>::new("default-view")
        .invoke_handler(tauri::generate_handler![set])
        .on_webview_ready(|mut window| {
            if window.label().eq("main") {
                let config_manager = window.state::<ConfigManager>();
                let mut url = window.url();
                let default_view = config_manager.get().default_view;

                let fragment = match default_view {
                    DefaultView::Library => "/library",
                    DefaultView::Playlists => "/playlists",
                };

                info!("Navigating to '{}'", fragment);
                url.set_fragment(Some(fragment));
                window.navigate(url);
            }
        })
        .build()
}

on macOS, the correct view gets loaded. On Windows, a blank page is displayed when starting the app (I did not test on Linux).

Digging a bit, and logging the url variable, it appears empty:

[2024-02-28][23:40:06][INFO][museeks::plugins::default_view] 'HERE Url { scheme: "about", cannot_be_a_base: true, username: "", password: None, host: None, port: None, path: "blank", query: None, fragment: None }

So when I mutate it, it of course loads nothing.

Reproduction

cf. code above.

Expected behavior

No response

Full tauri info output

PS C:\Users\pierre\Documents\GitHub\museeks> yarn tauri info
yarn run v1.22.19
$ tauri info

[✔] Environment
    - OS: Windows 10.0.22631 X64
    ✔ WebView2: 122.0.2365.52
    ✔ MSVC:
        - Visual Studio Build Tools 2019
        - Visual Studio Build Tools 2022
    ✔ rustc: 1.76.0 (07dca489a 2024-02-04)
    ✔ cargo: 1.76.0 (c84b36747 2024-01-18)
    ✔ rustup: 1.26.0 (5af9b9484 2023-04-05)
    ✔ Rust toolchain: stable-x86_64-pc-windows-msvc (default)
    - node: 20.11.1
    - yarn: 1.22.19
    - npm: 10.2.4

[-] Packages
    - tauri [RUST]: 2.0.0-beta.7
    - tauri-build [RUST]: 2.0.0-beta.5
    - wry [RUST]: 0.37.0
    - tao [RUST]: 0.26.0
    - @tauri-apps/api [NPM]: 2.0.0-beta.3
    - @tauri-apps/cli [NPM]: 2.0.0-beta.4

[-] App
    - build-type: bundle
    - CSP: default-src 'none'; img-src 'self' data:; media-src 'self' asset: https://asset.localhost http://asset.localhost; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src ipc: http://ipc.localhost 'self' https://api.github.com; font-src 'self' data:
    - frontendDist: ../dist
    - devUrl: http://localhost:1420/
    - framework: React
    - bundler: Vite
Done in 7.99s.


### Stack trace

_No response_

### Additional context

_No response_
martpie commented 6 months ago

It would seem the URL is not actually empty, but definitely wrong, here's a debug of window.url()

[2024-03-31][14:54:33][INFO][...] Url {
    scheme: "about",
    cannot_be_a_base: true,
    username: "",
    password: None,
    host: None,
    port: None,
    path: "blank",
    query: None,
    fragment: None,
}
martpie commented 6 months ago

For people looking for a workaround, I ended up using on_page_load instead

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::<R>::new("default-view")
        .invoke_handler(tauri::generate_handler![set])
        .on_page_load(|webview, payload| {
            if webview.label().eq("main") && payload.event() == PageLoadEvent::Finished {
                let config_manager = webview.state::<ConfigManager>();
                let mut url = payload.url().clone();
                let default_view = config_manager.get().default_view;

                let fragment = match default_view {
                    DefaultView::Library => "/library",
                    DefaultView::Playlists => "/playlists",
                };

                info!("Navigating to '{}'", fragment);
                url.set_fragment(Some(fragment));

                // For some reasons, it does not seem possible to navigate directly
                // from the webview argument, as we cannot make it &mut
                webview
                    .app_handle()
                    .get_webview_window("main")
                    .unwrap()
                    .navigate(url)
            }
        })
        .build()
}
FabianLars commented 6 months ago

Yup, on_webview_ready simply triggers too early. It triggers when the webview was started/registered, not when it navigated to the app's "website". Afaik webview2 has no config for an actual init page so it always starts on about:blank before we can navigate to the actual url.

Maybe it makes sense to remove on_webview_ready in its current state completely and also use navigation based hooks like we do outside of plugins (on the app and windows)...