Ten Things You Need to Know About WebView - An Update for Windows 8.1
If I've learned anything in the past year that I initially wrote Ten Things You Need to Know about WebView, it's that WebView continues to be one of the most used controls in Windows Store apps. It is a control that many people are looking to manipulate and hack in order to bring additional functionality to their app.
Now that Windows 8.1 has been out awhile, and with BUILD releasing the Windows 8.1 Update (with no WinRT APi changes) it's time to update my original post with updated information and additional information in order to make your WebView experience more productive. Here are my ten original points:
- WebView is not a general-purpose browser
- WebView always renders on top of XAML
- WebView doesn’t do Flash. Or Silverlight. Or PDF. Or any other ActiveX control or plugin.
- How to invoke Javascript inside the displayed webpage of a Webview
- How to receive information from the WebView
- How to inject javascript into a WebView page
- How to clear the WebView cache
- How to embed a font into your app to be used by WebView
- Launching other apps from a link inside WebView
- How to get rid of those annoying JavaScript exceptions when debugging
-
WebView is not a general-purpose browser.
"The WebView control is intended to allow a Store app developer to embed some part of the web inside the application, but should not be added to an application to allow browsing to any site on the Internet - it should be used to link specifically to pages hosted on your own website for the purposes of being displayed within your Store application."
I want to emphasize that this still holds true. The WebView should be used as a part of your overall application - allowing insight into parts of the web which are intended to be an extension of the experience which you can't/haven't gotten to incorporate into the app just yet."Aside from that, you are going to find that some things simply don’t work the way that they do in the full Internet Explorer browser. It’s not that these changes are intentional; it’s that this is a different (but similar) codebase – it is not IE. In fact, the documentation is clear about the limitations of this control:"
Even though greatly improved, the WebView still renders some things differently than standard IE, and you should plan on testing your app thoroughly in order to confirm that it works according to your specifications. However, let's look at a piece of documentation that has been changed.Original:
"WebView always uses Internet Explorer 10 in document mode. Additionally, WebView does not currently support HTML5, AppCache, IndexedDB, programmatic access to the Clipboard, or geo location, and supports only the Document Object Model (DOM) properties that are supported in Windows Store apps using JavaScript."
Changed: "WebView always uses Internet Explorer 11 in document mode."
I don't think that this means that every feature listed in the documentation originally has been added. Indeed, I know of forums posts where someone tested one of these features and found it to not work: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/2de1f83e-345b-416a-875b-ae521b0bc44b/application-cache-support-in-webview-in-windows81?forum=winappswithhtml5. If your application relies on one of these technologies, please plan on testing it to ensure that it exists in WebView.
WebView always renders on top of XAML
As noted in my previous post, the original WebView control always renders itself on top of existing XAML - this was known as the "airspace" issue.In 8.1, we now have the full power of XAML that will allow us to manipulate it as we please. The documentation now has a laundry list of new features which you can perform on the WebView control, such as Transforms, Opacity and Focus.
WebView doesn’t do Flash. Or Silverlight. Or PDF. Or any other ActiveX control or plugin.
This still holds true. The WebView will not load any plug-ins. However, one significant addition to the WinRT API set is the Windows.Data.Pdf namespace, which allows for rendering of PDF documents in XAML.
How to invoke JavaScript inside the displayed webpage of a WebView
How to receive information from the WebView
The original code that I posted for both invoking script and receiving notification from a JavaScript page still works fine in Windows 8.1, for the most part. There are a couple of important changes to invoking JavaScript which you must note in order to continue using this code:
- The method InvokeScript has been deprecated in favor of InvokeScriptAsync.
- In Windows 8, in order to receive notifications, the URI of the webpage had to have been added to a whitelist of URIs permitted to send the notification to the receiving page's ScriptNotify event handler. To do this, the following methods were used:
- AllowedScriptNotifyUris
- AnyScriptNotifyUri
- AllowedScriptNotifyUrisProperty In Windows 8.1, these WebView methods have been deprecated in favor of a whitelist which must be compiled into the app via the ApplicationContentUriRules section of the Package.appxmanifest. See more about this in the documentation.
How to inject javascript into a WebView page
In the original article, I published a rather clumsy method of getting new information into an HTML page. However, I've since learned that a far more effective manner of injecting JavaScript is by use of the eval function. Here's a simple sample of how to write to the document using the eval() function:
await MyWebView.InvokeScriptAsync("eval", new string[] { "document.write('Hello World!')" });
You should note that it is necessary to declare a string array in order to pass the parameters.
How to clear the WebView cache
It's unfortunate, but we still don't have a way to remove the WebView's cache, either programmatically or in the system, other than going into Explorer and manually doing a delete. We are still looking at the best ways to get this feature into v.Next.
How to embed a font into your app to be used by WebView
Launching other apps from a link inside WebView
How to get rid of those annoying JavaScript exceptions when debugging
I think that you'll find that the information presented in the original article still stands as well as it did when I originally wrote it for these points.
Now introducing x-ms-webview:
One thing you’ll notice is that the original post was written from the C#/.NET perspective – that’s where I do almost all of my work, and the sample code is easily ported to Visual Basic and C++. However, the JavaScript apps were not included in the WebView fun, so Windows 8.1 introduces x-ms-webview. The control gives you far more control over the displayed web content than a typical iFrame while allowing native integration.
The feature set of x-ms-webview closely matches the set on WinRT WebView but not one-for-one. Watch for future posts regarding this control and how it is effectively used in your JavaScript application.
Had it have it : NavigateWithHttpRequestMessage
There are many new features in WebView for Windows 8.1, but there is one that in my opinion, holds the greatest value of all of them: the method NavigateWithHttpRequestMessage.
The inclusion of this method resolves a major issue that developers have been asking about - how to pass cookies/headers along with an initial request to a WebView. The sample code shows how to pass cookies into a WebView for a request:
try
{
Uri baseUri = new Uri(txtURI.Text);
Windows.Web.Http.Filters.HttpBaseProtocolFilter filter =
new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
Windows.Web.Http.HttpCookie cookie =
new Windows.Web.Http.HttpCookie("cookieName", baseUri.Host, "/");
cookie.Value = "cookieValue";
filter.CookieManager.SetCookie(cookie, false);
Windows.Web.Http.HttpRequestMessage httpRequestMessage =
new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, baseUri);
wvTest.NavigateWithHttpRequestMessage(httpRequestMessage);
}
catch (Exception oEx)
{
// handle exception
}
What’s interesting about this is that you don’t see any obvious connection between the HttpbaseProtocolFilter and the WebView. It’s because the HttpBaseProtocolFilter and the WebView rely on a shared cookie container in the app’s sandbox. When the filter puts a cookie into the container, it’s accessible by the WebView and is sent when it pertains to that particular URL.
Thanks to my buddy Prashant Phadke for figuring out and writing the source code above.
New Navigation Methods:
Something that WebView sorely needed was better navigation events, and they’ve been provided in Windows 8.1:
- NavigationStarting
- ContentLoading
- DOMContentLoaded
- NavigationCompleted
- FrameNavigationStarting
- FrameContentLoading
- FrameDOMContentLoaded
- FrameNavigationCompleted
We needed to come up with parity to the WebBrowser control in WP8, and these events were being asked for on the forums. These events can come in very useful when injecting JavaScript into the page, or determining how the page interacts with your app.
I hope this update gives you the information you need when upgrading your app from Windows 8 to Windows 8.1, as well as gives you the new functionality you need to get your website working properly in a WebView.
Comments are encouraged, and feel free to tweet to me at WinDevMatt, or use my team’s handle WSDevSol.
Comments
- Anonymous
April 08, 2014
Hi Matt, We are building an application that needs to send all traffic through a custom secure http tunnel. This includes traffic for certain web properties that we need to load within our app. We have implementations in the works on iOS and Android and are exploring Windows Phone support. For Windows Phone, we are planning to use WebView to load these web properties and want to provide the underlying "transport" layer for the WebView instance such that ALL HTTP(S) GET/POST requests made by WebView instance used in the app come back to us so that we can fulfill those HTTP requests through the secure http tunnel. If we create a custom filter (msdn.microsoft.com/.../windows.web.http.filters) and instantiate HttpClient with the custom filter, is there any way to have WebView make use of this HttpClient (with our custom filter)? If not, could you please recommend any alternate approach? We obviously do not wish to write the browser from scratch! Please help us to handle above situation.