Thursday, April 14, 2016 2:13 PM

Problems with window.open under iOS using Ionic/Angular and Cordova

Author: matthias - Last modified: Wednesday, August 3, 2016 10:13 PM

en cordova  ios angular  ionic  javascript  bug  gap  csp

This is just a short note about how I solved a weird problem I recently experienced when window.open wouldn't work using Ionic/Angular with Cordova under iOS (9).

It's about having trouble to get window.open actually opening a window, not within current view, nor within new in-app-browser or external browser window. And it is related to using Cordova plugins, especially inAppBrowser, and having a CSP (Content-Security-Policy) defined with the main HTML file.

Searching on e.g. stackoverflow I wasn't able to find someone describing the very same problem and it was hard to find articles that brought me on the right path. Took me some time to debug stuff. So, I'm pretty sure there must be others out there who're facing the same problem I want to describe as concise as possible:

Scenario & Objective

A controller function (available through $scope) is defined as a ng-click attributes` value as:

<a ng-click="openTerms()">Terms & Conditions</a>

The function should open a new in-app-browser window and is defined within an angular controller like this:

$scope.openTerms = function() {
   window.open('http://www.example.com/terms', '_self', 'location=yes');
}

Effect

It works as expected when tested within a Desktop browser. But nothing happens on click when deployed and tested within the iOS simulator or directly on the device, (more precisely: under iOS 9 in my case). Additional effect I experienced however is that the window unexpectedly opens when the original click is followed by another action taken like clicking on a form field or triggering an internal router navigation step.

Inspecting the Cordova/iOS device logs as well as JavaScript logs shows up entries that caught my attention to investigate on it:

cordova.js: xxxx deviceready has not fired after 5 seconds 

In my case there was also another entry telling that Ionic was 'not ready' due to incomplete loading of plugins.

When having a close look on the JavaScript console I discovered log entries complaining that the Content-Security-Policy denies access to resources under the URL scheme gap://.

Solution

Adjust your Content-Security-Policy to allow accessing resources for gap::

<meta http-equiv="Content-Security-Policy" content="
    default-src
       'self' 
       gap:
       ...
    ...
">

Background & Conclusion

The gap scheme is Cordova specific, it enables JS <-> native communications for iOS. A missing CSP entry somehow prevents the plugins from loading fully or correctly.

Strange enough, using Ionic and Cordova examples extensively, there hasn't been a single example template nor note about not to forget the famous gap url scheme entry...

So, to be honest: I'm not sure about the exact root causes and it's still confusing me. But I haven't got enough time to spend more time on investigating on every single strange behavior or effect. This article just describes my specific scenario and how I successfully solved it.

If you want to dive deeper into the details of Cordova and Content-Security-Policies under iOS, you might want to check an in-depth article about it.

Hope to help others with it!

Comment / Share »