WebView Javascript interop woes in Windows (Phone) 8.1 Universal apps

I’m currently working in a project creating a web-hybrid app on Windows Phone (and iOS and Android). My role is creating the Windows Phone version, and I’ve bumped into a few hurdles that I’d like to share my adventures on.

For the impatient:

- Use script debugging to discover WebView problems

- Don’t end your Content URIs in the app manifest with a wildcard asterisk

- Beware of Javascript initialization/execution delays when calling scripts on the WebView from managed code

 

Now, onto the vivid explanation.

Javascript interop in general

The basics of interacting with Javascript (JS) in the WebView is described in our series on Windows Phone 8.1: Windows Phone 8 native and Javascript interop. Basically you call InvokeScriptAsync on the WebView to call JS from C#, and you can receive calls from JS through window.external.notify and WebView.ScriptNotify.

Debugging the WebView

Fortunately, the WebView can be debugged. The dev center article: Debug a WebView control describes how script debugging is done. In short, the process is:

1. Switch from managed to script debugging

script-debugging

2. Open the JS console

js-console

You will soon see how this renders itself very useful…

Woe 1: web-to-native

Help! My app does not receive any ScriptNotify events from the WebView, even though I’ve defined the URI as a content URI in the app manifest!

Back up a second, what manifest? For the WebView to allow JS communication via window.external.notify, the Windows app has to pre-define the URI in its manifest, and the endpoint has to be a https endpoint. The documentation on the WebView.ScriptNotify event clearly states this. Wildcards are allowed for the subdomain, e.g. https://*.jayway.com.

content-uris

So, the problem is that the JS code calls window.external.notify but no events are received via ScriptNotify, hmm…

A quick switch to script debugging shows the following output in the JS console:

DOM7010: Unable to receive a ScriptNotify event from: ‘https://api.jayway.com/index.html’. The website attempted to send a ScriptNotify event to the app from a WebView URI that is not included in the ApplicationContentUriRules for this app. To permit this event, add the URI to the ApplicationContentUriRules section of the package manifest. (In Visual Studio, add this URI to the Content URIs tab of the Manifest Designer.)

Aha – the URI is not correctly formatted.

I got your back: The Content URIs should not contain wildcards at the end.

Script debugging is your friend.

Woe 2: native-to-web

Help! I’m calling JS methods on the WebView via InvokeScriptAsync, but they’re not executing! I’m even waiting for the NavigationCompleted event.

So again, unexpected behaviour, but no exceptions or errors. Switching to script debugging and running immediately asks for our attention:

js-error

What? I know that the method is defined. Aha – maybe the JS hasn’t finished executing yet.

I got your back: Make sure your JS has finished executing before attempting to call methods on it.

We did this by adding a JS-to-managed call at the very end of JS init, and our managed code waits for that call before being allowed to call any methods on the WebView.

Script debugging is your friend.

Enjoy!

Leave a Reply