Martin Suchan – BloQ Random #WPdev stuff

28Apr/1612

Make WebView great again!

When developing Universal Windows Platform (UWP) apps for Windows 10 one of the core elements developers often use is the WebView. It's a control designed for displaying Web Pages, either from local or any online source. It's basically a Frame for rendering HTML content powered by the EdgeHTML rendering core.

The WebView went through many iterations since its conception in Windows 8 in late 2012. It went from hard to use always-on-top element powered by IE10 Trident Core to a modern and quite capable control supporting current HTML5 standards and modern HTTPS cipher suites.

From a developers' point of view lot of useful methods and settings was added in the Windows 10 version of WebView, for instance event handlers to allow access to Geolocation API or Webcam, detection when the website wants to open a new window, notification about loading state od each Frame, possibility to provide native object which is then available from the page DOM, and much more.

Unfortunately, the WebView, as it's available today, is still incomplete in terms of usability and does not provide several critical APIs. In this article I have gathered the most important missing or incomplete WebView features that would make the WebView finally a first class citizen, or great again.

I sorted these features into three groups:

  • Must fix are critical security and/or functional features that cannot be implemented using any workaround
  • Should fix are features, that would make the WebView much easier to use, but are not critical for daily use or can be implemented using nontrivial workarounds, like JavaScript injection and notification back to the app
  • Nice to haves are optional improvements for making developer more happy 🙂

Note that all missing features requested below are already available in the Microsoft Edge browser. I’m not requesting something, that is not yet available in the EdgeHTML core for obvious reasons.

Must fix issues

#1 Blocking insecure requests on secure HTTPS pages

When navigating to a secure HTTPS page it’s expected that all resources on that page are loaded using secure HTTPS requests as well. Single insecure JavaScript loaded in a secure page can compromise any data on that page. This is commonly called a Mixed Content problem.

Unfortunately, current WebView in Windows 10.10586 does not block any insecure requests on HTTPS pages. This can be easily tested on this page: https://mixed-script.badssl.com/. Note it is currently possible to block the loading of Frames with insecure origins, but no chance to block insecure requests for images, scripts, styles, fonts, etc.

The expected behavior is a WebView, that is automatically blocking any active mixed content requests, just like it works by default in IE, Edge, Chrome, etc. Alternative solution might be a new event handler for every request from target page, that we can selectively block based on the target domain address.

#2 Support for HTTP Strict Transport Security – HSTS

Another critical security feature that works in current modern browsers like IE, Edge or Chrome, but not in current WebView in Windows 10.10586, is HTTP Strict Transport Security. HSTS is a security feature that lets a web site tell browsers that it should only be communicated with HTTPS, instead of using HTTP. When a website sends HSTS header, it tells the browser to:

  • Automatically upgrade on the client side all HTTP requests to secure HTTPS for the target domain
  • Do not allow “click through” the security warning about invalid domain certificate.

The Windows 10 WebView currently completely ignores the HSTS header or the HSTS Preload List, making it possible to use SSLStrip or other similar MITM tools for a protocol downgrade attack. Support for HSTS in a browser can be easily tested here: https://hsts.badssl.com/

The expected behavior is a WebView that transparently supports HSTS including the HSTS Preaload List. Again this is not possible to implement using any local workaround. It might be only possible to emulate the HSTS Preload list for initial web requests, but not for any internal requests for page resources.

#3 More granular cookie management

Right now the WebView stores all page cookies in HttpCookieManager container which is shared between all WebView instances in the app. There is no way how to create for instance Anonymous Tab with cookies separated from all other WebViews. There is also no way how to create a workaround for this issue on a client side.

The expected behavior is a mechanism allowing developers to define custom “cookie context” for any WebView.

#4 Full access to Page Navigation History

Current WebView has properties CanGoBack, CanGoForward and methods GoBack() and GoForward(). This might be sufficient for most use-cases, but not when creating full-featured custom browser. It’s not possible right now to go Back more pages in the history in single step. It’s not possible to Clear WebView navigation history or to Restore custom history from previous app session.

