Skip to content

Use registerLibrary for pods in Firebase workspace #2137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 13, 2018
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Example/Auth/Tests/FIRAuthTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#import <FirebaseAuthInterop/FIRAuthInterop.h>
#import <FirebaseCore/FIRAppInternal.h>
#import <FirebaseCore/FIRComponent.h>
#import <FirebaseCore/FIRComponentRegistrant.h>
#import <FirebaseCore/FIRLibrary.h>

#import "FIRAdditionalUserInfo.h"
#import "FIRAuth_Internal.h"
Expand Down Expand Up @@ -225,7 +225,7 @@
static const NSTimeInterval kWaitInterval = .5;

/** Category for FIRAuth to expose FIRComponentRegistrant conformance. */
@interface FIRAuth () <FIRComponentRegistrant>
@interface FIRAuth () <FIRLibrary>
@end

/** @class FIRAuthTests
Expand Down
14 changes: 14 additions & 0 deletions Example/Core/Tests/FIRAppTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#import "FIRTestCase.h"
#import "FIRTestComponents.h"

#import <FirebaseCore/FIRAnalyticsConfiguration+Internal.h>
#import <FirebaseCore/FIRAppInternal.h>
Expand Down Expand Up @@ -735,6 +736,19 @@ - (void)testMultipleLibraries {
XCTAssertTrue([[FIRApp firebaseUserAgent] containsString:@"LegalName/1.0.0 LegalName2/2.0.0"]);
}

- (void)testRegisteringConformingLibrary {
Class testClass = [FIRTestClass class];
[FIRApp registerInternalLibrary:testClass withName:@"LegalName" withVersion:@"1.0.0"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance we could replace "Legal/Illegal" with "Valid/Invalid"? The term "Legal Name" has other connotations and may be confusing

XCTAssertTrue([[FIRApp firebaseUserAgent] containsString:@"LegalName/1.0.0"]);
}

- (void)testRegisteringNonConformingLibrary {
XCTAssertThrows([FIRApp registerInternalLibrary:[NSString class]
withName:@"IllegalLibrary"
withVersion:@"1.0.0"]);
XCTAssertFalse([[FIRApp firebaseUserAgent] containsString:@"IllegalLibrary/1.0.0"]);
}

#pragma mark - private

- (void)expectNotificationForObserver:(id)observer
Expand Down
29 changes: 19 additions & 10 deletions Example/Core/Tests/FIRComponentContainerTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,26 @@ @interface FIRComponentContainer (TestInternal)
@property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
@property(nonatomic, strong) NSMutableDictionary<NSString *, id> *cachedInstances;

+ (void)registerAsComponentRegistrant:(Class)klass inSet:(NSMutableSet<Class> *)allRegistrants;

+ (void)registerAsComponentRegistrant:(Class<FIRLibrary>)klass
inSet:(NSMutableSet<Class> *)allRegistrants;
- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet<Class> *)allRegistrants;
@end

@interface FIRComponentContainer (TestInternalImplementations)
- (instancetype)initWithApp:(FIRApp *)app
components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components;
@end

@implementation FIRComponentContainer (TestInternalImplementations)

- (instancetype)initWithApp:(FIRApp *)app
components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components {
self = [self initWithApp:app registrants:[[NSMutableSet alloc] init]];
if (self) {
self.components = [components mutableCopy];
}
return self;
}

@end

Expand All @@ -47,13 +64,6 @@ - (void)testRegisteringConformingClass {
XCTAssertTrue([allRegistrants containsObject:testClass]);
}

- (void)testRegisteringNonConformingClass {
NSMutableSet<Class> *allRegistrants = [NSMutableSet<Class> set];
XCTAssertThrows(
[FIRComponentContainer registerAsComponentRegistrant:[NSString class] inSet:allRegistrants]);
XCTAssertTrue(allRegistrants.count == 0);
}

- (void)testComponentsPopulatedOnInit {
FIRComponentContainer *container = [self containerWithRegistrants:@ [[FIRTestClass class]]];

Expand Down Expand Up @@ -149,7 +159,6 @@ - (FIRComponentContainer *)containerWithRegistrants:(NSArray<Class> *)registrant
for (Class c in registrants) {
[FIRComponentContainer registerAsComponentRegistrant:c inSet:allRegistrants];
}

return [[FIRComponentContainer alloc] initWithApp:appMock registrants:allRegistrants];
}

Expand Down
11 changes: 5 additions & 6 deletions Example/Core/Tests/FIRTestComponents.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#import <FirebaseCore/FIRComponent.h>
#import <FirebaseCore/FIRComponentContainer.h>
#import <FirebaseCore/FIRComponentRegistrant.h>
#import <FirebaseCore/FIRLibrary.h>

@protocol FIRComponentRegistrant;

Expand All @@ -28,13 +28,12 @@
@end

/// A test class that is a component registrant.
@interface FIRTestClass
: NSObject <FIRTestProtocol, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
@interface FIRTestClass : NSObject <FIRTestProtocol, FIRComponentLifecycleMaintainer, FIRLibrary>
@end

/// A test class that is a component registrant, a duplicate of FIRTestClass.
@interface FIRTestClassDuplicate
: NSObject <FIRTestProtocol, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
: NSObject <FIRTestProtocol, FIRComponentLifecycleMaintainer, FIRLibrary>
@end

#pragma mark - Eager Component
Expand All @@ -47,7 +46,7 @@
/// A test class that is a component registrant that provides a component requiring eager
/// instantiation, and is cached for easier validation that it was instantiated.
@interface FIRTestClassEagerCached
: NSObject <FIRTestProtocolEagerCached, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
: NSObject <FIRTestProtocol, FIRComponentLifecycleMaintainer, FIRLibrary>
@end

#pragma mark - Cached Component
Expand All @@ -59,5 +58,5 @@
/// A test class that is a component registrant that provides a component that requests to be
/// cached.
@interface FIRTestClassCached
: NSObject <FIRTestProtocolCached, FIRComponentRegistrant, FIRComponentLifecycleMaintainer>
: NSObject <FIRTestProtocol, FIRComponentLifecycleMaintainer, FIRLibrary>
@end
12 changes: 9 additions & 3 deletions Example/Core/Tests/FIRTestComponents.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ @implementation FIRTestClassDuplicate
- (void)doSomething {
}

/// FIRComponentRegistrant conformance.
/// FIRLibrary conformance.
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
FIRComponent *testComponent =
[FIRComponent componentWithProtocol:@protocol(FIRTestProtocol)
Expand All @@ -72,7 +72,7 @@ @implementation FIRTestClassEagerCached
- (void)doSomethingFaster {
}

/// FIRComponentRegistrant conformance.
/// FIRLibrary conformance.
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
FIRComponent *testComponent = [FIRComponent
componentWithProtocol:@protocol(FIRTestProtocolEagerCached)
Expand All @@ -92,13 +92,16 @@ - (void)doSomethingFaster {
- (void)appWillBeDeleted:(FIRApp *)app {
}

- (void)doSomething {
}

@end

#pragma mark - Cached Component

@implementation FIRTestClassCached

/// FIRComponentRegistrant conformance.
/// FIRLibrary conformance.
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
FIRComponent *testComponent = [FIRComponent
componentWithProtocol:@protocol(FIRTestProtocolCached)
Expand All @@ -115,4 +118,7 @@ @implementation FIRTestClassCached
- (void)appWillBeDeleted:(FIRApp *)app {
}

- (void)doSomething {
}

@end
21 changes: 21 additions & 0 deletions Example/Database/Tests/Helpers/FIRFakeApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,27 @@ @interface FIRDatabaseComponent (Internal)
- (instancetype)initWithApp:(FIRApp *)app;
@end

@interface FIRComponentContainer (TestInternal)
@property(nonatomic, strong) NSMutableDictionary<NSString *, FIRComponentCreationBlock> *components;
@end

@interface FIRComponentContainer (TestInternalImplementations)
- (instancetype)initWithApp:(FIRApp *)app
components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components;
@end

@implementation FIRComponentContainer (TestInternalImplementations)

- (instancetype)initWithApp:(FIRApp *)app
components:(NSDictionary<NSString *, FIRComponentCreationBlock> *)components {
self = [self initWithApp:app registrants:[[NSMutableSet alloc] init]];
if (self) {
self.components = [components mutableCopy];
}
return self;
}
@end

@implementation FIRFakeApp

- (instancetype)initWithName:(NSString *)name URL:(NSString *)url {
Expand Down
6 changes: 3 additions & 3 deletions Example/Storage/Tests/Unit/FIRStorageComponentTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@

#import <FirebaseCore/FIRAppInternal.h>
#import <FirebaseCore/FIRComponent.h>
#import <FirebaseCore/FIRComponentRegistrant.h>
#import <FirebaseCore/FIRLibrary.h>
#import <FirebaseCore/FIROptions.h>

#import "FIRComponentTestUtilities.h"
#import "FIRStorageComponent.h"

// Make FIRComponentRegistrant conformance visible to the tests and expose the initializer.
@interface FIRStorageComponent () <FIRComponentRegistrant>
/// Internal intializer.
@interface FIRStorageComponent () <FIRLibrary>
/// Internal initializer.
- (instancetype)initWithApp:(FIRApp *)app;
@end

Expand Down
12 changes: 6 additions & 6 deletions Firebase/Auth/Source/FIRAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
#import <FirebaseCore/FIRAppInternal.h>
#import <FirebaseCore/FIRComponent.h>
#import <FirebaseCore/FIRComponentContainer.h>
#import <FirebaseCore/FIRComponentRegistrant.h>
#import <FirebaseCore/FIRCoreConfigurable.h>
#import <FirebaseCore/FIRLibrary.h>
#import <FirebaseCore/FIRLogger.h>
#import <FirebaseCore/FIROptions.h>
#import <GoogleUtilities/GULAppEnvironmentUtil.h>
Expand Down Expand Up @@ -228,9 +227,9 @@ + (FIRActionCodeOperation)actionCodeOperationForRequestType:(NSString *)requestT
#pragma mark - FIRAuth

#if TARGET_OS_IOS
@interface FIRAuth () <FIRAuthAppDelegateHandler, FIRComponentRegistrant, FIRCoreConfigurable, FIRComponentLifecycleMaintainer>
@interface FIRAuth () <FIRAuthAppDelegateHandler, FIRLibrary, FIRComponentLifecycleMaintainer>
#else
@interface FIRAuth () <FIRComponentRegistrant, FIRCoreConfigurable, FIRComponentLifecycleMaintainer>
@interface FIRAuth () <FIRLibrary, FIRComponentLifecycleMaintainer>
#endif

/** @property firebaseAppId
Expand Down Expand Up @@ -310,8 +309,9 @@ @implementation FIRAuth {
}

+ (void)load {
[FIRComponentContainer registerAsComponentRegistrant:self];
[FIRApp registerAsConfigurable:self];
[FIRApp registerInternalLibrary:(Class<FIRLibrary>)self
withName:@"fire-auth"
withVersion:[NSString stringWithUTF8String:FirebaseAuthVersionStr]];
}

+ (void)initialize {
Expand Down
3 changes: 1 addition & 2 deletions Firebase/Auth/Source/FirebaseAuthVersion.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@

const double FirebaseAuthVersionNum = FIRAuth_MINOR_VERSION;

const unsigned char *const FirebaseAuthVersionStr =
(const unsigned char *const)STR(FIRAuth_VERSION);
const char *const FirebaseAuthVersionStr = (const char *const)STR(FIRAuth_VERSION);
2 changes: 1 addition & 1 deletion Firebase/Auth/Source/Public/FirebaseAuthVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ extern const double FirebaseAuthVersionNum;
/**
Version string for FirebaseAuth.
*/
extern const unsigned char *const FirebaseAuthVersionStr;
extern const char *const FirebaseAuthVersionStr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... do we count this as a breaking change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not on any architectures we care about. This is a cleanup that eliminates the need for extra casts.

