adding pods method of package managing
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKMetadataIndexer.h"
|
||||
#import "FBSDKMetadataIndexing.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKMetadataIndexer (MetadataIndexing) <FBSDKMetadataIndexing>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(MetadataIndexer)
|
||||
@interface FBSDKMetadataIndexer : NSObject
|
||||
@property (class, nonatomic, readonly) FBSDKMetadataIndexer *shared;
|
||||
|
||||
- (void)enable;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKMetadataIndexer.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/utsname.h>
|
||||
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKServerConfigurationManager.h"
|
||||
#import "FBSDKSwizzler.h"
|
||||
#import "FBSDKUtility.h"
|
||||
#import "FBSDKViewHierarchy.h"
|
||||
|
||||
@interface FBSDKUserDataStore (Internal)
|
||||
|
||||
+ (void)setInternalHashData:(nullable NSString *)hashData
|
||||
forType:(FBSDKAppEventUserDataType)type;
|
||||
+ (void)setEnabledRules:(NSArray<NSString *> *)rules;
|
||||
|
||||
+ (nullable NSString *)getInternalHashedDataForType:(FBSDKAppEventUserDataType)type;
|
||||
|
||||
@end
|
||||
|
||||
static const int FBSDKMetadataIndexerMaxTextLength = 100;
|
||||
static const int FBSDKMetadataIndexerMaxIndicatorLength = 100;
|
||||
static const int FBSDKMetadataIndexerMaxValue = 5;
|
||||
|
||||
static NSString *const FIELD_K = @"k";
|
||||
static NSString *const FIELD_V = @"v";
|
||||
static NSString *const FIELD_K_DELIMITER = @",";
|
||||
|
||||
@interface FBSDKMetadataIndexer ()
|
||||
|
||||
@property (nonatomic, readonly, strong) NSMutableDictionary<NSString *, NSDictionary<NSString *, NSString *> *> *rules;
|
||||
@property (nonatomic, readonly, strong) NSMutableDictionary<NSString *, NSMutableArray<NSString *> *> *store;
|
||||
@property (nonatomic, readonly, strong) dispatch_queue_t serialQueue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKMetadataIndexer
|
||||
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static dispatch_once_t nonce;
|
||||
static FBSDKMetadataIndexer *instance;
|
||||
dispatch_once(&nonce, ^{
|
||||
instance = [self new];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
_rules = [NSMutableDictionary new];
|
||||
_serialQueue = dispatch_queue_create("com.facebook.appevents.MetadataIndexer", DISPATCH_QUEUE_SERIAL);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)enable
|
||||
{
|
||||
@try {
|
||||
if ([FBSDKAppEventsUtility shouldDropAppEvent]) {
|
||||
return;
|
||||
}
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSDictionary<NSString *, id> *AAMRules = FBSDKServerConfigurationManager.shared.cachedServerConfiguration.AAMRules;
|
||||
if (AAMRules) {
|
||||
[self setupWithRules:AAMRules];
|
||||
}
|
||||
});
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to enable Automatic Advanced Matching, exception reason: %@", exception.reason);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupWithRules:(NSDictionary<NSString *, id> *_Nullable)rules
|
||||
{
|
||||
if (0 == rules.count) {
|
||||
return;
|
||||
}
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
[self constructRules:rules];
|
||||
[self initStore];
|
||||
|
||||
BOOL isEnabled = NO;
|
||||
for (NSString *key in _rules) {
|
||||
if (_rules[key]) {
|
||||
isEnabled = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEnabled) {
|
||||
[FBSDKUserDataStore setEnabledRules:_rules.allKeys];
|
||||
[self setupMetadataIndexing];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)initStore
|
||||
{
|
||||
_store = [NSMutableDictionary new];
|
||||
for (NSString *key in _rules) {
|
||||
NSString *data = [FBSDKUserDataStore getInternalHashedDataForType:key];
|
||||
if (data.length > 0) {
|
||||
[FBSDKTypeUtility dictionary:_store setObject:[NSMutableArray arrayWithArray:[data componentsSeparatedByString:FIELD_K_DELIMITER]] forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
for (NSString *key in _rules) {
|
||||
if (!_store[key]) {
|
||||
[FBSDKTypeUtility dictionary:_store setObject:[NSMutableArray new] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)constructRules:(NSDictionary<NSString *, id> *_Nullable)rules
|
||||
{
|
||||
for (NSString *key in rules) {
|
||||
NSDictionary<NSString *, NSString *> *value = [FBSDKTypeUtility dictionaryValue:rules[key]];
|
||||
if (value[FIELD_K].length > 0 && value[FIELD_V]) {
|
||||
[FBSDKTypeUtility dictionary:_rules setObject:value forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupMetadataIndexing
|
||||
{
|
||||
void (^block)(UIView *) = ^(UIView *view) {
|
||||
// Indexing when the view is removed from window and conforms to UITextInput, and skip UIFieldEditor, which is an internval view of UITextField
|
||||
if (![view window] && ![NSStringFromClass([view class]) isEqualToString:@"UIFieldEditor"] && [view conformsToProtocol:@protocol(UITextInput)]) {
|
||||
NSString *text = [FBSDKViewHierarchy getText:view];
|
||||
NSString *placeholder = [FBSDKViewHierarchy getHint:view];
|
||||
BOOL secureTextEntry = [self checkSecureTextEntry:view];
|
||||
NSArray<NSString *> *labels = [self getLabelsOfView:view];
|
||||
UIKeyboardType keyboardType = [self getKeyboardType:view];
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
|
||||
[self getMetadataWithText:text
|
||||
placeholder:placeholder
|
||||
labels:labels
|
||||
secureTextEntry:secureTextEntry
|
||||
inputType:keyboardType];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UIView class] withBlock:block named:@"metadataIndexingUIView"];
|
||||
|
||||
// iOS 12: UITextField implements didMoveToWindow without calling parent implementation
|
||||
if (@available(iOS 12, *)) {
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UITextField class] withBlock:block named:@"metadataIndexingUITextField"];
|
||||
} else {
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow) onClass:[UIControl class] withBlock:block named:@"metadataIndexingUIControl"];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray<UIView *> *)getSiblingViewsOfView:(UIView *)view
|
||||
{
|
||||
NSObject *parent = [FBSDKViewHierarchy getParent:view];
|
||||
if (parent) {
|
||||
NSArray<id> *views = [FBSDKViewHierarchy getChildren:parent];
|
||||
if (views) {
|
||||
NSMutableArray<id> *siblings = [NSMutableArray arrayWithArray:views];
|
||||
[siblings removeObject:view];
|
||||
return [siblings copy];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)getLabelsOfView:(UIView *)view
|
||||
{
|
||||
NSMutableArray<NSString *> *labels = [NSMutableArray new];
|
||||
|
||||
NSString *placeholder = [self normalizeField:[FBSDKViewHierarchy getHint:view]];
|
||||
if (placeholder.length > 0) {
|
||||
[FBSDKTypeUtility array:labels addObject:placeholder];
|
||||
}
|
||||
|
||||
NSArray<id> *siblingViews = [self getSiblingViewsOfView:view];
|
||||
for (id sibling in siblingViews) {
|
||||
if ([sibling isKindOfClass:[UILabel class]]) {
|
||||
NSString *text = [self normalizeField:[FBSDKViewHierarchy getText:sibling]];
|
||||
if (text.length > 0) {
|
||||
[FBSDKTypeUtility array:labels addObject:text];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [labels copy];
|
||||
}
|
||||
|
||||
- (BOOL)checkSecureTextEntry:(UIView *)view
|
||||
{
|
||||
if ([view isKindOfClass:[UITextField class]]) {
|
||||
return ((UITextField *)view).secureTextEntry;
|
||||
}
|
||||
if ([view isKindOfClass:[UITextView class]]) {
|
||||
return ((UITextView *)view).secureTextEntry;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (UIKeyboardType)getKeyboardType:(UIView *)view
|
||||
{
|
||||
if ([view isKindOfClass:[UITextField class]]) {
|
||||
return ((UITextField *)view).keyboardType;
|
||||
}
|
||||
if ([view isKindOfClass:[UITextView class]]) {
|
||||
return ((UITextView *)view).keyboardType;
|
||||
}
|
||||
|
||||
return UIKeyboardTypeDefault;
|
||||
}
|
||||
|
||||
- (void)getMetadataWithText:(NSString *)text
|
||||
placeholder:(NSString *)placeholder
|
||||
labels:(NSArray<NSString *> *)labels
|
||||
secureTextEntry:(BOOL)secureTextEntry
|
||||
inputType:(UIKeyboardType)inputType
|
||||
{
|
||||
text = [self normalizeValue:text];
|
||||
placeholder = [self normalizeField:placeholder];
|
||||
if (secureTextEntry || [placeholder containsString:@"password"]
|
||||
|| text.length == 0
|
||||
|| text.length > FBSDKMetadataIndexerMaxTextLength
|
||||
|| placeholder.length >= FBSDKMetadataIndexerMaxIndicatorLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *key in _rules) {
|
||||
NSDictionary<NSString *, NSString *> *rule = _rules[key];
|
||||
BOOL isRuleKMatched = [self checkMetadataHint:placeholder matchRuleK:rule[FIELD_K]]
|
||||
|| [self checkMetadataLabels:labels matchRuleK:rule[FIELD_K]];
|
||||
if (!isRuleKMatched) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *preProcessedText = text;
|
||||
if ([key isEqualToString:@"r2"]) {
|
||||
preProcessedText = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"+- ()."]] componentsJoinedByString:@""];
|
||||
}
|
||||
BOOL isRuleVMatched = [rule[FIELD_V] isEqualToString:@""] || [self checkMetadataText:preProcessedText matchRuleV:rule[FIELD_V]];
|
||||
if (isRuleVMatched) {
|
||||
NSString *prunedText = [self pruneValue:preProcessedText forKey:key];
|
||||
[self checkAndAppendData:prunedText forKey:key];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Helper Methods
|
||||
|
||||
- (void)checkAndAppendData:(NSString *)data
|
||||
forKey:(NSString *)key
|
||||
{
|
||||
NSString *hashData = [FBSDKUtility SHA256Hash:data];
|
||||
__weak typeof(_store) weakStore = _store;
|
||||
dispatch_block_t checkAndAppendDataBlock = ^{
|
||||
if (hashData.length == 0 || [weakStore[key] containsObject:hashData]) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (weakStore[key].count >= FBSDKMetadataIndexerMaxValue) {
|
||||
[weakStore[key] removeObjectAtIndex:0];
|
||||
}
|
||||
[FBSDKTypeUtility array:weakStore[key] addObject:hashData];
|
||||
[FBSDKUserDataStore setInternalHashData:[weakStore[key] componentsJoinedByString:FIELD_K_DELIMITER]
|
||||
forType:key];
|
||||
};
|
||||
#if FBTEST
|
||||
checkAndAppendDataBlock();
|
||||
#else
|
||||
dispatch_async(_serialQueue, checkAndAppendDataBlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)checkMetadataLabels:(NSArray<NSString *> *)labels
|
||||
matchRuleK:(NSString *)ruleK
|
||||
{
|
||||
for (NSString *label in labels) {
|
||||
if ([self checkMetadataHint:label matchRuleK:ruleK]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)checkMetadataHint:(NSString *)hint
|
||||
matchRuleK:(NSString *)ruleK
|
||||
{
|
||||
if (hint.length > 0 && ruleK) {
|
||||
NSArray<NSString *> *items = [ruleK componentsSeparatedByString:FIELD_K_DELIMITER];
|
||||
for (NSString *item in items) {
|
||||
if ([hint containsString:item]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)checkMetadataText:(NSString *)text
|
||||
matchRuleV:(NSString *)ruleV
|
||||
{
|
||||
if (text.length > 0 && ruleV) {
|
||||
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:ruleV
|
||||
options:NSRegularExpressionCaseInsensitive
|
||||
error:nil];
|
||||
return [regex numberOfMatchesInString:text options:0 range:NSMakeRange(0, text.length)] == 1;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *)normalizeField:(NSString *)field
|
||||
{
|
||||
if (field.length == 0) {
|
||||
return @"";
|
||||
}
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[_-]|\\s"
|
||||
options:NSRegularExpressionCaseInsensitive
|
||||
error:nil];
|
||||
return [regex stringByReplacingMatchesInString:field
|
||||
options:0
|
||||
range:NSMakeRange(0, field.length)
|
||||
withTemplate:@""].lowercaseString;
|
||||
}
|
||||
|
||||
- (NSString *)normalizeValue:(NSString *)value
|
||||
{
|
||||
if (value.length == 0) {
|
||||
return @"";
|
||||
}
|
||||
return [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].lowercaseString;
|
||||
}
|
||||
|
||||
- (NSString *)pruneValue:(NSString *)value forKey:(NSString *)key
|
||||
{
|
||||
if (value.length == 0) {
|
||||
return @"";
|
||||
}
|
||||
if ([key isEqualToString:@"r3"]) {
|
||||
if ([value hasPrefix:@"m"] || [value hasPrefix:@"b"] || [value hasPrefix:@"ge"]) {
|
||||
value = @"m";
|
||||
} else {
|
||||
value = @"f";
|
||||
}
|
||||
} else if ([key isEqualToString:@"r4"] || [key isEqualToString:@"r5"]) {
|
||||
value = [[value componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@""];
|
||||
} else if ([key isEqualToString:@"r6"]) {
|
||||
value = [FBSDKTypeUtility array:[value componentsSeparatedByString:@"-"] objectAtIndex:0];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(MetadataIndexing)
|
||||
@protocol FBSDKMetadataIndexing
|
||||
|
||||
- (void)enable;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKCoreKitAEMImport.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(SDKAEMNetworker)
|
||||
@interface FBSDKAEMNetworker : NSObject <FBAEMNetworking>
|
||||
|
||||
- (void)startGraphRequestWithGraphPath:(NSString *)graphPath
|
||||
parameters:(NSDictionary *)parameters
|
||||
tokenString:(nullable NSString *)tokenString
|
||||
HTTPMethod:(nullable NSString *)method
|
||||
completion:(FBGraphRequestCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
#import "FBSDKAEMNetworker.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKGraphRequest+Internal.h"
|
||||
#import "FBSDKGraphRequestFlags.h"
|
||||
|
||||
@implementation FBSDKAEMNetworker
|
||||
|
||||
- (void)startGraphRequestWithGraphPath:(NSString *)graphPath
|
||||
parameters:(NSDictionary *)parameters
|
||||
tokenString:(nullable NSString *)tokenString
|
||||
HTTPMethod:(nullable NSString *)method
|
||||
completion:(FBGraphRequestCompletion)completion
|
||||
{
|
||||
id<FBSDKGraphRequest> graphRequest = [[FBSDKGraphRequest alloc] initWithGraphPath:graphPath
|
||||
parameters:parameters
|
||||
tokenString:tokenString
|
||||
HTTPMethod:method
|
||||
flags:FBSDKGraphRequestFlagSkipClientToken | FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||
|
||||
[graphRequest startWithCompletion:^(id<FBSDKGraphRequestConnecting> _Nullable connection, id _Nullable result, NSError *_Nullable error) {
|
||||
completion(result, error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// TODO: Can these all be forward decls?
|
||||
|
||||
#import "FBSDKAdvertiserIDProviding.h"
|
||||
#import "FBSDKCodelessIndexer.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKGraphRequestConnectionProviding.h"
|
||||
#import "FBSDKGraphRequestProviding.h"
|
||||
#import "FBSDKServerConfigurationProviding.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
#import "FBSDKSwizzling.h"
|
||||
|
||||
@interface FBSDKCodelessIndexer (Internal)
|
||||
|
||||
+ (void)configureWithRequestProvider:(id<FBSDKGraphRequestProviding>)requestProvider
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
connectionProvider:(id<FBSDKGraphRequestConnectionProviding>)connectionProvider
|
||||
swizzler:(Class<FBSDKSwizzling>)swizzler
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
advertiserIDProvider:(id<FBSDKAdvertiserIDProviding>)advertisingIDProvider;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void(^FBSDKCodelessSettingLoadBlock)(BOOL isCodelessSetupEnabled, NSError *_Nullable error);
|
||||
|
||||
NS_SWIFT_NAME(CodelessIndexer)
|
||||
@interface FBSDKCodelessIndexer : NSObject
|
||||
|
||||
@property (class, nonatomic, copy, readonly) NSString *extInfo;
|
||||
|
||||
+ (void)enable;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Generated
+551
@@ -0,0 +1,551 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKCodelessIndexer.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/utsname.h>
|
||||
|
||||
#import "FBSDKAdvertiserIDProviding.h"
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKGraphRequestConnecting.h"
|
||||
#import "FBSDKGraphRequestConnectionProviding.h"
|
||||
#import "FBSDKGraphRequestHTTPMethod.h"
|
||||
#import "FBSDKGraphRequestProtocol.h"
|
||||
#import "FBSDKGraphRequestProviding.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKObjectDecoding.h"
|
||||
#import "FBSDKServerConfiguration.h"
|
||||
#import "FBSDKServerConfigurationManager.h"
|
||||
#import "FBSDKServerConfigurationProviding.h"
|
||||
#import "FBSDKSettings+Internal.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
#import "FBSDKSwizzling.h"
|
||||
#import "FBSDKUnarchiverProvider.h"
|
||||
#import "FBSDKUtility.h"
|
||||
#import "FBSDKViewHierarchy.h"
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
@interface FBSDKCodelessIndexer ()
|
||||
|
||||
@property (class, nullable, nonatomic, readonly) id<FBSDKGraphRequestProviding> requestProvider;
|
||||
@property (class, nullable, nonatomic, readonly) id<FBSDKServerConfigurationProviding> serverConfigurationProvider;
|
||||
@property (class, nullable, nonatomic, readonly) id<FBSDKDataPersisting> store;
|
||||
@property (class, nullable, nonatomic, readonly, copy) id<FBSDKGraphRequestConnectionProviding> connectionProvider;
|
||||
@property (class, nullable, nonatomic, readonly, copy) Class<FBSDKSwizzling> swizzler;
|
||||
@property (class, nullable, nonatomic, readonly) id<FBSDKSettings> settings;
|
||||
@property (class, nullable, nonatomic, readonly) id<FBSDKAdvertiserIDProviding> advertiserIDProvider;
|
||||
|
||||
@end
|
||||
|
||||
#if FBSDK_SWIFT_PACKAGE
|
||||
NS_EXTENSION_UNAVAILABLE("The Facebook iOS SDK is not currently supported in extensions")
|
||||
#endif
|
||||
@implementation FBSDKCodelessIndexer
|
||||
|
||||
static BOOL _isCodelessIndexing;
|
||||
static BOOL _isCheckingSession;
|
||||
static BOOL _isCodelessIndexingEnabled;
|
||||
static BOOL _isGestureSet;
|
||||
|
||||
static NSMutableDictionary<NSString *, id> *_codelessSetting;
|
||||
static const NSTimeInterval kTimeout = 4.0;
|
||||
|
||||
static NSString *_deviceSessionID;
|
||||
static NSTimer *_appIndexingTimer;
|
||||
static NSString *_lastTreeHash;
|
||||
static id<FBSDKGraphRequestProviding> _requestProvider;
|
||||
static id<FBSDKServerConfigurationProviding> _serverConfigurationProvider;
|
||||
static id<FBSDKDataPersisting> _store;
|
||||
static id<FBSDKGraphRequestConnectionProviding> _connectionProvider;
|
||||
static Class<FBSDKSwizzling> _swizzler;
|
||||
static id<FBSDKSettings> _settings;
|
||||
static id<FBSDKAdvertiserIDProviding> _advertiserIDProvider;
|
||||
static id<FBSDKSettings> _settings;
|
||||
|
||||
+ (void)configureWithRequestProvider:(id<FBSDKGraphRequestProviding>)requestProvider
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
connectionProvider:(id<FBSDKGraphRequestConnectionProviding>)connectionProvider
|
||||
swizzler:(Class<FBSDKSwizzling>)swizzler
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
advertiserIDProvider:(id<FBSDKAdvertiserIDProviding>)advertiserIDProvider
|
||||
{
|
||||
if (self == [FBSDKCodelessIndexer class]) {
|
||||
_requestProvider = requestProvider;
|
||||
_serverConfigurationProvider = serverConfigurationProvider;
|
||||
_store = store;
|
||||
_connectionProvider = connectionProvider;
|
||||
_swizzler = swizzler;
|
||||
_settings = settings;
|
||||
_advertiserIDProvider = advertiserIDProvider;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id<FBSDKGraphRequestProviding>)requestProvider
|
||||
{
|
||||
return _requestProvider;
|
||||
}
|
||||
|
||||
+ (id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
{
|
||||
return _serverConfigurationProvider;
|
||||
}
|
||||
|
||||
+ (id<FBSDKDataPersisting>)store
|
||||
{
|
||||
return _store;
|
||||
}
|
||||
|
||||
+ (id<FBSDKGraphRequestConnectionProviding>)connectionProvider
|
||||
{
|
||||
return _connectionProvider;
|
||||
}
|
||||
|
||||
+ (Class<FBSDKSwizzling>)swizzler
|
||||
{
|
||||
return _swizzler;
|
||||
}
|
||||
|
||||
+ (id<FBSDKSettings>)settings
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
|
||||
+ (id<FBSDKAdvertiserIDProviding>)advertiserIDProvider
|
||||
{
|
||||
return _advertiserIDProvider;
|
||||
}
|
||||
|
||||
+ (void)enable
|
||||
{
|
||||
if (_isGestureSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
#if TARGET_OS_SIMULATOR
|
||||
[self setupGesture];
|
||||
#else
|
||||
[self loadCodelessSettingWithCompletionBlock:^(BOOL isCodelessSetupEnabled, NSError *error) {
|
||||
if (isCodelessSetupEnabled) {
|
||||
[self setupGesture];
|
||||
}
|
||||
}];
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
// DO NOT call this function, it is only called once in the enable function
|
||||
+ (void)loadCodelessSettingWithCompletionBlock:(FBSDKCodelessSettingLoadBlock)completionBlock
|
||||
{
|
||||
NSString *appID = [self.settings appID];
|
||||
if (appID == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.serverConfigurationProvider loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *serverConfigurationLoadingError) {
|
||||
if (!serverConfiguration.isCodelessEventsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load the defaults
|
||||
NSString *defaultKey = [NSString stringWithFormat:CODELESS_SETTING_KEY, appID];
|
||||
NSData *data = [self.store objectForKey:defaultKey];
|
||||
if ([data isKindOfClass:[NSData class]]) {
|
||||
NSMutableDictionary<NSString *, id> *codelessSetting = nil;
|
||||
id<FBSDKObjectDecoding> unarchiver = [FBSDKUnarchiverProvider createInsecureUnarchiverFor:data];
|
||||
@try {
|
||||
codelessSetting = [unarchiver decodeObjectOfClass:NSDictionary.class forKey:NSKeyedArchiveRootObjectKey];
|
||||
} @catch (NSException *ex) {
|
||||
// ignore decoding exceptions
|
||||
}
|
||||
if (codelessSetting) {
|
||||
_codelessSetting = codelessSetting;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
_codelessSetting
|
||||
&& [self _codelessSetupTimestampIsValid:[FBSDKTypeUtility dictionary:_codelessSetting objectForKey:CODELESS_SETTING_TIMESTAMP_KEY ofType:NSObject.class]]
|
||||
) {
|
||||
completionBlock([FBSDKTypeUtility boolValue:[FBSDKTypeUtility dictionary:_codelessSetting objectForKey:CODELESS_SETUP_ENABLED_KEY ofType:NSObject.class]], nil);
|
||||
} else {
|
||||
_codelessSetting = [NSMutableDictionary new];
|
||||
id<FBSDKGraphRequest> request = [self requestToLoadCodelessSetup:appID];
|
||||
if (request == nil) {
|
||||
return;
|
||||
}
|
||||
id<FBSDKGraphRequestConnecting> requestConnection = [self.connectionProvider createGraphRequestConnection];
|
||||
requestConnection.timeout = kTimeout;
|
||||
[requestConnection addRequest:request completion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *codelessLoadingError) {
|
||||
if (codelessLoadingError) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, id> *resultDictionary = [FBSDKTypeUtility dictionaryValue:result];
|
||||
if (resultDictionary) {
|
||||
BOOL isCodelessSetupEnabled = [FBSDKTypeUtility boolValue:resultDictionary[CODELESS_SETUP_ENABLED_FIELD]];
|
||||
[FBSDKTypeUtility dictionary:_codelessSetting setObject:@(isCodelessSetupEnabled) forKey:CODELESS_SETUP_ENABLED_KEY];
|
||||
[FBSDKTypeUtility dictionary:_codelessSetting setObject:[NSDate date] forKey:CODELESS_SETTING_TIMESTAMP_KEY];
|
||||
// update the cached copy in user defaults
|
||||
[self.store setObject:[NSKeyedArchiver archivedDataWithRootObject:_codelessSetting] forKey:defaultKey];
|
||||
completionBlock(isCodelessSetupEnabled, codelessLoadingError);
|
||||
}
|
||||
}];
|
||||
[requestConnection start];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (id<FBSDKGraphRequest>)requestToLoadCodelessSetup:(NSString *)appID
|
||||
{
|
||||
NSString *advertiserID = self.advertiserIDProvider.advertiserID;
|
||||
if (!advertiserID) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, NSString *> *parameters = @{
|
||||
@"fields" : CODELESS_SETUP_ENABLED_FIELD,
|
||||
@"advertiser_id" : advertiserID
|
||||
};
|
||||
id<FBSDKGraphRequest> request = [self.requestProvider createGraphRequestWithGraphPath:appID
|
||||
parameters:parameters
|
||||
tokenString:nil
|
||||
HTTPMethod:nil
|
||||
flags:FBSDKGraphRequestFlagSkipClientToken | FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||
return request;
|
||||
}
|
||||
|
||||
+ (BOOL)_codelessSetupTimestampIsValid:(NSDate *)timestamp
|
||||
{
|
||||
return (timestamp != nil && [[NSDate date] timeIntervalSinceDate:timestamp] < CODELESS_SETTING_CACHE_TIMEOUT);
|
||||
}
|
||||
|
||||
+ (void)setupGesture
|
||||
{
|
||||
_isGestureSet = YES;
|
||||
[UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
|
||||
Class class = [UIApplication class];
|
||||
|
||||
[self.swizzler swizzleSelector:@selector(motionBegan:withEvent:)
|
||||
onClass:class
|
||||
withBlock:^{
|
||||
if (FBSDKServerConfigurationManager.shared.cachedServerConfiguration.isCodelessEventsEnabled) {
|
||||
[self checkCodelessIndexingSession];
|
||||
}
|
||||
}
|
||||
named:@"motionBegan"];
|
||||
}
|
||||
|
||||
+ (void)checkCodelessIndexingSession
|
||||
{
|
||||
if (_isCheckingSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isCheckingSession = YES;
|
||||
NSDictionary *parameters = @{
|
||||
CODELESS_INDEXING_SESSION_ID_KEY : [self currentSessionDeviceID],
|
||||
CODELESS_INDEXING_EXT_INFO_KEY : [self extInfo]
|
||||
};
|
||||
id<FBSDKGraphRequest> request = [_requestProvider createGraphRequestWithGraphPath:[NSString stringWithFormat:@"%@/%@",
|
||||
[self.settings appID],
|
||||
CODELESS_INDEXING_SESSION_ENDPOINT]
|
||||
parameters:parameters
|
||||
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||
[request startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *error) {
|
||||
_isCheckingSession = NO;
|
||||
if ([result isKindOfClass:[NSDictionary class]]) {
|
||||
_isCodelessIndexingEnabled = [((NSDictionary *)result)[CODELESS_INDEXING_STATUS_KEY] boolValue];
|
||||
if (_isCodelessIndexingEnabled) {
|
||||
_lastTreeHash = nil;
|
||||
if (!_appIndexingTimer) {
|
||||
_appIndexingTimer = [NSTimer timerWithTimeInterval:CODELESS_INDEXING_UPLOAD_INTERVAL_IN_SECONDS
|
||||
target:self
|
||||
selector:@selector(startIndexing)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[[NSRunLoop mainRunLoop] addTimer:_appIndexingTimer forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
} else {
|
||||
_deviceSessionID = nil;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSString *)currentSessionDeviceID
|
||||
{
|
||||
if (!_deviceSessionID) {
|
||||
_deviceSessionID = [NSUUID UUID].UUIDString;
|
||||
}
|
||||
return _deviceSessionID;
|
||||
}
|
||||
|
||||
+ (NSString *)extInfo
|
||||
{
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
NSString *machine = @(systemInfo.machine);
|
||||
NSString *advertiserID = [FBSDKAppEventsUtility.shared advertiserID] ?: @"";
|
||||
machine = machine ?: @"";
|
||||
NSString *debugStatus = [FBSDKAppEventsUtility isDebugBuild] ? @"1" : @"0";
|
||||
#if TARGET_OS_SIMULATOR
|
||||
NSString *isSimulator = @"1";
|
||||
#else
|
||||
NSString *isSimulator = @"0";
|
||||
#endif
|
||||
NSLocale *locale = [NSLocale currentLocale];
|
||||
NSString *languageCode = [locale objectForKey:NSLocaleLanguageCode];
|
||||
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
|
||||
NSString *localeString = locale.localeIdentifier;
|
||||
if (languageCode && countryCode) {
|
||||
localeString = [NSString stringWithFormat:@"%@_%@", languageCode, countryCode];
|
||||
}
|
||||
|
||||
NSString *extinfo = [FBSDKBasicUtility JSONStringForObject:@[machine,
|
||||
advertiserID,
|
||||
debugStatus,
|
||||
isSimulator,
|
||||
localeString]
|
||||
error:NULL
|
||||
invalidObjectHandler:NULL];
|
||||
|
||||
return extinfo ?: @"";
|
||||
}
|
||||
|
||||
+ (void)startIndexing
|
||||
{
|
||||
if (!_isCodelessIndexingEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (UIApplicationStateActive != [UIApplication sharedApplication].applicationState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If userAgentSuffix begins with Unity, trigger unity code to upload view hierarchy
|
||||
NSString *userAgentSuffix = [FBSDKSettings userAgentSuffix];
|
||||
if (userAgentSuffix != nil && [userAgentSuffix hasPrefix:@"Unity"]) {
|
||||
Class FBUnityUtility = objc_lookUpClass("FBUnityUtility");
|
||||
SEL selector = NSSelectorFromString(@"triggerUploadViewHierarchy");
|
||||
if (FBUnityUtility && selector && [FBUnityUtility respondsToSelector:selector]) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
[FBUnityUtility performSelector:selector];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
} else {
|
||||
[self uploadIndexing];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)uploadIndexing
|
||||
{
|
||||
if (_isCodelessIndexing) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *tree = [FBSDKCodelessIndexer currentViewTree];
|
||||
|
||||
[self uploadIndexing:tree];
|
||||
}
|
||||
|
||||
+ (void)uploadIndexing:(NSString *)tree
|
||||
{
|
||||
if (_isCodelessIndexing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *currentTreeHash = [FBSDKUtility SHA256Hash:tree];
|
||||
if (_lastTreeHash && [_lastTreeHash isEqualToString:currentTreeHash]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_lastTreeHash = currentTreeHash;
|
||||
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
NSString *version = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
id<FBSDKGraphRequest> request = [_requestProvider createGraphRequestWithGraphPath:[NSString stringWithFormat:@"%@/%@",
|
||||
[self.settings appID],
|
||||
CODELESS_INDEXING_ENDPOINT]
|
||||
parameters:@{
|
||||
CODELESS_INDEXING_TREE_KEY : tree,
|
||||
CODELESS_INDEXING_APP_VERSION_KEY : version ?: @"",
|
||||
CODELESS_INDEXING_PLATFORM_KEY : @"iOS",
|
||||
CODELESS_INDEXING_SESSION_ID_KEY : [self currentSessionDeviceID]
|
||||
}
|
||||
HTTPMethod:FBSDKHTTPMethodPOST];
|
||||
_isCodelessIndexing = YES;
|
||||
[request startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *error) {
|
||||
_isCodelessIndexing = NO;
|
||||
if ([result isKindOfClass:[NSDictionary class]]) {
|
||||
_isCodelessIndexingEnabled = [result[CODELESS_INDEXING_STATUS_KEY] boolValue];
|
||||
if (!_isCodelessIndexingEnabled) {
|
||||
_deviceSessionID = nil;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSString *)currentViewTree
|
||||
{
|
||||
NSMutableArray *trees = [NSMutableArray array];
|
||||
|
||||
NSArray *windows = [UIApplication sharedApplication].windows;
|
||||
for (UIWindow *window in windows) {
|
||||
NSDictionary *tree = [FBSDKViewHierarchy recursiveCaptureTreeWithCurrentNode:window
|
||||
targetNode:nil
|
||||
objAddressSet:nil
|
||||
hash:YES];
|
||||
if (tree) {
|
||||
if (window.isKeyWindow) {
|
||||
[trees insertObject:tree atIndex:0];
|
||||
} else {
|
||||
[FBSDKTypeUtility array:trees addObject:tree];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == trees.count) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSArray *viewTrees = [trees reverseObjectEnumerator].allObjects;
|
||||
|
||||
NSData *data = UIImageJPEGRepresentation([FBSDKCodelessIndexer screenshot], 0.5);
|
||||
NSString *screenshot = [data base64EncodedStringWithOptions:0];
|
||||
|
||||
NSMutableDictionary *treeInfo = [NSMutableDictionary dictionary];
|
||||
|
||||
[FBSDKTypeUtility dictionary:treeInfo setObject:viewTrees forKey:@"view"];
|
||||
[FBSDKTypeUtility dictionary:treeInfo setObject:screenshot ?: @"" forKey:@"screenshot"];
|
||||
|
||||
NSString *tree = nil;
|
||||
data = [FBSDKTypeUtility dataWithJSONObject:treeInfo options:0 error:nil];
|
||||
if (data) {
|
||||
tree = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
+ (UIImage *)screenshot
|
||||
{
|
||||
UIWindow *window = [FBSDKInternalUtility.sharedUtility findWindow];
|
||||
if (!window) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContext(window.bounds.size);
|
||||
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, NSNumber *> *)dimensionOf:(NSObject *)obj
|
||||
{
|
||||
UIView *view = nil;
|
||||
|
||||
if ([obj isKindOfClass:[UIView class]]) {
|
||||
view = (UIView *)obj;
|
||||
} else if ([obj isKindOfClass:[UIViewController class]]) {
|
||||
view = ((UIViewController *)obj).view;
|
||||
}
|
||||
|
||||
CGRect frame = view.frame;
|
||||
CGPoint offset = CGPointZero;
|
||||
|
||||
if ([view isKindOfClass:[UIScrollView class]]) {
|
||||
offset = ((UIScrollView *)view).contentOffset;
|
||||
}
|
||||
|
||||
return @{
|
||||
CODELESS_VIEW_TREE_TOP_KEY : @((int)frame.origin.y),
|
||||
CODELESS_VIEW_TREE_LEFT_KEY : @((int)frame.origin.x),
|
||||
CODELESS_VIEW_TREE_WIDTH_KEY : @((int)frame.size.width),
|
||||
CODELESS_VIEW_TREE_HEIGHT_KEY : @((int)frame.size.height),
|
||||
CODELESS_VIEW_TREE_OFFSET_X_KEY : @((int)offset.x),
|
||||
CODELESS_VIEW_TREE_OFFSET_Y_KEY : @((int)offset.y),
|
||||
CODELESS_VIEW_TREE_VISIBILITY_KEY : view.isHidden ? @4 : @0
|
||||
};
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
+ (void)reset
|
||||
{
|
||||
_isCheckingSession = NO;
|
||||
_isCodelessIndexing = NO;
|
||||
_isCodelessIndexingEnabled = NO;
|
||||
_isGestureSet = NO;
|
||||
_codelessSetting = nil;
|
||||
_requestProvider = nil;
|
||||
_serverConfigurationProvider = nil;
|
||||
_store = nil;
|
||||
_connectionProvider = nil;
|
||||
_swizzler = nil;
|
||||
_settings = nil;
|
||||
_advertiserIDProvider = nil;
|
||||
_deviceSessionID = nil;
|
||||
_lastTreeHash = nil;
|
||||
}
|
||||
|
||||
+ (void)resetIsCodelessIndexing
|
||||
{
|
||||
_isCodelessIndexing = NO;
|
||||
}
|
||||
|
||||
+ (BOOL)isCheckingSession
|
||||
{
|
||||
return _isCheckingSession;
|
||||
}
|
||||
|
||||
+ (NSTimer *)appIndexingTimer
|
||||
{
|
||||
return _appIndexingTimer;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_SWIFT_NAME(CodelessParameterComponent)
|
||||
@interface FBSDKCodelessParameterComponent : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *name;
|
||||
@property (nonatomic, copy, readonly) NSString *value;
|
||||
@property (nonatomic, readonly) NSArray *path;
|
||||
@property (nonatomic, copy, readonly) NSString *pathType;
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict;
|
||||
- (BOOL)isEqualToParameter:(FBSDKCodelessParameterComponent *)parameter;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKCodelessParameterComponent.h"
|
||||
|
||||
#import "FBSDKCodelessPathComponent.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
@implementation FBSDKCodelessParameterComponent
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_name = [dict[CODELESS_MAPPING_PARAMETER_NAME_KEY] copy];
|
||||
_value = [dict[CODELESS_MAPPING_PARAMETER_VALUE_KEY] copy];
|
||||
_pathType = [dict[CODELESS_MAPPING_PATH_TYPE_KEY] copy];
|
||||
|
||||
NSArray *ary = dict[CODELESS_MAPPING_PATH_KEY];
|
||||
NSMutableArray *mut = [NSMutableArray array];
|
||||
for (NSDictionary *info in ary) {
|
||||
FBSDKCodelessPathComponent *component = [[FBSDKCodelessPathComponent alloc] initWithJSON:info];
|
||||
[FBSDKTypeUtility array:mut addObject:component];
|
||||
}
|
||||
_path = [mut copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToParameter:(FBSDKCodelessParameterComponent *)parameter
|
||||
{
|
||||
if (_path.count != parameter.path.count) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *current = [NSString stringWithFormat:@"%@|%@|%@",
|
||||
_name ?: @"",
|
||||
_value ?: @"",
|
||||
_pathType ?: @""];
|
||||
NSString *compared = [NSString stringWithFormat:@"%@|%@|%@",
|
||||
parameter.name ?: @"",
|
||||
parameter.value ?: @"",
|
||||
parameter.pathType ?: @""];
|
||||
|
||||
if (![current isEqualToString:compared]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _path.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:_path objectAtIndex:i] isEqualToPath:[FBSDKTypeUtility array:parameter.path objectAtIndex:i]]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/Codeless/FBSDKCodelessPathComponent.h
Generated
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_OPTIONS(int, FBSDKCodelessMatchBitmaskField)
|
||||
{
|
||||
FBSDKCodelessMatchBitmaskFieldID = 1,
|
||||
FBSDKCodelessMatchBitmaskFieldText = 1 << 1,
|
||||
FBSDKCodelessMatchBitmaskFieldTag = 1 << 2,
|
||||
FBSDKCodelessMatchBitmaskFieldDescription = 1 << 3,
|
||||
FBSDKCodelessMatchBitmaskFieldHint = 1 << 4
|
||||
};
|
||||
|
||||
NS_SWIFT_NAME(CodelessPathComponent)
|
||||
@interface FBSDKCodelessPathComponent : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *className;
|
||||
@property (nonatomic, copy, readonly) NSString *text;
|
||||
@property (nonatomic, copy, readonly) NSString *hint;
|
||||
@property (nonatomic, copy, readonly) NSString *desc; // description
|
||||
@property (nonatomic, readonly) int index;
|
||||
@property (nonatomic, readonly) int tag;
|
||||
@property (nonatomic, readonly) int section;
|
||||
@property (nonatomic, readonly) int row;
|
||||
@property (nonatomic, readonly) int matchBitmask;
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict;
|
||||
- (BOOL)isEqualToPath:(FBSDKCodelessPathComponent *)path;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/Codeless/FBSDKCodelessPathComponent.m
Generated
+81
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKCodelessPathComponent.h"
|
||||
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
@implementation FBSDKCodelessPathComponent
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_className = [dict[CODELESS_MAPPING_CLASS_NAME_KEY] copy];
|
||||
_text = [dict[CODELESS_MAPPING_TEXT_KEY] copy];
|
||||
_hint = [dict[CODELESS_MAPPING_HINT_KEY] copy];
|
||||
_desc = [dict[CODELESS_MAPPING_DESC_KEY] copy];
|
||||
|
||||
if (dict[CODELESS_MAPPING_INDEX_KEY]) {
|
||||
_index = [dict[CODELESS_MAPPING_INDEX_KEY] intValue];
|
||||
} else {
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
if (dict[CODELESS_MAPPING_SECTION_KEY]) {
|
||||
_section = [dict[CODELESS_MAPPING_SECTION_KEY] intValue];
|
||||
} else {
|
||||
_section = -1;
|
||||
}
|
||||
|
||||
if (dict[CODELESS_MAPPING_ROW_KEY]) {
|
||||
_row = [dict[CODELESS_MAPPING_ROW_KEY] intValue];
|
||||
} else {
|
||||
_row = -1;
|
||||
}
|
||||
|
||||
_tag = [dict[CODELESS_MAPPING_TAG_KEY] intValue];
|
||||
_matchBitmask = [dict[CODELESS_MAPPING_MATCH_BITMASK_KEY] intValue];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToPath:(FBSDKCodelessPathComponent *)path
|
||||
{
|
||||
NSString *current = [NSString stringWithFormat:@"%@|%@|%@|%@|%d|%d|%d|%d|%d",
|
||||
_className ?: @"",
|
||||
_text ?: @"",
|
||||
_hint ?: @"",
|
||||
_desc ?: @"",
|
||||
_index, _section, _row, _tag, _matchBitmask];
|
||||
NSString *compared = [NSString stringWithFormat:@"%@|%@|%@|%@|%d|%d|%d|%d|%d",
|
||||
path.className ?: @"",
|
||||
path.text ?: @"",
|
||||
path.hint ?: @"",
|
||||
path.desc ?: @"",
|
||||
path.index, path.section, path.row, path.tag, path.matchBitmask];
|
||||
return [current isEqualToString:compared];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FBSDKAppEventsNumberParser.h"
|
||||
#import "FBSDKCodelessParameterComponent.h"
|
||||
|
||||
@protocol FBSDKEventLogging;
|
||||
|
||||
NS_SWIFT_NAME(EventBinding)
|
||||
@interface FBSDKEventBinding : NSObject
|
||||
|
||||
@property (class, nonatomic, readonly) id<FBSDKNumberParsing> numberParser;
|
||||
@property (nonatomic, copy, readonly) NSString *eventName;
|
||||
@property (nonatomic, copy, readonly) NSString *eventType;
|
||||
@property (nonatomic, copy, readonly) NSString *appVersion;
|
||||
@property (nonatomic, readonly) NSArray *path;
|
||||
@property (nonatomic, copy, readonly) NSString *pathType;
|
||||
@property (nonatomic, readonly) NSArray<FBSDKCodelessParameterComponent *> *parameters;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
+ (BOOL)isViewMatchPath:(UIView *)view path:(NSArray *)path;
|
||||
+ (BOOL)isPath:(NSArray *)path matchViewPath:(NSArray *)viewPath;
|
||||
- (FBSDKEventBinding *)initWithJSON:(NSDictionary *)dict
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger;
|
||||
- (void)trackEvent:(id)sender;
|
||||
- (BOOL)isEqualToBinding:(FBSDKEventBinding *)binding;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+354
@@ -0,0 +1,354 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKEventBinding.h"
|
||||
|
||||
#import "FBSDKCodelessPathComponent.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKEventLogging.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKSwizzler.h"
|
||||
#import "FBSDKUtility.h"
|
||||
#import "FBSDKViewHierarchy.h"
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
#define CODELESS_PATH_TYPE_ABSOLUTE @"absolute"
|
||||
#define CODELESS_PATH_TYPE_RELATIVE @"relative"
|
||||
#define CODELESS_CODELESS_EVENT_KEY @"_is_fb_codeless"
|
||||
#define PARAMETER_NAME_PRICE @"_valueToSum"
|
||||
|
||||
@interface FBSDKEventBinding ()
|
||||
|
||||
@property (nonnull, nonatomic) id<FBSDKEventLogging> eventLogger;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKEventBinding
|
||||
|
||||
static id<FBSDKNumberParsing> _numberParser;
|
||||
|
||||
+ (id<FBSDKNumberParsing>)numberParser
|
||||
{
|
||||
return _numberParser;
|
||||
}
|
||||
|
||||
+ (void)setNumberParser:(id<FBSDKNumberParsing>)numberParser
|
||||
{
|
||||
_numberParser = numberParser;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
_numberParser = [[FBSDKAppEventsNumberParser alloc] initWithLocale:NSLocale.currentLocale];
|
||||
}
|
||||
|
||||
- (FBSDKEventBinding *)initWithJSON:(NSDictionary *)dict
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventLogger = eventLogger;
|
||||
|
||||
_eventName = [dict[CODELESS_MAPPING_EVENT_NAME_KEY] copy];
|
||||
_eventType = [dict[CODELESS_MAPPING_EVENT_TYPE_KEY] copy];
|
||||
_appVersion = [dict[CODELESS_MAPPING_APP_VERSION_KEY] copy];
|
||||
_pathType = [dict[CODELESS_MAPPING_PATH_TYPE_KEY] copy];
|
||||
|
||||
NSArray *pathComponents = dict[CODELESS_MAPPING_PATH_KEY];
|
||||
NSMutableArray *mut = [NSMutableArray array];
|
||||
for (NSDictionary *info in pathComponents) {
|
||||
FBSDKCodelessPathComponent *component = [[FBSDKCodelessPathComponent alloc] initWithJSON:info];
|
||||
[FBSDKTypeUtility array:mut addObject:component];
|
||||
}
|
||||
_path = [mut copy];
|
||||
|
||||
NSArray *parameters = dict[CODELESS_MAPPING_PARAMETERS_KEY];
|
||||
mut = [NSMutableArray array];
|
||||
for (NSDictionary *info in parameters) {
|
||||
FBSDKCodelessParameterComponent *component = [[FBSDKCodelessParameterComponent alloc] initWithJSON:info];
|
||||
[FBSDKTypeUtility array:mut addObject:component];
|
||||
}
|
||||
_parameters = [mut copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)trackEvent:(id)sender
|
||||
{
|
||||
UIView *sourceView = [sender isKindOfClass:[UIView class]] ? (UIView *)sender : nil;
|
||||
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
||||
[FBSDKTypeUtility dictionary:params setObject:@"1" forKey:CODELESS_CODELESS_EVENT_KEY];
|
||||
for (FBSDKCodelessParameterComponent *component in self.parameters) {
|
||||
NSString *text = component.value;
|
||||
if (!text || text.length == 0) {
|
||||
text = [FBSDKEventBinding findParameterOfPath:component.path
|
||||
pathType:component.pathType
|
||||
sourceView:sourceView];
|
||||
}
|
||||
if (text.length > 0) {
|
||||
if ([component.name isEqualToString:PARAMETER_NAME_PRICE]) {
|
||||
NSNumber *value = [self.class.numberParser parseNumberFrom:text];
|
||||
[FBSDKTypeUtility dictionary:params setObject:value forKey:component.name];
|
||||
} else {
|
||||
[FBSDKTypeUtility dictionary:params setObject:text forKey:component.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self.eventLogger logEvent:_eventName parameters:[params copy]];
|
||||
}
|
||||
|
||||
+ (BOOL)matchAnyView:(NSArray *)views
|
||||
pathComponent:(FBSDKCodelessPathComponent *)component
|
||||
{
|
||||
for (NSObject *view in views) {
|
||||
if ([self match:view pathComponent:component]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL) match:(NSObject *)view
|
||||
pathComponent:(FBSDKCodelessPathComponent *)component
|
||||
{
|
||||
if (!view) {
|
||||
return NO;
|
||||
}
|
||||
NSString *className = NSStringFromClass([view class]);
|
||||
if (![className isEqualToString:component.className]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (component.index >= 0) {
|
||||
NSObject *parent = [FBSDKViewHierarchy getParent:view];
|
||||
if (parent) {
|
||||
NSArray *children = [FBSDKViewHierarchy getChildren:[FBSDKViewHierarchy getParent:view]];
|
||||
NSUInteger index = [children indexOfObject:view];
|
||||
if (index == NSNotFound || index != component.index) {
|
||||
return NO;
|
||||
}
|
||||
} else {
|
||||
if (0 != component.index) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldText) > 0) {
|
||||
NSString *text = [FBSDKViewHierarchy getText:view];
|
||||
BOOL match = ((text.length == 0 && component.text.length == 0)
|
||||
|| [text isEqualToString:component.text]);
|
||||
if (!match) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldTag) > 0
|
||||
&& [view isKindOfClass:[UIView class]]
|
||||
&& component.tag != ((UIView *)view).tag) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ((component.matchBitmask & FBSDKCodelessMatchBitmaskFieldHint) > 0) {
|
||||
NSString *hint = [FBSDKViewHierarchy getHint:view];
|
||||
BOOL match = ((hint.length == 0 && component.hint.length == 0)
|
||||
|| [hint isEqualToString:component.hint]);
|
||||
if (!match) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)isViewMatchPath:(UIView *)view path:(NSArray *)path
|
||||
{
|
||||
NSArray *viewPath = [FBSDKViewHierarchy getPath:view];
|
||||
BOOL isMatch = [self isPath:path matchViewPath:viewPath];
|
||||
|
||||
return isMatch;
|
||||
}
|
||||
|
||||
+ (BOOL)isPath:(NSArray *)path matchViewPath:(NSArray *)viewPath
|
||||
{
|
||||
if ((path.count == 0) || (viewPath.count == 0)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (NSInteger i = 0; i < MIN(path.count, viewPath.count); i++) {
|
||||
NSInteger idxPath = path.count - i - 1;
|
||||
NSInteger idxViewPath = viewPath.count - i - 1;
|
||||
|
||||
FBSDKCodelessPathComponent *pathComponent = [FBSDKTypeUtility array:path objectAtIndex:idxPath];
|
||||
FBSDKCodelessPathComponent *viewPathComponent = [FBSDKTypeUtility array:viewPath objectAtIndex:idxViewPath];
|
||||
|
||||
if (![pathComponent.className isEqualToString:viewPathComponent.className]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (pathComponent.index >= 0
|
||||
&& pathComponent.index != viewPathComponent.index) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldText) > 0) {
|
||||
NSString *text = viewPathComponent.text;
|
||||
BOOL match = ((text.length == 0 && pathComponent.text.length == 0)
|
||||
|| [text isEqualToString:pathComponent.text]
|
||||
|| [[FBSDKUtility SHA256Hash:text] isEqualToString:pathComponent.text]);
|
||||
if (!match) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldTag) > 0
|
||||
&& pathComponent.tag != viewPathComponent.tag) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ((pathComponent.matchBitmask & FBSDKCodelessMatchBitmaskFieldHint) > 0) {
|
||||
NSString *hint = viewPathComponent.hint;
|
||||
BOOL match = ((hint.length == 0 && pathComponent.hint.length == 0)
|
||||
|| [hint isEqualToString:pathComponent.hint]
|
||||
|| [[FBSDKUtility SHA256Hash:hint] isEqualToString:pathComponent.hint]);
|
||||
if (!match) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (NSObject *)findViewByPath:(NSArray *)path parent:(NSObject *)parent level:(int)level
|
||||
{
|
||||
if (level >= path.count) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
FBSDKCodelessPathComponent *pathComponent = [FBSDKTypeUtility array:path objectAtIndex:level];
|
||||
|
||||
// If found parent, skip to next level
|
||||
if ([pathComponent.className isEqualToString:CODELESS_MAPPING_PARENT_CLASS_NAME]) {
|
||||
NSObject *nextParent = [FBSDKViewHierarchy getParent:parent];
|
||||
|
||||
return [FBSDKEventBinding findViewByPath:path parent:nextParent level:level + 1];
|
||||
} else if ([pathComponent.className isEqualToString:CODELESS_MAPPING_CURRENT_CLASS_NAME]) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
NSArray *children;
|
||||
if (parent) {
|
||||
children = [FBSDKViewHierarchy getChildren:parent];
|
||||
} else {
|
||||
UIWindow *window = [FBSDKInternalUtility.sharedUtility findWindow];
|
||||
if (window) {
|
||||
children = @[window];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (path.count - 1 == level) {
|
||||
int index = pathComponent.index;
|
||||
if (index >= 0) {
|
||||
NSObject *child = index < children.count ? [FBSDKTypeUtility array:children objectAtIndex:index] : nil;
|
||||
if ([self match:child pathComponent:pathComponent]) {
|
||||
return child;
|
||||
}
|
||||
} else {
|
||||
for (NSObject *child in children) {
|
||||
if ([self match:child pathComponent:pathComponent]) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (NSObject *child in children) {
|
||||
NSObject *result = [self findViewByPath:path parent:child level:level + 1];
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToBinding:(FBSDKEventBinding *)binding
|
||||
{
|
||||
if (_path.count != binding.path.count
|
||||
|| _parameters.count != binding.parameters.count) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *current = [NSString stringWithFormat:@"%@|%@|%@|%@",
|
||||
_eventName ?: @"",
|
||||
_eventType ?: @"",
|
||||
_appVersion ?: @"",
|
||||
_pathType ?: @""];
|
||||
NSString *compared = [NSString stringWithFormat:@"%@|%@|%@|%@",
|
||||
binding.eventName ?: @"",
|
||||
binding.eventType ?: @"",
|
||||
binding.appVersion ?: @"",
|
||||
binding.pathType ?: @""];
|
||||
if (![current isEqualToString:compared]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _path.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:_path objectAtIndex:i] isEqualToPath:[FBSDKTypeUtility array:binding.path objectAtIndex:i]]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _parameters.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:_parameters objectAtIndex:i] isEqualToParameter:[FBSDKTypeUtility array:binding.parameters objectAtIndex:i]]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// MARK: - find event parameters via relative path
|
||||
+ (NSString *)findParameterOfPath:(NSArray *)path
|
||||
pathType:(NSString *)pathType
|
||||
sourceView:(UIView *)sourceView
|
||||
{
|
||||
if (0 == path.count) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIView *rootView = sourceView;
|
||||
if (![pathType isEqualToString:CODELESS_PATH_TYPE_RELATIVE]) {
|
||||
rootView = nil;
|
||||
}
|
||||
|
||||
NSObject *foundObj = [self findViewByPath:path parent:rootView level:0];
|
||||
|
||||
return [FBSDKViewHierarchy getText:foundObj];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol FBSDKSwizzling;
|
||||
@protocol FBSDKEventLogging;
|
||||
@class FBSDKEventBinding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(EventBindingManager)
|
||||
@interface FBSDKEventBindingManager : NSObject
|
||||
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger;
|
||||
- (void)updateBindings:(NSArray *)bindings;
|
||||
- (NSArray<FBSDKEventBinding *> *)parseArray:(NSArray *)array;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Generated
+498
@@ -0,0 +1,498 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKEventBindingManager.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "FBSDKCodelessPathComponent.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKEventBinding.h"
|
||||
#import "FBSDKEventLogging.h"
|
||||
#import "FBSDKSwizzling.h"
|
||||
#import "FBSDKViewHierarchy.h"
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
#define ReactNativeTargetKey @"target"
|
||||
#define ReactNativeTouchEndEventName @"touchEnd"
|
||||
|
||||
#define ReactNativeClassRCTTextView "RCTTextView"
|
||||
#define ReactNativeClassRCTImageView "RCTImageView"
|
||||
#define ReactNativeClassRCTTouchEvent "RCTTouchEvent"
|
||||
#define ReactNativeClassRCTTouchHandler "RCTTouchHandler"
|
||||
|
||||
@interface FBSDKEventBindingManager ()
|
||||
|
||||
@property (nonnull, nonatomic) id<FBSDKEventLogging> eventLogger;
|
||||
@property (nonnull, nonatomic) Class<FBSDKSwizzling> swizzler;
|
||||
@property (nonatomic) BOOL isStarted;
|
||||
@property (nullable, nonatomic) NSMutableDictionary *reactBindings;
|
||||
@property (nonnull, nonatomic) NSSet *validClasses;
|
||||
@property (nonatomic) BOOL hasReactNative;
|
||||
@property (nullable, nonatomic) NSArray *eventBindings;
|
||||
|
||||
@end
|
||||
|
||||
#if FBSDK_SWIFT_PACKAGE
|
||||
NS_EXTENSION_UNAVAILABLE("The Facebook iOS SDK is not currently supported in extensions")
|
||||
#endif
|
||||
@implementation FBSDKEventBindingManager
|
||||
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger;
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_swizzler = swizzling;
|
||||
_eventLogger = eventLogger;
|
||||
_hasReactNative = NO;
|
||||
_isStarted = NO;
|
||||
_reactBindings = [NSMutableDictionary dictionary];
|
||||
|
||||
NSMutableSet *classes = [NSMutableSet set];
|
||||
[classes addObject:[UIControl class]];
|
||||
[classes addObject:[UITableView class]];
|
||||
[classes addObject:[UICollectionView class]];
|
||||
// ReactNative
|
||||
Class classRCTRootView = objc_lookUpClass(ReactNativeClassRCTRootView);
|
||||
if (classRCTRootView != nil) {
|
||||
_hasReactNative = YES;
|
||||
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||
Class classRCTImageView = objc_lookUpClass(ReactNativeClassRCTImageView);
|
||||
if (classRCTView) {
|
||||
[classes addObject:classRCTView];
|
||||
}
|
||||
if (classRCTTextView) {
|
||||
[classes addObject:classRCTTextView];
|
||||
}
|
||||
if (classRCTImageView) {
|
||||
[classes addObject:classRCTImageView];
|
||||
}
|
||||
}
|
||||
_validClasses = [NSSet setWithSet:classes];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict
|
||||
swizzler:(Class<FBSDKSwizzling>)swizzler
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
{
|
||||
if ((self = [self initWithSwizzler:swizzler eventLogger:eventLogger])) {
|
||||
NSArray *eventBindingsDict = [FBSDKTypeUtility arrayValue:dict[@"event_bindings"]];
|
||||
NSMutableArray *bindings = [NSMutableArray array];
|
||||
for (NSDictionary *d in eventBindingsDict) {
|
||||
FBSDKEventBinding *e = [[FBSDKEventBinding alloc] initWithJSON:d eventLogger:eventLogger];
|
||||
[FBSDKTypeUtility array:bindings addObject:e];
|
||||
}
|
||||
_eventBindings = [bindings copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)parseArray:(NSArray *)array
|
||||
{
|
||||
NSMutableArray *result = [NSMutableArray array];
|
||||
|
||||
for (NSDictionary *json in array) {
|
||||
FBSDKEventBinding *binding = [[FBSDKEventBinding alloc] initWithJSON:json
|
||||
eventLogger:self.eventLogger];
|
||||
[FBSDKTypeUtility array:result addObject:binding];
|
||||
}
|
||||
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
- (void)start
|
||||
{
|
||||
if (self.isStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.isStarted = YES;
|
||||
|
||||
void (^blockToWindow)(id view) = ^(id view) {
|
||||
[self matchView:view delegate:nil];
|
||||
};
|
||||
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:[UIControl class]
|
||||
withBlock:blockToWindow
|
||||
named:@"map_control"];
|
||||
|
||||
// ReactNative
|
||||
if (self.hasReactNative) { // If app is built via ReactNative
|
||||
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||
Class classRCTImageView = objc_lookUpClass(ReactNativeClassRCTImageView);
|
||||
Class classRCTTouchHandler = objc_lookUpClass(ReactNativeClassRCTTouchHandler);
|
||||
|
||||
// All react-native views would be added tp RCTRootView, so no need to check didMoveToWindow
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTTextView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTImageView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
|
||||
// RCTTouchHandler handles with touch events, like touchEnd and uses RCTEventDispather to dispatch events, so we can check _updateAndDispatchTouches to fire events
|
||||
[self.swizzler swizzleSelector:@selector(_updateAndDispatchTouches:eventName:)
|
||||
onClass:classRCTTouchHandler
|
||||
withBlock:^(id touchHandler, SEL command, id touches, id eventName) {
|
||||
[self handleReactNativeTouchesWithHandler:touchHandler command:command touches:touches eventName:eventName];
|
||||
}
|
||||
named:@"dispatch_rn_event"];
|
||||
}
|
||||
|
||||
// UITableView
|
||||
void (^tableViewBlock)(UITableView *tableView,
|
||||
SEL cmd,
|
||||
id<UITableViewDelegate> delegate) =
|
||||
^(UITableView *tableView, SEL cmd, id<UITableViewDelegate> delegate) {
|
||||
if (!delegate) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self matchView:tableView delegate:delegate];
|
||||
};
|
||||
[self.swizzler swizzleSelector:@selector(setDelegate:)
|
||||
onClass:[UITableView class]
|
||||
withBlock:tableViewBlock
|
||||
named:@"match_table_view"];
|
||||
// UICollectionView
|
||||
void (^collectionViewBlock)(UICollectionView *collectionView,
|
||||
SEL cmd,
|
||||
id<UICollectionViewDelegate> delegate) =
|
||||
^(UICollectionView *collectionView, SEL cmd, id<UICollectionViewDelegate> delegate) {
|
||||
if (nil == delegate) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self matchView:collectionView delegate:delegate];
|
||||
};
|
||||
[self.swizzler swizzleSelector:@selector(setDelegate:)
|
||||
onClass:[UICollectionView class]
|
||||
withBlock:collectionViewBlock
|
||||
named:@"handle_collection_view"];
|
||||
}
|
||||
|
||||
- (void)rematchBindings
|
||||
{
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *windows = [UIApplication sharedApplication].windows;
|
||||
for (UIWindow *window in windows) {
|
||||
[self matchSubviewsIn:window];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)matchSubviewsIn:(UIView *)view
|
||||
{
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (UIView *subview in view.subviews) {
|
||||
BOOL isValidClass = NO;
|
||||
for (Class cls in self.validClasses) {
|
||||
if ([subview isKindOfClass:cls]) {
|
||||
isValidClass = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValidClass) {
|
||||
if ([subview isKindOfClass:[UITableView class]]) {
|
||||
UITableView *tableView = (UITableView *)subview;
|
||||
if (tableView.delegate) {
|
||||
[self matchView:subview delegate:tableView.delegate];
|
||||
}
|
||||
} else if ([subview isKindOfClass:[UICollectionView class]]) {
|
||||
UICollectionView *collectionView = (UICollectionView *)subview;
|
||||
if (collectionView.delegate) {
|
||||
[self matchView:subview delegate:collectionView.delegate];
|
||||
}
|
||||
} else {
|
||||
[self matchView:subview delegate:nil];
|
||||
}
|
||||
}
|
||||
|
||||
if (![subview isKindOfClass:[UIControl class]]) {
|
||||
[self matchSubviewsIn:subview];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the view is matched to any event
|
||||
- (void)matchView:(UIView *)view delegate:(id)delegate
|
||||
{
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
__weak Class<FBSDKSwizzling> weakSwizzler = self.swizzler;
|
||||
__block BOOL hasReactNative = self.hasReactNative;
|
||||
fb_dispatch_on_main_thread(^{
|
||||
if (![view window]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *path = [FBSDKViewHierarchy getPath:view];
|
||||
|
||||
void (^matchBlock)(void) = ^void () {
|
||||
if ([view isKindOfClass:[UIControl class]]) {
|
||||
UIControl *control = (UIControl *)view;
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
|
||||
fb_dispatch_on_main_thread(^{
|
||||
[control addTarget:binding
|
||||
action:@selector(trackEvent:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (hasReactNative
|
||||
&& [view respondsToSelector:@selector(reactTag)]) {
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
|
||||
fb_dispatch_on_main_thread(^{
|
||||
if (view) {
|
||||
NSNumber *reactTag = [FBSDKViewHierarchy getViewReactTag:view];
|
||||
if (reactTag != nil) {
|
||||
[FBSDKTypeUtility dictionary:self->_reactBindings setObject:binding forKey:reactTag];
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ([view isKindOfClass:[UITableView class]]
|
||||
&& [delegate conformsToProtocol:@protocol(UITableViewDelegate)]) {
|
||||
void (^tableViewBlock)(void) = ^void () {
|
||||
NSMutableSet *matchedBindings = [NSMutableSet set];
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if (binding.path.count > 1) {
|
||||
NSArray *shortPath = [binding.path
|
||||
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
|
||||
if ([FBSDKEventBinding isPath:shortPath matchViewPath:path]) {
|
||||
[matchedBindings addObject:binding];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedBindings.count > 0) {
|
||||
NSArray *bindings = matchedBindings.allObjects;
|
||||
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UITableView *tableView, NSIndexPath *indexPath) {
|
||||
[self handleDidSelectRowWithBindings:bindings target:target command:command tableView:tableView indexPath:indexPath];
|
||||
};
|
||||
[weakSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_table_view"];
|
||||
}
|
||||
};
|
||||
#if FBTEST
|
||||
tableViewBlock();
|
||||
#else
|
||||
fb_dispatch_on_default_thread(tableViewBlock);
|
||||
#endif
|
||||
} else if ([view isKindOfClass:[UICollectionView class]]
|
||||
&& [delegate conformsToProtocol:@protocol(UICollectionViewDelegate)]) {
|
||||
void (^collectionViewBlock)(void) = ^void () {
|
||||
NSMutableSet *matchedBindings = [NSMutableSet set];
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if (binding.path.count > 1) {
|
||||
NSArray *shortPath = [binding.path
|
||||
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
|
||||
if ([FBSDKEventBinding isPath:shortPath matchViewPath:path]) {
|
||||
[matchedBindings addObject:binding];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedBindings.count > 0) {
|
||||
NSArray *bindings = matchedBindings.allObjects;
|
||||
void (^block)(id, SEL, id, id) = ^(id target, SEL command, UICollectionView *collectionView, NSIndexPath *indexPath) {
|
||||
[self handleDidSelectItemWithBindings:bindings target:target command:command collectionView:collectionView indexPath:indexPath];
|
||||
};
|
||||
[weakSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_collection_view"];
|
||||
}
|
||||
};
|
||||
#if FBTEST
|
||||
collectionViewBlock();
|
||||
#else
|
||||
fb_dispatch_on_default_thread(collectionViewBlock);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if FBTEST
|
||||
matchBlock();
|
||||
#else
|
||||
fb_dispatch_on_default_thread(matchBlock);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
- (void)updateBindings:(NSArray *)bindings
|
||||
{
|
||||
if (self.eventBindings.count > 0 && self.eventBindings.count == bindings.count) {
|
||||
// Check whether event bindings are the same
|
||||
BOOL isSame = YES;
|
||||
for (int i = 0; i < self.eventBindings.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:self.eventBindings objectAtIndex:i] isEqualToBinding:[FBSDKTypeUtility array:bindings objectAtIndex:i]]) {
|
||||
isSame = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSame) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.eventBindings = bindings;
|
||||
[self.reactBindings removeAllObjects];
|
||||
if (!self.isStarted) {
|
||||
[self start];
|
||||
}
|
||||
|
||||
fb_dispatch_on_main_thread(^{
|
||||
[self rematchBindings];
|
||||
});
|
||||
}
|
||||
|
||||
// MARK: Method Replacements
|
||||
|
||||
- (void)handleReactNativeTouchesWithHandler:(id)handler
|
||||
command:(SEL)command
|
||||
touches:(id)touches
|
||||
eventName:(id)eventName
|
||||
{
|
||||
if ([touches isKindOfClass:[NSSet class]] && [eventName isKindOfClass:[NSString class]]) {
|
||||
@try {
|
||||
NSString *reactEventName = (NSString *)eventName;
|
||||
NSSet<UITouch *> *reactTouches = (NSSet<UITouch *> *)touches;
|
||||
if ([reactEventName isEqualToString:ReactNativeTouchEndEventName]) {
|
||||
for (UITouch *touch in reactTouches) {
|
||||
UIView *targetView = ((UITouch *)touch).view.superview;
|
||||
NSNumber *reactTag = nil;
|
||||
// Find the closest React-managed touchable view like RCTTouchHandler
|
||||
while (targetView) {
|
||||
reactTag = [FBSDKViewHierarchy getViewReactTag:targetView];
|
||||
if (reactTag != nil && targetView.userInteractionEnabled) {
|
||||
break;
|
||||
}
|
||||
targetView = targetView.superview;
|
||||
}
|
||||
FBSDKEventBinding *eventBinding = self->_reactBindings[reactTag];
|
||||
if (reactTag != nil && eventBinding != nil) {
|
||||
[eventBinding trackEvent:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
// Catch exception here to prevent LytroKit from crashing app
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
- (void)handleDidSelectRowWithBindings:(NSArray<FBSDKEventBinding *> *)bindings
|
||||
target:(nullable id)target
|
||||
command:(nullable SEL)command
|
||||
tableView:(UITableView *)tableView
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
fb_dispatch_on_main_thread(^{
|
||||
for (FBSDKEventBinding *binding in bindings) {
|
||||
FBSDKCodelessPathComponent *component = binding.path.lastObject;
|
||||
if ((component.section == -1 || component.section == indexPath.section)
|
||||
&& (component.row == -1 || component.row == indexPath.row)) {
|
||||
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell) {
|
||||
[binding trackEvent:cell];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)handleDidSelectItemWithBindings:(NSArray<FBSDKEventBinding *> *)bindings
|
||||
target:(nullable id)target
|
||||
command:(nullable SEL)command
|
||||
collectionView:(UICollectionView *)collectionView
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
fb_dispatch_on_main_thread(^{
|
||||
for (FBSDKEventBinding *binding in bindings) {
|
||||
FBSDKCodelessPathComponent *component = binding.path.lastObject;
|
||||
if ((component.section == -1 || component.section == indexPath.section)
|
||||
&& (component.row == -1 || component.row == indexPath.row)) {
|
||||
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
||||
if (cell) {
|
||||
[binding trackEvent:cell];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (NSSet *)validClasses
|
||||
{
|
||||
return _validClasses;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
- (void)setReactBindings:(NSMutableDictionary *)bindings
|
||||
{
|
||||
_reactBindings = bindings;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsParameterProcessing.h"
|
||||
#import "FBSDKEventDeactivationManager.h"
|
||||
#import "FBSDKEventsProcessing.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKEventDeactivationManager (Protocols) <FBSDKAppEventsParameterProcessing, FBSDKEventsProcessing>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(EventDeactivationManager)
|
||||
@interface FBSDKEventDeactivationManager : NSObject
|
||||
|
||||
- (void)enable;
|
||||
- (void)processEvents:(NSMutableArray<NSDictionary<NSString *, id> *> *)events;
|
||||
- (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKEventDeactivationManager.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKServerConfigurationManager+ServerConfigurationProviding.h"
|
||||
|
||||
static NSString *const DEPRECATED_PARAM_KEY = @"deprecated_param";
|
||||
static NSString *const DEPRECATED_EVENT_KEY = @"is_deprecated_event";
|
||||
|
||||
@interface FBSDKDeactivatedEvent : NSObject
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||
@property (nullable, nonatomic, readonly, copy) NSSet<NSString *> *deactivatedParams;
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName
|
||||
deactivatedParams:(NSSet<NSString *> *)deactivatedParams;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKDeactivatedEvent
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName
|
||||
deactivatedParams:(NSSet<NSString *> *)deactivatedParams
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_eventName = eventName;
|
||||
_deactivatedParams = deactivatedParams;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FBSDKEventDeactivationManager ()
|
||||
|
||||
@property (nonatomic) BOOL isEventDeactivationEnabled;
|
||||
@property (nonatomic, strong) NSMutableSet<NSString *> *deactivatedEvents;
|
||||
@property (nonatomic, strong) NSMutableArray<FBSDKDeactivatedEvent *> *eventsWithDeactivatedParams;
|
||||
@property (nonatomic) id<FBSDKServerConfigurationProviding> serverConfigurationProvider;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKEventDeactivationManager
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static FBSDKEventDeactivationManager *instance;
|
||||
static dispatch_once_t nonce;
|
||||
dispatch_once(&nonce, ^{
|
||||
instance = [[self alloc] initWithServerConfigurationProvider:FBSDKServerConfigurationManager.shared];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithServerConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
{
|
||||
self.isEventDeactivationEnabled = NO;
|
||||
self.serverConfigurationProvider = serverConfigurationProvider;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)enable
|
||||
{
|
||||
@try {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSDictionary<NSString *, id> *restrictiveParams = [self.serverConfigurationProvider cachedServerConfiguration].restrictiveParams;
|
||||
if (restrictiveParams) {
|
||||
[self _updateDeactivatedEvents:restrictiveParams];
|
||||
self.isEventDeactivationEnabled = YES;
|
||||
}
|
||||
});
|
||||
} @catch (NSException *exception) {}
|
||||
}
|
||||
|
||||
- (void)processEvents:(NSMutableArray<NSDictionary<NSString *, id> *> *)events
|
||||
{
|
||||
@try {
|
||||
if (!self.isEventDeactivationEnabled) {
|
||||
return;
|
||||
}
|
||||
NSArray<NSDictionary<NSString *, id> *> *eventArray = [events copy];
|
||||
for (NSDictionary<NSString *, NSDictionary<NSString *, id> *> *event in eventArray) {
|
||||
if ([self.deactivatedEvents containsObject:event[@"event"][@"_eventName"]]) {
|
||||
[events removeObject:event];
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {}
|
||||
}
|
||||
|
||||
- (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName
|
||||
{
|
||||
@try {
|
||||
if (!self.isEventDeactivationEnabled || parameters.count == 0 || self.eventsWithDeactivatedParams.count == 0) {
|
||||
return parameters;
|
||||
}
|
||||
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
for (NSString *key in [parameters keyEnumerator]) {
|
||||
for (FBSDKDeactivatedEvent *event in self.eventsWithDeactivatedParams) {
|
||||
if ([event.eventName isEqualToString:eventName] && [event.deactivatedParams containsObject:key]) {
|
||||
[params removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [params copy];
|
||||
} @catch (NSException *exception) {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
|
||||
- (void)_updateDeactivatedEvents:(nullable NSDictionary<NSString *, id> *)events
|
||||
{
|
||||
events = [FBSDKTypeUtility dictionaryValue:events];
|
||||
if (events.count == 0) {
|
||||
return;
|
||||
}
|
||||
[self.deactivatedEvents removeAllObjects];
|
||||
[self.eventsWithDeactivatedParams removeAllObjects];
|
||||
NSMutableArray<FBSDKDeactivatedEvent *> *deactivatedParamsArray = [NSMutableArray array];
|
||||
NSMutableSet<NSString *> *deactivatedEventSet = [NSMutableSet set];
|
||||
for (NSString *eventName in events.allKeys) {
|
||||
NSDictionary<NSString *, id> *eventInfo = [FBSDKTypeUtility dictionary:events objectForKey:eventName ofType:NSDictionary.class];
|
||||
if (!eventInfo) {
|
||||
continue;
|
||||
}
|
||||
if (eventInfo[DEPRECATED_EVENT_KEY]) {
|
||||
[deactivatedEventSet addObject:eventName];
|
||||
}
|
||||
if (eventInfo[DEPRECATED_PARAM_KEY]) {
|
||||
FBSDKDeactivatedEvent *eventWithDeactivatedParams = [[FBSDKDeactivatedEvent alloc] initWithEventName:eventName
|
||||
deactivatedParams:[NSSet setWithArray:eventInfo[DEPRECATED_PARAM_KEY]]];
|
||||
[FBSDKTypeUtility array:deactivatedParamsArray addObject:eventWithDeactivatedParams];
|
||||
}
|
||||
}
|
||||
self.deactivatedEvents = deactivatedEventSet;
|
||||
self.eventsWithDeactivatedParams = deactivatedParamsArray;
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
#import "FBSDKAppEvents.h"
|
||||
#else
|
||||
#import <FBSDKCoreKit/FBSDKAppEvents.h>
|
||||
#endif
|
||||
|
||||
#import "FBSDKEventLogging.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKAppEvents (EventLogging) <FBSDKEventLogging>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#if defined FBSDK_SWIFT_PACKAGE
|
||||
#import "FBSDKAppEvents.h"
|
||||
#else
|
||||
#import <FBSDKCoreKit/FBSDKAppEvents.h>
|
||||
#endif
|
||||
|
||||
#import <UIKit/UIApplication.h>
|
||||
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
|
||||
// Internally known event names
|
||||
|
||||
/** Use to log that the share dialog was launched */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareSheetLaunch;
|
||||
|
||||
/** Use to log that the share dialog was dismissed */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareSheetDismiss;
|
||||
|
||||
/** Use to log that the permissions UI was launched */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNamePermissionsUILaunch;
|
||||
|
||||
/** Use to log that the permissions UI was dismissed */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNamePermissionsUIDismiss;
|
||||
|
||||
/** Use to log that the share tray launched. */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareTrayDidLaunch;
|
||||
|
||||
/** Use to log that the person selected a sharing target. */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameShareTrayDidSelectActivity;
|
||||
|
||||
// Internally known event parameters
|
||||
|
||||
/** Use to log the result of a call to FBDialogs presentShareDialogWithParams: */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentShareDialog;
|
||||
|
||||
/** Use to log the result of a call to FBDialogs presentLikeDialogWithLikeParams: */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentLikeDialogOG;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentShareDialogPhoto;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialog;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialogPhoto;
|
||||
|
||||
/** Use to log the live streaming events from sdk */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingStart;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingStop;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingPause;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingResume;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingError;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingUpdateStatus;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingVideoID;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingMic;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingCamera;
|
||||
|
||||
/** Use to log the results of a share dialog */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogResult;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogShow;
|
||||
|
||||
/** Use to log parameters for share tray use */
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterShareTrayActivityName;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterShareTrayResult;
|
||||
|
||||
/** Use to log parameters for live streaming*/
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingPrevStatus;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingStatus;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingError;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingVideoID;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingMicEnabled;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventParameterLiveStreamingCameraEnabled;
|
||||
|
||||
// Internally known event parameter values
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogOutcomeValue_Completed;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsDialogOutcomeValue_Failed;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeButtonImpression;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonImpression;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLikeButtonDidTap;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonDidTap;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesHandlerKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesActionKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesEventKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesParamsKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackCustomKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelTrackSingleCustomKey;
|
||||
FOUNDATION_EXPORT NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey;
|
||||
|
||||
@interface FBSDKAppEvents (Internal)
|
||||
|
||||
@property (nonatomic) UIApplicationState applicationState;
|
||||
|
||||
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||
|
||||
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||
valueToSum:(double)valueToSum
|
||||
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||
|
||||
+ (void)logInternalEvent:(FBSDKAppEventName)eventName
|
||||
valueToSum:(double)valueToSum
|
||||
parameters:(NSDictionary *)parameters
|
||||
isImplicitlyLogged:(BOOL)isImplicitlyLogged;
|
||||
|
||||
+ (void)logInternalEvent:(NSString *)eventName
|
||||
valueToSum:(NSNumber *)valueToSum
|
||||
parameters:(NSDictionary *)parameters
|
||||
isImplicitlyLogged:(BOOL)isImplicitlyLogged
|
||||
accessToken:(FBSDKAccessToken *)accessToken;
|
||||
|
||||
+ (void)logImplicitEvent:(NSString *)eventName
|
||||
valueToSum:(NSNumber *)valueToSum
|
||||
parameters:(NSDictionary *)parameters
|
||||
accessToken:(FBSDKAccessToken *)accessToken;
|
||||
|
||||
- (void)flushForReason:(FBSDKAppEventsFlushReason)flushReason;
|
||||
- (void)startObservingApplicationLifecycleNotifications;
|
||||
|
||||
@end
|
||||
Generated
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAtePublishing.h"
|
||||
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKGraphRequestProviding;
|
||||
@protocol FBSDKSettings;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsAtePublisher)
|
||||
@interface FBSDKAppEventsAtePublisher : NSObject <FBSDKAtePublishing>
|
||||
|
||||
@property (nonatomic, readonly) NSString *appIdentifier;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (nullable instancetype)initWithAppIdentifier:(NSString *)appIdentifier
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
store:(id<FBSDKDataPersisting>)store;
|
||||
|
||||
- (void)publishATE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+121
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsAtePublisher.h"
|
||||
|
||||
#if FBSDK_SWIFT_PACKAGE
|
||||
#import "FBSDKGraphRequestFlags.h"
|
||||
#import "FBSDKGraphRequestHTTPMethod.h"
|
||||
#else
|
||||
#import <FBSDKCoreKit/FBSDKGraphRequestFlags.h>
|
||||
#import <FBSDKCoreKit/FBSDKGraphRequestHTTPMethod.h>
|
||||
#endif
|
||||
|
||||
#import "FBSDKAppEventsDeviceInfo.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKGraphRequestConnecting.h"
|
||||
#import "FBSDKGraphRequestProtocol.h"
|
||||
#import "FBSDKGraphRequestProviding.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKLogger.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
|
||||
@interface FBSDKAppEventsAtePublisher ()
|
||||
|
||||
@property (nullable, nonatomic) id<FBSDKGraphRequestProviding> graphRequestFactory;
|
||||
@property (nullable, nonatomic) id<FBSDKSettings> settings;
|
||||
@property (nullable, nonatomic) id<FBSDKDataPersisting> store;
|
||||
@property (nonatomic) BOOL isProcessing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppEventsAtePublisher
|
||||
|
||||
- (nullable instancetype)initWithAppIdentifier:(NSString *)appIdentifier
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
{
|
||||
if ((self = [self init])) {
|
||||
NSString *identifier = [FBSDKTypeUtility coercedToStringValue:appIdentifier];
|
||||
if (identifier.length == 0) {
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents appID] for [FBSDKAppEvents publishATE:]"];
|
||||
return nil;
|
||||
}
|
||||
_appIdentifier = identifier;
|
||||
_graphRequestFactory = graphRequestFactory;
|
||||
_settings = settings;
|
||||
_store = store;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)publishATE
|
||||
{
|
||||
if (self.isProcessing) {
|
||||
return;
|
||||
}
|
||||
self.isProcessing = YES;
|
||||
NSString *lastATEPingString = [NSString stringWithFormat:@"com.facebook.sdk:lastATEPing%@", self.appIdentifier];
|
||||
id lastPublishDate = [self.store objectForKey:lastATEPingString];
|
||||
if ([lastPublishDate isKindOfClass:[NSDate class]] && [(NSDate *)lastPublishDate timeIntervalSinceNow] * -1 < 24 * 60 * 60) {
|
||||
self.isProcessing = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:@"CUSTOM_APP_EVENTS" forKey:@"event"];
|
||||
|
||||
NSOperatingSystemVersion operatingSystemVersion = [FBSDKInternalUtility.sharedUtility operatingSystemVersion];
|
||||
NSString *osVersion = [NSString stringWithFormat:@"%ti.%ti.%ti",
|
||||
operatingSystemVersion.majorVersion,
|
||||
operatingSystemVersion.minorVersion,
|
||||
operatingSystemVersion.patchVersion];
|
||||
|
||||
NSArray *event = @[
|
||||
@{
|
||||
@"_eventName" : @"fb_mobile_ate_status",
|
||||
@"ate_status" : @(self.settings.advertisingTrackingStatus).stringValue,
|
||||
@"os_version" : osVersion,
|
||||
}
|
||||
];
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:[FBSDKBasicUtility JSONStringForObject:event error:NULL invalidObjectHandler:NULL] forKey:@"custom_events"];
|
||||
|
||||
[FBSDKAppEventsDeviceInfo extendDictionaryWithDeviceInfo:parameters];
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"%@/activities", self.appIdentifier];
|
||||
id<FBSDKGraphRequest> request = [self.graphRequestFactory createGraphRequestWithGraphPath:path
|
||||
parameters:parameters
|
||||
tokenString:nil
|
||||
HTTPMethod:FBSDKHTTPMethodPOST
|
||||
flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||
__block id<FBSDKDataPersisting> weakStore = self.store;
|
||||
[request startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *error) {
|
||||
if (!error) {
|
||||
[weakStore setObject:[NSDate date] forKey:lastATEPingString];
|
||||
}
|
||||
self.isProcessing = NO;
|
||||
}];
|
||||
|
||||
#if FBTEST
|
||||
self.isProcessing = NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsConfiguration.h"
|
||||
#import "FBSDKAppEventsConfigurationProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKAppEventsConfiguration (AppEventsConfigurationProtocol) <FBSDKAppEventsConfiguration>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
#import "FBSDKAdvertisingTrackingStatus.h"
|
||||
#else
|
||||
#import <FBSDKCoreKit/FBSDKAdvertisingTrackingStatus.h>
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsConfiguration)
|
||||
@interface FBSDKAppEventsConfiguration : NSObject<NSCopying, NSObject, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, assign) FBSDKAdvertisingTrackingStatus defaultATEStatus;
|
||||
|
||||
@property (nonatomic, readonly, assign) BOOL advertiserIDCollectionEnabled;
|
||||
|
||||
@property (nonatomic, readonly, assign) BOOL eventCollectionEnabled;
|
||||
|
||||
- (instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
+ (instancetype)defaultConfiguration;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+118
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsConfiguration.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
|
||||
#define FBSDK_APP_EVENTS_CONFIGURATION_DEFAULT_ATE_STATUS_KEY @"default_ate_status"
|
||||
#define FBSDK_APP_EVENTS_CONFIGURATION_ADVERTISER_ID_TRACKING_ENABLED_KEY @"advertiser_id_collection_enabled"
|
||||
#define FBSDK_APP_EVENTS_CONFIGURATION_EVENT_COLLECTION_ENABLED_KEY @"event_collection_enabled"
|
||||
|
||||
@implementation FBSDKAppEventsConfiguration
|
||||
|
||||
- (instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
@try {
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return FBSDKAppEventsConfiguration.defaultConfiguration;
|
||||
}
|
||||
NSDictionary<NSString *, id> *configs = [FBSDKTypeUtility dictionary:dict objectForKey:@"app_events_config" ofType:NSDictionary.class];
|
||||
if (!configs) {
|
||||
return FBSDKAppEventsConfiguration.defaultConfiguration;
|
||||
}
|
||||
NSNumber *defaultATEStatus = [FBSDKTypeUtility numberValue:configs[FBSDK_APP_EVENTS_CONFIGURATION_DEFAULT_ATE_STATUS_KEY]] ?: @(FBSDKAdvertisingTrackingUnspecified);
|
||||
NSNumber *advertiserIDCollectionEnabled = [FBSDKTypeUtility numberValue:configs[FBSDK_APP_EVENTS_CONFIGURATION_ADVERTISER_ID_TRACKING_ENABLED_KEY]] ?: @(YES);
|
||||
NSNumber *eventCollectionEnabled = [FBSDKTypeUtility numberValue:configs[FBSDK_APP_EVENTS_CONFIGURATION_EVENT_COLLECTION_ENABLED_KEY]] ?: @(NO);
|
||||
_defaultATEStatus = [defaultATEStatus integerValue];
|
||||
_advertiserIDCollectionEnabled = [advertiserIDCollectionEnabled boolValue];
|
||||
_eventCollectionEnabled = [eventCollectionEnabled boolValue];
|
||||
} @catch (NSException *exception) {
|
||||
return FBSDKAppEventsConfiguration.defaultConfiguration;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDefaultATEStatus:(FBSDKAdvertisingTrackingStatus)defaultATEStatus
|
||||
advertiserIDCollectionEnabled:(BOOL)advertiserIDCollectionEnabled
|
||||
eventCollectionEnabled:(BOOL)eventCollectionEnabled
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_defaultATEStatus = defaultATEStatus;
|
||||
_advertiserIDCollectionEnabled = advertiserIDCollectionEnabled;
|
||||
_eventCollectionEnabled = eventCollectionEnabled;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultConfiguration
|
||||
{
|
||||
FBSDKAppEventsConfiguration *config = [[FBSDKAppEventsConfiguration alloc] initWithDefaultATEStatus:FBSDKAdvertisingTrackingUnspecified
|
||||
advertiserIDCollectionEnabled:YES
|
||||
eventCollectionEnabled:NO];
|
||||
return config;
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
FBSDKAdvertisingTrackingStatus defaultATEStatus = [decoder decodeIntegerForKey:FBSDK_APP_EVENTS_CONFIGURATION_DEFAULT_ATE_STATUS_KEY];
|
||||
BOOL advertisingIDCollectionEnabled = [decoder decodeBoolForKey:FBSDK_APP_EVENTS_CONFIGURATION_ADVERTISER_ID_TRACKING_ENABLED_KEY];
|
||||
BOOL eventCollectionEnabled = [decoder decodeBoolForKey:FBSDK_APP_EVENTS_CONFIGURATION_EVENT_COLLECTION_ENABLED_KEY];
|
||||
return [[FBSDKAppEventsConfiguration alloc] initWithDefaultATEStatus:defaultATEStatus
|
||||
advertiserIDCollectionEnabled:advertisingIDCollectionEnabled
|
||||
eventCollectionEnabled:eventCollectionEnabled];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeInteger:_defaultATEStatus forKey:FBSDK_APP_EVENTS_CONFIGURATION_DEFAULT_ATE_STATUS_KEY];
|
||||
[encoder encodeBool:_advertiserIDCollectionEnabled forKey:FBSDK_APP_EVENTS_CONFIGURATION_ADVERTISER_ID_TRACKING_ENABLED_KEY];
|
||||
[encoder encodeBool:_eventCollectionEnabled forKey:FBSDK_APP_EVENTS_CONFIGURATION_EVENT_COLLECTION_ENABLED_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Testability
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
- (void)setDefaultATEStatus:(FBSDKAdvertisingTrackingStatus)status
|
||||
{
|
||||
_defaultATEStatus = status;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsConfigurationProviding.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKAppEventsConfigurationManager (AppEventsConfigurationProviding) <FBSDKAppEventsConfigurationProviding>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+46
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsConfiguration.h"
|
||||
|
||||
typedef void (^FBSDKAppEventsConfigurationManagerBlock)(void);
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKSettings;
|
||||
@protocol FBSDKGraphRequestProviding;
|
||||
@protocol FBSDKGraphRequestConnectionProviding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsConfigurationManager)
|
||||
@interface FBSDKAppEventsConfigurationManager : NSObject
|
||||
|
||||
+ (void)configureWithStore:(id<FBSDKDataPersisting>)store
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
graphRequestConnectionFactory:(id<FBSDKGraphRequestConnectionProviding>)graphRequestConnectionFactory
|
||||
NS_SWIFT_NAME(configure(store:settings:graphRequestFactory:graphRequestConnectionFactory:));
|
||||
|
||||
+ (FBSDKAppEventsConfiguration *)cachedAppEventsConfiguration;
|
||||
|
||||
+ (void)loadAppEventsConfigurationWithBlock:(FBSDKAppEventsConfigurationManagerBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+202
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsConfigurationManager.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKGraphRequestConnecting.h"
|
||||
#import "FBSDKGraphRequestConnectionProviding.h"
|
||||
#import "FBSDKGraphRequestProviding.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
|
||||
static NSString *const FBSDKAppEventsConfigurationKey = @"com.facebook.sdk:FBSDKAppEventsConfiguration";
|
||||
static NSString *const FBSDKAppEventsConfigurationTimestampKey = @"com.facebook.sdk:FBSDKAppEventsConfigurationTimestamp";
|
||||
static const NSTimeInterval kTimeout = 4.0;
|
||||
|
||||
@interface FBSDKAppEventsConfigurationManager ()
|
||||
|
||||
@property (nullable, nonatomic) id<FBSDKDataPersisting> store;
|
||||
@property (nullable, nonatomic) id<FBSDKSettings> settings;
|
||||
@property (nullable, nonatomic) id<FBSDKGraphRequestProviding> requestFactory;
|
||||
@property (nullable, nonatomic) id<FBSDKGraphRequestConnectionProviding> connectionFactory;
|
||||
@property (nonnull, nonatomic) FBSDKAppEventsConfiguration *configuration;
|
||||
@property (nonatomic) BOOL isLoadingConfiguration;
|
||||
@property (nonatomic) BOOL hasRequeryFinishedForAppStart;
|
||||
@property (nullable, nonatomic) NSDate *timestamp;
|
||||
@property (nullable, nonatomic) NSMutableArray *completionBlocks;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppEventsConfigurationManager
|
||||
|
||||
static dispatch_once_t sharedConfigurationManagerNonce;
|
||||
|
||||
// Transitional singleton introduced as a way to change the usage semantics
|
||||
// from a type-based interface to an instance-based interface.
|
||||
// The goal of the refactor is to move callsites from:
|
||||
// ClassWithoutUnderlyingInstance -> ClassRelyingOnUnderlyingInstance -> Instance
|
||||
+ (FBSDKAppEventsConfigurationManager *)shared
|
||||
{
|
||||
static id instance;
|
||||
dispatch_once(&sharedConfigurationManagerNonce, ^{
|
||||
instance = [self new];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (void) configureWithStore:(id<FBSDKDataPersisting>)store
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
graphRequestConnectionFactory:(id<FBSDKGraphRequestConnectionProviding>)graphRequestConnectionFactory
|
||||
{
|
||||
[self.shared configureWithStore:store
|
||||
settings:settings
|
||||
graphRequestFactory:graphRequestFactory
|
||||
graphRequestConnectionFactory:graphRequestConnectionFactory];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
- (void) configureWithStore:(id<FBSDKDataPersisting>)store
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
graphRequestConnectionFactory:(id<FBSDKGraphRequestConnectionProviding>)graphRequestConnectionFactory
|
||||
{
|
||||
self.store = store;
|
||||
self.settings = settings;
|
||||
self.requestFactory = graphRequestFactory;
|
||||
self.connectionFactory = graphRequestConnectionFactory;
|
||||
id data = [self.store objectForKey:FBSDKAppEventsConfigurationKey];
|
||||
if ([data isKindOfClass:NSData.class]) {
|
||||
if (@available(iOS 11.0, tvOS 11.0, *)) {
|
||||
self.configuration = [NSKeyedUnarchiver unarchivedObjectOfClass:FBSDKAppEventsConfiguration.class fromData:data error:nil];
|
||||
} else {
|
||||
self.configuration = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
}
|
||||
}
|
||||
if (!self.configuration) {
|
||||
self.configuration = [FBSDKAppEventsConfiguration defaultConfiguration];
|
||||
}
|
||||
self.completionBlocks = [NSMutableArray new];
|
||||
self.timestamp = [self.store objectForKey:FBSDKAppEventsConfigurationTimestampKey];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (FBSDKAppEventsConfiguration *)cachedAppEventsConfiguration
|
||||
{
|
||||
return self.shared.cachedAppEventsConfiguration;
|
||||
}
|
||||
|
||||
- (FBSDKAppEventsConfiguration *)cachedAppEventsConfiguration
|
||||
{
|
||||
return self.configuration;
|
||||
}
|
||||
|
||||
+ (void)loadAppEventsConfigurationWithBlock:(FBSDKAppEventsConfigurationManagerBlock)block
|
||||
{
|
||||
[self.shared loadAppEventsConfigurationWithBlock:block];
|
||||
}
|
||||
|
||||
- (void)loadAppEventsConfigurationWithBlock:(FBSDKAppEventsConfigurationManagerBlock)block
|
||||
{
|
||||
NSString *appID = self.settings.appID;
|
||||
@synchronized(self) {
|
||||
[FBSDKTypeUtility array:self.completionBlocks addObject:block];
|
||||
if (!appID || (self.hasRequeryFinishedForAppStart && [self _isTimestampValid])) {
|
||||
for (FBSDKAppEventsConfigurationManagerBlock completionBlock in self.completionBlocks) {
|
||||
completionBlock();
|
||||
}
|
||||
[self.completionBlocks removeAllObjects];
|
||||
return;
|
||||
}
|
||||
if (self.isLoadingConfiguration) {
|
||||
return;
|
||||
}
|
||||
self.isLoadingConfiguration = true;
|
||||
id<FBSDKGraphRequest> request = [self.requestFactory createGraphRequestWithGraphPath:appID
|
||||
parameters:@{
|
||||
@"fields" : [NSString stringWithFormat:@"app_events_config.os_version(%@)", [UIDevice currentDevice].systemVersion]
|
||||
}];
|
||||
id<FBSDKGraphRequestConnecting> requestConnection = [self.connectionFactory createGraphRequestConnection];
|
||||
requestConnection.timeout = kTimeout;
|
||||
[requestConnection addRequest:request completion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *error) {
|
||||
[self _processResponse:result error:error];
|
||||
}];
|
||||
[requestConnection start];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+ (void)_processResponse:(id)response
|
||||
error:(NSError *)error
|
||||
{
|
||||
[self.shared _processResponse:response error:error];
|
||||
}
|
||||
|
||||
- (void)_processResponse:(id)response
|
||||
error:(NSError *)error
|
||||
{
|
||||
NSDate *date = [NSDate date];
|
||||
@synchronized(self) {
|
||||
self.isLoadingConfiguration = NO;
|
||||
self.hasRequeryFinishedForAppStart = YES;
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
self.configuration = [[FBSDKAppEventsConfiguration alloc] initWithJSON:response];
|
||||
self.timestamp = date;
|
||||
for (FBSDKAppEventsConfigurationManagerBlock completionBlock in self.completionBlocks) {
|
||||
completionBlock();
|
||||
}
|
||||
[self.completionBlocks removeAllObjects];
|
||||
}
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.configuration];
|
||||
[self.store setObject:data forKey:FBSDKAppEventsConfigurationKey];
|
||||
[self.store setObject:date forKey:FBSDKAppEventsConfigurationTimestampKey];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (BOOL)_isTimestampValid
|
||||
{
|
||||
return self.timestamp && [[NSDate date] timeIntervalSinceDate:self.timestamp] < 3600;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
+ (void)reset
|
||||
{
|
||||
[self.shared reset];
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
{
|
||||
// Reset the nonce so that a new instance will be created.
|
||||
if (sharedConfigurationManagerNonce) {
|
||||
sharedConfigurationManagerNonce = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsConfigurationProtocol.h
Generated
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
//typedef NS_ENUM(NSUInteger, FBSDKAdvertisingTrackingStatus);
|
||||
|
||||
NS_SWIFT_NAME(AppEventsConfigurationProtocol)
|
||||
@protocol FBSDKAppEventsConfiguration
|
||||
|
||||
@property (nonatomic, readonly, assign) FBSDKAdvertisingTrackingStatus defaultATEStatus;
|
||||
@property (nonatomic, readonly, assign) BOOL advertiserIDCollectionEnabled;
|
||||
@property (nonatomic, readonly, assign) BOOL eventCollectionEnabled;
|
||||
- (instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict;
|
||||
+ (instancetype)defaultConfiguration;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_SWIFT_NAME(AppEventsConfigurationProvidingBlock)
|
||||
typedef void (^FBSDKAppEventsConfigurationProvidingBlock)(void);
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FBSDKAppEventsConfiguration;
|
||||
|
||||
NS_SWIFT_NAME(AppEventsConfigurationProviding)
|
||||
@protocol FBSDKAppEventsConfigurationProviding
|
||||
|
||||
+ (id<FBSDKAppEventsConfiguration>)cachedAppEventsConfiguration;
|
||||
|
||||
+ (void)loadAppEventsConfigurationWithBlock:(FBSDKAppEventsConfigurationProvidingBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsDeviceInfo)
|
||||
@interface FBSDKAppEventsDeviceInfo : NSObject
|
||||
|
||||
+ (void)extendDictionaryWithDeviceInfo:(NSMutableDictionary *)dictionary;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsDeviceInfo.h"
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/utsname.h>
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
#import <CoreTelephony/CTCarrier.h>
|
||||
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||
#endif
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDynamicFrameworkLoader.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKSettings+Internal.h"
|
||||
|
||||
#define FB_ARRAY_COUNT(x) sizeof(x) / sizeof(x[0])
|
||||
|
||||
static const u_int FB_GROUP1_RECHECK_DURATION = 30 * 60; // seconds
|
||||
|
||||
// Apple reports storage in binary gigabytes (1024^3) in their About menus, etc.
|
||||
static const u_int FB_GIGABYTE = 1024 * 1024 * 1024; // bytes
|
||||
|
||||
@implementation FBSDKAppEventsDeviceInfo
|
||||
{
|
||||
// Ephemeral data, may change during the lifetime of an app. We collect them in different
|
||||
// 'group' frequencies - group1 may gets collected once every 30 minutes.
|
||||
|
||||
// group1
|
||||
NSString *_carrierName;
|
||||
NSString *_timeZoneAbbrev;
|
||||
unsigned long long _remainingDiskSpaceGB;
|
||||
NSString *_timeZoneName;
|
||||
|
||||
// Persistent data, but we maintain it to make rebuilding the device info as fast as possible.
|
||||
NSString *_bundleIdentifier;
|
||||
NSString *_longVersion;
|
||||
NSString *_shortVersion;
|
||||
NSString *_sysVersion;
|
||||
NSString *_machine;
|
||||
NSString *_language;
|
||||
unsigned long long _totalDiskSpaceGB;
|
||||
unsigned long long _coreCount;
|
||||
CGFloat _width;
|
||||
CGFloat _height;
|
||||
CGFloat _density;
|
||||
|
||||
// Other state
|
||||
long _lastGroup1CheckTime;
|
||||
BOOL _isEncodingDirty;
|
||||
NSString *_encodedDeviceInfo;
|
||||
}
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
+ (void)extendDictionaryWithDeviceInfo:(NSMutableDictionary *)dictionary
|
||||
{
|
||||
[FBSDKTypeUtility dictionary:dictionary setObject:[[self sharedDeviceInfo] encodedDeviceInfo] forKey:@"extinfo"];
|
||||
}
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self == [FBSDKAppEventsDeviceInfo class]) {
|
||||
[[self sharedDeviceInfo] _collectPersistentData];
|
||||
}
|
||||
}
|
||||
|
||||
+ (instancetype)sharedDeviceInfo
|
||||
{
|
||||
static FBSDKAppEventsDeviceInfo *_sharedDeviceInfo = nil;
|
||||
if (_sharedDeviceInfo == nil) {
|
||||
_sharedDeviceInfo = [FBSDKAppEventsDeviceInfo new];
|
||||
}
|
||||
return _sharedDeviceInfo;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_isEncodingDirty = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)encodedDeviceInfo
|
||||
{
|
||||
@synchronized(self) {
|
||||
BOOL isGroup1Expired = [self _isGroup1Expired];
|
||||
BOOL isEncodingExpired = isGroup1Expired; // Can || other groups in if we add them
|
||||
|
||||
// As long as group1 hasn't expired, we can just return the last generated value
|
||||
if (_encodedDeviceInfo && !isEncodingExpired) {
|
||||
return _encodedDeviceInfo;
|
||||
}
|
||||
|
||||
if (isGroup1Expired) {
|
||||
[self _collectGroup1Data];
|
||||
}
|
||||
|
||||
if (_isEncodingDirty) {
|
||||
self.encodedDeviceInfo = [self _generateEncoding];
|
||||
_isEncodingDirty = NO;
|
||||
}
|
||||
|
||||
return _encodedDeviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEncodedDeviceInfo:(NSString *)encodedDeviceInfo
|
||||
{
|
||||
@synchronized(self) {
|
||||
if (![_encodedDeviceInfo isEqualToString:encodedDeviceInfo]) {
|
||||
_encodedDeviceInfo = [encodedDeviceInfo copy];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This data need only be collected once.
|
||||
- (void)_collectPersistentData
|
||||
{
|
||||
// Bundle stuff
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
_bundleIdentifier = mainBundle.bundleIdentifier;
|
||||
_longVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
_shortVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
|
||||
// Locale stuff
|
||||
_language = [NSLocale currentLocale].localeIdentifier;
|
||||
|
||||
// Device stuff
|
||||
UIDevice *device = [UIDevice currentDevice];
|
||||
_sysVersion = device.systemVersion;
|
||||
_coreCount = [FBSDKAppEventsDeviceInfo _coreCount];
|
||||
|
||||
UIScreen *sc = [UIScreen mainScreen];
|
||||
CGRect sr = sc.bounds;
|
||||
_width = sr.size.width;
|
||||
_height = sr.size.height;
|
||||
_density = sc.scale;
|
||||
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
_machine = @(systemInfo.machine);
|
||||
|
||||
// Disk space stuff
|
||||
float totalDiskSpace = [FBSDKAppEventsDeviceInfo _getTotalDiskSpace].floatValue;
|
||||
_totalDiskSpaceGB = (unsigned long long)round(totalDiskSpace / FB_GIGABYTE);
|
||||
}
|
||||
|
||||
- (BOOL)_isGroup1Expired
|
||||
{
|
||||
return ([self unixTimeNow] - _lastGroup1CheckTime) > FB_GROUP1_RECHECK_DURATION;
|
||||
}
|
||||
|
||||
// This data is collected only once every GROUP1_RECHECK_DURATION.
|
||||
- (void)_collectGroup1Data
|
||||
{
|
||||
const BOOL shouldUseCachedValues = [FBSDKSettings shouldUseCachedValuesForExpensiveMetadata];
|
||||
|
||||
if (!_carrierName || !shouldUseCachedValues) {
|
||||
NSString *newCarrierName = [FBSDKAppEventsDeviceInfo _getCarrier];
|
||||
if (!_carrierName || ![newCarrierName isEqualToString:_carrierName]) {
|
||||
_carrierName = newCarrierName;
|
||||
_isEncodingDirty = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_timeZoneName || !_timeZoneAbbrev || !shouldUseCachedValues) {
|
||||
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
|
||||
NSString *timeZoneName = timeZone.name;
|
||||
if (!_timeZoneName || ![timeZoneName isEqualToString:_timeZoneName]) {
|
||||
_timeZoneName = timeZoneName;
|
||||
_timeZoneAbbrev = timeZone.abbreviation;
|
||||
_isEncodingDirty = YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Remaining disk space
|
||||
float remainingDiskSpace = [FBSDKAppEventsDeviceInfo _getRemainingDiskSpace].floatValue;
|
||||
unsigned long long newRemainingDiskSpaceGB = (unsigned long long)round(remainingDiskSpace / FB_GIGABYTE);
|
||||
if (_remainingDiskSpaceGB != newRemainingDiskSpaceGB) {
|
||||
_remainingDiskSpaceGB = newRemainingDiskSpaceGB;
|
||||
_isEncodingDirty = YES;
|
||||
}
|
||||
|
||||
_lastGroup1CheckTime = [self unixTimeNow];
|
||||
}
|
||||
|
||||
- (NSString *)_generateEncoding
|
||||
{
|
||||
// Keep a bit of precision on density as it's the most likely to become non-integer.
|
||||
NSString *densityString = _density ? [NSString stringWithFormat:@"%.02f", _density] : @"";
|
||||
|
||||
NSArray *arr = @[
|
||||
@"i2", // version - starts with 'i' for iOS, we'll use 'a' for Android
|
||||
_bundleIdentifier ?: @"",
|
||||
_longVersion ?: @"",
|
||||
_shortVersion ?: @"",
|
||||
_sysVersion ?: @"",
|
||||
_machine ?: @"",
|
||||
_language ?: @"",
|
||||
_timeZoneAbbrev ?: @"",
|
||||
_carrierName ?: @"",
|
||||
_width ? @((unsigned long)_width) : @"",
|
||||
_height ? @((unsigned long)_height) : @"",
|
||||
densityString,
|
||||
@(_coreCount) ?: @"",
|
||||
@(_totalDiskSpaceGB) ?: @"",
|
||||
@(_remainingDiskSpaceGB) ?: @"",
|
||||
_timeZoneName ?: @""
|
||||
];
|
||||
|
||||
return [FBSDKBasicUtility JSONStringForObject:arr error:NULL invalidObjectHandler:NULL];
|
||||
}
|
||||
|
||||
#pragma mark - Helper Methods
|
||||
|
||||
- (NSTimeInterval)unixTimeNow
|
||||
{
|
||||
return round([NSDate date].timeIntervalSince1970);
|
||||
}
|
||||
|
||||
+ (NSNumber *)_getTotalDiskSpace
|
||||
{
|
||||
NSDictionary *attrs = [[NSFileManager new] attributesOfFileSystemForPath:NSHomeDirectory()
|
||||
error:nil];
|
||||
return attrs[NSFileSystemSize];
|
||||
}
|
||||
|
||||
+ (NSNumber *)_getRemainingDiskSpace
|
||||
{
|
||||
NSDictionary *attrs = [[NSFileManager new] attributesOfFileSystemForPath:NSHomeDirectory()
|
||||
error:nil];
|
||||
return attrs[NSFileSystemFreeSize];
|
||||
}
|
||||
|
||||
+ (uint)_coreCount
|
||||
{
|
||||
return [FBSDKAppEventsDeviceInfo _readSysCtlUInt:CTL_HW type:HW_AVAILCPU];
|
||||
}
|
||||
|
||||
+ (uint)_readSysCtlUInt:(int)ctl type:(int)type
|
||||
{
|
||||
int mib[2] = {ctl, type};
|
||||
uint value;
|
||||
size_t size = sizeof value;
|
||||
if (0 != sysctl(mib, FB_ARRAY_COUNT(mib), &value, &size, NULL, 0)) {
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+ (NSString *)_getCarrier
|
||||
{
|
||||
#if TARGET_OS_TV || TARGET_OS_SIMULATOR
|
||||
return @"NoCarrier";
|
||||
#else
|
||||
// Dynamically load class for this so calling app doesn't need to link framework in.
|
||||
CTTelephonyNetworkInfo *networkInfo = [[fbsdkdfl_CTTelephonyNetworkInfoClass() alloc] init];
|
||||
CTCarrier *carrier = networkInfo.subscriberCellularProvider;
|
||||
return carrier.carrierName ?: @"NoCarrier";
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@end
|
||||
Generated
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FBSDKNumberParsing <NSObject>
|
||||
|
||||
- (NSNumber *)parseNumberFrom:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
||||
NS_SWIFT_NAME(AppEventsNumberParser)
|
||||
@interface FBSDKAppEventsNumberParser : NSObject <FBSDKNumberParsing>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithLocale:(NSLocale *)locale;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsNumberParser.h"
|
||||
|
||||
@implementation FBSDKAppEventsNumberParser
|
||||
{
|
||||
NSLocale *_locale;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLocale:(NSLocale *)locale
|
||||
{
|
||||
if ((self = [self init])) {
|
||||
_locale = locale;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSNumber *)parseNumberFrom:(NSString *)string
|
||||
{
|
||||
NSNumber *value = @0;
|
||||
|
||||
NSString *ds = [_locale objectForKey:NSLocaleDecimalSeparator] ?: @".";
|
||||
NSString *gs = [_locale objectForKey:NSLocaleGroupingSeparator] ?: @",";
|
||||
NSString *separators = [ds stringByAppendingString:gs];
|
||||
|
||||
NSString *regex = [NSString stringWithFormat:@"[+-]?([0-9]+[%1$@]?)?[%1$@]?([0-9]+[%1$@]?)+", separators];
|
||||
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex
|
||||
options:0
|
||||
error:nil];
|
||||
NSTextCheckingResult *match = [re firstMatchInString:string
|
||||
options:0
|
||||
range:NSMakeRange(0, string.length)];
|
||||
if (match) {
|
||||
NSString *validText = [string substringWithRange:match.range];
|
||||
NSNumberFormatter *formatter = [NSNumberFormatter new];
|
||||
formatter.locale = _locale;
|
||||
formatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
|
||||
value = [formatter numberFromString:validText];
|
||||
if (nil == value) {
|
||||
value = @(validText.floatValue);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsParameterProcessing)
|
||||
@protocol FBSDKAppEventsParameterProcessing
|
||||
|
||||
- (void)enable;
|
||||
- (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsReporter)
|
||||
@protocol FBSDKAppEventsReporter
|
||||
|
||||
- (void)enable;
|
||||
- (void)recordAndUpdateEvent:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
NS_SWIFT_NAME(recordAndUpdate(event:currency:value:parameters:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FBSDKEventsProcessing.h"
|
||||
|
||||
// this type is not thread safe.
|
||||
NS_SWIFT_NAME(AppEventsState)
|
||||
@interface FBSDKAppEventsState : NSObject<NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, copy) NSArray *events;
|
||||
@property (nonatomic, readonly, assign) NSUInteger numSkipped;
|
||||
@property (nonatomic, readonly, copy) NSString *tokenString;
|
||||
@property (nonatomic, readonly, copy) NSString *appID;
|
||||
@property (nonatomic, readonly, getter=areAllEventsImplicit) BOOL allEventsImplicit;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)initWithToken:(NSString *)tokenString appID:(NSString *)appID NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)addEvent:(NSDictionary *)eventDictionary isImplicit:(BOOL)isImplicit;
|
||||
- (void)addEventsFromAppEventState:(FBSDKAppEventsState *)appEventsState;
|
||||
- (BOOL)isCompatibleWithAppEventsState:(FBSDKAppEventsState *)appEventsState;
|
||||
- (BOOL)isCompatibleWithTokenString:(NSString *)tokenString appID:(NSString *)appID;
|
||||
- (NSString *)JSONStringForEventsIncludingImplicitEvents:(BOOL)includeImplicitEvents;
|
||||
- (NSString *)extractReceiptData;
|
||||
|
||||
+ (void)configureWithEventProcessors:(NSArray<id<FBSDKEventsProcessing>> *)eventProcessors;
|
||||
|
||||
@end
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsState.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
|
||||
#define FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY @"isImplicit"
|
||||
|
||||
#define FBSDK_APPEVENTSSTATE_MAX_EVENTS 1000
|
||||
|
||||
#define FBSDK_APPEVENTSSTATE_APPID_KEY @"appID"
|
||||
#define FBSDK_APPEVENTSSTATE_EVENTS_KEY @"events"
|
||||
#define FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY @"numSkipped"
|
||||
#define FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY @"tokenString"
|
||||
#define FBSDK_APPEVENTSTATE_RECEIPTDATA_KEY @"receipt_data"
|
||||
#define FBSDK_APPEVENTSTATE_RECEIPTID_KEY @"receipt_id"
|
||||
|
||||
static NSArray<id<FBSDKEventsProcessing>> *_eventProcessors;
|
||||
|
||||
@implementation FBSDKAppEventsState
|
||||
{
|
||||
NSMutableArray *_mutableEvents;
|
||||
}
|
||||
|
||||
+ (void)configureWithEventProcessors:(nonnull NSArray<id<FBSDKEventsProcessing>> *)eventProcessors
|
||||
{
|
||||
_eventProcessors = eventProcessors;
|
||||
}
|
||||
|
||||
- (instancetype)initWithToken:(NSString *)tokenString appID:(NSString *)appID
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_tokenString = [tokenString copy];
|
||||
_appID = [appID copy];
|
||||
_mutableEvents = [NSMutableArray array];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
FBSDKAppEventsState *copy = [[FBSDKAppEventsState allocWithZone:zone] initWithToken:_tokenString appID:_appID];
|
||||
if (copy) {
|
||||
[copy->_mutableEvents addObjectsFromArray:_mutableEvents];
|
||||
copy->_numSkipped = _numSkipped;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
NSString *appID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_APPEVENTSSTATE_APPID_KEY];
|
||||
NSString *tokenString = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY];
|
||||
NSArray *events = [FBSDKTypeUtility arrayValue:[decoder decodeObjectOfClasses:
|
||||
[NSSet setWithArray:@[NSArray.class, NSDictionary.class]]
|
||||
forKey:FBSDK_APPEVENTSSTATE_EVENTS_KEY]];
|
||||
NSUInteger numSkipped = [[decoder decodeObjectOfClass:[NSNumber class] forKey:FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY] unsignedIntegerValue];
|
||||
|
||||
if ((self = [self initWithToken:tokenString appID:appID])) {
|
||||
_mutableEvents = [NSMutableArray arrayWithArray:events];
|
||||
_numSkipped = numSkipped;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeObject:_appID forKey:FBSDK_APPEVENTSSTATE_APPID_KEY];
|
||||
[encoder encodeObject:_tokenString forKey:FBSDK_APPEVENTSSTATE_TOKENSTRING_KEY];
|
||||
[encoder encodeObject:@(_numSkipped) forKey:FBSDK_APPEVENTSSTATE_NUMSKIPPED_KEY];
|
||||
[encoder encodeObject:_mutableEvents forKey:FBSDK_APPEVENTSSTATE_EVENTS_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - Implementation
|
||||
|
||||
- (NSArray *)events
|
||||
{
|
||||
return [_mutableEvents copy];
|
||||
}
|
||||
|
||||
- (void)addEventsFromAppEventState:(FBSDKAppEventsState *)appEventsState
|
||||
{
|
||||
NSArray *toAdd = appEventsState->_mutableEvents;
|
||||
NSInteger excess = _mutableEvents.count + toAdd.count - FBSDK_APPEVENTSSTATE_MAX_EVENTS;
|
||||
if (excess > 0) {
|
||||
NSInteger range = FBSDK_APPEVENTSSTATE_MAX_EVENTS - _mutableEvents.count;
|
||||
toAdd = [toAdd subarrayWithRange:NSMakeRange(0, range)];
|
||||
_numSkipped += excess;
|
||||
}
|
||||
|
||||
[_mutableEvents addObjectsFromArray:toAdd];
|
||||
}
|
||||
|
||||
- (void)addEvent:(NSDictionary *)eventDictionary
|
||||
isImplicit:(BOOL)isImplicit
|
||||
{
|
||||
if (_mutableEvents.count >= FBSDK_APPEVENTSSTATE_MAX_EVENTS) {
|
||||
_numSkipped++;
|
||||
} else {
|
||||
[FBSDKTypeUtility array:_mutableEvents addObject:@{
|
||||
@"event" : [eventDictionary mutableCopy],
|
||||
FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY : @(isImplicit)
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)extractReceiptData
|
||||
{
|
||||
NSMutableString *receipts_string = [NSMutableString string];
|
||||
NSInteger transactionId = 1;
|
||||
for (NSMutableDictionary *events in _mutableEvents) {
|
||||
NSMutableDictionary *event = events[@"event"];
|
||||
|
||||
NSString *receipt = event[@"receipt_data"];
|
||||
// Add receipt id as the identifier for receipt data in event parameter.
|
||||
// Receipt data will be sent as post parameter rather than the event parameter
|
||||
if (receipt) {
|
||||
NSString *idKey = [NSString stringWithFormat:@"receipt_%ld", (long)transactionId];
|
||||
[FBSDKTypeUtility dictionary:event setObject:idKey forKey:FBSDK_APPEVENTSTATE_RECEIPTID_KEY];
|
||||
NSString *receiptWithId = [NSString stringWithFormat:@"%@::%@;;;", idKey, receipt];
|
||||
[receipts_string appendString:receiptWithId];
|
||||
transactionId++;
|
||||
}
|
||||
}
|
||||
return receipts_string;
|
||||
}
|
||||
|
||||
- (BOOL)areAllEventsImplicit
|
||||
{
|
||||
for (NSDictionary *event in _mutableEvents) {
|
||||
if (![[event valueForKey:FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY] boolValue]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isCompatibleWithAppEventsState:(FBSDKAppEventsState *)appEventsState
|
||||
{
|
||||
return ([self isCompatibleWithTokenString:appEventsState.tokenString appID:appEventsState.appID]);
|
||||
}
|
||||
|
||||
- (BOOL)isCompatibleWithTokenString:(NSString *)tokenString appID:(NSString *)appID
|
||||
{
|
||||
// token strings can be nil (e.g., no user token) but appIDs should not.
|
||||
BOOL tokenCompatible = ([self.tokenString isEqualToString:tokenString]
|
||||
|| (self.tokenString == nil && tokenString == nil));
|
||||
return (tokenCompatible
|
||||
&& [self.appID isEqualToString:appID]);
|
||||
}
|
||||
|
||||
- (NSString *)JSONStringForEventsIncludingImplicitEvents:(BOOL)includeImplicitEvents
|
||||
{
|
||||
if (_eventProcessors != nil) {
|
||||
for (id<FBSDKEventsProcessing> processor in _eventProcessors) {
|
||||
[processor processEvents:_mutableEvents];
|
||||
}
|
||||
}
|
||||
NSMutableArray *events = [[NSMutableArray alloc] initWithCapacity:_mutableEvents.count];
|
||||
for (NSDictionary *eventAndImplicitFlag in _mutableEvents) {
|
||||
const BOOL isImplicitEvent = [eventAndImplicitFlag[FBSDK_APPEVENTSTATE_ISIMPLICIT_KEY] boolValue];
|
||||
if (!includeImplicitEvents && isImplicitEvent) {
|
||||
continue;
|
||||
}
|
||||
NSMutableDictionary *event = eventAndImplicitFlag[@"event"];
|
||||
NSAssert(event != nil, @"event cannot be nil");
|
||||
[event removeObjectForKey:FBSDK_APPEVENTSTATE_RECEIPTDATA_KEY];
|
||||
|
||||
[FBSDKTypeUtility array:events addObject:event];
|
||||
}
|
||||
|
||||
return [FBSDKBasicUtility JSONStringForObject:events error:NULL invalidObjectHandler:NULL];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#if FBTEST
|
||||
+ (NSArray<id<FBSDKEventsProcessing>> *)eventProcessors
|
||||
{
|
||||
return _eventProcessors;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
Generated
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FBSDKAppEventsStateProviding.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppEventsStateFactory)
|
||||
@interface FBSDKAppEventsStateFactory : NSObject<FBSDKAppEventsStateProviding>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsStateFactory.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsState.h"
|
||||
|
||||
@implementation FBSDKAppEventsStateFactory
|
||||
|
||||
- (FBSDKAppEventsState *)createStateWithToken:(NSString *)tokenString appID:(NSString *)appID
|
||||
{
|
||||
return [[FBSDKAppEventsState alloc] initWithToken:tokenString appID:appID];
|
||||
}
|
||||
|
||||
@end
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsStateManager.h"
|
||||
#import "FBSDKAppEventsStatePersisting.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKAppEventsStateManager (AppEventsStatePersisting) <FBSDKAppEventsStatePersisting>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FBSDKAppEventsState;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
NS_SWIFT_NAME(AppEventsStateManager)
|
||||
@interface FBSDKAppEventsStateManager : NSObject
|
||||
@property (class, readonly, nonatomic) FBSDKAppEventsStateManager* shared;
|
||||
|
||||
- (void)clearPersistedAppEventsStates;
|
||||
|
||||
// reads all saved event states, appends the param, and writes them all.
|
||||
- (void)persistAppEventsData:(FBSDKAppEventsState *)appEventsState;
|
||||
|
||||
// returns the array of saved app event states and deletes them.
|
||||
- (NSArray *)retrievePersistedAppEventsStates;
|
||||
|
||||
|
||||
@end
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+128
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsStateManager.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppEventsState.h"
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKLogger.h"
|
||||
#import "FBSDKSettings.h"
|
||||
#import "FBSDKUnarchiverProvider.h"
|
||||
|
||||
@interface FBSDKAppEventsStateManager (Internal)
|
||||
// A quick optimization to allow returning empty array if we know there are no persisted events.
|
||||
@property (nonatomic, readwrite, assign) BOOL canSkipDiskCheck;
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppEventsStateManager
|
||||
{
|
||||
BOOL _canSkipDiskCheck;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self.canSkipDiskCheck = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setCanSkipDiskCheck:(BOOL)canSkipDiskCheck
|
||||
{
|
||||
_canSkipDiskCheck = canSkipDiskCheck;
|
||||
}
|
||||
|
||||
- (BOOL)canSkipDiskCheck
|
||||
{
|
||||
return _canSkipDiskCheck;
|
||||
}
|
||||
|
||||
+ (FBSDKAppEventsStateManager *)shared
|
||||
{
|
||||
static dispatch_once_t nonce;
|
||||
static FBSDKAppEventsStateManager *instance = nil;
|
||||
|
||||
dispatch_once(&nonce, ^{
|
||||
instance = [FBSDKAppEventsStateManager new];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (void)clearPersistedAppEventsStates
|
||||
{
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||
logEntry:@"FBSDKAppEvents Persist: Clearing"];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[self filePath]
|
||||
error:NULL];
|
||||
self.canSkipDiskCheck = YES;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
- (void)persistAppEventsData:(FBSDKAppEventsState *)appEventsState
|
||||
{
|
||||
NSString *msg = [NSString stringWithFormat:@"FBSDKAppEvents Persist: Writing %lu events", (unsigned long)appEventsState.events.count];
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||
logEntry:msg];
|
||||
|
||||
if (!appEventsState.events.count) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray *existingEvents = [NSMutableArray arrayWithArray:[self retrievePersistedAppEventsStates]];
|
||||
[FBSDKTypeUtility array:existingEvents addObject:appEventsState];
|
||||
|
||||
[NSKeyedArchiver archiveRootObject:existingEvents toFile:[self filePath]];
|
||||
self.canSkipDiskCheck = NO;
|
||||
}
|
||||
|
||||
- (NSArray *)retrievePersistedAppEventsStates
|
||||
{
|
||||
NSMutableArray *eventsStates = [NSMutableArray array];
|
||||
if (!self.canSkipDiskCheck) {
|
||||
NSData *data = [[NSData alloc] initWithContentsOfFile:[self filePath] options:NSDataReadingMappedIfSafe error:NULL];
|
||||
id<FBSDKObjectDecoding> unarchiver = [FBSDKUnarchiverProvider createSecureUnarchiverFor:data];
|
||||
@try {
|
||||
NSArray<FBSDKAppEventsState *> *retrievedEvents = [unarchiver decodeObjectOfClasses:
|
||||
[NSSet setWithObjects:NSArray.class, FBSDKAppEventsState.class, NSDictionary.class, nil]
|
||||
forKey:NSKeyedArchiveRootObjectKey];
|
||||
[eventsStates addObjectsFromArray:[FBSDKTypeUtility arrayValue:retrievedEvents]];
|
||||
} @catch (NSException *ex) {
|
||||
// ignore decoding exceptions from previous versions of the archive, etc
|
||||
}
|
||||
|
||||
NSString *msg = [NSString stringWithFormat:@"FBSDKAppEvents Persist: Read %lu event states. First state has %lu events",
|
||||
(unsigned long)eventsStates.count,
|
||||
(unsigned long)(eventsStates.count > 0 ? ((FBSDKAppEventsState *)[FBSDKTypeUtility array:eventsStates objectAtIndex:0]).events.count : 0)];
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||
logEntry:msg];
|
||||
[self clearPersistedAppEventsStates];
|
||||
}
|
||||
return eventsStates;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#pragma mark - Private Helpers
|
||||
|
||||
- (NSString *)filePath
|
||||
{
|
||||
return [FBSDKBasicUtility persistenceFilePath:@"com-facebook-sdk-AppEventsPersistedEvents.json"];
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FBSDKAppEventsState;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
NS_SWIFT_NAME(AppEventsStatePersisting)
|
||||
@protocol FBSDKAppEventsStatePersisting
|
||||
|
||||
- (void)clearPersistedAppEventsStates;
|
||||
- (void)persistAppEventsData:(FBSDKAppEventsState *)appEventsState;
|
||||
- (NSArray *)retrievePersistedAppEventsStates;
|
||||
|
||||
@end
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FBSDKAppEventsState;
|
||||
|
||||
NS_SWIFT_NAME(AppEventsStateProviding)
|
||||
@protocol FBSDKAppEventsStateProviding
|
||||
|
||||
- (FBSDKAppEventsState*) createStateWithToken:(NSString *)tokenString appID:(NSString *)appID NS_SWIFT_NAME(createState(tokenString:appID:));
|
||||
|
||||
@end
|
||||
+490
@@ -0,0 +1,490 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsUtility.h"
|
||||
|
||||
#import <AdSupport/AdSupport.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "FBSDKAccessToken.h"
|
||||
#import "FBSDKAppEvents.h"
|
||||
#import "FBSDKAppEventsConfiguration.h"
|
||||
#import "FBSDKAppEventsConfigurationManager.h"
|
||||
#import "FBSDKAppEventsDeviceInfo.h"
|
||||
#import "FBSDKConstants.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDynamicFrameworkLoader.h"
|
||||
#import "FBSDKError+Internal.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKLogger.h"
|
||||
#import "FBSDKSettings.h"
|
||||
#import "FBSDKSettings+Internal.h"
|
||||
|
||||
#define FBSDK_APPEVENTSUTILITY_ANONYMOUSIDFILENAME @"com-facebook-sdk-PersistedAnonymousID.json"
|
||||
#define FBSDK_APPEVENTSUTILITY_ANONYMOUSID_KEY @"anon_id"
|
||||
#define FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH 40
|
||||
|
||||
static NSArray<NSString *> *standardEvents;
|
||||
static ASIdentifierManager *_cachedAdvertiserIdentifierManager;
|
||||
|
||||
@implementation FBSDKAppEventsUtility
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
standardEvents = @[
|
||||
FBSDKAppEventNameCompletedRegistration,
|
||||
FBSDKAppEventNameViewedContent,
|
||||
FBSDKAppEventNameSearched,
|
||||
FBSDKAppEventNameRated,
|
||||
FBSDKAppEventNameCompletedTutorial,
|
||||
FBSDKAppEventNameAddedToCart,
|
||||
FBSDKAppEventNameAddedToWishlist,
|
||||
FBSDKAppEventNameInitiatedCheckout,
|
||||
FBSDKAppEventNameAddedPaymentInfo,
|
||||
FBSDKAppEventNamePurchased,
|
||||
FBSDKAppEventNameAchievedLevel,
|
||||
FBSDKAppEventNameUnlockedAchievement,
|
||||
FBSDKAppEventNameSpentCredits,
|
||||
FBSDKAppEventNameContact,
|
||||
FBSDKAppEventNameCustomizeProduct,
|
||||
FBSDKAppEventNameDonate,
|
||||
FBSDKAppEventNameFindLocation,
|
||||
FBSDKAppEventNameSchedule,
|
||||
FBSDKAppEventNameStartTrial,
|
||||
FBSDKAppEventNameSubmitApplication,
|
||||
FBSDKAppEventNameSubscribe,
|
||||
FBSDKAppEventNameAdImpression,
|
||||
FBSDKAppEventNameAdClick
|
||||
];
|
||||
}
|
||||
|
||||
// Transitional singleton introduced as a way to change the usage semantics
|
||||
// from a type-based interface to an instance-based interface.
|
||||
// The goal is to move from:
|
||||
// ClassWithoutUnderlyingInstance -> ClassRelyingOnUnderlyingInstance -> Instance
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static dispatch_once_t nonce;
|
||||
static id instance;
|
||||
dispatch_once(&nonce, ^{
|
||||
instance = [self new];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (NSMutableDictionary *)activityParametersDictionaryForEvent:(NSString *)eventCategory
|
||||
shouldAccessAdvertisingID:(BOOL)shouldAccessAdvertisingID
|
||||
{
|
||||
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:eventCategory forKey:@"event"];
|
||||
|
||||
if (shouldAccessAdvertisingID) {
|
||||
NSString *advertiserID = [self.shared advertiserID];
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:advertiserID forKey:@"advertiser_id"];
|
||||
}
|
||||
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:[FBSDKBasicUtility anonymousID] forKey:FBSDK_APPEVENTSUTILITY_ANONYMOUSID_KEY];
|
||||
|
||||
FBSDKAdvertisingTrackingStatus advertisingTrackingStatus = [FBSDKSettings advertisingTrackingStatus];
|
||||
if (advertisingTrackingStatus != FBSDKAdvertisingTrackingUnspecified) {
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:@([FBSDKSettings isAdvertiserTrackingEnabled]).stringValue forKey:@"advertiser_tracking_enabled"];
|
||||
}
|
||||
|
||||
NSString *userData = [FBSDKAppEvents getUserData];
|
||||
if (userData) {
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:userData forKey:@"ud"];
|
||||
}
|
||||
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:@(!FBSDKSettings.limitEventAndDataUsage).stringValue forKey:@"application_tracking_enabled"];
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:@(FBSDKSettings.advertiserIDCollectionEnabled).stringValue forKey:@"advertiser_id_collection_enabled"];
|
||||
|
||||
NSString *userID = [FBSDKAppEvents userID];
|
||||
if (userID) {
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:userID forKey:@"app_user_id"];
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, id> *dataProcessingOptions = [FBSDKSettings dataProcessingOptions];
|
||||
if (dataProcessingOptions) {
|
||||
NSArray<NSString *> *options = (NSArray<NSString *> *)dataProcessingOptions[DATA_PROCESSING_OPTIONS];
|
||||
if (options && [options isKindOfClass:NSArray.class]) {
|
||||
NSString *optionsString = [FBSDKBasicUtility JSONStringForObject:options error:nil invalidObjectHandler:nil];
|
||||
[FBSDKTypeUtility dictionary:parameters
|
||||
setObject:optionsString
|
||||
forKey:DATA_PROCESSING_OPTIONS];
|
||||
}
|
||||
[FBSDKTypeUtility dictionary:parameters
|
||||
setObject:dataProcessingOptions[DATA_PROCESSING_OPTIONS_COUNTRY]
|
||||
forKey:DATA_PROCESSING_OPTIONS_COUNTRY];
|
||||
[FBSDKTypeUtility dictionary:parameters
|
||||
setObject:dataProcessingOptions[DATA_PROCESSING_OPTIONS_STATE]
|
||||
forKey:DATA_PROCESSING_OPTIONS_STATE];
|
||||
}
|
||||
|
||||
[FBSDKAppEventsDeviceInfo extendDictionaryWithDeviceInfo:parameters];
|
||||
|
||||
static dispatch_once_t fetchBundleOnce;
|
||||
static NSMutableArray *urlSchemes;
|
||||
|
||||
dispatch_once(&fetchBundleOnce, ^{
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
urlSchemes = [NSMutableArray new];
|
||||
for (NSDictionary<NSString *, id> *fields in [mainBundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]) {
|
||||
NSArray<NSString *> *schemesForType = fields[@"CFBundleURLSchemes"];
|
||||
if (schemesForType) {
|
||||
[urlSchemes addObjectsFromArray:schemesForType];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (urlSchemes.count > 0) {
|
||||
[FBSDKTypeUtility dictionary:parameters setObject:[FBSDKBasicUtility JSONStringForObject:urlSchemes error:NULL invalidObjectHandler:NULL] forKey:@"url_schemes"];
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
- (NSString *)advertiserID
|
||||
{
|
||||
BOOL shouldUseCachedManagerIfAvailable = [FBSDKSettings shouldUseCachedValuesForExpensiveMetadata];
|
||||
id<FBSDKDynamicFrameworkResolving> dynamicFrameworkResolver = FBSDKDynamicFrameworkLoader.shared;
|
||||
return [self _advertiserIDFromDynamicFrameworkResolver:dynamicFrameworkResolver
|
||||
shouldUseCachedManager:shouldUseCachedManagerIfAvailable];
|
||||
}
|
||||
|
||||
- (NSString *)_advertiserIDFromDynamicFrameworkResolver:(id<FBSDKDynamicFrameworkResolving>)dynamicFrameworkResolver
|
||||
shouldUseCachedManager:(BOOL)shouldUseCachedManager
|
||||
{
|
||||
if (!FBSDKSettings.isAdvertiserIDCollectionEnabled) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (@available(iOS 14.0, *)) {
|
||||
if (![FBSDKAppEventsConfigurationManager cachedAppEventsConfiguration].advertiserIDCollectionEnabled) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
ASIdentifierManager *manager = [self _asIdentifierManagerWithShouldUseCachedManager:shouldUseCachedManager
|
||||
dynamicFrameworkResolver:dynamicFrameworkResolver];
|
||||
return manager.advertisingIdentifier.UUIDString;
|
||||
}
|
||||
|
||||
- (ASIdentifierManager *)_asIdentifierManagerWithShouldUseCachedManager:(BOOL)shouldUseCachedManager
|
||||
dynamicFrameworkResolver:(id<FBSDKDynamicFrameworkResolving>)dynamicFrameworkResolver
|
||||
{
|
||||
if (shouldUseCachedManager && _cachedAdvertiserIdentifierManager) {
|
||||
return _cachedAdvertiserIdentifierManager;
|
||||
}
|
||||
|
||||
Class ASIdentifierManagerClass = [dynamicFrameworkResolver asIdentifierManagerClass];
|
||||
ASIdentifierManager *manager = [ASIdentifierManagerClass sharedManager];
|
||||
if (shouldUseCachedManager) {
|
||||
_cachedAdvertiserIdentifierManager = manager;
|
||||
} else {
|
||||
_cachedAdvertiserIdentifierManager = nil;
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
+ (BOOL)isStandardEvent:(nullable NSString *)event
|
||||
{
|
||||
if (!event) {
|
||||
return NO;
|
||||
}
|
||||
return [standardEvents containsObject:event];
|
||||
}
|
||||
|
||||
#pragma mark - Internal, for testing
|
||||
|
||||
+ (void)clearLibraryFiles
|
||||
{
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[[self class] persistenceFilePath:FBSDK_APPEVENTSUTILITY_ANONYMOUSIDFILENAME]
|
||||
error:NULL];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[[self class] persistenceFilePath:@"com-facebook-sdk-AppEventsTimeSpent.json"]
|
||||
error:NULL];
|
||||
}
|
||||
|
||||
+ (void)ensureOnMainThread:(NSString *)methodName className:(NSString *)className
|
||||
{
|
||||
FBSDKConditionalLog(
|
||||
[NSThread isMainThread],
|
||||
FBSDKLoggingBehaviorDeveloperErrors,
|
||||
@"*** <%@, %@> is not called on the main thread. This can lead to errors.",
|
||||
methodName,
|
||||
className
|
||||
);
|
||||
}
|
||||
|
||||
+ (NSString *)flushReasonToString:(FBSDKAppEventsFlushReason)flushReason
|
||||
{
|
||||
NSString *result = @"Unknown";
|
||||
switch (flushReason) {
|
||||
case FBSDKAppEventsFlushReasonExplicit:
|
||||
result = @"Explicit";
|
||||
break;
|
||||
case FBSDKAppEventsFlushReasonTimer:
|
||||
result = @"Timer";
|
||||
break;
|
||||
case FBSDKAppEventsFlushReasonSessionChange:
|
||||
result = @"SessionChange";
|
||||
break;
|
||||
case FBSDKAppEventsFlushReasonPersistedEvents:
|
||||
result = @"PersistedEvents";
|
||||
break;
|
||||
case FBSDKAppEventsFlushReasonEventThreshold:
|
||||
result = @"EventCountThreshold";
|
||||
break;
|
||||
case FBSDKAppEventsFlushReasonEagerlyFlushingEvent:
|
||||
result = @"EagerlyFlushingEvent";
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (void)logAndNotify:(NSString *)msg
|
||||
{
|
||||
[[self class] logAndNotify:msg allowLogAsDeveloperError:YES];
|
||||
}
|
||||
|
||||
+ (void)logAndNotify:(NSString *)msg allowLogAsDeveloperError:(BOOL)allowLogAsDeveloperError
|
||||
{
|
||||
NSString *behaviorToLog = FBSDKLoggingBehaviorAppEvents;
|
||||
if (allowLogAsDeveloperError) {
|
||||
if ([FBSDKSettings.loggingBehaviors containsObject:FBSDKLoggingBehaviorDeveloperErrors]) {
|
||||
// Rather than log twice, prefer 'DeveloperErrors' if it's set over AppEvents.
|
||||
behaviorToLog = FBSDKLoggingBehaviorDeveloperErrors;
|
||||
}
|
||||
}
|
||||
|
||||
[FBSDKLogger singleShotLogEntry:behaviorToLog logEntry:msg];
|
||||
NSError *error = [FBSDKError errorWithCode:FBSDKErrorAppEventsFlush message:msg];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:FBSDKAppEventsLoggingResultNotification object:error];
|
||||
}
|
||||
|
||||
+ (BOOL) matchString:(NSString *)string
|
||||
firstCharacterSet:(NSCharacterSet *)firstCharacterSet
|
||||
restOfStringCharacterSet:(NSCharacterSet *)restOfStringCharacterSet
|
||||
{
|
||||
if (string.length == 0) {
|
||||
return NO;
|
||||
}
|
||||
for (NSUInteger i = 0; i < string.length; i++) {
|
||||
const unichar c = [string characterAtIndex:i];
|
||||
if (i == 0) {
|
||||
if (![firstCharacterSet characterIsMember:c]) {
|
||||
return NO;
|
||||
}
|
||||
} else {
|
||||
if (![restOfStringCharacterSet characterIsMember:c]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)regexValidateIdentifier:(NSString *)identifier
|
||||
{
|
||||
static NSCharacterSet *firstCharacterSet;
|
||||
static NSCharacterSet *restOfStringCharacterSet;
|
||||
static dispatch_once_t onceToken;
|
||||
static NSMutableSet *cachedIdentifiers;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSMutableCharacterSet *mutableSet = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||
[mutableSet addCharactersInString:@"_"];
|
||||
firstCharacterSet = [mutableSet copy];
|
||||
|
||||
[mutableSet addCharactersInString:@"- "];
|
||||
restOfStringCharacterSet = [mutableSet copy];
|
||||
cachedIdentifiers = [NSMutableSet new];
|
||||
});
|
||||
|
||||
@synchronized(self) {
|
||||
if (![cachedIdentifiers containsObject:identifier]) {
|
||||
if ([self matchString:identifier
|
||||
firstCharacterSet:firstCharacterSet
|
||||
restOfStringCharacterSet:restOfStringCharacterSet]) {
|
||||
[cachedIdentifiers addObject:identifier];
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)validateIdentifier:(NSString *)identifier
|
||||
{
|
||||
if (identifier == nil || identifier.length == 0 || identifier.length > FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH || ![[self class] regexValidateIdentifier:identifier]) {
|
||||
[[self class] logAndNotify:[NSString stringWithFormat:@"Invalid identifier: '%@'. Must be between 1 and %d characters, and must be contain only alphanumerics, _, - or spaces, starting with alphanumeric or _.",
|
||||
identifier, FBSDK_APPEVENTSUTILITY_MAX_IDENTIFIER_LENGTH]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Given a candidate token (which may be nil), find the real token to string to use.
|
||||
// Precedence: 1) provided token, 2) current token, 3) app | client token, 4) fully anonymous session.
|
||||
+ (NSString *)tokenStringToUseFor:(FBSDKAccessToken *)token
|
||||
{
|
||||
if (!token) {
|
||||
token = [FBSDKAccessToken currentAccessToken];
|
||||
}
|
||||
|
||||
NSString *loggingOverrideAppID = [FBSDKAppEvents loggingOverrideAppID];
|
||||
|
||||
NSString *appID = loggingOverrideAppID ?: token.appID ?: [FBSDKSettings appID];
|
||||
NSString *tokenString = token.tokenString;
|
||||
NSString *clientTokenString = [FBSDKSettings clientToken];
|
||||
|
||||
if (![appID isEqualToString:token.appID]) {
|
||||
// If there's a logging override app id present
|
||||
// then we don't want to use the client token since the client token
|
||||
// is intended to match up with the primary app id
|
||||
// and AppEvents doesn't require a client token.
|
||||
if (clientTokenString && loggingOverrideAppID) {
|
||||
tokenString = nil;
|
||||
} else if (clientTokenString && appID && ([appID isEqualToString:token.appID] || token == nil)) {
|
||||
tokenString = [NSString stringWithFormat:@"%@|%@", appID, clientTokenString];
|
||||
} else if (appID) {
|
||||
tokenString = nil;
|
||||
}
|
||||
}
|
||||
return tokenString;
|
||||
}
|
||||
|
||||
+ (NSTimeInterval)unixTimeNow
|
||||
{
|
||||
return round([NSDate date].timeIntervalSince1970);
|
||||
}
|
||||
|
||||
+ (NSTimeInterval)convertToUnixTime:(NSDate *)date
|
||||
{
|
||||
return round([date timeIntervalSince1970]);
|
||||
}
|
||||
|
||||
+ (BOOL)isDebugBuild
|
||||
{
|
||||
#if TARGET_OS_SIMULATOR
|
||||
return YES;
|
||||
#else
|
||||
BOOL isDevelopment = NO;
|
||||
|
||||
// There is no provisioning profile in AppStore Apps.
|
||||
@try {
|
||||
NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]];
|
||||
if (data) {
|
||||
const char *bytes = [data bytes];
|
||||
NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length];
|
||||
for (NSUInteger i = 0; i < data.length; i++) {
|
||||
[profile appendFormat:@"%c", bytes[i]];
|
||||
}
|
||||
// Look for debug value, if detected we're in a development build.
|
||||
NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:@""];
|
||||
isDevelopment = ([cleared rangeOfString:@"<key>get-task-allow</key><true/>"].length > 0);
|
||||
}
|
||||
|
||||
return isDevelopment;
|
||||
} @catch (NSException *exception) {}
|
||||
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (BOOL)shouldDropAppEvent
|
||||
{
|
||||
if (@available(iOS 14.0, *)) {
|
||||
if ([FBSDKSettings advertisingTrackingStatus] == FBSDKAdvertisingTrackingDisallowed && ![FBSDKAppEventsConfigurationManager cachedAppEventsConfiguration].eventCollectionEnabled) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)isSensitiveUserData:(NSString *)text
|
||||
{
|
||||
if (0 == text.length) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isEmailAddress:text] || [self isCreditCardNumber:text];
|
||||
}
|
||||
|
||||
+ (BOOL)isCreditCardNumber:(NSString *)text
|
||||
{
|
||||
text = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet.decimalDigitCharacterSet invertedSet]] componentsJoinedByString:@""];
|
||||
|
||||
if (text.doubleValue == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (text.length < 9 || text.length > 21) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
const char *chars = [text cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
if (NULL == chars) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isOdd = YES;
|
||||
int oddSum = 0;
|
||||
int evenSum = 0;
|
||||
|
||||
for (int i = (int)text.length - 1; i >= 0; i--) {
|
||||
int digit = chars[i] - '0';
|
||||
|
||||
if (isOdd) {
|
||||
oddSum += digit;
|
||||
} else {
|
||||
evenSum += digit / 5 + (2 * digit) % 10;
|
||||
}
|
||||
|
||||
isOdd = !isOdd;
|
||||
}
|
||||
|
||||
return ((oddSum + evenSum) % 10 == 0);
|
||||
}
|
||||
|
||||
+ (BOOL)isEmailAddress:(NSString *)text
|
||||
{
|
||||
NSString *pattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
|
||||
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
NSUInteger matches = [regex numberOfMatchesInString:text options:0 range:NSMakeRange(0, [text length])];
|
||||
return matches > 0;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
+ (ASIdentifierManager *)cachedAdvertiserIdentifierManager
|
||||
{
|
||||
return _cachedAdvertiserIdentifierManager;
|
||||
}
|
||||
|
||||
+ (void)setCachedAdvertiserIdentifierManager:(ASIdentifierManager *)manager
|
||||
{
|
||||
_cachedAdvertiserIdentifierManager = manager;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
Generated
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AppStoreReceiptProviding)
|
||||
@protocol FBSDKAppStoreReceiptProviding
|
||||
|
||||
@property (nullable, readonly, copy) NSURL *appStoreReceiptURL;
|
||||
|
||||
@end
|
||||
|
||||
// Default conformance to the AppStoreReceiptProvider protocol
|
||||
@interface NSBundle () <FBSDKAppStoreReceiptProviding>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol FBSDKAtePublishing;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AtePublisherCreating)
|
||||
@protocol FBSDKAtePublisherCreating
|
||||
|
||||
- (nullable id<FBSDKAtePublishing>)createPublisherWithAppID:(NSString *)appID
|
||||
NS_SWIFT_NAME(createPublisher(appID:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAtePublisherCreating.h"
|
||||
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKGraphRequestProviding;
|
||||
@protocol FBSDKSettings;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AtePublisherFactory)
|
||||
@interface FBSDKAtePublisherFactory : NSObject<FBSDKAtePublisherCreating>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithStore:(id<FBSDKDataPersisting>)store
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
settings:(id<FBSDKSettings>)settings;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAtePublisherFactory.h"
|
||||
|
||||
#import "FBSDKAppEventsAtePublisher.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKAtePublisherFactory ()
|
||||
|
||||
@property (nonnull, nonatomic, readonly) id<FBSDKGraphRequestProviding> graphRequestFactory;
|
||||
@property (nonnull, nonatomic, readonly) id<FBSDKSettings> settings;
|
||||
@property (nonnull, nonatomic, readonly) id<FBSDKDataPersisting> store;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKAtePublisherFactory
|
||||
|
||||
- (instancetype)initWithStore:(id<FBSDKDataPersisting>)store
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_store = store;
|
||||
_graphRequestFactory = graphRequestFactory;
|
||||
_settings = settings;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable id<FBSDKAtePublishing>)createPublisherWithAppID:(NSString *)appID
|
||||
{
|
||||
return [[FBSDKAppEventsAtePublisher alloc] initWithAppIdentifier:appID
|
||||
graphRequestFactory:self.graphRequestFactory
|
||||
settings:self.settings
|
||||
store:self.store];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AtePublishing)
|
||||
@protocol FBSDKAtePublishing <NSObject>
|
||||
|
||||
- (void)publishATE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_SWIFT_NAME(EventsProcessing)
|
||||
@protocol FBSDKEventsProcessing
|
||||
- (void)processEvents:(NSMutableArray<NSDictionary<NSString *, id> *> *)events;
|
||||
@end
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(FeatureExtracting)
|
||||
@protocol FBSDKFeatureExtracting
|
||||
|
||||
+ (nullable float *)getDenseFeatures:(NSDictionary *)viewHierarchy;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(HybridAppEventsScriptMessageHandler)
|
||||
@interface FBSDKHybridAppEventsScriptMessageHandler : NSObject <WKScriptMessageHandler>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKHybridAppEventsScriptMessageHandler.h"
|
||||
|
||||
#import "FBSDKAppEvents+EventLogging.h"
|
||||
#import "FBSDKAppEvents+Internal.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKEventLogging.h"
|
||||
|
||||
NSString *const FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey = @"_fb_pixel_referral_id";
|
||||
|
||||
@protocol FBSDKEventLogging;
|
||||
@class WKUserContentController;
|
||||
|
||||
@interface FBSDKHybridAppEventsScriptMessageHandler ()
|
||||
|
||||
@property (nonatomic) id<FBSDKEventLogging> eventLogger;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKHybridAppEventsScriptMessageHandler
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithEventLogger:FBSDKAppEvents.singleton];
|
||||
}
|
||||
|
||||
- (instancetype)initWithEventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventLogger = eventLogger;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
|
||||
{
|
||||
if ([message.name isEqualToString:FBSDKAppEventsWKWebViewMessagesHandlerKey]) {
|
||||
NSDictionary *body = [FBSDKTypeUtility dictionaryValue:message.body];
|
||||
if (!body) {
|
||||
return;
|
||||
}
|
||||
NSString *event = body[FBSDKAppEventsWKWebViewMessagesEventKey];
|
||||
if ([event isKindOfClass:NSString.class] && (event.length > 0)) {
|
||||
NSString *stringedParams = [FBSDKTypeUtility stringValueOrNil:body[FBSDKAppEventsWKWebViewMessagesParamsKey]];
|
||||
NSMutableDictionary<NSString *, id> *params = nil;
|
||||
NSError *jsonParseError = nil;
|
||||
if (stringedParams) {
|
||||
params = [FBSDKTypeUtility JSONObjectWithData:[stringedParams dataUsingEncoding:NSUTF8StringEncoding]
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:&jsonParseError
|
||||
];
|
||||
}
|
||||
NSString *pixelID = body[FBSDKAppEventsWKWebViewMessagesPixelIDKey];
|
||||
if (pixelID == nil) {
|
||||
[FBSDKAppEventsUtility logAndNotify:@"Can't bridge an event without a referral Pixel ID. Check your webview Pixel configuration."];
|
||||
return;
|
||||
}
|
||||
if (jsonParseError != nil || ![params isKindOfClass:[NSDictionary class]] || params == nil) {
|
||||
[FBSDKAppEventsUtility logAndNotify:@"Could not find parameters for your Pixel request. Check your webview Pixel configuration."];
|
||||
params = [[NSMutableDictionary alloc] initWithObjectsAndKeys:pixelID, FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey, nil];
|
||||
} else {
|
||||
[FBSDKTypeUtility dictionary:params setObject:pixelID forKey:FBSDKAppEventsWKWebViewMessagesPixelReferralParamKey];
|
||||
}
|
||||
[self.eventLogger logInternalEvent:event
|
||||
parameters:params
|
||||
isImplicitlyLogged:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKPaymentObserver.h"
|
||||
#import "FBSDKPaymentObserving.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKPaymentObserver (PaymentObservingProtocol) <FBSDKPaymentObserving>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Class to encapsulate implicit logging of purchase events
|
||||
NS_SWIFT_NAME(PaymentObserver)
|
||||
@interface FBSDKPaymentObserver : NSObject
|
||||
|
||||
@property (class, readonly) FBSDKPaymentObserver *shared;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (void)startObservingTransactions;
|
||||
- (void)stopObservingTransactions;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKPaymentObserver.h"
|
||||
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
#import "FBSDKCoreKit+Internal.h"
|
||||
#import "FBSDKPaymentProductRequestor.h"
|
||||
#import "FBSDKPaymentProductRequestorCreating.h"
|
||||
#import "FBSDKPaymentProductRequestorFactory.h"
|
||||
|
||||
@interface FBSDKPaymentObserver () <SKPaymentTransactionObserver>
|
||||
|
||||
@property (nonatomic, readonly) SKPaymentQueue *paymentQueue;
|
||||
@property (nonatomic, readonly) id<FBSDKPaymentProductRequestorCreating> requestorFactory;
|
||||
@property (nonatomic) BOOL isObservingTransactions;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKPaymentObserver
|
||||
|
||||
- (instancetype)initWithPaymentQueue:(SKPaymentQueue *)paymentQueue
|
||||
paymentProductRequestorFactory:(id<FBSDKPaymentProductRequestorCreating>)paymentProductRequestorFactory
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_paymentQueue = paymentQueue;
|
||||
_requestorFactory = paymentProductRequestorFactory;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
+ (FBSDKPaymentObserver *)shared
|
||||
{
|
||||
static FBSDKPaymentObserver *shared = nil;
|
||||
static dispatch_once_t nonce;
|
||||
dispatch_once(&nonce, ^{
|
||||
shared = [[FBSDKPaymentObserver alloc] initWithPaymentQueue:SKPaymentQueue.defaultQueue
|
||||
paymentProductRequestorFactory:[FBSDKPaymentProductRequestorFactory new]];
|
||||
});
|
||||
return shared;
|
||||
}
|
||||
|
||||
- (void)startObservingTransactions
|
||||
{
|
||||
@synchronized(self) {
|
||||
if (!self.isObservingTransactions) {
|
||||
[self.paymentQueue addTransactionObserver:self];
|
||||
self.isObservingTransactions = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopObservingTransactions
|
||||
{
|
||||
@synchronized(self) {
|
||||
if (self.isObservingTransactions) {
|
||||
[self.paymentQueue removeTransactionObserver:self];
|
||||
self.isObservingTransactions = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) paymentQueue:(SKPaymentQueue *)queue
|
||||
updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
|
||||
{
|
||||
for (SKPaymentTransaction *transaction in transactions) {
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchasing:
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
case SKPaymentTransactionStateFailed:
|
||||
case SKPaymentTransactionStateRestored:
|
||||
[self handleTransaction:transaction];
|
||||
break;
|
||||
case SKPaymentTransactionStateDeferred:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTransaction:(SKPaymentTransaction *)transaction
|
||||
{
|
||||
FBSDKPaymentProductRequestor *productRequestor = [self.requestorFactory createRequestorWithTransaction:transaction];
|
||||
[productRequestor resolveProducts];
|
||||
}
|
||||
|
||||
@end
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Protocol of the class to encapsulate implicit logging of purchase events
|
||||
NS_SWIFT_NAME(PaymentObserving)
|
||||
@protocol FBSDKPaymentObserving
|
||||
- (void)startObservingTransactions;
|
||||
- (void)stopObservingTransactions;
|
||||
@end
|
||||
Generated
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
@protocol FBSDKSettings;
|
||||
@protocol FBSDKEventLogging;
|
||||
@protocol FBSDKGateKeeperManaging;
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKLoggingCreating;
|
||||
@protocol FBSDKProductsRequestCreating;
|
||||
@protocol FBSDKAppStoreReceiptProviding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Used for requesting information about purchase events from StoreKit to use when
|
||||
logging AppEvents
|
||||
*/
|
||||
NS_SWIFT_NAME(PaymentProductRequestor)
|
||||
@interface FBSDKPaymentProductRequestor : NSObject <SKProductsRequestDelegate>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithTransaction:(SKPaymentTransaction *)transaction
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
gateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
loggerFactory:(id<FBSDKLoggingCreating>)loggerFactory
|
||||
productsRequestFactory:(id<FBSDKProductsRequestCreating>)productRequestFactory
|
||||
appStoreReceiptProvider:(id<FBSDKAppStoreReceiptProviding>)receiptProvider;
|
||||
|
||||
- (void)resolveProducts;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+463
@@ -0,0 +1,463 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKPaymentProductRequestor.h"
|
||||
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
#import "FBSDKAppEventName.h"
|
||||
#import "FBSDKAppEventParameterName.h"
|
||||
#import "FBSDKAppEventsFlushReason.h"
|
||||
#import "FBSDKAppStoreReceiptProviding.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKEventLogging.h"
|
||||
#import "FBSDKGateKeeperManaging.h"
|
||||
#import "FBSDKLoggingCreating.h"
|
||||
#import "FBSDKProductsRequestProtocols.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
|
||||
static NSString *const FBSDKPaymentObserverOriginalTransactionKey = @"com.facebook.appevents.PaymentObserver.originalTransaction";
|
||||
static NSString *const FBSDKPaymentObserverDelimiter = @",";
|
||||
|
||||
static NSString *const FBSDKAppEventParameterImplicitlyLoggedPurchase = @"_implicitlyLogged";
|
||||
static NSString *const FBSDKAppEventNamePurchaseFailed = @"fb_mobile_purchase_failed";
|
||||
static NSString *const FBSDKAppEventNamePurchaseRestored = @"fb_mobile_purchase_restored";
|
||||
static NSString *const FBSDKAppEventParameterNameInAppPurchaseType = @"fb_iap_product_type";
|
||||
static NSString *const FBSDKAppEventParameterNameProductTitle = @"fb_content_title";
|
||||
static NSString *const FBSDKAppEventParameterNameOriginalTransactionID = @"fb_original_transaction_id";
|
||||
static NSString *const FBSDKAppEventParameterNameTransactionID = @"fb_transaction_id";
|
||||
static NSString *const FBSDKAppEventParameterNameTransactionDate = @"fb_transaction_date";
|
||||
static NSString *const FBSDKAppEventParameterNameSubscriptionPeriod = @"fb_iap_subs_period";
|
||||
static NSString *const FBSDKAppEventParameterNameIsStartTrial = @"fb_iap_is_start_trial";
|
||||
static NSString *const FBSDKAppEventParameterNameHasFreeTrial = @"fb_iap_has_free_trial";
|
||||
static NSString *const FBSDKAppEventParameterNameTrialPeriod = @"fb_iap_trial_period";
|
||||
static NSString *const FBSDKAppEventParameterNameTrialPrice = @"fb_iap_trial_price";
|
||||
|
||||
static NSString *const FBSDKGateKeeperAppEventsIfAutoLogSubs = @"app_events_if_auto_log_subs";
|
||||
static int const FBSDKMaxParameterValueLength = 100;
|
||||
|
||||
@interface FBSDKPaymentProductRequestor ()
|
||||
|
||||
@property (class, nonatomic, readonly) NSMutableArray *pendingRequestors;
|
||||
@property (nonatomic, retain) SKPaymentTransaction *transaction;
|
||||
@property (nonatomic, readonly) id<FBSDKAppStoreReceiptProviding> appStoreReceiptProvider;
|
||||
@property (nonatomic, retain) id<FBSDKProductsRequest> productsRequest;
|
||||
@property (nonatomic, readonly) id<FBSDKProductsRequestCreating> productRequestFactory;
|
||||
@property (nonatomic, readonly) id<FBSDKSettings> settings;
|
||||
@property (nonatomic, readonly) id<FBSDKEventLogging> eventLogger;
|
||||
@property (nonatomic, readonly) Class<FBSDKGateKeeperManaging> gateKeeperManager;
|
||||
@property (nonatomic, readonly) id<FBSDKDataPersisting> store;
|
||||
@property (nonatomic, readonly) id<FBSDKLoggingCreating> loggerFactory;
|
||||
@property (nonatomic) NSMutableSet<NSString *> *originalTransactionSet;
|
||||
@property (nonatomic) NSSet<NSString *> *eventsWithReceipt;
|
||||
@property (nonatomic, readonly) NSDateFormatter *formatter;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKPaymentProductRequestor
|
||||
|
||||
static NSMutableArray *_pendingRequestors;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if ([self class] == [FBSDKPaymentProductRequestor class]) {
|
||||
_pendingRequestors = [NSMutableArray new];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithTransaction:(SKPaymentTransaction *)transaction
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
gateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
loggerFactory:(id<FBSDKLoggingCreating>)loggerFactory
|
||||
productsRequestFactory:(id<FBSDKProductsRequestCreating>)productRequestFactory
|
||||
appStoreReceiptProvider:(id<FBSDKAppStoreReceiptProviding>)receiptProvider
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_settings = settings;
|
||||
_eventLogger = eventLogger;
|
||||
_gateKeeperManager = gateKeeperManager;
|
||||
_store = store;
|
||||
_loggerFactory = loggerFactory;
|
||||
_productRequestFactory = productRequestFactory;
|
||||
_appStoreReceiptProvider = receiptProvider;
|
||||
_transaction = transaction;
|
||||
_formatter = [NSDateFormatter new];
|
||||
_formatter.dateFormat = @"yyyy-MM-dd HH:mm:ssZ";
|
||||
NSString *data = [_store stringForKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||
_eventsWithReceipt = [NSSet setWithArray:@[FBSDKAppEventNamePurchased, FBSDKAppEventNameSubscribe,
|
||||
FBSDKAppEventNameStartTrial]];
|
||||
if (data) {
|
||||
_originalTransactionSet = [NSMutableSet setWithArray:[data componentsSeparatedByString:FBSDKPaymentObserverDelimiter]];
|
||||
} else {
|
||||
_originalTransactionSet = [NSMutableSet new];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)pendingRequestors
|
||||
{
|
||||
return _pendingRequestors;
|
||||
}
|
||||
|
||||
- (void)setProductsRequest:(id<FBSDKProductsRequest>)productsRequest
|
||||
{
|
||||
if (productsRequest != _productsRequest) {
|
||||
if (_productsRequest) {
|
||||
_productsRequest.delegate = nil;
|
||||
}
|
||||
_productsRequest = productsRequest;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resolveProducts
|
||||
{
|
||||
NSString *productId = self.transaction.payment.productIdentifier;
|
||||
NSSet *productIdentifiers = [NSSet setWithObjects:productId, nil];
|
||||
self.productsRequest = [self.productRequestFactory createWithProductIdentifiers:productIdentifiers];
|
||||
self.productsRequest.delegate = self;
|
||||
@synchronized(self.class.pendingRequestors) {
|
||||
[FBSDKTypeUtility array:self.class.pendingRequestors addObject:self];
|
||||
}
|
||||
[self.productsRequest start];
|
||||
}
|
||||
|
||||
- (NSString *)getTruncatedString:(NSString *)inputString
|
||||
{
|
||||
if (!inputString) {
|
||||
return @"";
|
||||
}
|
||||
|
||||
return inputString.length <= FBSDKMaxParameterValueLength ? inputString : [inputString substringToIndex:FBSDKMaxParameterValueLength];
|
||||
}
|
||||
|
||||
- (void)logTransactionEvent:(SKProduct *)product
|
||||
{
|
||||
if ([self isSubscription:product]
|
||||
&& [self.gateKeeperManager boolForKey:FBSDKGateKeeperAppEventsIfAutoLogSubs
|
||||
defaultValue:NO]) {
|
||||
[self logImplicitSubscribeTransaction:self.transaction ofProduct:product];
|
||||
} else {
|
||||
[self logImplicitPurchaseTransaction:self.transaction ofProduct:product];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isSubscription:(SKProduct *)product
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||
if (@available(iOS 11.2, *)) {
|
||||
return (product.subscriptionPeriod != nil) && ((unsigned long)product.subscriptionPeriod.numberOfUnits > 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary<NSString *, id> *)getEventParametersOfProduct:(SKProduct *)product
|
||||
withTransaction:(SKPaymentTransaction *)transaction
|
||||
{
|
||||
NSString *transactionID = nil;
|
||||
NSString *transactionDate = nil;
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchasing:
|
||||
break;
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
transactionID = transaction.transactionIdentifier;
|
||||
transactionDate = [_formatter stringFromDate:transaction.transactionDate];
|
||||
break;
|
||||
case SKPaymentTransactionStateFailed:
|
||||
break;
|
||||
case SKPaymentTransactionStateRestored:
|
||||
transactionDate = [_formatter stringFromDate:transaction.transactionDate];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
SKPayment *payment = transaction.payment;
|
||||
NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
FBSDKAppEventParameterNameContentID : payment.productIdentifier ?: @"",
|
||||
FBSDKAppEventParameterNameNumItems : @(payment.quantity),
|
||||
FBSDKAppEventParameterNameTransactionDate : transactionDate ?: @"",
|
||||
}];
|
||||
if (product) {
|
||||
[eventParameters addEntriesFromDictionary:@{
|
||||
FBSDKAppEventParameterNameNumItems : @(payment.quantity),
|
||||
FBSDKAppEventParameterNameProductTitle : [self getTruncatedString:product.localizedTitle],
|
||||
FBSDKAppEventParameterNameDescription : [self getTruncatedString:product.localizedDescription],
|
||||
}];
|
||||
if (@available(iOS 10.0, *)) {
|
||||
[FBSDKTypeUtility dictionary:eventParameters
|
||||
setObject:product.priceLocale.currencyCode
|
||||
forKey:FBSDKAppEventParameterNameCurrency];
|
||||
}
|
||||
if (transactionID) {
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:transactionID forKey:FBSDKAppEventParameterNameTransactionID];
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||
if (@available(iOS 11.2, *)) {
|
||||
if ([self isSubscription:product]) {
|
||||
// subs inapp
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:product.subscriptionPeriod] forKey:FBSDKAppEventParameterNameSubscriptionPeriod];
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:@"subs" forKey:FBSDKAppEventParameterNameInAppPurchaseType];
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:[self isStartTrial:transaction ofProduct:product] ? @"1" : @"0" forKey:FBSDKAppEventParameterNameIsStartTrial];
|
||||
// trial information for subs
|
||||
SKProductDiscount *discount = product.introductoryPrice;
|
||||
if (discount) {
|
||||
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial) {
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:@"1" forKey:FBSDKAppEventParameterNameHasFreeTrial];
|
||||
} else {
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:@"0" forKey:FBSDKAppEventParameterNameHasFreeTrial];
|
||||
}
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:discount.subscriptionPeriod] forKey:FBSDKAppEventParameterNameTrialPeriod];
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:discount.price forKey:FBSDKAppEventParameterNameTrialPrice];
|
||||
}
|
||||
} else {
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:@"inapp" forKey:FBSDKAppEventParameterNameInAppPurchaseType];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return eventParameters;
|
||||
}
|
||||
|
||||
- (void)appendOriginalTransactionID:(NSString *)transactionID
|
||||
{
|
||||
if (!transactionID) {
|
||||
return;
|
||||
}
|
||||
[self.originalTransactionSet addObject:transactionID];
|
||||
[self.store setObject:[[self.originalTransactionSet allObjects] componentsJoinedByString:FBSDKPaymentObserverDelimiter]
|
||||
forKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||
}
|
||||
|
||||
- (void)clearOriginalTransactionID:(NSString *)transactionID
|
||||
{
|
||||
if (!transactionID) {
|
||||
return;
|
||||
}
|
||||
[self.originalTransactionSet removeObject:transactionID];
|
||||
[self.store setObject:[[self.originalTransactionSet allObjects] componentsJoinedByString:FBSDKPaymentObserverDelimiter]
|
||||
forKey:FBSDKPaymentObserverOriginalTransactionKey];
|
||||
}
|
||||
|
||||
- (BOOL)isStartTrial:(SKPaymentTransaction *)transaction
|
||||
ofProduct:(SKProduct *)product
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_4
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_12_1
|
||||
// promotional offer starting from iOS 12.2
|
||||
if (@available(iOS 12.2, *)) {
|
||||
SKPaymentDiscount *paymentDiscount = transaction.payment.paymentDiscount;
|
||||
if (paymentDiscount) {
|
||||
NSArray<SKProductDiscount *> *discounts = product.discounts;
|
||||
for (SKProductDiscount *discount in discounts) {
|
||||
if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial
|
||||
&& [paymentDiscount.identifier isEqualToString:discount.identifier]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
// introductory offer starting from iOS 11.2
|
||||
if (@available(iOS 11.2, *)) {
|
||||
if (product.introductoryPrice
|
||||
&& product.introductoryPrice.paymentMode == SKProductDiscountPaymentModeFreeTrial) {
|
||||
NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier;
|
||||
// only consider the very first trial transaction as start trial
|
||||
if (!originalTransactionID) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *)durationOfSubscriptionPeriod:(id)subcriptionPeriod
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_11_1
|
||||
if (@available(iOS 11.2, *)) {
|
||||
if (subcriptionPeriod && [subcriptionPeriod isKindOfClass:[SKProductSubscriptionPeriod class]]) {
|
||||
SKProductSubscriptionPeriod *period = (SKProductSubscriptionPeriod *)subcriptionPeriod;
|
||||
NSString *unit = nil;
|
||||
switch (period.unit) {
|
||||
case SKProductPeriodUnitDay: unit = @"D"; break;
|
||||
case SKProductPeriodUnitWeek: unit = @"W"; break;
|
||||
case SKProductPeriodUnitMonth: unit = @"M"; break;
|
||||
case SKProductPeriodUnitYear: unit = @"Y"; break;
|
||||
}
|
||||
return [NSString stringWithFormat:@"P%lu%@", (unsigned long)period.numberOfUnits, unit];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
|
||||
{
|
||||
NSArray *products = response.products;
|
||||
NSArray *invalidProductIdentifiers = response.invalidProductIdentifiers;
|
||||
if (products.count + invalidProductIdentifiers.count != 1) {
|
||||
id<FBSDKLogging> logger = [self.loggerFactory createLoggerWithLoggingBehavior:FBSDKLoggingBehaviorAppEvents];
|
||||
[logger logEntry:@"FBSDKPaymentObserver: Expect to resolve one product per request"];
|
||||
}
|
||||
SKProduct *product = nil;
|
||||
if (products.count) {
|
||||
product = [FBSDKTypeUtility array:products objectAtIndex:0];
|
||||
}
|
||||
[self logTransactionEvent:product];
|
||||
}
|
||||
|
||||
- (void)requestDidFinish:(SKRequest *)request
|
||||
{
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
|
||||
{
|
||||
[self logTransactionEvent:nil];
|
||||
[self cleanUp];
|
||||
}
|
||||
|
||||
- (void)cleanUp
|
||||
{
|
||||
@synchronized(self.class.pendingRequestors) {
|
||||
[self.class.pendingRequestors removeObject:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logImplicitSubscribeTransaction:(SKPaymentTransaction *)transaction
|
||||
ofProduct:(SKProduct *)product
|
||||
{
|
||||
NSString *eventName = nil;
|
||||
NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier;
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchasing:
|
||||
eventName = @"SubscriptionInitiatedCheckout";
|
||||
break;
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
if ([self isStartTrial:transaction ofProduct:product]) {
|
||||
eventName = FBSDKAppEventNameStartTrial;
|
||||
[self clearOriginalTransactionID:originalTransactionID];
|
||||
} else {
|
||||
if (originalTransactionID && [self.originalTransactionSet containsObject:originalTransactionID]) {
|
||||
return;
|
||||
}
|
||||
eventName = FBSDKAppEventNameSubscribe;
|
||||
[self appendOriginalTransactionID:(originalTransactionID ?: transaction.transactionIdentifier)];
|
||||
}
|
||||
break;
|
||||
case SKPaymentTransactionStateFailed:
|
||||
eventName = @"SubscriptionFailed";
|
||||
break;
|
||||
case SKPaymentTransactionStateRestored:
|
||||
eventName = @"SubscriptionRestore";
|
||||
break;
|
||||
case SKPaymentTransactionStateDeferred:
|
||||
return;
|
||||
}
|
||||
|
||||
double totalAmount = 0;
|
||||
if (product) {
|
||||
totalAmount = transaction.payment.quantity * product.price.doubleValue;
|
||||
}
|
||||
|
||||
[self logImplicitTransactionEvent:eventName
|
||||
valueToSum:totalAmount
|
||||
parameters:[self getEventParametersOfProduct:product withTransaction:transaction]];
|
||||
}
|
||||
|
||||
- (void)logImplicitPurchaseTransaction:(SKPaymentTransaction *)transaction
|
||||
ofProduct:(SKProduct *)product
|
||||
{
|
||||
NSString *eventName = nil;
|
||||
switch (transaction.transactionState) {
|
||||
case SKPaymentTransactionStatePurchasing:
|
||||
eventName = FBSDKAppEventNameInitiatedCheckout;
|
||||
break;
|
||||
case SKPaymentTransactionStatePurchased:
|
||||
eventName = FBSDKAppEventNamePurchased;
|
||||
break;
|
||||
case SKPaymentTransactionStateFailed:
|
||||
eventName = FBSDKAppEventNamePurchaseFailed;
|
||||
break;
|
||||
case SKPaymentTransactionStateRestored:
|
||||
eventName = FBSDKAppEventNamePurchaseRestored;
|
||||
break;
|
||||
case SKPaymentTransactionStateDeferred:
|
||||
return;
|
||||
}
|
||||
|
||||
double totalAmount = 0;
|
||||
if (product) {
|
||||
totalAmount = transaction.payment.quantity * product.price.doubleValue;
|
||||
}
|
||||
|
||||
[self logImplicitTransactionEvent:eventName
|
||||
valueToSum:totalAmount
|
||||
parameters:[self getEventParametersOfProduct:product withTransaction:transaction]];
|
||||
}
|
||||
|
||||
- (void)logImplicitTransactionEvent:(NSString *)eventName
|
||||
valueToSum:(double)valueToSum
|
||||
parameters:(NSDictionary<NSString *, id> *)parameters
|
||||
{
|
||||
NSMutableDictionary *eventParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
|
||||
if ([_eventsWithReceipt containsObject:eventName]) {
|
||||
NSData *receipt = [self fetchDeviceReceipt];
|
||||
if (receipt) {
|
||||
NSString *base64encodedReceipt = [receipt base64EncodedStringWithOptions:0];
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:base64encodedReceipt forKey:@"receipt_data"];
|
||||
}
|
||||
}
|
||||
|
||||
[FBSDKTypeUtility dictionary:eventParameters setObject:@"1" forKey:FBSDKAppEventParameterImplicitlyLoggedPurchase];
|
||||
[self.eventLogger logEvent:eventName
|
||||
valueToSum:valueToSum
|
||||
parameters:eventParameters];
|
||||
|
||||
// Unless the behavior is set to only allow explicit flushing, we go ahead and flush, since purchase events
|
||||
// are relatively rare and relatively high value and worth getting across on wire right away.
|
||||
if ([self.eventLogger flushBehavior] != FBSDKAppEventsFlushBehaviorExplicitOnly) {
|
||||
[self.eventLogger flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the current receipt for this application.
|
||||
- (NSData *)fetchDeviceReceipt
|
||||
{
|
||||
NSURL *receiptURL = self.appStoreReceiptProvider.appStoreReceiptURL;
|
||||
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
|
||||
return receipt;
|
||||
}
|
||||
|
||||
@end
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FBSDKPaymentProductRequestor;
|
||||
@class SKPaymentTransaction;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(PaymentProductRequestorCreating)
|
||||
@protocol FBSDKPaymentProductRequestorCreating
|
||||
|
||||
- (nonnull FBSDKPaymentProductRequestor *)createRequestorWithTransaction:(SKPaymentTransaction *)transaction
|
||||
NS_SWIFT_NAME(createRequestor(transaction:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestorFactory.h
Generated
+48
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKPaymentProductRequestorCreating.h"
|
||||
|
||||
@protocol FBSDKSettings;
|
||||
@protocol FBSDKEventLogging;
|
||||
@protocol FBSDKGateKeeperManaging;
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKLoggingCreating;
|
||||
@protocol FBSDKProductsRequestCreating;
|
||||
@protocol FBSDKAppStoreReceiptProviding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Factory used to create `FBSDKPaymentProductRequestor` instances with dependencies.
|
||||
NS_SWIFT_NAME(PaymentProductRequestorFactory)
|
||||
@interface FBSDKPaymentProductRequestorFactory : NSObject<FBSDKPaymentProductRequestorCreating>
|
||||
|
||||
- (instancetype)initWithSettings:(id<FBSDKSettings>)settings
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
gateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
loggerFactory:(id<FBSDKLoggingCreating>)logger
|
||||
productsRequestFactory:(id<FBSDKProductsRequestCreating>)productsRequestFactory
|
||||
appStoreReceiptProvider:(id<FBSDKAppStoreReceiptProviding>)receiptProvider
|
||||
NS_SWIFT_NAME(init(settings:eventLogger:gateKeeperManager:store:loggerFactory:productsRequestFactory:receiptProvider:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Pods/FBSDKCoreKit/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestorFactory.m
Generated
+90
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKPaymentProductRequestorFactory.h"
|
||||
|
||||
#import "FBSDKAppEvents+EventLogging.h"
|
||||
#import "FBSDKAppStoreReceiptProviding.h"
|
||||
#import "FBSDKGateKeeperManager.h"
|
||||
#import "FBSDKGateKeeperManaging.h"
|
||||
#import "FBSDKLoggerFactory.h"
|
||||
#import "FBSDKPaymentProductRequestor.h"
|
||||
#import "FBSDKProductRequestFactory.h"
|
||||
#import "FBSDKProductsRequestProtocols.h"
|
||||
#import "FBSDKSettings+Internal.h"
|
||||
#import "NSUserDefaults+FBSDKDataPersisting.h"
|
||||
|
||||
@interface FBSDKPaymentProductRequestorFactory ()
|
||||
|
||||
@property (nonatomic, readonly) id<FBSDKSettings> settings;
|
||||
@property (nonatomic, readonly) id<FBSDKEventLogging> eventLogger;
|
||||
@property (nullable, nonatomic) Class<FBSDKGateKeeperManaging> gateKeeperManager;
|
||||
@property (nullable, nonatomic) id<FBSDKDataPersisting> store;
|
||||
@property (nullable, nonatomic) id<FBSDKLoggingCreating> loggerFactory;
|
||||
@property (nonatomic, readonly) id<FBSDKProductsRequestCreating> productsRequestFactory;
|
||||
@property (nonatomic, readonly) id<FBSDKAppStoreReceiptProviding> appStoreReceiptProvider;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKPaymentProductRequestorFactory
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithSettings:FBSDKSettings.sharedSettings
|
||||
eventLogger:FBSDKAppEvents.singleton
|
||||
gateKeeperManager:FBSDKGateKeeperManager.class
|
||||
store:NSUserDefaults.standardUserDefaults
|
||||
loggerFactory:[FBSDKLoggerFactory new]
|
||||
productsRequestFactory:[FBSDKProductRequestFactory new]
|
||||
appStoreReceiptProvider:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSettings:(id<FBSDKSettings>)settings
|
||||
eventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
gateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
loggerFactory:(id<FBSDKLoggingCreating>)loggerFactory
|
||||
productsRequestFactory:(id<FBSDKProductsRequestCreating>)productsRequestFactory
|
||||
appStoreReceiptProvider:(id<FBSDKAppStoreReceiptProviding>)receiptProvider
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_settings = settings;
|
||||
_eventLogger = eventLogger;
|
||||
_gateKeeperManager = gateKeeperManager;
|
||||
_store = store;
|
||||
_loggerFactory = loggerFactory;
|
||||
_productsRequestFactory = productsRequestFactory;
|
||||
_appStoreReceiptProvider = receiptProvider;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nonnull FBSDKPaymentProductRequestor *)createRequestorWithTransaction:(SKPaymentTransaction *)transaction
|
||||
{
|
||||
return [[FBSDKPaymentProductRequestor alloc] initWithTransaction:transaction
|
||||
settings:self.settings
|
||||
eventLogger:self.eventLogger
|
||||
gateKeeperManager:self.gateKeeperManager
|
||||
store:self.store
|
||||
loggerFactory:self.loggerFactory
|
||||
productsRequestFactory:self.productsRequestFactory
|
||||
appStoreReceiptProvider:self.appStoreReceiptProvider];
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKProductsRequestProtocols.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(ProductRequestFactory)
|
||||
@interface FBSDKProductRequestFactory : NSObject<FBSDKProductsRequestCreating>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKProductRequestFactory.h"
|
||||
|
||||
#import "SKProductsRequest+FBSDKProductsRequest.h"
|
||||
|
||||
@implementation FBSDKProductRequestFactory
|
||||
|
||||
- (nonnull id<FBSDKProductsRequest>)createWithProductIdentifiers:(nonnull NSSet<NSString *> *)identifiers
|
||||
{
|
||||
return [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+42
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@protocol SKProductsRequestDelegate;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// An abstraction for an `SKProductsRequest` instance
|
||||
NS_SWIFT_NAME(ProductsRequest)
|
||||
@protocol FBSDKProductsRequest
|
||||
|
||||
@property(nonatomic, weak, nullable) id <SKProductsRequestDelegate> delegate;
|
||||
|
||||
- (void)cancel;
|
||||
- (void)start;
|
||||
|
||||
@end
|
||||
|
||||
/// An abstraction for any object that can create a `ProductsRequest`
|
||||
NS_SWIFT_NAME(ProductsRequestCreating)
|
||||
@protocol FBSDKProductsRequestCreating
|
||||
|
||||
- (id<FBSDKProductsRequest>)createWithProductIdentifiers:(NSSet<NSString *> *)identifiers;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(SourceApplicationTracking)
|
||||
@protocol FBSDKSourceApplicationTracking
|
||||
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication openURL:(nullable NSURL *)url;
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication isFromAppLink:(BOOL)isFromAppLink;
|
||||
- (void)registerAutoResetSourceApplication;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKSourceApplicationTracking.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKTimeSpentData (SourceApplicationTracking) <FBSDKSourceApplicationTracking>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKTimeSpentData.h"
|
||||
#import "FBSDKTimeSpentRecording.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKTimeSpentData (TimeSpentRecording) <FBSDKTimeSpentRecording>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol FBSDKEventLogging;
|
||||
@protocol FBSDKServerConfigurationProviding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Class to encapsulate persisting of time spent data collected by [FBSDKAppEvents activateApp]. The activate app App Event is
|
||||
// logged when restore: is called with sufficient time since the last deactivation.
|
||||
NS_SWIFT_NAME(TimeSpentData)
|
||||
@interface FBSDKTimeSpentData : NSObject
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithEventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider;
|
||||
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication openURL:(nullable NSURL *)url;
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication isFromAppLink:(BOOL)isFromAppLink;
|
||||
- (void)registerAutoResetSourceApplication;
|
||||
- (void)suspend;
|
||||
- (void)restore:(BOOL)calledFromActivateApp;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKTimeSpentData.h"
|
||||
|
||||
#import "FBSDKAppEventParameterName.h"
|
||||
#import "FBSDKAppEventsFlushReason.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKEventLogging.h"
|
||||
#import "FBSDKInternalUtility+Internal.h"
|
||||
#import "FBSDKLogger.h"
|
||||
#import "FBSDKServerConfiguration.h"
|
||||
#import "FBSDKServerConfigurationProviding.h"
|
||||
|
||||
// Filename and keys for session length
|
||||
NSString *const FBSDKTimeSpentFilename = @"com-facebook-sdk-AppEventsTimeSpent.json";
|
||||
static NSString *const FBSDKTimeSpentPersistKeySessionSecondsSpent = @"secondsSpentInCurrentSession";
|
||||
static NSString *const FBSDKTimeSpentPersistKeySessionNumInterruptions = @"numInterruptions";
|
||||
static NSString *const FBSDKTimeSpentPersistKeyLastSuspendTime = @"lastSuspendTime";
|
||||
static NSString *const FBSDKTimeSpentPersistKeySessionID = @"sessionID";
|
||||
|
||||
static NSString *const FBSDKAppEventNameActivatedApp = @"fb_mobile_activate_app";
|
||||
static NSString *const FBSDKAppEventNameDeactivatedApp = @"fb_mobile_deactivate_app";
|
||||
static NSString *const FBSDKAppEventParameterNameSessionInterruptions = @"fb_mobile_app_interruptions";
|
||||
static NSString *const FBSDKAppEventParameterNameTimeBetweenSessions = @"fb_mobile_time_between_sessions";
|
||||
static NSString *const FBSDKAppEventParameterNameSessionID = @"_session_id";
|
||||
|
||||
FBSDKAppEventParameterName FBSDKAppEventParameterLaunchSource = @"fb_mobile_launch_source";
|
||||
|
||||
static const int SECS_PER_MIN = 60;
|
||||
static const int SECS_PER_HOUR = 60 * SECS_PER_MIN;
|
||||
static const int SECS_PER_DAY = 24 * SECS_PER_HOUR;
|
||||
|
||||
// Will be translated and displayed in App Insights. Need to maintain same number and value of quanta on the server.
|
||||
static const long INACTIVE_SECONDS_QUANTA[] =
|
||||
{
|
||||
5 * SECS_PER_MIN,
|
||||
15 * SECS_PER_MIN,
|
||||
30 * SECS_PER_MIN,
|
||||
1 * SECS_PER_HOUR,
|
||||
6 * SECS_PER_HOUR,
|
||||
12 * SECS_PER_HOUR,
|
||||
1 * SECS_PER_DAY,
|
||||
2 * SECS_PER_DAY,
|
||||
3 * SECS_PER_DAY,
|
||||
7 * SECS_PER_DAY,
|
||||
14 * SECS_PER_DAY,
|
||||
21 * SECS_PER_DAY,
|
||||
28 * SECS_PER_DAY,
|
||||
60 * SECS_PER_DAY,
|
||||
90 * SECS_PER_DAY,
|
||||
120 * SECS_PER_DAY,
|
||||
150 * SECS_PER_DAY,
|
||||
180 * SECS_PER_DAY,
|
||||
365 * SECS_PER_DAY,
|
||||
LONG_MAX, // keep as LONG_MAX to guarantee loop will terminate
|
||||
};
|
||||
|
||||
@interface FBSDKTimeSpentData ()
|
||||
|
||||
@property (nonatomic, weak) id<FBSDKEventLogging> eventLogger;
|
||||
@property (nonnull, nonatomic) id<FBSDKServerConfigurationProviding> serverConfigurationProvider;
|
||||
@property (nonatomic) NSString *sourceApplication;
|
||||
@property (nonatomic) BOOL isOpenedFromAppLink;
|
||||
@property (nonatomic) BOOL isCurrentlyLoaded;
|
||||
@property (nonatomic) NSTimeInterval lastRestoreTime;
|
||||
@property (nonatomic) NSTimeInterval secondsSpentInCurrentSession;
|
||||
@property (nonatomic) NSTimeInterval timeSinceLastSuspend;
|
||||
@property (nonatomic) int numInterruptionsInCurrentSession;
|
||||
@property (nonatomic) NSString *sessionID;
|
||||
@property (nonatomic) NSTimeInterval lastSuspendTime;
|
||||
@property (nonatomic) BOOL shouldLogActivateEvent;
|
||||
@property (nonatomic) BOOL shouldLogDeactivateEvent;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* This class encapsulates the notion of an app 'session' - the length of time that the user has
|
||||
* spent in the app that can be considered a single usage of the app. Apps may be frequently interrupted
|
||||
* do to other device activity, like a text message, so this class allows those interruptions to be smoothed
|
||||
* out and the time actually spent in the app excluding this interruption time to be accumulated. Also,
|
||||
* once a certain amount of time has gone by where the app is not in the foreground, we consider the
|
||||
* session to be complete, and a new session beginning. When this occurs, we log a 'deactivate app' event
|
||||
* with the duration of the previous session as the 'value' of this event, along with the number of
|
||||
* interruptions from that previous session as an event parameter.
|
||||
*/
|
||||
@implementation FBSDKTimeSpentData
|
||||
|
||||
- (instancetype)initWithEventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventLogger = eventLogger;
|
||||
_serverConfigurationProvider = serverConfigurationProvider;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Calculate and persist time spent data for this instance of the app activation.
|
||||
- (void)suspend
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self suspendTimeSpentData];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)suspendTimeSpentData
|
||||
{
|
||||
if (!self.isCurrentlyLoaded) {
|
||||
FBSDKConditionalLog(YES, FBSDKLoggingBehaviorInformational, @"[FBSDKTimeSpentData suspend] invoked without corresponding restore");
|
||||
return;
|
||||
}
|
||||
|
||||
NSTimeInterval now = round([NSDate date].timeIntervalSince1970);
|
||||
NSTimeInterval timeSinceRestore = now - self.lastRestoreTime;
|
||||
|
||||
// Can happen if the clock on the device is changed
|
||||
if (timeSinceRestore < 0) {
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||
logEntry:@"Clock skew detected"];
|
||||
timeSinceRestore = 0;
|
||||
}
|
||||
|
||||
self.secondsSpentInCurrentSession += timeSinceRestore;
|
||||
|
||||
NSDictionary *timeSpentData =
|
||||
@{
|
||||
FBSDKTimeSpentPersistKeySessionSecondsSpent : @(self.secondsSpentInCurrentSession),
|
||||
FBSDKTimeSpentPersistKeySessionNumInterruptions : @(self.numInterruptionsInCurrentSession),
|
||||
FBSDKTimeSpentPersistKeyLastSuspendTime : @(now),
|
||||
FBSDKTimeSpentPersistKeySessionID : self.sessionID,
|
||||
};
|
||||
|
||||
NSString *content = [FBSDKBasicUtility JSONStringForObject:timeSpentData error:NULL invalidObjectHandler:NULL];
|
||||
|
||||
[content writeToFile:[FBSDKBasicUtility persistenceFilePath:FBSDKTimeSpentFilename]
|
||||
atomically:YES
|
||||
encoding:NSASCIIStringEncoding
|
||||
error:nil];
|
||||
|
||||
NSString *msg = [NSString stringWithFormat:@"FBSDKTimeSpentData Persist: %@", content];
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
|
||||
logEntry:msg];
|
||||
|
||||
self.isCurrentlyLoaded = NO;
|
||||
}
|
||||
|
||||
// Called during activation - either through an explicit 'activateApp' call or implicitly when the app is foregrounded.
|
||||
// In both cases, we restore the persisted event data. In the case of the activateApp, we log an 'app activated'
|
||||
// event if there's been enough time between the last deactivation and now.
|
||||
- (void)restore:(BOOL)calledFromActivateApp
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self restoreTimeSpendDataWithCalledFromActivateApp:calledFromActivateApp];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)restoreTimeSpendDataWithCalledFromActivateApp:(BOOL)isCalledFromActivateApp
|
||||
{
|
||||
// It's possible to call this multiple times during the time the app is in the foreground. If this is the case,
|
||||
// just restore persisted data the first time.
|
||||
if (!self.isCurrentlyLoaded) {
|
||||
NSTimeInterval now = round([NSDate date].timeIntervalSince1970);
|
||||
NSString *content =
|
||||
[[NSString alloc] initWithContentsOfFile:[FBSDKBasicUtility persistenceFilePath:FBSDKTimeSpentFilename]
|
||||
usedEncoding:nil
|
||||
error:nil];
|
||||
|
||||
if (!content) {
|
||||
// Nothing persisted, so this is the first launch.
|
||||
self.sessionID = [NSUUID UUID].UUIDString;
|
||||
self.secondsSpentInCurrentSession = 0;
|
||||
self.numInterruptionsInCurrentSession = 0;
|
||||
self.lastSuspendTime = 0;
|
||||
|
||||
// We want to log the app activation event on the first launch, but not the deactivate event
|
||||
self.shouldLogActivateEvent = YES;
|
||||
self.shouldLogDeactivateEvent = NO;
|
||||
} else {
|
||||
NSDictionary<id, id> *results = [FBSDKBasicUtility objectForJSONString:content error:NULL];
|
||||
|
||||
self.lastSuspendTime = [results[FBSDKTimeSpentPersistKeyLastSuspendTime] longValue];
|
||||
|
||||
self.timeSinceLastSuspend = now - self.lastSuspendTime;
|
||||
self.secondsSpentInCurrentSession = [results[FBSDKTimeSpentPersistKeySessionSecondsSpent] intValue];
|
||||
self.sessionID = results[FBSDKTimeSpentPersistKeySessionID] ?: [NSUUID UUID].UUIDString;
|
||||
self.numInterruptionsInCurrentSession = [results[FBSDKTimeSpentPersistKeySessionNumInterruptions] intValue];
|
||||
self.shouldLogActivateEvent = (self.timeSinceLastSuspend > [[self.serverConfigurationProvider cachedServerConfiguration] sessionTimoutInterval]);
|
||||
|
||||
// Other than the first launch, we always log the last session's deactivate with this session's activate.
|
||||
self.shouldLogDeactivateEvent = self.shouldLogActivateEvent;
|
||||
|
||||
if (!self.shouldLogDeactivateEvent) {
|
||||
// If we're not logging, then the time we spent deactivated is considered another interruption. But cap it
|
||||
// so errant or test uses doesn't blow out the cardinality on the backend processing
|
||||
self.numInterruptionsInCurrentSession = MIN(self.numInterruptionsInCurrentSession + 1, 200);
|
||||
}
|
||||
}
|
||||
|
||||
self.lastRestoreTime = now;
|
||||
self.isCurrentlyLoaded = YES;
|
||||
|
||||
if (isCalledFromActivateApp) {
|
||||
// It's important to log deactivate first to reset sessionID
|
||||
if (self.shouldLogDeactivateEvent) {
|
||||
[self.eventLogger logEvent:FBSDKAppEventNameDeactivatedApp
|
||||
valueToSum:self.secondsSpentInCurrentSession
|
||||
parameters:[self appEventsParametersForDeactivate]];
|
||||
|
||||
// We've logged the session stats, now reset.
|
||||
self.secondsSpentInCurrentSession = 0;
|
||||
self.numInterruptionsInCurrentSession = 0;
|
||||
self.sessionID = [NSUUID UUID].UUIDString;
|
||||
}
|
||||
|
||||
if (self.shouldLogActivateEvent) {
|
||||
[self.eventLogger logEvent:FBSDKAppEventNameActivatedApp
|
||||
parameters:[self appEventsParametersForActivate]];
|
||||
// Unless the behavior is set to only allow explicit flushing, we go ahead and flush. App launch
|
||||
// events are critical to Analytics so we don't want to lose them.
|
||||
if (self.eventLogger.flushBehavior != FBSDKAppEventsFlushBehaviorExplicitOnly) {
|
||||
[self.eventLogger flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)appEventsParametersForActivate
|
||||
{
|
||||
return @{
|
||||
FBSDKAppEventParameterLaunchSource : [self getSourceApplication],
|
||||
FBSDKAppEventParameterNameSessionID : self.sessionID,
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDictionary *)appEventsParametersForDeactivate
|
||||
{
|
||||
int quantaIndex = 0;
|
||||
while (_timeSinceLastSuspend > INACTIVE_SECONDS_QUANTA[quantaIndex]) {
|
||||
quantaIndex++;
|
||||
}
|
||||
|
||||
NSMutableDictionary *params = [@{ FBSDKAppEventParameterNameSessionInterruptions : @(self.numInterruptionsInCurrentSession),
|
||||
FBSDKAppEventParameterNameTimeBetweenSessions : [NSString stringWithFormat:@"session_quanta_%d", quantaIndex],
|
||||
FBSDKAppEventParameterLaunchSource : [self getSourceApplication],
|
||||
FBSDKAppEventParameterNameSessionID : self.sessionID ?: @"", } mutableCopy];
|
||||
if (_lastSuspendTime) {
|
||||
[FBSDKTypeUtility dictionary:params setObject:@(_lastSuspendTime) forKey:@"_logTime"];
|
||||
}
|
||||
return [params copy];
|
||||
}
|
||||
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication openURL:(NSURL *)url
|
||||
{
|
||||
[self setSourceApplication:sourceApplication
|
||||
isFromAppLink:[FBSDKInternalUtility.sharedUtility parametersFromFBURL:url][@"al_applink_data"] != nil];
|
||||
}
|
||||
|
||||
- (void)setSourceApplication:(nullable NSString *)sourceApplication isFromAppLink:(BOOL)isFromAppLink
|
||||
{
|
||||
self.isOpenedFromAppLink = isFromAppLink;
|
||||
self.sourceApplication = sourceApplication;
|
||||
}
|
||||
|
||||
- (NSString *)getSourceApplication
|
||||
{
|
||||
NSString *openType = @"Unclassified";
|
||||
if (self.isOpenedFromAppLink) {
|
||||
openType = @"AppLink";
|
||||
}
|
||||
return (self.sourceApplication
|
||||
? [NSString stringWithFormat:@"%@(%@)", openType, self.sourceApplication]
|
||||
: openType);
|
||||
}
|
||||
|
||||
- (void)resetSourceApplication
|
||||
{
|
||||
self.sourceApplication = nil;
|
||||
self.isOpenedFromAppLink = NO;
|
||||
}
|
||||
|
||||
- (void)registerAutoResetSourceApplication
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(resetSourceApplication)
|
||||
name:UIApplicationDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(TimeSpentRecording)
|
||||
@protocol FBSDKTimeSpentRecording
|
||||
|
||||
- (void)suspend;
|
||||
- (void)restore:(BOOL)calledFromActivateApp;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKTimeSpentRecording.h"
|
||||
#import "FBSDKSourceApplicationTracking.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(TimeSpentRecordingCreating)
|
||||
@protocol FBSDKTimeSpentRecordingCreating
|
||||
|
||||
- (id<FBSDKTimeSpentRecording, FBSDKSourceApplicationTracking>)createTimeSpentRecorder;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKTimeSpentRecordingCreating.h"
|
||||
|
||||
@protocol FBSDKEventLogging;
|
||||
@protocol FBSDKServerConfigurationProviding;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(TimeSpentRecordingFactory)
|
||||
@interface FBSDKTimeSpentRecordingFactory : NSObject<FBSDKTimeSpentRecordingCreating>
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithEventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+56
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKTimeSpentRecordingFactory.h"
|
||||
|
||||
#import "FBSDKEventLogging.h"
|
||||
#import "FBSDKServerConfigurationProviding.h"
|
||||
#import "FBSDKTimeSpentData.h"
|
||||
#import "FBSDKTimeSpentData+SourceApplicationTracking.h"
|
||||
#import "FBSDKTimeSpentData+TimeSpentRecording.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKTimeSpentRecordingFactory ()
|
||||
|
||||
@property (nonnull, nonatomic, readonly) id<FBSDKServerConfigurationProviding> serverConfigurationProvider;
|
||||
@property (nonnull, nonatomic, readonly) id<FBSDKEventLogging> eventLogger;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKTimeSpentRecordingFactory
|
||||
|
||||
- (instancetype)initWithEventLogger:(id<FBSDKEventLogging>)eventLogger
|
||||
serverConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventLogger = eventLogger;
|
||||
_serverConfigurationProvider = serverConfigurationProvider;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<FBSDKSourceApplicationTracking, FBSDKTimeSpentRecording>)createTimeSpentRecorder
|
||||
{
|
||||
return [[FBSDKTimeSpentData alloc] initWithEventLogger:self.eventLogger
|
||||
serverConfigurationProvider:self.serverConfigurationProvider];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKAppEventsParameterProcessing.h"
|
||||
#import "FBSDKIntegrityManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKIntegrityManager (AppEventsParameterProcessing) <FBSDKAppEventsParameterProcessing>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Generated
+45
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol FBSDKGateKeeperManaging;
|
||||
@protocol FBSDKIntegrityProcessing;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(IntegrityManager)
|
||||
@interface FBSDKIntegrityManager : NSObject
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithGateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
integrityProcessor:(id<FBSDKIntegrityProcessing>)integrityProcessor;
|
||||
|
||||
- (void)enable;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Generated
+85
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKIntegrityManager.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKGateKeeperManaging.h"
|
||||
#import "FBSDKIntegrityProcessing.h"
|
||||
|
||||
@interface FBSDKIntegrityManager ()
|
||||
|
||||
@property (nonatomic) Class<FBSDKGateKeeperManaging> gateKeeperManager;
|
||||
@property (nonatomic, weak) id<FBSDKIntegrityProcessing> integrityProcessor;
|
||||
@property (nonatomic) BOOL isIntegrityEnabled;
|
||||
@property (nonatomic) BOOL isSampleEnabled;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKIntegrityManager
|
||||
|
||||
- (instancetype)initWithGateKeeperManager:(Class<FBSDKGateKeeperManaging>)gateKeeperManager
|
||||
integrityProcessor:(id<FBSDKIntegrityProcessing>)integrityProcessor
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_gateKeeperManager = gateKeeperManager;
|
||||
_integrityProcessor = integrityProcessor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)enable
|
||||
{
|
||||
self.isIntegrityEnabled = YES;
|
||||
self.isSampleEnabled = [self.gateKeeperManager boolForKey:@"FBSDKFeatureIntegritySample" defaultValue:false];
|
||||
}
|
||||
|
||||
// Unused parameter eventName is required for conformance to shared protocol for processing app events.
|
||||
- (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName
|
||||
{
|
||||
if (!self.isIntegrityEnabled || parameters.count == 0) {
|
||||
return parameters;
|
||||
}
|
||||
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
NSMutableDictionary<NSString *, id> *restrictiveParams = [NSMutableDictionary dictionary];
|
||||
|
||||
for (NSString *key in [parameters keyEnumerator]) {
|
||||
NSString *valueString = [FBSDKTypeUtility coercedToStringValue:parameters[key]];
|
||||
BOOL shouldFilter = [self.integrityProcessor processIntegrity:key] || [self.integrityProcessor processIntegrity:valueString];
|
||||
if (shouldFilter) {
|
||||
[FBSDKTypeUtility dictionary:restrictiveParams setObject:self.isSampleEnabled ? valueString : @"" forKey:key];
|
||||
[params removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
if ([restrictiveParams count] > 0) {
|
||||
NSString *restrictiveParamsJSONString = [FBSDKBasicUtility JSONStringForObject:restrictiveParams
|
||||
error:NULL
|
||||
invalidObjectHandler:NULL];
|
||||
[FBSDKTypeUtility dictionary:params setObject:restrictiveParamsJSONString forKey:@"_onDeviceParams"];
|
||||
}
|
||||
return [params copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Generated
+35
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(RestrictiveData)
|
||||
@interface FBSDKRestrictiveData : NSObject
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName params:(id)params;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||
@property (nullable, nonatomic, readonly, copy) NSDictionary<NSString *, NSString *> *restrictiveParams;
|
||||
@property (nullable, nonatomic, readonly, copy) NSArray<NSString *> *deprecatedParams;
|
||||
@property (nonatomic, readonly, assign) BOOL deprecatedEvent;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Generated
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKRestrictiveData.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
|
||||
#define RESTRICTIVE_PARAM @"restrictive_param"
|
||||
#define DEPRECATED_PARAM @"deprecated_param"
|
||||
#define IS_DEPRECATED_EVENT @"is_deprecated_event"
|
||||
|
||||
@implementation FBSDKRestrictiveData
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName params:(id)params
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSDictionary<NSString *, id> *paramDict = [FBSDKTypeUtility dictionaryValue:params];
|
||||
if (!paramDict) {
|
||||
return nil;
|
||||
}
|
||||
_eventName = eventName;
|
||||
_restrictiveParams = paramDict[RESTRICTIVE_PARAM] ? [FBSDKTypeUtility dictionaryValue:paramDict[RESTRICTIVE_PARAM]] : nil;
|
||||
_deprecatedParams = paramDict[DEPRECATED_PARAM] ? [FBSDKTypeUtility arrayValue:paramDict[DEPRECATED_PARAM]] : nil;
|
||||
_deprecatedEvent = (paramDict[IS_DEPRECATED_EVENT] && [paramDict[IS_DEPRECATED_EVENT] respondsToSelector:@selector(boolValue)]) ? [paramDict[IS_DEPRECATED_EVENT] boolValue] : NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKAppEventsParameterProcessing.h"
|
||||
#import "FBSDKEventsProcessing.h"
|
||||
#import "FBSDKRestrictiveDataFilterManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKRestrictiveDataFilterManager (AppEventsParameterProcessing) <FBSDKAppEventsParameterProcessing, FBSDKEventsProcessing>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FBSDKServerConfigurationProviding;
|
||||
|
||||
NS_SWIFT_NAME(RestrictiveDataFilterManager)
|
||||
@interface FBSDKRestrictiveDataFilterManager : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)initWithServerConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)enable;
|
||||
- (void)processEvents:(NSArray<NSDictionary<NSString *, id> *> *)events;
|
||||
- (nullable NSDictionary<NSString *, id> *)processParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "FBSDKRestrictiveDataFilterManager.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKServerConfigurationManager.h"
|
||||
#import "FBSDKServerConfigurationProviding.h"
|
||||
|
||||
@interface FBSDKRestrictiveEventFilter : NSObject
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *restrictiveParams;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName
|
||||
restrictiveParams:(NSDictionary<NSString *, id> *)restrictiveParams;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKRestrictiveEventFilter
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName
|
||||
restrictiveParams:(NSDictionary<NSString *, id> *)restrictiveParams
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_eventName = [eventName copy];
|
||||
_restrictiveParams = [restrictiveParams copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static FBSDKRestrictiveDataFilterManager *_instance;
|
||||
|
||||
@interface FBSDKRestrictiveDataFilterManager ()
|
||||
|
||||
@property (nonatomic) BOOL isRestrictiveEventFilterEnabled;
|
||||
@property (nonatomic) NSMutableArray<FBSDKRestrictiveEventFilter *> *params;
|
||||
@property (nonatomic) NSMutableSet<NSString *> *restrictedEvents;
|
||||
@property (nonatomic) id<FBSDKServerConfigurationProviding> serverConfigurationProvider;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKRestrictiveDataFilterManager
|
||||
|
||||
- (instancetype)initWithServerConfigurationProvider:(id<FBSDKServerConfigurationProviding>)serverConfigurationProvider
|
||||
{
|
||||
self.serverConfigurationProvider = serverConfigurationProvider;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)enable
|
||||
{
|
||||
@synchronized(self) {
|
||||
@try {
|
||||
if (!self.isRestrictiveEventFilterEnabled) {
|
||||
NSDictionary<NSString *, id> *restrictiveParams = [self.serverConfigurationProvider cachedServerConfiguration].restrictiveParams;
|
||||
if (restrictiveParams) {
|
||||
[self updateFilters:restrictiveParams];
|
||||
self.isRestrictiveEventFilterEnabled = YES;
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, id> *)processParameters:(NSDictionary<NSString *, id> *)parameters
|
||||
eventName:(NSString *)eventName
|
||||
{
|
||||
if (!self.isRestrictiveEventFilterEnabled) {
|
||||
return parameters;
|
||||
}
|
||||
if (parameters) {
|
||||
@try {
|
||||
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
NSMutableDictionary<NSString *, NSString *> *restrictedParams = [NSMutableDictionary dictionary];
|
||||
|
||||
for (NSString *key in [parameters keyEnumerator]) {
|
||||
NSString *type = [self getMatchedDataTypeWithEventName:eventName paramKey:key];
|
||||
if (type) {
|
||||
[FBSDKTypeUtility dictionary:restrictedParams setObject:type forKey:key];
|
||||
[params removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
if ([[restrictedParams allKeys] count] > 0) {
|
||||
NSString *restrictedParamsJSONString = [FBSDKBasicUtility JSONStringForObject:restrictedParams
|
||||
error:NULL
|
||||
invalidObjectHandler:NULL];
|
||||
[FBSDKTypeUtility dictionary:params setObject:restrictedParamsJSONString forKey:@"_restrictedParams"];
|
||||
}
|
||||
|
||||
return [params copy];
|
||||
} @catch (NSException *exception) {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)processEvents:(NSArray<NSMutableDictionary<NSString *, id> *> *)events
|
||||
{
|
||||
@try {
|
||||
if (!self.isRestrictiveEventFilterEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
static NSString *const REPLACEMENT_STRING = @"_removed_";
|
||||
|
||||
for (NSDictionary<NSString *, NSMutableDictionary<NSString *, id> *> *event in events) {
|
||||
if ([self isRestrictedEvent:event[@"event"][@"_eventName"]]) {
|
||||
[FBSDKTypeUtility dictionary:event[@"event"] setObject:REPLACEMENT_STRING forKey:@"_eventName"];
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {}
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods
|
||||
|
||||
- (BOOL)isRestrictedEvent:(NSString *)eventName
|
||||
{
|
||||
@synchronized(self) {
|
||||
return [self.restrictedEvents containsObject:eventName];
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSString *)getMatchedDataTypeWithEventName:(NSString *)eventName
|
||||
paramKey:(NSString *)paramKey
|
||||
{
|
||||
// match by params in custom events with event name
|
||||
for (FBSDKRestrictiveEventFilter *filter in self.params) {
|
||||
if ([filter.eventName isEqualToString:eventName]) {
|
||||
NSString *type = [FBSDKTypeUtility coercedToStringValue:filter.restrictiveParams[paramKey]];
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)updateFilters:(nullable NSDictionary<NSString *, id> *)restrictiveParams
|
||||
{
|
||||
static NSString *const RESTRICTIVE_PARAM_KEY = @"restrictive_param";
|
||||
static NSString *const PROCESS_EVENT_NAME_KEY = @"process_event_name";
|
||||
|
||||
restrictiveParams = [FBSDKTypeUtility dictionaryValue:restrictiveParams];
|
||||
if (restrictiveParams.count > 0) {
|
||||
@synchronized(self) {
|
||||
[self.params removeAllObjects];
|
||||
[self.restrictedEvents removeAllObjects];
|
||||
NSMutableArray<FBSDKRestrictiveEventFilter *> *eventFilterArray = [NSMutableArray array];
|
||||
NSMutableSet<NSString *> *restrictedEventSet = [NSMutableSet set];
|
||||
for (NSString *eventName in restrictiveParams.allKeys) {
|
||||
NSDictionary<NSString *, id> *eventInfo = restrictiveParams[eventName];
|
||||
if (!eventInfo) {
|
||||
continue;
|
||||
}
|
||||
if (eventInfo[RESTRICTIVE_PARAM_KEY]) {
|
||||
FBSDKRestrictiveEventFilter *restrictiveEventFilter = [[FBSDKRestrictiveEventFilter alloc] initWithEventName:eventName
|
||||
restrictiveParams:eventInfo[RESTRICTIVE_PARAM_KEY]];
|
||||
[FBSDKTypeUtility array:eventFilterArray addObject:restrictiveEventFilter];
|
||||
}
|
||||
if (restrictiveParams[eventName][PROCESS_EVENT_NAME_KEY]) {
|
||||
[restrictedEventSet addObject:eventName];
|
||||
}
|
||||
}
|
||||
self.params = eventFilterArray;
|
||||
self.restrictedEvents = restrictedEventSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef FBSDKMLMacros_h
|
||||
#define FBSDKMLMacros_h
|
||||
|
||||
// keys for ML
|
||||
#define MODEL_REQUEST_INTERVAL (60 * 60 * 24 * 3)
|
||||
#define MODEL_REQUEST_TIMESTAMP_KEY @"com.facebook.sdk:FBSDKModelRequestTimestamp"
|
||||
|
||||
#define FBSDK_ML_MODEL_PATH @"models"
|
||||
#define MODEL_INFO_KEY @"com.facebook.sdk:FBSDKModelInfo"
|
||||
#define ASSET_URI_KEY @"asset_uri"
|
||||
#define RULES_URI_KEY @"rules_uri"
|
||||
#define THRESHOLDS_KEY @"thresholds"
|
||||
#define USE_CASE_KEY @"use_case"
|
||||
#define VERSION_ID_KEY @"version_id"
|
||||
#define MODEL_DATA_KEY @"data"
|
||||
|
||||
#define MTMLKey @"MTML"
|
||||
#define MTMLTaskAppEventPredKey @"MTML_APP_EVENT_PRED"
|
||||
#define MTMLTaskIntegrityDetectKey @"MTML_INTEGRITY_DETECT"
|
||||
|
||||
// keys for Suggested Event
|
||||
#define SUGGEST_EVENT_KEY @"SUGGEST_EVENT"
|
||||
#define DENSE_FEATURE_KEY @"DENSE_FEATURE"
|
||||
#define SUGGESTED_EVENT_OTHER @"other"
|
||||
|
||||
#endif /* FBSDKMLMacros_h */
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKIntegrityParametersProcessorProvider.h"
|
||||
#import "FBSDKModelManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKModelManager (IntegrityParametersProcessorProvider) <FBSDKIntegrityParametersProcessorProvider>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKIntegrityProcessing.h"
|
||||
#import "FBSDKModelManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Default conformance to the integrity processing protocol
|
||||
@interface FBSDKModelManager (IntegrityProcessing) <FBSDKIntegrityProcessing>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKModelManager.h"
|
||||
#import "FBSDKRulesFromKeyProvider.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKModelManager (RulesFromKeyProvider) <FBSDKRulesFromKeyProvider>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKEventProcessing.h"
|
||||
|
||||
@protocol FBSDKDataPersisting;
|
||||
@protocol FBSDKFeatureChecking;
|
||||
@protocol FBSDKFileManaging;
|
||||
@protocol FBSDKGraphRequestProviding;
|
||||
@protocol FBSDKSettings;
|
||||
@protocol FBSDKFileDataExtracting;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(ModelManager)
|
||||
@interface FBSDKModelManager : NSObject<FBSDKEventProcessing>
|
||||
|
||||
@property (class, nonnull, readonly) FBSDKModelManager *shared;
|
||||
|
||||
- (void)enable;
|
||||
- (nullable NSData *)getWeightsForKey:(NSString *)useCase;
|
||||
- (nullable NSArray *)getThresholdsForKey:(NSString *)useCase;
|
||||
- (BOOL)processIntegrity:(nullable NSString *)param;
|
||||
- (NSString *)processSuggestedEvents:(NSString *)textFeature denseData:(nullable float *)denseData;
|
||||
- (void)configureWithFeatureChecker:(id<FBSDKFeatureChecking>)featureChecker
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
fileManager:(id<FBSDKFileManaging>)fileManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
dataExtractor:(Class<FBSDKFileDataExtracting>)dataExtractor;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+504
@@ -0,0 +1,504 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKModelManager.h"
|
||||
#import "FBSDKModelManager+IntegrityProcessing.h"
|
||||
|
||||
#import "FBSDKAppEvents+Internal.h"
|
||||
#import "FBSDKAppEventsParameterProcessing.h"
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "FBSDKFeatureChecking.h"
|
||||
#import "FBSDKFeatureExtractor.h"
|
||||
#import "FBSDKGateKeeperManager.h"
|
||||
#import "FBSDKGraphRequestProviding.h"
|
||||
#import "FBSDKIntegrityManager+AppEventsParametersProcessing.h"
|
||||
#import "FBSDKMLMacros.h"
|
||||
#import "FBSDKModelParser.h"
|
||||
#import "FBSDKModelRuntime.hpp"
|
||||
#import "FBSDKModelUtility.h"
|
||||
#import "FBSDKSettingsProtocol.h"
|
||||
#import "FBSDKSuggestedEventsIndexer.h"
|
||||
|
||||
static NSString *const INTEGRITY_NONE = @"none";
|
||||
static NSString *const INTEGRITY_ADDRESS = @"address";
|
||||
static NSString *const INTEGRITY_HEALTH = @"health";
|
||||
|
||||
extern FBSDKAppEventName FBSDKAppEventNameCompletedRegistration;
|
||||
extern FBSDKAppEventName FBSDKAppEventNameAddedToCart;
|
||||
extern FBSDKAppEventName FBSDKAppEventNamePurchased;
|
||||
extern FBSDKAppEventName FBSDKAppEventNameInitiatedCheckout;
|
||||
|
||||
static NSString *_directoryPath;
|
||||
static NSMutableDictionary<NSString *, id> *_modelInfo;
|
||||
static std::unordered_map<std::string, fbsdk::MTensor> _MTMLWeights;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBSDKModelManager ()
|
||||
|
||||
@property (nonatomic) id<FBSDKAppEventsParameterProcessing> integrityParametersProcessor;
|
||||
@property (nullable, nonatomic) id<FBSDKFeatureChecking> featureChecker;
|
||||
@property (nullable, nonatomic) id<FBSDKGraphRequestProviding> graphRequestFactory;
|
||||
@property (nullable, nonatomic) id<FBSDKFileManaging> fileManager;
|
||||
@property (nullable, nonatomic) id<FBSDKDataPersisting> store;
|
||||
@property (nullable, nonatomic) id<FBSDKSettings> settings;
|
||||
@property (nullable, nonatomic) Class<FBSDKFileDataExtracting> dataExtractor;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FBSDKModelManager
|
||||
|
||||
typedef void (^FBSDKDownloadCompletionBlock)(void);
|
||||
|
||||
// Transitional singleton introduced as a way to change the usage semantics
|
||||
// from a type-based interface to an instance-based interface.
|
||||
+ (instancetype)shared
|
||||
{
|
||||
static dispatch_once_t nonce;
|
||||
static id instance;
|
||||
dispatch_once(&nonce, ^{
|
||||
instance = [self new];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
#pragma mark - Dependency Management
|
||||
|
||||
- (void)configureWithFeatureChecker:(id<FBSDKFeatureChecking>)featureChecker
|
||||
graphRequestFactory:(id<FBSDKGraphRequestProviding>)graphRequestFactory
|
||||
fileManager:(id<FBSDKFileManaging>)fileManager
|
||||
store:(id<FBSDKDataPersisting>)store
|
||||
settings:(id<FBSDKSettings>)settings
|
||||
dataExtractor:(Class<FBSDKFileDataExtracting>)dataExtractor
|
||||
{
|
||||
_featureChecker = featureChecker;
|
||||
_graphRequestFactory = graphRequestFactory;
|
||||
_fileManager = fileManager;
|
||||
_store = store;
|
||||
_settings = settings;
|
||||
_dataExtractor = dataExtractor;
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
static dispatch_once_t enableNonce;
|
||||
|
||||
- (void)enable
|
||||
{
|
||||
@try {
|
||||
dispatch_once(&enableNonce, ^{
|
||||
NSString *languageCode = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
|
||||
// If the languageCode could not be fetched successfully, it's regarded as "en" by default.
|
||||
if (languageCode && ![languageCode isEqualToString:@"en"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_directoryPath = [NSTemporaryDirectory() stringByAppendingPathComponent:FBSDK_ML_MODEL_PATH];
|
||||
if (![self.fileManager fileExistsAtPath:_directoryPath]) {
|
||||
[self.fileManager createDirectoryAtPath:_directoryPath withIntermediateDirectories:YES attributes:NULL error:NULL];
|
||||
}
|
||||
_modelInfo = [self.store objectForKey:MODEL_INFO_KEY];
|
||||
NSDate *timestamp = [self.store objectForKey:MODEL_REQUEST_TIMESTAMP_KEY];
|
||||
if ([_modelInfo count] == 0 || ![self.featureChecker isEnabled:FBSDKFeatureModelRequest] || ![self.class isValidTimestamp:timestamp]) {
|
||||
// fetch api
|
||||
NSString *graphPath = [NSString stringWithFormat:@"%@/model_asset", self.settings.appID];
|
||||
id<FBSDKGraphRequest> request = [self.graphRequestFactory createGraphRequestWithGraphPath:graphPath];
|
||||
__weak FBSDKModelManager *weakSelf = self;
|
||||
[request startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection, id result, NSError *error) {
|
||||
if (!error) {
|
||||
NSDictionary<NSString *, id> *resultDictionary = [FBSDKTypeUtility dictionaryValue:result];
|
||||
NSArray *rawModels = resultDictionary[MODEL_DATA_KEY];
|
||||
if ([rawModels isKindOfClass:NSArray.class]) {
|
||||
NSDictionary<NSString *, id> *modelInfo = [weakSelf.class convertToDictionary:rawModels];
|
||||
if (modelInfo) {
|
||||
_modelInfo = [modelInfo mutableCopy];
|
||||
[weakSelf.class processMTML];
|
||||
// update cache for model info and timestamp
|
||||
[weakSelf.store setObject:_modelInfo forKey:MODEL_INFO_KEY];
|
||||
[weakSelf.store setObject:[NSDate date] forKey:MODEL_REQUEST_TIMESTAMP_KEY];
|
||||
}
|
||||
}
|
||||
}
|
||||
[self checkFeaturesAndExecuteForMTML];
|
||||
}];
|
||||
} else {
|
||||
[self checkFeaturesAndExecuteForMTML];
|
||||
}
|
||||
});
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to enable model manager, exception reason: %@", exception.reason);
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSDictionary *)getRulesForKey:(NSString *)useCase
|
||||
{
|
||||
@try {
|
||||
NSDictionary<NSString *, id> *model = [FBSDKTypeUtility dictionary:_modelInfo objectForKey:useCase ofType:NSObject.class];
|
||||
if (model && model[VERSION_ID_KEY]) {
|
||||
NSString *filePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.rules", useCase, model[VERSION_ID_KEY]]];
|
||||
if (filePath) {
|
||||
NSData *rulesData = [self.dataExtractor dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:nil];
|
||||
NSDictionary *rules = [FBSDKTypeUtility JSONObjectWithData:rulesData options:0 error:nil];
|
||||
return rules;
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to get rules for usecase %@ from ml model, exception reason: %@", useCase, exception.reason);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSData *)getWeightsForKey:(NSString *)useCase
|
||||
{
|
||||
if (!_modelInfo || !_directoryPath) {
|
||||
return nil;
|
||||
}
|
||||
if ([useCase hasPrefix:MTMLKey]) {
|
||||
useCase = MTMLKey;
|
||||
}
|
||||
NSDictionary<NSString *, id> *model = [FBSDKTypeUtility dictionary:_modelInfo objectForKey:useCase ofType:NSObject.class];
|
||||
if (model && model[VERSION_ID_KEY]) {
|
||||
NSString *path = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.weights", useCase, model[VERSION_ID_KEY]]];
|
||||
if (!path) {
|
||||
return nil;
|
||||
}
|
||||
return [NSData dataWithContentsOfFile:path
|
||||
options:NSDataReadingMappedIfSafe
|
||||
error:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSArray *)getThresholdsForKey:(NSString *)useCase
|
||||
{
|
||||
if (!_modelInfo) {
|
||||
return nil;
|
||||
}
|
||||
NSDictionary<NSString *, id> *modelInfo = _modelInfo[useCase];
|
||||
if (!modelInfo) {
|
||||
return nil;
|
||||
}
|
||||
return modelInfo[THRESHOLDS_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - Integrity Inferencer method
|
||||
|
||||
// Used by the `integrityParametersProcessor` which holds a weak reference to this instance
|
||||
- (BOOL)processIntegrity:(nullable NSString *)param
|
||||
{
|
||||
NSString *integrityType = INTEGRITY_NONE;
|
||||
@try {
|
||||
if (param.length == 0 || _MTMLWeights.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
NSArray<NSString *> *integrityMapping = [self.class getIntegrityMapping];
|
||||
NSString *text = [FBSDKModelUtility normalizedText:param];
|
||||
const char *bytes = [text UTF8String];
|
||||
if ((int)strlen(bytes) == 0) {
|
||||
return false;
|
||||
}
|
||||
NSArray *thresholds = [FBSDKModelManager.shared getThresholdsForKey:MTMLTaskIntegrityDetectKey];
|
||||
if (thresholds.count != integrityMapping.count) {
|
||||
return false;
|
||||
}
|
||||
const fbsdk::MTensor &res = fbsdk::predictOnMTML("integrity_detect", bytes, _MTMLWeights, nullptr);
|
||||
const float *res_data = res.data();
|
||||
for (int i = 0; i < thresholds.count; i++) {
|
||||
if ((float)res_data[i] >= (float)[[FBSDKTypeUtility array:thresholds objectAtIndex:i] floatValue]) {
|
||||
integrityType = [FBSDKTypeUtility array:integrityMapping objectAtIndex:i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to process parameter for integrity usecase, exception reason: %@", exception.reason);
|
||||
}
|
||||
return ![integrityType isEqualToString:INTEGRITY_NONE];
|
||||
}
|
||||
|
||||
#pragma mark - SuggestedEvents Inferencer method
|
||||
|
||||
- (NSString *)processSuggestedEvents:(NSString *)textFeature denseData:(nullable float *)denseData
|
||||
{
|
||||
@try {
|
||||
NSArray<NSString *> *eventMapping = [FBSDKModelManager getSuggestedEventsMapping];
|
||||
if (textFeature.length == 0 || _MTMLWeights.size() == 0 || !denseData) {
|
||||
return SUGGESTED_EVENT_OTHER;
|
||||
}
|
||||
const char *bytes = [textFeature UTF8String];
|
||||
if ((int)strlen(bytes) == 0) {
|
||||
return SUGGESTED_EVENT_OTHER;
|
||||
}
|
||||
|
||||
NSArray *thresholds = [FBSDKModelManager.shared getThresholdsForKey:MTMLTaskAppEventPredKey];
|
||||
if (thresholds.count != eventMapping.count) {
|
||||
return SUGGESTED_EVENT_OTHER;
|
||||
}
|
||||
|
||||
const fbsdk::MTensor &res = fbsdk::predictOnMTML("app_event_pred", bytes, _MTMLWeights, denseData);
|
||||
const float *res_data = res.data();
|
||||
for (int i = 0; i < thresholds.count; i++) {
|
||||
if ((float)res_data[i] >= (float)[[FBSDKTypeUtility array:thresholds objectAtIndex:i] floatValue]) {
|
||||
return [FBSDKTypeUtility array:eventMapping objectAtIndex:i];
|
||||
}
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to process suggested events, exception reason: %@", exception.reason);
|
||||
}
|
||||
return SUGGESTED_EVENT_OTHER;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
+ (BOOL)isValidTimestamp:(NSDate *)timestamp
|
||||
{
|
||||
if (!timestamp) {
|
||||
return NO;
|
||||
}
|
||||
return ([[NSDate date] timeIntervalSinceDate:timestamp] < MODEL_REQUEST_INTERVAL);
|
||||
}
|
||||
|
||||
+ (void)processMTML
|
||||
{
|
||||
NSString *mtmlAssetUri = nil;
|
||||
long mtmlVersionId = 0;
|
||||
for (NSString *useCase in _modelInfo) {
|
||||
if (![useCase isKindOfClass:NSString.class]) {
|
||||
continue;
|
||||
}
|
||||
NSDictionary<NSString *, id> *model = _modelInfo[useCase];
|
||||
if ([useCase hasPrefix:MTMLKey]) {
|
||||
if (![model[ASSET_URI_KEY] isKindOfClass:NSString.class]
|
||||
|| ![model[VERSION_ID_KEY] isKindOfClass:NSNumber.class]) {
|
||||
continue;
|
||||
}
|
||||
mtmlAssetUri = model[ASSET_URI_KEY];
|
||||
long thisVersionId = [model[VERSION_ID_KEY] longValue];
|
||||
mtmlVersionId = thisVersionId > mtmlVersionId ? thisVersionId : mtmlVersionId;
|
||||
}
|
||||
}
|
||||
if (mtmlAssetUri && mtmlVersionId > 0) {
|
||||
[FBSDKTypeUtility dictionary:_modelInfo setObject:@{
|
||||
USE_CASE_KEY : MTMLKey,
|
||||
ASSET_URI_KEY : mtmlAssetUri,
|
||||
VERSION_ID_KEY : [NSNumber numberWithLong:mtmlVersionId],
|
||||
} forKey:MTMLKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)checkFeaturesAndExecuteForMTML
|
||||
{
|
||||
[self getModelAndRules:MTMLKey onSuccess:^() {
|
||||
NSData *data = [FBSDKModelManager.shared getWeightsForKey:MTMLKey];
|
||||
_MTMLWeights = [FBSDKModelParser parseWeightsData:data];
|
||||
if (![FBSDKModelParser validateWeights:_MTMLWeights forKey:MTMLKey]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self.featureChecker isEnabled:FBSDKFeatureSuggestedEvents]) {
|
||||
[self getModelAndRules:MTMLTaskAppEventPredKey onSuccess:^() {
|
||||
[FBSDKFeatureExtractor loadRulesForKey:MTMLTaskAppEventPredKey];
|
||||
[FBSDKSuggestedEventsIndexer.shared enable];
|
||||
}];
|
||||
}
|
||||
|
||||
if ([self.featureChecker isEnabled:FBSDKFeatureIntelligentIntegrity]) {
|
||||
[self getModelAndRules:MTMLTaskIntegrityDetectKey onSuccess:^() {
|
||||
[self setIntegrityParametersProcessor:[[FBSDKIntegrityManager alloc] initWithGateKeeperManager:FBSDKGateKeeperManager.class
|
||||
integrityProcessor:self]];
|
||||
[[self integrityParametersProcessor] enable];
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)getModelAndRules:(NSString *)useCaseKey
|
||||
onSuccess:(FBSDKDownloadCompletionBlock)handler
|
||||
{
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
|
||||
NSDictionary<NSString *, id> *model = [FBSDKTypeUtility dictionary:_modelInfo objectForKey:useCaseKey ofType:NSObject.class];
|
||||
if (!model || !_directoryPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
// download model asset only if not exist before
|
||||
NSString *assetUrlString = [FBSDKTypeUtility dictionary:model objectForKey:ASSET_URI_KEY ofType:NSObject.class];
|
||||
NSString *assetFilePath;
|
||||
if (assetUrlString.length > 0) {
|
||||
[self clearCacheForModel:model suffix:@".weights"];
|
||||
NSString *fileName = useCaseKey;
|
||||
if ([useCaseKey hasPrefix:MTMLKey]) {
|
||||
// all mtml tasks share the same weights file
|
||||
fileName = MTMLKey;
|
||||
}
|
||||
assetFilePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.weights", fileName, model[VERSION_ID_KEY]]];
|
||||
[self download:assetUrlString filePath:assetFilePath queue:queue group:group];
|
||||
}
|
||||
|
||||
// download rules
|
||||
NSString *rulesUrlString = [FBSDKTypeUtility dictionary:model objectForKey:RULES_URI_KEY ofType:NSObject.class];
|
||||
NSString *rulesFilePath = nil;
|
||||
// rules are optional and rulesUrlString may be empty
|
||||
if (rulesUrlString.length > 0) {
|
||||
[self clearCacheForModel:model suffix:@".rules"];
|
||||
rulesFilePath = [_directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.rules", useCaseKey, model[VERSION_ID_KEY]]];
|
||||
[self download:rulesUrlString filePath:rulesFilePath queue:queue group:group];
|
||||
}
|
||||
dispatch_group_notify(group,
|
||||
dispatch_get_main_queue(), ^{
|
||||
if (handler) {
|
||||
if ([fileManager fileExistsAtPath:assetFilePath] && (!rulesFilePath || [fileManager fileExistsAtPath:rulesFilePath])) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)clearCacheForModel:(NSDictionary<NSString *, id> *)model
|
||||
suffix:(NSString *)suffix
|
||||
{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *useCase = model[USE_CASE_KEY];
|
||||
NSString *version = model[VERSION_ID_KEY];
|
||||
NSArray<NSString *> *files = [fileManager contentsOfDirectoryAtPath:_directoryPath error:nil];
|
||||
NSString *prefixWithVersion = [NSString stringWithFormat:@"%@_%@", useCase, version];
|
||||
for (NSString *file in files) {
|
||||
if ([file hasSuffix:suffix] && [file hasPrefix:useCase] && ![file hasPrefix:prefixWithVersion]) {
|
||||
[fileManager removeItemAtPath:[_directoryPath stringByAppendingPathComponent:file] error:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)download:(NSString *)urlString
|
||||
filePath:(NSString *)filePath
|
||||
queue:(dispatch_queue_t)queue
|
||||
group:(dispatch_group_t)group
|
||||
{
|
||||
if (!filePath || [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
return;
|
||||
}
|
||||
dispatch_group_async(group,
|
||||
queue, ^{
|
||||
NSURL *url = [NSURL URLWithString:urlString];
|
||||
NSData *urlData = [NSData dataWithContentsOfURL:url];
|
||||
if (urlData) {
|
||||
[urlData writeToFile:filePath atomically:YES];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+ (nullable NSMutableDictionary<NSString *, id> *)convertToDictionary:(NSArray<NSDictionary<NSString *, id> *> *)models
|
||||
{
|
||||
if ([models count] == 0) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableDictionary<NSString *, id> *modelInfo = [NSMutableDictionary dictionary];
|
||||
for (NSDictionary<NSString *, id> *model in models) {
|
||||
if ([model isKindOfClass:NSDictionary.class]
|
||||
&& [model[USE_CASE_KEY] isKindOfClass:NSString.class]
|
||||
&& [self isPlistFormatDictionary:model]) {
|
||||
[modelInfo addEntriesFromDictionary:@{model[USE_CASE_KEY] : model}];
|
||||
}
|
||||
}
|
||||
|
||||
if (modelInfo.allKeys.count > 0) {
|
||||
return modelInfo;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isPlistFormatDictionary:(NSDictionary *)dictionary
|
||||
{
|
||||
__block BOOL isPlistFormat = YES;
|
||||
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {
|
||||
if (![key isKindOfClass:NSString.class]) {
|
||||
isPlistFormat = NO;
|
||||
*stop = YES;
|
||||
}
|
||||
if (![obj isKindOfClass:NSArray.class]
|
||||
&& ![obj isKindOfClass:NSDictionary.class]
|
||||
&& ![obj isKindOfClass:NSData.class]
|
||||
&& ![obj isKindOfClass:NSDate.class]
|
||||
&& ![obj isKindOfClass:NSNumber.class]
|
||||
&& ![obj isKindOfClass:NSString.class]) {
|
||||
isPlistFormat = NO;
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
return isPlistFormat;
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)getIntegrityMapping
|
||||
{
|
||||
return @[INTEGRITY_NONE, INTEGRITY_ADDRESS, INTEGRITY_HEALTH];
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)getSuggestedEventsMapping
|
||||
{
|
||||
return
|
||||
@[SUGGESTED_EVENT_OTHER,
|
||||
FBSDKAppEventNameCompletedRegistration,
|
||||
FBSDKAppEventNameAddedToCart,
|
||||
FBSDKAppEventNamePurchased,
|
||||
FBSDKAppEventNameInitiatedCheckout];
|
||||
}
|
||||
|
||||
#if DEBUG && FBTEST
|
||||
|
||||
+ (void)reset
|
||||
{
|
||||
if (enableNonce) {
|
||||
enableNonce = 0;
|
||||
}
|
||||
_directoryPath = nil;
|
||||
_modelInfo = nil;
|
||||
|
||||
self.shared.featureChecker = nil;
|
||||
self.shared.graphRequestFactory = nil;
|
||||
self.shared.fileManager = nil;
|
||||
self.shared.store = nil;
|
||||
self.shared.settings = nil;
|
||||
self.shared.dataExtractor = nil;
|
||||
}
|
||||
|
||||
+ (void)setModelInfo:(NSDictionary<NSString *, id> *)modelInfo
|
||||
{
|
||||
_modelInfo = [NSMutableDictionary dictionaryWithDictionary:modelInfo];
|
||||
}
|
||||
|
||||
+ (void)setDirectoryPath:(NSString *)directoryPath
|
||||
{
|
||||
_directoryPath = directoryPath;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKTensor.hpp"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(ModelParser)
|
||||
@interface FBSDKModelParser : NSObject
|
||||
|
||||
+ (std::unordered_map<std::string, fbsdk::MTensor>)parseWeightsData:(NSData *)weightsData;
|
||||
+ (bool)validateWeights:(std::unordered_map<std::string, fbsdk::MTensor>)weights forKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKModelParser.h"
|
||||
|
||||
#import "FBSDKCoreKitBasicsImport.h"
|
||||
#import "FBSDKMLMacros.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation FBSDKModelParser
|
||||
|
||||
+ (std::unordered_map<std::string, fbsdk::MTensor>)parseWeightsData:(NSData *)weightsData
|
||||
{
|
||||
std::unordered_map<std::string, fbsdk::MTensor> weights;
|
||||
if (!weightsData) {
|
||||
return weights;
|
||||
}
|
||||
|
||||
const void *data = weightsData.bytes;
|
||||
NSUInteger totalLength = weightsData.length;
|
||||
|
||||
if (totalLength < 4) {
|
||||
// Make sure data length is valid
|
||||
return weights;
|
||||
}
|
||||
try {
|
||||
int length;
|
||||
memcpy(&length, data, 4);
|
||||
if (length + 4 > totalLength) {
|
||||
// Make sure data length is valid
|
||||
return weights;
|
||||
}
|
||||
|
||||
char *json = (char *)data + 4;
|
||||
NSDictionary<NSString *, id> *info = [FBSDKTypeUtility JSONObjectWithData:[NSData dataWithBytes:json length:length]
|
||||
options:0
|
||||
error:nil];
|
||||
NSArray<NSString *> *keys = [[info allKeys] sortedArrayUsingComparator:^NSComparisonResult (NSString *key1, NSString *key2) {
|
||||
return [key1 compare:key2];
|
||||
}];
|
||||
|
||||
int totalFloats = 0;
|
||||
float *floats = (float *)(json + length);
|
||||
NSDictionary<NSString *, NSString *> *keysMapping = [self getKeysMapping];
|
||||
for (NSString *key in keys) {
|
||||
NSString *finalKey = key;
|
||||
NSString *mapping = [FBSDKTypeUtility dictionary:keysMapping objectForKey:key ofType:NSObject.class];
|
||||
if (mapping) {
|
||||
finalKey = mapping;
|
||||
}
|
||||
std::string s_name([finalKey UTF8String]);
|
||||
|
||||
std::vector<int> v_shape;
|
||||
NSArray<NSString *> *shape = [FBSDKTypeUtility dictionary:info objectForKey:key ofType:NSObject.class];
|
||||
int count = 1;
|
||||
for (NSNumber *_s in shape) {
|
||||
int i = [_s intValue];
|
||||
v_shape.push_back(i);
|
||||
count *= i;
|
||||
}
|
||||
|
||||
totalFloats += count;
|
||||
|
||||
if ((4 + length + totalFloats * 4) > totalLength) {
|
||||
// Make sure data length is valid
|
||||
break;
|
||||
}
|
||||
fbsdk::MTensor tensor(v_shape);
|
||||
memcpy(tensor.mutable_data(), floats, sizeof(float) * count);
|
||||
floats += count;
|
||||
|
||||
weights[s_name] = tensor;
|
||||
}
|
||||
} catch (const std::exception &e) {}
|
||||
|
||||
return weights;
|
||||
}
|
||||
|
||||
+ (bool)validateWeights:(std::unordered_map<std::string, fbsdk::MTensor>)weights forKey:(NSString *)key
|
||||
{
|
||||
NSMutableDictionary<NSString *, NSArray *> *weightsInfoDict = [NSMutableDictionary new];
|
||||
if ([key hasPrefix:MTMLKey]) {
|
||||
[weightsInfoDict addEntriesFromDictionary:[self getMTMLWeightsInfo]];
|
||||
}
|
||||
return [self checkWeights:weights withExpectedInfo:weightsInfoDict];
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
|
||||
+ (NSDictionary<NSString *, NSString *> *)getKeysMapping
|
||||
{
|
||||
return @{
|
||||
@"embedding.weight" : @"embed.weight",
|
||||
@"dense1.weight" : @"fc1.weight",
|
||||
@"dense2.weight" : @"fc2.weight",
|
||||
@"dense3.weight" : @"fc3.weight",
|
||||
@"dense1.bias" : @"fc1.bias",
|
||||
@"dense2.bias" : @"fc2.bias",
|
||||
@"dense3.bias" : @"fc3.bias"
|
||||
};
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, NSArray *> *)getMTMLWeightsInfo
|
||||
{
|
||||
return @{
|
||||
@"embed.weight" : @[@256, @32],
|
||||
@"convs.0.weight" : @[@32, @32, @3],
|
||||
@"convs.0.bias" : @[@32],
|
||||
@"convs.1.weight" : @[@64, @32, @3],
|
||||
@"convs.1.bias" : @[@64],
|
||||
@"convs.2.weight" : @[@64, @64, @3],
|
||||
@"convs.2.bias" : @[@64],
|
||||
@"fc1.weight" : @[@128, @190],
|
||||
@"fc1.bias" : @[@128],
|
||||
@"fc2.weight" : @[@64, @128],
|
||||
@"fc2.bias" : @[@64],
|
||||
@"integrity_detect.weight" : @[@3, @64],
|
||||
@"integrity_detect.bias" : @[@3],
|
||||
@"app_event_pred.weight" : @[@5, @64],
|
||||
@"app_event_pred.bias" : @[@5]
|
||||
};
|
||||
}
|
||||
|
||||
+ (bool)checkWeights:(std::unordered_map<std::string, fbsdk::MTensor>)weights
|
||||
withExpectedInfo:(NSDictionary<NSString *, NSArray *> *)weightsInfoDict
|
||||
{
|
||||
if (weightsInfoDict.count != weights.size()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
for (NSString *key in weightsInfoDict) {
|
||||
if (weights.count(std::string([key UTF8String])) == 0) {
|
||||
return false;
|
||||
}
|
||||
fbsdk::MTensor tensor = weights[std::string([key UTF8String])];
|
||||
const std::vector<int> &actualSize = tensor.sizes();
|
||||
NSArray *expectedSize = weightsInfoDict[key];
|
||||
if (actualSize.size() != expectedSize.count) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < expectedSize.count; i++) {
|
||||
if ((int)actualSize[i] != (int)[[FBSDKTypeUtility array:expectedSize objectAtIndex:i] intValue]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
#include "FBSDKTensor.hpp"
|
||||
|
||||
#define SEQ_LEN 128
|
||||
#define DENSE_FEATURE_LEN 30
|
||||
|
||||
namespace fbsdk {
|
||||
static void relu(MTensor &x)
|
||||
{
|
||||
float min = 0;
|
||||
float max = FLT_MAX;
|
||||
float *x_data = x.mutable_data();
|
||||
vDSP_vclip(x_data, 1, &min, &max, x_data, 1, x.count());
|
||||
}
|
||||
|
||||
static void flatten(MTensor &x, int start_dim)
|
||||
{
|
||||
const std::vector<int> &shape = x.sizes();
|
||||
std::vector<int> new_shape;
|
||||
for (int i = 0; i < start_dim; i++) {
|
||||
new_shape.push_back(shape[i]);
|
||||
}
|
||||
int count = 1;
|
||||
for (int i = start_dim; i < shape.size(); i++) {
|
||||
count *= shape[i];
|
||||
}
|
||||
new_shape.push_back(count);
|
||||
x.Reshape(new_shape);
|
||||
}
|
||||
|
||||
static MTensor concatenate(std::vector<MTensor *> &tensors)
|
||||
{
|
||||
int n_examples = tensors[0]->size(0);
|
||||
int count = 0;
|
||||
for (int i = 0; i < tensors.size(); i++) {
|
||||
count += tensors[i]->size(1);
|
||||
}
|
||||
MTensor y({n_examples, count});
|
||||
float *y_data = y.mutable_data();
|
||||
for (int i = 0; i < tensors.size(); i++) {
|
||||
int this_count = (int)tensors[i]->size(1);
|
||||
const float *this_data = tensors[i]->data();
|
||||
for (int n = 0; n < n_examples; n++) {
|
||||
memcpy(y_data + n * count, this_data + n * this_count, this_count * sizeof(float));
|
||||
}
|
||||
y_data += this_count;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void softmax(MTensor &x)
|
||||
{
|
||||
int n_examples = x.size(0);
|
||||
int n_channel = x.size(1);
|
||||
float *x_data = x.mutable_data();
|
||||
float max;
|
||||
float sum;
|
||||
for (int n = 0; n < n_examples; n++) {
|
||||
vDSP_maxv(x_data, 1, &max, n_channel);
|
||||
max = -max;
|
||||
vDSP_vsadd(x_data, 1, &max, x_data, 1, n_channel);
|
||||
vvexpf(x_data, x_data, &n_channel);
|
||||
vDSP_sve(x_data, 1, &sum, n_channel);
|
||||
vDSP_vsdiv(x_data, 1, &sum, x_data, 1, n_channel);
|
||||
x_data += n_channel;
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<int> vectorize(const char *texts, const int seq_length)
|
||||
{
|
||||
int str_len = (int)strlen(texts);
|
||||
std::vector<int> vec(seq_length, 0);
|
||||
for (int i = 0; i < seq_length; i++) {
|
||||
if (i < str_len) {
|
||||
vec[i] = static_cast<unsigned char>(texts[i]);
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
static MTensor embedding(const char *texts, const int seq_length, const MTensor &w)
|
||||
{
|
||||
// TODO: T65152708 support batch prediction
|
||||
const std::vector<int> &vec = vectorize(texts, seq_length);
|
||||
int n_examples = 1;
|
||||
int embedding_size = w.size(1);
|
||||
MTensor y({n_examples, seq_length, embedding_size});
|
||||
const float *w_data = w.data();
|
||||
float *y_data = y.mutable_data();
|
||||
for (int i = 0; i < n_examples; i++) {
|
||||
for (int j = 0; j < seq_length; j++) {
|
||||
memcpy(y_data, w_data + vec[i * seq_length + j] * embedding_size, (size_t)(embedding_size * sizeof(float)));
|
||||
y_data += embedding_size;
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
x shape: n_examples, in_vector_size
|
||||
w shape: in_vector_size, out_vector_size
|
||||
b shape: out_vector_size
|
||||
return shape: n_examples, out_vector_size
|
||||
*/
|
||||
static MTensor dense(const MTensor &x, const MTensor &w, const MTensor &b)
|
||||
{
|
||||
int n_examples = x.size(0);
|
||||
int in_vector_size = x.size(1);
|
||||
int out_vector_size = w.size(1);
|
||||
MTensor y({n_examples, out_vector_size});
|
||||
float *y_data = y.mutable_data();
|
||||
const float *b_data = b.data();
|
||||
vDSP_mmul(x.data(), 1, w.data(), 1, y_data, 1, n_examples, out_vector_size, in_vector_size);
|
||||
for (int i = 0; i < out_vector_size; i++) {
|
||||
vDSP_vsadd(y_data + i, out_vector_size, b_data + i, y_data + i, out_vector_size, n_examples);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
x shape: n_examples, seq_len, input_size
|
||||
w shape: kernel_size, input_size, output_size
|
||||
return shape: n_examples, seq_len - kernel_size + 1, output_size
|
||||
*/
|
||||
static MTensor conv1D(const MTensor &x, const MTensor &w)
|
||||
{
|
||||
int n_examples = x.size(0);
|
||||
int seq_len = x.size(1);
|
||||
int input_size = x.size(2);
|
||||
int kernel_size = w.size(0);
|
||||
int output_size = w.size(2);
|
||||
MTensor y({n_examples, seq_len - kernel_size + 1, output_size});
|
||||
MTensor temp_x({kernel_size, input_size});
|
||||
MTensor temp_w({kernel_size, input_size});
|
||||
const float *x_data = x.data();
|
||||
const float *w_data = w.data();
|
||||
float *y_data = y.mutable_data();
|
||||
float *temp_x_data = temp_x.mutable_data();
|
||||
float *temp_w_data = temp_w.mutable_data();
|
||||
float sum;
|
||||
for (int n = 0; n < n_examples; n++) {
|
||||
for (int o = 0; o < output_size; o++) {
|
||||
for (int i = 0; i < seq_len - kernel_size + 1; i++) {
|
||||
for (int m = 0; m < kernel_size; m++) {
|
||||
for (int k = 0; k < input_size; k++) {
|
||||
temp_x_data[m * input_size + k] = x_data[n * (seq_len * input_size) + (m + i) * input_size + k];
|
||||
temp_w_data[m * input_size + k] = w_data[(m * input_size + k) * output_size + o];
|
||||
}
|
||||
}
|
||||
vDSP_dotpr(temp_x_data, 1, temp_w_data, 1, &sum, (size_t)(kernel_size * input_size));
|
||||
y_data[(n * (output_size * (seq_len - kernel_size + 1)) + i * output_size + o)] = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
input shape: n_examples, len, n_channel
|
||||
return shape: n_examples, len - pool_size + 1, n_channel
|
||||
*/
|
||||
static MTensor maxPool1D(const MTensor &x, const int pool_size)
|
||||
{
|
||||
int n_examples = x.size(0);
|
||||
int input_len = x.size(1);
|
||||
int n_channel = x.size(2);
|
||||
int output_len = input_len - pool_size + 1;
|
||||
MTensor y({n_examples, output_len, n_channel});
|
||||
const float *x_data = x.data();
|
||||
float *y_data = y.mutable_data();
|
||||
for (int n = 0; n < n_examples; n++) {
|
||||
for (int c = 0; c < n_channel; c++) {
|
||||
for (int i = 0; i < output_len; i++) {
|
||||
float this_max = -FLT_MAX;
|
||||
for (int r = i; r < i + pool_size; r++) {
|
||||
this_max = fmax(this_max, x_data[n * (n_channel * input_len) + r * n_channel + c]);
|
||||
}
|
||||
y_data[n * (n_channel * output_len) + i * n_channel + c] = this_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
input shape: m, n
|
||||
return shape: n, m
|
||||
*/
|
||||
static MTensor transpose2D(const MTensor &x)
|
||||
{
|
||||
int m = x.size(0);
|
||||
int n = x.size(1);
|
||||
MTensor y({n, m});
|
||||
float *y_data = y.mutable_data();
|
||||
const float *x_data = x.data();
|
||||
for (int i = 0; i < m; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
y_data[j * m + i] = x_data[i * n + j];
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
input shape: m, n, p
|
||||
return shape: p, n, m
|
||||
*/
|
||||
static MTensor transpose3D(const MTensor &x)
|
||||
{
|
||||
int m = x.size(0);
|
||||
int n = x.size(1);
|
||||
int p = x.size(2);
|
||||
MTensor y({p, n, m});
|
||||
float *y_data = y.mutable_data();
|
||||
const float *x_data = x.data();
|
||||
for (int i = 0; i < m; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
for (int k = 0; k < p; k++) {
|
||||
y_data[k * m * n + j * m + i] = x_data[i * n * p + j * p + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void addmv(MTensor &y, const MTensor &x)
|
||||
{
|
||||
int m = y.size(0);
|
||||
int n = y.size(1);
|
||||
int p = y.size(2);
|
||||
float *y_data = y.mutable_data();
|
||||
const float *x_data = x.data();
|
||||
for (int i = 0; i < p; i++) {
|
||||
vDSP_vsadd(y_data + i, p, x_data + i, y_data + i, p, m * n);
|
||||
}
|
||||
}
|
||||
|
||||
static MTensor getDenseTensor(const float *df)
|
||||
{
|
||||
MTensor dense_tensor({1, DENSE_FEATURE_LEN});
|
||||
if (df) {
|
||||
memcpy(dense_tensor.mutable_data(), df, DENSE_FEATURE_LEN * sizeof(float));
|
||||
} else {
|
||||
memset(dense_tensor.mutable_data(), 0, DENSE_FEATURE_LEN * sizeof(float));
|
||||
}
|
||||
return dense_tensor;
|
||||
}
|
||||
|
||||
static MTensor predictOnMTML(const std::string task, const char *texts, const std::unordered_map<std::string, MTensor> &weights, const float *df)
|
||||
{
|
||||
MTensor dense_tensor = getDenseTensor(df);
|
||||
std::string final_layer_weight_key = task + ".weight";
|
||||
std::string final_layer_bias_key = task + ".bias";
|
||||
|
||||
const MTensor &embed_t = weights.at("embed.weight");
|
||||
const MTensor &conv0w_t = weights.at("convs.0.weight");
|
||||
const MTensor &conv1w_t = weights.at("convs.1.weight");
|
||||
const MTensor &conv2w_t = weights.at("convs.2.weight");
|
||||
const MTensor &conv0b_t = weights.at("convs.0.bias");
|
||||
const MTensor &conv1b_t = weights.at("convs.1.bias");
|
||||
const MTensor &conv2b_t = weights.at("convs.2.bias");
|
||||
const MTensor &fc1w_t = weights.at("fc1.weight"); // (128, 190)
|
||||
const MTensor &fc1b_t = weights.at("fc1.bias"); // 128
|
||||
const MTensor &fc2w_t = weights.at("fc2.weight"); // (64, 128)
|
||||
const MTensor &fc2b_t = weights.at("fc2.bias"); // 64
|
||||
const MTensor &final_layer_weight_t = weights.at(final_layer_weight_key); // (2, 64) or (5, 64)
|
||||
const MTensor &final_layer_bias_t = weights.at(final_layer_bias_key); // 2 or 5
|
||||
|
||||
const MTensor &convs_0_weight = transpose3D(conv0w_t);
|
||||
const MTensor &convs_1_weight = transpose3D(conv1w_t);
|
||||
const MTensor &convs_2_weight = transpose3D(conv2w_t);
|
||||
const MTensor &fc1_weight = transpose2D(fc1w_t);
|
||||
const MTensor &fc2_weight = transpose2D(fc2w_t);
|
||||
const MTensor &final_layer_weight = transpose2D(final_layer_weight_t);
|
||||
|
||||
// embedding
|
||||
const MTensor &embed_x = embedding(texts, SEQ_LEN, embed_t);
|
||||
|
||||
// conv0
|
||||
MTensor c0 = conv1D(embed_x, convs_0_weight); // (1, 126, 32)
|
||||
addmv(c0, conv0b_t);
|
||||
relu(c0);
|
||||
|
||||
// conv1
|
||||
MTensor c1 = conv1D(c0, convs_1_weight); // (1, 124, 64)
|
||||
addmv(c1, conv1b_t);
|
||||
relu(c1);
|
||||
c1 = maxPool1D(c1, 2); // (1, 123, 64)
|
||||
|
||||
// conv2
|
||||
MTensor c2 = conv1D(c1, convs_2_weight); // (1, 121, 64)
|
||||
addmv(c2, conv2b_t);
|
||||
relu(c2);
|
||||
|
||||
// max pooling
|
||||
MTensor ca = maxPool1D(c0, c0.size(1));
|
||||
MTensor cb = maxPool1D(c1, c1.size(1));
|
||||
MTensor cc = maxPool1D(c2, c2.size(1));
|
||||
|
||||
// concatenate
|
||||
flatten(ca, 1);
|
||||
flatten(cb, 1);
|
||||
flatten(cc, 1);
|
||||
std::vector<MTensor *> concat_tensors { &ca, &cb, &cc, &dense_tensor };
|
||||
const MTensor &concat = concatenate(concat_tensors);
|
||||
|
||||
// dense + relu
|
||||
MTensor dense1_x = dense(concat, fc1_weight, fc1b_t);
|
||||
relu(dense1_x);
|
||||
MTensor dense2_x = dense(dense1_x, fc2_weight, fc2b_t);
|
||||
relu(dense2_x);
|
||||
MTensor final_layer_dense_x = dense(dense2_x, final_layer_weight, final_layer_bias_t);
|
||||
softmax(final_layer_dense_x);
|
||||
return final_layer_dense_x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(ModelUtility)
|
||||
@interface FBSDKModelUtility : NSObject
|
||||
|
||||
+ (NSString *)normalizedText:(NSString *)text;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKModelUtility.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@implementation FBSDKModelUtility : NSObject
|
||||
|
||||
+ (NSString *)normalizedText:(NSString *)text
|
||||
{
|
||||
NSMutableArray *tokens = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy];
|
||||
[tokens removeObject:@""];
|
||||
return [tokens componentsJoinedByString:@" "];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
// minimal aten implementation
|
||||
#define MAT_ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
namespace fbsdk {
|
||||
static void *MAllocateMemory(size_t nbytes)
|
||||
{
|
||||
void *ptr = nullptr;
|
||||
assert(nbytes > 0);
|
||||
#ifdef __ANDROID__
|
||||
ptr = memalign(64, nbytes);
|
||||
#else
|
||||
const int ret = posix_memalign(&ptr, 64, nbytes);
|
||||
(void)ret;
|
||||
assert(ret == 0);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void MFreeMemory(void *ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
class MTensor {
|
||||
public:
|
||||
MTensor() :
|
||||
storage_(nullptr),
|
||||
sizes_(),
|
||||
strides_(),
|
||||
capacity_(0) {};
|
||||
explicit MTensor(const std::vector<int> &sizes)
|
||||
{
|
||||
std::vector<int> strides = std::vector<int>(sizes.size());
|
||||
strides[strides.size() - 1] = 1;
|
||||
for (int i = static_cast<int32_t>(strides.size()) - 2; i >= 0; --i) {
|
||||
strides[i] = strides[i + 1] * sizes[i + 1];
|
||||
}
|
||||
strides_ = strides;
|
||||
sizes_ = sizes;
|
||||
capacity_ = 1;
|
||||
for (int size : sizes) {
|
||||
capacity_ *= size;
|
||||
}
|
||||
storage_ = std::shared_ptr<void>(MAllocateMemory((size_t)capacity_ * sizeof(float)), MFreeMemory);
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE int count() const
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE int size(int dim) const
|
||||
{
|
||||
return sizes_[dim];
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE const std::vector<int> &sizes() const
|
||||
{
|
||||
return sizes_;
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE const std::vector<int> &strides() const
|
||||
{
|
||||
return strides_;
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE const float *data() const
|
||||
{
|
||||
return (const float *)(storage_.get());
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE float *mutable_data()
|
||||
{
|
||||
return static_cast<float *>(storage_.get());
|
||||
}
|
||||
|
||||
MAT_ALWAYS_INLINE void Reshape(const std::vector<int> &sizes)
|
||||
{
|
||||
int count = 1;
|
||||
for (int i = 0; i < sizes.size(); i++) {
|
||||
count *= sizes[i];
|
||||
}
|
||||
if (count > capacity_) {
|
||||
capacity_ = count;
|
||||
storage_.reset(MAllocateMemory((size_t)capacity_ * sizeof(float)), MFreeMemory);
|
||||
}
|
||||
sizes_ = sizes;
|
||||
}
|
||||
|
||||
private:
|
||||
int capacity_;
|
||||
std::vector<int> sizes_;
|
||||
std::vector<int> strides_;
|
||||
std::shared_ptr<void> storage_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// An internal protocol used to describe a type that can update a value
|
||||
NS_SWIFT_NAME(ConversionValueUpdating)
|
||||
@protocol FBSDKConversionValueUpdating
|
||||
|
||||
+ (void)updateConversionValue:(NSInteger)conversionValue;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user