Showing posts with label mobile safari. Show all posts
Showing posts with label mobile safari. Show all posts

Tuesday, January 12, 2016

Opening App Transport Security failures in Safari

One of my client projects is an iOS application which, like many iOS Applications, has an embedded web view, which it uses in this case to display help content from the web. Because this app targets iOS 7.x as a baseline, it uses UIWebView instead of, say, SFSafariViewController.

The help content is part of the company's website, and the web page footer has social media links, and some of these links, if you clicked on them, wouldn't load.

Initially, I thought this might be because of the target="_blank" attribute, which has been a problem with UIWebView in the past, so I built a UIWebViewDelegate that would inject a little bit of JavaScript to remove the targets. It didn't work. So I changed the JavaScript to set the target to "_self". Still didn't work:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *injectedJavascript = @"function "
      "AppPrefix_Injected_suppressBlankTargets() {\n"
      "  var links = document.getElementsByTagName('a');\n"
      "  var hrefs = [];\n"
      "  for( index = 0; index < links.length; index++ ) {\n"
      "    var link = links.item( index );\n"
      "    if( link.getAttribute( 'target' ) == '_blank' ) {\n"
      "      link.setAttribute( 'target', '_self' );\n"
    "      hrefs.push( link.outerHTML );\n"
      "    }\n"
      "  }\n"
      "  return hrefs.join();\n"
      "}"
      "AppPrefix_Injected_suppressBlankTargets();";
    NSString *result = [webView 
      stringByEvaluatingJavaScriptFromString:injectedJavascript];
    DLog( "Injected javascript to suppress blank targets on links: %@", result );
}

Having failed on two assumptions, I realized that I should verify my assumption instead, and implemented webView:didFailLoadWithError, which quickly showed me that the actual problem was App Transport Security.

The social media links? Some of them are HTTP rather than HTTPS, and those ones won't load because App Transport Security doesn't like it. That left options.

Disable App Transport Security?
I don't like going this route until I have to.  I don't want to whitelist certain sites because the social media links might lead to other sites which would also need to be whitelisted and then eventually you just end up disabling app transport security anyway.

Open ATS Failures in Safari
What I ended up doing instead is listening for errors (webView:didFailLoadWithError) and then check the error. If it was an app transport security failure, pull the URL out of NSError's userInfo and then open that link in mobile safari instead.

It's fairly straightforward. Write a UIWebViewDelegate like this:

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    NSURL *failedUrl = [self parseATSError:error];
    if( failedUrl != nil ) {
        DLog( "ATS Failure, opening in Safari: %@", failedUrl );
        [[UIApplication sharedApplication] openURL:failedUrl];
    } else {
        DLog( "Failed to load, with non-ATS error: %@", error );
    }
}

- (NSURL *)parseATSError:(NSError*)error {
    if( error == nil )
        return nil;
    if( ![error.domain isEqualToString:NSURLErrorDomain] )
        return nil;
    if( error.code != -1022 )
        return nil;
    NSString *url = error.userInfo[ NSURLErrorFailingURLStringErrorKey ];
    return [NSURL URLWithString:url];
}

This seems to work. So if you're using an UIWebView and running afoul of App Transport Security, maybe this will help you.

Monday, June 27, 2011

Tabs in Mobile Safari


I don't get it.

I've never really understood why people felt they were missing "tabs" in mobile safari. I use tabs all the time in desktop browsers, but in iOS in both the iPhone and the iPad, I felt like Apple had selected the metaphor that worked best for the constraints of the smaller screens.

Safari still has multiple open pages, but you switch between them using an icon which allows you to scroll horizontally through thumbnails of the pages that you have open:


Clearly, there are people who disagree with me. There are lots of people who have wanted tabs in mobile safari since the very first iPhone, there are lots of iPhone browsers that support tabs and now tabs are coming to Mobile Safari in iOS 5.

There are also people who agree with me, so I was pleased to read that Lukas Mathias has a similar point of view. In his post on iOS 5, he wrote:

Apple replaced that simple, beautiful, easy-to-understand, high-bandwidth UI with a row of text labels that show the first few words of the titles of about four open web pages.

Why? Simply to cut the one tap required to enter the zoomed-out view? The trade-offs involved don’t seem to make sense.


I'm going to end up preferring the old style of page switching, and I remain hopeful that it's configurable, although Apple tends to pick a path and go with it rather than offering configurable options for every taste.