WKWebView has been the modern way to create webviews for some time on iOS. It would be best to support that.
The only backwards compat friendly mode of implementation here is to copy the old renderer to WKWebViewRenderer
and modify it to use WKWebView
. This renderer will then be available but not enabled by default.
No Change
If the user puts
[assembly: ExportRenderer(typeof(WebView), typeof(WKWebViewRenderer))]
in the AssemblyInfo.cs of their application, they will then use the new renderer.
No change
Not relevant to CSS
All good since this makes no modifications to existing code and is 100% opt-in.
There will likely be some hiccups in the port but it looks to be fairly straightforward. There will certainly be unresolvable behavioral differences, but to a certain extent that is expected.
i think we might use #1578 for this no?
I can take this! Some tweaks are definitely needed, but I have this mostly implemented already on a personal project 😄
Moving to InProgress :)
Hey @alanag13, you still working on this? If not we can move it back to the ready for work column
Yeah like I said I basically have this already done, it just needs some tweaking. I should be able to get in within a couple weeks if that's okay.
Thats fine, you might get another checkup message before then, we're just trying to make sure we keep this all organized :)
I still haven't gotten started on this in an official XF capacity, but I'd like to continue on with it. WKWebView has a lot of quirks that I took the time to overcome in my aforementioned implementation that are not easily discoverable that I think others wanting to pick this up could easily miss.
If I still don't have anything to show for this the next time @davidortinau asks for status updates I'm happy to return it to the available items and maybe summarize some of those oddities in a post.
@alanag13 - Any progress on the renderer? We've been banging our heads against the walls on this for a while now and would love to see what you've got--maybe even the unfinished version if you don't mind so we could get insight on how to solve some of our issues. Thanks!
yep, it'd be great to see any version
FWIW, UIWebView has been deprecated as of iOS 12.
Of course it's been deprecated... and WKWebView is still frighteningly buggy (you can't modify a POST without it breaking). However, I've put together a basic version of a renderer/WKWebView/delegate that I'll try to upload today. It by no means has any kind of feature parity, but maybe it'll help someone get started.
Ok, here's a gist with most of the stuff needed to get it working. It alphabetizes by filename automatically, so you'll mainly want to look at WebViewCustomRenderer.cs and WKWebViewCustom.cs.
This is a _pretty basic implementation_, and I recognize I may not be doing things the best way. It handles loading external URLs in browser instead of in the WebView, logging out, and has simple back/retry methods in case the loading in the WebView itself fails. The main thing that we wanted to do, though, was add headers on our first request (this info is then stored in a cookie server side), which we do in the WebViewCustomRenderer.cs file.
NOTE: as I mentioned, you can't modify a POST (not even adding headers) without it breaking. This is a known bug in WKWebView that has been around for years. Apple has not fixed it, nor do I have faith they will any time soon. There are a few sketchy ways around it, but for the most part if you need to add a header to a POST or modify a POST for any reason, you're out of luck.
Hope this helps. 😄
@mrdaneeyul couldn't you do a PR for it ? And I will help with review and make sure is feature complete.
We would need to keep the old renderer around for back compact issues.
@rmarinho I wouldn't mind contributing, since it'd turn my pain of working with WKWebView into something useful, but I'm not certain my implementation will work for that. In order to modify headers, for example, you'd need to make a custom renderer anyway, even with UIWebView or in Android. The way you do it with WKWebview is just different and a little more complex. My request interception in the delegate is pretty specific to our app use, but is good for an example of how to do it.
If we're talking a pull request to replace UIWebView with WKWebView, I'm worried that's a bit out of my depth. I'm curious to give it a look though.
So, should we still expect @alanag13 to own this? What's the direction with this issue as of now?
@adrianknight89 i will talk with the team so we can have a better understand where we are going to scheadule this work. It's in our backlog. As for now i don't think we will pick it up the the next 2 weeks , so i will mark as up for grabs if anyone wants to do it now.
Is this something you think you want help?
Thanks
@jassmith @rmarinho If [assembly: ExportRenderer(typeof(WebView), typeof(WKWebViewRenderer))]
is placed in AssemblyInfo.cs
, doesn't that force the developer to forgo the old renderer across the app? What if some pages needed to use the old one for example due to a lot of existing renderer customization?
Also, should this be put in the assembly info file for the ControlGallery
app (i.e. are you okay with it)?
I was thinking more in using the feature flag (like we have for fast renderers on android) , and one day remove the need to use the flag and make it the default renderer if @jassmith agrees.
Also, both UIWebView and WKWebView trigger multiple ShouldStartLoad
and DecidePolicy
calls (for example once for the main content and every time an async plugin is being loaded). The current logic for ShouldStartLoad
is to send a Navigating
event every time this occurs.
Strangely, you might get these invocations even after navigation is complete (i.e. after Navigated is raised in another handler). So, the user will get (depending on the web page) Navigating events raised while they think navigation is already complete.
My question is, when you were designing these events, what did you have in mind? Were you assuming Navigating would never be raised after Navigated? Another strange quirk I've seen is, for these types of partial views, iOS sometimes never raises an event for navigation completion.
Right now, it is possible to get event chains like this:
Navigating
Navigating
Navigating
Navigated
Navigating
Navigating
....
i.e. multiple Navigating events back to back and Navigating events after Navigated is raised.
whereas what I assumed initially was WebView
would raise both Navigating and Navigated once and in this particular order.
How should the new renderer be designed with regards to this matter? Also, remember that Navigating has a Cancel property to selectively stop navigating to / fetching a resource.
@davidortinau Can these be migrated over to Github?
https://bugzilla.xamarin.com/show_bug.cgi?id=41760
https://bugzilla.xamarin.com/show_bug.cgi?id=58337
https://bugzilla.xamarin.com/show_bug.cgi?id=54072
I don't feel comfortable about how these navigation events are firing in Core, and they [probably] exhibit different behavior on different platforms. Maybe axe the existing events and introduce new ones?
Here's a test output of a custom WKWebView
I made:
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> didstartprovisionalnavigation
[0:] DEBUG ======> didcommitnavigation
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> didfinishnavigation
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
[0:] DEBUG ======> decidepolicy
If DecidePolicy
is sending out Navigating
events, you could imagine just how many of them we'll be getting and we might get them after Navigated
is fired. In cases when JQuery fires an async script load on documentReady, this issue can happen or when tracking scripts are being loaded.
I came across an even scarier scenario when we click a link that opens an app installed on the phone:
[0:] DEBUG ======> decidepolicy
Yep, iOS fired nothing else but a single DecidePolicy. :)
As for navigation completion, at least on iOS, we could pursue different paths such as KVOs or both LoadHtmlString and LoadRequest return a Task (not sure what handling completion of these tasks means presently).
Having said that, if we copy the old renderer into the new one [with minor mods] as @jassmith mentioned, we'll be bringing along existing behavioral bugs. I think the team should first research the navigation logic across all platforms before introducing a new renderer. What do you think?
@alanag13 Would you mind sharing your implementation as it currently stands?
Hey @kingces95 sorry for my absence here just been busy. I'm setting aside some time to address the items assigned to me here and I'll get you something.
Most helpful comment
@alanag13 - Any progress on the renderer? We've been banging our heads against the walls on this for a while now and would love to see what you've got--maybe even the unfinished version if you don't mind so we could get insight on how to solve some of our issues. Thanks!