Skip to content

Commit 06b5a2f

Browse files
committed
Merge remote-tracking branch 'origin/master' into snappy2
2 parents 70aa8b8 + 2e53f23 commit 06b5a2f

File tree

92 files changed

+3536
-855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+3536
-855
lines changed

.github/workflows/remoteconfig.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
- '.github/workflows/remoteconfig.yml'
99
- 'Gemfile*'
1010
- 'scripts/generate_access_token.sh'
11+
- 'scripts/gha-encrypted/RemoteConfigSwiftAPI/**'
1112
schedule:
1213
# Run every day at 12am (PST) - cron uses UTC times
1314
- cron: '0 8 * * *'

AddNewPod.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ For top-level Firebase pods that map to documented products:
7676
[FIRApp.m](FirebaseCore/Sources/FIRApp.m).
7777
* When ready to release with Firebase, add to the
7878
[Firebase manifest](ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift).
79+
* Create an empty JSON file to enable the Carthage build
80+
[here](ReleaseTooling/Sources/CarthageJSON).
7981
* Add a [quickstart](https://github.com/firebase/quickstart-ios).
8082

8183
## Review and Release

FirebaseAnalytics.podspec.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"z"
2323
],
2424
"license": {
25-
"text": "Copyright 2021 Google",
25+
"text": "Copyright 2022 Google",
2626
"type": "Copyright"
2727
},
2828
"name": "FirebaseAnalytics",
@@ -32,7 +32,7 @@
3232
"tvos": "12.0"
3333
},
3434
"source": {
35-
"http": "https://dl.google.com/firebase/ios/analytics/dcdcf15b4c4831d9/FirebaseAnalytics-8.15.0.tar.gz"
35+
"http": "https://dl.google.com/firebase/ios/analytics/a596b932b0fcdc4b/FirebaseAnalytics-9.0.0.tar.gz"
3636
},
3737
"subspecs": [
3838
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"authors": "Google, Inc.",
3+
"cocoapods_version": ">= 1.10.2",
4+
"dependencies": {
5+
"GoogleAppMeasurementOnDeviceConversion": "9.0.0"
6+
},
7+
"description": "On device conversion measurement plugin for FirebaseAnalytics. This pod does not expose any headers and isn't intended for direct use, but rather as a plugin of FirebaseAnalytics.",
8+
"homepage": "https://firebase.google.com/features/analytics/",
9+
"license": {
10+
"text": "Copyright 2022 Google",
11+
"type": "Copyright"
12+
},
13+
"name": "FirebaseAnalyticsOnDeviceConversion",
14+
"platforms": {
15+
"ios": "10.0"
16+
},
17+
"source": {
18+
"git": "https://github.com/firebase/firebase-ios-sdk.git",
19+
"tag": "CocoaPods-9.0.0"
20+
},
21+
"source_files": [ "FirebaseAnalyticsOnDeviceConversionWrapper/*" ],
22+
"static_framework": true,
23+
"summary": "On device conversion measurement plugin for FirebaseAnalytics. Not intended for direct use.",
24+
"version": "9.0.0"
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// Swift Package Manager needs at least one source file.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// Swift Package Manager needs at least one header to prevent a warning. See
18+
// https://github.com/firebase/firebase-ios-sdk/pull/6504.

FirebaseAppCheck.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Pod::Spec.new do |s|
4646
s.tvos.weak_framework = 'DeviceCheck'
4747

4848
s.dependency 'FirebaseCore', '~> 9.0'
49-
s.dependency 'PromisesObjC', '~> 2.0'
49+
s.dependency 'PromisesObjC', '~> 2.1'
5050
s.dependency 'GoogleUtilities/Environment', '~> 7.7'
5151

5252
s.pod_target_xcconfig = {

FirebaseAppDistribution.podspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,4 @@ iOS SDK for App Distribution for Firebase.
5151
unit_tests.dependency 'OCMock'
5252
end
5353

54-
# end
5554
end

FirebaseAuth.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ supports email and password accounts, as well as several 3rd party authenticatio
5454
s.dependency 'FirebaseCore', '~> 9.0'
5555
s.dependency 'GoogleUtilities/AppDelegateSwizzler', '~> 7.7'
5656
s.dependency 'GoogleUtilities/Environment', '~> 7.7'
57-
s.dependency 'GTMSessionFetcher/Core', '~> 1.5'
57+
s.dependency 'GTMSessionFetcher/Core', '~> 1.7'
5858

5959
# Using environment variable because of the dependency on the unpublished
6060
# HeartbeatLoggingTestUtils.

FirebaseAuth/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# v9.0.0
22
- [fixed] **Breaking change:** Fixed an ObjC-to-Swift API conversion error where `getStoredUser(forAccessGroup:)` returned a non-optional type. This change is breaking for Swift users only (#8599).
3+
- [fixed] Fixed an iOS 15 keychain access issue related to prewarming. (#8695)
34

45
# v8.14.0
56
- [added] Started to collect the Firebase user agent for Firebase Auth. (#9066)

FirebaseAuth/Sources/Auth/FIRAuth.m

Lines changed: 96 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ @implementation FIRAuth {
420420
UIApplicationDidEnterBackgroundNotification.
421421
*/
422422
id<NSObject> _applicationDidEnterBackgroundObserver;
423+
424+
/** @var _protectedDataDidBecomeAvailableObserver
425+
@brief An opaque object to act as the observer for
426+
UIApplicationProtectedDataDidBecomeAvailable.
427+
*/
428+
id<NSObject> _protectedDataDidBecomeAvailableObserver;
423429
}
424430

425431
+ (void)load {
@@ -485,65 +491,107 @@ - (nullable instancetype)initWithAPIKey:(NSString *)APIKey
485491
_firebaseAppName = [appName copy];
486492
#if TARGET_OS_IOS
487493
_settings = [[FIRAuthSettings alloc] init];
494+
495+
[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods];
496+
[GULSceneDelegateSwizzler proxyOriginalSceneDelegate];
497+
#endif // TARGET_OS_IOS
498+
499+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
488500
static Class applicationClass = nil;
489501
// iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication
490502
// responds to it.
491503
if (![GULAppEnvironmentUtil isAppExtension]) {
492504
Class cls = NSClassFromString(@"UIApplication");
493-
if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) {
505+
if (cls && [cls respondsToSelector:@selector(sharedApplication)]) {
494506
applicationClass = cls;
495507
}
496508
}
497509
UIApplication *application = [applicationClass sharedApplication];
498-
499-
[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods];
500-
[GULSceneDelegateSwizzler proxyOriginalSceneDelegate];
501-
#endif // TARGET_OS_IOS
502-
503-
// Continue with the rest of initialization in the work thread.
504-
__weak FIRAuth *weakSelf = self;
505-
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
506-
// Load current user from Keychain.
507-
FIRAuth *strongSelf = weakSelf;
508-
if (!strongSelf) {
509-
return;
510-
}
511-
NSString *keychainServiceName =
512-
[FIRAuth keychainServiceNameForAppName:strongSelf->_firebaseAppName];
513-
if (keychainServiceName) {
514-
strongSelf->_keychainServices =
515-
[[FIRAuthKeychainServices alloc] initWithService:keychainServiceName];
516-
strongSelf.storedUserManager =
517-
[[FIRAuthStoredUserManager alloc] initWithServiceName:keychainServiceName];
510+
if ([application respondsToSelector:@selector(isProtectedDataAvailable)]) {
511+
if ([application isProtectedDataAvailable]) {
512+
[self protectedDataInitialization];
513+
} else {
514+
// Add listener for UIApplicationProtectedDataDidBecomeAvailable.
515+
self->_protectedDataDidBecomeAvailableObserver = [[NSNotificationCenter defaultCenter]
516+
addObserverForName:UIApplicationProtectedDataDidBecomeAvailable
517+
object:nil
518+
queue:nil
519+
usingBlock:^(NSNotification *notification) {
520+
[self protectedDataInitialization];
521+
}];
518522
}
523+
} else {
524+
[self protectedDataInitialization];
525+
}
526+
#else
527+
[self protectedDataInitialization];
528+
#endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
529+
}
530+
return self;
531+
}
519532

520-
NSError *error;
521-
NSString *storedUserAccessGroup =
522-
[strongSelf.storedUserManager getStoredUserAccessGroupWithError:&error];
523-
if (!error) {
524-
if (!storedUserAccessGroup) {
525-
FIRUser *user;
526-
if ([strongSelf getUser:&user error:&error]) {
527-
strongSelf.tenantID = user.tenantID;
528-
[strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error];
529-
self->_lastNotifiedUserToken = user.rawAccessToken;
530-
} else {
531-
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
532-
@"Error loading saved user when starting up: %@", error);
533-
}
533+
- (void)protectedDataInitialization {
534+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
535+
[[NSNotificationCenter defaultCenter] removeObserver:_protectedDataDidBecomeAvailableObserver
536+
name:UIApplicationProtectedDataDidBecomeAvailable
537+
object:nil];
538+
#endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
539+
// Continue with the rest of initialization in the work thread.
540+
__weak FIRAuth *weakSelf = self;
541+
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
542+
// Load current user from Keychain.
543+
FIRAuth *strongSelf = weakSelf;
544+
if (!strongSelf) {
545+
return;
546+
}
547+
NSString *keychainServiceName =
548+
[FIRAuth keychainServiceNameForAppName:strongSelf->_firebaseAppName];
549+
if (keychainServiceName) {
550+
strongSelf->_keychainServices =
551+
[[FIRAuthKeychainServices alloc] initWithService:keychainServiceName];
552+
strongSelf.storedUserManager =
553+
[[FIRAuthStoredUserManager alloc] initWithServiceName:keychainServiceName];
554+
}
555+
556+
NSError *error;
557+
NSString *storedUserAccessGroup =
558+
[strongSelf.storedUserManager getStoredUserAccessGroupWithError:&error];
559+
if (!error) {
560+
if (!storedUserAccessGroup) {
561+
FIRUser *user;
562+
if ([strongSelf getUser:&user error:&error]) {
563+
strongSelf.tenantID = user.tenantID;
564+
[strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error];
565+
self->_lastNotifiedUserToken = user.rawAccessToken;
534566
} else {
535-
[strongSelf internalUseUserAccessGroup:storedUserAccessGroup error:&error];
536-
if (error) {
537-
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
538-
@"Error loading saved user when starting up: %@", error);
539-
}
567+
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
568+
@"Error loading saved user when starting up: %@", error);
540569
}
541570
} else {
542-
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
543-
@"Error loading saved user when starting up: %@", error);
571+
[strongSelf internalUseUserAccessGroup:storedUserAccessGroup error:&error];
572+
if (error) {
573+
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
574+
@"Error loading saved user when starting up: %@", error);
575+
}
544576
}
577+
} else {
578+
FIRLogError(kFIRLoggerAuth, @"I-AUT000001", @"Error loading saved user when starting up: %@",
579+
error);
580+
}
545581

546582
#if TARGET_OS_IOS
583+
static Class applicationClass = nil;
584+
// iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication
585+
// responds to it.
586+
if (![GULAppEnvironmentUtil isAppExtension]) {
587+
Class cls = NSClassFromString(@"UIApplication");
588+
if (cls && [cls respondsToSelector:@selector(sharedApplication)]) {
589+
applicationClass = cls;
590+
}
591+
}
592+
UIApplication *application = [applicationClass sharedApplication];
593+
594+
if (application) {
547595
// Initialize for phone number auth.
548596
strongSelf->_tokenManager = [[FIRAuthAPNSTokenManager alloc] initWithApplication:application];
549597

@@ -553,17 +601,16 @@ - (nullable instancetype)initWithAPIKey:(NSString *)APIKey
553601
strongSelf->_notificationManager = [[FIRAuthNotificationManager alloc]
554602
initWithApplication:application
555603
appCredentialManager:strongSelf->_appCredentialManager];
604+
}
556605

557-
[GULAppDelegateSwizzler registerAppDelegateInterceptor:strongSelf];
606+
[GULAppDelegateSwizzler registerAppDelegateInterceptor:strongSelf];
558607
#if ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000))
559-
if (@available(iOS 13, tvos 13, *)) {
560-
[GULSceneDelegateSwizzler registerSceneDelegateInterceptor:strongSelf];
561-
}
608+
if (@available(iOS 13, tvos 13, *)) {
609+
[GULSceneDelegateSwizzler registerSceneDelegateInterceptor:strongSelf];
610+
}
562611
#endif // ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000))
563612
#endif // TARGET_OS_IOS
564-
});
565-
}
566-
return self;
613+
});
567614
}
568615