56 changes: 35 additions & 21 deletions Firebase/Core/FIRApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@

#include <sys/utsname.h>

#import "FIRApp.h"
#import "FIRConfiguration.h"
#import "Private/FIRAnalyticsConfiguration+Internal.h"
#import "Private/FIRAppInternal.h"
#import "Private/FIRBundleUtil.h"
#import "Private/FIRComponentContainerInternal.h"
#import "Private/FIRCoreConfigurable.h"
#import "Private/FIRLibrary.h"
#import "Private/FIRLogger.h"
#import "Private/FIROptionsInternal.h"
#import "Public/FIRApp.h"
#import "Public/FIRConfiguration.h"

NSString *const kFIRServiceAdMob = @"AdMob";
NSString *const kFIRServiceAuth = @"Auth";
Expand Down Expand Up @@ -81,7 +81,7 @@
* An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle
* events from Core.
*/
static NSMutableArray<Class<FIRCoreConfigurable>> *gRegisteredAsConfigurable;
static NSMutableArray<Class<FIRLibrary>> *sRegisteredAsConfigurable;

@interface FIRApp ()

Expand Down Expand Up @@ -422,7 +422,7 @@ + (void)sendNotificationsToSDKs:(FIRApp *)app {

// This is the new way of sending information to SDKs.
// TODO: Do we want this on a background thread, maybe?
for (Class<FIRCoreConfigurable> library in gRegisteredAsConfigurable) {
for (Class<FIRLibrary> library in sRegisteredAsConfigurable) {
[library configureWithApp:app];
}
}
Expand Down Expand Up @@ -462,41 +462,55 @@ + (NSError *)errorForInvalidAppID {
userInfo:errorDict];
}

