소스 검색

Merge remote-tracking branch 'origin/master' into auth-swift

Paul Beusterien 2 년 전
부모
커밋
bcac846589
100개의 변경된 파일788개의 추가작업 그리고 4077개의 파일을 삭제
  1. 3 0
      .github/workflows/abtesting.yml
  2. 9 3
      .github/workflows/auth.yml
  3. 8 1
      .github/workflows/crashlytics.yml
  4. 3 1
      .github/workflows/database.yml
  5. 3 0
      .github/workflows/dynamiclinks.yml
  6. 12 0
      .github/workflows/firestore.yml
  7. 3 0
      .github/workflows/functions.yml
  8. 3 0
      .github/workflows/installations.yml
  9. 3 0
      .github/workflows/messaging.yml
  10. 3 0
      .github/workflows/performance.yml
  11. 2 0
      .github/workflows/shared-swift.yml
  12. 7 1
      .github/workflows/storage.yml
  13. 113 11
      .github/workflows/zip.yml
  14. 1 1
      ClientApp/Shared-iOS11+/swift-import-test.swift
  15. 231 235
      CoreOnly/NOTICES
  16. 1 1
      CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift
  17. 1 1
      Example/CombineSample/CombineSample/App/CombineSampleApp.swift
  18. 2 2
      Example/CombineSample/CombineSample/ViewModels/Authentication/AnonymousSignInViewModel.swift
  19. 1 1
      Example/CombineSample/CombineSample/ViewModels/Authentication/UserInfoViewModel.swift
  20. 2 2
      Example/CombineSample/CombineSample/Views/Authentication/AnonymousSignInView.swift
  21. 2 2
      Example/FirestoreSample/FirestoreSample/App/FirestoreSampleApp.swift
  22. 1 1
      Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsAnimationView.swift
  23. 1 1
      Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsMappingErrorView.swift
  24. 1 1
      Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsMappingErrorView2.swift
  25. 1 1
      Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsNoAnimationsView.swift
  26. 1 1
      Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsView.swift
  27. 1 1
      Example/tvOSSample/tvOSSample/AppDelegate.swift
  28. 1 1
      Example/tvOSSample/tvOSSample/AuthLoginViewController.swift
  29. 1 1
      Example/tvOSSample/tvOSSample/AuthViewController.swift
  30. 1 1
      Example/tvOSSample/tvOSSample/DatabaseViewController.swift
  31. 1 1
      Example/tvOSSample/tvOSSample/EmailLoginViewController.swift
  32. 1 1
      Example/tvOSSample/tvOSSample/StorageViewController.swift
  33. 1 1
      Example/watchOSSample/SampleWatchAppWatchKitExtension/InterfaceController.swift
  34. 1 1
      Example/watchOSSample/SampleWatchAppWatchKitExtension/NotificationController.swift
  35. 1 1
      Example/watchOSSample/ServiceExtension/NotificationService.swift
  36. 24 24
      Firebase.podspec
  37. 1 1
      FirebaseABTesting.podspec
  38. 1 1
      FirebaseABTesting/Tests/Integration/ABTQA/AppDelegate.swift
  39. 1 1
      FirebaseABTesting/Tests/Integration/ABTQA/ViewController.swift
  40. 3 3
      FirebaseAnalytics.podspec
  41. 1 1
      FirebaseAnalytics/Analytics+SwiftUI.swift
  42. 2 2
      FirebaseAnalyticsOnDeviceConversion.podspec
  43. 1 1
      FirebaseAnalyticsSwift.podspec
  44. 1 1
      FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift
  45. 2 2
      FirebaseAppCheck.podspec
  46. 2 2
      FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/AppDelegate.swift
  47. 2 2
      FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/MyAppCheckProvider.swift
  48. 1 1
      FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/SceneDelegate.swift
  49. 1 1
      FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp/AppDelegate.swift
  50. 4 0
      FirebaseAppCheck/CHANGELOG.md
  51. 0 65
      FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.h
  52. 0 261
      FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.m
  53. 0 43
      FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h
  54. 0 96
      FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.m
  55. 0 21
      FirebaseAppCheck/Sources/AppAttestProvider/DCAppAttestService+FIRAppAttestService.m
  56. 0 29
      FirebaseAppCheck/Sources/AppAttestProvider/Errors/FIRAppAttestRejectionError.m
  57. 31 468
      FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProvider.m
  58. 0 73
      FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.h
  59. 0 57
      FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.m
  60. 0 42
      FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestService.h
  61. 0 74
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.h
  62. 0 125
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.m
  63. 0 60
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.h
  64. 0 93
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.m
  65. 0 41
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.h
  66. 0 74
      FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.m
  67. 0 58
      FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h
  68. 0 177
      FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.m
  69. 0 36
      FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.h
  70. 0 93
      FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.m
  71. 0 87
      FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.h
  72. 0 287
      FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.m
  73. 1 40
      FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h
  74. 29 133
      FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.m
  75. 0 32
      FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h
  76. 0 75
      FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.m
  77. 7 8
      FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.h
  78. 7 8
      FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.m
  79. 74 177
      FirebaseAppCheck/Sources/Core/FIRAppCheck.m
  80. 4 10
      FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.h
  81. 18 10
      FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.m
  82. 7 8
      FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.h
  83. 11 9
      FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.m
  84. 9 1
      FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h
  85. 12 0
      FirebaseAppCheck/Sources/Core/FIRAppCheckToken.m
  86. 6 7
      FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.h
  87. 34 0
      FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.m
  88. 7 3
      FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.h
  89. 57 0
      FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.m
  90. 0 73
      FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.h
  91. 0 125
      FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.m
  92. 0 35
      FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken+FIRAppCheckToken.m
  93. 0 39
      FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.h
  94. 0 62
      FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.m
  95. 0 41
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.h
  96. 0 91
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.m
  97. 0 63
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.h
  98. 0 64
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.m
  99. 0 69
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.h
  100. 0 215
      FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.m

+ 3 - 0
.github/workflows/abtesting.yml

@@ -118,6 +118,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       env:
         LEGACY: true

+ 9 - 3
.github/workflows/auth.yml

@@ -31,8 +31,11 @@ jobs:
         include:
           - os: macos-12
             xcode: Xcode_14.2
+            tests:
+          # Flaky tests on CI
           - os: macos-13
             xcode: Xcode_15.0.1
+            tests: --skip-tests
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
@@ -45,9 +48,10 @@ jobs:
       run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Build and test
 # TODO: Restore warnings check after resolution of #11693
-#      run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseAuth.podspec --platforms=${{ matrix.target }}
+#      run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb ${{ matrix.podspec }} --platforms=${{ matrix.target }}
       run: |
-        scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb ${{ matrix.podspec }} --platforms=${{ matrix.target }} --allow-warnings
+        scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb ${{ matrix.podspec }} --platforms=${{ matrix.target }} \
+         ${{ matrix.tests }} --allow-warnings
 
   integration-tests:
     # Don't run on private repo unless it is a PR.
@@ -96,8 +100,10 @@ jobs:
         include:
           - os: macos-12
             xcode: Xcode_14.2
+            test: spm
           - os: macos-13
             xcode: Xcode_15.0.1
+            test: spmbuildonly
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
@@ -109,7 +115,7 @@ jobs:
     - name: Initialize xcodebuild
       run: scripts/setup_spm_tests.sh
     - name: Unit Tests
-      run: scripts/third_party/travis/retry.sh ./scripts/build.sh AuthUnit ${{ matrix.target }} spm
+      run: scripts/third_party/travis/retry.sh ./scripts/build.sh AuthUnit ${{ matrix.target }} ${{ matrix.test }}
 
   catalyst:
     # Don't run on private repo unless it is a PR.

+ 8 - 1
.github/workflows/crashlytics.yml

@@ -29,8 +29,11 @@ jobs:
         include:
           - os: macos-12
             xcode: Xcode_14.2
+            tests:
+          # Flaky tests on CI
           - os: macos-13
             xcode: Xcode_15.0.1
+            tests: --skip-tests
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
@@ -41,7 +44,8 @@ jobs:
       run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Build and test
       run: |
-        scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseCrashlytics.podspec --platforms=${{ matrix.target }}
+        scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseCrashlytics.podspec --platforms=${{ matrix.target }} \
+         ${{ matrix.tests }}
 
   spm:
     # Don't run on private repo unless it is a PR.
@@ -128,6 +132,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh crashlytics
       env:

+ 3 - 1
.github/workflows/database.yml

@@ -31,8 +31,10 @@ jobs:
         include:
           - os: macos-12
             xcode: Xcode_14.2
+            tests: --test-specs=unit
           - os: macos-13
             xcode: Xcode_15.0.1
+            tests: --skip-tests
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
@@ -42,7 +44,7 @@ jobs:
     - name: Xcode
       run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Build and test
-      run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseDatabase.podspec --test-specs=unit --platforms=${{ matrix.target }}
+      run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseDatabase.podspec ${{ matrix.tests }} --platforms=${{ matrix.target }}
 
   integration:
     # Don't run on private repo unless it is a PR.

+ 3 - 0
.github/workflows/dynamiclinks.yml

@@ -120,6 +120,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh DynamicLinks
     - name: Install Secret GoogleService-Info.plist

+ 12 - 0
.github/workflows/firestore.yml

@@ -130,6 +130,10 @@ jobs:
         key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
         restore-keys: ${{ runner.os }}-mint-
 
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
+
     - name: Setup build
       run:  scripts/install_prereqs.sh Firestore ${{ runner.os }} cmake
 
@@ -176,6 +180,10 @@ jobs:
         key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
         restore-keys: ${{ runner.os }}-mint-
 
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
+
     - name: Install Secret GoogleService-Info.plist
       run: scripts/decrypt_gha_secret.sh scripts/gha-encrypted/firestore.plist.gpg \
         Firestore/Example/App/GoogleService-Info.plist "$plist_secret"
@@ -252,6 +260,10 @@ jobs:
         restore-keys: |
           ${{ matrix.sanitizer }}-firestore-ccache-${{ runner.os }}-
 
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
+
     - name: Setup build
       run:  scripts/install_prereqs.sh Firestore ${{ runner.os }} cmake
 

+ 3 - 0
.github/workflows/functions.yml

@@ -145,6 +145,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh functions
     - name: install secret googleservice-info.plist

+ 3 - 0
.github/workflows/installations.yml

@@ -123,6 +123,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh installations
     - name: Copy mock plist

+ 3 - 0
.github/workflows/messaging.yml

@@ -160,6 +160,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh messaging
     - name: Install Secret GoogleService-Info.plist

+ 3 - 0
.github/workflows/performance.yml

@@ -103,6 +103,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh performance
     - name: Install Secret GoogleService-Info.plist

+ 2 - 0
.github/workflows/shared-swift.yml

@@ -4,6 +4,7 @@ on:
   pull_request:
     paths:
     - 'FirebaseSharedSwift**'
+    - '.github/workflows/shared-swift.yml'
     - 'Gemfile*'
 
   schedule:
@@ -45,6 +46,7 @@ jobs:
     if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
     strategy:
       matrix:
+        target: [iOS, tvOS, macOS, catalyst, watchOS]
         os: [macos-12, macos-13]
         include:
           - os: macos-12

+ 7 - 1
.github/workflows/storage.yml

@@ -147,6 +147,9 @@ jobs:
     steps:
     - uses: actions/checkout@v3
     - uses: ruby/setup-ruby@v1
+    - uses: actions/setup-python@v4
+      with:
+        python-version: '3.7'
     - name: Setup quickstart
       run: scripts/setup_quickstart.sh storage
     - name: Install Secret GoogleService-Info.plist
@@ -173,8 +176,10 @@ jobs:
         include:
           - os: macos-12
             xcode: Xcode_14.2
+            tests: --test-specs=unit
           - os: macos-13
             xcode: Xcode_15.0.1
+            tests: --skip-tests
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
@@ -187,7 +192,8 @@ jobs:
       run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Build and test
       run: |
-       scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseStorage.podspec --test-specs=unit --platforms=${{ matrix.target }}
+       scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseStorage.podspec ${{ matrix.tests }} \
+         --platforms=${{ matrix.target }}
 
   storage-cron-only:
     # Don't run on private repo.

+ 113 - 11
.github/workflows/zip.yml

@@ -101,7 +101,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "ABTesting"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -116,6 +124,8 @@ jobs:
         mkdir -p "${HOME}"/ios_frameworks/
         find "${GITHUB_WORKSPACE}/${FRAMEWORK_DIR}" -name "Firebase*latest.zip" -exec unzip -d "${HOME}"/ios_frameworks/ {} +
     - uses: actions/checkout@v3
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup quickstart
       env:
         LEGACY: true
