Skip to content

Commit 08cced4

Browse files
committed
Forward along swizzled calls using an invocation in necessary
Developers can add a layer that only implements some of the swizzled calls, and redirecting others by using forwardInvocation. In order to handle that case, if the original function is not found, use forwardInvocation instead. PiperOrigin-RevId: 250306551
1 parent fa9bb4d commit 08cced4

File tree

3 files changed

+123
-4
lines changed

3 files changed

+123
-4
lines changed

app/src/invites/ios/invites_ios_startup.mm

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ static BOOL AppDelegateApplicationOpenUrlSourceApplicationAnnotation(id self, SE
5656
return ((util::AppDelegateApplicationOpenUrlSourceApplicationAnnotationFunc)
5757
app_delegate_application_open_url_source_application_annotation)(
5858
self, selectorValue, application, url, sourceApplication, annotation);
59+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
60+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
61+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selectorValue];
62+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
63+
[invocation setSelector:selectorValue];
64+
[invocation setTarget:self];
65+
[invocation setArgument:&application atIndex:2];
66+
[invocation setArgument:&url atIndex:3];
67+
[invocation setArgument:&sourceApplication atIndex:4];
68+
[invocation setArgument:&annotation atIndex:5];
69+
[self forwardInvocation:invocation];
70+
// Read the return value from the invocation.
71+
[invocation getReturnValue:&ret];
5972
}
6073
return ret;
6174
}
@@ -76,6 +89,18 @@ static BOOL AppDelegateApplicationContinueUserActivityRestorationHandler(
7689
return ((util::AppDelegateApplicationContinueUserActivityRestorationHandlerFunc)
7790
app_delegate_application_continue_user_activity_restoration_handler)(
7891
self, selectorValue, application, userActivity, restorationHandler);
92+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
93+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
94+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selectorValue];
95+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
96+
[invocation setSelector:selectorValue];
97+
[invocation setTarget:self];
98+
[invocation setArgument:&application atIndex:2];
99+
[invocation setArgument:&userActivity atIndex:3];
100+
[invocation setArgument:&restorationHandler atIndex:4];
101+
[self forwardInvocation:invocation];
102+
// Read the return value from the invocation.
103+
[invocation getReturnValue:&ret];
79104
}
80105
return ret;
81106
}
@@ -96,23 +121,42 @@ static BOOL AppDelegateApplicationOpenUrlOptions(id self, SEL selectorValue,
96121
return (
97122
(util::AppDelegateApplicationOpenUrlOptionsFunc)app_delegate_application_open_url_options)(
98123
self, selectorValue, application, url, options);
124+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
125+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
126+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selectorValue];
127+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
128+
[invocation setSelector:selectorValue];
129+
[invocation setTarget:self];
130+
[invocation setArgument:&application atIndex:2];
131+
[invocation setArgument:&url atIndex:3];
132+
[invocation setArgument:&options atIndex:4];
133+
[self forwardInvocation:invocation];
134+
// Read the return value from the invocation.
135+
[invocation getReturnValue:&ret];
99136
}
100137
return ret;
101138
}
102139

103140
// Fetch link when entering foreground.
104-
static void AppDelegateApplicationDidBecomeActive(id self, SEL selector_value,
141+
static void AppDelegateApplicationDidBecomeActive(id self, SEL selectorValue,
105142
UIApplication *application) {
106143
internal::InvitesIosStartup::DidBecomeActive(application);
107144
IMP app_delegate_application_did_become_active =
108145
SwizzledMethodCache().GetMethodForObject(self, @selector(applicationDidBecomeActive:));
109146
if (app_delegate_application_did_become_active) {
110147
((util::AppDelegateApplicationDidBecomeActiveFunc)app_delegate_application_did_become_active)(
111-
self, selector_value, application);
148+
self, selectorValue, application);
149+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
150+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
151+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selectorValue];
152+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
153+
[invocation setSelector:selectorValue];
154+
[invocation setTarget:self];
155+
[invocation setArgument:&application atIndex:2];
156+
[self forwardInvocation:invocation];
112157
}
113158
}
114159

115-
116160
// Hook all AppDelegate methods that Firebase Invites requires to intercept incoming invites and
117161
// dynamic links.
118162
//

instance_id/src/ios/instance_id.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ static void AppDelegateApplicationDidRegisterForRemoteNotificationsWithDeviceTok
118118
((util::AppDelegateApplicationDidRegisterForRemoteNotificationsWithDeviceTokenFunc)
119119
app_delegate_application_did_register_for_remote_notifications_with_device_token)(
120120
self, selector_value, application, device_token);
121+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
122+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
123+
NSMethodSignature* signature = [[self class] instanceMethodSignatureForSelector:selector_value];
124+
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
125+
[invocation setSelector:selector_value];
126+
[invocation setTarget:self];
127+
[invocation setArgument:&application atIndex:2];
128+
[invocation setArgument:&device_token atIndex:3];
129+
[self forwardInvocation:invocation];
121130
}
122131
}
123132
// Hook all AppDelegate methods that IID requires to cache data for token fetch operations.

messaging/src/ios/messaging.mm

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,14 @@ static void AppDelegateApplicationDidBecomeActive(id self, SEL selector_value,
287287
if (app_delegate_application_did_become_active) {
288288
((util::AppDelegateApplicationDidBecomeActiveFunc)app_delegate_application_did_become_active)(
289289
self, selector_value, application);
290+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
291+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
292+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
293+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
294+
[invocation setSelector:selector_value];
295+
[invocation setTarget:self];
296+
[invocation setArgument:&application atIndex:2];
297+
[self forwardInvocation:invocation];
290298
}
291299
}
292300

