helpful error on canOpenURL for missing scheme (#23535)

Summary:
iOS 9 introduced a whitelist for schemes that apps are allowed to open / check against, the current behavior of React Native is to simple return `NO` when a scheme is missing from that whitelist. It would be more helpful to throw an error with a suggested fix for the problem:
```
Unable to open URL: asos://checkout, add asos to LSApplicationQueriesSchemes in Info.plist.
```

[iOS] [Changed] - canOpenURL throws when custom scheme isn't in LSApplicationQueriesSchemes.
Pull Request resolved: https://github.com/facebook/react-native/pull/23535

Differential Revision: D14143005

Pulled By: cpojer

fbshipit-source-id: 4ead5f073690e627b4a4bbe3fa5a6cb5af46b589
This commit is contained in:
Eric Lewis
2019-02-19 22:05:33 -08:00
committed by Facebook Github Bot
parent eb414b7f8d
commit 35b6f866f1

View File

@@ -106,13 +106,23 @@ RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL
return;
}
// TODO: on iOS9 this will fail if URL isn't included in the plist
// we should probably check for that and reject in that case instead of
// simply resolving with NO
// This can be expensive, so we deliberately don't call on main thread
BOOL canOpen = [RCTSharedApplication() canOpenURL:URL];
resolve(@(canOpen));
NSString *scheme = [URL scheme];
// On iOS 9 and above canOpenURL returns NO without a helpful error.
// Check if a custom scheme is being used, and if it exists in LSApplicationQueriesSchemes
if (![[scheme lowercaseString] hasPrefix:@"http"] && ![[scheme lowercaseString] hasPrefix:@"https"]) {
NSArray *querySchemes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSApplicationQueriesSchemes"];
if (querySchemes != nil && ([querySchemes containsObject:scheme] || [querySchemes containsObject:[scheme lowercaseString]])) {
resolve(@(canOpen));
} else {
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@. Add %@ to LSApplicationQueriesSchemes in your Info.plist.", URL, scheme], nil);
}
} else {
resolve(@(canOpen));
}
}
RCT_EXPORT_METHOD(getInitialURL:(RCTPromiseResolveBlock)resolve