What did I learn today?
Today I learned that opening local content in InAppBrowser on iOS devices using the system browser (Safari) is impossible. This is due to Apple’s security scheme setup to protect iOS devices from total security failures due to improperly secured applications. This is a GOOD thing! Without sandboxing, a hacker could exploit a vulnerability in an app to gain access to the entire device.
I’m going to explain how I chose to maintain current functionality of viewing content in an InAppBrowser while still giving the user the option to share the content using default mechanisms.
The Setup
I’m working on an Ionic mobile application that accesses a remote web service the serves content stored by a content management system. In the past, content was stored on a file server and the web service would return the location of the content to the mobile app. Users could then click on the content in the mobile app to download the files and view them on the device. Users could then use the share button to send the content using built in functionality of Safari on iOS.
A new requirement specified that content could no longer be stored on the file server but should be served from the database. Easy right? Just send the over the wire as a byte array and save to the device. But this had unintended consequences.
Background Information
Apple Sandboxing
For full information about this topic please read the documentation on Apple’s website.
The long and the short of it, Apple Sandboxing is great for security but makes things tough when you want to do specific things for perceived usability improvements. Any application written on iOS has its own set repository of data and system resources. It cannot touch another applications repositories or resources.
InAppBrowser
For full information about this topic please read the documentation on ngCordova’s website and the documentation on Cordova’s website.
The InAppBrowser plugin available for Cordova apps is a pretty amazing widget. Almost all of the functionality you could ask for when trying decide how you want to open content in a browser. The thing I mess up the most is what target my window should open with. There are currently 3 targets:
- _self – Opens the path in the Cordova Webview if the domain is in the whitelist of the app. I’ve never actually used this one.
- _blank – Opens the path in the InAppBrowser itself. It offers a lot of events that can be subscribed to for a very user friendly experience.
- _system – Opens the path in the default device browser (Safari in iOS)
The Issue
Before Changes
The previous version of the application was very user friendly. Users were able to easily click on content, view the content in Safari and then share content using built in iOS features. The image below shows what this looks like opening the content in Safari. This was using the “_system” target of InAppBrowser.

My new requirement though was to eliminate calling the web server to retrieve the content from the file system and store it on the device. This created the problem of a blank white screen.
The Fix
The Code
$scope.openFile = function (entry, mimeType, share) {
var nativePath = entry.toURL();
if (share == true) {
$scope.isLoading = false;
$cordovaFileOpener2.open(nativePath, mimeType).then(
function () {
$scope.isLoading = false;// Success!
}, function (err) {
console.log(err);
});
} else {
var path = decodeURIComponent(nativePath);
inAppBrowserRef = cordova.InAppBrowser.open(path, '_blank', 'enableViewportScale=yes,location=no');
inAppBrowserRef.addEventListener('exit', onExit);
}
}
function onExit() {
$scope.$apply(function () {
$scope.isLoading = false;
});
}
After Changes
I accomplished two things as shown in the above screenshots.
- I incorporated a share button at the top of each content item to get users to opportunity to share the content since InAppBrowser does not contain this functionality. This opens the iOS drawer that allows cross app share sharing by copying the content into other applications repositories.
- I am now opening the content in InAppBrowser using “_blank” target option which shows a “Done” button in the lower left hand corner.