神刀安全网

Privacy and URL Schemes in iOS 9

As of iOS 9, third party applications are no longer able to query arbitrary URL schemes. Several third party applications, most notably Twitter, misused the canOpenURL(_:) method of the  UIApplication class to track which applications are installed on a particular device.

Apple has put a number of restrictions in place to protect the privacy of its customers. In this quick tip, I tell you what you need to know about these changes and I show you how you can update your applications.

1. Querying URL Schemes

I assume you already know that an iOS application can ask the operating system to launch another application using a URL scheme. In its simplest form, it works something like this.

let URLAsString = "tweetbot://_bartjacobs/timeline"  if let URL = NSURL.init(string: URLAsString) {     UIApplication.sharedApplication().openURL(URL) }

At times, it is useful to first ask the operating system whether a URL can be opened before opening it. This is especially useful if you want to update the user interface based on which applications the user has installed and your application can interact with. In the above example, openURL(_:) won’t succeed if Tweetbot isn’t installed on the user’s device. To ask the operating system whether a URL can be opened, you can make use of the  canOpenURL(_:) method of the  UIApplication class.

let URLAsString = "tweetbot://_bartjacobs/timeline"  if let URL = NSURL.init(string: URLAsString) {     if UIApplication.sharedApplication().canOpenURL(URL) {         UIApplication.sharedApplication().openURL(URL)     } else {         print("Cannot Open URL")     } }

Unfortunately, some applications, most notably Twitter, have been misusing canOpenURL(_:) to detect which applications are installed on the user’s device. According to Apple, this breaches the user’s privacy. As a result, Apple no longer tolerates this type of misuse in iOS 9 by imposing two restrictions.

  • Applications built against the iOS 9 SDK are forced to whitelist the URL schemes they would like to query. In other words, a call to  canOpenURL(_:)  fails if the URL isn’t added to a whitelist in the application’s  Info.plist .
  • Applications not built against the iOS 9 SDK continue to work as expected. There is one limitation, though. An application can only query 50 distinct URL schemes. Subsequent requests return false and throw an error. The documentation emphasizes that this limitation is reset when the user reinstalls or upgrades the application.

2. Project Setup

Let me show you what this means in practice by creating a simple application that opens Tweetbot, my favorite Twitter client. Create a new project in Xcode 7 and choose the Single View Application template. Name the project  Schemes and set  Language to  Swift .

Privacy and URL Schemes in iOS 9
Privacy and URL Schemes in iOS 9

Before we take a look at URL schemes, I want to set up the user interface. Open  ViewController.swift and add an action, openTweetbot(_:) , to the ViewController class. You can leave its implementation empty for now.

// MARK: - Actions  @IBAction func openTweetbot(sender: AnyObject) {  }

Open Main.storyboard and add a button to the  View Controller Scene . Set the title of the button to  Open Tweetbot and connect the button with the view controller’s  openTweetbot(_:) action we created earlier.

Privacy and URL Schemes in iOS 9

We are not going to make anything too complicated. When I tap the Open Tweetbot button, the operating system opens Tweetbot, showing me my timeline. You can read more about the URL schemes for Tweetbot on the Tapbots website.

3. Before iOS 9

Before Apple imposed the aforementioned restrictions on querying URL schemes, you could do the following:

@IBAction func openTweetbot(sender: AnyObject) {     let application = UIApplication.sharedApplication()     let URLAsString = "tweetbot://_bartjacobs/timeline"      guard let URL = NSURL.init(string: URLAsString) else { return }     guard application.canOpenURL(URL) else { return }      // Open URL     application.openURL(URL) }

We ask the operating system whether it can open the URL we pass to canOpenURL(_:) . If this method returns  false on iOS 8 and lower, we know the application we are interested in is not installed on the user’s device, assuming the URL scheme relates to another application. This can be very useful, but Apple wants to put some restrictions on the API to avoid abuse.

4. iOS 9

If you build the application in Xcode 7 and tap the Open Tweetbot  button, canOpenURL(_:) returns  false and the operating system throws an error that looks something like this:

Schemes[9227:3539016] -canOpenURL: failed for URL: "tweetbot://_bartjacobs/timeline" - error: "This app is not allowed to query for scheme tweetbot"

The operating system explicitly informs us that the application is not allowed to know whether it can open the URL we pass to  canOpenURL(_:) . It doesn’t mean that the application is not allowed to open the URL we passed to  openURL(_:) , though.

If you update the implementation of openTweetbot(_:) as shown below and you have Tweetbot installed, the application is able to open Tweetbot when the button is tapped. This emphasizes that Apple wants to limit the (mis)use of  canOpenURL(_:) , not  openURL(_:) .

@IBAction func openTweetbot(sender: AnyObject) {     let application = UIApplication.sharedApplication()     let URLAsString = "tweetbot://_bartjacobs/timeline"      guard let URL = NSURL.init(string: URLAsString) else { return }      // Open URL     application.openURL(URL) }

5. Whitelisting URL Schemes

Fortunately, there is an easy solution to this problem. As of iOS 9, Apple asks developers to whitelist the URL schemes an application would like to query. This is as simple as adding an entry to the application’s Info.plist .

Open Info.plist , add a key named  LSApplicationQueriesSchemes , and set the type of the value to  Array . Add an item of type String to the array and set its value to  tweetbot .

Privacy and URL Schemes in iOS 9

If we revert openTweetbot(_:) to its original implementation, we are able to invoke  canOpenURL(_:) without the operating system throwing errors at us. You can add as many URL schemes to your application’s  Info.plist .

@IBAction func openTweetbot(sender: AnyObject) {     let application = UIApplication.sharedApplication()     let URLAsString = "tweetbot://_bartjacobs/timeline"      guard let URL = NSURL.init(string: URLAsString) else { return }     guard application.canOpenURL(URL) else { return }      // Open URL     application.openURL(URL) }

Conclusion

Most applications won’t have a problem with Apple’s new policy. It is clear Apple aims to protect the privacy of its customers by limiting the information applications can extract from the operating system. Applications are sandboxed on iOS and Apple wants to control how much information an application can extract from the environment the sandbox lives in.

Whitelisting URL schemes isn’t a big pain for most applications, but it can become tedious if you plan to create an application launcher, such as Launch Center Pro . It is still possible to create a launcher as long as you whitelist every URL scheme the application would like to query. This can be pretty tedious, though.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Privacy and URL Schemes in iOS 9

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址