@@ -153,7 +163,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK:  "Authentication"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -167,6 +185,8 @@ jobs:
       run: |
         mkdir -p "${HOME}"/ios_frameworks/
         find "${GITHUB_WORKSPACE}/${FRAMEWORK_DIR}" -name "Firebase*latest.zip" -exec unzip -d "${HOME}"/ios_frameworks/ {} +
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup Swift Quickstart
       run: SAMPLE="$SDK" TARGET="${SDK}Example" NON_FIREBASE_SDKS="FBSDKLoginKit FBSDKCoreKit FBSDKCoreKit_Basics FBAEMKit" scripts/setup_quickstart_framework.sh \
                                                "${HOME}"/ios_frameworks/Firebase/NonFirebaseSDKs/* \
@@ -197,7 +217,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Config"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -211,6 +239,8 @@ jobs:
       run: |
         mkdir -p "${HOME}"/ios_frameworks/
         find "${GITHUB_WORKSPACE}/${FRAMEWORK_DIR}" -name "Firebase*latest.zip" -exec unzip -d "${HOME}"/ios_frameworks/ {} +
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup Swift Quickstart
 
       run: SAMPLE="$SDK" TARGET="${SDK}Example" scripts/setup_quickstart_framework.sh \
@@ -239,7 +269,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Crashlytics"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -254,6 +292,8 @@ jobs:
         mkdir -p "${HOME}"/ios_frameworks/
         find "${GITHUB_WORKSPACE}/${FRAMEWORK_DIR}" -name "Firebase*latest.zip" -exec unzip -d "${HOME}"/ios_frameworks/ {} +
     - uses: actions/checkout@v3
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup quickstart
       env:
         LEGACY: true
@@ -304,7 +344,16 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Database"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          # TODO: Building FirebaseUI fails on Xcode 15 because it needs to sign the resources.
+          # - os: macos-13
+          #   xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -319,6 +368,8 @@ jobs:
         mkdir -p "${HOME}"/ios_frameworks/
         find "${GITHUB_WORKSPACE}/${FRAMEWORK_DIR}" -name "Firebase*latest.zip" -exec unzip -d "${HOME}"/ios_frameworks/ {} +
     - uses: actions/checkout@v3
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup quickstart
       run: SAMPLE="$SDK" TARGET="${SDK}Example" NON_FIREBASE_SDKS="FirebaseDatabaseUI" scripts/setup_quickstart_framework.sh \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseDatabase/* \
@@ -350,7 +401,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "DynamicLinks"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -368,6 +427,8 @@ jobs:
       run: SAMPLE="$SDK" TARGET="${SDK}Example" scripts/setup_quickstart_framework.sh \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseDynamicLinks/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/*
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup Swift Quickstart
       run: SAMPLE="$SDK" TARGET="${SDK}ExampleSwift" scripts/setup_quickstart_framework.sh
     - name: Update Environment Variable For DynamicLinks
@@ -400,7 +461,16 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Firestore"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          # TODO: Building FirebaseUI fails on Xcode 15 because it needs to sign the resources.
+          # - os: macos-13
+          #   xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -421,6 +491,8 @@ jobs:
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseFirestore/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAuth/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/*
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Install Secret GoogleService-Info.plist
       run: scripts/decrypt_gha_secret.sh scripts/gha-encrypted/qs-firestore.plist.gpg \
         quickstart-ios/firestore/GoogleService-Info.plist "$plist_secret"
@@ -442,7 +514,7 @@ jobs:
     env:
       FRAMEWORK_DIR: "Firebase-actions-dir"
       FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: 1
-    runs-on: macos-12
+    runs-on: macos-13
     steps:
       - name: Xcode 14.1
         run: sudo xcode-select -s /Applications/Xcode_14.1.app/Contents/Developer
@@ -476,7 +548,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "InAppMessaging"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -496,6 +576,8 @@ jobs:
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseDynamicLinks/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseInAppMessaging/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/*
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup swift quickstart
       run: SAMPLE="$SDK" TARGET="${SDK}ExampleSwift" scripts/setup_quickstart_framework.sh
     - name: Install Secret GoogleService-Info.plist
@@ -523,7 +605,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Messaging"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -542,6 +632,8 @@ jobs:
       run: SAMPLE="$SDK" TARGET="${SDK}Example" scripts/setup_quickstart_framework.sh \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseMessaging/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/*
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup swift quickstart
       run: SAMPLE="$SDK" TARGET="${SDK}ExampleSwift" scripts/setup_quickstart_framework.sh
     - name: Install Secret GoogleService-Info.plist
@@ -569,7 +661,15 @@ jobs:
       signin_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
       FRAMEWORK_DIR: "Firebase-actions-dir"
       SDK: "Storage"
-    runs-on: macos-12
+    strategy:
+      matrix:
+        os: [macos-12, macos-13]
+        include:
+          - os: macos-12
+            xcode: Xcode_14.2
+          - os: macos-13
+            xcode: Xcode_15.0.1
+    runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v3
     - name: Get framework dir
@@ -591,6 +691,8 @@ jobs:
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseStorage/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAuth/* \
                                                "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/*
+    - name: Xcode
+      run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
     - name: Setup swift quickstart
       env:
         LEGACY: true

+ 1 - 1
ClientApp/Shared-iOS11+/swift-import-test.swift

@@ -49,8 +49,8 @@ import FirebaseInstallations
 import FirebaseMessaging
 import FirebaseMLModelDownloader
 #if (os(iOS) && !targetEnvironment(macCatalyst)) || os(tvOS)
-  import FirebasePerformance
   import FirebaseInAppMessaging
+  import FirebasePerformance
 #endif
 import FirebaseRemoteConfig
 import FirebaseRemoteConfigSwift

+ 231 - 235
CoreOnly/NOTICES

@@ -1,3 +1,234 @@
+AppCheckCore
+Firebase
+FirebaseABTesting
+FirebaseAppCheck
+FirebaseAppCheckInterop
+FirebaseAppDistribution
+FirebaseAuth
+FirebaseAuthInterop
+FirebaseCore
+FirebaseCoreExtension
+FirebaseCoreInternal
+FirebaseDynamicLinks
+FirebaseFunctions
+FirebaseInAppMessaging
+FirebaseInstallations
+FirebaseMLModelDownloader
+FirebaseMessaging
+FirebaseMessagingInterop
+FirebasePerformance
+FirebaseRemoteConfig
+FirebaseSessions
+FirebaseStorage
+GTMSessionFetcher
+GoogleDataTransport
+PromisesObjC
+PromisesSwift
+RecaptchaInterop
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
 BoringSSL-GRPC
 BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
 licensing. Files that are completely new have a Google copyright and an ISC
@@ -252,241 +483,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Firebase
-FirebaseABTesting
-FirebaseAnalyticsSwift
-FirebaseAppCheck
-FirebaseAppCheckInterop
-FirebaseAppDistribution
-FirebaseAuth
-FirebaseAuthInterop
-FirebaseCore
-FirebaseCoreExtension
-FirebaseCoreInternal
-FirebaseDatabaseSwift
-FirebaseDynamicLinks
-FirebaseFirestoreSwift
-FirebaseFunctions
-FirebaseInAppMessaging
-FirebaseInAppMessagingSwift
-FirebaseInstallations
-FirebaseMLModelDownloader
-FirebaseMessaging
-FirebaseMessagingInterop
-FirebasePerformance
-FirebaseRemoteConfig
-FirebaseRemoteConfigSwift
-FirebaseSessions
-FirebaseStorage
-GTMSessionFetcher
-GoogleDataTransport
-PromisesObjC
-PromisesSwift
-RecaptchaInterop
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
 FirebaseAnalytics
 FirebaseAnalyticsOnDeviceConversion
 GoogleAppMeasurement

+ 1 - 1
CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift

@@ -12,12 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import Firebase
 // Verify that the following Firebase Swift APIs can be found.
 import FirebaseAnalyticsSwift
 import FirebaseFirestoreSwift
 import FirebaseInAppMessagingSwift
+import UIKit
 
 class CoreExists: FirebaseApp {}
 class AnalyticsExists: Analytics {}

+ 1 - 1
Example/CombineSample/CombineSample/App/CombineSampleApp.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import Firebase
+import SwiftUI
 
 @main
 struct CombineSampleApp: App {

+ 2 - 2
Example/CombineSample/CombineSample/ViewModels/Authentication/AnonymousSignInViewModel.swift

@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import Foundation
+import Combine
 import Firebase
 import FirebaseAuthCombineSwift
 import FirebaseFirestoreCombineSwift
 import FirebaseFunctionsCombineSwift
 import FirebaseStorageCombineSwift
-import Combine
+import Foundation
 
 class AnonymousSignInViewModel: UserInfoViewModel {
   private var cancellables = Set<AnyCancellable>()

+ 1 - 1
Example/CombineSample/CombineSample/ViewModels/Authentication/UserInfoViewModel.swift

@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import Combine
 import Firebase
 import FirebaseAuth
 import FirebaseAuthCombineSwift
-import Combine
 
 class UserInfoViewModel: ObservableObject {
   @Published var user: User?

+ 2 - 2
Example/CombineSample/CombineSample/Views/Authentication/AnonymousSignInView.swift

@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
+import Combine
 import Firebase
 import FirebaseAuthCombineSwift
-import Combine
+import SwiftUI
 
 struct AnonymousSignInView: View {
   @StateObject var viewModel = AnonymousSignInViewModel()

+ 2 - 2
Example/FirestoreSample/FirestoreSample/App/FirestoreSampleApp.swift

@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
+import FirebaseAuth
 import FirebaseCore
 import FirebaseFirestore
-import FirebaseAuth
+import SwiftUI
 
 class AppDelegate: NSObject, UIApplicationDelegate {
   func application(_ application: UIApplication,

+ 1 - 1
Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsAnimationView.swift

@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseFirestore
 import FirebaseFirestoreSwift
+import SwiftUI
 
 private struct Fruit: Codable, Identifiable, Equatable {
   @DocumentID var id: String?

+ 1 - 1
Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsMappingErrorView.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseFirestoreSwift
+import SwiftUI
 
 private struct Fruit: Codable, Identifiable, Equatable {
   @DocumentID var id: String?

+ 1 - 1
Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsMappingErrorView2.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseFirestoreSwift
+import SwiftUI
 
 private struct Fruit: Codable, Identifiable, Equatable {
   @DocumentID var id: String?

+ 1 - 1
Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsNoAnimationsView.swift

@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseFirestore
 import FirebaseFirestoreSwift
+import SwiftUI
 
 private struct Fruit: Codable, Identifiable, Equatable {
   @DocumentID var id: String?

+ 1 - 1
Example/FirestoreSample/FirestoreSample/Views/FavouriteFruitsView.swift

@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseFirestore
 import FirebaseFirestoreSwift
+import SwiftUI
 
 private struct Fruit: Codable, Identifiable, Equatable {
   @DocumentID var id: String?

+ 1 - 1
Example/tvOSSample/tvOSSample/AppDelegate.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseCore
+import UIKit
 
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

+ 1 - 1
Example/tvOSSample/tvOSSample/AuthLoginViewController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseAuth
+import UIKit
 
 class AuthLoginViewController: UIViewController {
   override func viewDidLoad() {

+ 1 - 1
Example/tvOSSample/tvOSSample/AuthViewController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseAuth
+import UIKit
 
 class AuthViewController: UIViewController {
   // MARK: - User Interface

+ 1 - 1
Example/tvOSSample/tvOSSample/DatabaseViewController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseDatabase
+import UIKit
 
 /// A class to demonstrate the Firebase Realtime Database API. This will show a number read
 /// from the Database and increase or decrease it based on the buttons pressed.

+ 1 - 1
Example/tvOSSample/tvOSSample/EmailLoginViewController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseAuth
+import UIKit
 
 protocol EmailLoginDelegate {
   func emailLogin(_ controller: EmailLoginViewController, signedInAs user: User)

+ 1 - 1
Example/tvOSSample/tvOSSample/StorageViewController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UIKit
 import FirebaseStorage
+import UIKit
 
 class StorageViewController: UIViewController {
   /// An enum describing the different states of the view controller.

+ 1 - 1
Example/watchOSSample/SampleWatchAppWatchKitExtension/InterfaceController.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import SwiftUI
 import FirebaseStorage
+import SwiftUI
 
 class InterfaceController: WKInterfaceController {
   @IBOutlet var imageView: WKInterfaceImage!

+ 1 - 1
Example/watchOSSample/SampleWatchAppWatchKitExtension/NotificationController.swift

@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import WatchKit
 import Foundation
 import UserNotifications
+import WatchKit
 
 class NotificationController: WKUserNotificationInterfaceController {
   override init() {

+ 1 - 1
Example/watchOSSample/ServiceExtension/NotificationService.swift

@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import UserNotifications
 import FirebaseMessaging
+import UserNotifications
 
 class NotificationService: UNNotificationServiceExtension {
   var contentHandler: ((UNNotificationContent) -> Void)?

+ 24 - 24
Firebase.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = 'Firebase'
-  s.version          = '10.18.0'
+  s.version          = '10.19.0'
   s.summary          = 'Firebase'
 
   s.description      = <<-DESC
@@ -36,14 +36,14 @@ Simplify your app development, grow your user base, and monetize more effectivel
     ss.ios.deployment_target = '10.0'
     ss.osx.deployment_target = '10.13'
     ss.tvos.deployment_target = '12.0'
-    ss.ios.dependency 'FirebaseAnalytics', '~> 10.18.0'
-    ss.osx.dependency 'FirebaseAnalytics', '~> 10.18.0'
-    ss.tvos.dependency 'FirebaseAnalytics', '~> 10.18.0'
+    ss.ios.dependency 'FirebaseAnalytics', '~> 10.19.0'
+    ss.osx.dependency 'FirebaseAnalytics', '~> 10.19.0'
+    ss.tvos.dependency 'FirebaseAnalytics', '~> 10.19.0'
     ss.dependency 'Firebase/CoreOnly'
   end
 
   s.subspec 'CoreOnly' do |ss|
-    ss.dependency 'FirebaseCore', '10.18.0'
+    ss.dependency 'FirebaseCore', '10.19.0'
     ss.source_files = 'CoreOnly/Sources/Firebase.h'
     ss.preserve_paths = 'CoreOnly/Sources/module.modulemap'
     if ENV['FIREBASE_POD_REPO_FOR_DEV_POD'] then
@@ -79,13 +79,13 @@ Simplify your app development, grow your user base, and monetize more effectivel
     ss.ios.deployment_target = '10.0'
     ss.osx.deployment_target = '10.13'
     ss.tvos.deployment_target = '12.0'
-    ss.dependency 'FirebaseAnalytics/WithoutAdIdSupport', '~> 10.18.0'
+    ss.dependency 'FirebaseAnalytics/WithoutAdIdSupport', '~> 10.19.0'
     ss.dependency 'Firebase/CoreOnly'
   end
 
   s.subspec 'ABTesting' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseABTesting', '~> 10.18.0'
+    ss.dependency 'FirebaseABTesting', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -95,13 +95,13 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'AppDistribution' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.ios.dependency 'FirebaseAppDistribution', '~> 10.18.0-beta'
+    ss.ios.dependency 'FirebaseAppDistribution', '~> 10.19.0-beta'
     ss.ios.deployment_target = '11.0'
   end
 
   s.subspec 'AppCheck' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseAppCheck', '~> 10.18.0'
+    ss.dependency 'FirebaseAppCheck', '~> 10.19.0'
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
     ss.tvos.deployment_target = '12.0'
@@ -110,7 +110,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Auth' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseAuth', '~> 10.18.0'
+    ss.dependency 'FirebaseAuth', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -120,7 +120,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Crashlytics' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseCrashlytics', '~> 10.18.0'
+    ss.dependency 'FirebaseCrashlytics', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -130,7 +130,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Database' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseDatabase', '~> 10.18.0'
+    ss.dependency 'FirebaseDatabase', '~> 10.19.0'
     # Standard platforms PLUS watchOS 7.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -140,13 +140,13 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'DynamicLinks' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.ios.dependency 'FirebaseDynamicLinks', '~> 10.18.0'
+    ss.ios.dependency 'FirebaseDynamicLinks', '~> 10.19.0'
     ss.ios.deployment_target = '11.0'
   end
 
   s.subspec 'Firestore' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseFirestore', '~> 10.18.0'
+    ss.dependency 'FirebaseFirestore', '~> 10.19.0'
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
     ss.tvos.deployment_target = '12.0'
@@ -154,7 +154,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Functions' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseFunctions', '~> 10.18.0'
+    ss.dependency 'FirebaseFunctions', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -164,20 +164,20 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'InAppMessaging' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.ios.dependency 'FirebaseInAppMessaging', '~> 10.18.0-beta'
-    ss.tvos.dependency 'FirebaseInAppMessaging', '~> 10.18.0-beta'
+    ss.ios.dependency 'FirebaseInAppMessaging', '~> 10.19.0-beta'
+    ss.tvos.dependency 'FirebaseInAppMessaging', '~> 10.19.0-beta'
     ss.ios.deployment_target = '11.0'
     ss.tvos.deployment_target = '12.0'
   end
 
   s.subspec 'Installations' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseInstallations', '~> 10.18.0'
+    ss.dependency 'FirebaseInstallations', '~> 10.19.0'
   end
 
   s.subspec 'Messaging' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseMessaging', '~> 10.18.0'
+    ss.dependency 'FirebaseMessaging', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -187,7 +187,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'MLModelDownloader' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseMLModelDownloader', '~> 10.18.0-beta'
+    ss.dependency 'FirebaseMLModelDownloader', '~> 10.19.0-beta'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -197,15 +197,15 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Performance' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.ios.dependency 'FirebasePerformance', '~> 10.18.0'
-    ss.tvos.dependency 'FirebasePerformance', '~> 10.18.0'
+    ss.ios.dependency 'FirebasePerformance', '~> 10.19.0'
+    ss.tvos.dependency 'FirebasePerformance', '~> 10.19.0'
     ss.ios.deployment_target = '11.0'
     ss.tvos.deployment_target = '12.0'
   end
 
   s.subspec 'RemoteConfig' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseRemoteConfig', '~> 10.18.0'
+    ss.dependency 'FirebaseRemoteConfig', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'
@@ -215,7 +215,7 @@ Simplify your app development, grow your user base, and monetize more effectivel
 
   s.subspec 'Storage' do |ss|
     ss.dependency 'Firebase/CoreOnly'
-    ss.dependency 'FirebaseStorage', '~> 10.18.0'
+    ss.dependency 'FirebaseStorage', '~> 10.19.0'
     # Standard platforms PLUS watchOS.
     ss.ios.deployment_target = '11.0'
     ss.osx.deployment_target = '10.13'

+ 1 - 1
FirebaseABTesting.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = 'FirebaseABTesting'
-  s.version          = '10.18.0'
+  s.version          = '10.19.0'
   s.summary          = 'Firebase ABTesting'
 
   s.description      = <<-DESC

+ 1 - 1
FirebaseABTesting/Tests/Integration/ABTQA/AppDelegate.swift

@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-import UIKit
 import Firebase
+import UIKit
 
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

+ 1 - 1
FirebaseABTesting/Tests/Integration/ABTQA/ViewController.swift

@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-import UIKit
 import FirebaseAnalytics
 import FirebaseRemoteConfig
+import UIKit
 
 class ViewController: UIViewController {
   @IBAction func fireAnalyticsEventButtonTapped(_ sender: Any) {

+ 3 - 3
FirebaseAnalytics.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
     s.name             = 'FirebaseAnalytics'
-    s.version          = '10.18.0'
+    s.version          = '10.19.0'
     s.summary          = 'Firebase Analytics for iOS'
 
     s.description      = <<-DESC
@@ -37,12 +37,12 @@ Pod::Spec.new do |s|
     s.default_subspecs = 'AdIdSupport'
 
     s.subspec 'AdIdSupport' do |ss|
-        ss.dependency 'GoogleAppMeasurement', '10.18.0'
+        ss.dependency 'GoogleAppMeasurement', '10.19.0'
         ss.vendored_frameworks = 'Frameworks/FirebaseAnalytics.xcframework'
     end
 
     s.subspec 'WithoutAdIdSupport' do |ss|
-        ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.18.0'
+        ss.dependency 'GoogleAppMeasurement/WithoutAdIdSupport', '10.19.0'
         ss.vendored_frameworks = 'Frameworks/FirebaseAnalytics.xcframework'
     end
 

+ 1 - 1
FirebaseAnalytics/Analytics+SwiftUI.swift

@@ -19,7 +19,7 @@
   /// Custom view modifier to allow for easily logging screen view events.
   @available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, *)
   @available(watchOS, unavailable)
-  internal struct LoggedAnalyticsModifier: ViewModifier {
+  struct LoggedAnalyticsModifier: ViewModifier {
     /// The name of the view to log in the `AnalyticsParameterScreenName` parameter.
     let screenName: String
 

+ 2 - 2
FirebaseAnalyticsOnDeviceConversion.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
     s.name             = 'FirebaseAnalyticsOnDeviceConversion'
-    s.version          = '10.18.0'
+    s.version          = '10.19.0'
     s.summary          = 'On device conversion measurement plugin for FirebaseAnalytics. Not intended for direct use.'
 
     s.description      = <<-DESC
@@ -18,7 +18,7 @@ Pod::Spec.new do |s|
 
     s.cocoapods_version = '>= 1.10.2'
 
-    s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.18.0'
+    s.dependency 'GoogleAppMeasurementOnDeviceConversion', '10.19.0'
 
     s.static_framework = true
 

+ 1 - 1
FirebaseAnalyticsSwift.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name                    = 'FirebaseAnalyticsSwift'
-  s.version                 = '10.18.0'
+  s.version                 = '10.19.0'
   s.summary                 = 'Swift Extensions for Firebase Analytics'
 
   s.description      = <<-DESC

+ 1 - 1
FirebaseAnalyticsSwift/Tests/SwiftUnit/AnalyticsAPITests.swift

@@ -20,9 +20,9 @@ import Foundation
 import StoreKit
 import SwiftUI
 
+import FirebaseAnalytics
 import FirebaseAnalyticsSwift
 import SwiftUI
-import FirebaseAnalytics
 
 final class AnalyticsAPITests {
   func usage() {

+ 2 - 2
FirebaseAppCheck.podspec

@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name             = 'FirebaseAppCheck'
-  s.version          = '10.18.0'
+  s.version          = '10.19.0'
   s.summary          = 'Firebase App Check SDK.'
 
   s.description      = <<-DESC
@@ -44,6 +44,7 @@ Pod::Spec.new do |s|
   s.osx.weak_framework = 'DeviceCheck'
   s.tvos.weak_framework = 'DeviceCheck'
 
+  s.dependency 'AppCheckCore', '~> 10.18'
   s.dependency 'FirebaseAppCheckInterop', '~> 10.17'
   s.dependency 'FirebaseCore', '~> 10.0'
   s.dependency 'PromisesObjC', '~> 2.1'
@@ -93,7 +94,6 @@ Pod::Spec.new do |s|
     }
     swift_unit_tests.source_files = [
       base_dir + 'Tests/Unit/Swift/**/*.swift',
-      base_dir + 'Tests/Unit/Swift/**/*.h',
     ]
   end
 

+ 2 - 2
FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/AppDelegate.swift

@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-import UIKit
-import FirebaseCore
 import FirebaseAppCheck
+import FirebaseCore
+import UIKit
 
 @main
 class AppDelegate: UIResponder, UIApplicationDelegate {

+ 2 - 2
FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/MyAppCheckProvider.swift

@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-import Foundation
-import FirebaseCore
 import FirebaseAppCheck
+import FirebaseCore
+import Foundation
 
 class MyAppCheckProvider: NSObject, AppCheckProvider {
   func getToken(completion handler: @escaping AppCheckTokenHandler) {

+ 1 - 1
FirebaseAppCheck/Apps/AppCheckCustomProvideApp/AppCheckCustomProvideApp/SceneDelegate.swift

@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-import UIKit
 import SwiftUI
+import UIKit
 
 class SceneDelegate: UIResponder, UIWindowSceneDelegate {
   var window: UIWindow?

+ 1 - 1
FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp/AppDelegate.swift

@@ -16,8 +16,8 @@
 
 import UIKit
 
-import FirebaseCore
 import FirebaseAppCheck
+import FirebaseCore
 
 @main
 class AppDelegate: UIResponder, UIApplicationDelegate {

+ 4 - 0
FirebaseAppCheck/CHANGELOG.md

@@ -1,3 +1,7 @@
+# 10.18.0
+- [changed] Extracted core `FirebaseAppCheck` functionality into a new
+  [`AppCheckCore`](https://github.com/google/app-check) dependency. (#12067)
+
 # 10.17.0
 - [fixed] Added invalid key error handling in App Attest key attestation. (#11986)
 - [fixed] Replaced semantic imports (`@import FirebaseAppCheckInterop`) with umbrella header imports

+ 0 - 65
FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.h

@@ -1,65 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<Result>;
-@class FIRAppAttestAttestationResponse;
-@class FIRAppCheckToken;
-@protocol FIRAppCheckAPIServiceProtocol;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// Methods to send API requests required for App Attest based attestation sequence.
-@protocol FIRAppAttestAPIServiceProtocol <NSObject>
-
-/// Request a random challenge from server.
-- (FBLPromise<NSData *> *)getRandomChallenge;
-
-/// Sends attestation data to Firebase backend for validation.
-/// @param attestation The App Attest key attestation data obtained from the method
-/// `-[DCAppAttestService attestKey:clientDataHash:completionHandler:]` using the random challenge
-/// received from Firebase backend.
-/// @param keyID The key ID used to generate the attestation.
-/// @param challenge The challenge used to generate the attestation.
-/// @return A promise that is fulfilled with a response object with an encrypted attestation
-/// artifact and an Firebase App Check token or rejected with an error.
-- (FBLPromise<FIRAppAttestAttestationResponse *> *)attestKeyWithAttestation:(NSData *)attestation
-                                                                      keyID:(NSString *)keyID
-                                                                  challenge:(NSData *)challenge;
-
-/// Exchanges attestation data (artifact & assertion) and a challenge for a FAC token.
-- (FBLPromise<FIRAppCheckToken *> *)getAppCheckTokenWithArtifact:(NSData *)artifact
-                                                       challenge:(NSData *)challenge
-                                                       assertion:(NSData *)assertion;
-
-@end
-
-/// A default implementation of `FIRAppAttestAPIServiceProtocol`.
-@interface FIRAppAttestAPIService : NSObject <FIRAppAttestAPIServiceProtocol>
-
-/// Default initializer.
-/// @param APIService An instance implementing `FIRAppCheckAPIServiceProtocol` to be used to send
-/// network requests to Firebase App Check backend.
-/// @param projectID A Firebase project ID for the requests (`FIRApp.options.projectID`).
-/// @param appID A Firebase app ID for the requests (`FIRApp.options.googleAppID`).
-- (instancetype)initWithAPIService:(id<FIRAppCheckAPIServiceProtocol>)APIService
-                         projectID:(NSString *)projectID
-                             appID:(NSString *)appID;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 261
FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.m

@@ -1,261 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h"
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h"
-
-#import <GoogleUtilities/GULURLSessionDataResponse.h>
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-static NSString *const kRequestFieldArtifact = @"artifact";
-static NSString *const kRequestFieldAssertion = @"assertion";
-static NSString *const kRequestFieldAttestation = @"attestation_statement";
-static NSString *const kRequestFieldChallenge = @"challenge";
-static NSString *const kRequestFieldKeyID = @"key_id";
-
-static NSString *const kExchangeAppAttestAssertionEndpoint = @"exchangeAppAttestAssertion";
-static NSString *const kExchangeAppAttestAttestationEndpoint = @"exchangeAppAttestAttestation";
-static NSString *const kGenerateAppAttestChallengeEndpoint = @"generateAppAttestChallenge";
-
-static NSString *const kContentTypeKey = @"Content-Type";
-static NSString *const kJSONContentType = @"application/json";
-static NSString *const kHTTPMethodPost = @"POST";
-
-@interface FIRAppAttestAPIService ()
-
-@property(nonatomic, readonly) id<FIRAppCheckAPIServiceProtocol> APIService;
-
-@property(nonatomic, readonly) NSString *projectID;
-@property(nonatomic, readonly) NSString *appID;
-
-@end
-
-@implementation FIRAppAttestAPIService
-
-- (instancetype)initWithAPIService:(id<FIRAppCheckAPIServiceProtocol>)APIService
-                         projectID:(NSString *)projectID
-                             appID:(NSString *)appID {
-  self = [super init];
-  if (self) {
-    _APIService = APIService;
-    _projectID = projectID;
-    _appID = appID;
-  }
-  return self;
-}
-
-#pragma mark - Assertion request
-
-- (FBLPromise<FIRAppCheckToken *> *)getAppCheckTokenWithArtifact:(NSData *)artifact
-                                                       challenge:(NSData *)challenge
-                                                       assertion:(NSData *)assertion {
-  NSURL *URL = [self URLForEndpoint:kExchangeAppAttestAssertionEndpoint];
-
-  return [self HTTPBodyWithArtifact:artifact challenge:challenge assertion:assertion]
-      .then(^FBLPromise<GULURLSessionDataResponse *> *(NSData *HTTPBody) {
-        return [self.APIService sendRequestWithURL:URL
-                                        HTTPMethod:kHTTPMethodPost
-                                              body:HTTPBody
-                                 additionalHeaders:@{kContentTypeKey : kJSONContentType}];
-      })
-      .then(^id _Nullable(GULURLSessionDataResponse *_Nullable response) {
-        return [self.APIService appCheckTokenWithAPIResponse:response];
-      });
-}
-
-#pragma mark - Random Challenge
-
-- (nonnull FBLPromise<NSData *> *)getRandomChallenge {
-  NSURL *URL = [self URLForEndpoint:kGenerateAppAttestChallengeEndpoint];
-
-  return [FBLPromise onQueue:[self backgroundQueue]
-                          do:^id _Nullable {
-                            return [self.APIService sendRequestWithURL:URL
-                                                            HTTPMethod:kHTTPMethodPost
-                                                                  body:nil
-                                                     additionalHeaders:nil];
-                          }]
-      .then(^id _Nullable(GULURLSessionDataResponse *_Nullable response) {
-        return [self randomChallengeWithAPIResponse:response];
-      });
-}
-
-#pragma mark - Challenge response parsing
-
-- (FBLPromise<NSData *> *)randomChallengeWithAPIResponse:(GULURLSessionDataResponse *)response {
-  return [FBLPromise onQueue:[self backgroundQueue]
-                          do:^id _Nullable {
-                            NSError *error;
-
-                            NSData *randomChallenge =
-                                [self randomChallengeFromResponseBody:response.HTTPBody
-                                                                error:&error];
-
-                            return randomChallenge ?: error;
-                          }];
-}
-
-- (nullable NSData *)randomChallengeFromResponseBody:(NSData *)response error:(NSError **)outError {
-  if (response.length <= 0) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil errorWithFailureReason:@"Empty server response body."], outError);
-    return nil;
-  }
-
-  NSError *JSONError;
-  NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:response
-                                                               options:0
-                                                                 error:&JSONError];
-
-  if (![responseDict isKindOfClass:[NSDictionary class]]) {
-    FIRAppCheckSetErrorToPointer([FIRAppCheckErrorUtil JSONSerializationError:JSONError], outError);
-    return nil;
-  }
-
-  NSString *challenge = responseDict[@"challenge"];
-  if (![challenge isKindOfClass:[NSString class]]) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil appCheckTokenResponseErrorWithMissingField:@"challenge"], outError);
-    return nil;
-  }
-
-  NSData *randomChallenge = [[NSData alloc] initWithBase64EncodedString:challenge options:0];
-  return randomChallenge;
-}
-
-#pragma mark - Attestation request
-
-- (FBLPromise<FIRAppAttestAttestationResponse *> *)attestKeyWithAttestation:(NSData *)attestation
-                                                                      keyID:(NSString *)keyID
-                                                                  challenge:(NSData *)challenge {
-  NSURL *URL = [self URLForEndpoint:kExchangeAppAttestAttestationEndpoint];
-
-  return [self HTTPBodyWithAttestation:attestation keyID:keyID challenge:challenge]
-      .then(^FBLPromise<GULURLSessionDataResponse *> *(NSData *HTTPBody) {
-        return [self.APIService sendRequestWithURL:URL
-                                        HTTPMethod:kHTTPMethodPost
-                                              body:HTTPBody
-                                 additionalHeaders:@{kContentTypeKey : kJSONContentType}];
-      })
-      .thenOn(
-          [self backgroundQueue], ^id _Nullable(GULURLSessionDataResponse *_Nullable URLResponse) {
-            NSError *error;
-
-            __auto_type response =
-                [[FIRAppAttestAttestationResponse alloc] initWithResponseData:URLResponse.HTTPBody
-                                                                  requestDate:[NSDate date]
-                                                                        error:&error];
-
-            return response ?: error;
-          });
-}
-
-#pragma mark - Request HTTP Body
-
-- (FBLPromise<NSData *> *)HTTPBodyWithArtifact:(NSData *)artifact
-                                     challenge:(NSData *)challenge
-                                     assertion:(NSData *)assertion {
-  if (artifact.length <= 0 || challenge.length <= 0 || assertion.length <= 0) {
-    FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-    [rejectedPromise reject:[FIRAppCheckErrorUtil
-                                errorWithFailureReason:@"Missing or empty request parameter."]];
-    return rejectedPromise;
-  }
-
-  return [FBLPromise onQueue:[self backgroundQueue]
-                          do:^id {
-                            id JSONObject = @{
-                              kRequestFieldArtifact : [self base64StringWithData:artifact],
-                              kRequestFieldChallenge : [self base64StringWithData:challenge],
-                              kRequestFieldAssertion : [self base64StringWithData:assertion]
-                            };
-
-                            return [self HTTPBodyWithJSONObject:JSONObject];
-                          }];
-}
-
-- (FBLPromise<NSData *> *)HTTPBodyWithAttestation:(NSData *)attestation
-                                            keyID:(NSString *)keyID
-                                        challenge:(NSData *)challenge {
-  if (attestation.length <= 0 || keyID.length <= 0 || challenge.length <= 0) {
-    FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-    [rejectedPromise reject:[FIRAppCheckErrorUtil
-                                errorWithFailureReason:@"Missing or empty request parameter."]];
-    return rejectedPromise;
-  }
-
-  return [FBLPromise onQueue:[self backgroundQueue]
-                          do:^id {
-                            id JSONObject = @{
-                              kRequestFieldKeyID : keyID,
-                              kRequestFieldAttestation : [self base64StringWithData:attestation],
-                              kRequestFieldChallenge : [self base64StringWithData:challenge]
-                            };
-
-                            return [self HTTPBodyWithJSONObject:JSONObject];
-                          }];
-}
-
-- (FBLPromise<NSData *> *)HTTPBodyWithJSONObject:(nonnull id)JSONObject {
-  NSError *encodingError;
-  NSData *payloadJSON = [NSJSONSerialization dataWithJSONObject:JSONObject
-                                                        options:0
-                                                          error:&encodingError];
-  FBLPromise<NSData *> *HTTPBodyPromise = [FBLPromise pendingPromise];
-  if (payloadJSON) {
-    [HTTPBodyPromise fulfill:payloadJSON];
-  } else {
-    [HTTPBodyPromise reject:[FIRAppCheckErrorUtil JSONSerializationError:encodingError]];
-  }
-  return HTTPBodyPromise;
-}
-
-#pragma mark - Helpers
-
-- (NSString *)base64StringWithData:(NSData *)data {
-  return [data base64EncodedStringWithOptions:0];
-}
-
-- (NSURL *)URLForEndpoint:(NSString *)endpoint {
-  NSString *URL = [[self class] URLWithBaseURL:self.APIService.baseURL
-                                     projectID:self.projectID
-                                         appID:self.appID];
-  return [NSURL URLWithString:[NSString stringWithFormat:@"%@:%@", URL, endpoint]];
-}
-
-+ (NSString *)URLWithBaseURL:(NSString *)baseURL
-                   projectID:(NSString *)projectID
-                       appID:(NSString *)appID {
-  return [NSString stringWithFormat:@"%@/projects/%@/apps/%@", baseURL, projectID, appID];
-}
-
-- (dispatch_queue_t)backgroundQueue {
-  return dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 43
FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h

@@ -1,43 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FIRAppCheckToken;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppAttestAttestationResponse : NSObject
-
-/// App Attest attestation artifact required to refresh Firebase App Check token.
-@property(nonatomic, readonly) NSData *artifact;
-
-/// Firebase App Check token.
-@property(nonatomic, readonly) FIRAppCheckToken *token;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-- (instancetype)initWithArtifact:(NSData *)artifact
-                           token:(FIRAppCheckToken *)token NS_DESIGNATED_INITIALIZER;
-
-/// Init with the server response.
-- (nullable instancetype)initWithResponseData:(NSData *)response
-                                  requestDate:(NSDate *)requestDate
-                                        error:(NSError **)outError;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 96
FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.m

@@ -1,96 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h"
-
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-static NSString *const kResponseFieldAppCheckTokenDict = @"appCheckToken";
-static NSString *const kResponseFieldArtifact = @"artifact";
-
-@implementation FIRAppAttestAttestationResponse
-
-- (instancetype)initWithArtifact:(NSData *)artifact token:(FIRAppCheckToken *)token {
-  self = [super init];
-  if (self) {
-    _artifact = artifact;
-    _token = token;
-  }
-  return self;
-}
-
-- (nullable instancetype)initWithResponseData:(NSData *)response
-                                  requestDate:(NSDate *)requestDate
-                                        error:(NSError **)outError {
-  if (response.length <= 0) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil
-            errorWithFailureReason:
-                @"Failed to parse the initial handshake response. Empty server response body."],
-        outError);
-    return nil;
-  }
-
-  NSError *JSONError;
-  NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:response
-                                                               options:0
-                                                                 error:&JSONError];
-
-  if (![responseDict isKindOfClass:[NSDictionary class]]) {
-    FIRAppCheckSetErrorToPointer([FIRAppCheckErrorUtil JSONSerializationError:JSONError], outError);
-    return nil;
-  }
-
-  NSString *artifactBase64String = responseDict[kResponseFieldArtifact];
-  if (![artifactBase64String isKindOfClass:[NSString class]]) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil
-            appAttestAttestationResponseErrorWithMissingField:kResponseFieldArtifact],
-        outError);
-    return nil;
-  }
-  NSData *artifactData = [[NSData alloc] initWithBase64EncodedString:artifactBase64String
-                                                             options:0];
-  if (artifactData == nil) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil
-            appAttestAttestationResponseErrorWithMissingField:kResponseFieldArtifact],
-        outError);
-    return nil;
-  }
-
-  NSDictionary *appCheckTokenDict = responseDict[kResponseFieldAppCheckTokenDict];
-  if (![appCheckTokenDict isKindOfClass:[NSDictionary class]]) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil
-            appAttestAttestationResponseErrorWithMissingField:kResponseFieldAppCheckTokenDict],
-        outError);
-    return nil;
-  }
-
-  FIRAppCheckToken *appCheckToken = [[FIRAppCheckToken alloc] initWithResponseDict:appCheckTokenDict
-                                                                       requestDate:requestDate
-                                                                             error:outError];
-
-  if (appCheckToken == nil) {
-    return nil;
-  }
-
-  return [self initWithArtifact:artifactData token:appCheckToken];
-}
-
-@end