569616
- (void)dealloc {

FirebaseCore/Internal/Sources/HeartbeatLogging/HeartbeatController.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public final class HeartbeatController {
2222
private let heartbeatsStorageCapacity: Int = 30
2323
/// Current date provider. It is used for testability.
2424
private let dateProvider: () -> Date
25-
// TODO: Maybe share config with HeartbeatsPayload's DateFormatter?
2625
/// Used for standardizing dates for calendar-day comparision.
2726
static let dateStandardizer: (Date) -> (Date) = {
2827
var calendar = Calendar(identifier: .iso8601)

FirebaseCore/Internal/Sources/HeartbeatLogging/HeartbeatStorage.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ final class HeartbeatStorage: HeartbeatStorageProtocol {
9090

9191
// MARK: - HeartbeatStorageProtocol
9292

93-
// TODO: Document.
93+
/// Synchronously reads from and writes to storage using the given transform block.
94+
/// - Parameter transform: A block to transform the currently stored heartbeats bundle to a new
95+
/// heartbeats bundle value.
9496
func readAndWriteSync(using transform: (HeartbeatsBundle?) -> HeartbeatsBundle?) {
9597
queue.sync {
9698
let oldHeartbeatsBundle = try? load(from: storage)

FirebaseCore/Internal/Sources/HeartbeatLogging/StorageFactory.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ extension FileStorage: StorageFactory {
3232
static func makeStorage(id: String) -> Storage {
3333
let rootDirectory = FileManager.default.applicationSupportDirectory
3434
let heartbeatDirectoryPath = Constants.heartbeatFileStorageDirectoryPath
35-
let heartbeatFilePath = "heartbeats-\(id)"
35+
36+
// Sanitize the `id` so the heartbeat file name does not include a ":".
37+
let sanitizedID = id.replacingOccurrences(of: ":", with: "_")
38+
let heartbeatFilePath = "heartbeats-\(sanitizedID)"
3639

3740
let storageURL = rootDirectory
3841
.appendingPathComponent(heartbeatDirectoryPath, isDirectory: true)

FirebaseCore/Internal/Tests/Integration/HeartbeatLoggingIntegrationTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,30 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {
364364
XCTAssertNotNil(try Data(contentsOf: heartbeatsFileURL), "Data should not be nil.")
365365
#endif
366366
}
367+
368+
#if !os(tvOS)
369+
// Do not run on tvOS because tvOS uses UserDefaults to store heartbeats.
370+
func testControllerCreatesHeartbeatStorageWithSanitizedFileName() throws {
371+
// Given
372+
let appID = "1:123456789000:ios:abcdefghijklmnop"
373+
let sanitizedAppID = appID.replacingOccurrences(of: ":", with: "_")
374+
let controller = HeartbeatController(id: appID)
375+
// When
376+
// - Trigger the controller to write to the file system.
377+
controller.log("dummy_agent")
378+
_ = XCTWaiter.wait(for: [expectation(description: "Wait for async log.")], timeout: 0.1)
379+
// Then
380+
let heartbeatsDirectoryURL = FileManager.default
381+
.applicationSupportDirectory
382+
.appendingPathComponent(
383+
HeartbeatLoggingTestUtils.Constants.heartbeatFileStorageDirectoryPath,
384+
isDirectory: true
385+
)
386+
387+
let directoryContents = try FileManager.default
388+
.contentsOfDirectory(atPath: heartbeatsDirectoryURL.path)
389+
390+
XCTAssertEqual(directoryContents, ["heartbeats-\(sanitizedAppID)"])
391+
}
392+
#endif // !os(tvOS)
367393
}

FirebaseCrashlytics.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Pod::Spec.new do |s|
5555

5656
s.dependency 'FirebaseCore', '~> 9.0'
5757
s.dependency 'FirebaseInstallations', '~> 9.0'
58-
s.dependency 'PromisesObjC', '~> 2.0'
58+
s.dependency 'PromisesObjC', '~> 2.1'
5959
s.dependency 'GoogleDataTransport', '~> 9.1'
6060
s.dependency 'GoogleUtilities/Environment', '~> 7.7'
6161
s.dependency 'nanopb', '~> 2.30908.0'

FirebaseDatabase.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Simplify your iOS development, grow your user base, and monetize more effectivel
7878
s.test_spec 'integration' do |int_tests|
7979
int_tests.platforms = {:ios => ios_deployment_target, :osx => osx_deployment_target, :tvos => tvos_deployment_target}
8080
int_tests.scheme = { :code_coverage => true }
81+
int_tests.requires_app_host = true
8182
int_tests.source_files = [
8283
'FirebaseDatabase/Tests/Integration/*.[mh]',
8384
'FirebaseDatabase/Tests/Helpers/*.[mh]',

0 commit comments

Comments
 (0)