Repository navigation
What's Changed
- Add a configurable origin trust policy by @mbarta in #215
- Don't leak the previous Activity and its WebViews when it is destroyed by @jonashan in #221
- Recover when the WebView render process is gone by @jonashan in #222
- Scope WebView cookies to the request host by @mbarta in #211
- Stop the redirect check before the cross-origin destination by @jeremy in #213
- Add web authentication (passkey) support by @leonvogt in #218
- Hide native title when HTML
<title>is not present or blank by @leonvogt in #204
New Features
Origin verification
Hotwire Native now checks the origin of every page before it lets the page navigate in-app or reach native code. Only origins your app trusts can:
- open in the app instead of a browser tab
- receive the library's JavaScript and send Turbo and bridge component messages
- open the file chooser
- get geolocation, camera and microphone permissions
The default DefaultOriginTrustPolicy trusts the origins of your NavigatorHost start locations. If your app loads a single origin, you don't need to change anything.
To trust more origins, set your own policy. You can build on the default:
private val accounts = Origin.parse("https://accounts.example.com")
Hotwire.config.originTrustPolicy = object : OriginTrustPolicy() {
override fun isTrustedForNavigation(origin: Origin) =
origin == accounts || DefaultOriginTrustPolicy.isTrustedForNavigation(origin)
override fun isTrustedForNativeAccess(origin: Origin) =
origin == accounts || DefaultOriginTrustPolicy.isTrustedForNativeAccess(origin)
}An origin is the full scheme, host and port, so http://example.com and https://example.com:8443 are different origins from https://example.com. See #215.
Passkeys
Set Hotwire.config.webAuthenticationEnabled = true in Application.onCreate() to allow WebAuthn (passkey) requests from your WebViews. Your app needs Digital Asset Links set up with your site, and your server has to accept the app's android:apk-key-hash origin. Only turn this on if your WebViews load nothing but your own sites. See #218.
Fixes
- When the WebView render process is gone, every
NavigatorHostnow replaces its session and reloads its current page instead of staying blank. See #222. - Apps with registered bridge components no longer keep every destroyed
Activityand its WebViews in memory after a recreation (dark mode, locale changes) or after signing out. See #221. - The library's own HTTP requests now send each host only its own WebView cookies, including on redirects. See #211.
- When a visit fails on a cross-origin redirect, the library now follows same-origin redirects first, so a chain like
/account→/login→ your identity provider opens the identity provider. See #213. - Pages without a
<title>now show an empty title instead of the page URL, matching iOS. See #204. data-native-prevent-pull-to-refreshand scrollable elements now block pull-to-refresh. See #222.
Breaking Changes ⚠️
- If your app doesn't use
NavigatorHost, the default policy trusts nothing, and every page fails to load withLoadError.UntrustedOrigin. SetHotwire.config.originTrustPolicy. See #215. - If your app loads more than one origin in-app, links to the other origins now open in a browser tab, and pages from them fail to load with
LoadError.UntrustedOrigin. Set a policy that trusts them. See #215. LoadErrorhas 2 new cases,UntrustedOriginandWebViewNotSupported. Add branches for them to any exhaustivewhenoverLoadError. See #215.VisitError.description()is now adescriptionproperty. Switch to the property, or Kotlin callers can import the deprecateddev.hotwire.core.turbo.errors.descriptionextension. See #215.
New Contributors
Full Changelog: 1.3.2...1.4.0