+ 0 - 21
FirebaseAppCheck/Sources/AppAttestProvider/DCAppAttestService+FIRAppAttestService.m

@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/DCAppAttestService+FIRAppAttestService.h"
-
-@implementation DCAppAttestService (FIRAppAttestService)
-
-@end

+ 0 - 29
FirebaseAppCheck/Sources/AppAttestProvider/Errors/FIRAppAttestRejectionError.m

@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Errors/FIRAppAttestRejectionError.h"
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-@implementation FIRAppAttestRejectionError
-
-- (instancetype)init {
-  return [self initWithDomain:FIRAppCheckErrorDomain code:FIRAppCheckErrorCodeUnknown userInfo:nil];
-}
-
-@end

+ 31 - 468
FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProvider.m

@@ -16,507 +16,70 @@
 
 #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppAttestProvider.h"
 
-#import "FirebaseAppCheck/Sources/AppAttestProvider/DCAppAttestService+FIRAppAttestService.h"
+#import <AppCheckCore/AppCheckCore.h>
 
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAPIService.h"
-#import "FirebaseAppCheck/Sources/AppAttestProvider/API/FIRAppAttestAttestationResponse.h"
-#import "FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.h"
-#import "FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestService.h"
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.h"
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.h"
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h"
-#import "FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.h"
+#import "FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.h"
 #import "FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.h"
-
-#import "FirebaseAppCheck/Sources/Core/Utils/FIRAppCheckCryptoUtils.h"
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Errors/FIRAppAttestRejectionError.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h"
+#import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
+#import "FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.h"
 
 #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-/// A data object that contains all key attest data required for FAC token exchange.
-@interface FIRAppAttestKeyAttestationResult : NSObject
-
-@property(nonatomic, readonly) NSString *keyID;
-@property(nonatomic, readonly) NSData *challenge;
-@property(nonatomic, readonly) NSData *attestation;
-
-- (instancetype)initWithKeyID:(NSString *)keyID
-                    challenge:(NSData *)challenge
-                  attestation:(NSData *)attestation;
-
-@end
-
-@implementation FIRAppAttestKeyAttestationResult
-
-- (instancetype)initWithKeyID:(NSString *)keyID
-                    challenge:(NSData *)challenge
-                  attestation:(NSData *)attestation {
-  self = [super init];
-  if (self) {
-    _keyID = keyID;
-    _challenge = challenge;
-    _attestation = attestation;
-  }
-  return self;
-}
-
-@end
-
-/// A data object that contains information required for assertion request.
-@interface FIRAppAttestAssertionData : NSObject
-
-@property(nonatomic, readonly) NSData *challenge;
-@property(nonatomic, readonly) NSData *artifact;
-@property(nonatomic, readonly) NSData *assertion;
-
-- (instancetype)initWithChallenge:(NSData *)challenge
-                         artifact:(NSData *)artifact
-                        assertion:(NSData *)assertion;
-
-@end
-
-@implementation FIRAppAttestAssertionData
-
-- (instancetype)initWithChallenge:(NSData *)challenge
-                         artifact:(NSData *)artifact
-                        assertion:(NSData *)assertion {
-  self = [super init];
-  if (self) {
-    _challenge = challenge;
-    _artifact = artifact;
-    _assertion = assertion;
-  }
-  return self;
-}
-
-@end
-
 @interface FIRAppAttestProvider ()
 
-@property(nonatomic, readonly) id<FIRAppAttestAPIServiceProtocol> APIService;
-@property(nonatomic, readonly) id<FIRAppAttestService> appAttestService;
-@property(nonatomic, readonly) id<FIRAppAttestKeyIDStorageProtocol> keyIDStorage;
-@property(nonatomic, readonly) id<FIRAppAttestArtifactStorageProtocol> artifactStorage;
-@property(nonatomic, readonly) id<FIRAppCheckBackoffWrapperProtocol> backoffWrapper;
-
-@property(nonatomic, nullable) FBLPromise<FIRAppCheckToken *> *ongoingGetTokenOperation;
-
-@property(nonatomic, readonly) dispatch_queue_t queue;
+@property(nonatomic, readonly) GACAppAttestProvider *appAttestProvider;
 
 @end
 
 @implementation FIRAppAttestProvider
 
