aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Auth/Source/FIRAuthAppDelegateProxy.m
diff options
context:
space:
mode:
authorGravatar Xiangtian Dai <xiangtian@google.com>2017-08-21 21:14:20 -0700
committerGravatar GitHub <noreply@github.com>2017-08-21 21:14:20 -0700
commit6e12c501f8dde3057d26149826e82489e114b2a1 (patch)
tree21145365c0433793ed1f59240db8815812d24fce /Firebase/Auth/Source/FIRAuthAppDelegateProxy.m
parent2c19745fb8f263730a390bb959b00b4209e00916 (diff)
Forwards app delegate's openURL invocations to `FIRAuth`. (#207)
Diffstat (limited to 'Firebase/Auth/Source/FIRAuthAppDelegateProxy.m')
-rw-r--r--Firebase/Auth/Source/FIRAuthAppDelegateProxy.m128
1 files changed, 121 insertions, 7 deletions
diff --git a/Firebase/Auth/Source/FIRAuthAppDelegateProxy.m b/Firebase/Auth/Source/FIRAuthAppDelegateProxy.m
index f24765a..15151f3 100644
--- a/Firebase/Auth/Source/FIRAuthAppDelegateProxy.m
+++ b/Firebase/Auth/Source/FIRAuthAppDelegateProxy.m
@@ -107,6 +107,53 @@ static id noop(id object, SEL cmd, ...) {
didReceiveRemoteNotification:notification];
}];
}
+ SEL openURLOptionsSelector = @selector(application:openURL:options:);
+ SEL openURLAnnotationSelector = @selector(application:openURL:sourceApplication:annotation:);
+ SEL handleOpenURLSelector = @selector(application:handleOpenURL:);
+ if (&UIApplicationOpenURLOptionsAnnotationKey && // the constant is only available on iOS 9+
+ ([_appDelegate respondsToSelector:openURLOptionsSelector] ||
+ (![_appDelegate respondsToSelector:openURLAnnotationSelector] &&
+ ![_appDelegate respondsToSelector:handleOpenURLSelector]))) {
+ // Replace the modern selector which is avaliable on iOS 9 and above because this is the one
+ // that the client app uses or the client app doesn't use any of them.
+ [self replaceSelector:openURLOptionsSelector
+ withBlock:^BOOL(id object, UIApplication *application, NSURL *url,
+ NSDictionary *options) {
+ return [weakSelf object:object
+ selector:openURLOptionsSelector
+ application:application
+ openURL:url
+ options:options];
+ }];
+ } else if ([_appDelegate respondsToSelector:openURLAnnotationSelector] ||
+ ![_appDelegate respondsToSelector:handleOpenURLSelector]) {
+ // Replace the longer form of the deprecated selectors on iOS 8 and below because this is the
+ // one that the client app uses or the client app doesn't use either of the applicable ones.
+ [self replaceSelector:openURLAnnotationSelector
+ withBlock:^(id object, UIApplication *application, NSURL *url,
+ NSString *sourceApplication, id annotation) {
+ return [weakSelf object:object
+ selector:openURLAnnotationSelector
+ application:application
+ openURL:url
+ sourceApplication:sourceApplication
+ annotation:annotation];
+ }];
+ } else {
+ // Replace the shorter form of the deprecated selectors on iOS 8 and below because this is
+ // the only one that the client app uses.
+ [self replaceSelector:handleOpenURLSelector
+ withBlock:^(id object, UIApplication *application, NSURL *url) {
+ return [weakSelf object:object
+ selector:handleOpenURLSelector
+ application:application
+ handleOpenURL:url];
+ }];
+ }
+ // Reset the application delegate to clear the system cache that indicates whether each of the
+ // openURL: methods is implemented on the application delegate.
+ application.delegate = nil;
+ application.delegate = _appDelegate;
}
return self;
}
@@ -146,7 +193,7 @@ static id noop(id object, SEL cmd, ...) {
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
- if (originalImplementation) {
+ if (originalImplementation && originalImplementation != &noop) {
typedef void (*Implmentation)(id, SEL, UIApplication*, NSData *);
((Implmentation)originalImplementation)(object, selector, application, deviceToken);
}
@@ -166,10 +213,12 @@ static id noop(id object, SEL cmd, ...) {
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
- typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *,
- void (^)(UIBackgroundFetchResult));
- ((Implmentation)originalImplementation)(object, selector, application, notification,
- completionHandler);
+ if (originalImplementation && originalImplementation != &noop) {
+ typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *,
+ void (^)(UIBackgroundFetchResult));
+ ((Implmentation)originalImplementation)(object, selector, application, notification,
+ completionHandler);
+ }
}
- (void)object:(id)object
@@ -184,12 +233,77 @@ static id noop(id object, SEL cmd, ...) {
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
- typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *);
- ((Implmentation)originalImplementation)(object, selector, application, notification);
+ if (originalImplementation && originalImplementation != &noop) {
+ typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *);
+ ((Implmentation)originalImplementation)(object, selector, application, notification);
+ }
+}
+
+- (BOOL)object:(id)object
+ selector:(SEL)selector
+ application:(UIApplication *)application
+ openURL:(NSURL *)url
+ options:(NSDictionary *)options {
+ if (object == _appDelegate && [self delegateCanHandleURL:url]) {
+ return YES;
+ }
+ IMP originalImplementation = [self originalImplementationForSelector:selector];
+ if (originalImplementation && originalImplementation != &noop) {
+ typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *, NSDictionary *);
+ return ((Implmentation)originalImplementation)(object, selector, application, url, options);
+ }
+ return NO;
+}
+
+- (BOOL)object:(id)object
+ selector:(SEL)selector
+ application:(UIApplication *)application
+ openURL:(NSURL *)url
+ sourceApplication:(NSString *)sourceApplication
+ annotation:(id)annotation {
+ if (object == _appDelegate && [self delegateCanHandleURL:url]) {
+ return YES;
+ }
+ IMP originalImplementation = [self originalImplementationForSelector:selector];
+ if (originalImplementation && originalImplementation != &noop) {
+ typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *, NSString *, id);
+ return ((Implmentation)originalImplementation)(object, selector, application, url,
+ sourceApplication, annotation);
+ }
+ return NO;
+}
+
+- (BOOL)object:(id)object
+ selector:(SEL)selector
+ application:(UIApplication *)application
+ handleOpenURL:(NSURL *)url {
+ if (object == _appDelegate && [self delegateCanHandleURL:url]) {
+ return YES;
+ }
+ IMP originalImplementation = [self originalImplementationForSelector:selector];
+ if (originalImplementation && originalImplementation != &noop) {
+ typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *);
+ return ((Implmentation)originalImplementation)(object, selector, application, url);
+ }
+ return NO;
}
#pragma mark - Internal Methods
+/** @fn delegateCanHandleURL:
+ @brief Checks for whether any of the delegates can handle the URL.
+ @param url The URL in question.
+ @return Whether any of the delegate can handle the URL.
+ */
+- (BOOL)delegateCanHandleURL:(NSURL *)url {
+ for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
+ if ([handler canHandleURL:url]) {
+ return YES;
+ };
+ }
+ return NO;
+}
+
/** @fn handlers
@brief Gets the list of handlers from `_handlers` safely.
*/