I'm having problems loading youku.com videos inside a UIWebView in my app. I'm pretty sure it's due to App Transport Security because replacing the embed with an HTTPS URL works fine. There is, of course, no HTTPS equivalent URL, because China.
I've read about the various NSAppTransportSecurity settings. My first instinct of course was to try NSAllowsArbitraryLoads to at least verify the problem, but that didn't work. Then I followed various online guides that show how to NSExceptionDomains like you're supposed to, but that's not working either.
And now I'm stuck. FWIW, I'm catching URL loading errors like this:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
...
if (error.code == NSURLErrorCancelled)
{
NSLog(@"NSURLErrorCancelled: URL %@ error %@", urlString, error);
}
}
For the moment I'm using a dummy test URL exon.name, and that produces:
2015-12-02 15:47:22.312 ZaoMengShe[81707:903426] NSURLErrorCancelled: URL https://dev1.zaomengshe.com/c/54260 error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
To confirm, -999 is the error when App Transport Security does this, right? (It's not a very informative error!)
The other thing, as noted in e.g. NSAllowsArbitraryLoads not working, is that you have to edit the "Info.plist" file. I don't have such a file. I have "ZaoMengShe-Info.plist" ("ZaoMengShe" being the name of my app). But none of the questions show an actual screenshot including the file name, so for all I know everyone's Info.plist file actually includes the name of the app and that's normal. Am I mistaken?
It turns out that NSAllowsArbitraryLoads is working fine in this case. My problem is I'm hitting another restriction. In the new security policy, you're not allowed to load insecure (HTTP) active content inside a secure (HTTPS) page. This is true in the browser as well as UIWebView. There doesn't seem to be any way to turn this behaviour off.
Here's some extra logs to show the error message with NSAllowsArbitraryLoads switched off and then on. It fails either way, but I get an extra error message in the first case:
2015-12-07 17:58:10.589 TestWeb[13583:4566542] about to load url https://dev1.zaomengshe.com/c/54260
2015-12-07 17:58:15.966 TestWeb[13583:4569606] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
2015-12-07 17:58:16.045 TestWeb[13583:4566542] failed to load
2015-12-07 17:58:40.879 TestWeb[13583:4566542] NSURLErrorCancelled: error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
2015-12-07 17:58:40.895 TestWeb[13583:4569023] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
2015-12-07 17:58:41.878 TestWeb[13583:4569606] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
2015-12-07 17:58:41.884 TestWeb[13583:4566542] finished load urlString: https://dev1.zaomengshe.com/c/54260
2015-12-07 17:54:57.431 TestWeb[13503:4532874] about to load url https://dev1.zaomengshe.com/c/54260
2015-12-07 17:55:02.339 TestWeb[13503:4532874] failed to load
2015-12-07 17:55:15.310 TestWeb[13503:4532874] NSURLErrorCancelled: error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
2015-12-07 17:55:15.313 TestWeb[13503:4533886] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
2015-12-07 17:55:16.210 TestWeb[13503:4534307] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
2015-12-07 17:55:16.653 TestWeb[13503:4532874] finished load urlString: https://dev1.zaomengshe.com/c/54260
In my case I was loading an insecure youku video in an iframe, and iframes count as active content. So there's no way it can be made to work. Youku doesn't provide HTTPS content.
The solution turns out to be elegantly simple: move the entire app back to the HTTP version of my site and keep the NSAllowsArbitraryLoads flag. Hooray! That was a fun experiment with HTTPS everyone, thanks for that. Be sure to get back to me when it works.