-- (instancetype)initWithAppAttestService:(id<FIRAppAttestService>)appAttestService
-                              APIService:(id<FIRAppAttestAPIServiceProtocol>)APIService
-                            keyIDStorage:(id<FIRAppAttestKeyIDStorageProtocol>)keyIDStorage
-                         artifactStorage:(id<FIRAppAttestArtifactStorageProtocol>)artifactStorage
-                          backoffWrapper:(id<FIRAppCheckBackoffWrapperProtocol>)backoffWrapper {
+- (instancetype)initWithAppAttestProvider:(GACAppAttestProvider *)appAttestProvider {
   self = [super init];
   if (self) {
-    _appAttestService = appAttestService;
-    _APIService = APIService;
-    _keyIDStorage = keyIDStorage;
-    _artifactStorage = artifactStorage;
-    _backoffWrapper = backoffWrapper;
-    _queue = dispatch_queue_create("com.firebase.FIRAppAttestProvider", DISPATCH_QUEUE_SERIAL);
+    _appAttestProvider = appAttestProvider;
   }
   return self;
 }
 
 - (nullable instancetype)initWithApp:(FIRApp *)app {
-  NSURLSession *URLSession = [NSURLSession
-      sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
-
-  FIRAppAttestKeyIDStorage *keyIDStorage =
-      [[FIRAppAttestKeyIDStorage alloc] initWithAppName:app.name appID:app.options.googleAppID];
-
-  FIRAppCheckAPIService *APIService =
-      [[FIRAppCheckAPIService alloc] initWithURLSession:URLSession
+  GACAppAttestProvider *appAttestProvider =
+      [[GACAppAttestProvider alloc] initWithServiceName:app.name
+                                           resourceName:app.resourceName
+                                                baseURL:nil
                                                  APIKey:app.options.APIKey
-                                                  appID:app.options.googleAppID
-                                        heartbeatLogger:app.heartbeatLogger];
-
-  FIRAppAttestAPIService *appAttestAPIService =
-      [[FIRAppAttestAPIService alloc] initWithAPIService:APIService
-                                               projectID:app.options.projectID
-                                                   appID:app.options.googleAppID];
-
-  FIRAppAttestArtifactStorage *artifactStorage =
-      [[FIRAppAttestArtifactStorage alloc] initWithAppName:app.name
-                                                     appID:app.options.googleAppID
-                                               accessGroup:app.options.appGroupID];
-
-  FIRAppCheckBackoffWrapper *backoffWrapper = [[FIRAppCheckBackoffWrapper alloc] init];
+                                    keychainAccessGroup:app.options.appGroupID
+                                           requestHooks:@[ [app.heartbeatLogger requestHook] ]];
 
-  return [self initWithAppAttestService:DCAppAttestService.sharedService
-                             APIService:appAttestAPIService
-                           keyIDStorage:keyIDStorage
-                        artifactStorage:artifactStorage
-                         backoffWrapper:backoffWrapper];
+  return [self initWithAppAttestProvider:appAttestProvider];
 }
 
 #pragma mark - FIRAppCheckProvider
 
 - (void)getTokenWithCompletion:(void (^)(FIRAppCheckToken *_Nullable, NSError *_Nullable))handler {
-  [self getToken]
-      // Call the handler with the result.
-      .then(^FBLPromise *(FIRAppCheckToken *token) {
-        handler(token, nil);
-        return nil;
-      })
-      .catch(^(NSError *error) {
-        handler(nil, error);
-      });
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)getToken {
-  return [FBLPromise onQueue:self.queue
-                          do:^id _Nullable {
-                            if (self.ongoingGetTokenOperation == nil) {
-                              // Kick off a new handshake sequence only when there is not an ongoing
-                              // handshake to avoid race conditions.
-                              self.ongoingGetTokenOperation =
-                                  [self createGetTokenSequenceWithBackoffPromise]
-
-                                      // Release the ongoing operation promise on completion.
-                                      .then(^FIRAppCheckToken *(FIRAppCheckToken *token) {
-                                        self.ongoingGetTokenOperation = nil;
-                                        return token;
-                                      })
-                                      .recover(^NSError *(NSError *error) {
-                                        self.ongoingGetTokenOperation = nil;
-                                        return error;
-                                      });
-                            }
-                            return self.ongoingGetTokenOperation;
-                          }];
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)createGetTokenSequenceWithBackoffPromise {
-  return [self.backoffWrapper
-      applyBackoffToOperation:^FBLPromise *_Nonnull {
-        return [self createGetTokenSequencePromise];
-      }
-                 errorHandler:[self.backoffWrapper defaultAppCheckProviderErrorHandler]];
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)createGetTokenSequencePromise {
-  // Check attestation state to decide on the next steps.
-  return [self attestationState].thenOn(self.queue, ^id(FIRAppAttestProviderState *attestState) {
-    switch (attestState.state) {
-      case FIRAppAttestAttestationStateUnsupported:
-        FIRAppCheckDebugLog(kFIRLoggerAppCheckMessageCodeAppAttestNotSupported,
-                            @"App Attest is not supported.");
-        return attestState.appAttestUnsupportedError;
-        break;
-
-      case FIRAppAttestAttestationStateSupportedInitial:
-      case FIRAppAttestAttestationStateKeyGenerated:
-        // Initial handshake is required for both the "initial" and the "key generated" states.
-        return [self initialHandshakeWithKeyID:attestState.appAttestKeyID];
-        break;
-
-      case FIRAppAttestAttestationStateKeyRegistered:
-        // Refresh FAC token using the existing registered App Attest key pair.
-        return [self refreshTokenWithKeyID:attestState.appAttestKeyID
-                                  artifact:attestState.attestationArtifact];
-        break;
+  [self.appAttestProvider getTokenWithCompletion:^(GACAppCheckToken *_Nullable internalToken,
+                                                   NSError *_Nullable error) {
+    if (error) {
+      handler(nil, error);
+      return;
     }
-  });
-}
-
-#pragma mark - Initial handshake sequence (attestation)
-
-- (FBLPromise<FIRAppCheckToken *> *)initialHandshakeWithKeyID:(nullable NSString *)keyID {
-  // 1. Attest the device. Retry once on 403 from Firebase backend (attestation rejection error).
-  __block NSString *keyIDForAttempt = keyID;
-  return [FBLPromise onQueue:self.queue
-             attempts:1
-             delay:0
-             condition:^BOOL(NSInteger attemptCount, NSError *_Nonnull error) {
-               // Reset keyID before retrying.
-               keyIDForAttempt = nil;
-               return [error isKindOfClass:[FIRAppAttestRejectionError class]];
-             }
-             retry:^FBLPromise<NSArray * /*[keyID, attestArtifact]*/> *_Nullable {
-               return [self attestKeyGenerateIfNeededWithID:keyIDForAttempt];
-             }]
-      .thenOn(self.queue, ^FBLPromise<FIRAppCheckToken *> *(NSArray *attestationResults) {
-        // 4. Save the artifact and return the received FAC token.
-
-        FIRAppAttestKeyAttestationResult *attestation = attestationResults.firstObject;
-        FIRAppAttestAttestationResponse *firebaseAttestationResponse =
-            attestationResults.lastObject;
-
-        return [self saveArtifactAndGetAppCheckTokenFromResponse:firebaseAttestationResponse
-                                                           keyID:attestation.keyID];
-      });
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)saveArtifactAndGetAppCheckTokenFromResponse:
-                                        (FIRAppAttestAttestationResponse *)response
-                                                                          keyID:(NSString *)keyID {
-  return [self.artifactStorage setArtifact:response.artifact forKey:keyID].thenOn(
-      self.queue, ^FIRAppCheckToken *(id result) {
-        return response.token;
-      });
-}
-
-- (FBLPromise<FIRAppAttestKeyAttestationResult *> *)attestKey:(NSString *)keyID
-                                                    challenge:(NSData *)challenge {
-  return [FBLPromise onQueue:self.queue
-                          do:^NSData *_Nullable {
-                            return [FIRAppCheckCryptoUtils sha256HashFromData:challenge];
-                          }]
-      .thenOn(self.queue,
-              ^FBLPromise<NSData *> *(NSData *challengeHash) {
-                return [FBLPromise onQueue:self.queue
-                           wrapObjectOrErrorCompletion:^(
-                               FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
-                             [self.appAttestService attestKey:keyID
-                                               clientDataHash:challengeHash
-                                            completionHandler:handler];
-                           }]
-                    .recoverOn(self.queue, ^id(NSError *error) {
-                      return [FIRAppCheckErrorUtil appAttestAttestKeyFailedWithError:error
-                                                                               keyId:keyID
-                                                                      clientDataHash:challengeHash];
-                    });
-              })
-      .thenOn(self.queue, ^FBLPromise<FIRAppAttestKeyAttestationResult *> *(NSData *attestation) {
-        FIRAppAttestKeyAttestationResult *result =
-            [[FIRAppAttestKeyAttestationResult alloc] initWithKeyID:keyID
-                                                          challenge:challenge
-                                                        attestation:attestation];
-        return [FBLPromise resolvedWith:result];
-      });
-}
-
-- (FBLPromise<NSArray * /*[keyID, attestArtifact]*/> *)attestKeyGenerateIfNeededWithID:
-    (nullable NSString *)keyID {
-  // 1. Request a random challenge and get App Attest key ID concurrently.
-  return [FBLPromise onQueue:self.queue
-                         all:@[
-                           // 1.1. Request random challenge.
-                           [self.APIService getRandomChallenge],
-                           // 1.2. Get App Attest key ID.
-                           [self generateAppAttestKeyIDIfNeeded:keyID]
-                         ]]
-      .thenOn(self.queue,
-              ^FBLPromise<FIRAppAttestKeyAttestationResult *> *(NSArray *challengeAndKeyID) {
-                // 2. Attest the key.
-                NSData *challenge = challengeAndKeyID.firstObject;
-                NSString *keyID = challengeAndKeyID.lastObject;
-
-                return [self attestKey:keyID challenge:challenge];
-              })
-      .recoverOn(self.queue,
-                 ^id(NSError *error) {
-                   // If Apple rejected the key (DCErrorInvalidKey) then reset the attestation and
-                   // throw a specific error to signal retry (FIRAppAttestRejectionError).
-                   NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey];
-                   if (underlyingError && [underlyingError.domain isEqualToString:DCErrorDomain] &&
-                       underlyingError.code == DCErrorInvalidKey) {
-                     FIRAppCheckDebugLog(
-                         kFIRLoggerAppCheckMessageCodeAttestationRejected,
-                         @"App Attest invalid key; the existing attestation will be reset.");
-
-                     // Reset the attestation.
-                     return [self resetAttestation].thenOn(self.queue, ^NSError *(id result) {
-                       // Throw the rejection error.
-                       return [[FIRAppAttestRejectionError alloc] init];
-                     });
-                   }
-
-                   // Otherwise just re-throw the error.
-                   return error;
-                 })
-      .thenOn(self.queue,
-              ^FBLPromise<NSArray *> *(FIRAppAttestKeyAttestationResult *result) {
-                // 3. Exchange the attestation to FAC token and pass the results to the next step.
-                NSArray *attestationResults = @[
-                  // 3.1. Just pass the attestation result to the next step.
-                  [FBLPromise resolvedWith:result],
-                  // 3.2. Exchange the attestation to FAC token.
-                  [self.APIService attestKeyWithAttestation:result.attestation
-                                                      keyID:result.keyID
-                                                  challenge:result.challenge]
-                ];
-
-                return [FBLPromise onQueue:self.queue all:attestationResults];
-              })
-      .recoverOn(self.queue, ^id(NSError *error) {
-        // If App Attest attestation was rejected then reset the attestation and throw a specific
-        // error.
-        FIRAppCheckHTTPError *HTTPError = (FIRAppCheckHTTPError *)error;
-        if ([HTTPError isKindOfClass:[FIRAppCheckHTTPError class]] &&
-            HTTPError.HTTPResponse.statusCode == 403) {
-          FIRAppCheckDebugLog(kFIRLoggerAppCheckMessageCodeAttestationRejected,
-                              @"App Attest attestation was rejected by backend. The existing "
-                              @"attestation will be reset.");
-          // Reset the attestation.
-          return [self resetAttestation].thenOn(self.queue, ^NSError *(id result) {
-            // Throw the rejection error.
-            return [[FIRAppAttestRejectionError alloc] init];
-          });
-        }
-
-        // Otherwise just re-throw the error.
-        return error;
-      });
-}
 
-/// Resets stored key ID and attestation artifact.
-- (FBLPromise<NSNull *> *)resetAttestation {
-  return [self.keyIDStorage setAppAttestKeyID:nil].thenOn(self.queue, ^id(id result) {
-    return [self.artifactStorage setArtifact:nil forKey:@""];
-  });
+    handler([[FIRAppCheckToken alloc] initWithInternalToken:internalToken], nil);
+  }];
 }
 
-#pragma mark - Token refresh sequence (assertion)
-
-- (FBLPromise<FIRAppCheckToken *> *)refreshTokenWithKeyID:(NSString *)keyID
-                                                 artifact:(NSData *)artifact {
-  return [self.APIService getRandomChallenge]
-      .thenOn(self.queue,
-              ^FBLPromise<FIRAppAttestAssertionData *> *(NSData *challenge) {
-                return [self generateAssertionWithKeyID:keyID
-                                               artifact:artifact
-                                              challenge:challenge];
-              })
-      .thenOn(self.queue, ^id(FIRAppAttestAssertionData *assertion) {
-        return [self.APIService getAppCheckTokenWithArtifact:assertion.artifact
-                                                   challenge:assertion.challenge
-                                                   assertion:assertion.assertion];
-      });
-}
-
-- (FBLPromise<FIRAppAttestAssertionData *> *)generateAssertionWithKeyID:(NSString *)keyID
-                                                               artifact:(NSData *)artifact
-                                                              challenge:(NSData *)challenge {
-  // 1. Calculate the statement and its hash for assertion.
-  return [FBLPromise
-             onQueue:self.queue
-                  do:^NSData *_Nullable {
-                    // 1.1. Compose statement to generate assertion for.
-                    NSMutableData *statementForAssertion = [artifact mutableCopy];
-                    [statementForAssertion appendData:challenge];
-
-                    // 1.2. Get the statement SHA256 hash.
-                    return [FIRAppCheckCryptoUtils sha256HashFromData:[statementForAssertion copy]];
-                  }]
-      .thenOn(self.queue,
-              ^FBLPromise<NSData *> *(NSData *statementHash) {
-                return [FBLPromise onQueue:self.queue
-                           wrapObjectOrErrorCompletion:^(
-                               FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
-                             [self.appAttestService generateAssertion:keyID
-                                                       clientDataHash:statementHash
-                                                    completionHandler:handler];
-                           }]
-                    .recoverOn(self.queue, ^id(NSError *error) {
-                      return [FIRAppCheckErrorUtil
-                          appAttestGenerateAssertionFailedWithError:error
-                                                              keyId:keyID
-                                                     clientDataHash:statementHash];
-                    });
-              })
-      // 3. Compose the result object.
-      .thenOn(self.queue, ^FIRAppAttestAssertionData *(NSData *assertion) {
-        return [[FIRAppAttestAssertionData alloc] initWithChallenge:challenge
-                                                           artifact:artifact
-                                                          assertion:assertion];
-      });
-}
-
-#pragma mark - State handling
-
-- (FBLPromise<FIRAppAttestProviderState *> *)attestationState {
-  dispatch_queue_t stateQueue =
-      dispatch_queue_create("FIRAppAttestProvider.state", DISPATCH_QUEUE_SERIAL);
-
-  return [FBLPromise
-      onQueue:stateQueue
-           do:^id _Nullable {
-             NSError *error;
-
-             // 1. Check if App Attest is supported.
-             id isSupportedResult = FBLPromiseAwait([self isAppAttestSupported], &error);
-             if (isSupportedResult == nil) {
-               return [[FIRAppAttestProviderState alloc] initUnsupportedWithError:error];
-             }
-
-             // 2. Check for stored key ID of the generated App Attest key pair.
-             NSString *appAttestKeyID =
-                 FBLPromiseAwait([self.keyIDStorage getAppAttestKeyID], &error);
-             if (appAttestKeyID == nil) {
-               return [[FIRAppAttestProviderState alloc] initWithSupportedInitialState];
-             }
-
-             // 3. Check for stored attestation artifact received from Firebase backend.
-             NSData *attestationArtifact =
-                 FBLPromiseAwait([self.artifactStorage getArtifactForKey:appAttestKeyID], &error);
-             if (attestationArtifact == nil) {
-               return [[FIRAppAttestProviderState alloc] initWithGeneratedKeyID:appAttestKeyID];
-             }
-
-             // 4. A valid App Attest key pair was generated and registered with Firebase
-             // backend. Return the corresponding state.
-             return [[FIRAppAttestProviderState alloc] initWithRegisteredKeyID:appAttestKeyID
-                                                                      artifact:attestationArtifact];
-           }];
-}
-
-#pragma mark - Helpers
-
-/// Returns a resolved promise if App Attest is supported and a rejected promise if it is not.
-- (FBLPromise<NSNull *> *)isAppAttestSupported {
-  if (self.appAttestService.isSupported) {
-    return [FBLPromise resolvedWith:[NSNull null]];
-  } else {
-    NSError *error = [FIRAppCheckErrorUtil unsupportedAttestationProvider:@"AppAttestProvider"];
-    FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-    [rejectedPromise reject:error];
-    return rejectedPromise;
-  }
-}
-
-/// Generates a new App Attest key associated with the Firebase app if `storedKeyID == nil`.
-- (FBLPromise<NSString *> *)generateAppAttestKeyIDIfNeeded:(nullable NSString *)storedKeyID {
-  if (storedKeyID) {
-    // The key ID has been fetched already, just return it.
-    return [FBLPromise resolvedWith:storedKeyID];
-  } else {
-    // Generate and save a new key otherwise.
-    return [self generateAppAttestKey];
-  }
-}
+- (void)getLimitedUseTokenWithCompletion:(void (^)(FIRAppCheckToken *_Nullable,
+                                                   NSError *_Nullable))handler {
+  [self.appAttestProvider getLimitedUseTokenWithCompletion:^(
+                              GACAppCheckToken *_Nullable internalToken, NSError *_Nullable error) {
+    if (error) {
+      handler(nil, error);
+      return;
+    }
 
-/// Generates and stores App Attest key associated with the Firebase app.
-- (FBLPromise<NSString *> *)generateAppAttestKey {
-  return [FBLPromise onQueue:self.queue
-             wrapObjectOrErrorCompletion:^(FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
-               [self.appAttestService generateKeyWithCompletionHandler:handler];
-             }]
-      .recoverOn(self.queue,
-                 ^id(NSError *error) {
-                   return [FIRAppCheckErrorUtil appAttestGenerateKeyFailedWithError:error];
-                 })
-      .thenOn(self.queue, ^FBLPromise<NSString *> *(NSString *keyID) {
-        return [self.keyIDStorage setAppAttestKeyID:keyID];
-      });
+    handler([[FIRAppCheckToken alloc] initWithInternalToken:internalToken], nil);
+  }];
 }
 
 @end

+ 0 - 73
FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.h

@@ -1,73 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// Represents different stages of App Attest attestation.
-typedef NS_ENUM(NSInteger, FIRAppAttestAttestationState) {
-  /// App Attest is not supported on the current device.
-  FIRAppAttestAttestationStateUnsupported,
-
-  /// App Attest is supported, the App Attest key pair has been generated.
-  FIRAppAttestAttestationStateSupportedInitial,
-
-  /// App Attest key pair has been generated but has not been attested and registered with Firebase
-  /// backend.
-  FIRAppAttestAttestationStateKeyGenerated,
-
-  /// App Attest key has been generated, attested with Apple backend and registered with Firebase
-  /// backend. An encrypted artifact required to refresh FAC token is stored on the device.
-  FIRAppAttestAttestationStateKeyRegistered,
-};
-
-/// Represents attestation stages of App Attest. The class is designed to be used exclusively by
-/// `FIRAppAttestProvider`.
-@interface FIRAppAttestProviderState : NSObject
-
-/// App Attest attestation state.
-@property(nonatomic, readonly) FIRAppAttestAttestationState state;
-
-/// An error object when state is FIRAppAttestAttestationStateUnsupported.
-@property(nonatomic, nullable, readonly) NSError *appAttestUnsupportedError;
-
-/// An App Attest key ID when state is FIRAppAttestAttestationStateKeyGenerated or
-/// FIRAppAttestAttestationStateKeyRegistered.
-@property(nonatomic, nullable, readonly) NSString *appAttestKeyID;
-
-/// An attestation artifact received from Firebase backend when state is
-/// FIRAppAttestAttestationStateKeyRegistered.
-@property(nonatomic, nullable, readonly) NSData *attestationArtifact;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/// Init with FIRAppAttestAttestationStateUnsupported and an error describing issue.
-- (instancetype)initUnsupportedWithError:(NSError *)error;
-
-/// Init with FIRAppAttestAttestationStateSupportedInitial.
-- (instancetype)initWithSupportedInitialState;
-
-/// Init with FIRAppAttestAttestationStateKeyGenerated and the key ID.
-- (instancetype)initWithGeneratedKeyID:(NSString *)keyID;
-
-/// Init with FIRAppAttestAttestationStateKeyRegistered, the key ID and the attestation artifact
-/// received from Firebase backend.
-- (instancetype)initWithRegisteredKeyID:(NSString *)keyID artifact:(NSData *)artifact;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 57
FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.m

@@ -1,57 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestProviderState.h"
-
-@implementation FIRAppAttestProviderState
-
-- (instancetype)initUnsupportedWithError:(NSError *)error {
-  self = [super init];
-  if (self) {
-    _state = FIRAppAttestAttestationStateUnsupported;
-    _appAttestUnsupportedError = error;
-  }
-  return self;
-}
-
-- (instancetype)initWithSupportedInitialState {
-  self = [super init];
-  if (self) {
-    _state = FIRAppAttestAttestationStateSupportedInitial;
-  }
-  return self;
-}
-
-- (instancetype)initWithGeneratedKeyID:(NSString *)keyID {
-  self = [super init];
-  if (self) {
-    _state = FIRAppAttestAttestationStateKeyGenerated;
-    _appAttestKeyID = keyID;
-  }
-  return self;
-}
-
-- (instancetype)initWithRegisteredKeyID:(NSString *)keyID artifact:(NSData *)artifact {
-  self = [super init];
-  if (self) {
-    _state = FIRAppAttestAttestationStateKeyRegistered;
-    _appAttestKeyID = keyID;
-    _attestationArtifact = artifact;
-  }
-  return self;
-}
-
-@end

+ 0 - 42
FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestService.h

@@ -1,42 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<ValueType>;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// See `DCAppAttestService`
-/// https://developer.apple.com/documentation/devicecheck/dcappattestservice?language=objc
-@protocol FIRAppAttestService <NSObject>
-
-@property(getter=isSupported, readonly) BOOL supported;
-
-- (void)generateKeyWithCompletionHandler:(void (^)(NSString *keyId,
-                                                   NSError *error))completionHandler;
-
-- (void)attestKey:(NSString *)keyId
-       clientDataHash:(NSData *)clientDataHash
-    completionHandler:(void (^)(NSData *attestationObject, NSError *error))completionHandler;
-
-- (void)generateAssertion:(NSString *)keyId
-           clientDataHash:(NSData *)clientDataHash
-        completionHandler:(void (^)(NSData *assertionObject, NSError *error))completionHandler;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 74
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.h

@@ -1,74 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<ValueType>;
-@class GULKeychainStorage;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// Defines API of a storage capable to store an encrypted artifact required to refresh Firebase App
-/// Check token obtained with App Attest provider.
-@protocol FIRAppAttestArtifactStorageProtocol <NSObject>
-
-/// Set the artifact. An artifact previously set for *any* key ID will be replaced by the new one
-/// with the new key ID. The storage always stores a single artifact.
-/// @param artifact The artifact data to store. Pass `nil` to remove the stored artifact.
-/// @param keyID The App Attest key ID used to generate the artifact.
-/// @return An artifact that is resolved with the artifact data passed into the method in case of
-/// success or is rejected with an error.
-- (FBLPromise<NSData *> *)setArtifact:(nullable NSData *)artifact forKey:(NSString *)keyID;
-
-/// Get the artifact.
-/// @param keyID The App Attest key ID used to generate the artifact.
-/// @return A promise that is resolved with the artifact data if artifact exists, is resolved with
-/// `nil` if no artifact found (or the existing artifact was set for a different key ID)  or is
-/// rejected with an error.
-- (FBLPromise<NSData *> *)getArtifactForKey:(NSString *)keyID;
-
-@end
-
-/// An implementation of FIRAppAttestArtifactStorageProtocol.
-@interface FIRAppAttestArtifactStorage : NSObject <FIRAppAttestArtifactStorageProtocol>
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/// Default convenience initializer.
-/// @param appName A Firebase App name (`FirebaseApp.name`). The app name will be used as a part of
-/// the key to store the token for the storage instance.
-/// @param appID A Firebase App identifier (`FirebaseOptions.googleAppID`). The app ID will be used
-/// as a part of the key to store the token for the storage instance.
-/// @param accessGroup The Keychain Access Group.
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                    accessGroup:(nullable NSString *)accessGroup;
-
-/// Designated initializer.
-/// @param appName A Firebase App name (`FirebaseApp.name`). The app name will be used as a part of
-/// the key to store the token for the storage instance.
-/// @param appID A Firebase App identifier (`FirebaseOptions.googleAppID`). The app ID will be used
-/// as a part of the key to store the token for the storage instance.
-/// @param keychainStorage An instance of `GULKeychainStorage` used as an underlying secure storage.
-/// @param accessGroup The Keychain Access Group.
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                keychainStorage:(GULKeychainStorage *)keychainStorage
-                    accessGroup:(nullable NSString *)accessGroup NS_DESIGNATED_INITIALIZER;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 125
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.m

@@ -1,125 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestArtifactStorage.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import <GoogleUtilities/GULKeychainStorage.h>
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-static NSString *const kKeychainService = @"com.firebase.app_check.app_attest_artifact_storage";
-
-@interface FIRAppAttestArtifactStorage ()
-
-@property(nonatomic, readonly) NSString *appName;
-@property(nonatomic, readonly) NSString *appID;
-@property(nonatomic, readonly) GULKeychainStorage *keychainStorage;
-@property(nonatomic, readonly, nullable) NSString *accessGroup;
-
-@end
-
-@implementation FIRAppAttestArtifactStorage
-
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                keychainStorage:(GULKeychainStorage *)keychainStorage
-                    accessGroup:(nullable NSString *)accessGroup {
-  self = [super init];
-  if (self) {
-    _appName = [appName copy];
-    _appID = [appID copy];
-    _keychainStorage = keychainStorage;
-    _accessGroup = [accessGroup copy];
-  }
-  return self;
-}
-
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                    accessGroup:(nullable NSString *)accessGroup {
-  GULKeychainStorage *keychainStorage =
-      [[GULKeychainStorage alloc] initWithService:kKeychainService];
-  return [self initWithAppName:appName
-                         appID:appID
-               keychainStorage:keychainStorage
-                   accessGroup:accessGroup];
-}
-
-- (FBLPromise<NSData *> *)getArtifactForKey:(NSString *)keyID {
-  return [self.keychainStorage getObjectForKey:[self artifactKey]
-                                   objectClass:[FIRAppAttestStoredArtifact class]
-                                   accessGroup:self.accessGroup]
-      .then(^NSData *(id<NSSecureCoding> storedArtifact) {
-        FIRAppAttestStoredArtifact *artifact = (FIRAppAttestStoredArtifact *)storedArtifact;
-        if ([artifact isKindOfClass:[FIRAppAttestStoredArtifact class]] &&
-            [artifact.keyID isEqualToString:keyID]) {
-          return artifact.artifact;
-        } else {
-          return nil;
-        }
-      })
-      .recover(^NSError *(NSError *error) {
-        return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-      });
-}
-
-- (FBLPromise<NSData *> *)setArtifact:(nullable NSData *)artifact forKey:(nonnull NSString *)keyID {
-  if (artifact) {
-    return [self storeArtifact:artifact forKey:keyID].recover(^NSError *(NSError *error) {
-      return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-    });
-  } else {
-    return [self.keychainStorage removeObjectForKey:[self artifactKey] accessGroup:self.accessGroup]
-        .then(^id _Nullable(NSNull *_Nullable value) {
-          return nil;
-        })
-        .recover(^NSError *(NSError *error) {
-          return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-        });
-  }
-}
-
-#pragma mark - Helpers
-
-- (FBLPromise<NSData *> *)storeArtifact:(nullable NSData *)artifact
-                                 forKey:(nonnull NSString *)keyID {
-  FIRAppAttestStoredArtifact *storedArtifact =
-      [[FIRAppAttestStoredArtifact alloc] initWithKeyID:keyID artifact:artifact];
-  return [self.keychainStorage setObject:storedArtifact
-                                  forKey:[self artifactKey]
-                             accessGroup:self.accessGroup]
-      .then(^id _Nullable(NSNull *_Nullable value) {
-        return artifact;
-      });
-}
-
-- (NSString *)artifactKey {
-  return
-      [NSString stringWithFormat:@"app_check_app_attest_artifact.%@.%@", self.appName, self.appID];
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 60
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.h

@@ -1,60 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<ValueType>;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// The protocol defines methods to store App Attest key IDs per Firebase app.
-@protocol FIRAppAttestKeyIDStorageProtocol <NSObject>
-
-/** Manages storage of an app attest key ID.
- *  @param keyID The app attest key ID to store or `nil` to remove the existing app attest key ID.
- *  @return A promise that is resolved with a stored app attest key ID or `nil` if the existing app
- * attest key ID has been removed.
- */
-- (FBLPromise<NSString *> *)setAppAttestKeyID:(nullable NSString *)keyID;
-
-/** Reads a stored app attest key ID.
- *  @return A promise that is resolved with a stored app attest key ID or `nil` if there is not a
- * stored app attest key ID. The promise is rejected with an error in the case of a missing app
- * attest key ID .
- */
-- (FBLPromise<NSString *> *)getAppAttestKeyID;
-
-@end
-
-/// The App Attest key ID storage implementation.
-/// This class is designed for use by `FIRAppAttestProvider`. It's operations are managed by
-/// `FIRAppAttestProvider`'s internal serial queue. It is not considered thread safe and should not
-/// be used by other classes at this time.
-@interface FIRAppAttestKeyIDStorage : NSObject <FIRAppAttestKeyIDStorageProtocol>
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/** Default convenience initializer.
- *  @param appName A Firebase App name (`FirebaseApp.name`). The app name will be used as a part of
- * the key to store the token for the storage instance.
- *  @param appID A Firebase App identifier (`FirebaseOptions.googleAppID`). The app ID will be used
- * as a part of the key to store the token for the storage instance.
- */
-- (instancetype)initWithAppName:(NSString *)appName appID:(NSString *)appID;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 93
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.m

@@ -1,93 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestKeyIDStorage.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-/// The `NSUserDefaults` suite name for the storage location of the app attest key ID.
-static NSString *const kKeyIDStorageDefaultsSuiteName = @"com.firebase.FIRAppAttestKeyIDStorage";
-
-@interface FIRAppAttestKeyIDStorage ()
-
-@property(nonatomic, readonly) NSString *appName;
-@property(nonatomic, readonly) NSString *appID;
-
-/// The app attest key ID is stored using `NSUserDefaults` .
-@property(nonatomic, readonly) NSUserDefaults *userDefaults;
-
-@end
-
-@implementation FIRAppAttestKeyIDStorage
-
-- (instancetype)initWithAppName:(NSString *)appName appID:(NSString *)appID {
-  self = [super init];
-  if (self) {
-    _appName = [appName copy];
-    _appID = [appID copy];
-    _userDefaults = [[NSUserDefaults alloc] initWithSuiteName:kKeyIDStorageDefaultsSuiteName];
-  }
-  return self;
-}
-
-- (nonnull FBLPromise<NSString *> *)setAppAttestKeyID:(nullable NSString *)keyID {
-  [self storeAppAttestKeyID:keyID];
-  return [FBLPromise resolvedWith:keyID];
-}
-
-- (nonnull FBLPromise<NSString *> *)getAppAttestKeyID {
-  NSString *appAttestKeyID = [self appAttestKeyIDFromStorage];
-  if (appAttestKeyID) {
-    return [FBLPromise resolvedWith:appAttestKeyID];
-  } else {
-    NSError *error = [FIRAppCheckErrorUtil appAttestKeyIDNotFound];
-    FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-    [rejectedPromise reject:error];
-    return rejectedPromise;
-  }
-}
-
-#pragma mark - Helpers
-
-- (void)storeAppAttestKeyID:(nullable NSString *)keyID {
-  if (keyID) {
-    [self.userDefaults setObject:keyID forKey:[self keyIDStorageKey]];
-  } else {
-    [self.userDefaults removeObjectForKey:[self keyIDStorageKey]];
-  }
-}
-
-- (nullable NSString *)appAttestKeyIDFromStorage {
-  NSString *appAttestKeyID = nil;
-  appAttestKeyID = [self.userDefaults objectForKey:[self keyIDStorageKey]];
-  return appAttestKeyID;
-}
-
-- (NSString *)keyIDStorageKey {
-  return [[self class] keyIDStorageKeyForAppName:self.appName appID:self.appID];
-}
-
-+ (NSString *)keyIDStorageKeyForAppName:(NSString *)appName appID:(NSString *)appID {
-  return [NSString stringWithFormat:@"app_attest_keyID.%@.%@", appName, appID];
-}
-
-@end

+ 0 - 41
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.h

@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppAttestStoredArtifact : NSObject <NSSecureCoding>
-
-/// The App Attest key ID used to generate the artifact.
-@property(nonatomic, readonly) NSString *keyID;
-
-/// The Firebase App Attest artifact generated by the backend.
-@property(nonatomic, readonly) NSData *artifact;
-
-/// The object version.
-/// WARNING: The version must be incremented if properties are added, removed or modified. Migration
-/// must be handled accordingly in `initWithCoder:` method.
-@property(nonatomic, readonly) NSInteger storageVersion;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-- (instancetype)initWithKeyID:(NSString *)keyID
-                     artifact:(NSData *)artifact NS_DESIGNATED_INITIALIZER;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 74
FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.m

@@ -1,74 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/Storage/FIRAppAttestStoredArtifact.h"
-
-static NSString *const kKeyIDKey = @"keyID";
-static NSString *const kArtifactKey = @"artifact";
-static NSString *const kStorageVersionKey = @"storageVersion";
-
-static NSInteger const kStorageVersion = 1;
-
-@implementation FIRAppAttestStoredArtifact
-
-- (instancetype)initWithKeyID:(NSString *)keyID artifact:(NSData *)artifact {
-  self = [super init];
-  if (self) {
-    _keyID = keyID;
-    _artifact = artifact;
-  }
-  return self;
-}
-
-- (NSInteger)storageVersion {
-  return kStorageVersion;
-}
-
-#pragma mark - NSSecureCoding
-
-+ (BOOL)supportsSecureCoding {
-  return YES;
-}
-
-- (void)encodeWithCoder:(nonnull NSCoder *)coder {
-  [coder encodeObject:self.keyID forKey:kKeyIDKey];
-  [coder encodeObject:self.artifact forKey:kArtifactKey];
-  [coder encodeInteger:self.storageVersion forKey:kStorageVersionKey];
-}
-
-- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
-  NSInteger storageVersion = [coder decodeIntegerForKey:kStorageVersionKey];
-
-  if (storageVersion < kStorageVersion) {
-    // Handle migration here when new versions are added
-  }
-
-  // If the version of the stored object is equal or higher than the current version then try the
-  // best to get enough data to initialize the object.
-  NSString *keyID = [coder decodeObjectOfClass:[NSString class] forKey:kKeyIDKey];
-  if (keyID.length < 1) {
-    return nil;
-  }
-
-  NSData *artifact = [coder decodeObjectOfClass:[NSData class] forKey:kArtifactKey];
-  if (artifact.length < 1) {
-    return nil;
-  }
-
-  return [self initWithKeyID:keyID artifact:artifact];
-}
-
-@end

+ 0 - 58
FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h

@@ -1,58 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<Result>;
-@class GULURLSessionDataResponse;
-@class FIRAppCheckToken;
-
-@protocol FIRHeartbeatLoggerProtocol;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol FIRAppCheckAPIServiceProtocol <NSObject>
-
-@property(nonatomic, readonly) NSString *baseURL;
-
-- (FBLPromise<GULURLSessionDataResponse *> *)
-    sendRequestWithURL:(NSURL *)requestURL
-            HTTPMethod:(NSString *)HTTPMethod
-                  body:(nullable NSData *)body
-     additionalHeaders:(nullable NSDictionary<NSString *, NSString *> *)additionalHeaders;
-
-- (FBLPromise<FIRAppCheckToken *> *)appCheckTokenWithAPIResponse:
-    (GULURLSessionDataResponse *)response;
-
-@end
-
-@interface FIRAppCheckAPIService : NSObject <FIRAppCheckAPIServiceProtocol>
-
-/**
- * The default initializer.
- * @param session The URL session used to make network requests.
- * @param APIKey The Firebase project API key (see `FIROptions.APIKey`).
- * @param appID The Firebase app ID (see `FIROptions.googleAppID`).
- * @param heartbeatLogger The heartbeat logger used to populate heartbeat data in request headers.
- */
-- (instancetype)initWithURLSession:(NSURLSession *)session
-                            APIKey:(NSString *)APIKey
-                             appID:(NSString *)appID
-                   heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 177
FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.m

@@ -1,177 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckAPIService.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-#import "FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.h"
-
-#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
-
-#import <GoogleUtilities/GULURLSessionDataResponse.h>
-#import <GoogleUtilities/NSURLSession+GULPromises.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-static NSString *const kAPIKeyHeaderKey = @"X-Goog-Api-Key";
-static NSString *const kHeartbeatKey = @"X-firebase-client";
-static NSString *const kBundleIdKey = @"X-Ios-Bundle-Identifier";
-
-static NSString *const kDefaultBaseURL = @"https://firebaseappcheck.googleapis.com/v1";
-
-@interface FIRAppCheckAPIService ()
-
-@property(nonatomic, readonly) NSURLSession *URLSession;
-@property(nonatomic, readonly) NSString *APIKey;
-@property(nonatomic, readonly) NSString *appID;
-@property(nonatomic, readonly) id<FIRHeartbeatLoggerProtocol> heartbeatLogger;
-
-@end
-
-@implementation FIRAppCheckAPIService
-
-// Synthesize properties declared in a protocol.
-@synthesize baseURL = _baseURL;
-
-- (instancetype)initWithURLSession:(NSURLSession *)session
-                            APIKey:(NSString *)APIKey
-                             appID:(NSString *)appID
-                   heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger {
-  return [self initWithURLSession:session
-                           APIKey:APIKey
-                            appID:appID
-                  heartbeatLogger:heartbeatLogger
-                          baseURL:kDefaultBaseURL];
-}
-
-- (instancetype)initWithURLSession:(NSURLSession *)session
-                            APIKey:(NSString *)APIKey
-                             appID:(NSString *)appID
-                   heartbeatLogger:(id<FIRHeartbeatLoggerProtocol>)heartbeatLogger
-                           baseURL:(NSString *)baseURL {
-  self = [super init];
-  if (self) {
-    _URLSession = session;
-    _APIKey = APIKey;
-    _appID = appID;
-    _heartbeatLogger = heartbeatLogger;
-    _baseURL = baseURL;
-  }
-  return self;
-}
-
-- (FBLPromise<GULURLSessionDataResponse *> *)
-    sendRequestWithURL:(NSURL *)requestURL
-            HTTPMethod:(NSString *)HTTPMethod
-                  body:(nullable NSData *)body
-     additionalHeaders:(nullable NSDictionary<NSString *, NSString *> *)additionalHeaders {
-  return [self requestWithURL:requestURL
-                    HTTPMethod:HTTPMethod
-                          body:body
-             additionalHeaders:additionalHeaders]
-      .then(^id _Nullable(NSURLRequest *_Nullable request) {
-        return [self sendURLRequest:request];
-      })
-      .then(^id _Nullable(GULURLSessionDataResponse *_Nullable response) {
-        return [self validateHTTPResponseStatusCode:response];
-      });
-}
-
-- (FBLPromise<NSURLRequest *> *)requestWithURL:(NSURL *)requestURL
-                                    HTTPMethod:(NSString *)HTTPMethod
-                                          body:(NSData *)body
-                             additionalHeaders:(nullable NSDictionary<NSString *, NSString *> *)
-                                                   additionalHeaders {
-  return [FBLPromise
-      onQueue:[self defaultQueue]
-           do:^id _Nullable {
-             __block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
-             request.HTTPMethod = HTTPMethod;
-             request.HTTPBody = body;
-
-             [request setValue:self.APIKey forHTTPHeaderField:kAPIKeyHeaderKey];
-
-             [request setValue:FIRHeaderValueFromHeartbeatsPayload(
-                                   [self.heartbeatLogger flushHeartbeatsIntoPayload])
-                 forHTTPHeaderField:kHeartbeatKey];
-
-             [request setValue:[[NSBundle mainBundle] bundleIdentifier]
-                 forHTTPHeaderField:kBundleIdKey];
-
-             [additionalHeaders
-                 enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, NSString *_Nonnull obj,
-                                                     BOOL *_Nonnull stop) {
-                   [request setValue:obj forHTTPHeaderField:key];
-                 }];
-
-             return [request copy];
-           }];
-}
-
-- (FBLPromise<GULURLSessionDataResponse *> *)sendURLRequest:(NSURLRequest *)request {
-  return [self.URLSession gul_dataTaskPromiseWithRequest:request]
-      .recover(^id(NSError *networkError) {
-        // Wrap raw network error into App Check domain error.
-        return [FIRAppCheckErrorUtil APIErrorWithNetworkError:networkError];
-      })
-      .then(^id _Nullable(GULURLSessionDataResponse *response) {
-        return [self validateHTTPResponseStatusCode:response];
-      });
-}
-
-- (FBLPromise<GULURLSessionDataResponse *> *)validateHTTPResponseStatusCode:
-    (GULURLSessionDataResponse *)response {
-  NSInteger statusCode = response.HTTPResponse.statusCode;
-  return [FBLPromise do:^id _Nullable {
-    if (statusCode < 200 || statusCode >= 300) {
-      FIRAppCheckDebugLog(kFIRLoggerAppCheckMessageCodeUnexpectedHTTPCode,
-                          @"Unexpected API response: %@, body: %@.", response.HTTPResponse,
-                          [[NSString alloc] initWithData:response.HTTPBody
-                                                encoding:NSUTF8StringEncoding]);
-      return [FIRAppCheckErrorUtil APIErrorWithHTTPResponse:response.HTTPResponse
-                                                       data:response.HTTPBody];
-    }
-    return response;
-  }];
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)appCheckTokenWithAPIResponse:
-    (GULURLSessionDataResponse *)response {
-  return [FBLPromise onQueue:[self defaultQueue]
-                          do:^id _Nullable {
-                            NSError *error;
-
-                            FIRAppCheckToken *token = [[FIRAppCheckToken alloc]
-                                initWithTokenExchangeResponse:response.HTTPBody
-                                                  requestDate:[NSDate date]
-                                                        error:&error];
-                            return token ?: error;
-                          }];
-}
-
-- (dispatch_queue_t)defaultQueue {
-  return dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 36
FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.h

@@ -1,36 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckToken.h"
-
-@class FBLPromise<Result>;
-@class GULURLSessionDataResponse;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppCheckToken (APIResponse)
-
-- (nullable instancetype)initWithTokenExchangeResponse:(NSData *)response
-                                           requestDate:(NSDate *)requestDate
-                                                 error:(NSError **)outError;
-
-- (nullable instancetype)initWithResponseDict:(NSDictionary<NSString *, id> *)responseDict
-                                  requestDate:(NSDate *)requestDate
-                                        error:(NSError **)outError;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 93
FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.m

@@ -1,93 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/APIService/FIRAppCheckToken+APIResponse.h"
-#import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-
-#import <GoogleUtilities/GULURLSessionDataResponse.h>
-
-static NSString *const kResponseFieldToken = @"token";
-static NSString *const kResponseFieldTTL = @"ttl";
-
-@implementation FIRAppCheckToken (APIResponse)
-
-- (nullable instancetype)initWithTokenExchangeResponse:(NSData *)response
-                                           requestDate:(NSDate *)requestDate
-                                                 error:(NSError **)outError {
-  if (response.length <= 0) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil errorWithFailureReason:@"Empty server response body."], outError);
-    return nil;
-  }
-
-  NSError *JSONError;
-  NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:response
-                                                               options:0
-                                                                 error:&JSONError];
-
-  if (![responseDict isKindOfClass:[NSDictionary class]]) {
-    FIRAppCheckSetErrorToPointer([FIRAppCheckErrorUtil JSONSerializationError:JSONError], outError);
-    return nil;
-  }
-
-  return [self initWithResponseDict:responseDict requestDate:requestDate error:outError];
-}
-
-- (nullable instancetype)initWithResponseDict:(NSDictionary<NSString *, id> *)responseDict
-                                  requestDate:(NSDate *)requestDate
-                                        error:(NSError **)outError {
-  NSString *token = responseDict[kResponseFieldToken];
-  if (![token isKindOfClass:[NSString class]]) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil appCheckTokenResponseErrorWithMissingField:kResponseFieldToken],
-        outError);
-    return nil;
-  }
-
-  NSString *timeToLiveString = responseDict[kResponseFieldTTL];
-  if (![token isKindOfClass:[NSString class]] || token.length <= 0) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil appCheckTokenResponseErrorWithMissingField:kResponseFieldTTL],
-        outError);
-    return nil;
-  }
-
-  // Expect a string like "3600s" representing a time interval in seconds.
-  NSString *timeToLiveValueString = [timeToLiveString stringByReplacingOccurrencesOfString:@"s"
-                                                                                withString:@""];
-  NSTimeInterval secondsToLive = timeToLiveValueString.doubleValue;
-
-  if (secondsToLive == 0) {
-    FIRAppCheckSetErrorToPointer(
-        [FIRAppCheckErrorUtil appCheckTokenResponseErrorWithMissingField:kResponseFieldTTL],
-        outError);
-    return nil;
-  }
-
-  NSDate *expirationDate = [requestDate dateByAddingTimeInterval:secondsToLive];
-
-  return [self initWithToken:token expirationDate:expirationDate receivedAtDate:requestDate];
-}
-
-@end