The expected behavior is a full-featured WebView Navigation history API allowing developers access to all entries in the Back stack and Forward stack, making it possible to Store, Clear and Restore custom navigation history. Basically it should work in a similar manner like the Frame Navigation Stack.

#5 Proper access to Frames

There is no way in the current WebView how to uniquely identify Iframes in a page or how to run custom JavaScript code in target Iframes. This is especially problematic when developer wants to handle right mouse clicks for opening custom context menu or key combos inside the page with custom JavaScript. Invoking custom script is just not possible inside Frames or Iframes.

The expected behavior is to have unique references for each Frame and have InvokeScriptAsync and AddWebAllowedObject method overloads taking the frame references as parameters, so we can run our code inside frames as well.

Should fix issues

#6 Access to full Request and Response headers

After navigating to a web page in Windows 10 WebView the app receives several events:

  • NavigationStarting - Occurs before the WebView navigates to new content.
  • ContentLoading - Occurs when the WebView has started loading new content.
  • DOMContentLoaded - Occurs when the WebView has finished parsing the current HTML content.
  • NavigationCompleted - Occurs when the WebView has finished loading the current content or if navigation has failed.

These event provide only limited information about the web page we can use and that’s a problem. For instance, there is no access to HTTPS certificate used for the TLS handshake, no information about its validity, issuer, EV status, etc. There is also no info about sent and received cookies, basic authentication header, redirects, caching options, etc.

The expected behavior is a WebView providing full HttpWebRequest and HttpWebResponse object in NavigationStarting and NavigationCompleted event args, just like developers have access to these objects and headers when using HttpClient for making web requests.

Available workaround is using HttpClient with additional HEAD request after the NavigationCompleted event is raised to access the cookies or certificate details. Problem with this workaround is obvious – there is no guarantee that the additional HEAD request will succeed or contain the same data that the WebView received moments ago. There is also no simple solution for accessing the Basic Authentication header if user wants to download a file, that is only accessible with Basic Authentication.

#7 Option to set custom User Agent or other custom headers

Related to the previous issue, it’s not possible to set custom User Agent or custom header which will be used for all requests inside the current WebView.

Although it’s possible to use NavigateWithHttpRequestMessage method with custom User Agent, the custom value is lost as soon as user navigates to a different page.

The expected behavior, there should be consistent method for setting custom User Agent and other custom headers for all requests within the current WebView or all webview in the app.

#8 Proper Popup Window handling

Since Windows 10 the WebView has a method called NewWindowRequested. This method is raised when the page requests new window to be created. This is nice, but once a new window is created, there is no link between the original page and the new popup window in the page DOM and there is no notification when the parent window is requesting window.close() for the popup window.

I’m not sure how this could be achieved in the context of separate WebViews, but right now it’s breaking some webpages, typically Facebook shows login for web comments in a new window and once the user is logged in, the new window closes and user continues in the previous page.

#9 Possibility to use different default browser on all flavors of Windows 10

It’s not possible to use different default browser on Windows 10 Mobile right now, or different default app for *.html file types. I know, that Microsoft wants Edge to be the default browser, if possible, but the option should be there at least for experienced users.

Note it’s possible to use another UWP app as a default browser on Windows 10 Desktop, but not on Mobile yet. It’s also possible to change the default browser on Android, but not on iOS just for the record.

Strictly speaking this point is not related to the WebView component, but if anyone wants to create custom UWP browser app, this is a major issue that cannot be solved right now.

#10 Possibility to load page with invalid certificate

Even though this might be a gray-zone request, I still think it should be mentioned. Right now there is no easy way how to display HTTPS page with invalid certificate in the WebView. There is only one hard workaround I know, but it’s not usable for any more complex pages.

The expected behavior, just like it’s possible in HttpClient to ignore specific certificate errors, there should be a mechanism for ignoring these errors in the WebView. Maybe after confirming system dialog or only in apps with special Capability in the manifest, but the functionality should be there in my opionion.

Nice to have

#11 TitleChanged, Favicon and FaviconChanged properties

