Release 4.7.0
This commit is contained in:
Родитель
a72c241324
Коммит
9d7ccbc81a
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Unity Advertisements copyright © 2022 Unity Technologies.
|
||||
Unity Advertisements copyright © 2023 Unity Technologies.
|
||||
This software is subject to, and made available under, the terms of service for Operate Solutions (see https://unity3d.com/legal/one-operate-services-terms-of-service), and is an "Operate Service" as defined therein.
|
||||
|
||||
Your use of the Services constitutes your acceptance of such terms. Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions.
|
|
@ -7,6 +7,5 @@ typedef NS_ENUM (NSInteger, USRVDownloadLatestWebViewStatus) {
|
|||
kDownloadLatestWebViewStatusMissingLatestConfig,
|
||||
kDownloadLatestWebViewStatusBackgroundDownloadStarted
|
||||
};
|
||||
+ (void)setServiceProviderForTesting: (id)sProvider;
|
||||
+ (void)WebViewExposed_getTrrData: (USRVWebViewCallback *)callback;
|
||||
+ (void)WebViewExposed_getTrrData: (nonnull USRVWebViewCallback *)callback;
|
||||
@end
|
||||
|
|
|
@ -7,17 +7,8 @@
|
|||
#import "USRVDevice.h"
|
||||
#import "UADSServiceProviderContainer.h"
|
||||
|
||||
static UADSServiceProvider* serviceProvider;
|
||||
@implementation USRVApiSdk
|
||||
|
||||
+ (void)load {
|
||||
serviceProvider = UADSServiceProviderContainer.sharedInstance.serviceProvider;
|
||||
}
|
||||
|
||||
+ (void)setServiceProviderForTesting: (UADSServiceProvider*)sProvider {
|
||||
serviceProvider = sProvider;
|
||||
}
|
||||
|
||||
+ (void)WebViewExposed_loadComplete: (USRVWebViewCallback *)callback {
|
||||
USRVLogDebug(@"Web application loaded");
|
||||
[[USRVWebViewApp getCurrentApp] setWebAppLoaded: true];
|
||||
|
@ -114,11 +105,11 @@ static UADSServiceProvider* serviceProvider;
|
|||
}
|
||||
|
||||
+ (void)WebViewExposed_getTrrData: (USRVWebViewCallback *)callback {
|
||||
[callback invoke: serviceProvider.configurationStorage.getCurrentConfiguration.originalJSON, nil];
|
||||
[callback invoke: UADSServiceProviderContainer.sharedInstance.serviceProvider.configurationStorage.getCurrentConfiguration.originalJSON, nil];
|
||||
}
|
||||
|
||||
+ (void)WebViewExposed_getSharedSessionID:(USRVWebViewCallback *)callback {
|
||||
[callback invoke: serviceProvider.sharedSessionId];
|
||||
[callback invoke: UADSServiceProviderContainer.sharedInstance.serviceProvider.sharedSessionId];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#import "UADSConfigurationLoaderWithPrivacy.h"
|
||||
#import "UADSErrorState.h"
|
||||
|
||||
@interface UADSConfigurationLoaderWithPrivacy ()
|
||||
@property (nonatomic, strong) id<UADSConfigurationLoader>original;
|
||||
@property (nonatomic, strong) id<UADSPrivacyLoader>privacyLoader;
|
||||
@property (nonatomic, strong) id<UADSPrivacyResponseSaver, UADSPrivacyResponseReader>responseStorage;
|
||||
@property (nonatomic, strong) NSArray<NSNumber*> *fastFailCodes;
|
||||
@end
|
||||
|
||||
@implementation UADSConfigurationLoaderWithPrivacy
|
||||
|
@ -17,6 +19,7 @@
|
|||
decorator.original = original;
|
||||
decorator.privacyLoader = privacyLoader;
|
||||
decorator.responseStorage = responseStorage;
|
||||
decorator.fastFailCodes = @[@(kPrivacyGameIdDisabledCode)];
|
||||
return decorator;
|
||||
}
|
||||
|
||||
|
@ -72,7 +75,7 @@
|
|||
}
|
||||
|
||||
- (BOOL)shouldProceedWithTheCallForError: (id<UADSError>)error {
|
||||
return error.errorDomain == kPrivacyLoaderErrorDomain;
|
||||
return error.errorDomain == kPrivacyLoaderErrorDomain && ![_fastFailCodes containsObject: error.errorCode];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, strong, readonly) NSDictionary *originalJSON;
|
||||
@property (nonatomic, assign) long responseCode;
|
||||
@property (nonatomic, assign) BOOL allowTracking;
|
||||
@property (nonatomic, assign) BOOL shouldSendNonBehavioural;
|
||||
|
||||
+ (instancetype)newFromDictionary: (NSDictionary *)dictionary;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
response.originalJSON = dictionary;
|
||||
|
||||
response.allowTracking = [dictionary[@"pas"] boolValue] ? : false;
|
||||
response.shouldSendNonBehavioural = [dictionary[@"snb"] boolValue] ?: false;
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#import "UADSInitializationResponse.h"
|
||||
#import "UADSGenericCompletion.h"
|
||||
#import "USRVInitializationRequestFactory.h"
|
||||
#import "UADSErrorState.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^UADSPrivacyCompletion)(UADSInitializationResponse *);
|
||||
|
@ -32,6 +34,11 @@ extern NSString *const kPrivacyLoaderErrorDomain;
|
|||
code: kUADSPrivacyLoaderInvalidResponseCode \
|
||||
userInfo: nil] \
|
||||
|
||||
#define uads_privacyGameDisabledError \
|
||||
[[NSError alloc] initWithDomain: kPrivacyLoaderErrorDomain \
|
||||
code: kPrivacyGameIdDisabledCode \
|
||||
userInfo: nil] \
|
||||
|
||||
@protocol UADSPrivacyLoader <NSObject>
|
||||
- (void)loadPrivacyWithSuccess: (UADSPrivacyCompletion)success
|
||||
andErrorCompletion: (UADSErrorCompletion)errorCompletion;
|
||||
|
|
|
@ -68,6 +68,10 @@ NSString * uads_privacyErrorTypeToString(UADSPrivacyLoaderError type) {
|
|||
}
|
||||
|
||||
if (![request is2XXResponse]) {
|
||||
if (request.responseCode == 423) {
|
||||
errorCompletion(uads_privacyGameDisabledError);
|
||||
return;
|
||||
}
|
||||
errorCompletion(uads_privacyInvalidResponseCodeError);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ NSString * uads_privacyResponseStateToString(UADSPrivacyResponseState);
|
|||
@protocol UADSPrivacyResponseReader <NSObject>
|
||||
|
||||
- (UADSPrivacyResponseState)responseState;
|
||||
- (BOOL)shouldSendUserNonBehavioral;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ NSString * uads_privacyResponseStateToString(UADSPrivacyResponseState state) {
|
|||
[self.mediator notifyObserversWithObjectAndRemove: response];
|
||||
}
|
||||
|
||||
- (BOOL)shouldSendUserNonBehavioral {
|
||||
return self.response.shouldSendNonBehavioural;
|
||||
}
|
||||
|
||||
- (UADSPrivacyResponseState)responseState {
|
||||
if (!self.response) {
|
||||
return kUADSPrivacyResponseUnknown;
|
||||
|
|
|
@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, strong) id<UADSLogger>logger;
|
||||
@property (nonatomic, strong) id<UADSRetryInfoReader> retryInfoReader;
|
||||
@property (nonatomic, strong) id<UADSGameSessionIdReader> gameSessionIdReader;
|
||||
@property (nonatomic, strong) id<UADSSharedSessionIdReader> sharedSessionIdReader;
|
||||
@property (nonatomic) BOOL noCompression;
|
||||
|
||||
- (id<USRVInitializationRequestFactory>)requestFactoryWithExtendedInfo: (BOOL)hasExtendedInfo;
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
builder.logger = self.logger;
|
||||
builder.currentTimeStampReader = self.currentTimeStampReader;
|
||||
builder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
builder.sharedSessionIdReader = self.sharedSessionIdReader;
|
||||
return builder.defaultReader;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (BOOL) isPrivacyWaitEnabled;
|
||||
- (BOOL) isNativeWebViewCacheEnabled;
|
||||
- (BOOL) isWebAdAssetCacheEnabled;
|
||||
- (BOOL) isSwiftTokenEnabled;
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)nextSessionFlags;
|
||||
- (NSDictionary<NSString *, NSString *> *)currentSessionFlags;
|
||||
|
|
|
@ -73,6 +73,10 @@
|
|||
return [self isExperimentEnabledWithKey: @"wac"];
|
||||
}
|
||||
|
||||
- (BOOL)isSwiftTokenEnabled {
|
||||
return [self isExperimentEnabledWithKey: @"s_tkn"];
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)nextSessionFlags {
|
||||
return [self flattenFlagsWith:^BOOL (id key) {
|
||||
return [self isExperimentForNextSession: key];
|
||||
|
|
|
@ -13,3 +13,5 @@ typedef NS_ENUM (NSInteger, UADSErrorState) {
|
|||
|
||||
NSString * uads_errorStateString(UADSErrorState state);
|
||||
BOOL uads_isWebViewErrorState(UADSErrorState state);
|
||||
|
||||
extern const int kPrivacyGameIdDisabledCode;
|
||||
|
|
|
@ -45,3 +45,5 @@ BOOL uads_isWebViewErrorState(UADSErrorState state) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const int kPrivacyGameIdDisabledCode = 423;
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
@"USRVApiPermissions",
|
||||
@"USRVApiMainBundle",
|
||||
@"USRVApiWebAuth",
|
||||
@"USRVApiTrackingManager",
|
||||
@"USRVApiSKAdNetwork"
|
||||
@"USRVApiTrackingManager"
|
||||
];
|
||||
} /* getWebAppApiClassList */
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#import "UADSDeviceInfoReader.h"
|
||||
#import "UADSPIIDataProvider.h"
|
||||
#import "UADSPrivacyStorage.h"
|
||||
#import "UADSPIITrackingStatusReader.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSDeviceInfoReaderGate : NSObject<UADSDeviceInfoReader>
|
||||
+ (instancetype)decorateOriginal: (id<UADSDeviceInfoReader>)original
|
||||
withPrivacyReader: (id<UADSPrivacyResponseReader>)privacyReader;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,32 @@
|
|||
#import "UADSDeviceInfoReaderGate.h"
|
||||
#import "NSMutableDictionary+SafeRemoval.h"
|
||||
#import "UADSJsonStorageKeyNames.h"
|
||||
|
||||
@interface UADSDeviceInfoReaderGate ()
|
||||
@property (nonatomic, strong) id<UADSDeviceInfoReader>original;
|
||||
@property (nonatomic, strong) id<UADSPrivacyResponseReader>privacyReader;
|
||||
@end
|
||||
|
||||
|
||||
@implementation UADSDeviceInfoReaderGate
|
||||
+ (instancetype)decorateOriginal: (id<UADSDeviceInfoReader>)original
|
||||
withPrivacyReader: (id<UADSPrivacyResponseReader>)privacyReader {
|
||||
UADSDeviceInfoReaderGate *decorator = [self new];
|
||||
|
||||
decorator.original = original;
|
||||
decorator.privacyReader = privacyReader;
|
||||
return decorator;
|
||||
}
|
||||
|
||||
|
||||
- (nonnull NSDictionary *)getDeviceInfoForGameMode:(UADSGameMode)mode {
|
||||
NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithDictionary: [_original getDeviceInfoForGameMode: mode]];
|
||||
if (!_privacyReader.shouldSendUserNonBehavioral) {
|
||||
[info uads_removeObjectForKeyAndReturn: UADSJsonStorageKeyNames.userNonBehavioralFlagKey];
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -55,4 +55,8 @@ extern NSString *const kUADSDeviceInfoSKADNVersionsKey;
|
|||
extern NSString *const kUADSDeviceInfoAnalyticSessionIDKey;
|
||||
extern NSString *const kUADSDeviceInfoAnalyticUserIDKey;
|
||||
|
||||
extern NSString *const kUADSDeviceInfoSessionIdKey;
|
||||
|
||||
extern NSString *const kUADSDeviceInfoReaderAUIDKey;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -50,3 +50,5 @@ NSString *const kUADSDeviceInfoAppUptimeTimestampKey = @"appUptime";
|
|||
NSString *const kUADSDeviceInfoBuiltSDKVersionKey = @"builtSdkVersion";
|
||||
NSString *const kUADSDeviceInfoAnalyticSessionIDKey = @"analyticsSessionId";
|
||||
NSString *const kUADSDeviceInfoAnalyticUserIDKey = @"analyticsUserId";
|
||||
NSString *const kUADSDeviceInfoSessionIdKey = @"sessionId";
|
||||
NSString *const kUADSDeviceInfoReaderAUIDKey = @"auid";
|
||||
|
|
|
@ -31,9 +31,6 @@
|
|||
if (_privacyReader.responseState == kUADSPrivacyResponseAllowed) {
|
||||
mInfo[self.vendorIDKey] = _dataProvider.vendorID;
|
||||
mInfo[self.advertisingTrackingIdKey] = _dataProvider.advertisingTrackingID;
|
||||
|
||||
[mInfo uads_setValueIfNotNil: @(_userContainer.userNonBehavioralFlag)
|
||||
forKey: self.userNonBehavioralFlagKey];
|
||||
}
|
||||
|
||||
return mInfo;
|
||||
|
|
|
@ -14,7 +14,7 @@ extern NSString * uads_privacyModeString(UADSPrivacyMode mode);
|
|||
|
||||
@protocol UADSPIITrackingStatusReader <NSObject>
|
||||
- (UADSPrivacyMode)privacyMode;
|
||||
- (BOOL) userNonBehavioralFlag;
|
||||
- (NSNumber *)userNonBehavioralFlag;
|
||||
@end
|
||||
|
||||
@interface UADSPIITrackingStatusReaderBase : NSObject<UADSPIITrackingStatusReader>
|
||||
|
|
|
@ -93,14 +93,14 @@ NSString * uads_privacyModeString(UADSPrivacyMode mode) {
|
|||
return uads_privacyModeFromString(privacyMode);
|
||||
}
|
||||
|
||||
- (BOOL)userNonBehavioralFlag {
|
||||
- (NSNumber *)userNonBehavioralFlag {
|
||||
id flag = [self.storageReader getValueForKey: [UADSJsonStorageKeyNames userNonBehavioralValueFlagKey]];
|
||||
|
||||
if (flag == nil) {
|
||||
flag = [self.storageReader getValueForKey: [UADSJsonStorageKeyNames userNonbehavioralValueFlagKey]];
|
||||
}
|
||||
|
||||
return [flag boolValue];
|
||||
return flag ? @([flag boolValue]) : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "UADSDeviceInfoReader.h"
|
||||
#import "UADSSharedSessionIdReader.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSDeviceInfoReaderWithSessionId : NSObject<UADSDeviceInfoReader>
|
||||
|
||||
+ (id<UADSDeviceInfoReader>)newWithOriginal: (id<UADSDeviceInfoReader>)original
|
||||
andSessionIdReader: (id<UADSSharedSessionIdReader>)sessionIdReader;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,28 @@
|
|||
#import "UADSDeviceInfoReaderWithSessionId.h"
|
||||
#import "UADSDeviceInfoReaderKeys.h"
|
||||
|
||||
@interface UADSDeviceInfoReaderWithSessionId()
|
||||
@property (nonatomic, strong) id<UADSDeviceInfoReader> original;
|
||||
@property (nonatomic, strong) id<UADSSharedSessionIdReader> sessionIdReader;
|
||||
@end
|
||||
|
||||
@implementation UADSDeviceInfoReaderWithSessionId
|
||||
|
||||
+ (id<UADSDeviceInfoReader>)newWithOriginal: (id<UADSDeviceInfoReader>)original
|
||||
andSessionIdReader: (id<UADSSharedSessionIdReader>)sessionIdReader {
|
||||
UADSDeviceInfoReaderWithSessionId *reader = [UADSDeviceInfoReaderWithSessionId new];
|
||||
reader.original = original;
|
||||
reader.sessionIdReader = sessionIdReader;
|
||||
return reader;
|
||||
}
|
||||
|
||||
- (NSDictionary *)getDeviceInfoForGameMode: (UADSGameMode)mode {
|
||||
NSDictionary *info = [_original getDeviceInfoForGameMode: mode];
|
||||
|
||||
NSMutableDictionary *mInfo = [[NSMutableDictionary alloc] initWithDictionary: info];
|
||||
mInfo[kUADSDeviceInfoSessionIdKey] = _sessionIdReader.sessionId;
|
||||
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
@end
|
|
@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (NSString *)sessionID;
|
||||
- (NSString *)userID;
|
||||
- (NSString *)auID;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
- (nonnull NSString *)idfi {
|
||||
NSString *currentValue = [USRVPreferences getString: kUADSStorageIDFIKey];
|
||||
NSString *currentValue = [USRVPreferences getString: kUADSStorageIDFIKey] ?: [self auID];
|
||||
|
||||
if (currentValue == nil || currentValue.length == 0) {
|
||||
currentValue = [[USRVDevice getUniqueEventId] lowercaseString];
|
||||
|
@ -25,6 +25,10 @@
|
|||
return [USRVPreferences getString: kUADSStorageAnalyticSessionKey];
|
||||
}
|
||||
|
||||
- (NSString *)auID {
|
||||
return [USRVPreferences getString: kUADSStorageAUIDKey];
|
||||
}
|
||||
|
||||
- (NSString *)userID {
|
||||
return [USRVPreferences getString: kUADSStorageAnalyticUserKey];
|
||||
}
|
||||
|
|
|
@ -270,6 +270,12 @@
|
|||
[info uads_setValueIfNotNil: self.userDefaultsReader.sessionID
|
||||
forKey: kUADSDeviceInfoAnalyticSessionIDKey];
|
||||
}];
|
||||
|
||||
[self measurePerformanceAndLog: @"AUID"
|
||||
using: ^{
|
||||
[info uads_setValueIfNotNil: self.userDefaultsReader.auID
|
||||
forKey: kUADSDeviceInfoReaderAUIDKey];
|
||||
}];
|
||||
|
||||
[self measurePerformanceAndLog: @"userID"
|
||||
using: ^{
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#import "UADSPrivacyStorage.h"
|
||||
#import "UADSLogger.h"
|
||||
#import "UADSGameSessionIdReader.h"
|
||||
#import "UADSSharedSessionIdReader.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSDeviceInfoReaderBuilder : NSObject <UADSDeviceInfoProvider>
|
||||
|
@ -16,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, strong) id<UADSCurrentTimestamp>currentTimeStampReader;
|
||||
@property (nonatomic, strong) id<UADSClientConfig> clientConfig;
|
||||
@property (nonatomic, strong) id<UADSGameSessionIdReader>gameSessionIdReader;
|
||||
@property (nonatomic, strong) id<UADSSharedSessionIdReader> sharedSessionIdReader;
|
||||
@property BOOL extendedReader;
|
||||
- (id<UADSDeviceInfoReader>)defaultReader;
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#import "UADSDeviceInfoStorageKeysProviderExtended.h"
|
||||
#import "UADSDeviceInfoStorageKeysProviderMinimal.h"
|
||||
#import "UADSDeviceInfoReaderWithPrivacy.h"
|
||||
#import "UADSDeviceInfoReaderGate.h"
|
||||
#import "UADSDeviceInfoReaderWithSessionId.h"
|
||||
|
||||
@implementation UADSDeviceInfoReaderBuilder
|
||||
- (id<UADSDeviceInfoReader>)defaultReader {
|
||||
|
@ -28,14 +30,19 @@
|
|||
deviceInfoReader = [self addStorageDumpDecorator: deviceInfoReader];
|
||||
|
||||
if (extendedReader) {
|
||||
deviceInfoReader = [self addGate: deviceInfoReader];
|
||||
deviceInfoReader = [self addPIIDecorator: deviceInfoReader];
|
||||
|
||||
deviceInfoReader = [self addSessionIdDecorator: deviceInfoReader];
|
||||
|
||||
deviceInfoReader = [self addMetrics: deviceInfoReader
|
||||
usingMetricsSender: self.metricsSender
|
||||
currentTimestamp: self.currentTimeStampReader];
|
||||
|
||||
}
|
||||
|
||||
deviceInfoReader = [self addFilter: deviceInfoReader];
|
||||
|
||||
return deviceInfoReader;
|
||||
}
|
||||
|
||||
|
@ -69,6 +76,11 @@
|
|||
andBlockList: self.defaultBlockList];
|
||||
}
|
||||
|
||||
- (id<UADSDeviceInfoReader>)addGate: (id<UADSDeviceInfoReader>)original {
|
||||
return [UADSDeviceInfoReaderGate decorateOriginal: original
|
||||
withPrivacyReader: self.privacyReader];
|
||||
}
|
||||
|
||||
- (id<UADSDictionaryKeysBlockList>)defaultBlockList {
|
||||
if (_storageBlockListProvider) {
|
||||
return _storageBlockListProvider;
|
||||
|
@ -84,6 +96,11 @@
|
|||
andUserContainer: self.userStorageReader];
|
||||
}
|
||||
|
||||
- (id<UADSDeviceInfoReader>)addSessionIdDecorator: (id<UADSDeviceInfoReader>)original {
|
||||
return [UADSDeviceInfoReaderWithSessionId newWithOriginal: original
|
||||
andSessionIdReader: self.sharedSessionIdReader];
|
||||
}
|
||||
|
||||
- (id<UADSDeviceInfoReader>)addMetrics: (id<UADSDeviceInfoReader>)original
|
||||
usingMetricsSender: (id<ISDKMetrics>)metricsSender
|
||||
currentTimestamp: (id<UADSCurrentTimestamp>)timestampReader {
|
||||
|
|
|
@ -18,6 +18,7 @@ extern NSString *const kUADSUserContainerName;
|
|||
extern NSString *const kUADSStorageIDFIKey;
|
||||
extern NSString *const kUADSStorageAnalyticSessionKey;
|
||||
extern NSString *const kUADSStorageAnalyticUserKey;
|
||||
extern NSString *const kUADSStorageAUIDKey;
|
||||
|
||||
@interface UADSJsonStorageKeyNames : NSObject
|
||||
+ (NSString *)webViewContainerKey;
|
||||
|
|
|
@ -26,7 +26,7 @@ NSString *const kPrivacySPMKey = @"spm";
|
|||
|
||||
NSString *const kUADSStorageAnalyticSessionKey = @"unity.player_sessionid";
|
||||
NSString *const kUADSStorageAnalyticUserKey = @"unity.cloud_userid";
|
||||
|
||||
NSString *const kUADSStorageAUIDKey = @"auid";
|
||||
|
||||
NSString *const kUADSSdkServiceModeKey = @"sdk.mode.value";
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
[info uads_setValueIfNotNil: self.userDefaultsReader.idfi
|
||||
forKey: kUADSDeviceInfoIDFIKey];
|
||||
|
||||
[info uads_setValueIfNotNil: @(_userContainerReader.userNonBehavioralFlag)
|
||||
[info uads_setValueIfNotNil: _userContainerReader.userNonBehavioralFlag
|
||||
forKey: UADSJsonStorageKeyNames.userNonBehavioralFlagKey];
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
|
||||
+ (instancetype)newScarSendTimeFailure: (NSNumber *)value tags: (NSDictionary<NSString *, NSString *> *)tags isAsync:(BOOL)isAsync {
|
||||
return [self newWithName: isAsync ? @"native_hb_signals_async_upload_failure" : @"native_hb_signals_sync_upload_success"
|
||||
return [self newWithName: isAsync ? @"native_hb_signals_async_upload_failure" : @"native_hb_signals_sync_upload_failure"
|
||||
value: value
|
||||
tags: tags];
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#import "UADSSCARRawSignalsReader.h"
|
||||
#import "UADSSCARSignalIdentifiers.h"
|
||||
#import "UADSSCARHeaderBiddingMetric.h"
|
||||
#import "NSMutableDictionary+SafeOperations.h"
|
||||
|
||||
@implementation UADSSCARRawSignalsReader
|
||||
|
||||
|
@ -16,9 +17,8 @@
|
|||
};
|
||||
|
||||
id error = ^(id<UADSError> _Nonnull error) {
|
||||
NSMutableDictionary *tags = [NSMutableDictionary dictionaryWithDictionary: @{
|
||||
@"reason": error.errorCode
|
||||
}];
|
||||
NSMutableDictionary *tags = [NSMutableDictionary new];
|
||||
[tags uads_setValueIfNotNil:error.errorCode forKey:@"reason"];
|
||||
[self.config.metricsSender sendMetric: [UADSSCARHeaderBiddingMetric newScarFetchTimeFailure:[self durationFromStartTime:startTime] tags:tags isAsync:isAsync]];
|
||||
completion(nil);
|
||||
};
|
||||
|
|
|
@ -63,8 +63,14 @@
|
|||
request.body = jsonString;
|
||||
|
||||
dispatch_async(queue, ^{
|
||||
NSData* data = [request makeRequest];
|
||||
[self.config.metricsSender sendMetric: [UADSSCARHeaderBiddingMetric newScarSendTimeSuccess:[self durationFromStartTime:startTime] isAsync:isAsync]];
|
||||
[request makeRequest];
|
||||
if (request.error) {
|
||||
NSMutableDictionary *tags = [NSMutableDictionary new];
|
||||
[tags uads_setValueIfNotNil:[NSString stringWithFormat:@"%li",(long)request.error.code] forKey:@"reason"];
|
||||
[self.config.metricsSender sendMetric: [UADSSCARHeaderBiddingMetric newScarSendTimeFailure:[self durationFromStartTime:startTime] tags:tags isAsync:isAsync]];
|
||||
} else {
|
||||
[self.config.metricsSender sendMetric: [UADSSCARHeaderBiddingMetric newScarSendTimeSuccess:[self durationFromStartTime:startTime] isAsync:isAsync]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (instancetype)newWebToken: (NSString *)value;
|
||||
+ (instancetype)newInvalidToken;
|
||||
+ (instancetype)newInvalidNativeToken;
|
||||
+ (instancetype)newWithDictionary: (NSDictionary *)dictionary;
|
||||
- (BOOL) isValid;
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,18 @@
|
|||
return token;
|
||||
}
|
||||
|
||||
+ (instancetype)newWithDictionary: (NSDictionary *)dictionary {
|
||||
UADSHeaderBiddingToken *token = [self new];
|
||||
token.value = dictionary[@"value"];
|
||||
NSNumber *type = dictionary[@"type"];
|
||||
token.type = type.intValue;
|
||||
token.uuidString = dictionary[@"uuidString"];
|
||||
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary:dictionary[@"info"]];
|
||||
token.info = info;
|
||||
token.customPrefix = dictionary[@"customPrefix"];
|
||||
return token;
|
||||
}
|
||||
|
||||
- (BOOL)isValid {
|
||||
return _value != nil && ![_value isEqual: @""];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#import "UADSPrivacyStorage.h"
|
||||
#import "UADSGameSessionIdReader.h"
|
||||
#import "UADSGMAScar.h"
|
||||
#import "UADSSharedSessionIdReader.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -22,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, strong) id<IUSRVWebRequestFactory> requestFactory;
|
||||
@property (nonatomic, weak) UADSGMAScar* scar;
|
||||
@property (nonatomic) id<UADSUniqueIdGenerator> uniqueIdGenerator;
|
||||
@property (nonatomic, strong) id<UADSSharedSessionIdReader> sharedSessionIdReader;
|
||||
|
||||
|
||||
- (id<UADSHeaderBiddingAsyncTokenReader, UADSHeaderBiddingTokenCRUD>)defaultReader;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#import "UADSHBTokenReaderWithPrivacyWait.h"
|
||||
#import "UADSHeaderBiddingTokenReaderWithSCARSignals.h"
|
||||
#import "UADSUUIDStringGenerator.h"
|
||||
#import "UADSHeaderBiddingTokenReaderSwiftBridge.h"
|
||||
|
||||
static NSString *const kDefaultTokenPrefix = @"1:";
|
||||
|
||||
|
@ -71,6 +72,7 @@ static NSString *const kDefaultTokenPrefix = @"1:";
|
|||
builder.extendedReader = true;
|
||||
builder.currentTimeStampReader = [UADSCurrentTimestampBase new];
|
||||
builder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
builder.sharedSessionIdReader = self.sharedSessionIdReader;
|
||||
_deviceInfoReader = builder.defaultReader;
|
||||
return _deviceInfoReader;
|
||||
}
|
||||
|
@ -91,11 +93,15 @@ static NSString *const kDefaultTokenPrefix = @"1:";
|
|||
|
||||
- (id<UADSHeaderBiddingAsyncTokenReader>)tokenGenerator {
|
||||
if (!_tokenGenerator) {
|
||||
_tokenGenerator = [UADSHeaderBiddingTokenReaderBase newWithDeviceInfoReader: self.deviceInfoReader
|
||||
if (self.experiments.isSwiftTokenEnabled) {
|
||||
_tokenGenerator = [UADSHeaderBiddingTokenReaderSwiftBridge new];
|
||||
} else {
|
||||
_tokenGenerator = [UADSHeaderBiddingTokenReaderBase newWithDeviceInfoReader: self.deviceInfoReader
|
||||
andCompressor: self.bodyCompressor
|
||||
withTokenPrefix: self.nativeTokenPrefix
|
||||
withUniqueIdGenerator: self.uniqueIdGenerator ?: [UADSUUIDStringGenerator new]
|
||||
withConfigurationReader: self.sdkConfigReader];
|
||||
}
|
||||
}
|
||||
|
||||
if (self.experiments.isPrivacyWaitEnabled) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "UADSHeaderBiddingTokenReaderBase.h"
|
||||
#import "UADSServiceProviderContainer.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSHeaderBiddingTokenReaderSwiftBridge : NSObject <UADSHeaderBiddingAsyncTokenReader>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,13 @@
|
|||
#import "UADSHeaderBiddingTokenReaderSwiftBridge.h"
|
||||
|
||||
@implementation UADSHeaderBiddingTokenReaderSwiftBridge
|
||||
|
||||
- (void)getToken:(nonnull UADSHeaderBiddingTokenCompletion)completion {
|
||||
[[UADSServiceProviderContainer.sharedInstance.serviceProvider objBridge] getToken:^(NSDictionary * _Nonnull tokenDict) {
|
||||
completion([UADSHeaderBiddingToken newWithDictionary:tokenDict]);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -1,32 +1,14 @@
|
|||
#import "UADSGameSessionIdReader.h"
|
||||
#import "USRVStorageManager.h"
|
||||
#import "USRVDevice.h"
|
||||
#import "UADSJsonStorageKeyNames.h"
|
||||
#import "UADSServiceProviderContainer.h"
|
||||
|
||||
@interface UADSGameSessionIdReaderBase ()
|
||||
@property (nonatomic, strong) NSNumber *gameSessionId;
|
||||
@end
|
||||
|
||||
@implementation UADSGameSessionIdReaderBase
|
||||
|
||||
- (nonnull NSNumber *)gameSessionId {
|
||||
@synchronized (self) {
|
||||
[self generateSessionIdIfNeeded];
|
||||
}
|
||||
return _gameSessionId;
|
||||
}
|
||||
|
||||
- (void)generateSessionIdIfNeeded {
|
||||
if (_gameSessionId != nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *uuidString = [[[USRVDevice getUniqueEventId] stringByReplacingOccurrencesOfString:@"-" withString:@""] substringToIndex:12];
|
||||
long long hex = strtoull([uuidString UTF8String], NULL, 16);
|
||||
_gameSessionId = [NSNumber numberWithLongLong:hex];
|
||||
|
||||
[[USRVStorageManager getStorage: kUnityServicesStorageTypePrivate] set: UADSJsonStorageKeyNames.webViewDataGameSessionIdKey
|
||||
value: _gameSessionId];
|
||||
UADSServiceProvider *provider = UADSServiceProviderContainer.sharedInstance.serviceProvider;
|
||||
return [NSNumber numberWithLongLong: [[provider.objBridge gameSessionId] longLongValue]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#import "UADSSharedSessionIdReader.h"
|
||||
#import "UADSSessionId.h"
|
||||
#import "UADSServiceProviderContainer.h"
|
||||
|
||||
@implementation UADSSharedSessionIdReaderBase
|
||||
|
||||
- (nonnull NSString *)sessionId {
|
||||
return UADSSessionId.shared.sessionId;
|
||||
UADSServiceProvider *provider = UADSServiceProviderContainer.sharedInstance.serviceProvider;
|
||||
return [provider.objBridge sessionId];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -44,7 +44,7 @@ static void soundCompletionCallback(SystemSoundID soundId, void *myself) {
|
|||
}
|
||||
|
||||
- (bool)writeToMuteDetectionPath: (NSString *)filePath {
|
||||
NSLog(@"MuteSwitch: Attempting to write bytes to file");
|
||||
USRVLogDebug(@"MuteSwitch: Attempting to write bytes to file");
|
||||
|
||||
@try {
|
||||
NSData *muteFileData = [[NSData alloc] initWithBytesNoCopy: MuteSwitchDetection_aiff
|
||||
|
@ -53,12 +53,12 @@ static void soundCompletionCallback(SystemSoundID soundId, void *myself) {
|
|||
[muteFileData writeToFile: filePath
|
||||
atomically: YES];
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"MuteSwitch: File creation failed.");
|
||||
USRVLogDebug(@"MuteSwitch: File creation failed.");
|
||||
self.fileCreated = NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSLog(@"MuteSwitch: File creation successful");
|
||||
USRVLogDebug(@"MuteSwitch: File creation successful");
|
||||
self.fileCreated = YES;
|
||||
return YES;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ static void soundCompletionCallback(SystemSoundID soundId, void *myself) {
|
|||
}
|
||||
|
||||
- (void)sendMuteState: (bool)muteState {
|
||||
NSLog(@"MuteSwitch: Device mute state detected to be %@", muteState ? @"true" : @"false");
|
||||
USRVLogDebug(@"MuteSwitch: Device mute state detected to be %@", muteState ? @"true" : @"false");
|
||||
|
||||
if ([USRVWebViewApp getCurrentApp]) {
|
||||
[[USRVWebViewApp getCurrentApp] sendEvent: @"MUTE_STATE_RECEIVED"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
+ (instancetype) sharedInstance;
|
||||
+ (USRVStorage *)getStorage: (UnityServicesStorageType)storageType;
|
||||
+ (void)removeStorage: (UnityServicesStorageType)storageType;
|
||||
|
||||
- (void)commit: (NSDictionary *)storageContents;
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
return [[USRVStorageManager sharedInstance] getStorage: storageType];
|
||||
}
|
||||
|
||||
+ (void)removeStorage: (UnityServicesStorageType)storageType {
|
||||
[[USRVStorageManager sharedInstance] removeStorage: storageType];
|
||||
}
|
||||
|
||||
_uads_custom_singleton_imp(USRVStorageManager, ^{
|
||||
return [self new];
|
||||
})
|
||||
|
@ -97,13 +93,6 @@ _uads_custom_singleton_imp(USRVStorageManager, ^{
|
|||
}
|
||||
} /* initStorage */
|
||||
|
||||
- (void)removeStorage: (UnityServicesStorageType)storageType {
|
||||
dispatch_sync(_syncQueue, ^{
|
||||
[_storageLocations removeObjectForKey: [NSNumber numberWithInteger: storageType]];
|
||||
[_storages removeObjectForKey: [NSNumber numberWithInteger: storageType]];
|
||||
});
|
||||
}
|
||||
|
||||
- (USRVStorage *)getStorage: (UnityServicesStorageType)storageType {
|
||||
__block USRVStorage *result = NULL;
|
||||
|
||||
|
|
|
@ -63,6 +63,14 @@
|
|||
return nextState;
|
||||
}
|
||||
} else if (configError && self.retries < [self.configuration maxRetries]) {
|
||||
if (configError.code == kPrivacyGameIdDisabledCode) {
|
||||
id nextState = [[USRVInitializeStateError alloc] initWithConfiguration: self.configuration
|
||||
erroredState: self
|
||||
code: kUADSErrorStateNetworkConfigRequest
|
||||
message: @"GameId disabled"];
|
||||
return nextState;
|
||||
}
|
||||
|
||||
self.retryDelay = self.retryDelay * [self.configuration retryScalingFactor];
|
||||
self.retries++;
|
||||
[[UADSInitializeEventsMetricSender sharedInstance] didRetryConfig];
|
||||
|
@ -114,26 +122,34 @@
|
|||
andCompletion: (void (^)(void))completion
|
||||
error:(void (^)(NSError * _Nonnull))error {
|
||||
if (configError && self.retries < [self.configuration maxRetries]) {
|
||||
self.retryDelay = self.retryDelay * [self.configuration retryScalingFactor];
|
||||
self.retries++;
|
||||
[[UADSInitializeEventsMetricSender sharedInstance] didRetryConfig];
|
||||
USRVInitializeStateConfig *retryState = [[USRVInitializeStateConfig alloc] initWithConfiguration: self.localConfig];
|
||||
retryState.configuration = self.localConfig;
|
||||
retryState.localConfig = self.localConfig;
|
||||
[retryState setRetries: self.retries];
|
||||
[retryState setRetryDelay: self.retryDelay];
|
||||
retryState.configLoader = self.configLoader;
|
||||
if (configError.code == kPrivacyGameIdDisabledCode) {
|
||||
id nextState = [[USRVInitializeStateError alloc] initWithConfiguration: self.configuration
|
||||
erroredState: self
|
||||
code: kUADSErrorStateNetworkConfigRequest
|
||||
message: @"GameId disabled"];
|
||||
[nextState startWithCompletion:completion error:error];
|
||||
} else {
|
||||
self.retryDelay = self.retryDelay * [self.configuration retryScalingFactor];
|
||||
self.retries++;
|
||||
[[UADSInitializeEventsMetricSender sharedInstance] didRetryConfig];
|
||||
USRVInitializeStateConfig *retryState = [[USRVInitializeStateConfig alloc] initWithConfiguration: self.localConfig];
|
||||
retryState.configuration = self.localConfig;
|
||||
retryState.localConfig = self.localConfig;
|
||||
[retryState setRetries: self.retries];
|
||||
[retryState setRetryDelay: self.retryDelay];
|
||||
retryState.configLoader = self.configLoader;
|
||||
|
||||
id nextState = [[USRVInitializeStateRetry alloc] initWithConfiguration: self.localConfig
|
||||
retryState: retryState
|
||||
retryDelay: self.retryDelay];
|
||||
[nextState startWithCompletion:^{
|
||||
self.retries = retryState.retries;
|
||||
completion();
|
||||
} error:^(NSError * _Nonnull er) {
|
||||
self.retries = retryState.retries;
|
||||
error(er);
|
||||
}];
|
||||
id nextState = [[USRVInitializeStateRetry alloc] initWithConfiguration: self.localConfig
|
||||
retryState: retryState
|
||||
retryDelay: self.retryDelay];
|
||||
[nextState startWithCompletion:^{
|
||||
self.retries = retryState.retries;
|
||||
completion();
|
||||
} error:^(NSError * _Nonnull er) {
|
||||
self.retries = retryState.retries;
|
||||
error(er);
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
USRVInitializeStateConfig *erroredState = [[USRVInitializeStateConfig alloc] initWithConfiguration: self.localConfig
|
||||
retries: self.retries
|
||||
|
|
|
@ -11,12 +11,12 @@ NSString *const kUnityServicesLocalCacheFilePrefix = @"UnityAdsCache-";
|
|||
NSString *const kUnityServicesLocalStorageFilePrefix = @"UnityAdsStorage-";
|
||||
NSString *const kUnityServicesWebviewBranchInfoDictionaryKey = @"UADSWebviewBranch";
|
||||
NSString *const kUnityServicesWebviewConfigInfoDictionaryKey = @"UADSWebviewConfig";
|
||||
NSString *const kUnityServicesVersionName = @"4.6.1";
|
||||
NSString *const kUnityServicesVersionName = @"4.7.0";
|
||||
NSString *const kUnityServicesFlavorDebug = @"debug";
|
||||
NSString *const kUnityServicesFlavorRelease = @"release";
|
||||
NSString *const kChinaIsoAlpha2Code = @"CN";
|
||||
NSString *const kChinaIsoAlpha3Code = @"CHN";
|
||||
int const kUnityServicesVersionCode = 4610;
|
||||
int const kUnityServicesVersionCode = 4700;
|
||||
|
||||
@implementation USRVSdkProperties
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
UADSMetric *other = (UADSMetric *)object;
|
||||
|
||||
return [self.name isEqual: other.name] &&
|
||||
((!self.value && !other.value) || [self.value isEqualToNumber: other.value]) &&
|
||||
// ((!self.value && !other.value) || [self.value isEqualToNumber: other.value]) &&
|
||||
((!self.tags && !other.tags) || [self.tags isEqualToDictionary: other.tags]);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
@interface USRVApiSKAdNetwork : NSObject
|
||||
@end
|
|
@ -1,24 +0,0 @@
|
|||
#import "USRVApiSKAdNetwork.h"
|
||||
#import "USRVWebViewCallback.h"
|
||||
#import "USRVSKAdNetworkProxy.h"
|
||||
|
||||
@implementation USRVApiSKAdNetwork
|
||||
|
||||
|
||||
+ (void)WebViewExposed_available: (USRVWebViewCallback *)callback {
|
||||
BOOL available = [[USRVSKAdNetworkProxy sharedInstance] available];
|
||||
|
||||
[callback invoke: [NSNumber numberWithBool: available], nil];
|
||||
}
|
||||
|
||||
+ (void)WebViewExposed_updateConversionValue: (NSInteger)conversionValue callback: (USRVWebViewCallback *)callback {
|
||||
[[USRVSKAdNetworkProxy sharedInstance] updateConversionValue: conversionValue];
|
||||
[callback invoke: nil];
|
||||
}
|
||||
|
||||
+ (void)WebViewExposed_registerAppForAdNetworkAttribution: (USRVWebViewCallback *)callback {
|
||||
[[USRVSKAdNetworkProxy sharedInstance] registerAppForAdNetworkAttribution];
|
||||
[callback invoke: nil];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,11 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "USRVWebViewApp.h"
|
||||
|
||||
@interface USRVSKAdNetworkProxy : NSObject
|
||||
|
||||
+ (USRVSKAdNetworkProxy *)sharedInstance;
|
||||
- (BOOL) available;
|
||||
- (void) updateConversionValue: (NSInteger)conversionValue;
|
||||
- (void) registerAppForAdNetworkAttribution;
|
||||
|
||||
@end
|
|
@ -1,105 +0,0 @@
|
|||
#import "USRVSKAdNetworkProxy.h"
|
||||
#import <dlfcn.h>
|
||||
#import <objc/runtime.h>
|
||||
#import "USRVDevice.h"
|
||||
|
||||
@interface USRVSKAdNetworkProxy ()
|
||||
@property (strong, nonatomic) Class skAdNetworkClass;
|
||||
@end
|
||||
|
||||
@implementation USRVSKAdNetworkProxy
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
if (![USRVSKAdNetworkProxy loadFramework]) {
|
||||
USRVLogDebug(@"Can't load StoreKit Dll");
|
||||
}
|
||||
|
||||
self.skAdNetworkClass = NSClassFromString(@"SKAdNetwork");
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)available {
|
||||
return self.skAdNetworkClass != nil;
|
||||
}
|
||||
|
||||
- (void)updateConversionValue: (NSInteger)conversionValue {
|
||||
if (!self.available) {
|
||||
return;
|
||||
}
|
||||
|
||||
SEL requestSelector = NSSelectorFromString(@"updateConversionValue:");
|
||||
|
||||
if ([self.skAdNetworkClass respondsToSelector: requestSelector]) {
|
||||
NSNumber *val = [NSNumber numberWithInteger: conversionValue];
|
||||
[self.skAdNetworkClass performSelector: requestSelector
|
||||
withObject: val];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)registerAppForAdNetworkAttribution {
|
||||
if (!self.available) {
|
||||
return;
|
||||
}
|
||||
|
||||
SEL requestSelector = NSSelectorFromString(@"registerAppForAdNetworkAttribution:");
|
||||
|
||||
if ([self.skAdNetworkClass respondsToSelector: requestSelector]) {
|
||||
[self.skAdNetworkClass performSelector: requestSelector];
|
||||
}
|
||||
}
|
||||
|
||||
+ (USRVSKAdNetworkProxy *)sharedInstance {
|
||||
static USRVSKAdNetworkProxy *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[USRVSKAdNetworkProxy alloc] init];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (BOOL)isFrameworkPresent {
|
||||
id attClass = objc_getClass("SKAdNetwork");
|
||||
|
||||
if (attClass) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)loadFramework {
|
||||
NSString *frameworkLocation;
|
||||
|
||||
if (![USRVSKAdNetworkProxy isFrameworkPresent]) {
|
||||
USRVLogDebug(@"StoreKit.framework is not present, trying to load it.");
|
||||
|
||||
if ([USRVDevice isSimulator]) {
|
||||
NSString *frameworkPath = [[NSProcessInfo processInfo] environment][@"DYLD_FALLBACK_FRAMEWORK_PATH"];
|
||||
|
||||
if (frameworkPath) {
|
||||
frameworkLocation = [NSString pathWithComponents: @[frameworkPath, @"StoreKit.framework", @"SkAdNetwork"]];
|
||||
}
|
||||
} else {
|
||||
frameworkLocation = [NSString stringWithFormat: @"/System/Library/Frameworks/StoreKit.framework/SkAdNetwork"];
|
||||
}
|
||||
|
||||
dlopen([frameworkLocation cStringUsingEncoding: NSUTF8StringEncoding], RTLD_LAZY);
|
||||
|
||||
if (![USRVSKAdNetworkProxy isFrameworkPresent]) {
|
||||
USRVLogError(@"StoreKit.framework still not present!");
|
||||
return NO;
|
||||
} else {
|
||||
USRVLogDebug(@"Succesfully loaded StoreKit.framework");
|
||||
return YES;
|
||||
}
|
||||
} else {
|
||||
USRVLogDebug(@"StoreKit.framework already present");
|
||||
return YES;
|
||||
}
|
||||
} /* loadFramework */
|
||||
|
||||
@end
|
|
@ -11,6 +11,7 @@
|
|||
#import "UADSWebRequestFactorySwiftAdapter.h"
|
||||
#import "UADSDeviceInfoReaderBuilder.h"
|
||||
#import "UADSSharedSessionIdReader.h"
|
||||
#import "USRVJsonStorageAggregator.h"
|
||||
|
||||
@interface UADSServiceProvider ()
|
||||
@property (nonatomic, strong) id<UADSPerformanceLogger>performanceLogger;
|
||||
|
@ -63,6 +64,21 @@
|
|||
[_privacyStorage saveResponse: [UADSInitializationResponse newFromDictionary:privacy]];
|
||||
}
|
||||
|
||||
- (id)getValueFromJSONStorageFor: (NSString *)key {
|
||||
return [USRVJsonStorageAggregator.defaultAggregator getValueForKey: key];
|
||||
}
|
||||
|
||||
- (id)storageContent {
|
||||
return [USRVJsonStorageAggregator.defaultAggregator getContents];
|
||||
}
|
||||
|
||||
- (void)deleteKeyFromJSONStorageFor: (NSString *)key {
|
||||
[[USRVStorageManager getStorage: kUnityServicesStorageTypePrivate] deleteKey:key];
|
||||
}
|
||||
-(void)setValueToJSONStorage:(id)value for: (NSString *)key {
|
||||
[[USRVStorageManager getStorage: kUnityServicesStorageTypePrivate] set:key value: value];
|
||||
}
|
||||
|
||||
- (id<UADSHeaderBiddingAsyncTokenReader, UADSHeaderBiddingTokenCRUD>)hbTokenReader {
|
||||
@synchronized (self) {
|
||||
if (!_hbTokenReader) {
|
||||
|
@ -102,6 +118,7 @@
|
|||
tokenReaderBuilder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
tokenReaderBuilder.scar = [UADSGMAScar sharedInstance];
|
||||
tokenReaderBuilder.requestFactory = self.webViewRequestFactory;
|
||||
tokenReaderBuilder.sharedSessionIdReader = self.sharedSessionIdReader;
|
||||
return tokenReaderBuilder;
|
||||
}
|
||||
|
||||
|
@ -162,25 +179,27 @@
|
|||
builder.logger = self.logger;
|
||||
builder.currentTimeStampReader = [UADSCurrentTimestampBase new];
|
||||
builder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
builder.sharedSessionIdReader = self.sharedSessionIdReader;
|
||||
return builder;
|
||||
}
|
||||
|
||||
- (id<UADSConfigurationLoader>)configurationLoader {
|
||||
UADSCClientConfigBase *config = [UADSCClientConfigBase defaultWithExperiments: self.experiments];
|
||||
UADSCClientConfigBase *config = [UADSCClientConfigBase defaultWithExperiments: self.experiments];
|
||||
|
||||
|
||||
UADSConfigurationLoaderBuilder *builder = [UADSConfigurationLoaderBuilder newWithConfig: config
|
||||
andWebRequestFactory: self.webViewRequestFactory
|
||||
metricSender: self.metricSender];
|
||||
|
||||
builder.privacyStorage = self.privacyStorage;
|
||||
builder.logger = self.logger;
|
||||
builder.configurationSaver = self.configurationSaver;
|
||||
builder.currentTimeStampReader = [UADSCurrentTimestampBase new];
|
||||
builder.retryInfoReader = self.retryReader;
|
||||
builder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
builder.metricsSender = self.metricSender;
|
||||
return builder.configurationLoader;
|
||||
|
||||
UADSConfigurationLoaderBuilder *builder = [UADSConfigurationLoaderBuilder newWithConfig: config
|
||||
andWebRequestFactory: self.webViewRequestFactory
|
||||
metricSender: self.metricSender];
|
||||
|
||||
builder.privacyStorage = self.privacyStorage;
|
||||
builder.logger = self.logger;
|
||||
builder.configurationSaver = self.configurationSaver;
|
||||
builder.currentTimeStampReader = [UADSCurrentTimestampBase new];
|
||||
builder.retryInfoReader = self.retryReader;
|
||||
builder.gameSessionIdReader = self.gameSessionIdReader;
|
||||
builder.metricsSender = self.metricSender;
|
||||
builder.sharedSessionIdReader = self.sharedSessionIdReader;
|
||||
return builder.configurationLoader;
|
||||
}
|
||||
|
||||
- (UADSConfigurationExperiments *)experiments {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#import "UADSSDKInitializerProxy.h"
|
||||
#import "NSPrimitivesBox.h"
|
||||
|
||||
static NSString *const kInitializeMethodName = @"initializeWithGameID:testMode:completion:error:";
|
||||
|
||||
|
@ -13,8 +14,9 @@ static NSString *const kInitializeMethodName = @"initializeWithGameID:testMode:c
|
|||
completion: (UADSVoidClosure)completion
|
||||
error: (UADSNSErrorCompletion)error {
|
||||
|
||||
NSPrimitivesBox *box = [NSPrimitivesBox newWithBytes: &testMode objCType: @encode(BOOL)];
|
||||
[self callInstanceMethod: kInitializeMethodName
|
||||
args:@[gameId, @(testMode), completion, error]];
|
||||
args:@[gameId, box, completion, error]];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSDictionary * _Nonnull (^UADSInfoGetter)(bool);
|
||||
typedef void (^UADSTokenCompletion)(NSDictionary *_Nonnull);
|
||||
|
||||
@protocol UADSNativeNetworkLayerProvider <NSObject>
|
||||
- (UADSCommonNetworkProxy *)nativeNetworkLayer;
|
||||
|
@ -20,6 +21,9 @@ typedef NSDictionary * _Nonnull (^UADSInfoGetter)(bool);
|
|||
- (UADSSDKInitializerProxy *)sdkInitializerWithFactory: (USRVInitializeStateFactory *)factory;
|
||||
- (void)setDebugMode: (BOOL)isDebugMode;
|
||||
- (InitializationState)currentState;
|
||||
- (NSNumber *)gameSessionId;
|
||||
- (NSString *)sessionId;
|
||||
- (void)getToken:(UADSTokenCompletion)completion;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -11,7 +11,9 @@ static NSString *const SAVE_CONFIGURATION_SELECTOR = @"saveSDKConfigFrom:";
|
|||
static NSString *const GET_CONFIGURATION_SELECTOR = @"configDictionary";
|
||||
static NSString *const SET_DEBUG_MODE_SELECTOR = @"setDebugMode:";
|
||||
static NSString *const CURRENT_STATE_KVO = @"currentState";
|
||||
|
||||
static NSString *const GAME_SESSION_ID_KVO = @"gameSessionId";
|
||||
static NSString *const SESSION_ID_KVO = @"sessionId";
|
||||
static NSString *const GET_TOKEN_SELECTOR = @"getToken:";
|
||||
|
||||
|
||||
@implementation UADSServiceProviderProxy
|
||||
|
@ -60,5 +62,18 @@ static NSString *const CURRENT_STATE_KVO = @"currentState";
|
|||
return state.intValue;
|
||||
}
|
||||
|
||||
- (NSNumber *)gameSessionId {
|
||||
NSNumber *gameSessionId = [self callInstanceMethodWithReturn:GAME_SESSION_ID_KVO args:@[]];
|
||||
return gameSessionId;
|
||||
}
|
||||
|
||||
- (NSString *)sessionId {
|
||||
return [self callInstanceMethodWithReturn:SESSION_ID_KVO args:@[]];
|
||||
}
|
||||
|
||||
|
||||
- (void)getToken:(UADSTokenCompletion)completion {
|
||||
[self callInstanceMethod:GET_TOKEN_SELECTOR args:@[completion]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol UADSIdStore
|
||||
|
||||
- (NSString *_Nullable)getValue;
|
||||
|
||||
- (void)commitValue:(NSString *)value;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,93 +0,0 @@
|
|||
#import "UADSInstallationId.h"
|
||||
#import "UADSIdStore.h"
|
||||
#import "UADSUnityPlayerPrefsStore.h"
|
||||
#import "UADSUserDefaultsStore.h"
|
||||
|
||||
@interface UADSInstallationId ()
|
||||
|
||||
@property(nonatomic, strong) NSString *_Nullable savedInstallationId;
|
||||
@property(nonatomic, strong) id<UADSIdStore> installationIdStore;
|
||||
@property(nonatomic, strong) id<UADSIdStore> analyticsIdStore;
|
||||
@property(nonatomic, strong) id<UADSIdStore> unityAdsIdStore;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UADSInstallationId
|
||||
|
||||
+ (instancetype)shared {
|
||||
static UADSInstallationId *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[UADSInstallationId alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
// https://github.cds.internal.unity3d.com/unity/operate-services-sample/blob/c4fad12071bb3a74aa9631c7c4cce12112fd0156/ZippedPackages/com.unity.services.core-1.1.0-pre.8/Runtime/Device/InstallationId.cs
|
||||
UADSUnityPlayerPrefsStore *installationIdStore =
|
||||
[[UADSUnityPlayerPrefsStore alloc] initWithKey:@"UnityInstallationId"];
|
||||
UADSUnityPlayerPrefsStore *analyticsIdStore =
|
||||
[[UADSUnityPlayerPrefsStore alloc] initWithKey:@"unity.cloud_userid"];
|
||||
UADSUserDefaultsStore *unityAdsIdStore =
|
||||
[[UADSUserDefaultsStore alloc] initWithKey:@"unityads-idfi"];
|
||||
self = [self initWithInstallationIdStore:installationIdStore
|
||||
analyticsIdStore:analyticsIdStore
|
||||
unityAdsIdStore:unityAdsIdStore];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithInstallationIdStore:(id<UADSIdStore>)installationIdStore
|
||||
analyticsIdStore:(id<UADSIdStore>)analyticsIdStore
|
||||
unityAdsIdStore:(id<UADSIdStore>)unityAdsIdStore {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_installationIdStore = installationIdStore;
|
||||
_analyticsIdStore = analyticsIdStore;
|
||||
_unityAdsIdStore = unityAdsIdStore;
|
||||
|
||||
[self readInstallationId];
|
||||
[self writeInstallationId];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)installationId {
|
||||
return self.savedInstallationId;
|
||||
}
|
||||
|
||||
- (void)readInstallationId {
|
||||
// Check core services installation id
|
||||
NSString *installationId = [self.installationIdStore getValue];
|
||||
if (installationId) {
|
||||
self.savedInstallationId = installationId;
|
||||
return;
|
||||
}
|
||||
// Check analytics
|
||||
NSString *analyticsId = [self.analyticsIdStore getValue];
|
||||
if (analyticsId) {
|
||||
self.savedInstallationId = analyticsId;
|
||||
return;
|
||||
}
|
||||
// Check Unity Ads
|
||||
NSString *unityAdsId = [self.unityAdsIdStore getValue];
|
||||
if (unityAdsId) {
|
||||
self.savedInstallationId = unityAdsId;
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate id and write it to user defaults if none is found.
|
||||
NSString *generatedInstallationId = [[NSUUID UUID] UUIDString];
|
||||
self.savedInstallationId = generatedInstallationId;
|
||||
}
|
||||
|
||||
- (void)writeInstallationId {
|
||||
[self.installationIdStore commitValue:self.savedInstallationId];
|
||||
[self.analyticsIdStore commitValue:self.savedInstallationId];
|
||||
[self.unityAdsIdStore commitValue:self.savedInstallationId];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,22 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSPlist : NSObject
|
||||
|
||||
+ (BOOL)writePlistIosEleven:(NSDictionary *)mutableDictionary
|
||||
toFileUrl:(NSURL *)url API_AVAILABLE(ios(11));
|
||||
|
||||
+ (BOOL)writePlistIosTen:(NSDictionary *)mutableDictionary toFileUrl:(NSURL *)url;
|
||||
|
||||
+ (void)writePlist:(NSDictionary *)mutableDictionary toFileUrl:(NSURL *)url;
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURLIosEleven:(NSURL *)url API_AVAILABLE(ios(11));
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURLIosTen:(NSURL *)url;
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURL:(NSURL *)url;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,48 +0,0 @@
|
|||
#import "UADSPlist.h"
|
||||
|
||||
@implementation UADSPlist
|
||||
|
||||
+ (BOOL)writePlistIosEleven:(NSDictionary *)mutableDictionary
|
||||
toFileUrl:(NSURL *)url API_AVAILABLE(ios(11)) {
|
||||
return [mutableDictionary writeToURL:url error:nil];
|
||||
}
|
||||
|
||||
+ (BOOL)writePlistIosTen:(NSDictionary *)mutableDictionary toFileUrl:(NSURL *)url {
|
||||
return [mutableDictionary writeToURL:url atomically:YES];
|
||||
}
|
||||
|
||||
+ (void)writePlist:(NSDictionary *)mutableDictionary toFileUrl:(NSURL *)url {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
// We don't care if there is an error.
|
||||
[UADSPlist writePlistIosEleven:mutableDictionary toFileUrl:url];
|
||||
} else {
|
||||
[UADSPlist writePlistIosTen:mutableDictionary toFileUrl:url];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURLIosEleven:(NSURL *)url
|
||||
API_AVAILABLE(ios(11)) {
|
||||
NSError *plistError;
|
||||
NSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfURL:url error:&plistError];
|
||||
if (plistError) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return plistDictionary;
|
||||
}
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURLIosTen:(NSURL *)url {
|
||||
NSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfURL:url];
|
||||
|
||||
return plistDictionary;
|
||||
}
|
||||
|
||||
+ (NSDictionary *_Nullable)dictionaryWithContentsOfURL:(NSURL *)url {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
return [UADSPlist dictionaryWithContentsOfURLIosEleven:url];
|
||||
} else {
|
||||
return [UADSPlist dictionaryWithContentsOfURLIosTen:url];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,36 +0,0 @@
|
|||
#import "UADSSessionId.h"
|
||||
#import "UADSIdStore.h"
|
||||
#import "UADSUnityPlayerPrefsStore.h"
|
||||
#import "UADSUserDefaultsStore.h"
|
||||
|
||||
@interface UADSSessionId ()
|
||||
|
||||
@property(nonatomic, strong) NSString *_Nullable currentSessionId;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UADSSessionId
|
||||
|
||||
+ (instancetype)shared {
|
||||
static UADSSessionId *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[UADSSessionId alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_currentSessionId = [[NSUUID UUID] UUIDString];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)sessionId {
|
||||
return self.currentSessionId;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "UADSIdStore.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSUnityPlayerPrefsStore : NSObject <UADSIdStore>
|
||||
|
||||
- (instancetype)initWithKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,65 +0,0 @@
|
|||
#import "UADSUnityPlayerPrefsStore.h"
|
||||
#import "UADSPlist.h"
|
||||
|
||||
@interface UADSUnityPlayerPrefsStore ()
|
||||
|
||||
@property(nonatomic, strong) NSString *key;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UADSUnityPlayerPrefsStore
|
||||
|
||||
- (instancetype)initWithKey:(NSString *)key {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_key = key;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *_Nullable)getValue {
|
||||
NSDictionary *plistDictionary = [self plistDictionary];
|
||||
id value = [plistDictionary valueForKey:self.key];
|
||||
if (value && [value isKindOfClass:[NSString class]]) {
|
||||
return (NSString *)value;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)commitValue:(NSString *)value {
|
||||
NSDictionary *plistDictionary = [self plistDictionary];
|
||||
NSURL *plistFileUrl = [self plistFileUrl];
|
||||
|
||||
if (plistFileUrl) {
|
||||
NSMutableDictionary *mutablePlistDictionary = [plistDictionary mutableCopy];
|
||||
[mutablePlistDictionary setValue:value forKey:self.key];
|
||||
[UADSPlist writePlist:mutablePlistDictionary toFileUrl:plistFileUrl];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)plistDictionary {
|
||||
NSURL *fileUrl = [self plistFileUrl];
|
||||
NSDictionary *plistDictionary = [UADSPlist dictionaryWithContentsOfURL:fileUrl];
|
||||
if (!plistDictionary) {
|
||||
return [[NSDictionary alloc] init];
|
||||
}
|
||||
|
||||
return plistDictionary;
|
||||
}
|
||||
|
||||
- (NSURL *_Nullable)plistFileUrl {
|
||||
NSURL *_Nullable url = [NSURL fileURLWithPath:[self plistFilePath]];
|
||||
return url;
|
||||
}
|
||||
|
||||
// The file path According to the Unity PlayerPrefs Documenation :
|
||||
// https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
|
||||
// ~/Library/Preferences/com.ExampleCompanyName.ExampleProductName.plist
|
||||
- (NSString *_Nullable)plistFilePath {
|
||||
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
|
||||
return [[NSString stringWithFormat:@"~/Library/Preferences/%@.plist", bundleIdentifier]
|
||||
stringByExpandingTildeInPath];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,12 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "UADSIdStore.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UADSUserDefaultsStore : NSObject <UADSIdStore>
|
||||
|
||||
- (instancetype)initWithKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,29 +0,0 @@
|
|||
#import "UADSUserDefaultsStore.h"
|
||||
|
||||
@interface UADSUserDefaultsStore ()
|
||||
|
||||
@property(nonatomic, strong) NSString *key;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UADSUserDefaultsStore
|
||||
|
||||
- (instancetype)initWithKey:(NSString *)key {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_key = key;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *_Nullable)getValue {
|
||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
||||
return [userDefaults stringForKey:self.key];
|
||||
}
|
||||
|
||||
- (void)commitValue:(NSString *)value {
|
||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
||||
[userDefaults setObject:value forKey:self.key];
|
||||
}
|
||||
|
||||
@end
|
|
@ -33,7 +33,5 @@ FOUNDATION_EXPORT const unsigned char UnityAdsModuleVersionString[];
|
|||
#import <UnityAds/USRVInitializeStateFactory.h>
|
||||
#import <UnityAds/USRVInitializeStateType.h>
|
||||
#import <UnityAds/UADSDeviceInfoProvider.h>
|
||||
#import <UnityAds/UADSInstallationId.h>
|
||||
#import <UnityAds/UADSSessionId.h>
|
||||
|
||||
#endif /* UnityAds_h */
|
||||
|
|
|
@ -124,19 +124,34 @@
|
|||
[UnityServices setDebugMode: [USRVSdkProperties getDebugMode]];
|
||||
[USRVClientProperties setGameId: gameId];
|
||||
[USRVSdkProperties setTestMode: testMode];
|
||||
|
||||
|
||||
[UADSServiceProviderContainer.sharedInstance.serviceProvider.sdkInitializer initializeWithGameID: gameId
|
||||
testMode:testMode
|
||||
completion:^{
|
||||
[USRVSdkProperties setInitializationState: INITIALIZED_SUCCESSFULLY];
|
||||
testMode:testMode
|
||||
completion:^{
|
||||
[USRVSdkProperties setInitializationState: INITIALIZED_SUCCESSFULLY];
|
||||
|
||||
} error:^(NSError * _Nonnull error) {
|
||||
|
||||
[USRVSdkProperties setInitializationState: INITIALIZED_FAILED];
|
||||
}];
|
||||
} error:^(NSError * _Nonnull error) {
|
||||
[self onInitError:error];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)onInitError: (NSError *)error {
|
||||
[UADSServiceProviderContainer.sharedInstance.serviceProvider.hbTokenReader setInitToken: nil];
|
||||
[UADSServiceProviderContainer.sharedInstance.serviceProvider.hbTokenReader deleteTokens];
|
||||
|
||||
[USRVSdkProperties setInitializationState: INITIALIZED_FAILED];
|
||||
|
||||
[[USRVInitializationNotificationCenter sharedInstance] triggerSdkInitializeDidFail: @"Unity Ads SDK failed to initialize"
|
||||
code: error.code];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[USRVSdkProperties notifyInitializationFailed: kUnityInitializationErrorInternalError
|
||||
withErrorMessage: error.localizedDescription];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
+ (BOOL)getDebugMode {
|
||||
return [USRVSdkProperties getDebugMode];
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UADSInstallationId handles generating or retrieving an installation id across Unity services.
|
||||
*/
|
||||
@interface UADSInstallationId : NSObject
|
||||
|
||||
/**
|
||||
* Static method to return a singleton instance of UADSInstallationId.
|
||||
*
|
||||
* @return UADSInstallationId
|
||||
*/
|
||||
+ (instancetype)shared;
|
||||
|
||||
/**
|
||||
* Method to get the string installation id.
|
||||
*
|
||||
* @return NSString
|
||||
*/
|
||||
- (NSString *)installationId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1,27 +0,0 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* UADSSessionId handles generating a shared user sessionId to be used across Unity services.
|
||||
* Use this id to tie data from the same session together.
|
||||
*/
|
||||
@interface UADSSessionId : NSObject
|
||||
|
||||
/**
|
||||
* Static method to return a singleton instance of UADSSessionId.
|
||||
*
|
||||
* @return UADSSessionId
|
||||
*/
|
||||
+ (instancetype)shared;
|
||||
|
||||
/**
|
||||
* Method to get the string session UUID.
|
||||
*
|
||||
* @return NSString
|
||||
*/
|
||||
- (NSString *)sessionId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,83 @@
|
|||
import Foundation
|
||||
import AVFoundation
|
||||
import UIKit
|
||||
|
||||
extension WebUserAgentReaderBase {
|
||||
static var unityAdsAgent: WebUserAgentReader {
|
||||
WebUserAgentReaderBase(lastKnownOSKey: Constants.UserDefaultsKeys.LastKnownSystemVersion,
|
||||
userAgentValueKey: Constants.UserDefaultsKeys.LastKnownUserAgentKey)
|
||||
}
|
||||
}
|
||||
|
||||
final class DeviceInfoBodyReaderBuilder: DeviceInfoBodyReaderProvider {
|
||||
|
||||
private let baseConfig: Config
|
||||
private(set) var getLegacyInfo: ClosureWithReturn<Bool, [String: Any]>?
|
||||
private let deviceInfoReader: DeviceInfoReader
|
||||
init(baseConfig: Config) {
|
||||
self.baseConfig = baseConfig
|
||||
|
||||
let deviceInfoConfig = DeviceInfoReaderBase.Config(timeReader: baseConfig.timeReader,
|
||||
logger: baseConfig.logger,
|
||||
userAgentReader: WebUserAgentReaderBase.unityAdsAgent,
|
||||
sessionInfoProvider: baseConfig.sessionInfoStorage,
|
||||
gameSettingsReader: baseConfig.gameSettingsReader,
|
||||
appStartTimeProvider: baseConfig.sdkStateStorage,
|
||||
telephonyInfoProvider: baseConfig.telephonyInfoProvider)
|
||||
deviceInfoReader = DeviceInfoReaderBase(config: deviceInfoConfig)
|
||||
}
|
||||
|
||||
var deviceInfoBodyReader: DeviceInfoBodyStrategy {
|
||||
self.reader(using: baseConfig)
|
||||
}
|
||||
|
||||
func setLegacyInfoGetter(_ closure: ClosureWithReturn<Bool, [String: Any]>?) {
|
||||
getLegacyInfo = closure
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DeviceInfoBodyReaderBuilder {
|
||||
private func reader(using config: Config) -> DeviceInfoBodyStrategy {
|
||||
let minStorageReader = JSONStorageContentNormalizer.minStorageContentReader(with: config.persistenceStorage)
|
||||
let extendedStorageReader = JSONStorageContentNormalizer.extendedStorageContentReader(with: config.persistenceStorage)
|
||||
|
||||
let strategyConfig = DeviceInfoBodyStrategyBase.Config(sessionInfoStorage: config.sessionInfoStorage,
|
||||
trackingStatusReader: config.trackingStatusReader,
|
||||
gameIdProvider: config.gameSettingsReader,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
privacyReader: config.sdkStateStorage,
|
||||
piiDataProvider: config.piiDataProvider,
|
||||
minStorageContentReader: minStorageReader,
|
||||
extendedStorageContentReader: extendedStorageReader)
|
||||
|
||||
var base: DeviceInfoBodyStrategy = DeviceInfoBodyStrategyBase(config: strategyConfig)
|
||||
|
||||
base = DeviceInfoBodyReaderWithMetrics(original: base,
|
||||
measurer: baseConfig.performanceMeasurer,
|
||||
metricsSender: baseConfig.metricsSender)
|
||||
let decoratorConfig = DeviceInfoObjBridgeDecorator.Config(logger: config.logger,
|
||||
experimentsReader: config.sdkStateStorage,
|
||||
original: base,
|
||||
getLegacyInfo: getLegacyInfo)
|
||||
return DeviceInfoObjBridgeDecorator(config: decoratorConfig)
|
||||
}
|
||||
}
|
||||
|
||||
extension DeviceInfoBodyReaderBuilder {
|
||||
typealias TimeInfoReader = BootTimeReader & TimeZoneReader & TimeReader
|
||||
struct Config {
|
||||
let sessionInfoStorage: SessionInfoReader
|
||||
let trackingStatusReader: TrackingStatusReader
|
||||
let gameSettingsReader: SDKGameSettingsProvider
|
||||
let sdkStateStorage: PrivacyStateReader & ExperimentsReader & AppStartTimeProvider
|
||||
var piiDataProvider: UIDevicePIIDataProvider = UIDevice.current
|
||||
let persistenceStorage: JSONStorageBridge
|
||||
let logger: Logger
|
||||
let timeReader: TimeInfoReader
|
||||
let telephonyInfoProvider: TelephonyInfoProvider & CountryCodeProvider
|
||||
let performanceMeasurer: PerformanceMeasurer<String>
|
||||
let metricsSender: MetricSender
|
||||
}
|
||||
|
||||
}
|
|
@ -4,29 +4,39 @@ protocol InitializationStateSubject {
|
|||
func subscribe(_ block: @escaping ResultClosure<Void>)
|
||||
}
|
||||
|
||||
protocol AppStartTimeSaver {
|
||||
func save(startTime: TimeInterval)
|
||||
}
|
||||
final class SDKStateStorage: GenericMediator<UResult<Void>>,
|
||||
InitializationStateSubject,
|
||||
MetricsSenderBatchConditionSubject,
|
||||
UnityAdsConfigurationProvider,
|
||||
UnityAdsLocalConfigurationLoader,
|
||||
RetriesInfoStorage {
|
||||
let retriesInfoStorage: RetriesInfoWriter & RetriesInfoReader = RetriesInfoStorageBase()
|
||||
|
||||
typealias ConfigProvider = UnityAdsConfigurationProvider &
|
||||
UnityAdsLocalConfigurationLoader &
|
||||
UnityAdsConfigSubject &
|
||||
ExperimentsReader
|
||||
|
||||
@Atomic var currentState: SDKInitializerBase.State = .notInitialized {
|
||||
didSet {
|
||||
notifyStateChange()
|
||||
}
|
||||
@Atomic private var startTimeStamp: TimeInterval = 0
|
||||
|
||||
@Atomic private var initializeState: SDKInitializerBase.State = .notInitialized
|
||||
|
||||
private let privacyStorage = PrivacyStateStorage()
|
||||
|
||||
private(set) var configProvider: ConfigProvider
|
||||
|
||||
init(configProvider: ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
}
|
||||
|
||||
var webViewConfig: UnityAdsConfig.Network.WebView {
|
||||
guard !privacyStorage.privacyResponse.webViewConfig.url.isEmpty else {
|
||||
guard !privacyStorage.$privacyResponse.load().webViewConfig.url.isEmpty else {
|
||||
return config.network.webView
|
||||
}
|
||||
return privacyStorage.privacyResponse.webViewConfig
|
||||
return privacyStorage.$privacyResponse.load().webViewConfig
|
||||
}
|
||||
|
||||
var config: UnityAdsConfig {
|
||||
|
@ -34,13 +44,12 @@ final class SDKStateStorage: GenericMediator<UResult<Void>>,
|
|||
set { configProvider.config = newValue }
|
||||
}
|
||||
|
||||
private let privacyStorage = PrivacyStateStorage()
|
||||
|
||||
private(set) var configProvider: ConfigProvider
|
||||
let retriesInfoStorage: RetriesInfoWriter & RetriesInfoReader = RetriesInfoStorageBase()
|
||||
|
||||
init(configProvider: ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
var currentState: SDKInitializerBase.State {
|
||||
get { _initializeState.load() }
|
||||
set {
|
||||
_initializeState.mutate({ $0 = newValue })
|
||||
notifyStateChange()
|
||||
}
|
||||
}
|
||||
|
||||
// Metric Condition subscribes to be able to release batch on failure or success.
|
||||
|
@ -67,6 +76,8 @@ final class SDKStateStorage: GenericMediator<UResult<Void>>,
|
|||
}
|
||||
|
||||
extension SDKStateStorage: PrivacyStateReader, PrivacyResponseSaver {
|
||||
var shouldSendNonBehavioural: Bool { privacyStorage.shouldSendNonBehavioural }
|
||||
|
||||
var privacyState: PrivacyState { privacyStorage.privacyState }
|
||||
|
||||
func save(response: PrivacyResponse) {
|
||||
|
@ -88,19 +99,6 @@ extension SDKStateStorage: ExperimentsReader, SessionTokenReader {
|
|||
}
|
||||
}
|
||||
|
||||
final class PrivacyStateStorage: GenericMediator<UResult<PrivacyResponse>>,
|
||||
PrivacyStateReader,
|
||||
PrivacyResponseSaver {
|
||||
@Atomic var privacyResponse: PrivacyResponse = .empty
|
||||
|
||||
var privacyState: PrivacyState { privacyResponse.state }
|
||||
|
||||
func save(response: PrivacyResponse) {
|
||||
privacyResponse = response
|
||||
notifyObservers(with: .success(privacyResponse))
|
||||
}
|
||||
}
|
||||
|
||||
extension SDKStateStorage {
|
||||
func retryInfo() -> [String: String] {
|
||||
retriesInfoStorage.retryInfo()
|
||||
|
@ -110,3 +108,14 @@ extension SDKStateStorage {
|
|||
retriesInfoStorage.set(retried: retried, task: task)
|
||||
}
|
||||
}
|
||||
|
||||
extension SDKStateStorage: AppStartTimeSaver, AppStartTimeProvider {
|
||||
|
||||
var appStartTime: TimeInterval {
|
||||
_startTimeStamp.load()
|
||||
}
|
||||
|
||||
func save(startTime: TimeInterval) {
|
||||
_startTimeStamp.mutate({ $0 = startTime })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,25 +3,37 @@ import Foundation
|
|||
final class InitializationTaskFactoryBase: TaskFactory {
|
||||
typealias SettingsProvider = LoggerSettingsReader
|
||||
private let downloaderBuilder: WebViewDownloadBuilder
|
||||
private let networkSenderProvider: MetricsSenderProvider & UnityAdsNetworkSenderProvider
|
||||
private let metricSenderProvider: MetricsSenderProvider
|
||||
private let objcFactory: USRVInitializeStateFactory
|
||||
private let performanceMeasurer: PerformanceMeasurer<String>
|
||||
private let sdkStateStorage: SDKStateStorage
|
||||
private let settingsProvider: SettingsProvider
|
||||
private var networkConfig: UnityAdsConfig.Network { sdkStateStorage.networkConfig }
|
||||
private let keyValueStorage: KeyValueStorage
|
||||
private let cleanupKeys: [String]
|
||||
private let deviceInfoReader: DeviceInfoBodyStrategy
|
||||
private let networkSenderProvider: UnityAdsNetworkSenderProvider
|
||||
|
||||
init(downloaderBuilder: WebViewDownloadBuilder,
|
||||
metricSenderProvider: MetricsSenderProvider & UnityAdsNetworkSenderProvider,
|
||||
metricSenderProvider: MetricsSenderProvider,
|
||||
networkSenderProvider: UnityAdsNetworkSenderProvider,
|
||||
sdkStateStorage: SDKStateStorage,
|
||||
performanceMeasurer: PerformanceMeasurer<String>,
|
||||
stateFactoryObjc: USRVInitializeStateFactory = .init(),
|
||||
settingsProvider: SettingsProvider) {
|
||||
settingsProvider: SettingsProvider,
|
||||
keyValueStorage: KeyValueStorage,
|
||||
cleanupKeys: [String],
|
||||
deviceInfoReader: DeviceInfoBodyStrategy) {
|
||||
self.downloaderBuilder = downloaderBuilder
|
||||
self.objcFactory = stateFactoryObjc
|
||||
self.networkSenderProvider = metricSenderProvider
|
||||
self.metricSenderProvider = metricSenderProvider
|
||||
self.networkSenderProvider = networkSenderProvider
|
||||
self.performanceMeasurer = performanceMeasurer
|
||||
self.sdkStateStorage = sdkStateStorage
|
||||
self.settingsProvider = settingsProvider
|
||||
self.keyValueStorage = keyValueStorage
|
||||
self.cleanupKeys = cleanupKeys
|
||||
self.deviceInfoReader = deviceInfoReader
|
||||
}
|
||||
|
||||
func task(of type: InitTaskState) -> Task {
|
||||
|
@ -51,7 +63,7 @@ extension InitializationTaskFactoryBase {
|
|||
|
||||
extension InitializationTaskFactoryBase {
|
||||
var metricSender: MetricSender {
|
||||
networkSenderProvider.metricsSender
|
||||
metricSenderProvider.metricsSender
|
||||
}
|
||||
|
||||
var requestRetryConfig: RetriableOperationConfig {
|
||||
|
@ -76,7 +88,13 @@ extension InitializationTaskFactoryBase {
|
|||
case .reset:
|
||||
let legacy = taskForObjcType(type)
|
||||
return useNewTasksFlow ? PreviousSessionCleanupTask(loggerSettingsReader: settingsProvider,
|
||||
legacyTask: legacy) : legacy
|
||||
legacyTask: legacy,
|
||||
storage: keyValueStorage,
|
||||
cleanupKeys: cleanupKeys) : legacy
|
||||
case .initModules:
|
||||
let legacy = taskForObjcType(type)
|
||||
return useNewTasksFlow ? InitModulesTask(legacyTask: legacy,
|
||||
deviceInfoReader: deviceInfoReader) : legacy
|
||||
default:
|
||||
return taskForObjcType(type)
|
||||
}
|
||||
|
|
|
@ -5,18 +5,26 @@ final class InitializationTaskFactoryStrategy: TaskFactory {
|
|||
private let factoryBase: InitializationTaskFactoryBase
|
||||
|
||||
init(downloaderBuilder: WebViewDownloadBuilder,
|
||||
metricSenderProvider: MetricsSenderProvider & UnityAdsNetworkSenderProvider,
|
||||
metricSenderProvider: MetricsSenderProvider,
|
||||
networkSenderProvider: UnityAdsNetworkSenderProvider,
|
||||
sdkStateStorage: SDKStateStorage,
|
||||
performanceMeasurer: PerformanceMeasurer<String>,
|
||||
stateFactoryObjc: USRVInitializeStateFactory = .init(),
|
||||
settingsProvider: SettingsProvider) {
|
||||
settingsProvider: SettingsProvider,
|
||||
keyValueStorage: KeyValueStorage,
|
||||
cleanupKeys: [String],
|
||||
deviceInfoReader: DeviceInfoBodyStrategy) {
|
||||
|
||||
self.factoryBase = .init(downloaderBuilder: downloaderBuilder,
|
||||
metricSenderProvider: metricSenderProvider,
|
||||
networkSenderProvider: networkSenderProvider,
|
||||
sdkStateStorage: sdkStateStorage,
|
||||
performanceMeasurer: performanceMeasurer,
|
||||
stateFactoryObjc: stateFactoryObjc,
|
||||
settingsProvider: settingsProvider)
|
||||
settingsProvider: settingsProvider,
|
||||
keyValueStorage: keyValueStorage,
|
||||
cleanupKeys: cleanupKeys,
|
||||
deviceInfoReader: deviceInfoReader)
|
||||
}
|
||||
|
||||
func task(of type: InitTaskCategory) -> Task {
|
||||
|
|
|
@ -17,8 +17,8 @@ final class SDKInitializerBase: SDKInitializer {
|
|||
}
|
||||
|
||||
private var initConfig: SDKInitializerConfig {
|
||||
get { settingsStorage.currentInitConfig }
|
||||
set { settingsStorage.currentInitConfig = newValue }
|
||||
get { settingsStorage.$currentInitConfig.load() }
|
||||
set { settingsStorage.$currentInitConfig.mutate({ $0 = newValue }) }
|
||||
}
|
||||
|
||||
init(task: Task,
|
||||
|
@ -37,6 +37,12 @@ final class SDKInitializerBase: SDKInitializer {
|
|||
private extension SDKInitializerBase {
|
||||
func startInitialization(with config: SDKInitializerConfig, completion: @escaping ResultClosure<Void>) {
|
||||
completions = completions.appended(completion)
|
||||
|
||||
if !isGameIdValid(config) {
|
||||
notifySavedCompletionsAndClean(with: .failure(InvalidGameId()))
|
||||
return
|
||||
}
|
||||
|
||||
switch state {
|
||||
case .notInitialized:
|
||||
changeStatusAndStartTheTask(config: config)
|
||||
|
@ -47,7 +53,6 @@ private extension SDKInitializerBase {
|
|||
case .initialized:
|
||||
notifySavedCompletionsAndClean(with: VoidSuccess)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func changeStatusAndStartTheTask(config: SDKInitializerConfig) {
|
||||
|
@ -55,6 +60,10 @@ private extension SDKInitializerBase {
|
|||
startTask()
|
||||
}
|
||||
|
||||
func isGameIdValid(_ config: SDKInitializerConfig) -> Bool {
|
||||
return Int(config.gameID) != nil
|
||||
}
|
||||
|
||||
func setInProgress(for config: SDKInitializerConfig) {
|
||||
initConfig = config
|
||||
state = .inProcess
|
||||
|
@ -85,9 +94,11 @@ private extension SDKInitializerBase {
|
|||
|
||||
public struct SDKInitializerConfig {
|
||||
public let gameID: String
|
||||
|
||||
public init(gameID: String) {
|
||||
public let isTestModeEnabled: Bool
|
||||
public init(gameID: String,
|
||||
isTestModeEnabled: Bool) {
|
||||
self.gameID = gameID
|
||||
self.isTestModeEnabled = isTestModeEnabled
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,3 +122,9 @@ extension SDKInitializerBase {
|
|||
case initialized
|
||||
}
|
||||
}
|
||||
|
||||
struct InvalidGameId: LocalizedError {
|
||||
var errorDescription: String? {
|
||||
return "GameId should be a number"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
protocol SharedSessionIdReader {
|
||||
var sessionId: String { get }
|
||||
}
|
||||
|
||||
class SharedSessionIdReaderBase: SharedSessionIdReader {
|
||||
var sessionId: String {
|
||||
UADSSessionId.shared().sessionId()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import Foundation
|
||||
|
||||
final class InitModulesTask: PerformanceMeasurableTask {
|
||||
var startEventName: String?
|
||||
var resultMetrics: ResultMetrics.Type { Constants.Metrics.Task.InitModules.self }
|
||||
|
||||
private let legacyTask: PerformanceMeasurableTask
|
||||
private let deviceInfoReader: DeviceInfoBodyStrategy
|
||||
|
||||
init(legacyTask: PerformanceMeasurableTask,
|
||||
deviceInfoReader: DeviceInfoBodyStrategy) {
|
||||
self.legacyTask = legacyTask
|
||||
self.deviceInfoReader = deviceInfoReader
|
||||
}
|
||||
|
||||
func start(completion: @escaping ResultClosure<Void>) {
|
||||
initDeviceStaticInfo()
|
||||
legacyTask.start(completion: completion)
|
||||
}
|
||||
|
||||
private func initDeviceStaticInfo() {
|
||||
deviceInfoReader.initializeStaticInfo()
|
||||
}
|
||||
|
||||
}
|
|
@ -6,16 +6,23 @@ final class PreviousSessionCleanupTask: PerformanceMeasurableTask {
|
|||
private let loggerSettingsReader: LoggerSettingsReader
|
||||
private let fileManager: FileManager
|
||||
private let legacyTask: PerformanceMeasurableTask
|
||||
private let storage: KeyValueStorage
|
||||
private let cleanupKeys: [String]
|
||||
init(loggerSettingsReader: LoggerSettingsReader,
|
||||
fileManager: FileManager = .default,
|
||||
legacyTask: PerformanceMeasurableTask) {
|
||||
legacyTask: PerformanceMeasurableTask,
|
||||
storage: KeyValueStorage,
|
||||
cleanupKeys: [String]) {
|
||||
self.loggerSettingsReader = loggerSettingsReader
|
||||
self.fileManager = fileManager
|
||||
self.legacyTask = legacyTask
|
||||
self.storage = storage
|
||||
self.cleanupKeys = cleanupKeys
|
||||
}
|
||||
|
||||
func start(completion: @escaping ResultClosure<Void>) {
|
||||
try? fileManager.deleteFile(at: loggerSettingsReader.logsFileURL)
|
||||
cleanupKeys.forEach { storage.delete(forKey: $0) }
|
||||
legacyTask.start(completion: completion)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ final class PrivacyFetchTask: PerformanceMeasurableTask {
|
|||
|
||||
private let asyncReader: PrivacyAsyncReader
|
||||
private let storage: PrivacyCRUD
|
||||
private let codesToFail = [PrivacyError.gameIdDisabled.rawValue]
|
||||
init(asyncReader: PrivacyAsyncReader, storage: PrivacyCRUD) {
|
||||
self.asyncReader = asyncReader
|
||||
self.storage = storage
|
||||
|
@ -20,12 +21,32 @@ final class PrivacyFetchTask: PerformanceMeasurableTask {
|
|||
return
|
||||
}
|
||||
|
||||
asyncReader.getPrivacyData { [storage] result in
|
||||
asyncReader.getPrivacyData { [storage] (result: UResult<PrivacyResponse>) in
|
||||
result.do(storage.save)
|
||||
.map({ _ in })
|
||||
.recover({ _ in })
|
||||
.flatMapError(self.failErrorIfNeed)
|
||||
.sink(completion)
|
||||
}
|
||||
}
|
||||
|
||||
private func failErrorIfNeed(_ error: Error) -> UResult<Void> {
|
||||
guard let error = error as? NetworkResponseError,
|
||||
let errorCode = error.errorCode,
|
||||
codesToFail.contains(errorCode),
|
||||
let privacyErrorCode = PrivacyError(rawValue: errorCode) else {
|
||||
return VoidSuccess
|
||||
}
|
||||
return .failure(privacyErrorCode)
|
||||
}
|
||||
}
|
||||
|
||||
enum PrivacyError: Int, LocalizedError {
|
||||
case gameIdDisabled = 423
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .gameIdDisabled:
|
||||
return "GameId disabled"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,53 @@ final class StartInitTask<F: TaskFactory>: PerformanceMeasurableTask {
|
|||
var startEventName: String? = Constants.Metrics.Task.Initializer.Started
|
||||
var resultMetrics: ResultMetrics.Type { Constants.Metrics.Task.Initializer.self }
|
||||
private let runner: SyncTaskRunner<F>
|
||||
init(factory: F, sequence: [F.Element]) {
|
||||
private let timeReader: TimeReader
|
||||
private let appStartTimeSaver: AppStartTimeSaver
|
||||
private let logger: Logger
|
||||
private let settingProvider: SDKGameSettingsProvider
|
||||
private let sessionInfoReader: SessionInfoReader
|
||||
|
||||
init(factory: F,
|
||||
sequence: [F.Element],
|
||||
timeReader: TimeReader,
|
||||
appStartTimeSaver: AppStartTimeSaver,
|
||||
logger: Logger,
|
||||
settingProvider: SDKGameSettingsProvider,
|
||||
sessionInfoReader: SessionInfoReader) {
|
||||
self.runner = .init(factory: factory, sequence: sequence)
|
||||
self.timeReader = timeReader
|
||||
self.appStartTimeSaver = appStartTimeSaver
|
||||
self.logger = logger
|
||||
self.settingProvider = settingProvider
|
||||
self.sessionInfoReader = sessionInfoReader
|
||||
}
|
||||
|
||||
func start(completion: @escaping ResultClosure<Void>) {
|
||||
appStartTimeSaver.save(startTime: timeReader.currentTimestamp(in: .milliseconds))
|
||||
logger.info(message: initLogMessage)
|
||||
runner.start(completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
extension StartInitTask {
|
||||
|
||||
var initLogMessage: String {
|
||||
"Initializing Unity Ads \(versionName) \(versionNumber) with game id \(settingProvider.gameID) in \(mode) mode, session \(sessionId)"
|
||||
}
|
||||
|
||||
var versionName: String {
|
||||
Version().versionName
|
||||
}
|
||||
|
||||
var versionNumber: Int {
|
||||
Version().versionNumber
|
||||
}
|
||||
|
||||
var mode: String {
|
||||
settingProvider.isTestModeEnabled ? "test" : "production"
|
||||
}
|
||||
|
||||
var sessionId: String {
|
||||
sessionInfoReader.sessionID
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import Foundation
|
||||
|
||||
protocol MetricsSenderProvider {
|
||||
var metricsSender: MetricSender { get }
|
||||
}
|
||||
protocol DiagnosticMetricsSenderProvider {
|
||||
var diagnosticMetricSender: MetricSender { get }
|
||||
}
|
||||
|
||||
final class UnityAdsEventsNetworkServicesFactory: MetricsSenderProvider, DiagnosticMetricsSenderProvider {
|
||||
|
||||
let metricsSender: MetricSender
|
||||
let diagnosticMetricSender: MetricSender
|
||||
let config: Config
|
||||
let urlSession: URLSession
|
||||
init(config: Config) {
|
||||
self.config = config
|
||||
urlSession = URLSession(configuration: config.settingsReader.metricSessionConfiguration)
|
||||
let networkBuilder = CoreNetworkServicesBuilder(session: urlSession,
|
||||
configurationProvider: config.configProvider,
|
||||
metricsCollector: nil,
|
||||
metricsSender: nil)
|
||||
|
||||
let metricsAdapter = MetricsAdapter(deviceInfoReader: config.uiDeviceInfoProvider,
|
||||
telephonyProvider: config.teleponyProvider,
|
||||
metricsMetaDataReader: config.metricsDataReader,
|
||||
allowedResourceTypes: config.settingsReader.metricsResourceTypes,
|
||||
retriesInfoReader: config.retriesReader,
|
||||
gameSettingsReader: config.settingsReader,
|
||||
sessionId: config.sessionInfoReader.sessionID)
|
||||
let factoryConfig = UnityAdsEventsRequestFactory.Config(configurationProvider: config.configProvider,
|
||||
metricsAdapter: metricsAdapter)
|
||||
let networkSenderBuilder = networkBuilder.createNetworkSenderBuilder(with: config.codes)
|
||||
|
||||
let factory = UnityAdsEventsRequestFactory(config: factoryConfig)
|
||||
let metricsSenderBuilder = MetricsSenderBuilder(metricsConfigReader: config.configProvider,
|
||||
unityAdsRequestFactory: factory,
|
||||
networkBuilder: networkSenderBuilder,
|
||||
conditionSubject: config.configProvider,
|
||||
logger: config.logger,
|
||||
metricAdapter: metricsAdapter)
|
||||
|
||||
metricsSender = metricsSenderBuilder.metricsSender
|
||||
diagnosticMetricSender = metricsSenderBuilder.networkDiagnosticMetricsSender
|
||||
}
|
||||
}
|
||||
|
||||
extension UnityAdsEventsNetworkServicesFactory {
|
||||
var unityAdsMetricsNativeNetwork: UnityAdsWebViewNetwork {
|
||||
.init(networkSender: metricsNetworkServicesBuilder.sender(withAllowedCodes: config.codes, retryConfig: nil),
|
||||
networkDownloader: metricsNetworkServicesBuilder.downloader(withAllowedCodes: [],
|
||||
baseDirectory: config.filePaths.baseDir,
|
||||
retryConfig: nil))
|
||||
}
|
||||
|
||||
private var metricsNetworkServicesBuilder: CoreNetworkServicesBuilder {
|
||||
.init(session: urlSession,
|
||||
configurationProvider: config.configProvider,
|
||||
metricsCollector: nil,
|
||||
metricsSender: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension UnityAdsEventsNetworkServicesFactory {
|
||||
struct Config {
|
||||
let configProvider: UnityAdsConfigurationProvider & MetricsSenderBatchConditionSubject
|
||||
let uiDeviceInfoProvider: UIDeviceInfoProvider = UIDevice.current
|
||||
let metricsDataReader: ExperimentsReader & SessionTokenReader
|
||||
let retriesReader: RetriesInfoReader
|
||||
let logger: Logger
|
||||
let settingsReader: NetworkSettingsProvider & SDKGameSettingsProvider
|
||||
var sessionInfoReader: SessionInfoReader
|
||||
var codes: [Int] = Array((200...299))
|
||||
var filePaths: FilePaths = FilePaths()
|
||||
var teleponyProvider: TelephonyNetworkStatusProvider = TelephonyNetworkStatusProvider()
|
||||
}
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
import Foundation
|
||||
|
||||
protocol MetricsSenderProvider {
|
||||
var metricsSender: MetricSender { get }
|
||||
}
|
||||
|
||||
protocol UnityAdsNetworkSenderProvider {
|
||||
func networkSender(includeRetryLogic: Bool, collectCompressionMetrics: Bool) -> UnityAdsNetworkSender
|
||||
}
|
||||
|
@ -19,7 +15,7 @@ protocol NetworkSettingsProvider {
|
|||
Factory that creates network services for swift layer as well as objc layer. Services can be used with metrics or without them.
|
||||
|
||||
*/
|
||||
final class UnityAdsNetworkServicesFactory: MetricsSenderProvider {
|
||||
final class UnityAdsNetworkServicesFactory {
|
||||
typealias ConfigProvider = UnityAdsConfigurationProvider &
|
||||
MetricsSenderBatchConditionSubject &
|
||||
ExperimentsReader &
|
||||
|
@ -27,48 +23,37 @@ final class UnityAdsNetworkServicesFactory: MetricsSenderProvider {
|
|||
RetriesInfoStorage
|
||||
typealias SettingsProvider = LoggerSettingsReader &
|
||||
NetworkSettingsProvider &
|
||||
SDKGameIdProvider
|
||||
SDKGameSettingsProvider
|
||||
|
||||
private let configurationProvider: ConfigProvider
|
||||
private let metricsCollector: URLSessionTaskMetricCollector = URLSessionTaskMetricCollectorBase()
|
||||
private var metricSession: URLSession
|
||||
private var mainSession: URLSession
|
||||
private let allowedCodes: [Int]
|
||||
private let filePaths = FilePaths()
|
||||
private let metricsAdapter: MetricsAdapter
|
||||
private let performanceMeasurer: PerformanceMeasurer<String>
|
||||
let metricsSender: MetricSender
|
||||
let diagnosticMetricsSender: MetricSender
|
||||
let deviceInfoReader: DeviceInfoReader & LegacyDeviceInfoReader
|
||||
let metricSenderProvider: MetricsSenderProvider & DiagnosticMetricsSenderProvider
|
||||
let deviceInfoReaderProvider: DeviceInfoBodyReaderProvider
|
||||
|
||||
private let configEndpointProvider: ConfigEndpointProvider
|
||||
|
||||
private let telephonyProvider: TelephonyNetworkStatusProvider
|
||||
init(settingsProvider: SettingsProvider,
|
||||
configurationProvider: ConfigProvider,
|
||||
deviceInfoReader: DeviceInfoReader & LegacyDeviceInfoReader,
|
||||
deviceInfoReaderProvider: DeviceInfoBodyReaderProvider,
|
||||
performanceMeasurer: PerformanceMeasurer<String>,
|
||||
logger: Logger) {
|
||||
logger: Logger,
|
||||
metricSenderProvider: MetricsSenderProvider & DiagnosticMetricsSenderProvider,
|
||||
telephonyProvider: TelephonyNetworkStatusProvider = TelephonyNetworkStatusProvider()) {
|
||||
self.configurationProvider = configurationProvider
|
||||
self.deviceInfoReader = deviceInfoReader
|
||||
self.deviceInfoReaderProvider = deviceInfoReaderProvider
|
||||
self.allowedCodes = settingsProvider.responseSuccessCodes
|
||||
self.telephonyProvider = telephonyProvider
|
||||
mainSession = URLSession(configuration: settingsProvider.mainSessionConfiguration,
|
||||
delegate: metricsCollector,
|
||||
delegateQueue: nil)
|
||||
metricSession = URLSession(configuration: settingsProvider.metricSessionConfiguration)
|
||||
self.metricsAdapter = MetricsAdapter(deviceInfoReader: deviceInfoReader,
|
||||
metricsMetaDataReader: self.configurationProvider,
|
||||
allowedResourceTypes: settingsProvider.metricsResourceTypes,
|
||||
retriesInfoReader: configurationProvider,
|
||||
gameId: settingsProvider.gameID,
|
||||
sessionId: SharedSessionIdReaderBase().sessionId)
|
||||
self.configEndpointProvider = EndpointProviderBase(worldZoneReader: WorldZoneReaderBase(countryCodeProvider: deviceInfoReader))
|
||||
let metricSenderBuilder = createMetricsSenderBuilder(session: metricSession,
|
||||
configProvider: configurationProvider,
|
||||
metricsAdapter: self.metricsAdapter,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
logger: logger)
|
||||
metricsSender = metricSenderBuilder.metricsSender
|
||||
diagnosticMetricsSender = metricSenderBuilder.networkDiagnosticMetricsSender
|
||||
let deviceInfoReader = deviceInfoReaderProvider.deviceInfoBodyReader
|
||||
self.configEndpointProvider = EndpointProviderBase(worldZoneReader: WorldZoneReaderBase(countryCodeProvider: telephonyProvider))
|
||||
|
||||
self.metricSenderProvider = metricSenderProvider
|
||||
self.performanceMeasurer = performanceMeasurer
|
||||
}
|
||||
}
|
||||
|
@ -113,33 +98,25 @@ extension UnityAdsNetworkServicesFactory {
|
|||
networkDownloader: coreNetworkServicesBuilder.downloader(withAllowedCodes: [], baseDirectory: filePaths.baseDir, retryConfig: nil))
|
||||
}
|
||||
|
||||
var unityAdsMetricsNativeNetwork: UnityAdsWebViewNetwork {
|
||||
.init(networkSender: metricsNetworkServicesBuilder.sender(withAllowedCodes: allowedCodes, retryConfig: nil),
|
||||
networkDownloader: metricsNetworkServicesBuilder.downloader(withAllowedCodes: [], baseDirectory: filePaths.baseDir, retryConfig: nil))
|
||||
}
|
||||
}
|
||||
|
||||
extension UnityAdsNetworkServicesFactory {
|
||||
|
||||
private func unityAdsRequestFactory(collectCompressionMetrics: Bool) -> UnityAdsRequestFactory {
|
||||
.init(configurationProvider: configurationProvider,
|
||||
adapter: metricsAdapter,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
bodyCompressor: bodyCompressor(includeMetrics: collectCompressionMetrics))
|
||||
.init(config: .init(configurationProvider: configurationProvider,
|
||||
deviceInfoReaderProvider: deviceInfoReaderProvider,
|
||||
bodyCompressor: bodyCompressor(includeMetrics: collectCompressionMetrics),
|
||||
countryCodeProvider: telephonyProvider))
|
||||
}
|
||||
|
||||
private func bodyCompressor(includeMetrics: Bool) -> DataCompressor {
|
||||
let original = GZipCompressor()
|
||||
return includeMetrics ? DataCompressorWithMetrics(original: original,
|
||||
measurer: performanceMeasurer,
|
||||
metricsSender: metricsSender) : original
|
||||
metricsSender: metricSenderProvider.metricsSender) : original
|
||||
|
||||
}
|
||||
|
||||
private var metricsNetworkBuilder: NetworkSenderBuilder {
|
||||
metricsNetworkServicesBuilder.createNetworkSenderBuilder(with: allowedCodes)
|
||||
}
|
||||
|
||||
private var unityAdsDownloader: UnityAdsNetworkDownloader {
|
||||
let downloader = coreNetworkServicesBuilder.downloader(withAllowedCodes: allowedCodes,
|
||||
baseDirectory: filePaths.baseDir,
|
||||
|
@ -152,67 +129,6 @@ extension UnityAdsNetworkServicesFactory {
|
|||
.init(session: mainSession,
|
||||
configurationProvider: configurationProvider,
|
||||
metricsCollector: metricsCollector,
|
||||
metricsSender: diagnosticMetricsSender)
|
||||
metricsSender: metricSenderProvider.diagnosticMetricSender)
|
||||
}
|
||||
|
||||
private var metricsNetworkServicesBuilder: CoreNetworkServicesBuilder {
|
||||
.init(session: metricSession,
|
||||
configurationProvider: configurationProvider,
|
||||
metricsCollector: nil,
|
||||
metricsSender: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func createMetricsSender(session: URLSession,
|
||||
configProvider: UnityAdsConfigurationProvider & MetricsSenderBatchConditionSubject,
|
||||
metricsAdapter: MetricsAdapter,
|
||||
deviceInfoReader: DeviceInfoReader & LegacyDeviceInfoReader,
|
||||
logger: Logger,
|
||||
codes: [Int] = Array((200...299))) -> MetricSender {
|
||||
|
||||
let networkBuilder = CoreNetworkServicesBuilder(session: session,
|
||||
configurationProvider: configProvider,
|
||||
metricsCollector: nil,
|
||||
metricsSender: nil)
|
||||
|
||||
let unityAdsRequestFactory = UnityAdsRequestFactory(configurationProvider: configProvider,
|
||||
adapter: metricsAdapter,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
bodyCompressor: GZipCompressor())
|
||||
let networkSenderBuilder = networkBuilder.createNetworkSenderBuilder(with: codes)
|
||||
|
||||
let metricsSenderBuilder = MetricsSenderBuilder(metricsConfigReader: configProvider,
|
||||
unityAdsRequestFactory: unityAdsRequestFactory,
|
||||
networkBuilder: networkSenderBuilder,
|
||||
conditionSubject: configProvider,
|
||||
logger: logger,
|
||||
metricAdapter: metricsAdapter)
|
||||
return metricsSenderBuilder.networkDiagnosticMetricsSender
|
||||
}
|
||||
|
||||
private func createMetricsSenderBuilder(session: URLSession,
|
||||
configProvider: UnityAdsConfigurationProvider & MetricsSenderBatchConditionSubject,
|
||||
metricsAdapter: MetricsAdapter,
|
||||
deviceInfoReader: DeviceInfoReader & LegacyDeviceInfoReader,
|
||||
logger: Logger,
|
||||
codes: [Int] = Array((200...299))) -> MetricsSenderBuilder {
|
||||
|
||||
let networkBuilder = CoreNetworkServicesBuilder(session: session,
|
||||
configurationProvider: configProvider,
|
||||
metricsCollector: nil,
|
||||
metricsSender: nil)
|
||||
|
||||
let unityAdsRequestFactory = UnityAdsRequestFactory(configurationProvider: configProvider,
|
||||
adapter: metricsAdapter,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
bodyCompressor: GZipCompressor())
|
||||
let networkSenderBuilder = networkBuilder.createNetworkSenderBuilder(with: codes)
|
||||
|
||||
return MetricsSenderBuilder(metricsConfigReader: configProvider,
|
||||
unityAdsRequestFactory: unityAdsRequestFactory,
|
||||
networkBuilder: networkSenderBuilder,
|
||||
conditionSubject: configProvider,
|
||||
logger: logger,
|
||||
metricAdapter: metricsAdapter)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import Foundation
|
||||
|
||||
final class DeviceInfoObjBridgeDecorator: DeviceInfoBodyStrategy {
|
||||
func initializeStaticInfo() {
|
||||
guard shouldUseNewImplementation else { return }
|
||||
config.original.initializeStaticInfo()
|
||||
}
|
||||
|
||||
private let config: Config
|
||||
init(config: Config) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
func getDeviceInfoBody(of type: DeviceInfoType) -> [String: Any] {
|
||||
guard shouldUseNewImplementation else {
|
||||
return getLegacyDeviceInfo(of: type)
|
||||
|
||||
}
|
||||
return config.original.getDeviceInfoBody(of: type)
|
||||
}
|
||||
|
||||
private var shouldUseNewImplementation: Bool {
|
||||
config.experimentsReader.experiments?.isSwiftDeviceInfoEnabled.value ?? false
|
||||
}
|
||||
|
||||
private func getLegacyDeviceInfo(of type: DeviceInfoType) -> [String: Any] {
|
||||
guard let getLegacyInfo = config.getLegacyInfo else {
|
||||
config.logger.fatal(message: "Legacy Device Info Closure is Not set")
|
||||
return [:]
|
||||
}
|
||||
return getLegacyInfo(type == .extended)
|
||||
}
|
||||
}
|
||||
|
||||
extension DeviceInfoObjBridgeDecorator {
|
||||
struct Config {
|
||||
let logger: Logger
|
||||
let experimentsReader: ExperimentsReader
|
||||
let original: DeviceInfoBodyStrategy
|
||||
let getLegacyInfo: ClosureWithReturn<Bool, [String: Any]>?
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ final class SDKInitializerOBJBridge: NSObject {
|
|||
testMode: Bool,
|
||||
completion: @escaping VoidClosure,
|
||||
error: @escaping Closure<Error>) {
|
||||
let config = SDKInitializerConfig(gameID: gameID)
|
||||
let config = SDKInitializerConfig(gameID: gameID, isTestModeEnabled: testMode)
|
||||
sdkInitializer.initialize(with: config) { result in
|
||||
result.do(completion)
|
||||
.onFailure(error)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
|
||||
final class JSONStorageBridge: KeyValueStorage, StorageContentReader {
|
||||
|
||||
var jsonStorageReaderClosure: ClosureWithReturn<String, Any?>?
|
||||
|
||||
var jsonStorageSaverClosure: Closure<(String, Any)>?
|
||||
|
||||
var jsonStorageDeleteClosure: Closure<(String)>?
|
||||
|
||||
var jsonStorageReaderContentClosure: VoidClosureWithReturn<[String: Any]>?
|
||||
|
||||
func getValue<T>(for key: String) -> T? {
|
||||
jsonStorageReaderClosure?(key) as? T
|
||||
}
|
||||
|
||||
func saveValue<T>(value: T, forKey key: String) {
|
||||
jsonStorageSaverClosure?((key, value))
|
||||
}
|
||||
|
||||
func delete(forKey key: String) {
|
||||
jsonStorageDeleteClosure?(key)
|
||||
}
|
||||
|
||||
var allContent: [String: Any] {
|
||||
jsonStorageReaderContentClosure?() ?? [:]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import Foundation
|
||||
|
||||
final class JSONStorageContentNormalizer: StorageContentReader {
|
||||
private let config: Config
|
||||
init(config: Config) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
var allContent: [String: Any] {
|
||||
var mergedDictionary = [String: Any]()
|
||||
|
||||
config.original.allContent.forEach { pair in
|
||||
processRootPair(&mergedDictionary, pair: pair)
|
||||
}
|
||||
return mergedDictionary
|
||||
}
|
||||
|
||||
func processRootPair(_ output: inout [String: Any], pair: (key: String, value: Any)) {
|
||||
guard shouldIncludeRoot(key: pair.key) else { return }
|
||||
guard let value = pair.value as? [String: Any] else {
|
||||
output[pair.key] = pair.value
|
||||
return
|
||||
}
|
||||
normalize(dictionary: value, output: &output, withParentKey: pair.key)
|
||||
}
|
||||
|
||||
func normalize(dictionary: [String: Any],
|
||||
output: inout [String: Any],
|
||||
withParentKey parentKey: String = "") {
|
||||
dictionary.forEach { pair in
|
||||
processPair(&output, parentKey: parentKey, pair: pair)
|
||||
}
|
||||
}
|
||||
|
||||
private func shouldIncludeRoot(key: String) -> Bool {
|
||||
guard !config.excludeKeys.contains(key) else { return false }
|
||||
guard !config.rootLevelKeysInclude.isEmpty else { return true }
|
||||
return config.rootLevelKeysInclude.contains(key)
|
||||
}
|
||||
|
||||
private func processPair(_ output: inout [String: Any],
|
||||
parentKey: String = "",
|
||||
pair: (key: String, value: Any)) {
|
||||
guard !config.excludeKeys.contains(pair.key) else { return }
|
||||
let newKey = newKey(for: pair.key, parentKey: parentKey)
|
||||
guard let dictionary = pair.value as? [String: Any] else {
|
||||
output[newKey] = pair.value
|
||||
return
|
||||
}
|
||||
normalize(dictionary: dictionary, output: &output, withParentKey: newKey)
|
||||
}
|
||||
|
||||
private func newKey(for key: String, parentKey: String) -> String {
|
||||
guard !parentKey.isEmpty else { return key }
|
||||
return config.reduceKeys.contains(key) ? parentKey : "\(parentKey)\(config.separator)\(key)"
|
||||
}
|
||||
}
|
||||
|
||||
extension JSONStorageContentNormalizer {
|
||||
struct Config {
|
||||
var separator = "."
|
||||
let original: StorageContentReader
|
||||
let rootLevelKeysInclude: [String]
|
||||
let excludeKeys: [String]
|
||||
let reduceKeys: [String]
|
||||
}
|
||||
}
|
||||
|
||||
extension JSONStorageContentNormalizer {
|
||||
static func minStorageContentReader(with storage: StorageContentReader) -> StorageContentReader {
|
||||
JSONStorageContentNormalizer(config: .init(original: storage,
|
||||
rootLevelKeysInclude:
|
||||
[
|
||||
JSONStorageKeys.Privacy,
|
||||
JSONStorageKeys.GDPR,
|
||||
JSONStorageKeys.Unity,
|
||||
JSONStorageKeys.PIPL
|
||||
],
|
||||
excludeKeys: [ "ts" ],
|
||||
reduceKeys: [ "value" ]))
|
||||
}
|
||||
|
||||
static func extendedStorageContentReader(with storage: StorageContentReader) -> StorageContentReader {
|
||||
JSONStorageContentNormalizer(config: .init(original: storage,
|
||||
rootLevelKeysInclude:
|
||||
[
|
||||
JSONStorageKeys.Mediation,
|
||||
JSONStorageKeys.Framework,
|
||||
JSONStorageKeys.Adapter,
|
||||
JSONStorageKeys.Configuration,
|
||||
JSONStorageKeys.User,
|
||||
JSONStorageKeys.UnifiedConfig
|
||||
],
|
||||
excludeKeys: [ "ts",
|
||||
JSONStorageKeys.Exclude,
|
||||
JSONStorageKeys.PII,
|
||||
"nonBehavioral",
|
||||
"nonbehavioral"
|
||||
],
|
||||
reduceKeys: [ "value" ]))
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
import Foundation
|
||||
// swiftlint:disable type_body_length
|
||||
|
||||
@objc
|
||||
protocol ServiceProviderObjCBridgeDelegate: AnyObject {
|
||||
func getDeviceInfo(extended: Bool) -> [String: Any]
|
||||
func getGameSessionId() -> String
|
||||
func didCompleteInit(_ config: [String: Any])
|
||||
func didReceivePrivacy(_ privacy: [String: Any])
|
||||
func getValueFromJSONStorage(for key: String) -> Any?
|
||||
func setValueToJSONStorage(_ value: Any?, for key: String)
|
||||
func deleteKeyFromJSONStorage(for key: String)
|
||||
func storageContent() -> [String: Any]
|
||||
}
|
||||
|
||||
@objc
|
||||
|
@ -13,7 +17,7 @@ final class ServiceProviderObjCBridge: NSObject {
|
|||
|
||||
private(set) weak var delegate: ServiceProviderObjCBridgeDelegate?
|
||||
|
||||
var serviceProvider = UnityAdsServiceProvider() {
|
||||
var serviceProvider = UnityAdsServiceProvider(skdSettingsStorage: .init()) {
|
||||
didSet {
|
||||
// this is required only for tests until we have objc legacy code and swift
|
||||
subscribeDelegate()
|
||||
|
@ -64,7 +68,19 @@ final class ServiceProviderObjCBridge: NSObject {
|
|||
|
||||
@objc
|
||||
func setDebugMode(_ debugMode: Bool) {
|
||||
serviceProvider.logLevel = debugMode ? .trace : .fatal
|
||||
serviceProvider.logLevel = debugMode ? .trace : .info
|
||||
}
|
||||
|
||||
@objc
|
||||
func getToken(_ completion: Closure<[String: Any]>) {
|
||||
do {
|
||||
try serviceProvider.headerBiddingTokenReader.getToken({ token in
|
||||
let tokenDict = (try? token.convertIntoDictionary()) ?? [:]
|
||||
completion(tokenDict)
|
||||
})
|
||||
} catch {
|
||||
completion([:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +99,16 @@ extension ServiceProviderObjCBridge {
|
|||
}
|
||||
}
|
||||
|
||||
extension ServiceProviderObjCBridge {
|
||||
@objc var gameSessionId: String {
|
||||
"\(serviceProvider.sessionInfoStorage.gameSessionID)"
|
||||
}
|
||||
|
||||
@objc var sessionId: String {
|
||||
serviceProvider.sessionInfoStorage.sessionID
|
||||
}
|
||||
}
|
||||
|
||||
private extension ServiceProviderObjCBridge {
|
||||
|
||||
func subscribeDelegate() {
|
||||
|
@ -90,6 +116,22 @@ private extension ServiceProviderObjCBridge {
|
|||
return delegate?.getDeviceInfo(extended: $0) ?? [:]
|
||||
})
|
||||
|
||||
serviceProvider.setLegacyJSONSaverClosure { [weak delegate] in
|
||||
delegate?.setValueToJSONStorage($0.1, for: $0.0)
|
||||
}
|
||||
|
||||
serviceProvider.setLegacyJSONReaderClosure { [weak delegate] in
|
||||
return delegate?.getValueFromJSONStorage(for: $0)
|
||||
}
|
||||
|
||||
serviceProvider.jsonStorageObjCBridge.jsonStorageReaderContentClosure = { [weak delegate] in
|
||||
delegate?.storageContent() ?? [:]
|
||||
}
|
||||
|
||||
serviceProvider.setLegacyJSONKeyDeleteClosure { [weak delegate] in
|
||||
delegate?.deleteKeyFromJSONStorage(for: $0)
|
||||
}
|
||||
|
||||
serviceProvider.subscribeToPrivacyComplete { [weak delegate] privacyResponse in
|
||||
delegate?.didReceivePrivacy(privacyResponse)
|
||||
}
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
import Foundation
|
||||
|
||||
protocol PrivacyStateReader {
|
||||
var privacyState: PrivacyState { get }
|
||||
}
|
||||
|
||||
protocol PrivacyResponseSaver {
|
||||
func save(response: PrivacyResponse)
|
||||
}
|
||||
|
||||
final class SDKSettingsStorage: LoggerLevelReader,
|
||||
LoggerSettingsReader,
|
||||
NetworkSettingsProvider,
|
||||
SDKGameIdProvider {
|
||||
SDKGameSettingsProvider {
|
||||
|
||||
var metricSessionConfiguration: URLSessionConfiguration = .ephemeral
|
||||
|
||||
|
@ -21,15 +13,28 @@ final class SDKSettingsStorage: LoggerLevelReader,
|
|||
|
||||
var metricsResourceTypes: [Int] = [1] // corresponds to .networkLoad
|
||||
|
||||
@Atomic var allowDumpToFile: Bool = false
|
||||
@Atomic var currentLevel: LogLevel = .fatal
|
||||
@Atomic var currentInitConfig: SDKInitializerConfig = .init(gameID: "")
|
||||
var allowDumpToFile: Bool {
|
||||
get { _logsIntoFile.load() }
|
||||
set { _logsIntoFile.mutate({ $0 = newValue }) }
|
||||
}
|
||||
@Atomic private var logsIntoFile: Bool = false
|
||||
var currentLevel: LogLevel {
|
||||
get { _logLevel.load() }
|
||||
set { _logLevel.mutate({ $0 = newValue }) }
|
||||
}
|
||||
@Atomic private var logLevel: LogLevel = .fatal
|
||||
|
||||
@Atomic var currentInitConfig: SDKInitializerConfig = .init(gameID: "", isTestModeEnabled: true)
|
||||
|
||||
var logsFileURL: URL { filePaths.diagnosticDump }
|
||||
let filePaths = FilePaths()
|
||||
|
||||
var gameID: String {
|
||||
currentInitConfig.gameID
|
||||
_currentInitConfig.load().gameID
|
||||
}
|
||||
|
||||
var isTestModeEnabled: Bool {
|
||||
_currentInitConfig.load().isTestModeEnabled
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import Foundation
|
||||
|
||||
enum HeaderBiddingTokenType: Int, Codable {
|
||||
case native = 0
|
||||
case remote = 1
|
||||
}
|
||||
|
||||
struct HeaderBiddingToken: DictionaryConvertible {
|
||||
let value: String
|
||||
let type: HeaderBiddingTokenType
|
||||
let uuidString: String
|
||||
let info: [String: Any]
|
||||
let customPrefix: String
|
||||
|
||||
enum CodingKeys: CodingKey {
|
||||
case value
|
||||
case type
|
||||
case uuidString
|
||||
case info
|
||||
case customPrefix
|
||||
}
|
||||
|
||||
func convertIntoDictionary() throws -> [String: Any] {
|
||||
var dict = [String: Any]()
|
||||
dict.set(value, forCoding: CodingKeys.value)
|
||||
dict.set(type.rawValue, forCoding: CodingKeys.type)
|
||||
dict.set(uuidString, forCoding: CodingKeys.uuidString)
|
||||
dict.set(info, forCoding: CodingKeys.info)
|
||||
dict.set(customPrefix, forCoding: CodingKeys.customPrefix)
|
||||
return dict
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import Foundation
|
||||
|
||||
protocol HeaderBiddingTokenReader {
|
||||
func getToken(_ completion: Closure<HeaderBiddingToken>) throws
|
||||
}
|
||||
|
||||
final class HeaderBiddingTokenReaderBase: HeaderBiddingTokenReader {
|
||||
private let config: Config
|
||||
|
||||
init(_ config: Config) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
func getToken(_ completion: Closure<HeaderBiddingToken>) throws {
|
||||
var info = config.deviceInfoReader.getDeviceInfoBody(of: .extended)
|
||||
let uniqueId = config.uniqueIdGenerator.uniqueID
|
||||
if config.experiments.experiments?.scarHbStrategyType != .disabled {
|
||||
info["tid"] = uniqueId
|
||||
}
|
||||
let tokenValue = try config.compressor.compressedInfoString(info)
|
||||
let prefixedTokenValue = config.customPrefix + tokenValue
|
||||
let token = HeaderBiddingToken(value: prefixedTokenValue,
|
||||
type: .native,
|
||||
uuidString: uniqueId,
|
||||
info: info,
|
||||
customPrefix: config.customPrefix)
|
||||
completion(token)
|
||||
}
|
||||
|
||||
struct Config {
|
||||
let deviceInfoReader: DeviceInfoBodyStrategy
|
||||
let compressor: StringCompressor
|
||||
let customPrefix: String
|
||||
let uniqueIdGenerator: UniqueGenerator
|
||||
let experiments: ExperimentsReader
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import Foundation
|
||||
|
||||
class UnityAdsServiceProvider {
|
||||
|
||||
// swiftlint:disable type_body_length
|
||||
final class UnityAdsServiceProvider {
|
||||
typealias TimeInfoReader = BootTimeReader & TimeZoneReader & TimeReader
|
||||
var sdkStateStorage: SDKStateStorage
|
||||
var skdSettingsStorage: SDKSettingsStorage
|
||||
var deviceInfoReader: DeviceInfoReader & LegacyDeviceInfoReader
|
||||
var allowedNetworkCodes = Array(200...299)
|
||||
var legacyStateFactory = USRVInitializeStateFactory()
|
||||
var sessionInfoStorage: SessionInfoReader
|
||||
|
||||
let performanceMeasurer: PerformanceMeasurer<String> // probably should use a struct to represent System?
|
||||
|
||||
|
@ -17,28 +17,65 @@ class UnityAdsServiceProvider {
|
|||
var logger: Logger
|
||||
|
||||
private let networkServicesFactory: UnityAdsNetworkServicesFactory
|
||||
private let timeReader: TimeReader
|
||||
private let eventsNetworkServicesFactory: UnityAdsEventsNetworkServicesFactory
|
||||
private let syncQueue: DispatchQueue = .init(label: "Sync.queue")
|
||||
|
||||
init(skdSettingsStorage: SDKSettingsStorage = .init()) {
|
||||
timeReader = TimeReaderBase()
|
||||
let jsonStorageObjCBridge = JSONStorageBridge()
|
||||
let timeInfoReader: TimeInfoReader
|
||||
let trackingStatusReader: TrackingStatusReader = TrackingStatusReaderBase()
|
||||
let headerBiddingTokenReader: HeaderBiddingTokenReader
|
||||
private let deviceInfoReaderBuilder: DeviceInfoBodyReaderBuilder
|
||||
init(skdSettingsStorage: SDKSettingsStorage = .init(),
|
||||
timeReader: TimeInfoReader = TimeReaderBase(),
|
||||
telephonyProvider: TelephonyInfoProvider & CountryCodeProvider = TelephonyNetworkStatusProvider()) {
|
||||
self.skdSettingsStorage = skdSettingsStorage
|
||||
|
||||
self.timeInfoReader = timeReader
|
||||
let loggerStrategy = LoggerStrategy(settingsReader: skdSettingsStorage)
|
||||
logger = LoggerWithGate(loggerLevelReader: skdSettingsStorage,
|
||||
original: loggerStrategy)
|
||||
deviceInfoReader = defaultDeviceInfoReader(withLogger: logger)
|
||||
let fileStorage = SDKConfigurationFileStorage(filePaths: skdSettingsStorage.filePaths, logger: logger)
|
||||
|
||||
let fileStorage = SDKConfigurationFileStorage(filePaths: skdSettingsStorage.filePaths,
|
||||
logger: logger)
|
||||
let sdkConfigurationStorage = SDKConfigurationInMemoryStorage(fileStorage: fileStorage)
|
||||
sdkStateStorage = SDKStateStorage(configProvider: sdkConfigurationStorage)
|
||||
|
||||
performanceMeasurer = .init(timeReader: timeReader)
|
||||
sessionInfoStorage = SessionInfoStorage(settings: .defaultSettings(privateStorage: jsonStorageObjCBridge))
|
||||
|
||||
performanceMeasurer = .init(timeReader: timeInfoReader)
|
||||
|
||||
let eventsServicesConfig = UnityAdsEventsNetworkServicesFactory.Config(configProvider: sdkStateStorage,
|
||||
metricsDataReader: sdkStateStorage,
|
||||
retriesReader: sdkStateStorage,
|
||||
logger: logger,
|
||||
settingsReader: skdSettingsStorage,
|
||||
sessionInfoReader: sessionInfoStorage)
|
||||
|
||||
eventsNetworkServicesFactory = UnityAdsEventsNetworkServicesFactory(config: eventsServicesConfig)
|
||||
let builderConfig = DeviceInfoBodyReaderBuilder.Config(sessionInfoStorage: sessionInfoStorage,
|
||||
trackingStatusReader: trackingStatusReader,
|
||||
gameSettingsReader: skdSettingsStorage,
|
||||
sdkStateStorage: sdkStateStorage,
|
||||
persistenceStorage: jsonStorageObjCBridge,
|
||||
logger: logger,
|
||||
timeReader: timeReader,
|
||||
telephonyInfoProvider: telephonyProvider,
|
||||
performanceMeasurer: performanceMeasurer,
|
||||
metricsSender: eventsNetworkServicesFactory.metricsSender)
|
||||
deviceInfoReaderBuilder = DeviceInfoBodyReaderBuilder(baseConfig: builderConfig)
|
||||
|
||||
networkServicesFactory = .init(settingsProvider: skdSettingsStorage,
|
||||
configurationProvider: sdkStateStorage,
|
||||
deviceInfoReader: deviceInfoReader,
|
||||
deviceInfoReaderProvider: deviceInfoReaderBuilder,
|
||||
performanceMeasurer: performanceMeasurer,
|
||||
logger: logger)
|
||||
logger: logger,
|
||||
metricSenderProvider: eventsNetworkServicesFactory)
|
||||
|
||||
let hbTokenConfig = HeaderBiddingTokenReaderBase.Config(
|
||||
deviceInfoReader: deviceInfoReaderBuilder.deviceInfoBodyReader,
|
||||
compressor: Base64GzipCompressor(dataCompressor: GZipCompressor()),
|
||||
customPrefix: "1:",
|
||||
uniqueIdGenerator: IdentifiersGeneratorBase(),
|
||||
experiments: sdkConfigurationStorage)
|
||||
headerBiddingTokenReader = HeaderBiddingTokenReaderBase(hbTokenConfig)
|
||||
}
|
||||
|
||||
private var _sdkInitializer: SDKInitializer?
|
||||
|
@ -46,13 +83,27 @@ class UnityAdsServiceProvider {
|
|||
var sdkInitializer: SDKInitializer {
|
||||
syncQueue.sync { getOrCreateInitializer() }
|
||||
}
|
||||
}
|
||||
|
||||
extension UnityAdsServiceProvider {
|
||||
func updateConfiguration(_ config: UnityAdsConfig) {
|
||||
sdkStateStorage.config = config
|
||||
}
|
||||
|
||||
func setLegacyInfoClosure(_ closure: ClosureWithReturn<Bool, [String: Any]>?) {
|
||||
deviceInfoReader.setLegacyInfoGetter(closure)
|
||||
deviceInfoReaderBuilder.setLegacyInfoGetter(closure)
|
||||
}
|
||||
|
||||
func setLegacyJSONReaderClosure(_ closure: ClosureWithReturn<String, Any?>?) {
|
||||
jsonStorageObjCBridge.jsonStorageReaderClosure = closure
|
||||
}
|
||||
|
||||
func setLegacyJSONSaverClosure(_ closure: Closure<(String, Any?)>?) {
|
||||
jsonStorageObjCBridge.jsonStorageSaverClosure = closure
|
||||
}
|
||||
|
||||
func setLegacyJSONKeyDeleteClosure(_ closure: Closure<String>?) {
|
||||
jsonStorageObjCBridge.jsonStorageDeleteClosure = closure
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,19 +160,25 @@ extension UnityAdsServiceProvider {
|
|||
}
|
||||
|
||||
var unityAdsMetricsNativeNetwork: UnityAdsWebViewNetwork {
|
||||
networkServicesFactory.unityAdsMetricsNativeNetwork
|
||||
eventsNetworkServicesFactory.unityAdsMetricsNativeNetwork
|
||||
}
|
||||
}
|
||||
|
||||
extension UnityAdsServiceProvider {
|
||||
private var initTaskRunner: Task {
|
||||
TaskPerformanceDecorator(original: mainTask,
|
||||
metricSender: networkServicesFactory.metricsSender,
|
||||
metricSender: eventsNetworkServicesFactory.metricsSender,
|
||||
performanceMeasurer: performanceMeasurer)
|
||||
}
|
||||
|
||||
private var mainTask: PerformanceMeasurableTask {
|
||||
StartInitTask(factory: initTaskFactory, sequence: sequence)
|
||||
StartInitTask(factory: initTaskFactory,
|
||||
sequence: sequence,
|
||||
timeReader: timeInfoReader,
|
||||
appStartTimeSaver: sdkStateStorage,
|
||||
logger: logger,
|
||||
settingProvider: skdSettingsStorage,
|
||||
sessionInfoReader: sessionInfoStorage)
|
||||
}
|
||||
|
||||
private var sequence: [InitTaskCategory] {
|
||||
|
@ -137,17 +194,29 @@ extension UnityAdsServiceProvider {
|
|||
|
||||
var initTaskFactory: InitializationTaskFactoryStrategy {
|
||||
.init(downloaderBuilder: networkServicesFactory.webViewDownloaderBuilder,
|
||||
metricSenderProvider: networkServicesFactory,
|
||||
metricSenderProvider: eventsNetworkServicesFactory,
|
||||
networkSenderProvider: networkServicesFactory,
|
||||
sdkStateStorage: sdkStateStorage,
|
||||
performanceMeasurer: performanceMeasurer,
|
||||
stateFactoryObjc: legacyStateFactory,
|
||||
settingsProvider: skdSettingsStorage)
|
||||
settingsProvider: skdSettingsStorage,
|
||||
keyValueStorage: jsonStorageObjCBridge,
|
||||
cleanupKeys: [JSONStorageKeys.GameSessionID],
|
||||
deviceInfoReader: deviceInfoReaderBuilder.deviceInfoBodyReader)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func defaultDeviceInfoReader(withLogger logger: Logger) -> DeviceInfoReader & LegacyDeviceInfoReader {
|
||||
let webUserAgent = WebUserAgentReaderBase(lastKnownOSKey: Constants.UserDefaultsKeys.LastKnownSystemVersion,
|
||||
userAgentValueKey: Constants.UserDefaultsKeys.LastKnownUserAgentKey)
|
||||
return DeviceInfoReaderBase(logger: logger, userAgentReader: webUserAgent)
|
||||
extension SessionInfoStorage.Settings {
|
||||
static func defaultSettings(privateStorage: KeyValueStorage,
|
||||
idGenerator: IdentifiersGenerator = IdentifiersGeneratorBase()) -> Self {
|
||||
.init(privateStorage: privateStorage,
|
||||
gameSessionIDKey: JSONStorageKeys.GameSessionID,
|
||||
sessionIDKey: JSONStorageKeys.SessionID,
|
||||
userIDKey: JSONStorageKeys.UserID,
|
||||
idfiIDKey: JSONStorageKeys.IDFI,
|
||||
auIDKey: JSONStorageKeys.AUID,
|
||||
userNonBehavioralFlagKey: JSONStorageKeys.UserNonBehavioralValue,
|
||||
idGenerator: idGenerator)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ disabled_rules: # rule identifiers to exclude from running
|
|||
- generic_type_name
|
||||
- identifier_name
|
||||
- discouraged_direct_init
|
||||
- blanket_disable_command
|
||||
# - type_name
|
||||
opt_in_rules: # some rules are only opt-in
|
||||
- empty_count
|
||||
|
@ -26,14 +27,13 @@ opt_in_rules: # some rules are only opt-in
|
|||
- multiline_function_chains
|
||||
- multiline_parameters
|
||||
- number_separator
|
||||
- unused_import
|
||||
- unused_capture_list
|
||||
- unused_declaration
|
||||
- unused_setter_value
|
||||
- yoda_condition
|
||||
|
||||
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
|
||||
- explicit_self
|
||||
- unused_import
|
||||
- unused_declaration
|
||||
# configurable rules can be customized from this configuration file
|
||||
# binary rules can set their severity level
|
||||
nesting:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#import "USRVWebViewApp.h"
|
||||
#import "USRVWebViewAsyncOperationStorage.h"
|
||||
#import "USRVWebViewAsyncOperation.h"
|
||||
#import "UADSServiceProviderContainer.h"
|
||||
@class UnityAds;
|
||||
@class USRVSdkProperties;
|
||||
|
||||
|
@ -18,7 +19,16 @@
|
|||
[USRVWebViewApp setCurrentApp: nil];
|
||||
[USRVWebViewAsyncOperationStorage.sharedInstance resetForTesting];
|
||||
[USRVWebViewAsyncOperation signalLock];
|
||||
|
||||
[USRVInvocation setClassTable: [[USRVConfiguration new] getWebAppApiClassList]];
|
||||
[self deleteConfigFile];
|
||||
[UADSServiceProviderContainer sharedInstance].serviceProvider = [UADSServiceProvider new];
|
||||
}
|
||||
|
||||
+ (void)deleteConfigFile {
|
||||
NSString *fileName = [USRVSdkProperties getLocalConfigFilepath];
|
||||
|
||||
[[NSFileManager defaultManager] removeItemAtPath: fileName
|
||||
error: nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,6 +29,7 @@ static NSString *const kUnityAdsWebViewMockURL = @"https://webview.unityads.unit
|
|||
@implementation InitializeTests
|
||||
|
||||
- (void)setUp {
|
||||
UADSServiceProviderContainer.sharedInstance.serviceProvider = [UADSServiceProvider new];
|
||||
[self cleanupCache];
|
||||
[super setUp];
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@ final class InitializationPerformanceTest: SDKInitializerLegacyIntegrationTestsB
|
|||
}
|
||||
|
||||
func test_get_token_during_swift_new_task_initializing() throws {
|
||||
try run_get_token_during_initializing(with: ["s_init": true, "s_ntf": true],
|
||||
try run_get_token_during_initializing(with: ["s_init": true, "s_ntf": true, "s_din": true],
|
||||
metrics: ExpectedMetrics.SequentialFlow.HappyPath,
|
||||
expectedDiagnostic: true)
|
||||
}
|
||||
|
||||
func test_get_token_during_swift_parallel_initializing() throws {
|
||||
try run_get_token_during_initializing(with: ["s_init": true, "s_pte": true],
|
||||
try run_get_token_during_initializing(with: ["s_init": true, "s_pte": true, "s_din": true],
|
||||
metrics: ExpectedMetrics.ParallelFlow.HappyPath,
|
||||
expectedDiagnostic: true)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ final class InitializationPerformanceTest: SDKInitializerLegacyIntegrationTestsB
|
|||
var metrics = metrics
|
||||
metrics.append(contentsOf: [
|
||||
.legacy(.nativeTokenAvailable),
|
||||
.legacy(.latency(.intoCollection)),
|
||||
.legacy(.latency(.infoCollection)),
|
||||
.legacy(.latency(.infoCompression))])
|
||||
try? runFlow(sdkMetrics: metrics,
|
||||
experiments: experiments,
|
||||
|
@ -81,7 +81,8 @@ final class InitializationPerformanceTest: SDKInitializerLegacyIntegrationTestsB
|
|||
try? runFlow(sdkMetrics: ExpectedMetrics.LegacyFlow.HappyPath,
|
||||
experiments: [:],
|
||||
expectNetworkDiagnostic: false,
|
||||
legacyFlow: true)
|
||||
legacyFlow: true,
|
||||
validateTimeStamp: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +100,7 @@ final class InitializationPerformanceTest: SDKInitializerLegacyIntegrationTestsB
|
|||
measure(metrics: metrics,
|
||||
options: testOptions) {
|
||||
try? runFlow(sdkMetrics: ExpectedMetrics.SequentialFlow.HappyPath,
|
||||
experiments: ["s_init": true, "s_ntf": true],
|
||||
experiments: ["s_init": true, "s_ntf": true, "s_din": true],
|
||||
expectNetworkDiagnostic: true)
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,7 @@ final class InitializationPerformanceTest: SDKInitializerLegacyIntegrationTestsB
|
|||
measure(metrics: metrics,
|
||||
options: testOptions) {
|
||||
try? runFlow(sdkMetrics: ExpectedMetrics.ParallelFlow.HappyPath,
|
||||
experiments: ["s_init": true, "s_pte": true],
|
||||
experiments: ["s_init": true, "s_pte": true, "s_din": true],
|
||||
expectNetworkDiagnostic: true)
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +134,7 @@ extension InitializationPerformanceTest {
|
|||
expectNetworkDiagnostic: Bool,
|
||||
legacyFlow: Bool = false,
|
||||
parallelToInit: VoidClosure? = nil,
|
||||
validateTimeStamp: Bool = true,
|
||||
line: UInt = #line,
|
||||
file: StaticString = #file) throws {
|
||||
let overrideJson = ["hash": configMockFactory.longWebViewDataDataHash]
|
||||
|
@ -154,7 +156,8 @@ extension InitializationPerformanceTest {
|
|||
expectedNumberOfRequests: responses.count,
|
||||
multithreadCount: 1,
|
||||
metrics: sdkMetrics,
|
||||
expectDiagnostic: expectNetworkDiagnostic)
|
||||
expectDiagnostic: expectNetworkDiagnostic,
|
||||
validateStartTimeStamp: validateTimeStamp)
|
||||
try executeTest(with: testConfig,
|
||||
file: file,
|
||||
line: line,
|
||||
|
|
|
@ -44,10 +44,6 @@
|
|||
#import "UADSTsiMetric.h"
|
||||
#import "UADSPrivacyMetrics.h"
|
||||
#import "USRVApiSdk.h"
|
||||
#import "UADSInstallationIdExtension.h"
|
||||
#import "UADSPlist.h"
|
||||
#import "UADSUnityPlayerPrefsStore.h"
|
||||
#import "UADSUserDefaultsStore.h"
|
||||
#import "USRVInitializeStateCreate.h"
|
||||
#import "USRVInitializeStateReset.h"
|
||||
#import "USRVInitializeStateLoadCache.h"
|
||||
|
@ -58,7 +54,11 @@
|
|||
#import "USRVInitializeStateLoadConfigFile.h"
|
||||
#import "USRVInitializeStateLoadWeb.h"
|
||||
#import "UADSInitializeEventsMetricSender.h"
|
||||
#import "USRVJsonStorageAggregator.h"
|
||||
#import "USRVStorageManager.h"
|
||||
// TESTING SPECIFIC
|
||||
#import "UnityAds+Testability.h"
|
||||
#import "TestUtilities.h"
|
||||
#import "USRVWebViewCallbackMock.h"
|
||||
#import "UADSDeviceTestsHelper.h"
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
return self.expectedMode;
|
||||
}
|
||||
|
||||
- (BOOL)userNonBehavioralFlag {
|
||||
- (NSNumber *)userNonBehavioralFlag {
|
||||
_userBehavioralCount += 1;
|
||||
return self.expectedUserBehaviouralFlag ? : false;
|
||||
return self.expectedUserBehaviouralFlag ? @(self.expectedUserBehaviouralFlag) : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -44,6 +44,15 @@
|
|||
errorPrivacy: self.privacyErrorMock];
|
||||
}
|
||||
|
||||
- (void)test_game_disabled_error_doesnt_call_loader_and_saver {
|
||||
[self runFlowWithPrivacyCodeAndValidate: 0
|
||||
allowTrackingFlag: false
|
||||
expectedSaverCalls: 0
|
||||
privacyCalls: 1
|
||||
loaderCalled: 0
|
||||
errorPrivacy: uads_privacyGameDisabledError];
|
||||
}
|
||||
|
||||
- (void)test_privacy_error_doesnt_block_loader_request_but_calls_saver {
|
||||
[self runFlowWithPrivacyCodeAndValidate: 0
|
||||
allowTrackingFlag: false
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче