From bb29366ee2c1301657e70c529fc6d7e8786fe411 Mon Sep 17 00:00:00 2001 From: Sam Odom Date: Thu, 23 Jun 2022 13:40:22 -0700 Subject: [PATCH] Make InfoDictionaryProviding protocol less likely to produce conflicts Summary: The NSBundle basis for this protocol creates a risk of conflict if we make any of the referenced symbols more abstract Reviewed By: joesus Differential Revision: D37358716 fbshipit-source-id: 2ca5885075e89bddbab664a1e6b785772577f6cd --- .../AppLink/FBSDKAppLinkUtility.m | 2 +- .../FBSDKCoreKit/FBSDKInternalUtility.m | 4 +- FBSDKCoreKit/FBSDKCoreKit/FBSDKSettings.m | 16 ++--- .../FBSDKBridgeAPIProtocolWebV2.m | 2 +- .../Internal/FBSDKBackgroundEventLogger.m | 2 +- .../BridgeAPIProtocolWebV2Tests.swift | 4 +- .../Internal/InternalUtilityTests.swift | 2 +- .../FBSDKCoreKit_Basics/FBSDKCrashHandler.m | 6 +- .../NSBundle+FBSDKInfoDictionaryProviding.m | 32 ++++++++++ .../include/FBSDKCoreKit_Basics.h | 1 - .../include/FBSDKInfoDictionaryProviding.h | 12 +++- .../NSBundle+InfoDictionaryProviding.h | 19 ------ .../BundleTests.swift | 60 +++++++++++++++++++ TestTools/TestTools/TestBundle.swift | 10 ++-- 14 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/NSBundle+FBSDKInfoDictionaryProviding.m delete mode 100644 FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/NSBundle+InfoDictionaryProviding.h create mode 100644 FBSDKCoreKit_Basics/FBSDKCoreKit_BasicsTests/BundleTests.swift diff --git a/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m b/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m index 264769fa3..55da609d1 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m +++ b/FBSDKCoreKit/FBSDKCoreKit/AppLink/FBSDKAppLinkUtility.m @@ -285,7 +285,7 @@ static BOOL _isConfigured = NO; return NO; } [self validateConfiguration]; - for (NSDictionary *urlType in [self.infoDictionaryProvider objectForInfoDictionaryKey:@"CFBundleURLTypes"]) { + for (NSDictionary *urlType in [self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"CFBundleURLTypes"]) { for (NSString *urlScheme in urlType[@"CFBundleURLSchemes"]) { if ([urlScheme caseInsensitiveCompare:scheme] == NSOrderedSame) { return YES; diff --git a/FBSDKCoreKit/FBSDKCoreKit/FBSDKInternalUtility.m b/FBSDKCoreKit/FBSDKCoreKit/FBSDKInternalUtility.m index 45d73e578..b5f4969df 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/FBSDKInternalUtility.m +++ b/FBSDKCoreKit/FBSDKCoreKit/FBSDKInternalUtility.m @@ -600,7 +600,7 @@ static NSMapTable *_transientObjects; static NSArray *> *urlTypes = nil; dispatch_once(&fetchUrlSchemesToken, ^{ - urlTypes = [self.infoDictionaryProvider.infoDictionary valueForKey:@"CFBundleURLTypes"]; + urlTypes = [self.infoDictionaryProvider.fb_infoDictionary valueForKey:@"CFBundleURLTypes"]; }); for (NSDictionary *urlType in urlTypes) { NSArray *urlSchemes = [urlType valueForKey:@"CFBundleURLSchemes"]; @@ -637,7 +637,7 @@ static NSMapTable *_transientObjects; { static NSArray *schemes = nil; dispatch_once(&fetchApplicationQuerySchemesToken, ^{ - schemes = [self.infoDictionaryProvider.infoDictionary valueForKey:@"LSApplicationQueriesSchemes"]; + schemes = [self.infoDictionaryProvider.fb_infoDictionary valueForKey:@"LSApplicationQueriesSchemes"]; }); return [schemes containsObject:urlScheme]; diff --git a/FBSDKCoreKit/FBSDKCoreKit/FBSDKSettings.m b/FBSDKCoreKit/FBSDKCoreKit/FBSDKSettings.m index b1051e8c2..9f4b4c46c 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/FBSDKSettings.m +++ b/FBSDKCoreKit/FBSDKCoreKit/FBSDKSettings.m @@ -33,7 +33,7 @@ _ ## PROPERTY_NAME = [[self.store objectForKey:@#PLIST_KEY] copy]; \ } \ if (_ ## PROPERTY_NAME == nil) { \ - _ ## PROPERTY_NAME = [[self.infoDictionaryProvider objectForInfoDictionaryKey:@#PLIST_KEY] copy] ?: DEFAULT_VALUE; \ + _ ## PROPERTY_NAME = [[self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@#PLIST_KEY] copy] ?: DEFAULT_VALUE; \ } \ return _ ## PROPERTY_NAME; \ } \ @@ -186,7 +186,7 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( - (NSString *)appID { if (!_appID) { - _appID = [[self.infoDictionaryProvider objectForInfoDictionaryKey:@"FacebookAppID"] copy] ?: nil; + _appID = [[self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"FacebookAppID"] copy] ?: nil; } return _appID; } @@ -201,7 +201,7 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( - (CGFloat)JPEGCompressionQuality { if (!_JPEGCompressionQuality) { - NSNumber *compressionQuality = [self.infoDictionaryProvider objectForInfoDictionaryKey:@"FacebookJpegCompressionQuality"]; + NSNumber *compressionQuality = [self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"FacebookJpegCompressionQuality"]; _JPEGCompressionQuality = [self _validateJPEGCompressionQuality:compressionQuality.floatValue ?: 0.9]; } return _JPEGCompressionQuality; @@ -287,7 +287,7 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( } if (_SKAdNetworkReportEnabled == nil) { - _SKAdNetworkReportEnabled = [[self.infoDictionaryProvider objectForInfoDictionaryKey:FacebookSKAdNetworkReportEnabled] copy] ?: @(1); + _SKAdNetworkReportEnabled = [[self.infoDictionaryProvider fb_objectForInfoDictionaryKey:FacebookSKAdNetworkReportEnabled] copy] ?: @(1); } return _SKAdNetworkReportEnabled.boolValue; @@ -360,7 +360,7 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( - (NSSet *)loggingBehaviors { if (!_loggingBehaviors) { - NSArray *bundleLoggingBehaviors = [self.infoDictionaryProvider objectForInfoDictionaryKey:@"FacebookLoggingBehavior"]; + NSArray *bundleLoggingBehaviors = [self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"FacebookLoggingBehavior"]; if (bundleLoggingBehaviors) { _loggingBehaviors = [[NSMutableSet alloc] initWithArray:bundleLoggingBehaviors]; } else { @@ -475,10 +475,10 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( - (void)logWarnings { // Log warnings for App Event Flags - if (![self.infoDictionaryProvider objectForInfoDictionaryKey:@"FacebookAutoLogAppEventsEnabled"]) { + if (![self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"FacebookAutoLogAppEventsEnabled"]) { NSLog(autoLogAppEventsEnabledNotSetWarning); } - if (![self.infoDictionaryProvider objectForInfoDictionaryKey:@"FacebookAdvertiserIDCollectionEnabled"]) { + if (![self.infoDictionaryProvider fb_objectForInfoDictionaryKey:@"FacebookAdvertiserIDCollectionEnabled"]) { NSLog(advertiserIDCollectionEnabledNotSetWarning); } if (!self._advertiserIDCollectionEnabled.boolValue) { @@ -504,7 +504,7 @@ FBSDKSETTINGS_PLIST_CONFIGURATION_SETTING_IMPL( NSInteger initialBitmask = 0; NSInteger usageBitmask = 0; for (int i = 0; i < keys.count; i++) { - NSNumber *plistValue = [self.infoDictionaryProvider objectForInfoDictionaryKey:[FBSDKTypeUtility array:keys objectAtIndex:i]]; + NSNumber *plistValue = [self.infoDictionaryProvider fb_objectForInfoDictionaryKey:[FBSDKTypeUtility array:keys objectAtIndex:i]]; BOOL initialValue = [(plistValue ?: [FBSDKTypeUtility array:defaultValues objectAtIndex:i]) boolValue]; initialBitmask |= (initialValue ? 1 : 0) << i; usageBitmask |= (plistValue != nil ? 1 : 0) << i; diff --git a/FBSDKCoreKit/FBSDKCoreKit/Internal/BridgeAPI/ProtocolVersions/FBSDKBridgeAPIProtocolWebV2.m b/FBSDKCoreKit/FBSDKCoreKit/Internal/BridgeAPI/ProtocolVersions/FBSDKBridgeAPIProtocolWebV2.m index fd8c88a56..06c37e1ef 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/Internal/BridgeAPI/ProtocolVersions/FBSDKBridgeAPIProtocolWebV2.m +++ b/FBSDKCoreKit/FBSDKCoreKit/Internal/BridgeAPI/ProtocolVersions/FBSDKBridgeAPIProtocolWebV2.m @@ -121,7 +121,7 @@ } NSMutableDictionary *queryParameters = [[FBSDKBasicUtility dictionaryWithQueryString:requestURL.query] mutableCopy]; - [FBSDKTypeUtility dictionary:queryParameters setObject:self.infoDictionaryProvider.bundleIdentifier forKey:@"ios_bundle_id"]; + [FBSDKTypeUtility dictionary:queryParameters setObject:self.infoDictionaryProvider.fb_bundleIdentifier forKey:@"ios_bundle_id"]; [FBSDKTypeUtility dictionary:queryParameters setObject:redirectURL.absoluteString forKey:@"redirect_url"]; return [self.internalUtility URLWithScheme:requestURL.scheme diff --git a/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKBackgroundEventLogger.m b/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKBackgroundEventLogger.m index 6399ae824..2630c342f 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKBackgroundEventLogger.m +++ b/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKBackgroundEventLogger.m @@ -55,7 +55,7 @@ - (BOOL)_isNewBackgroundRefresh { - if ([_infoDictionaryProvider objectForInfoDictionaryKey:@"BGTaskSchedulerPermittedIdentifiers"]) { + if ([_infoDictionaryProvider fb_objectForInfoDictionaryKey:@"BGTaskSchedulerPermittedIdentifiers"]) { return YES; } return NO; diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/BridgeAPI/ProtocolVersions/BridgeAPIProtocolWebV2Tests.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/BridgeAPI/ProtocolVersions/BridgeAPIProtocolWebV2Tests.swift index ae35dfb58..4aecb031b 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/BridgeAPI/ProtocolVersions/BridgeAPIProtocolWebV2Tests.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/BridgeAPI/ProtocolVersions/BridgeAPIProtocolWebV2Tests.swift @@ -46,7 +46,7 @@ final class BridgeAPIProtocolWebV2Tests: XCTestCase { errorFactory = TestErrorFactory() internalUtility = TestInternalUtility() bundle = TestBundle() - bundle.bundleIdentifier = Values.bundleIdentifier + bundle.fb_bundleIdentifier = Values.bundleIdentifier bridge = BridgeAPIProtocolWebV2( serverConfigurationProvider: serverConfigurationProvider, nativeBridge: nativeBridge, @@ -218,7 +218,7 @@ final class BridgeAPIProtocolWebV2Tests: XCTestCase { XCTAssertEqual( queryParameters[Keys.iosBundleID], - bundle.bundleIdentifier, + bundle.fb_bundleIdentifier, "Should add the bundle ID to the query parameters" ) XCTAssertEqual( diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/InternalUtilityTests.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/InternalUtilityTests.swift index 4f9552ef1..b94a9b7f0 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/InternalUtilityTests.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/InternalUtilityTests.swift @@ -719,7 +719,7 @@ final class InternalUtilityTests: XCTestCase { XCTAssertTrue(internalUtility.isRegisteredCanOpenURLScheme(name), "Sanity check") - bundle.infoDictionary = [:] + bundle.fb_infoDictionary = [:] XCTAssertTrue( internalUtility.isRegisteredCanOpenURLScheme(name), diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/FBSDKCrashHandler.m b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/FBSDKCrashHandler.m index e5fb4e5e5..a2254057b 100644 --- a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/FBSDKCrashHandler.m +++ b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/FBSDKCrashHandler.m @@ -15,9 +15,9 @@ #import "FBSDKCrashObserving.h" #import "FBSDKFileDataExtracting.h" #import "FBSDKFileManaging.h" +#import "FBSDKInfoDictionaryProviding.h" #import "FBSDKLibAnalyzer.h" #import "FBSDKTypeUtility.h" -#import "NSBundle+InfoDictionaryProviding.h" #define FBSDK_MAX_CRASH_LOGS 5 #define FBSDK_CRASH_PATH_NAME @"instrument" @@ -289,8 +289,8 @@ static void FBSDKExceptionHandler(NSException *exception) [FBSDKTypeUtility dictionary:completeCrashLog setObject:currentTimestamp forKey:kFBSDKCrashTimestamp]; [FBSDKTypeUtility dictionary:completeCrashLog setObject:mappingTableIdentifier forKey:kFBSDKMappingTableIdentifier]; - NSString *version = [self.bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; - NSString *build = [self.bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + NSString *version = [self.bundle fb_objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + NSString *build = [self.bundle fb_objectForInfoDictionaryKey:@"CFBundleVersion"]; [FBSDKTypeUtility dictionary:completeCrashLog setObject:[NSString stringWithFormat:@"%@(%@)", version, build] forKey:kFBSDKAppVersion]; struct utsname systemInfo; diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/NSBundle+FBSDKInfoDictionaryProviding.m b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/NSBundle+FBSDKInfoDictionaryProviding.m new file mode 100644 index 000000000..ab0d721fe --- /dev/null +++ b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/NSBundle+FBSDKInfoDictionaryProviding.m @@ -0,0 +1,32 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSBundle (InfoDictionaryProviding) + +- (nullable NSDictionary *)fb_infoDictionary +{ + return self.infoDictionary; +} + +- (nullable NSString *)fb_bundleIdentifier +{ + return self.bundleIdentifier; +} + +- (nullable id)fb_objectForInfoDictionaryKey:(nonnull NSString *)key +{ + return [self objectForInfoDictionaryKey:key]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKCoreKit_Basics.h b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKCoreKit_Basics.h index 64798ce7e..277058a9c 100644 --- a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKCoreKit_Basics.h +++ b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKCoreKit_Basics.h @@ -20,6 +20,5 @@ #import #import #import -#import #import #import diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKInfoDictionaryProviding.h b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKInfoDictionaryProviding.h index f52440515..346b5c5bb 100644 --- a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKInfoDictionaryProviding.h +++ b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/FBSDKInfoDictionaryProviding.h @@ -10,13 +10,19 @@ NS_ASSUME_NONNULL_BEGIN +/// An internal protocol used for accessing bundles NS_SWIFT_NAME(InfoDictionaryProviding) @protocol FBSDKInfoDictionaryProviding -@property (nullable, readonly, copy) NSDictionary *infoDictionary; -@property (nullable, readonly, copy) NSString *bundleIdentifier; +@property (nullable, readonly, copy) NSDictionary *fb_infoDictionary; +@property (nullable, readonly, copy) NSString *fb_bundleIdentifier; -- (nullable id)objectForInfoDictionaryKey:(NSString *)key; +- (nullable id)fb_objectForInfoDictionaryKey:(NSString *)key +NS_SWIFT_NAME(fb_object(forInfoDictionaryKey:)); + +@end + +@interface NSBundle (InfoDictionaryProviding) @end diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/NSBundle+InfoDictionaryProviding.h b/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/NSBundle+InfoDictionaryProviding.h deleted file mode 100644 index a75e146c9..000000000 --- a/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics/include/NSBundle+InfoDictionaryProviding.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -/// Default conformance to the info dictionary providing protocol -@interface NSBundle (InfoDictionaryProviding) -@end - -NS_ASSUME_NONNULL_END diff --git a/FBSDKCoreKit_Basics/FBSDKCoreKit_BasicsTests/BundleTests.swift b/FBSDKCoreKit_Basics/FBSDKCoreKit_BasicsTests/BundleTests.swift new file mode 100644 index 000000000..d4938f7ae --- /dev/null +++ b/FBSDKCoreKit_Basics/FBSDKCoreKit_BasicsTests/BundleTests.swift @@ -0,0 +1,60 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBSDKCoreKit_Basics +import XCTest + +final class BundleTests: XCTestCase { + + // swiftlint:disable:next implicitly_unwrapped_optional + var bundle: Bundle! + + override func setUp() { + super.setUp() + bundle = Bundle(for: BundleTests.self) + } + + override func tearDown() { + bundle = nil + super.tearDown() + } + + func testInfoDictionary() throws { + let expected = try XCTUnwrap(bundle.infoDictionary) + let actual = try XCTUnwrap(bundle.fb_infoDictionary, .infoDictionary) + + XCTAssertEqual( + Set(actual.keys), + Set(expected.keys), + .infoDictionary + ) + } + + func testBundleIdentifier() throws { + let bundleIdentifier = try XCTUnwrap(bundle.fb_bundleIdentifier, .bundleIdentifier) + XCTAssertEqual(bundleIdentifier, bundle.bundleIdentifier, .bundleIdentifier) + } + + func testIndexingInfoDictionary() throws { + let expected = try XCTUnwrap(bundle.infoDictionary?[kCFBundleNameKey as String] as? String) + + XCTAssertEqual( + bundle.fb_object(forInfoDictionaryKey: kCFBundleNameKey as String) as? String, + expected, + .infoDictionaryIndexing + ) + } +} + +// MARK: - Assumptions + +fileprivate extension String { + static let infoDictionary = "An info dictionary is provided through an internal abstraction" + static let bundleIdentifier = "A bundle identifier is provided through an internal abstraction" + static let infoDictionaryIndexing = "An info dictionary is indexed through an internal abstraction" +} diff --git a/TestTools/TestTools/TestBundle.swift b/TestTools/TestTools/TestBundle.swift index ff2a1d777..714ce120c 100644 --- a/TestTools/TestTools/TestBundle.swift +++ b/TestTools/TestTools/TestBundle.swift @@ -17,7 +17,8 @@ public final class TestBundle: NSObject, InfoDictionaryProviding { public var capturedKeys = [String]() public var didAccessInfoDictionary = false - public var infoDictionary: [String: Any]? { + // swiftlint:disable:next identifier_name + public var fb_infoDictionary: [String: Any]? { get { didAccessInfoDictionary = true return stubbedInfoDictionary @@ -35,12 +36,13 @@ public final class TestBundle: NSObject, InfoDictionaryProviding { stubbedInfoDictionary = infoDictionary } - public var bundleIdentifier: String? + // swiftlint:disable:next identifier_name + public var fb_bundleIdentifier: String? - public func object(forInfoDictionaryKey key: String) -> Any? { + public func fb_object(forInfoDictionaryKey key: String) -> Any? { lastCapturedKey = key capturedKeys.append(key) - return infoDictionary?[key] as Any? + return fb_infoDictionary?[key] as Any? } public func reset() {