/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTLinkingManager.h" #import #import #import static NSString *const kOpenURLNotification = @"RCTOpenURLNotification"; static void postNotificationWithURL(NSURL *URL, id sender) { NSDictionary *payload = @{@"url": URL.absoluteString}; [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:sender userInfo:payload]; } @implementation RCTLinkingManager RCT_EXPORT_MODULE() - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURLNotification:) name:kOpenURLNotification object:nil]; } - (void)stopObserving { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (NSArray *)supportedEvents { return @[@"url"]; } + (BOOL)application:(UIApplication *)app openURL:(NSURL *)URL options:(NSDictionary *)options { postNotificationWithURL(URL, self); return YES; } + (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { postNotificationWithURL(URL, self); return YES; } + (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * __nullable))restorationHandler { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSDictionary *payload = @{@"url": userActivity.webpageURL.absoluteString}; [[NSNotificationCenter defaultCenter] postNotificationName:kOpenURLNotification object:self userInfo:payload]; } return YES; } - (void)handleOpenURLNotification:(NSNotification *)notification { [self sendEventWithName:@"url" body:notification.userInfo]; } RCT_EXPORT_METHOD(openURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { BOOL opened = [RCTSharedApplication() openURL:URL]; if (opened) { resolve(nil); } else { reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unable to open URL: %@", URL], nil); } } RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject) { if (RCTRunningInAppExtension()) { // Technically Today widgets can open urls, but supporting that would require // a reference to the NSExtensionContext resolve(@NO); 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)); } RCT_EXPORT_METHOD(getInitialURL:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject) { NSURL *initialURL = nil; if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) { initialURL = self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; } else { NSDictionary *userActivityDictionary = self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; if ([userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey] isEqual:NSUserActivityTypeBrowsingWeb]) { initialURL = ((NSUserActivity *)userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"]).webpageURL; } } resolve(RCTNullIfNil(initialURL.absoluteString)); } @end