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

refactor(android): use http scheme by default for custom protocols and add option to change it ref #994 #1020

Merged
merged 3 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/android-protocol-http.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

**Breaking change** Wry now defaults to `http://<scheme>.localhost/` for custom protocols on Android.
5 changes: 5 additions & 0 deletions .changes/https-protocol-option-android.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

Add `WebViewBuilderExtAndroid::with_https_scheme` to be able to choose between `http` and `https` for custom protocols on Android.
2 changes: 1 addition & 1 deletion examples/stream.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
if (navigator.userAgent.includes("Windows")) {
const video = document.getElementById("video_source");
const sources = video.getElementsByTagName("source");
sources[0].src = "https://wry.localhost/examples/test_video.mp4";
sources[0].src = "http://wry.localhost/examples/test_video.mp4";
video.load();
}
})();
Expand Down
14 changes: 9 additions & 5 deletions src/webview/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,20 @@ impl InnerWebView {
on_webview_created,
with_asset_loader,
asset_loader_domain,
https_scheme,
} = pl_attrs;

let custom_protocol_scheme = if https_scheme { "https" } else { "http" };

let url = if let Some(u) = url {
let mut url_string = String::from(u.as_str());
let name = u.scheme();
let is_custom_protocol = custom_protocols.iter().any(|(n, _)| n == name);
if is_custom_protocol {
url_string = u
.as_str()
.replace(&format!("{}://", name), &format!("https://{}.", name))
url_string = u.as_str().replace(
&format!("{name}://"),
&format!("{custom_protocol_scheme}://{name}."),
)
}
Some(url_string)
} else {
Expand Down Expand Up @@ -175,13 +179,13 @@ impl InnerWebView {
request
.uri()
.to_string()
.starts_with(&format!("https://{}.", name))
.starts_with(&format!("{custom_protocol_scheme}://{}.", name))
}) {
*request.uri_mut() = request
.uri()
.to_string()
.replace(
&format!("https://{}.", custom_protocol.0),
&format!("{custom_protocol_scheme}://{}.", custom_protocol.0),
&format!("{}://", custom_protocol.0),
)
.parse()
Expand Down
39 changes: 29 additions & 10 deletions src/webview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,20 @@ pub struct WebViewAttributes {
/// The closure takes a [Request] and returns a [Response].
///
/// # Warning
///
/// Pages loaded from custom protocol will have different Origin on different platforms. And
/// servers which enforce CORS will need to add exact same Origin header in `Access-Control-Allow-Origin`
/// if you wish to send requests with native `fetch` and `XmlHttpRequest` APIs. Here are the
/// different Origin headers across platforms:
///
/// - macOS and Linux: `<scheme_name>://<path>` (so it will be `wry://examples` in `custom_protocol` example). On Linux, You need to enable `linux-headers` feature flag.
/// - Windows: `https://<scheme_name>.<path>` (so it will be `https://wry.examples` in `custom_protocol` example)
/// - Android: Custom protocol on Android is fixed to `https://tauri.wry/` due to its design and
/// our approach to use it. On Android, We only handle the scheme name and ignore the closure. So
/// when you load the url like `wry://assets/index.html`, it will become
/// `https://tauri.wry/assets/index.html`. Android has `assets` and `resource` path finder to
/// - macOS, iOS and Linux: `<scheme_name>://<path>` (so it will be `wry://examples` in `custom_protocol` example). On Linux, You need to enable `linux-headers` feature flag.
/// - Windows and Android: `http://<scheme_name>.<path>` by default (so it will be `http://wry.examples` in `custom_protocol` example). To use `https` instead of `http`, use [`WebViewBuilderExtWindows::with_https_scheme`] and [`WebViewBuilderExtAndroid::with_https_scheme`].
///
/// # Reading assets on mobile
///
/// - Android: Android has `assets` and `resource` path finder to
/// locate your files in those directories. For more information, see [Loading in-app content](https://developer.android.com/guide/webapps/load-local-content) page.
/// - iOS: Same as macOS. To get the path of your assets, you can call [`CFBundle::resources_path`](https://docs.rs/core-foundation/latest/core_foundation/bundle/struct.CFBundle.html#method.resources_path). So url like `wry://assets/index.html` could get the html file in assets directory.
/// - iOS: To get the path of your assets, you can call [`CFBundle::resources_path`](https://docs.rs/core-foundation/latest/core_foundation/bundle/struct.CFBundle.html#method.resources_path). So url like `wry://assets/index.html` could get the html file in assets directory.
///
/// [bug]: https://bugs.webkit.org/show_bug.cgi?id=229034
pub custom_protocols: Vec<(String, Box<dyn Fn(Request<Vec<u8>>, RequestAsyncResponder)>)>,
Expand Down Expand Up @@ -349,6 +350,7 @@ pub(crate) struct PlatformSpecificWebViewAttributes {
>,
with_asset_loader: bool,
asset_loader_domain: Option<String>,
https_scheme: bool,
}

/// Type alias for a color in the RGBA format.
Expand Down Expand Up @@ -460,19 +462,23 @@ impl<'a> WebViewBuilder<'a> {
/// The closure takes a [Request] and returns a [Response]
///
/// # Warning
///
/// Pages loaded from custom protocol will have different Origin on different platforms. And
/// servers which enforce CORS will need to add exact same Origin header in `Access-Control-Allow-Origin`
/// if you wish to send requests with native `fetch` and `XmlHttpRequest` APIs. Here are the
/// different Origin headers across platforms:
///
/// - macOS and Linux: `<scheme_name>://<path>` (so it will be `wry://examples` in `custom_protocol` example). On Linux, You need to enable `linux-headers` feature flag.
/// - Windows: `https://<scheme_name>.<path>` (so it will be `https://wry.examples` in `custom_protocol` example)
/// - macOS, iOS and Linux: `<scheme_name>://<path>` (so it will be `wry://examples` in `custom_protocol` example). On Linux, You need to enable `linux-headers` feature flag.
/// - Windows and Android: `http://<scheme_name>.<path>` by default (so it will be `http://wry.examples` in `custom_protocol` example). To use `https` instead of `http`, use [`WebViewBuilderExtWindows::with_https_scheme`] and [`WebViewBuilderExtAndroid::with_https_scheme`].
///
/// # Reading assets on mobile
///
/// - Android: For loading content from the `assets` folder (which is copied to the Andorid apk) please
/// use the function [`with_asset_loader`] from [`WebViewBuilderExtAndroid`] instead.
/// This function on Android can only be used to serve assets you can embed in the binary or are
/// elsewhere in Android (provided the app has appropriate access), but not from the `assets`
/// folder which lives within the apk. For the cases where this can be used, it works the same as in macOS and Linux.
/// - iOS: Same as macOS. To get the path of your assets, you can call [`CFBundle::resources_path`](https://docs.rs/core-foundation/latest/core_foundation/bundle/struct.CFBundle.html#method.resources_path). So url like `wry://assets/index.html` could get the html file in assets directory.
/// - iOS: To get the path of your assets, you can call [`CFBundle::resources_path`](https://docs.rs/core-foundation/latest/core_foundation/bundle/struct.CFBundle.html#method.resources_path). So url like `wry://assets/index.html` could get the html file in assets directory.
///
/// [bug]: https://bugs.webkit.org/show_bug.cgi?id=229034
#[cfg(feature = "protocol")]
Expand Down Expand Up @@ -848,6 +854,14 @@ pub trait WebViewBuilderExtAndroid {
/// to `with_custom_protocol` for Android, as it changes the way in which requests are handled.
#[cfg(feature = "protocol")]
fn with_asset_loader(self, protocol: String) -> Self;

/// Determines whether the custom protocols should use `https://<scheme>.localhost` instead of the default `http://<scheme>.localhost`.
///
/// Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints
/// and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.
///
/// The default value is `false`.
fn with_https_scheme(self, enabled: bool) -> Self;
}

#[cfg(target_os = "android")]
Expand Down Expand Up @@ -881,6 +895,11 @@ impl WebViewBuilderExtAndroid for WebViewBuilder<'_> {
self.platform_specific.asset_loader_domain = Some(format!("{}.assets", protocol));
self
}

fn with_https_scheme(mut self, enabled: bool) -> Self {
self.platform_specific.https_scheme = enabled;
self
}
}

/// The fundamental type to present a [`WebView`].
Expand Down
Loading