@@ -298,6 +306,14 @@ static void AppDelegateApplicationDidEnterBackground(id self, SEL selector_value
298306
if (app_delegate_application_did_enter_background) {
299307
((util::AppDelegateApplicationDidEnterBackgroundFunc)
300308
app_delegate_application_did_enter_background)(self, selector_value, application);
309+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
310+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
311+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
312+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
313+
[invocation setSelector:selector_value];
314+
[invocation setTarget:self];
315+
[invocation setArgument:&application atIndex:2];
316+
[self forwardInvocation:invocation];
301317
}
302318
if (MessagingIsInitialized()) {
303319
LogInfo("FCM: Disconnect FCM service");
@@ -341,6 +357,15 @@ static void AppDelegateApplicationDidRegisterForRemoteNotificationsWithDeviceTok
341357
((util::AppDelegateApplicationDidRegisterForRemoteNotificationsWithDeviceTokenFunc)
342358
app_delegate_application_did_register_for_remote_notifications_with_device_token)(
343359
self, selector_value, application, deviceToken);
360+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
361+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
362+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
363+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
364+
[invocation setSelector:selector_value];
365+
[invocation setTarget:self];
366+
[invocation setArgument:&application atIndex:2];
367+
[invocation setArgument:&deviceToken atIndex:3];
368+
[self forwardInvocation:invocation];
344369
}
345370
}
346371

@@ -358,6 +383,15 @@ static void AppDelegateApplicationDidFailToRegisterForRemoteNotificationsWithErr
358383
((util::AppDelegateApplicationDidFailToRegisterForRemoteNotificationsWithErrorFunc)
359384
app_delegate_application_did_fail_to_register_for_remote_notifications_with_error)(
360385
self, selector_value, application, error);
386+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
387+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
388+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
389+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
390+
[invocation setSelector:selector_value];
391+
[invocation setTarget:self];
392+
[invocation setArgument:&application atIndex:2];
393+
[invocation setArgument:&error atIndex:3];
394+
[self forwardInvocation:invocation];
361395
}
362396
}
363397

@@ -475,7 +509,7 @@ static BOOL AppDelegateApplicationDidFinishLaunchingWithOptions(id self, SEL sel
475509
NSDictionary *launch_options) {
476510
// Set up Messaging on iOS 10, if possible.
477511
Class notification_center_class = NSClassFromString(@"UNUserNotificationCenter");
478-
if (notification_center_class) {
512+
if (notification_center_class && application) {
479513
LogInfo("Setting up iOS 10 message delegate.");
480514

481515
// Cache the existing delegate if one exists it so we can pass along messages when needed.
@@ -499,6 +533,19 @@ static BOOL AppDelegateApplicationDidFinishLaunchingWithOptions(id self, SEL sel
499533
return ((util::AppDelegateApplicationDidFinishLaunchingWithOptionsFunc)
500534
app_delegate_application_did_finish_launching_with_options)(
501535
self, selector_value, application, launch_options);
536+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
537+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
538+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
539+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
540+
[invocation setSelector:selector_value];
541+
[invocation setTarget:self];
542+
[invocation setArgument:&application atIndex:2];
543+
[invocation setArgument:&launch_options atIndex:3];
544+
[self forwardInvocation:invocation];
545+
// Read the return value from the invocation.
546+
BOOL ret = NO;
547+
[invocation getReturnValue:&ret];
548+
return ret;
502549
}
503550
return NO;
504551
}
@@ -525,6 +572,15 @@ static void AppDelegateApplicationDidReceiveRemoteNotification(id self, SEL sele
525572
((util::AppDelegateApplicationDidReceiveRemoteNotificationFunc)
526573
app_delegate_application_did_receive_remote_notification)(self, selector_value,
527574
application, user_info);
575+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
576+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
577+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
578+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
579+
[invocation setSelector:selector_value];
580+
[invocation setTarget:self];
581+
[invocation setArgument:&application atIndex:2];
582+
[invocation setArgument:&user_info atIndex:3];
583+
[self forwardInvocation:invocation];
528584
}
529585
}
530586

@@ -550,6 +606,16 @@ static void AppDelegateApplicationDidReceiveRemoteNotificationFetchCompletionHan
550606
((util::AppDelegateApplicationDidReceiveRemoteNotificationFetchCompletionHandlerFunc)
551607
app_delegate_application_did_receive_remote_notification_fetch_completion_handler)(
552608
self, selector_value, application, user_info, handler);
609+
} else if ([self methodForSelector:@selector(forwardInvocation:)] !=
610+
[NSObject instanceMethodForSelector:@selector(forwardInvocation:)]) {
611+
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector_value];
612+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
613+
[invocation setSelector:selector_value];
614+
[invocation setTarget:self];
615+
[invocation setArgument:&application atIndex:2];
616+
[invocation setArgument:&user_info atIndex:3];
617+
[invocation setArgument:&handler atIndex:4];
618+
[self forwardInvocation:invocation];
553619
} else {
554620
// TODO(smiles): We should determine whether the entire message is sent to this notification
555621
// method, if not this is clearly wrong and will need to download the rest of the message.

0 commit comments

Comments
 (0)