+ 0 - 87
FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.h

@@ -1,87 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FBLPromise<ValueType>;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// Backoff type. Backoff interval calculation depends on the type.
-typedef NS_ENUM(NSUInteger, FIRAppCheckBackoffType) {
-  /// No backoff. Another retry is allowed straight away.
-  FIRAppCheckBackoffTypeNone,
-
-  /// Next retry will be allowed in 1 day (24 hours) after the failure.
-  FIRAppCheckBackoffType1Day,
-
-  /// A small backoff interval that exponentially increases after each consequent failure.
-  FIRAppCheckBackoffTypeExponential
-};
-
-/// Creates a promise for an operation to apply the backoff to.
-typedef FBLPromise *_Nonnull (^FIRAppCheckBackoffOperationProvider)(void);
-
-/// Converts an error to a backoff type.
-typedef FIRAppCheckBackoffType (^FIRAppCheckBackoffErrorHandler)(NSError *error);
-
-/// A block returning a date. Is used instead of `+[NSDate date]` for better testability of logic
-/// dependent on the current time.
-typedef NSDate *_Nonnull (^FIRAppCheckDateProvider)(void);
-
-/// Defines API for an object that conditionally applies backoff to a given operation based on the
-/// history of previous operation failures.
-@protocol FIRAppCheckBackoffWrapperProtocol <NSObject>
-
-/// Conditionally applies backoff to the given operation.
-/// @param operationProvider A block that returns a new promise. The block will be called only when
-/// the operation is allowed.
-///        NOTE: We cannot accept just a promise because the operation will be started once the
-///        promise has been instantiated, so we need to have a way to instantiate the promise only
-///        when the operation is good to go. The provider block is the way we use.
-/// @param errorHandler A block that receives an operation error as an input and returns the
-/// appropriate backoff type. `defaultErrorHandler` provides a default implementation for Firebase
-/// services.
-/// @return A promise that is either:
-///   - a promise returned by the promise provider if no backoff is required
-///   - rejected if the backoff is needed
-- (FBLPromise *)applyBackoffToOperation:(FIRAppCheckBackoffOperationProvider)operationProvider
-                           errorHandler:(FIRAppCheckBackoffErrorHandler)errorHandler;
-
-/// The default Firebase services error handler. It keeps track of network errors and
-/// `FIRAppCheckHTTPError.HTTPResponse.statusCode.statusCode` value to return the appropriate
-/// backoff type for the standard Firebase App Check backend response codes.
-- (FIRAppCheckBackoffErrorHandler)defaultAppCheckProviderErrorHandler;
-
-@end
-
-/// Provides a backoff implementation. Keeps track of the operation successes and failures to either
-/// create and perform the operation promise or fails with a backoff error when the backoff is
-/// needed.
-@interface FIRAppCheckBackoffWrapper : NSObject <FIRAppCheckBackoffWrapperProtocol>
-
-/// Initializes the wrapper with `+[FIRAppCheckBackoffWrapper currentDateProvider]`.
-- (instancetype)init;
-
-- (instancetype)initWithDateProvider:(FIRAppCheckDateProvider)dateProvider
-    NS_DESIGNATED_INITIALIZER;
-
-/// A date provider that returns `+[NSDate date]`.
-+ (FIRAppCheckDateProvider)currentDateProvider;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 287
FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.m

