Repository: firebase/firebase-ios-sdk (language: cpp)

Issue:
Cleanup deprecated notification API usages in Firebase
### Description

Firebase has multiple usages of the deprecated ` (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo ` API. 

It's usages should be removed across Firebase and GoogleUtilities.

In addition, GoogleUtilities should stop conditionalizing the swizzling of the replacement API: https://github.com/google/GoogleUtilities/blame/main/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m#L520

Auth part of this is done in #13003 
GoogleUtilities in https://github.com/google/GoogleUtilities/pull/162
FirebaseMessging and CocoaPods updates still need to be done.

### Reproducing the issue

_No response_

### Firebase SDK Version

All

### Xcode Version

14.3

### Installation Method

N/A

### Firebase Product(s)

Authentication

### Targeted Platforms

iOS

### Relevant Log Output

_No response_

### If using Swift Package Manager, the project's Package.resolved

<!--- Look below for instructions on how to share your Package.resolved. --->

<details>
<summary>Expand <code>Package.resolved</code> snippet</summary>
<br>

```json

Replace this line with the contents of your Package.resolved.

```

</details>


### If using CocoaPods, the project's Podfile.lock

<!--- Look below for instructions on how to share your Podfile.lock. --->

<details>
<summary>Expand <code>Podfile.lock</code> snippet</summary>
<br>

```yml

Replace this line with the contents of your Podfile.lock!

```

</details>



Discussion / hints:

Fix patch:
diff --git a/FirebaseMessaging/Sources/FIRMessaging.m b/FirebaseMessaging/Sources/FIRMessaging.m
index 9511d34a29e..9a688b034be 100644
--- a/FirebaseMessaging/Sources/FIRMessaging.m
+++ b/FirebaseMessaging/Sources/FIRMessaging.m
@@ -437,9 +437,7 @@ - (void)handleIncomingLinkIfNeededFromMessage:(NSDictionary *)message {
     // Similarly, |application:openURL:sourceApplication:annotation:| will also always be called,
     // due to the default swizzling done by FIRAAppDelegateProxy in Firebase Analytics
   } else if ([appDelegate respondsToSelector:openURLWithSourceApplicationSelector]) {
-// TODO(Xcode 15): When Xcode 15 is the minimum supported Xcode version, it will be unnecessary to
-// check if `TARGET_OS_VISION` is defined.
-#if TARGET_OS_IOS && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
+#if TARGET_OS_IOS
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
     [appDelegate application:application
diff --git a/FirebaseMessaging/Sources/FIRMessagingRemoteNotificationsProxy.m b/FirebaseMessaging/Sources/FIRMessagingRemoteNotificationsProxy.m
index 52c5ff0f82d..5cd5d8b16a2 100644
--- a/FirebaseMessaging/Sources/FIRMessagingRemoteNotificationsProxy.m
+++ b/FirebaseMessaging/Sources/FIRMessagingRemoteNotificationsProxy.m
@@ -384,13 +384,6 @@ id FIRMessagingPropertyNameFromObject(id object, NSString *propertyName, Class k
 }
 
 #pragma mark - GULApplicationDelegate
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-implementations"
-- (void)application:(GULApplication *)application
-    didReceiveRemoteNotification:(NSDictionary *)userInfo {
-  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
-}
-#pragma clang diagnostic pop
 
 #if TARGET_OS_IOS || TARGET_OS_TV
 - (void)application:(UIApplication *)application
diff --git a/FirebaseMessaging/Sources/Token/FIRMessagingAPNSInfo.m b/FirebaseMessaging/Sources/Token/FIRMessagingAPNSInfo.m
index 6bf33f9b5d6..ea061e8a284 100644
--- a/FirebaseMessaging/Sources/Token/FIRMessagingAPNSInfo.m
+++ b/FirebaseMessaging/Sources/Token/FIRMessagingAPNSInfo.m
@@ -75,10 +75,12 @@ + (BOOL)supportsSecureCoding {
 }
 
 - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
-  id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey];
-  if (![deviceToken isKindOfClass:[NSData class]]) {
+  NSData *deviceToken = [aDecoder decodeObjectOfClass:[NSData class]
+                                               forKey:kFIRInstanceIDAPNSInfoTokenKey];
+  if (!deviceToken) {
     return nil;
   }
+
   BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey];
   return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox];
 }
