[Enhancement] Improved WebView That Supports Async Cancellation + Extensibility
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
## Summary
In Xamarin.Forms I had raised the following issue & PR:
[[Bug] WebView Navigating Race Condition #12720](https://github.com/xamarin/Xamarin.Forms/issues/12720)
[WebView Navigation Now Uses Deferral Token #14137](https://github.com/xamarin/Xamarin.Forms/pull/14137)
A requirement for the app I was developing at the time was to confirm ability to navigate to a site within the webview (if I click microsoft.com, is the user allowed to visit the site). This functionality was restricted by the implementation of the webview the cancellation result could not be delayed.
I raised an initial PR converting the implementation to use a task. @PureWeen had a great suggestion of using a `DeferralToken` to control the navigation, making the whole cancellation process easier for multiple subscribers to halt. I have raised that PR but it contains a break to the API, so is not suitable for Xamarin Forms.
I had business needs to implement this feature as any hacks / work arounds carried other bugs which were not ideal. I forked the WebView control and currently use an [alternate implementation](https://github.com/Axemasta/SuperWebView) of `WebView` which contains the changes I made in this PR + extra nice to haves.
I was reading the implementation of `WebView` in MAUI and its the same as in forms, meaning that the issue will persist in MAUI. Since MAUI is in development, I think its the perfect time to revisit the API of `WebView`, make the control more powerful aswell as addressing some pain points I experienced refactoring the code for my control.
## API Changes
Change `WebViewNavigatingArgs`:
- Remove `Cancel` boolean
- Add `DeferralToken` property
- Cancellation is performed in the following manor:
```csharp
private async void OnNavigating(object sender, WebNavigatingEventArgs e)
{
if (e.CanCancel)
{
var token = e.GetDeferral();
bool canBrowse = await CanBrowse(e.Url);
if (!canBrowse)
{
e.Cancel();
}
token.Complete();
}
}
```
The API changes I made in my XF PR ended up refactoring the deferral token code from Shell & making it more generic. I also changed the navigating args to implement an interface instead of inheriting an abstract base:
```csharp
public interface IWebNavigationEventArgs
{
WebNavigationEvent NavigationEvent { get; }
WebViewSource Source { get; }
string Url { get; }
}
```
This was so I could make the `DeferralToken` available to the event args by inheriting a base class.
## Intended Use Case
This will generally improve the experience developers have with `WebView`. Developers can confirm navigation without having a race condition present when navigating. The only way I could get around this issue in XF without my custom `SuperWebView` was to cancel navigation immediately, run a task then re-navigate (this was hacky & caused other issues).
## Proof Of Concept
I have raised this issue & will put up a PR with my first cut of what I think it should look like. I'm very happy to accept and and all advice for design & implementation + I would like ideas on the best way of testing this functionality.
I've maintained the code for iOS & Android and the implementations vary WILDY between them, so it will end up affecting a lot of code. I think there will need to be a lot of testing to make this feature a success.
Contributor guide
Research direction
The issue names WebView, WebViewNavigatingArgs, the iOS and Android implementations, and Shell’s deferral-token code as the relevant entry points. Read those implementations first and identify the existing navigation event and cancellation tests; no test files are named. Done means agreeing on a compatible deferral-based API, implementing it across both platforms, and covering delayed cancellation and multiple subscribers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, csharp, ios
- Domain
- frontend, mobile-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100