@@ -1,287 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/Backoff/FIRAppCheckBackoffWrapper.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-static NSTimeInterval const k24Hours = 24 * 60 * 60;
-
-/// Jitter coefficient 0.5 means that the backoff interval can be up to 50% longer.
-static double const kMaxJitterCoefficient = 0.5;
-
-/// Maximum exponential backoff interval.
-static double const kMaxExponentialBackoffInterval = 4 * 60 * 60;  // 4 hours.
-
-/// A class representing an operation result with data required for the backoff calculation.
-@interface FIRAppCheckBackoffOperationFailure : NSObject
-
-/// The operation finish date.
-@property(nonatomic, readonly) NSDate *finishDate;
-
-/// The operation error.
-@property(nonatomic, readonly) NSError *error;
-
-/// A backoff type calculated based on the error.
-@property(nonatomic, readonly) FIRAppCheckBackoffType backoffType;
-
-/// Number of retries. Is 0 for the first attempt and incremented with each error. Is reset back to
-/// 0 on success.
-@property(nonatomic, readonly) NSInteger retryCount;
-
-/// Designated initializer.
-- (instancetype)initWithFinishDate:(NSDate *)finishDate
-                             error:(NSError *)error
-                       backoffType:(FIRAppCheckBackoffType)backoffType
-                        retryCount:(NSInteger)retryCount NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/// Creates a new result with incremented retryCount and specified error and backoff type.
-+ (instancetype)nextRetryFailureWithFailure:
-                    (nullable FIRAppCheckBackoffOperationFailure *)previousFailure
-                                 finishDate:(NSDate *)finishDate
-                                      error:(NSError *)error
-                                backoffType:(FIRAppCheckBackoffType)backoffType;
-
-@end
-
-@implementation FIRAppCheckBackoffOperationFailure
-
-- (instancetype)initWithFinishDate:(NSDate *)finishDate
-                             error:(NSError *)error
-                       backoffType:(FIRAppCheckBackoffType)backoffType
-                        retryCount:(NSInteger)retryCount {
-  self = [super init];
-  if (self) {
-    _finishDate = finishDate;
-    _error = error;
-    _retryCount = retryCount;
-    _backoffType = backoffType;
-  }
-  return self;
-}
-
-+ (instancetype)nextRetryFailureWithFailure:
-                    (nullable FIRAppCheckBackoffOperationFailure *)previousFailure
-                                 finishDate:(NSDate *)finishDate
-                                      error:(NSError *)error
-                                backoffType:(FIRAppCheckBackoffType)backoffType {
-  NSInteger newRetryCount = previousFailure ? previousFailure.retryCount + 1 : 0;
-
-  return [[self alloc] initWithFinishDate:finishDate
-                                    error:error
-                              backoffType:backoffType
-                               retryCount:newRetryCount];
-}
-
-@end
-
-@interface FIRAppCheckBackoffWrapper ()
-
-/// Current date provider. Is used instead of `+[NSDate date]` for testability.
-@property(nonatomic, readonly) FIRAppCheckDateProvider dateProvider;
-
-/// Last operation result.
-@property(nonatomic, nullable) FIRAppCheckBackoffOperationFailure *lastFailure;
-
-@end
-
-@implementation FIRAppCheckBackoffWrapper
-
-- (instancetype)init {
-  return [self initWithDateProvider:[FIRAppCheckBackoffWrapper currentDateProvider]];
-}
-
-- (instancetype)initWithDateProvider:(FIRAppCheckDateProvider)dateProvider {
-  self = [super init];
-  if (self) {
-    _dateProvider = [dateProvider copy];
-  }
-  return self;
-}
-
-+ (FIRAppCheckDateProvider)currentDateProvider {
-  return ^NSDate *(void) {
-    return [NSDate date];
-  };
-}
-
-- (FBLPromise *)applyBackoffToOperation:(FIRAppCheckBackoffOperationProvider)operationProvider
-                           errorHandler:(FIRAppCheckBackoffErrorHandler)errorHandler {
-  if (![self isNextOperationAllowed]) {
-    // Backing off - skip the operation and return an error straight away.
-    return [self promiseWithRetryDisallowedError:self.lastFailure.error];
-  }
-
-  __auto_type operationPromise = operationProvider();
-  return operationPromise
-      .thenOn([self queue],
-              ^id(id result) {
-                @synchronized(self) {
-                  // Reset failure on success.
-                  self.lastFailure = nil;
-                }
-
-                // Return the result.
-                return result;
-              })
-      .recoverOn([self queue], ^NSError *(NSError *error) {
-        @synchronized(self) {
-          // Update the last failure to calculate the backoff.
-          self.lastFailure =
-              [FIRAppCheckBackoffOperationFailure nextRetryFailureWithFailure:self.lastFailure
-                                                                   finishDate:self.dateProvider()
-                                                                        error:error
-                                                                  backoffType:errorHandler(error)];
-        }
-
-        // Re-throw the error.
-        return error;
-      });
-}
-
-#pragma mark - Private
-
-- (BOOL)isNextOperationAllowed {
-  @synchronized(self) {
-    if (self.lastFailure == nil) {
-      // It is first attempt. Always allow it.
-      return YES;
-    }
-
-    switch (self.lastFailure.backoffType) {
-      case FIRAppCheckBackoffTypeNone:
-        return YES;
-        break;
-
-      case FIRAppCheckBackoffType1Day:
-        return [self hasTimeIntervalPassedSinceLastFailure:k24Hours];
-        break;
-
-      case FIRAppCheckBackoffTypeExponential:
-        return [self hasTimeIntervalPassedSinceLastFailure:
-                         [self exponentialBackoffIntervalForFailure:self.lastFailure]];
-        break;
-    }
-  }
-}
-
-- (BOOL)hasTimeIntervalPassedSinceLastFailure:(NSTimeInterval)timeInterval {
-  NSDate *failureDate = self.lastFailure.finishDate;
-  // Return YES if there has not been a failure yet.
-  if (failureDate == nil) return YES;
-
-  NSTimeInterval timeSinceFailure = [self.dateProvider() timeIntervalSinceDate:failureDate];
-  return timeSinceFailure >= timeInterval;
-}
-
-- (FBLPromise *)promiseWithRetryDisallowedError:(NSError *)error {
-  NSString *reason =
-      [NSString stringWithFormat:@"Too many attempts. Underlying error: %@",
-                                 error.localizedDescription ?: error.localizedFailureReason];
-  NSError *retryDisallowedError = [FIRAppCheckErrorUtil errorWithFailureReason:reason];
-  FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-  [rejectedPromise reject:retryDisallowedError];
-  return rejectedPromise;
-}
-
-- (dispatch_queue_t)queue {
-  return dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
-}
-
-#pragma mark - Exponential backoff
-
-/// @return Exponential backoff interval with jitter. Jitter is needed to avoid all clients to retry
-/// at the same time after e.g. a backend outage.
-- (NSTimeInterval)exponentialBackoffIntervalForFailure:
-    (FIRAppCheckBackoffOperationFailure *)failure {
-  // Base exponential backoff interval.
-  NSTimeInterval baseBackoff = pow(2, failure.retryCount);
-
-  // Get a random number from 0 to 1.
-  double maxRandom = 1000;
-  double randomNumber = (double)arc4random_uniform((int32_t)maxRandom) / maxRandom;
-
-  // A number from 1 to 1 + kMaxJitterCoefficient, e.g. from 1 to 1.5. Indicates how much the
-  // backoff can be extended.
-  double jitterCoefficient = 1 + randomNumber * kMaxJitterCoefficient;
-
-  // Exponential backoff interval with jitter.
-  NSTimeInterval backoffIntervalWithJitter = baseBackoff * jitterCoefficient;
-
-  // Apply limit to the backoff interval.
-  return MIN(backoffIntervalWithJitter, kMaxExponentialBackoffInterval);
-}
-
-#pragma mark - Error handling
-
-- (FIRAppCheckBackoffErrorHandler)defaultAppCheckProviderErrorHandler {
-  return ^FIRAppCheckBackoffType(NSError *error) {
-    FIRAppCheckHTTPError *HTTPError =
-        [error isKindOfClass:[FIRAppCheckHTTPError class]] ? (FIRAppCheckHTTPError *)error : nil;
-
-    if (HTTPError == nil) {
-      // No backoff for attestation providers for non-backend (e.g. network) errors.
-      return FIRAppCheckBackoffTypeNone;
-    }
-
-    NSInteger statusCode = HTTPError.HTTPResponse.statusCode;
-
-    if (statusCode < 400) {
-      // No backoff for codes before 400.
-      return FIRAppCheckBackoffTypeNone;
-    }
-
-    if (statusCode == 400 || statusCode == 404) {
-      // Firebase project misconfiguration. It will unlikely be fixed soon and often requires
-      // another version of the app. Try again in 1 day.
-      return FIRAppCheckBackoffType1Day;
-    }
-
-    if (statusCode == 403) {
-      // Project may have been soft-deleted accidentally. There is a chance of timely recovery, so
-      // try again later.
-      return FIRAppCheckBackoffTypeExponential;
-    }
-
-    if (statusCode == 429) {
-      // Too many requests. Try again in a while.
-      return FIRAppCheckBackoffTypeExponential;
-    }
-
-    if (statusCode == 503) {
-      // Server is overloaded. Try again in a while.
-      return FIRAppCheckBackoffTypeExponential;
-    }
-
-    // For all other server error cases default to the exponential backoff.
-    return FIRAppCheckBackoffTypeExponential;
-  };
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 1 - 40
FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h

@@ -16,53 +16,14 @@
 
 #import <Foundation/Foundation.h>
 
-@class FIRAppCheckHTTPError;
+#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-void FIRAppCheckSetErrorToPointer(NSError *error, NSError **pointer);
-
 @interface FIRAppCheckErrorUtil : NSObject
 
 + (NSError *)publicDomainErrorWithError:(NSError *)error;
 
-// MARK: - Internal errors
-
-+ (NSError *)cachedTokenNotFound;
-
-+ (NSError *)cachedTokenExpired;
-
-+ (NSError *)keychainErrorWithError:(NSError *)error;
-
-+ (FIRAppCheckHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse
-                                              data:(nullable NSData *)data;
-
-+ (NSError *)APIErrorWithNetworkError:(NSError *)networkError;
-
-+ (NSError *)appCheckTokenResponseErrorWithMissingField:(NSString *)fieldName;
-
-+ (NSError *)appAttestAttestationResponseErrorWithMissingField:(NSString *)fieldName;
-
-+ (NSError *)JSONSerializationError:(NSError *)error;
-
-+ (NSError *)errorWithFailureReason:(NSString *)failureReason;
-
-+ (NSError *)unsupportedAttestationProvider:(NSString *)providerName;
-
-+ (NSError *)appAttestKeyIDNotFound;
-
-// MARK: - App Attest Errors
-
-+ (NSError *)appAttestGenerateKeyFailedWithError:(NSError *)error;
-
-+ (NSError *)appAttestAttestKeyFailedWithError:(NSError *)error
-                                         keyId:(NSString *)keyId
-                                clientDataHash:(NSData *)clientDataHash;
-
-+ (NSError *)appAttestGenerateAssertionFailedWithError:(NSError *)error
-                                                 keyId:(NSString *)keyId
-                                        clientDataHash:(NSData *)clientDataHash;
-
 @end
 
 NS_ASSUME_NONNULL_END

+ 29 - 133
FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.m

@@ -16,145 +16,47 @@
 
 #import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
 
-#import <GoogleUtilities/GULKeychainUtils.h>
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h"
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
+#import <AppCheckCore/AppCheckCore.h>
 
 @implementation FIRAppCheckErrorUtil
 
 + (NSError *)publicDomainErrorWithError:(NSError *)error {
-  if ([error.domain isEqualToString:FIRAppCheckErrorDomain]) {
+  if ([error.domain isEqualToString:GACAppCheckErrorDomain]) {
+    return [self publicDomainErrorWithGACError:error];
+  } else if ([error.domain isEqualToString:FIRAppCheckErrorDomain]) {
     return error;
   }
 
   return [self unknownErrorWithError:error];
 }
 
-#pragma mark - Internal errors
-
-+ (NSError *)cachedTokenNotFound {
-  NSString *failureReason = [NSString stringWithFormat:@"Cached token not found."];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)cachedTokenExpired {
-  NSString *failureReason = [NSString stringWithFormat:@"Cached token expired."];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)keychainErrorWithError:(NSError *)error {
-  if ([error.domain isEqualToString:kGULKeychainUtilsErrorDomain]) {
-    NSString *failureReason = [NSString stringWithFormat:@"Keychain access error."];
-    return [self appCheckErrorWithCode:FIRAppCheckErrorCodeKeychain
-                         failureReason:failureReason
-                       underlyingError:error];
+/// Converts an App Check Core error (`GACAppCheckErrorDomain`) to a public error
+/// (`FIRAppCheckErrorDomain`).
++ (NSError *)publicDomainErrorWithGACError:(NSError *)appCheckCoreError {
+  FIRAppCheckErrorCode errorCode;
+  switch ((GACAppCheckErrorCode)appCheckCoreError.code) {
+    case GACAppCheckErrorCodeUnknown:
+      errorCode = FIRAppCheckErrorCodeUnknown;
+      break;
+    case GACAppCheckErrorCodeServerUnreachable:
+      errorCode = FIRAppCheckErrorCodeServerUnreachable;
+      break;
+    case GACAppCheckErrorCodeInvalidConfiguration:
+      errorCode = FIRAppCheckErrorCodeInvalidConfiguration;
+      break;
+    case GACAppCheckErrorCodeKeychain:
+      errorCode = FIRAppCheckErrorCodeKeychain;
+      break;
+    case GACAppCheckErrorCodeUnsupported:
+      errorCode = FIRAppCheckErrorCodeUnsupported;
+      break;
+    default:
+      return [self unknownErrorWithError:appCheckCoreError];
   }
 
-  return [self unknownErrorWithError:error];
-}
-
-+ (FIRAppCheckHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse
-                                              data:(nullable NSData *)data {
-  return [[FIRAppCheckHTTPError alloc] initWithHTTPResponse:HTTPResponse data:data];
-}
-
-+ (NSError *)APIErrorWithNetworkError:(NSError *)networkError {
-  NSString *failureReason = [NSString stringWithFormat:@"API request error."];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeServerUnreachable
-                       failureReason:failureReason
-                     underlyingError:networkError];
-}
-
-+ (NSError *)appCheckTokenResponseErrorWithMissingField:(NSString *)fieldName {
-  NSString *failureReason = [NSString
-      stringWithFormat:@"Unexpected app check token response format. Field `%@` is missing.",
-                       fieldName];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)appAttestAttestationResponseErrorWithMissingField:(NSString *)fieldName {
-  NSString *failureReason =
-      [NSString stringWithFormat:@"Unexpected attestation response format. Field `%@` is missing.",
-                                 fieldName];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)JSONSerializationError:(NSError *)error {
-  NSString *failureReason = [NSString stringWithFormat:@"JSON serialization error."];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:error];
-}
-
-+ (NSError *)unsupportedAttestationProvider:(NSString *)providerName {
-  NSString *failureReason = [NSString
-      stringWithFormat:
-          @"The attestation provider %@ is not supported on current platform and OS version.",
-          providerName];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnsupported
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)appAttestKeyIDNotFound {
-  NSString *failureReason = [NSString stringWithFormat:@"App attest key ID not found."];
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-+ (NSError *)errorWithFailureReason:(NSString *)failureReason {
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:nil];
-}
-
-#pragma mark - App Attest
-
-+ (NSError *)appAttestGenerateKeyFailedWithError:(NSError *)error {
-  NSString *failureReason = @"Failed to generate a new cryptographic key for use with the App "
-                            @"Attest service (`generateKeyWithCompletionHandler:`).";
-  // TODO(#11967): Add a new error code for this case (e.g., FIRAppCheckAppAttestGenerateKeyFailed).
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:error];
-}
-
-+ (NSError *)appAttestAttestKeyFailedWithError:(NSError *)error
-                                         keyId:(NSString *)keyId
-                                clientDataHash:(NSData *)clientDataHash {
-  NSString *failureReason =
-      [NSString stringWithFormat:@"Failed to attest the validity of the generated cryptographic "
-                                 @"key (`attestKey:clientDataHash:completionHandler:`); "
-                                 @"keyId.length = %lu, clientDataHash.length = %lu",
-                                 (unsigned long)keyId.length, (unsigned long)clientDataHash.length];
-  // TODO(#11967): Add a new error code for this case (e.g., FIRAppCheckAppAttestAttestKeyFailed).
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:error];
-}
-
-+ (NSError *)appAttestGenerateAssertionFailedWithError:(NSError *)error
-                                                 keyId:(NSString *)keyId
-                                        clientDataHash:(NSData *)clientDataHash {
-  NSString *failureReason = [NSString
-      stringWithFormat:@"Failed to create a block of data that demonstrates the legitimacy of the "
-                       @"app instance (`generateAssertion:clientDataHash:completionHandler:`); "
-                       @"keyId.length = %lu, clientDataHash.length = %lu.",
-                       (unsigned long)keyId.length, (unsigned long)clientDataHash.length];
-  // TODO(#11967): Add error code for this case (e.g., FIRAppCheckAppAttestGenerateAssertionFailed).
-  return [self appCheckErrorWithCode:FIRAppCheckErrorCodeUnknown
-                       failureReason:failureReason
-                     underlyingError:error];
+  return [NSError errorWithDomain:FIRAppCheckErrorDomain
+                             code:errorCode
+                         userInfo:appCheckCoreError.userInfo];
 }
 
 #pragma mark - Helpers
@@ -177,9 +79,3 @@
 }
 
 @end
-
-void FIRAppCheckSetErrorToPointer(NSError *error, NSError **pointer) {
-  if (pointer != NULL) {
-    *pointer = error;
-  }
-}

+ 0 - 32
FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h

@@ -1,32 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppCheckHTTPError : NSError
-
-@property(nonatomic, readonly) NSHTTPURLResponse *HTTPResponse;
-@property(nonatomic, readonly, nonnull) NSData *data;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse data:(nullable NSData *)data;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 75
FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.m

@@ -1,75 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckHTTPError.h"
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
-
-@implementation FIRAppCheckHTTPError
-
-- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse
-                                data:(nullable NSData *)data {
-  NSDictionary *userInfo = [[self class] userInfoWithHTTPResponse:HTTPResponse data:data];
-  self = [super initWithDomain:FIRAppCheckErrorDomain
-                          code:FIRAppCheckErrorCodeUnknown
-                      userInfo:userInfo];
-  if (self) {
-    _HTTPResponse = HTTPResponse;
-    _data = data;
-  }
-  return self;
-}
-
-+ (NSDictionary *)userInfoWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse
-                                      data:(nullable NSData *)data {
-  NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-  NSString *failureReason =
-      [NSString stringWithFormat:@"The server responded with an error: \n - URL: %@ \n - HTTP "
-                                 @"status code: %ld \n - Response body: %@",
-                                 HTTPResponse.URL, (long)HTTPResponse.statusCode, responseString];
-  return @{NSLocalizedFailureReasonErrorKey : failureReason};
-}
-
-#pragma mark - NSCopying
-
-- (id)copyWithZone:(NSZone *)zone {
-  return [[[self class] alloc] initWithHTTPResponse:self.HTTPResponse data:self.data];
-}
-
-#pragma mark - NSSecureCoding
-
-- (nullable instancetype)initWithCoder:(NSCoder *)coder {
-  NSHTTPURLResponse *HTTPResponse = [coder decodeObjectOfClass:[NSHTTPURLResponse class]
-                                                        forKey:@"HTTPResponse"];
-  if (!HTTPResponse) {
-    return nil;
-  }
-  NSData *data = [coder decodeObjectOfClass:[NSData class] forKey:@"data"];
-
-  return [self initWithHTTPResponse:HTTPResponse data:data];
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
-  [coder encodeObject:self.HTTPResponse forKey:@"HTTPResponse"];
-  [coder encodeObject:self.data forKey:@"data"];
-}
-
-+ (BOOL)supportsSecureCoding {
-  return YES;
-}
-
-@end

+ 7 - 8
FirebaseAppCheck/Sources/AppAttestProvider/DCAppAttestService+FIRAppAttestService.h → FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2023 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-#import <DeviceCheck/DeviceCheck.h>
-
-#import "FirebaseAppCheck/Sources/AppAttestProvider/FIRAppAttestService.h"
-
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckAvailability.h"
+#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-FIR_APP_ATTEST_PROVIDER_AVAILABILITY
-@interface DCAppAttestService (FIRAppAttestService) <FIRAppAttestService>
+@interface FIRApp (AppCheck)
+
+/// The resource name for the Firebase App in the format "projects/{project_id}/apps/{app_id}".
+/// See https://google.aip.dev/122 for more details about resource names.
+@property(nonatomic, readonly, copy) NSString *resourceName;
 
 @end
 

+ 7 - 8
FirebaseAppCheck/Sources/AppAttestProvider/Errors/FIRAppAttestRejectionError.h → FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.m

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2023 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-#import <Foundation/Foundation.h>
+#import "FirebaseAppCheck/Sources/Core/FIRApp+AppCheck.h"
 
-NS_ASSUME_NONNULL_BEGIN
+@implementation FIRApp (AppCheck)
 
-@interface FIRAppAttestRejectionError : NSError
-
-- (instancetype)init;
+- (NSString *)resourceName {
+  return [NSString
+      stringWithFormat:@"projects/%@/apps/%@", self.options.projectID, self.options.googleAppID];
+}
 
 @end
-
-NS_ASSUME_NONNULL_END

+ 74 - 177
FirebaseAppCheck/Sources/Core/FIRAppCheck.m

@@ -16,14 +16,9 @@
 
 #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheck.h"
 
+#import <AppCheckCore/AppCheckCore.h>
 #import <FirebaseAppCheckInterop/FirebaseAppCheckInterop.h>
 
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
 #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckErrors.h"
 #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckProvider.h"
 #import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckProviderFactory.h"
@@ -34,9 +29,7 @@
 #import "FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.h"
 #import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
 #import "FirebaseAppCheck/Sources/Core/FIRAppCheckTokenResult.h"
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.h"
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.h"
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.h"
+#import "FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -55,22 +48,16 @@ NSString *const kFIRAppCheckAppNameNotificationKey = @"FIRAppCheckAppNameNotific
 
 static id<FIRAppCheckProviderFactory> _providerFactory;
 
-static const NSTimeInterval kTokenExpirationThreshold = 5 * 60;  // 5 min.
-
 static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1IifQ==";
 
-@interface FIRAppCheck () <FIRAppCheckInterop>
+@interface FIRAppCheck () <FIRAppCheckInterop, GACAppCheckTokenDelegate>
 @property(class, nullable) id<FIRAppCheckProviderFactory> providerFactory;
 
 @property(nonatomic, readonly) NSString *appName;
-@property(nonatomic, readonly) id<FIRAppCheckProvider> appCheckProvider;
-@property(nonatomic, readonly) id<FIRAppCheckStorageProtocol> storage;
 @property(nonatomic, readonly) NSNotificationCenter *notificationCenter;
-@property(nonatomic, readonly) id<FIRAppCheckSettingsProtocol> settings;
+@property(nonatomic, readonly) FIRAppCheckSettings *settings;
+@property(nonatomic, readonly) GACAppCheck *appCheckCore;
 
-@property(nonatomic, readonly, nullable) id<FIRAppCheckTokenRefresherProtocol> tokenRefresher;
-
-@property(nonatomic, nullable) FBLPromise<FIRAppCheckToken *> *ongoingRetrieveOrRefreshTokenPromise;
 @end
 
 @implementation FIRAppCheck
@@ -78,6 +65,9 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
 #pragma mark - Internal
 
 - (nullable instancetype)initWithApp:(FIRApp *)app {
+  // Set the App Check Core logging level to the current equivalent Firebase logging level.
+  GACAppCheckLogger.logLevel = FIRGetGACAppCheckLogLevel();
+
   id<FIRAppCheckProviderFactory> providerFactory = [FIRAppCheck providerFactory];
 
   if (providerFactory == nil) {
@@ -98,47 +88,40 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
     return nil;
   }
 
+  NSString *serviceName = [self serviceNameForApp:app];
+  NSString *resourceName = [self resourceNameForApp:app];
+  id<GACAppCheckProvider> appCheckCoreProvider =
+      [[FIRInternalAppCheckProvider alloc] initWithAppCheckProvider:appCheckProvider];
   FIRAppCheckSettings *settings =
       [[FIRAppCheckSettings alloc] initWithApp:app
                                    userDefault:[NSUserDefaults standardUserDefaults]
                                     mainBundle:[NSBundle mainBundle]];
-  FIRAppCheckTokenRefreshResult *refreshResult =
-      [[FIRAppCheckTokenRefreshResult alloc] initWithStatusNever];
-  FIRAppCheckTokenRefresher *tokenRefresher =
-      [[FIRAppCheckTokenRefresher alloc] initWithRefreshResult:refreshResult settings:settings];
 
-  FIRAppCheckStorage *storage = [[FIRAppCheckStorage alloc] initWithAppName:app.name
-                                                                      appID:app.options.googleAppID
-                                                                accessGroup:app.options.appGroupID];
+  GACAppCheck *appCheckCore = [[GACAppCheck alloc] initWithServiceName:serviceName
+                                                          resourceName:resourceName
+                                                      appCheckProvider:appCheckCoreProvider
+                                                              settings:settings
+                                                         tokenDelegate:self
+                                                   keychainAccessGroup:app.options.appGroupID];
 
   return [self initWithAppName:app.name
+                  appCheckCore:appCheckCore
               appCheckProvider:appCheckProvider
-                       storage:storage
-                tokenRefresher:tokenRefresher
             notificationCenter:NSNotificationCenter.defaultCenter
                       settings:settings];
 }
 
 - (instancetype)initWithAppName:(NSString *)appName
+                   appCheckCore:(GACAppCheck *)appCheckCore
                appCheckProvider:(id<FIRAppCheckProvider>)appCheckProvider
-                        storage:(id<FIRAppCheckStorageProtocol>)storage
-                 tokenRefresher:(id<FIRAppCheckTokenRefresherProtocol>)tokenRefresher
              notificationCenter:(NSNotificationCenter *)notificationCenter
-                       settings:(id<FIRAppCheckSettingsProtocol>)settings {
+                       settings:(FIRAppCheckSettings *)settings {
   self = [super init];
   if (self) {
     _appName = appName;
-    _appCheckProvider = appCheckProvider;
-    _storage = storage;
-    _tokenRefresher = tokenRefresher;
+    _appCheckCore = appCheckCore;
     _notificationCenter = notificationCenter;
     _settings = settings;
-
-    __auto_type __weak weakSelf = self;
-    tokenRefresher.tokenRefreshHandler = ^(FIRAppCheckTokenRefreshCompletion _Nonnull completion) {
-      __auto_type strongSelf = weakSelf;
-      [strongSelf periodicTokenRefreshWithCompletion:completion];
-    };
   }
   return self;
 }
@@ -166,26 +149,28 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
 - (void)tokenForcingRefresh:(BOOL)forcingRefresh
                  completion:(void (^)(FIRAppCheckToken *_Nullable token,
                                       NSError *_Nullable error))handler {
-  [self retrieveOrRefreshTokenForcingRefresh:forcingRefresh]
-      .then(^id _Nullable(FIRAppCheckToken *token) {
-        handler(token, nil);
-        return token;
-      })
-      .catch(^(NSError *_Nonnull error) {
-        handler(nil, [FIRAppCheckErrorUtil publicDomainErrorWithError:error]);
-      });
+  [self.appCheckCore
+      tokenForcingRefresh:forcingRefresh
+               completion:^(GACAppCheckTokenResult *result) {
+                 if (result.error) {
+                   handler(nil, [FIRAppCheckErrorUtil publicDomainErrorWithError:result.error]);
+                   return;
+                 }
+
+                 handler([[FIRAppCheckToken alloc] initWithInternalToken:result.token], nil);
+               }];
 }
 
 - (void)limitedUseTokenWithCompletion:(void (^)(FIRAppCheckToken *_Nullable token,
                                                 NSError *_Nullable error))handler {
-  [self limitedUseToken]
-      .then(^id _Nullable(FIRAppCheckToken *token) {
-        handler(token, nil);
-        return token;
-      })
-      .catch(^(NSError *_Nonnull error) {
-        handler(nil, [FIRAppCheckErrorUtil publicDomainErrorWithError:error]);
-      });
+  [self.appCheckCore limitedUseTokenWithCompletion:^(GACAppCheckTokenResult *result) {
+    if (result.error) {
+      handler(nil, [FIRAppCheckErrorUtil publicDomainErrorWithError:result.error]);
+      return;
+    }
+
+    handler([[FIRAppCheckToken alloc] initWithInternalToken:result.token], nil);
+  }];
 }
 
 + (void)setAppCheckProviderFactory:(nullable id<FIRAppCheckProviderFactory>)factory {
@@ -218,33 +203,27 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
 
 - (void)getTokenForcingRefresh:(BOOL)forcingRefresh
                     completion:(FIRAppCheckTokenHandlerInterop)handler {
-  [self retrieveOrRefreshTokenForcingRefresh:forcingRefresh]
-      .then(^id _Nullable(FIRAppCheckToken *token) {
-        FIRAppCheckTokenResult *result = [[FIRAppCheckTokenResult alloc] initWithToken:token.token
-                                                                                 error:nil];
-        handler(result);
-        return result;
-      })
-      .catch(^(NSError *_Nonnull error) {
-        FIRAppCheckTokenResult *result =
-            [[FIRAppCheckTokenResult alloc] initWithToken:kDummyFACTokenValue error:error];
-        handler(result);
-      });
+  [self.appCheckCore
+      tokenForcingRefresh:forcingRefresh
+               completion:^(GACAppCheckTokenResult *internalResult) {
+                 FIRAppCheckToken *token =
+                     [[FIRAppCheckToken alloc] initWithInternalToken:internalResult.token];
+                 FIRAppCheckTokenResult *tokenResult =
+                     [[FIRAppCheckTokenResult alloc] initWithToken:token.token
+                                                             error:internalResult.error];
+
+                 handler(tokenResult);
+               }];
 }
 
 - (void)getLimitedUseTokenWithCompletion:(FIRAppCheckTokenHandlerInterop)handler {
-  [self limitedUseToken]
-      .then(^id _Nullable(FIRAppCheckToken *token) {
-        FIRAppCheckTokenResult *result = [[FIRAppCheckTokenResult alloc] initWithToken:token.token
-                                                                                 error:nil];
-        handler(result);
-        return result;
-      })
-      .catch(^(NSError *_Nonnull error) {
-        FIRAppCheckTokenResult *result =
-            [[FIRAppCheckTokenResult alloc] initWithToken:kDummyFACTokenValue error:error];
-        handler(result);
-      });
+  [self.appCheckCore limitedUseTokenWithCompletion:^(GACAppCheckTokenResult *internalResult) {
+    FIRAppCheckToken *token = [[FIRAppCheckToken alloc] initWithInternalToken:internalResult.token];
+    FIRAppCheckTokenResult *tokenResult =
+        [[FIRAppCheckTokenResult alloc] initWithToken:token.token error:internalResult.error];
+
+    handler(tokenResult);
+  }];
 }
 
 - (nonnull NSString *)tokenDidChangeNotificationName {
@@ -259,105 +238,12 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
   return kFIRAppCheckTokenNotificationKey;
 }
 
-#pragma mark - FAA token cache
-
-- (FBLPromise<FIRAppCheckToken *> *)retrieveOrRefreshTokenForcingRefresh:(BOOL)forcingRefresh {
-  return [FBLPromise do:^id _Nullable {
-    if (self.ongoingRetrieveOrRefreshTokenPromise == nil) {
-      // Kick off a new operation only when there is not an ongoing one.
-      self.ongoingRetrieveOrRefreshTokenPromise =
-          [self createRetrieveOrRefreshTokenPromiseForcingRefresh:forcingRefresh]
-
-              // Release the ongoing operation promise on completion.
-              .then(^FIRAppCheckToken *(FIRAppCheckToken *token) {
-                self.ongoingRetrieveOrRefreshTokenPromise = nil;
-                return token;
-              })
-              .recover(^NSError *(NSError *error) {
-                self.ongoingRetrieveOrRefreshTokenPromise = nil;
-                return error;
-              });
-    }
-    return self.ongoingRetrieveOrRefreshTokenPromise;
-  }];
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)createRetrieveOrRefreshTokenPromiseForcingRefresh:
-    (BOOL)forcingRefresh {
-  return [self getCachedValidTokenForcingRefresh:forcingRefresh].recover(
-      ^id _Nullable(NSError *_Nonnull error) {
-        return [self refreshToken];
-      });
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)getCachedValidTokenForcingRefresh:(BOOL)forcingRefresh {
-  if (forcingRefresh) {
-    FBLPromise *rejectedPromise = [FBLPromise pendingPromise];
-    [rejectedPromise reject:[FIRAppCheckErrorUtil cachedTokenNotFound]];
-    return rejectedPromise;
-  }
-
-  return [self.storage getToken].then(^id(FIRAppCheckToken *_Nullable token) {
-    if (token == nil) {
-      return [FIRAppCheckErrorUtil cachedTokenNotFound];
-    }
-
-    BOOL isTokenExpiredOrExpiresSoon =
-        [token.expirationDate timeIntervalSinceNow] < kTokenExpirationThreshold;
-    if (isTokenExpiredOrExpiresSoon) {
-      return [FIRAppCheckErrorUtil cachedTokenExpired];
-    }
-
-    return token;
-  });
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)refreshToken {
-  return [FBLPromise
-             wrapObjectOrErrorCompletion:^(FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
-               [self.appCheckProvider getTokenWithCompletion:handler];
-             }]
-      .then(^id _Nullable(FIRAppCheckToken *_Nullable token) {
-        return [self.storage setToken:token];
-      })
-      .then(^id _Nullable(FIRAppCheckToken *_Nullable token) {
-        // TODO: Make sure the self.tokenRefresher is updated only once. Currently the timer will be
-        // updated twice in the case when the refresh triggered by self.tokenRefresher, but it
-        // should be fine for now as it is a relatively cheap operation.
-        __auto_type refreshResult = [[FIRAppCheckTokenRefreshResult alloc]
-            initWithStatusSuccessAndExpirationDate:token.expirationDate
-                                    receivedAtDate:token.receivedAtDate];
-        [self.tokenRefresher updateWithRefreshResult:refreshResult];
-        [self postTokenUpdateNotificationWithToken:token];
-        return token;
-      });
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)limitedUseToken {
-  return
-      [FBLPromise wrapObjectOrErrorCompletion:^(
-                      FBLPromiseObjectOrErrorCompletion _Nonnull handler) {
-        [self.appCheckProvider getTokenWithCompletion:handler];
-      }].then(^id _Nullable(FIRAppCheckToken *_Nullable token) {
-        return token;
-      });
-}
+#pragma mark - GACAppCheckTokenDelegate
 
-#pragma mark - Token auto refresh
-
-- (void)periodicTokenRefreshWithCompletion:(FIRAppCheckTokenRefreshCompletion)completion {
-  [self retrieveOrRefreshTokenForcingRefresh:NO]
-      .then(^id _Nullable(FIRAppCheckToken *_Nullable token) {
-        __auto_type refreshResult = [[FIRAppCheckTokenRefreshResult alloc]
-            initWithStatusSuccessAndExpirationDate:token.expirationDate
-                                    receivedAtDate:token.receivedAtDate];
-        completion(refreshResult);
-        return nil;
-      })
-      .catch(^(NSError *error) {
-        __auto_type refreshResult = [[FIRAppCheckTokenRefreshResult alloc] initWithStatusFailure];
-        completion(refreshResult);
-      });
+- (void)tokenDidUpdate:(nonnull GACAppCheckToken *)token
+           serviceName:(nonnull NSString *)serviceName {
+  FIRAppCheckToken *appCheckToken = [[FIRAppCheckToken alloc] initWithInternalToken:token];
+  [self postTokenUpdateNotificationWithToken:appCheckToken];
 }
 
 #pragma mark - Token update notification
@@ -371,6 +257,17 @@ static NSString *const kDummyFACTokenValue = @"eyJlcnJvciI6IlVOS05PV05fRVJST1Iif
                                        }];
 }
 
+#pragma mark - Helpers
+
+- (NSString *)serviceNameForApp:(FIRApp *)app {
+  return [NSString stringWithFormat:@"FirebaseApp:%@", app.name];
+}
+
+- (NSString *)resourceNameForApp:(FIRApp *)app {
+  return [NSString
+      stringWithFormat:@"projects/%@/apps/%@", app.options.projectID, app.options.googleAppID];
+}
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 4 - 10
FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.h

@@ -16,22 +16,18 @@
 
 #import <Foundation/Foundation.h>
 
+#import <AppCheckCore/AppCheckCore.h>
+
 #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
 
 extern FIRLoggerService kFIRLoggerAppCheck;
 
-FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeUnknown;
-
 // FIRAppCheck.m
 FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeProviderFactoryIsMissing;
 FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeProviderIsMissing;
 
-// FIRAppCheckAPIService.m
-FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeUnexpectedHTTPCode;
-
 // FIRAppCheckDebugProvider.m
 FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageDebugProviderIncompleteFIROptions;
-FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageDebugProviderFailedExchange;
 
 // FIRAppCheckDebugProviderFactory.m
 FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeDebugToken;
@@ -39,8 +35,6 @@ FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeDebugToken;
 // FIRDeviceCheckProvider.m
 FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageDeviceCheckProviderIncompleteFIROptions;
 
-// FIRAppAttestProvider.m
-FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeAppAttestNotSupported;
-FOUNDATION_EXPORT NSString *const kFIRLoggerAppCheckMessageCodeAttestationRejected;
-
 void FIRAppCheckDebugLog(NSString *messageCode, NSString *message, ...);
+
+GACAppCheckLogLevel FIRGetGACAppCheckLogLevel(void);

+ 18 - 10
FirebaseAppCheck/Sources/Core/FIRAppCheckLogger.m

@@ -22,18 +22,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 FIRLoggerService kFIRLoggerAppCheck = @"[FirebaseAppCheck]";
 
-NSString *const kFIRLoggerAppCheckMessageCodeUnknown = @"I-FAA001001";
-
 // FIRAppCheck.m
 NSString *const kFIRLoggerAppCheckMessageCodeProviderFactoryIsMissing = @"I-FAA002001";
 NSString *const kFIRLoggerAppCheckMessageCodeProviderIsMissing = @"I-FAA002002";
 
-// FIRAppCheckAPIService.m
-NSString *const kFIRLoggerAppCheckMessageCodeUnexpectedHTTPCode = @"I-FAA003001";
-
 // FIRAppCheckDebugProvider.m
 NSString *const kFIRLoggerAppCheckMessageDebugProviderIncompleteFIROptions = @"I-FAA004001";
-NSString *const kFIRLoggerAppCheckMessageDebugProviderFailedExchange = @"I-FAA004002";
 
 // FIRAppCheckDebugProviderFactory.m
 NSString *const kFIRLoggerAppCheckMessageCodeDebugToken = @"I-FAA005001";
@@ -41,11 +35,8 @@ NSString *const kFIRLoggerAppCheckMessageCodeDebugToken = @"I-FAA005001";
 // FIRDeviceCheckProvider.m
 NSString *const kFIRLoggerAppCheckMessageDeviceCheckProviderIncompleteFIROptions = @"I-FAA006001";
 
-// FIRAppAttestProvider.m
-NSString *const kFIRLoggerAppCheckMessageCodeAppAttestNotSupported = @"I-FAA007001";
-NSString *const kFIRLoggerAppCheckMessageCodeAttestationRejected = @"I-FAA007002";
-
 #pragma mark - Log functions
+
 void FIRAppCheckDebugLog(NSString *messageCode, NSString *message, ...) {
   va_list args_ptr;
   va_start(args_ptr, message);
@@ -53,4 +44,21 @@ void FIRAppCheckDebugLog(NSString *messageCode, NSString *message, ...) {
   va_end(args_ptr);
 }
 
+#pragma mark - Helper functions
+
+GACAppCheckLogLevel FIRGetGACAppCheckLogLevel(void) {
+  FIRLoggerLevel loggerLevel = FIRGetLoggerLevel();
+  switch (loggerLevel) {
+    case FIRLoggerLevelError:
+      return GACAppCheckLogLevelError;
+    case FIRLoggerLevelWarning:
+    case FIRLoggerLevelNotice:
+      return GACAppCheckLogLevelWarning;
+    case FIRLoggerLevelInfo:
+      return GACAppCheckLogLevelInfo;
+    case FIRLoggerLevelDebug:
+      return GACAppCheckLogLevelDebug;
+  }
+}
+
 NS_ASSUME_NONNULL_END

+ 7 - 8
FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.h

@@ -16,6 +16,8 @@
 
 #import <Foundation/Foundation.h>
 
+#import <AppCheckCore/AppCheckCore.h>
+
 @class FIRApp;
 
 NS_ASSUME_NONNULL_BEGIN
@@ -23,20 +25,17 @@ NS_ASSUME_NONNULL_BEGIN
 FOUNDATION_EXPORT NSString *const kFIRAppCheckTokenAutoRefreshEnabledUserDefaultsPrefix;
 FOUNDATION_EXPORT NSString *const kFIRAppCheckTokenAutoRefreshEnabledInfoPlistKey;
 
-/// A collection of Firebase app check wide settings and parameters.
-@protocol FIRAppCheckSettingsProtocol <NSObject>
+/// Handles storing and updating the Firebase app check wide settings and parameters.
+@interface FIRAppCheckSettings : GACAppCheckSettings
 
 /// If Firebase app check token auto-refresh is allowed.
 @property(nonatomic, assign) BOOL isTokenAutoRefreshEnabled;
 
-@end
-
-/// Handles storing and updating the Firebase app check wide settings and parameters.
-@interface FIRAppCheckSettings : NSObject <FIRAppCheckSettingsProtocol>
-
 - (instancetype)initWithApp:(FIRApp *)firebaseApp
                 userDefault:(NSUserDefaults *)userDefaults
-                 mainBundle:(NSBundle *)mainBundle;
+                 mainBundle:(NSBundle *)mainBundle NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
 
 @end
 

+ 11 - 9
FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.m

@@ -31,14 +31,12 @@ NSString *const kFIRAppCheckTokenAutoRefreshEnabledInfoPlistKey =
 @property(nonatomic, readonly) NSUserDefaults *userDefaults;
 @property(nonatomic, readonly) NSBundle *mainBundle;
 @property(nonatomic, readonly) NSString *userDefaultKey;
-@property(nonatomic, nullable) NSNumber *isTokenAutoRefreshEnabledNumber;
+@property(nonatomic, assign) BOOL isTokenAutoRefreshConfigured;
 
 @end
 
 @implementation FIRAppCheckSettings
 
-@dynamic isTokenAutoRefreshEnabled;
-
 - (instancetype)initWithApp:(FIRApp *)firebaseApp
                 userDefault:(NSUserDefaults *)userDefaults
                  mainBundle:(NSBundle *)mainBundle {
@@ -49,16 +47,18 @@ NSString *const kFIRAppCheckTokenAutoRefreshEnabledInfoPlistKey =
     _mainBundle = mainBundle;
     _userDefaultKey = [kFIRAppCheckTokenAutoRefreshEnabledUserDefaultsPrefix
         stringByAppendingString:firebaseApp.name];
+    [super setIsTokenAutoRefreshEnabled:NO];
+    _isTokenAutoRefreshConfigured = NO;
   }
   return self;
 }
 
 - (BOOL)isTokenAutoRefreshEnabled {
   @synchronized(self) {
-    if (self.isTokenAutoRefreshEnabledNumber != nil) {
+    if (self.isTokenAutoRefreshConfigured) {
       // Return value form the in-memory cache to avoid accessing the user default or bundle when
       // not required.
-      return self.isTokenAutoRefreshEnabledNumber.boolValue;
+      return [super isTokenAutoRefreshEnabled];
     }
 
     // Check user defaults for a value set during the previous launch.
@@ -73,9 +73,10 @@ NSString *const kFIRAppCheckTokenAutoRefreshEnabledInfoPlistKey =
 
     if (isTokenAutoRefreshEnabledNumber != nil) {
       // Update in-memory cache.
-      self.isTokenAutoRefreshEnabledNumber = isTokenAutoRefreshEnabledNumber;
+      self.isTokenAutoRefreshConfigured = YES;
+      self.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabledNumber.boolValue;
       // Return the value.
-      return isTokenAutoRefreshEnabledNumber.boolValue;
+      return [super isTokenAutoRefreshEnabled];
     }
 
     // Fallback to the global data collection flag.
@@ -91,8 +92,9 @@ NSString *const kFIRAppCheckTokenAutoRefreshEnabledInfoPlistKey =
 
 - (void)setIsTokenAutoRefreshEnabled:(BOOL)isTokenAutoRefreshEnabled {
   @synchronized(self) {
-    self.isTokenAutoRefreshEnabledNumber = @(isTokenAutoRefreshEnabled);
-    [self.userDefaults setObject:self.isTokenAutoRefreshEnabledNumber forKey:self.userDefaultKey];
+    self.isTokenAutoRefreshConfigured = YES;
+    [super setIsTokenAutoRefreshEnabled:isTokenAutoRefreshEnabled];
+    [self.userDefaults setBool:isTokenAutoRefreshEnabled forKey:self.userDefaultKey];
   }
 }
 

+ 9 - 1
FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h

@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
+#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckToken.h"
+
 #import <Foundation/Foundation.h>
 
-#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckToken.h"
+#import <AppCheckCore/AppCheckCore.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -34,6 +36,12 @@ NS_ASSUME_NONNULL_BEGIN
                expirationDate:(NSDate *)expirationDate
                receivedAtDate:(NSDate *)receivedAtDate NS_DESIGNATED_INITIALIZER;
 
+/// Instantiates a `FIRAppCheckToken` token from a `GACAppCheckToken`.
+/// @param token The internal App Check token to be converted into a Firebase App Check token.
+- (instancetype)initWithInternalToken:(GACAppCheckToken *)token;
+
+- (GACAppCheckToken *)internalToken;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 12 - 0
FirebaseAppCheck/Sources/Core/FIRAppCheckToken.m

@@ -36,6 +36,18 @@ NS_ASSUME_NONNULL_BEGIN
   return [self initWithToken:token expirationDate:expirationDate receivedAtDate:[NSDate date]];
 }
 
+- (instancetype)initWithInternalToken:(GACAppCheckToken *)token {
+  return [self initWithToken:token.token
+              expirationDate:token.expirationDate
+              receivedAtDate:token.receivedAtDate];
+}
+
+- (GACAppCheckToken *)internalToken {
+  return [[GACAppCheckToken alloc] initWithToken:self.token
+                                  expirationDate:self.expirationDate
+                                  receivedAtDate:self.receivedAtDate];
+}
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 6 - 7
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken+FIRAppCheckToken.h → FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 Google LLC
+ * Copyright 2023 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,17 +14,16 @@
  * limitations under the License.
  */
 
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.h"
+#import "FirebaseCore/Extension/FIRHeartbeatLogger.h"
 
-@class FIRAppCheckToken;
+#import <AppCheckCore/AppCheckCore.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface FIRAppCheckStoredToken (FIRAppCheckToken)
+@interface FIRHeartbeatLogger (AppCheck)
 
-- (void)updateWithToken:(FIRAppCheckToken *)token;
-
-- (FIRAppCheckToken *)appCheckToken;
+/// Returns a closure that adds a heartbeat logging header to a `URLRequest`.
+- (GACAppCheckAPIRequestHook)requestHook;
 
 @end
 

+ 34 - 0
FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.m

@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FirebaseAppCheck/Sources/Core/FIRHeartbeatLogger+AppCheck.h"
+
+/// The HTTP request header key for a heartbeat logging payload.
+static NSString *const kFIRHeartbeatLoggerPayloadHeaderKey = @"X-firebase-client";
+
+@implementation FIRHeartbeatLogger (AppCheck)
+
+- (GACAppCheckAPIRequestHook)requestHook {
+  return ^(NSMutableURLRequest *request) {
+    NSString *heartbeatsValue =
+        FIRHeaderValueFromHeartbeatsPayload([self flushHeartbeatsIntoPayload]);
+    if (heartbeatsValue) {
+      [request setValue:heartbeatsValue forHTTPHeaderField:kFIRHeartbeatLoggerPayloadHeaderKey];
+    }
+  };
+}
+
+@end

+ 7 - 3
FirebaseAppCheck/Sources/Core/Utils/FIRAppCheckCryptoUtils.h → FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2023 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,11 +16,15 @@
 
 #import <Foundation/Foundation.h>
 
+#import <AppCheckCore/AppCheckCore.h>
+
 NS_ASSUME_NONNULL_BEGIN
 
-@interface FIRAppCheckCryptoUtils : NSObject
+@protocol FIRAppCheckProvider;
+
+@interface FIRInternalAppCheckProvider : NSObject <GACAppCheckProvider>
 
-+ (NSData *)sha256HashFromData:(NSData *)dataToHash;
+- (instancetype)initWithAppCheckProvider:(id<FIRAppCheckProvider>)appCheckProvider;
 
 @end
 

+ 57 - 0
FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.m

@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "FirebaseAppCheck/Sources/Core/FIRInternalAppCheckProvider.h"
+
+#import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
+#import "FirebaseAppCheck/Sources/Public/FirebaseAppCheck/FIRAppCheckProvider.h"
+
+@interface FIRInternalAppCheckProvider ()
+
+@property(nonatomic, readonly) id<FIRAppCheckProvider> appCheckProvider;
+
+@end
+
+@implementation FIRInternalAppCheckProvider
+
+- (instancetype)initWithAppCheckProvider:(id<FIRAppCheckProvider>)appCheckProvider {
+  if (self = [super init]) {
+    _appCheckProvider = appCheckProvider;
+  }
+
+  return self;
+}
+
+- (void)getTokenWithCompletion:(void (^)(GACAppCheckToken *_Nullable, NSError *_Nullable))handler {
+  [self.appCheckProvider
+      getTokenWithCompletion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
+        handler([token internalToken], error);
+      }];
+}
+
+- (void)getLimitedUseTokenWithCompletion:(nonnull void (^)(GACAppCheckToken *_Nullable,
+                                                           NSError *_Nullable))handler {
+  if ([self.appCheckProvider respondsToSelector:@selector(getLimitedUseTokenWithCompletion:)]) {
+    [self.appCheckProvider getLimitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token,
+                                                              NSError *_Nullable error) {
+      handler([token internalToken], error);
+    }];
+  } else {
+    [self getTokenWithCompletion:handler];
+  }
+}
+
+@end

+ 0 - 73
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.h

@@ -1,73 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FIRAppCheckToken;
-@class FBLPromise<ValueType>;
-@class GULKeychainStorage;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol FIRAppCheckStorageProtocol <NSObject>
-
-/** Manages storage of the FAA token.
- *  @param token A token object to store or `nil` to remove existing token.
- *  @return A promise that is resolved with the stored object in the case of success or is rejected
- * with a specific error otherwise.
- */
-- (FBLPromise<FIRAppCheckToken *> *)setToken:(nullable FIRAppCheckToken *)token;
-
-/** Reads a stored FAA token.
- *  @return A promise that is resolved with a stored token or `nil` if there is not a stored token.
- * The promise is rejected with an error in the case of a failure.
- */
-- (FBLPromise<FIRAppCheckToken *> *)getToken;
-
-@end
-
-/// The class provides an implementation of persistent storage to store data like FAA token, etc.
-@interface FIRAppCheckStorage : NSObject <FIRAppCheckStorageProtocol>
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/** Default convenience initializer.
- *  @param appName A Firebase App name (`FirebaseApp.name`). The app name will be used as a part of
- * the key to store the token for the storage instance.
- *  @param appID A Firebase App identifier (`FirebaseOptions.googleAppID`). The app ID will be used
- * as a part of the key to store the token for the storage instance.
- *  @param accessGroup The Keychain Access Group.
- */
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                    accessGroup:(nullable NSString *)accessGroup;
-
-/** Designated initializer.
- *  @param appName A Firebase App name (`FirebaseApp.name`). The app name will be used as a part of
- * the key to store the token for the storage instance.
- *  @param appID A Firebase App identifier (`FirebaseOptions.googleAppID`). The app ID will be used
- * as a part of the key to store the token for the storage instance.
- *  @param keychainStorage An instance of `GULKeychainStorage` used as an underlying secure storage.
- *  @param accessGroup The Keychain Access Group.
- */
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                keychainStorage:(GULKeychainStorage *)keychainStorage
-                    accessGroup:(nullable NSString *)accessGroup NS_DESIGNATED_INITIALIZER;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 125
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.m

@@ -1,125 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStorage.h"
-
-#if __has_include(<FBLPromises/FBLPromises.h>)
-#import <FBLPromises/FBLPromises.h>
-#else
-#import "FBLPromises.h"
-#endif
-
-#import <GoogleUtilities/GULKeychainStorage.h>
-
-#import "FirebaseAppCheck/Sources/Core/Errors/FIRAppCheckErrorUtil.h"
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken+FIRAppCheckToken.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-static NSString *const kKeychainService = @"com.firebase.app_check.token_storage";
-
-@interface FIRAppCheckStorage ()
-
-@property(nonatomic, readonly) NSString *appName;
-@property(nonatomic, readonly) NSString *appID;
-@property(nonatomic, readonly) GULKeychainStorage *keychainStorage;
-@property(nonatomic, readonly, nullable) NSString *accessGroup;
-
-@end
-
-@implementation FIRAppCheckStorage
-
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                keychainStorage:(GULKeychainStorage *)keychainStorage
-                    accessGroup:(nullable NSString *)accessGroup {
-  self = [super init];
-  if (self) {
-    _appName = [appName copy];
-    _appID = [appID copy];
-    _keychainStorage = keychainStorage;
-    _accessGroup = [accessGroup copy];
-  }
-  return self;
-}
-
-- (instancetype)initWithAppName:(NSString *)appName
-                          appID:(NSString *)appID
-                    accessGroup:(nullable NSString *)accessGroup {
-  GULKeychainStorage *keychainStorage =
-      [[GULKeychainStorage alloc] initWithService:kKeychainService];
-  return [self initWithAppName:appName
-                         appID:appID
-               keychainStorage:keychainStorage
-                   accessGroup:accessGroup];
-}
-
-- (FBLPromise<FIRAppCheckToken *> *)getToken {
-  return [self.keychainStorage getObjectForKey:[self tokenKey]
-                                   objectClass:[FIRAppCheckStoredToken class]
-                                   accessGroup:self.accessGroup]
-      .then(^FIRAppCheckToken *(id<NSSecureCoding> storedToken) {
-        if ([(NSObject *)storedToken isKindOfClass:[FIRAppCheckStoredToken class]]) {
-          return [(FIRAppCheckStoredToken *)storedToken appCheckToken];
-        } else {
-          return nil;
-        }
-      })
-      .recover(^NSError *(NSError *error) {
-        return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-      });
-}
-
-- (FBLPromise<NSNull *> *)setToken:(nullable FIRAppCheckToken *)token {
-  if (token) {
-    return [self storeToken:token].recover(^NSError *(NSError *error) {
-      return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-    });
-  } else {
-    return [self.keychainStorage removeObjectForKey:[self tokenKey] accessGroup:self.accessGroup]
-        .then(^id _Nullable(NSNull *_Nullable value) {
-          return token;
-        })
-        .recover(^NSError *(NSError *error) {
-          return [FIRAppCheckErrorUtil keychainErrorWithError:error];
-        });
-  }
-}
-
-#pragma mark - Helpers
-
-- (FBLPromise<NSNull *> *)storeToken:(nullable FIRAppCheckToken *)token {
-  FIRAppCheckStoredToken *storedToken = [[FIRAppCheckStoredToken alloc] init];
-  [storedToken updateWithToken:token];
-  return [self.keychainStorage setObject:storedToken
-                                  forKey:[self tokenKey]
-                             accessGroup:self.accessGroup]
-      .then(^id _Nullable(NSNull *_Nullable value) {
-        return token;
-      });
-}
-
-- (NSString *)tokenKey {
-  return [[self class] tokenKeyForAppName:self.appName appID:self.appID];
-}
-
-+ (NSString *)tokenKeyForAppName:(NSString *)appName appID:(NSString *)appID {
-  return [NSString stringWithFormat:@"app_check_token.%@.%@", appName, appID];
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 35
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken+FIRAppCheckToken.m

@@ -1,35 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken+FIRAppCheckToken.h"
-
-#import "FirebaseAppCheck/Sources/Core/FIRAppCheckToken+Internal.h"
-
-@implementation FIRAppCheckStoredToken (FIRAppCheckToken)
-
-- (void)updateWithToken:(FIRAppCheckToken *)token {
-  self.token = token.token;
-  self.expirationDate = token.expirationDate;
-  self.receivedAtDate = token.receivedAtDate;
-}
-
-- (FIRAppCheckToken *)appCheckToken {
-  return [[FIRAppCheckToken alloc] initWithToken:self.token
-                                  expirationDate:self.expirationDate
-                                  receivedAtDate:self.receivedAtDate];
-}
-
-@end

+ 0 - 39
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.h

@@ -1,39 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-@class FIRApp;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppCheckStoredToken : NSObject <NSSecureCoding>
-
-/// The Firebase App Check token.
-@property(nonatomic, copy, nullable) NSString *token;
-
-/// The Firebase App Check token expiration date in the device local time.
-@property(nonatomic, strong, nullable) NSDate *expirationDate;
-
-/// The date when the Firebase App Check token was received in the device's local time.
-@property(nonatomic, strong, nullable) NSDate *receivedAtDate;
-
-/// The version of local storage.
-@property(nonatomic, readonly) NSInteger storageVersion;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 62
FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.m

@@ -1,62 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/Storage/FIRAppCheckStoredToken.h"
-
-static NSString *const kTokenKey = @"token";
-static NSString *const kExpirationDateKey = @"expirationDate";
-static NSString *const kReceivedAtDateKey = @"receivedAtDate";
-static NSString *const kStorageVersionKey = @"storageVersion";
-
-static const NSInteger kStorageVersion = 2;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@implementation FIRAppCheckStoredToken
-
-- (NSInteger)storageVersion {
-  return kStorageVersion;
-}
-
-+ (BOOL)supportsSecureCoding {
-  return YES;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
-  [coder encodeObject:self.token forKey:kTokenKey];
-  [coder encodeObject:self.expirationDate forKey:kExpirationDateKey];
-  [coder encodeObject:self.receivedAtDate forKey:kReceivedAtDateKey];
-  [coder encodeInteger:self.storageVersion forKey:kStorageVersionKey];
-}
-
-- (nullable instancetype)initWithCoder:(NSCoder *)coder {
-  self = [super init];
-  if (self) {
-    NSInteger decodedStorageVersion = [coder decodeIntegerForKey:kStorageVersionKey];
-    if (decodedStorageVersion > kStorageVersion) {
-      // TODO: Log a message.
-    }
-
-    _token = [coder decodeObjectOfClass:[NSString class] forKey:kTokenKey];
-    _expirationDate = [coder decodeObjectOfClass:[NSDate class] forKey:kExpirationDateKey];
-    _receivedAtDate = [coder decodeObjectOfClass:[NSDate class] forKey:kReceivedAtDateKey];
-  }
-  return self;
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 41
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.h

@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol FIRAppCheckTimerProtocol <NSObject>
-
-- (void)invalidate;
-
-@end
-
-typedef id<FIRAppCheckTimerProtocol> _Nullable (^FIRTimerProvider)(NSDate *fireDate,
-                                                                   dispatch_queue_t queue,
-                                                                   dispatch_block_t handler);
-
-@interface FIRAppCheckTimer : NSObject <FIRAppCheckTimerProtocol>
-
-+ (FIRTimerProvider)timerProvider;
-
-- (nullable instancetype)initWithFireDate:(NSDate *)date
-                            dispatchQueue:(dispatch_queue_t)dispatchQueue
-                                    block:(dispatch_block_t)block;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 91
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.m

@@ -1,91 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppCheckTimer ()
-@property(nonatomic, readonly) dispatch_queue_t dispatchQueue;
-@property(atomic, readonly) dispatch_source_t timer;
-@end
-
-@implementation FIRAppCheckTimer
-
-+ (FIRTimerProvider)timerProvider {
-  return ^id<FIRAppCheckTimerProtocol> _Nullable(NSDate *fireDate, dispatch_queue_t queue,
-                                                 dispatch_block_t handler) {
-    return [[FIRAppCheckTimer alloc] initWithFireDate:fireDate dispatchQueue:queue block:handler];
-  };
-}
-
-+ (nullable instancetype)timerFireDate:(NSDate *)fireDate
-                         dispatchQueue:(dispatch_queue_t)dispatchQueue
-                                 block:(dispatch_block_t)block {
-  return [[FIRAppCheckTimer alloc] initWithFireDate:fireDate
-                                      dispatchQueue:dispatchQueue
-                                              block:block];
-}
-
-- (nullable instancetype)initWithFireDate:(NSDate *)date
-                            dispatchQueue:(dispatch_queue_t)dispatchQueue
-                                    block:(dispatch_block_t)block {
-  self = [super init];
-  if (self == nil) {
-    return nil;
-  }
-
-  if (block == nil) {
-    return nil;
-  }
-
-  NSTimeInterval scheduleInSec = [date timeIntervalSinceNow];
-  if (scheduleInSec <= 0) {
-    return nil;
-  }
-
-  dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, scheduleInSec * NSEC_PER_SEC);
-  _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.dispatchQueue);
-  dispatch_source_set_timer(_timer, startTime, UINT64_MAX * NSEC_PER_SEC, 0);
-
-  __auto_type __weak weakSelf = self;
-  dispatch_source_set_event_handler(_timer, ^{
-    __auto_type strongSelf = weakSelf;
-
-    // The initializer returns a one-off timer, so we need to invalidate the dispatch timer to
-    // prevent firing again.
-    [strongSelf invalidate];
-    block();
-  });
-
-  dispatch_resume(_timer);
-
-  return self;
-}
-
-- (void)dealloc {
-  [self invalidate];
-}
-
-- (void)invalidate {
-  if (self.timer != nil) {
-    dispatch_source_cancel(self.timer);
-  }
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 63
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.h

@@ -1,63 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// Represents possible results of a Firebase App Check token refresh attempt that matter for
-/// `FIRAppCheckTokenRefresher`.
-typedef NS_ENUM(NSInteger, FIRAppCheckTokenRefreshStatus) {
-  // The token has not been refreshed.
-  FIRAppCheckTokenRefreshStatusNever,
-
-  // The token was successfully refreshed.
-  FIRAppCheckTokenRefreshStatusSuccess,
-
-  // The token refresh failed.
-  FIRAppCheckTokenRefreshStatusFailure
-};
-
-/// An object to pass the possible results of a Firebase App Check token refresh attempt and
-/// supplementary data.
-@interface FIRAppCheckTokenRefreshResult : NSObject
-
-/// Status of the refresh.
-@property(nonatomic, readonly) FIRAppCheckTokenRefreshStatus status;
-
-/// A date when the new Firebase App Check token is expiring.
-@property(nonatomic, readonly, nullable) NSDate *tokenExpirationDate;
-
-/// A date when the new Firebase App Check token was received from the server.
-@property(nonatomic, readonly, nullable) NSDate *tokenReceivedAtDate;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/// Initializes the instance with `FIRAppCheckTokenRefreshStatusNever`.
-- (instancetype)initWithStatusNever;
-
-/// Initializes the instance with `FIRAppCheckTokenRefreshStatusFailure`.
-- (instancetype)initWithStatusFailure;
-
-/// Initializes the instance with `FIRAppCheckTokenRefreshStatusSuccess`.
-/// @param tokenExpirationDate See `tokenExpirationDate` property.
-/// @param tokenReceivedAtDate See `tokenReceivedAtDate` property.
-- (instancetype)initWithStatusSuccessAndExpirationDate:(NSDate *)tokenExpirationDate
-                                        receivedAtDate:(NSDate *)tokenReceivedAtDate;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 64
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.m

@@ -1,64 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FIRAppCheckTokenRefreshResult ()
-
-- (instancetype)initWithStatus:(FIRAppCheckTokenRefreshStatus)status
-                expirationDate:(nullable NSDate *)tokenExpirationDate
-                receivedAtDate:(nullable NSDate *)tokenReceivedAtDate NS_DESIGNATED_INITIALIZER;
-
-@end
-
-@implementation FIRAppCheckTokenRefreshResult
-
-- (instancetype)initWithStatus:(FIRAppCheckTokenRefreshStatus)status
-                expirationDate:(nullable NSDate *)tokenExpirationDate
-                receivedAtDate:(nullable NSDate *)tokenReceivedAtDate {
-  self = [super init];
-  if (self) {
-    _status = status;
-    _tokenExpirationDate = tokenExpirationDate;
-    _tokenReceivedAtDate = tokenReceivedAtDate;
-  }
-  return self;
-}
-
-- (instancetype)initWithStatusNever {
-  return [self initWithStatus:FIRAppCheckTokenRefreshStatusNever
-               expirationDate:nil
-               receivedAtDate:nil];
-}
-
-- (instancetype)initWithStatusFailure {
-  return [self initWithStatus:FIRAppCheckTokenRefreshStatusFailure
-               expirationDate:nil
-               receivedAtDate:nil];
-}
-
-- (instancetype)initWithStatusSuccessAndExpirationDate:(NSDate *)tokenExpirationDate
-                                        receivedAtDate:(NSDate *)tokenReceivedAtDate {
-  return [self initWithStatus:FIRAppCheckTokenRefreshStatusSuccess
-               expirationDate:tokenExpirationDate
-               receivedAtDate:tokenReceivedAtDate];
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 69
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.h

@@ -1,69 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.h"
-
-@protocol FIRAppCheckSettingsProtocol;
-@class FIRAppCheckTokenRefreshResult;
-
-NS_ASSUME_NONNULL_BEGIN
-
-/** The block to be called on the token refresh completion.
- *  @param refreshResult The refresh result.
- */
-typedef void (^FIRAppCheckTokenRefreshCompletion)(FIRAppCheckTokenRefreshResult *refreshResult);
-
-/** The block that will be called by `FIRAppCheckTokenRefresher` to trigger the token refresh.
- *  @param completion The block that the client must call when the token refresh was completed.
- */
-typedef void (^FIRAppCheckTokenRefreshBlock)(FIRAppCheckTokenRefreshCompletion completion);
-
-@protocol FIRAppCheckTokenRefresherProtocol <NSObject>
-
-/// The block to be called when refresh is needed. The client is responsible for actual token
-/// refresh in the block.
-@property(nonatomic, copy) FIRAppCheckTokenRefreshBlock tokenRefreshHandler;
-
-/// Updates the next refresh date based on the new token expiration date. This method should be
-/// called when the token update was initiated not by the refresher.
-/// @param refreshResult A result of a refresh attempt.
-- (void)updateWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult;
-
-@end
-
-/// The class calls `tokenRefreshHandler` periodically to keep FAC token fresh to reduce FAC token
-/// exchange overhead for product requests.
-@interface FIRAppCheckTokenRefresher : NSObject <FIRAppCheckTokenRefresherProtocol>
-
-- (instancetype)init NS_UNAVAILABLE;
-
-/// The designated initializer.
-/// @param refreshResult A previous token refresh attempt result.
-/// @param settings An object that handles Firebase app check settings.
-- (instancetype)initWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult
-                        timerProvider:(FIRTimerProvider)timerProvider
-                             settings:(id<FIRAppCheckSettingsProtocol>)settings
-    NS_DESIGNATED_INITIALIZER;
-
-/// A convenience initializer with a timer provider returning an instance of  `FIRAppCheckTimer`.
-- (instancetype)initWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult
-                             settings:(id<FIRAppCheckSettingsProtocol>)settings;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 215
FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.m

@@ -1,215 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefresher.h"
-
-#import "FirebaseAppCheck/Sources/Core/FIRAppCheckSettings.h"
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTimer.h"
-#import "FirebaseAppCheck/Sources/Core/TokenRefresh/FIRAppCheckTokenRefreshResult.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-static const NSTimeInterval kInitialBackoffTimeInterval = 30;
-static const NSTimeInterval kMaximumBackoffTimeInterval = 16 * 60;
-
-static const NSTimeInterval kMinimumAutoRefreshTimeInterval = 60;  // 1 min.
-
-/// How much time in advance to auto-refresh token before it's expiration. E.g. 0.5 means that the
-/// token will be refreshed half way through it's intended time to live.
-static const double kAutoRefreshFraction = 0.5;
-
-@interface FIRAppCheckTokenRefresher ()
-
-@property(nonatomic, readonly) dispatch_queue_t refreshQueue;
-
-@property(nonatomic, readonly) id<FIRAppCheckSettingsProtocol> settings;
-
-@property(nonatomic, readonly) FIRTimerProvider timerProvider;
-@property(atomic, nullable) id<FIRAppCheckTimerProtocol> timer;
-@property(atomic) NSUInteger retryCount;
-
-/// Initial refresh result to be used when `tokenRefreshHandler` has been sent.
-@property(nonatomic, nullable) FIRAppCheckTokenRefreshResult *initialRefreshResult;
-
-@end
-
-@implementation FIRAppCheckTokenRefresher
-
-@synthesize tokenRefreshHandler = _tokenRefreshHandler;
-
-- (instancetype)initWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult
-                        timerProvider:(FIRTimerProvider)timerProvider
-                             settings:(id<FIRAppCheckSettingsProtocol>)settings {
-  self = [super init];
-  if (self) {
-    _refreshQueue =
-        dispatch_queue_create("com.firebase.FIRAppCheckTokenRefresher", DISPATCH_QUEUE_SERIAL);
-    _initialRefreshResult = refreshResult;
-    _timerProvider = timerProvider;
-    _settings = settings;
-  }
-  return self;
-}
-
-- (instancetype)initWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult
-                             settings:(id<FIRAppCheckSettingsProtocol>)settings {
-  return [self initWithRefreshResult:refreshResult
-                       timerProvider:[FIRAppCheckTimer timerProvider]
-                            settings:settings];
-}
-
-- (void)dealloc {
-  [self cancelTimer];
-}
-
-- (void)setTokenRefreshHandler:(FIRAppCheckTokenRefreshBlock)tokenRefreshHandler {
-  @synchronized(self) {
-    _tokenRefreshHandler = tokenRefreshHandler;
-
-    // Check if handler is being set for the first time and if yes then schedule first refresh.
-    if (tokenRefreshHandler && self.initialRefreshResult) {
-      FIRAppCheckTokenRefreshResult *initialTokenRefreshResult = self.initialRefreshResult;
-      self.initialRefreshResult = nil;
-      [self scheduleWithTokenRefreshResult:initialTokenRefreshResult];
-    }
-  }
-}
-
-- (FIRAppCheckTokenRefreshBlock)tokenRefreshHandler {
-  @synchronized(self) {
-    return _tokenRefreshHandler;
-  }
-}
-
-- (void)updateWithRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult {
-  switch (refreshResult.status) {
-    case FIRAppCheckTokenRefreshStatusNever:
-    case FIRAppCheckTokenRefreshStatusSuccess:
-      self.retryCount = 0;
-      break;
-
-    case FIRAppCheckTokenRefreshStatusFailure:
-      self.retryCount += 1;
-      break;
-  }
-
-  [self scheduleWithTokenRefreshResult:refreshResult];
-}
-
-- (void)refresh {
-  if (self.tokenRefreshHandler == nil) {
-    return;
-  }
-
-  if (!self.settings.isTokenAutoRefreshEnabled) {
-    return;
-  }
-
-  __auto_type __weak weakSelf = self;
-  self.tokenRefreshHandler(^(FIRAppCheckTokenRefreshResult *refreshResult) {
-    __auto_type strongSelf = weakSelf;
-    [strongSelf updateWithRefreshResult:refreshResult];
-  });
-}
-
-- (void)scheduleWithTokenRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult {
-  // Schedule the refresh only when allowed.
-  if (self.settings.isTokenAutoRefreshEnabled) {
-    NSDate *refreshDate = [self nextRefreshDateWithTokenRefreshResult:refreshResult];
-    [self scheduleRefreshAtDate:refreshDate];
-  }
-}
-
-- (void)scheduleRefreshAtDate:(NSDate *)refreshDate {
-  [self cancelTimer];
-
-  NSTimeInterval scheduleInSec = [refreshDate timeIntervalSinceNow];
-
-  __auto_type __weak weakSelf = self;
-  dispatch_block_t refreshHandler = ^{
-    __auto_type strongSelf = weakSelf;
-    [strongSelf refresh];
-  };
-
-  // Refresh straight away if the refresh time is too close.
-  if (scheduleInSec <= 0) {
-    dispatch_async(self.refreshQueue, refreshHandler);
-    return;
-  }
-
-  self.timer = self.timerProvider(refreshDate, self.refreshQueue, refreshHandler);
-}
-
-- (void)cancelTimer {
-  [self.timer invalidate];
-}
-
-- (NSDate *)nextRefreshDateWithTokenRefreshResult:(FIRAppCheckTokenRefreshResult *)refreshResult {
-  switch (refreshResult.status) {
-    case FIRAppCheckTokenRefreshStatusSuccess: {
-      NSTimeInterval timeToLive = [refreshResult.tokenExpirationDate
-          timeIntervalSinceDate:refreshResult.tokenReceivedAtDate];
-      timeToLive = MAX(timeToLive, 0);
-
-      // Refresh in 50% of TTL + 5 min.
-      NSTimeInterval targetRefreshSinceReceivedDate = timeToLive * kAutoRefreshFraction + 5 * 60;
-      NSDate *targetRefreshDate = [refreshResult.tokenReceivedAtDate
-          dateByAddingTimeInterval:targetRefreshSinceReceivedDate];
-
-      // Don't schedule later than expiration date.
-      NSDate *refreshDate = [targetRefreshDate earlierDate:refreshResult.tokenExpirationDate];
-
-      // Don't schedule a refresh earlier than in 1 min from now.
-      if ([refreshDate timeIntervalSinceNow] < kMinimumAutoRefreshTimeInterval) {
-        refreshDate = [NSDate dateWithTimeIntervalSinceNow:kMinimumAutoRefreshTimeInterval];
-      }
-      return refreshDate;
-    } break;
-
-    case FIRAppCheckTokenRefreshStatusFailure: {
-      // Repeat refresh attempt later.
-      NSTimeInterval backoffTime = [[self class] backoffTimeForRetryCount:self.retryCount];
-      return [NSDate dateWithTimeIntervalSinceNow:backoffTime];
-    } break;
-
-    case FIRAppCheckTokenRefreshStatusNever:
-      // Refresh ASAP.
-      return [NSDate date];
-      break;
-  }
-}
-
-#pragma mark - Backoff
-
-+ (NSTimeInterval)backoffTimeForRetryCount:(NSInteger)retryCount {
-  if (retryCount == 0) {
-    // No backoff for the first attempt.
-    return 0;
-  }
-
-  NSTimeInterval exponentialInterval =
-      kInitialBackoffTimeInterval * pow(2, retryCount - 1) + [self randomMilliseconds];
-  return MIN(exponentialInterval, kMaximumBackoffTimeInterval);
-}
-
-+ (NSTimeInterval)randomMilliseconds {
-  int32_t random_millis = ABS(arc4random() % 1000);
-  return (double)random_millis * 0.001;
-}
-
-@end
-
-NS_ASSUME_NONNULL_END

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.