diff --git a/FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.m b/FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.m
index 90420d1e72e..2852f0cad69 100644
--- a/FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.m
+++ b/FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.m
@@ -143,32 +143,29 @@ - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
   BOOL needsMigration = NO;
   // These value cannot be nil
 
-  id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey];
-  if (![authorizedEntity isKindOfClass:[NSString class]]) {
+  NSString *authorizedEntity = [aDecoder decodeObjectOfClass:[NSString class]
+                                                      forKey:kFIRInstanceIDAuthorizedEntityKey];
+  if (!authorizedEntity) {
     return nil;
   }
 
-  id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey];
-  if (![scope isKindOfClass:[NSString class]]) {
+  NSString *scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kFIRInstanceIDScopeKey];
+  if (!scope) {
     return nil;
   }
 
-  id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey];
-  if (![token isKindOfClass:[NSString class]]) {
+  NSString *token = [aDecoder decodeObjectOfClass:[NSString class] forKey:kFIRInstanceIDTokenKey];
+  if (!token) {
     return nil;
   }
 
-  // These values are nullable, so only fail the decode if the type does not match
+  // These values are nullable, so don't fail on nil.
 
-  id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey];
-  if (appVersion && ![appVersion isKindOfClass:[NSString class]]) {
-    return nil;
-  }
+  NSString *appVersion = [aDecoder decodeObjectOfClass:[NSString class]
+                                                forKey:kFIRInstanceIDAppVersionKey];
+  NSString *firebaseAppID = [aDecoder decodeObjectOfClass:[NSString class]
+                                                   forKey:kFIRInstanceIDFirebaseAppIDKey];
 
-  id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey];
-  if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) {
-    return nil;
-  }
   NSSet *classes = [[NSSet alloc] initWithArray:@[ FIRMessagingAPNSInfo.class ]];
   FIRMessagingAPNSInfo *rawAPNSInfo = [aDecoder decodeObjectOfClasses:classes
                                                                forKey:kFIRInstanceIDAPNSInfoKey];
diff --git a/FirebaseMessaging/Tests/UnitTests/FIRMessagingRemoteNotificationsProxyTest.m b/FirebaseMessaging/Tests/UnitTests/FIRMessagingRemoteNotificationsProxyTest.m
index d3bbdc3ead3..16f7086f1d3 100644
--- a/FirebaseMessaging/Tests/UnitTests/FIRMessagingRemoteNotificationsProxyTest.m
+++ b/FirebaseMessaging/Tests/UnitTests/FIRMessagingRemoteNotificationsProxyTest.m
@@ -64,19 +64,13 @@ @interface FakeAppDelegate : NSObject <GULApplicationDelegate>
 @property(nonatomic, strong) NSError *registerForRemoteNotificationsError;
 @end
 @implementation FakeAppDelegate
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-implementations"
-- (void)application:(GULApplication *)application
-    didReceiveRemoteNotification:(NSDictionary *)userInfo {
-  self.remoteNotificationMethodWasCalled = YES;
-}
-#pragma clang diagnostic pop
 
 #if TARGET_OS_IOS || TARGET_OS_TV
 - (void)application:(UIApplication *)application
     didReceiveRemoteNotification:(NSDictionary *)userInfo
           fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
   self.remoteNotificationWithFetchHandlerWasCalled = YES;
+  completionHandler(UIBackgroundFetchResultNewData);
 }
 #endif
 