The WebView has currently string property Title which returns the Title value defined in the HTML. Unfortunately, there is no notification about Title changes from the WebView. It would be nice to have TitleChanged event notifying the app about every Title change.

Similarly, there should be property with the path to the current page Favicon and FaviconChanged notification about each favicon change.

Note all these features can be achieved by injecting custom JavaScript into the page that would notify the app about any favicon or Title changes.

#12 Web Notifications API

Web Notifications is a new standard for displaying messages from any currently open tab. Chrome, Firefox and Safari browsers already support it and Edge should support it in the Windows 10 Anniversary Update.

It would be nice to have support for Web Notification in the updated WebView as well, ideally with some event handler where I can ignore or display any received notification.

Bonus!

Missing features discovered after completing this article:

#13 WebView printing support

When using web browser on a PC it's often required to print the content of a webpage to a paper. Many websites use for this purpose special Print Style Sheets that are applied when the content of the page is about to be printed.

Unfortunately direct printing of the WebView content is not supported right now and the recommended solution is using WebViewBrush to render the content of a WebView to a Rectangle and print that. This is very limited solution as you can see.

The expected behavior is support for printing similar to the printing options currently available in the Edge browser, including Print Style Sheets and preview rendering.

The summary

Why am I writing all this? We’ve just recently started developing Seznam.cz browser for Windows 10 and most of these issues emerged in the analysis and prototyping phase. Even though we managed to work around most of these issues, my fingers are crossed that the remaining issues will be fixed ideally in the Anniversary Update 🙂

Even though there is a lot to fix in the WebView, I’d like to thank the Microsoft Edge team for making a fast and modern rendering engine. Keep up the great work guys!

So thanks for reading the post to the very end, and as always, if you have any comments or questions, you can ping me on my Twitter, thanks!

  • Mike

    #9 Possibility to use different default browser on all flavors of Windows 10
    IMHO has nothing to do with WebView. WebView is part of an app and should use the most reliable (in terms of compatibility with SDK) UA which would always be the system UA which is Edge. Same as on Android where it is Chrome.

    • Martin Suchan

      I’ve updated that point. Note that Edge uses different UA than Android, and the WebView uses even another different UA.
      The option to use custom UA might be helpful in case some websites don’t work with WebView UA – the possibility to spoof Edge or iPad UA might help, but this is not possible right now.

  • Mike

    Not sure if it belongs here but Printing from A WebView in a JS based app is currently broken (actually for months now). Maybe working from a WebView in a XAML based app but I have not tested that. But that would be a priority 1 bug to fix IMHO.

    • Martin Suchan

      I’ve added Point #13 – Proper printing support. Thanks for this hint!

  • Κωστας

    Hello Martin, this is a great summary of how Microsoft should improve the WebView! I hope they make it quickly!

    In your experience, have you found a way to intercept an AJAX POST request, read the post content and respond with custom data?
    For GET requests I have used successfully the IUriToStreamResolver interface.

    Thank you

  • Make Luv

    Change default User-Agent not fixed yet?

    • Fabio Di Peri

      You can change the default user-agent calling a win32 api via dllimport, not sure if it would be accepted on the store

  • Pingback: Hacking UWP WebView Part 3. Bypassing HTTPS certificate validation in UWP WebView « Martin Suchan – BloQ()

  • Rafael Martins

    Context menu for links and images. I need this. And a better download suport.

    • Deepak Yogi

      Hello Martins,

      i am using WebView in my application. In that custom user-agent not working properly
      any idea how can use it.

      • Rafael Martins

        Actually I only use the user agent to send an equest to use in desktop mode, because unfortunately the user-agent has to be required every time I start a navigation, so I do not try to put my app information in it (Caravelle).

  • Herrick

    Hi,

    Thanks for the informative post !

    More than a year has passed since that post and anniversary update was released…

    I Wonder if any of that got fixed/improved since then or if WebView is still lacking all these functionnalities.

    Thanks again !

  • Deepak Yogi

    Hi,

    i am using WebView in my application. In that custom user-agent not working properly
    any idea how can use it.