+ (void)registerAsConfigurable:(Class<FIRCoreConfigurable>)klass {
// This is called at +load time, keep the work to a minimum.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
gRegisteredAsConfigurable = [[NSMutableArray alloc] initWithCapacity:1];
});

NSAssert([(Class)klass conformsToProtocol:@protocol(FIRCoreConfigurable)],
@"The class being registered (%@) must conform to `FIRCoreConfigurable`.", klass);
[gRegisteredAsConfigurable addObject:klass];
}

+ (BOOL)isDefaultAppConfigured {
return (sDefaultApp != nil);
}

+ (void)registerLibrary:(nonnull NSString *)library withVersion:(nonnull NSString *)version {
+ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version {
// Create the set of characters which aren't allowed, only if this feature is used.
NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet];
[allowedSet addCharactersInString:@"-_."];
NSCharacterSet *disallowedSet = [allowedSet invertedSet];
// Make sure the library name and version strings do not contain unexpected characters, and
// add the name/version pair to the dictionary.
if ([library rangeOfCharacterFromSet:disallowedSet].location == NSNotFound &&
if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound &&
[version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) {
if (!sLibraryVersions) {
sLibraryVersions = [[NSMutableDictionary alloc] init];
}
sLibraryVersions[library] = version;
sLibraryVersions[name] = version;
} else {
FIRLogError(kFIRLoggerCore, @"I-COR000027",
@"The library name (%@) or version number (%@) contain illegal characters. "
@"Only alphanumeric, dash, underscore and period characters are allowed.",
library, version);
name, version);
}
}

+ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
withName:(nonnull NSString *)name
withVersion:(nonnull NSString *)version {
// This is called at +load time, keep the work to a minimum.

// Ensure the class given conforms to the proper protocol.
if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] ||
![(Class)library respondsToSelector:@selector(componentsToRegister)]) {
[NSException raise:NSInvalidArgumentException
format:
@"Class %@ attempted to register components, but it does not conform to "
@"`FIRLibrary or provide a `componentsToRegister:` method.",
library];
}

[FIRComponentContainer registerAsComponentRegistrant:library];
if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sRegisteredAsConfigurable = [[NSMutableArray alloc] init];
});
[sRegisteredAsConfigurable addObject:library];
}
[self registerLibrary:name withVersion:version];
}

+ (NSString *)firebaseUserAgent {
Expand Down
Loading