davbeck / TUSafariActivity

A UIActivity subclass that opens URLs in Safari
Other
311 stars 71 forks source link

iOS 9 privacy changes #25

Open jengelsma opened 8 years ago

jengelsma commented 8 years ago

As of iOS9 Apple has changed the behavior of UIApplication.canOpenURL for privacy reasons. The method will now return false on any URL schemes that are not whitelisted in the app's Info.plist. After a bit of debugging, we've determined that this impacts some non-custom native (e.g. http:) URLs as well. Native YouTube URLs are one good example. In order to get any such URLs to work ok with this component you need to explicitly whitelist the scheme (or http url). For YouTube we had to add the following to our info.plist:

 <key>LSApplicationQueriesSchemes</key>
 <array>
  <string>youtube</string>
 </array>

It might be good to call this out in the README, as its sure to confound folks. I'm guessing this will only impact native urls of "special apps" such as YouTube where iOS automatically will attempt to run the app (if available) instead of Safari, even when a native http url is presented.

davbeck commented 8 years ago

Wait, you're saying that the new canOpenURL behavior applies to http links as well? That's kind of crazy. And the solution is to not add http to the schemes list, but the specific apps scheme? Do you have a link to any more information on this?

jengelsma commented 8 years ago

The best explanation that I can find of the changes to this particular API and the rationale is in this WWDC 2015 session. Fast forward to around t=8:35. As far as I can tell, there are certain apps on iOS that are treated "magically" in that normal http: urls get handled as custom app url schemes in that they cause the native app to load if present, otherwise they fall back to Safari.

davbeck commented 8 years ago

I'm familiar with the session. I think you're talking about universal links, which are based on what apps you have installed. But my understanding is that universal links are suppose to replace custom url schemes for this very purpose. Even if an http link opens a native app, it shouldn't matter to the calling app.

Can you provide a sample application demonstrating, say youtube links not opening because of this?

jengelsma commented 8 years ago

Oops, hit return to soon. Youtube is one example of http: urls that get treated magically. The only other one that I could find so far is Facebook. Ironically, http://facebook.com gets routed to Safari, but certain links to facebook items (events and profiles) get routed to the Facebook native app if installed. Based on my observations, these apps get a false on the canOpenURL() if the app is actually present when called with the http: url.

jengelsma commented 8 years ago

So for example, if you replace URL in your README.md sample code with the url "http://www.youtube.com/watch?v=U37lyRoECn4" the "Show in Safari" will not show. If you add the entry cited above to your info.plist it will work.

ajfigueroa commented 8 years ago

I had no idea this was a thing, this is good to know! Here is the message I get when reproducing the steps @jengelsma mentioned above without adding the scheme to LSApplicationQueriesSchemes:

-canOpenURL: failed for URL: "youtube://www.youtube.com/watch?v=U37lyRoECn4" - error: "This app is not allowed to query for scheme youtube"

Code:

NSURL *url = [NSURL URLWithString:@"http://www.youtube.com/watch?v=U37lyRoECn4"];

UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:@[url]
                                                                                 applicationActivities:@[[TUSafariActivity alloc] init]];

[self presentViewController:activityController animated:YES completion:nil];