Brian
Brian

Reputation: 325

Cordova - internal hyperlinks always open in Safari

I'm very new to Cordova, so it may be that I don't fully understand its purpose. Let me start with what I'm trying to achieve overall.

We have an asp.net website that has mobile support, that I'm basically just trying to wrap with an iPhone app. The site of course runs on an IIS server, so I just want a thin wrapper to launch the site, and remove the address bar, navigation, etc. It's my understanding that you can achieve that with the Cordova hybrid approach.

I followed the tutorial, and got the site to launch within an xCode iPhone Simulator, and it came up just like I wanted to.

The problem I'm having is that hyperlinks within the site launch the target page in a Safari browser. And from all of my googling, it seems like this is the opposite problem most people have. It seems like most people struggle with external sites opening within the app, which basically locks them out of their app. I'm just trying to go from Page1 to Page2 on my own site within the app.

I was able to reproduce this problem with the simplest of sites, so I'll post the relevant bits. In this example, clicking on "Page 2" will open up in Safari.

Asp.net site:

Page1.html

<html>
    <a href="page2.html">Page 2</a>
</html>

Page2.html

<html>
    Page 2
</html>

Cordova:

Index.html

<!DOCTYPE html>
<html>
    <head>
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    </head>
    <body>
        Cordova site
    </body>
    <script>
        window.location = "http://192.168.1.157:8081/Page1.html";
    </script>
</html>

config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget id="vsisolutions.testsite" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>Test Site</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="[email protected]" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <allow-navigation href="http://192.168.1.157:8081/*" />
    <allow-navigation href="*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
    <engine name="ios" spec="~4.1.1" />
    <plugin name="com.msopentech.authdialog" spec="~0.1.6" />
</widget>

Thanks for the help!

Upvotes: 3

Views: 1676

Answers (4)

user3171221
user3171221

Reputation: 1

Just changing allow-navigation to append with * worked:

<allow-navigation href="http://yourwebsite/*" />

Upvotes: 0

jcesarmobile
jcesarmobile

Reputation: 53301

This was a bug

It was fixed on latest released version of cordova-ios 4.2.0

So you don't have to do any hack to make it work anymore, just have to use the allow-navigation tag to set the urls you want to allow to navigate inside the app, and the rest of them will open in safari as you have allow-intent set for all http and https urls.

Upvotes: 2

Guy Lowe
Guy Lowe

Reputation: 2370

I found that in Cordova the WKWebView plugin (it could be occurring in the UIWebView as well) asks around for any other plugins to see if they can use URL on the link. This was being picked up by the CDVIntentAndNavigationFilter and running through the logic as in:

- (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:    (UIWebViewNavigationType)navigationType
{
   NSURL* url = [request URL];

 switch (navigationType) {
    case UIWebViewNavigationTypeLinkClicked:
        // Note that the rejection strings will *only* print if
        // it's a link click (and url is not whitelisted by <allow-*>)
        if ([self.allowIntentsWhitelist URLIsAllowed:url]) {
            // the url *is* in a <allow-intent> tag, push to the system
            [[UIApplication sharedApplication] openURL:url];
            return NO;
        }
        // fall through, to check whether you can load this in the webview
    default:
        // check whether we can internally navigate to this url
        return ([self.allowNavigationsWhitelist URLIsAllowed:url]);
    }
}

Because the navigationType == UIWebViewNavigationTypeLinkClicked it was passing it off to the browser via [[UIApplication sharedApplication] openURL:url];

Currently I have only found a hack around this and that is to override this logic by treating links in the same way i.e. like so:

switch (navigationType) {
  case UIWebViewNavigationTypeLinkClicked:
    // Note that the rejection strings will *only* print if
    // it's a link click (and url is not whitelisted by <allow-*>)
    if ([self.allowIntentsWhitelist URLIsAllowed:url]) {
        // the url *is* in a <allow-intent> tag, push to the system
       // [[UIApplication sharedApplication] openURL:url];
        return YES;
    }
    // fall through, to check whether you can load this in the webview
  default:
    // check whether we can internally navigate to this url
    return ([self.allowNavigationsWhitelist URLIsAllowed:url]);
    }
}

This is obviously not ideal and I'll ask around on the Cordova forum for a better solution which I'll post here once I find it.

Upvotes: 2

May Rest in Peace
May Rest in Peace

Reputation: 2207

<a href="page2.html" target="_blank">Page 2</a>

This should work.

Upvotes: 0

Related Questions