@@ -192,6 +186,7 @@ - (void)testSwizzlingNonAppDelegate {
 #if !SWIFT_PACKAGE
 // The next 3 tests depend on a sharedApplication which is not available in the Swift PM test env.
 - (void)testSwizzledIncompleteAppDelegateRemoteNotificationMethod {
+  XCTestExpectation *expectation = [self expectationWithDescription:@"completion"];
   IncompleteAppDelegate *incompleteAppDelegate = [[IncompleteAppDelegate alloc] init];
   [[GULAppDelegateSwizzler sharedApplication] setDelegate:incompleteAppDelegate];
   [self.proxy swizzleMethodsIfPossible];
@@ -199,15 +194,18 @@ - (void)testSwizzledIncompleteAppDelegateRemoteNotificationMethod {
   NSDictionary *notification = @{@"test" : @""};
   OCMExpect([self.mockMessaging appDidReceiveMessage:notification]);
 
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
   [incompleteAppDelegate application:[GULAppDelegateSwizzler sharedApplication]
-        didReceiveRemoteNotification:notification];
-#pragma clang diagnostic pop
+        didReceiveRemoteNotification:notification
+              fetchCompletionHandler:^(UIBackgroundFetchResult result) {
+                [expectation fulfill];
+              }];
 
   [self.mockMessaging verify];
+  [self waitForExpectationsWithTimeout:0.5 handler:nil];
 }
 
+// This test demonstrates the difference between Firebase 10 and 11. In 10 and earlier the
+// swizzler inserts the old `didReceiveRemoteNotification` method. In 11, the new.
 - (void)testIncompleteAppDelegateRemoteNotificationWithFetchHandlerMethod {
   IncompleteAppDelegate *incompleteAppDelegate = [[IncompleteAppDelegate alloc] init];
   [[GULAppDelegateSwizzler sharedApplication] setDelegate:incompleteAppDelegate];
@@ -216,11 +214,11 @@ - (void)testIncompleteAppDelegateRemoteNotificationWithFetchHandlerMethod {
 #if TARGET_OS_IOS || TARGET_OS_TV
   SEL remoteNotificationWithFetchHandler = @selector(application:
                                     didReceiveRemoteNotification:fetchCompletionHandler:);
-  XCTAssertFalse([incompleteAppDelegate respondsToSelector:remoteNotificationWithFetchHandler]);
+  XCTAssertTrue([incompleteAppDelegate respondsToSelector:remoteNotificationWithFetchHandler]);
 #endif
 
   SEL remoteNotification = @selector(application:didReceiveRemoteNotification:);
-  XCTAssertTrue([incompleteAppDelegate respondsToSelector:remoteNotification]);
+  XCTAssertFalse([incompleteAppDelegate respondsToSelector:remoteNotification]);
 }
 
 - (void)testSwizzledAppDelegateRemoteNotificationMethods {
@@ -230,21 +228,6 @@ - (void)testSwizzledAppDelegateRemoteNotificationMethods {
 
   NSDictionary *notification = @{@"test" : @""};
 
-  // Test application:didReceiveRemoteNotification:
-
-  // Verify our swizzled method was called
-  OCMExpect([self.mockMessaging appDidReceiveMessage:notification]);
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-  [appDelegate application:[GULAppDelegateSwizzler sharedApplication]
-      didReceiveRemoteNotification:notification];
-#pragma clang diagnostic pop
-
-  // Verify our original method was called
-  XCTAssertTrue(appDelegate.remoteNotificationMethodWasCalled);
-  [self.mockMessaging verify];
-
   // Test application:didReceiveRemoteNotification:fetchCompletionHandler:
 #if TARGET_OS_IOS || TARGET_OS_TV
   // Verify our swizzled method was called
@@ -252,7 +235,8 @@ - (void)testSwizzledAppDelegateRemoteNotificationMethods {
 
   [appDelegate application:[GULAppDelegateSwizzler sharedApplication]
       didReceiveRemoteNotification:notification
-            fetchCompletionHandler:^(UIBackgroundFetchResult result){
+            fetchCompletionHandler:^(UIBackgroundFetchResult result) {
+              XCTAssertEqual(result, UIBackgroundFetchResultNewData);
             }];
 
   // Verify our original method was called


Test patch: