-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Working drop of Segmentation SDK along with test app and unit tests. #4574
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
Changes from all commits
bee3664
21aa26d
f3478be
d61830e
e6d2cef
9d3c5bd
682ad21
2492f68
29a79ad
5bc5c4c
b42843b
f969d69
4e27545
09c3fb1
ac85c3d
18533a4
69436cd
d4fb492
34f8879
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
#import <FirebaseCore/FIRComponentContainer.h> | ||
#import <FirebaseCore/FIROptionsInternal.h> | ||
#import "FirebaseSegmentation/Sources/Private/FIRSegmentationInternal.h" | ||
#import "FirebaseSegmentation/Sources/SEGSegmentationConstants.h" | ||
|
||
#ifndef FIRSegmentation_VERSION | ||
#error "FIRSegmentation_VERSION is not defined: \ | ||
|
@@ -29,8 +30,6 @@ | |
#define STR(x) STR_EXPAND(x) | ||
#define STR_EXPAND(x) #x | ||
|
||
NSString *const kFirebaseSegmentationErrorDomain = @"com.firebase.segmentation"; | ||
|
||
@implementation FIRSegmentationComponent | ||
|
||
/// Default method for retrieving a Segmentation instance, or creating one if it doesn't exist. | ||
|
@@ -70,7 +69,10 @@ - (instancetype)initWithApp:(FIRApp *)app { | |
self = [super init]; | ||
if (self) { | ||
_app = app; | ||
_segmentationInstance = nil; | ||
if (!_segmentationInstance) { | ||
_segmentationInstance = [[FIRSegmentation alloc] initWithAppName:app.name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you describe a situation where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not typical. Unless initWithApp is called twice tomorrow from elsewhere. |
||
FIROptions:app.options]; | ||
} | ||
} | ||
return self; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,19 @@ NS_ASSUME_NONNULL_BEGIN | |
NS_SWIFT_NAME(Segmentation) | ||
@interface FIRSegmentation : NSObject | ||
|
||
/// Firebase Remote Config service fetch error. | ||
typedef NS_ENUM(NSInteger, FIRSegmentationErrorCode) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has not gone through API review - please add it to the API doc or create a new one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. PTAL in the API review (commented) |
||
/// No error. The operation was successful. | ||
FIRSegmentationErrorCodeNone = 8001, | ||
/// An internal error occurred. | ||
FIRSegmentationErrorCodeInternal = 8002, | ||
/// Error indicating that backend reports an existing association for this custom installation | ||
/// identifier. | ||
FIRSegmentationErrorCodeConflict = 8003, | ||
/// Error indicating that a network error occurred during association. | ||
FIRSegmentationErrorCodeNetwork = 8004, | ||
} NS_SWIFT_NAME(SegmentationErrorCode); | ||
|
||
/** | ||
* Singleton instance (scoped to the default FIRApp) | ||
* Returns the FIRSegmentation instance for the default Firebase application. Please make sure you | ||
|
@@ -56,8 +69,8 @@ NS_SWIFT_NAME(Segmentation) | |
/// installation ID. | ||
/// @param completionHandler Set custom installation ID completion. Returns nil if initialization | ||
/// succeeded or an NSError object if initialization failed. | ||
- (void)setCustomInstallationID:(NSString *)customInstallationID | ||
completion:(void (^)(NSError *))completionHandler; | ||
- (void)setCustomInstallationID:(nullable NSString *)customInstallationID | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you share this amendment in the API review? Also, can you add documentation as to what happens when the |
||
completion:(nullable void (^)(NSError *))completionHandler; | ||
|
||
@end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2019 Google | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: 2020 now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and below. |
||
// | ||
// 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 "SEGSegmentationConstants.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@class FIROptions; | ||
|
||
@interface SEGContentManager : NSObject | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add some documentation in terms of what this class does? I realize it's internal but looking at the API surface I'm not sure sure what the responsibility is. |
||
|
||
/// Shared Singleton Instance | ||
+ (instancetype)sharedInstanceWithOptions:(FIROptions*)options; | ||
|
||
- (void)associateCustomInstallationIdentiferNamed:(NSString*)customInstallationID | ||
firebaseApp:(NSString*)appName | ||
completion:(SEGRequestCompletion)completionHandler; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright 2019 Google | ||
// | ||
// 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 "SEGContentManager.h" | ||
|
||
#import <FirebaseCore/FIRAppInternal.h> | ||
#import <FirebaseInstanceID/FIRInstanceID.h> | ||
#import "FIRSegmentation.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should be using fully qualified imports. @paulb777 to confirm There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes - we should now use repo-relative imports. See the |
||
#import "SEGDatabaseManager.h" | ||
#import "SEGNetworkManager.h" | ||
#import "SEGSegmentationConstants.h" | ||
|
||
NSString *const kErrorDescription = @"ErrorDescription"; | ||
|
||
@interface SEGContentManager () { | ||
NSMutableDictionary<NSString *, id> *_associationData; | ||
NSString *_instanceIdentifier; | ||
NSString *_instanceIdentifierToken; | ||
SEGDatabaseManager *_databaseManager; | ||
SEGNetworkManager *_networkManager; | ||
} | ||
@end | ||
|
||
@implementation SEGContentManager | ||
|
||
+ (instancetype)sharedInstanceWithOptions:(FIROptions *)options { | ||
static dispatch_once_t onceToken; | ||
static SEGContentManager *sharedInstance; | ||
dispatch_once(&onceToken, ^{ | ||
sharedInstance = [[SEGContentManager alloc] | ||
initWithDatabaseManager:[SEGDatabaseManager sharedInstance] | ||
networkManager:[[SEGNetworkManager alloc] initWithFIROptions:options]]; | ||
}); | ||
return sharedInstance; | ||
} | ||
|
||
- (instancetype)initWithDatabaseManager:databaseManager networkManager:networkManager { | ||
self = [super init]; | ||
if (self) { | ||
// Initialize the database manager. | ||
_databaseManager = databaseManager; | ||
|
||
// Initialize the network manager. | ||
_networkManager = networkManager; | ||
|
||
// Load all data from the database. | ||
[_databaseManager createOrOpenDatabaseWithCompletion:^(BOOL success, NSDictionary *result) { | ||
self->_associationData = [result mutableCopy]; | ||
}]; | ||
// TODO(dmandar) subscribe to FIS notifications once integrated. | ||
} | ||
return self; | ||
} | ||
|
||
// TODO(dmandar) IID only supports default instance. Modify for FIS. | ||
- (FIRInstanceID *)instanceIDForApp:(NSString *)firebaseApp { | ||
return [FIRInstanceID instanceID]; | ||
} | ||
|
||
- (void)associateCustomInstallationIdentiferNamed:(NSString *)customInstallationID | ||
firebaseApp:(NSString *)firebaseApp | ||
completion:(SEGRequestCompletion)completionHandler { | ||
// Get the latest instance identifier | ||
if (![self instanceIDForApp:firebaseApp]) { | ||
completionHandler(NO, @{kErrorDescription : @"InstanceID SDK not available"}); | ||
} | ||
__weak SEGContentManager *weakSelf = self; | ||
[[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult *_Nullable result, | ||
NSError *_Nullable error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we don't actually check if there was an error here or not - this means it could wipe out all the existing information on a fetch failure. Is that expected? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch. done. |
||
SEGContentManager *strongSelf = weakSelf; | ||
if (!strongSelf) { | ||
completionHandler(NO, @{kErrorDescription : @"Internal Error getting instance ID."}); | ||
return; | ||
} | ||
|
||
if (!result || error) { | ||
NSString *errorMessage = @"Error getting instance ID."; | ||
if (error) { | ||
errorMessage = [errorMessage stringByAppendingString:error.description]; | ||
} | ||
NSDictionary *errorDictionary = @{kErrorDescription : errorMessage}; | ||
completionHandler(NO, errorDictionary); | ||
return; | ||
} | ||
|
||
strongSelf->_instanceIdentifier = result.instanceID; | ||
strongSelf->_instanceIdentifierToken = result.token; | ||
|
||
NSMutableDictionary<NSString *, NSString *> *appAssociationData = | ||
[[NSMutableDictionary alloc] init]; | ||
[appAssociationData setObject:customInstallationID forKey:kSEGCustomInstallationIdentifierKey]; | ||
[appAssociationData setObject:self->_instanceIdentifier | ||
forKey:kSEGFirebaseInstallationIdentifierKey]; | ||
[appAssociationData setObject:kSEGAssociationStatusPending forKey:kSEGAssociationStatusKey]; | ||
[strongSelf->_associationData setObject:appAssociationData forKey:firebaseApp]; | ||
|
||
// Update the database async. | ||
// TODO(mandard) The database write and corresponding completion handler needs to be wired up | ||
// once we support listening to FID changes. | ||
[strongSelf->_databaseManager insertMainTableApplicationNamed:firebaseApp | ||
customInstanceIdentifier:customInstallationID | ||
firebaseInstanceIdentifier:strongSelf->_instanceIdentifier | ||
associationStatus:kSEGAssociationStatusPending | ||
completionHandler:nil]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please add a comment about why we don't care when the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated comment. |
||
|
||
// Send the change up to the backend. Also add the token. | ||
|
||
[strongSelf->_networkManager | ||
makeAssociationRequestToBackendWithData:appAssociationData | ||
token:strongSelf->_instanceIdentifierToken | ||
completion:^(BOOL status, | ||
NSDictionary<NSString *, id> *result) { | ||
// TODO...log, update database. | ||
|
||
completionHandler(status, result); | ||
}]; | ||
}]; | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2019 Google | ||
// | ||
// 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 "SEGSegmentationConstants.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/// Persist config data in sqlite database on device. Managing data read/write from/to database. | ||
@interface SEGDatabaseManager : NSObject | ||
/// Shared Singleton Instance | ||
+ (instancetype)sharedInstance; | ||
|
||
/// Open the database. | ||
- (void)createOrOpenDatabaseWithCompletion:(SEGRequestCompletion)completionHandler; | ||
|
||
/// Read all contents of main table. | ||
- (void)loadMainTableWithCompletion:(SEGRequestCompletion)completionHandler; | ||
|
||
/// Insert a record in main table. | ||
/// @param firebaseApplication The name of the Firebase App that this segmentation instance is | ||
/// associated with. | ||
/// @param customInstanceIdentifier The custom instance identifier provided by the developer. | ||
/// @param firebaseInstanceIdentifier The firebase instance identifier provided by the IID/FIS SDK. | ||
/// @param associationStatus The current status of the association - Pending until reported to the | ||
/// backend. | ||
- (void)insertMainTableApplicationNamed:(NSString *)firebaseApplication | ||
customInstanceIdentifier:(NSString *)customInstanceIdentifier | ||
firebaseInstanceIdentifier:(NSString *)firebaseInstanceIdentifier | ||
associationStatus:(NSString *)associationStatus | ||
completionHandler:(nullable SEGRequestCompletion)handler; | ||
|
||
/// Clear the record of given namespace and package name | ||
/// before updating the table.//TODO: Add delete. | ||
- (void)deleteRecordFromMainTableWithCustomInstanceIdentifier:(NSString *)customInstanceIdentifier; | ||
|
||
/// Remove all the records from a config content table. | ||
- (void)deleteAllRecordsFromTable; | ||
|
||
NS_ASSUME_NONNULL_END | ||
|
||
@end |
Uh oh!
There was an error while loading. Please reload this page.