diff --git a/FBAEMKit/FBAEMKit.xcodeproj/project.pbxproj b/FBAEMKit/FBAEMKit.xcodeproj/project.pbxproj index 4dd71604f6..5220b2e3c2 100644 --- a/FBAEMKit/FBAEMKit.xcodeproj/project.pbxproj +++ b/FBAEMKit/FBAEMKit.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 474EFD6AB5988C7361FA0E15 /* FBAEMRule.h in Headers */ = {isa = PBXBuildFile; fileRef = F9ACAD4216D72E4122034CB9 /* FBAEMRule.h */; }; 499A9AE9074800B75AAA76E5 /* FBAEMRequestBody.m in Sources */ = {isa = PBXBuildFile; fileRef = 69F89ACD1C21793D31565351 /* FBAEMRequestBody.m */; }; 5630949F273EEA4D536894D9 /* SampleAEMData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4177A5533D7CFF825F97ECA0 /* SampleAEMData.swift */; }; + 565CE9AC0313BEDA111FA043 /* FBSKAdNetworkReporting.h in Headers */ = {isa = PBXBuildFile; fileRef = 153B4C403EFEC54B3E5A0203 /* FBSKAdNetworkReporting.h */; settings = {ATTRIBUTES = (Public, ); }; }; 567D930E785504CA4A62B0ED /* FBAEMAdvertiserSingleEntryRule.h in Headers */ = {isa = PBXBuildFile; fileRef = EA8FABFB4D409A28FC534768 /* FBAEMAdvertiserSingleEntryRule.h */; }; 599163559FEC9EF5DB917435 /* FBAEMNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 8060F398EB7F033AD9F1D6AA /* FBAEMNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5A6B01E84A3CDA4D6B39BBA2 /* FBAEMInvocation.m in Sources */ = {isa = PBXBuildFile; fileRef = BF14F7D688B16F470687F043 /* FBAEMInvocation.m */; }; @@ -80,6 +81,7 @@ CB0B635973208B511A062FB5 /* FBAEMReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8554100C2E72F8997D18A1D1 /* FBAEMReporter.h */; settings = {ATTRIBUTES = (Public, ); }; }; CC7B4787404ACCEE7D6B6E8F /* FBAEMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = BDDBCE1CDBD3488598FE265C /* FBAEMKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; CF815EBD130A652187ED6DA7 /* FBAEMRequestBody.m in Sources */ = {isa = PBXBuildFile; fileRef = 69F89ACD1C21793D31565351 /* FBAEMRequestBody.m */; }; + D006673B24F89813D040D9E6 /* TestSKAdNetworkRepoter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B11CF6827A713779EB0D1E /* TestSKAdNetworkRepoter.swift */; }; D14F628136A6491B9258692D /* FBAEMNetworker.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F60F57E8A966C73543C6E7 /* FBAEMNetworker.m */; }; D175879013592F781F627ED5 /* FBAEMEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = C2368B332ED43BBAF2493859 /* FBAEMEvent.m */; }; D5636656757EDC3E1CD3560D /* FBAEMAdvertiserRuleFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 931238348E95CD28C59333BD /* FBAEMAdvertiserRuleFactoryTests.swift */; }; @@ -91,6 +93,7 @@ E87F536334B42D42EC3452A2 /* FBAEMConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = CAAE2115CC5A03D37FABC343 /* FBAEMConfiguration.h */; }; F1104751E43FE9AB97E4AABA /* FBCoreKitBasicsImportForAEMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0954C8A4F08D670E5928AA17 /* FBCoreKitBasicsImportForAEMKit.h */; }; F317CC64B9EA550F74510E37 /* FBAEMAdvertiserRuleFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 308D372D24FA9EC87811E74C /* FBAEMAdvertiserRuleFactory.m */; }; + F581E474473D84C5DA5D3B98 /* FBSKAdNetworkReporting.h in Headers */ = {isa = PBXBuildFile; fileRef = 153B4C403EFEC54B3E5A0203 /* FBSKAdNetworkReporting.h */; settings = {ATTRIBUTES = (Public, ); }; }; FB2ED4B8A9D7F7BEFA0891DA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55624583B4F08EB7CA742BFA /* UIKit.framework */; }; FC81960674090AD38CABBA41 /* FBAEMReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = F9CB68BCAEA3667ED30FF01A /* FBAEMReporter.m */; }; FC96D3627E3CC140C8B64E37 /* AEMConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCF97D130F84518CF735123 /* AEMConfigurationTests.swift */; }; @@ -172,11 +175,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 02B11CF6827A713779EB0D1E /* TestSKAdNetworkRepoter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSKAdNetworkRepoter.swift; sourceTree = ""; }; 0485B2A82D1087BAD40DEF28 /* TestAEMNetworker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAEMNetworker.swift; sourceTree = ""; }; 06D636174F633A8977B80DC4 /* FBAEMEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FBAEMEventTests.swift; sourceTree = ""; }; 08EA45F62800A6094DE6FE23 /* FBAEMKitTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FBAEMKitTests.xcconfig; sourceTree = ""; }; 0954C8A4F08D670E5928AA17 /* FBCoreKitBasicsImportForAEMKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBCoreKitBasicsImportForAEMKit.h; sourceTree = ""; }; 0B2DB862A2534E9BCF64D92F /* TestTools */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TestTools; path = ../TestTools/TestTools.xcodeproj; sourceTree = ""; }; + 153B4C403EFEC54B3E5A0203 /* FBSKAdNetworkReporting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSKAdNetworkReporting.h; sourceTree = ""; }; 200CAFDF7052329542187DCB /* FBSDKCoreKit_Basics */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FBSDKCoreKit_Basics; path = ../FBSDKCoreKit_Basics/FBSDKCoreKit_Basics.xcodeproj; sourceTree = ""; }; 27B0E5D3B1EF8C9BA530BC3D /* FBAEMAdvertiserMultiEntryRule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAEMAdvertiserMultiEntryRule.m; sourceTree = ""; }; 2D50412F133CE2A6A7D5150D /* SampleAEMInvocations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAEMInvocations.swift; sourceTree = ""; }; @@ -296,6 +301,7 @@ 7BE582199B8FBA1789FEC3E0 /* SampleAEMSingleEntryRules.swift */, 0485B2A82D1087BAD40DEF28 /* TestAEMNetworker.swift */, 8D1A8648B7AF86852325E167 /* TestInvocation.swift */, + 02B11CF6827A713779EB0D1E /* TestSKAdNetworkRepoter.swift */, ); path = Helpers; sourceTree = ""; @@ -408,6 +414,7 @@ BDDBCE1CDBD3488598FE265C /* FBAEMKit.h */, 8060F398EB7F033AD9F1D6AA /* FBAEMNetworking.h */, 8554100C2E72F8997D18A1D1 /* FBAEMReporter.h */, + 153B4C403EFEC54B3E5A0203 /* FBSKAdNetworkReporting.h */, ); name = include; path = ../Sources/FBAEMKit/include; @@ -437,6 +444,7 @@ 5B97E50781C011C42447373D /* FBAEMRequestBody.h in Headers */, 191858C71EF3965CC6068391 /* FBAEMRule.h in Headers */, F1104751E43FE9AB97E4AABA /* FBCoreKitBasicsImportForAEMKit.h in Headers */, + F581E474473D84C5DA5D3B98 /* FBSKAdNetworkReporting.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -461,6 +469,7 @@ A04003FA9F804ECE55FEBDBD /* FBAEMRequestBody.h in Headers */, 474EFD6AB5988C7361FA0E15 /* FBAEMRule.h in Headers */, B3CD5E0EB8287EF16619F04D /* FBCoreKitBasicsImportForAEMKit.h in Headers */, + 565CE9AC0313BEDA111FA043 /* FBSKAdNetworkReporting.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -699,6 +708,7 @@ 7C15398E0B92F0A99548AA17 /* SampleAEMSingleEntryRules.swift in Sources */, C31C49F965C147E171E9F7AF /* TestAEMNetworker.swift in Sources */, 92A75FC874F8470A8B25D944 /* TestInvocation.swift in Sources */, + D006673B24F89813D040D9E6 /* TestSKAdNetworkRepoter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FBAEMKit/FBAEMKitTests/FBAEM+Testing.h b/FBAEMKit/FBAEMKitTests/FBAEM+Testing.h index 3a767db265..0c04916385 100644 --- a/FBAEMKit/FBAEMKitTests/FBAEM+Testing.h +++ b/FBAEMKit/FBAEMKitTests/FBAEM+Testing.h @@ -118,6 +118,8 @@ NS_ASSUME_NONNULL_BEGIN @property (class, nonatomic) NSMutableArray *invocations; @property (class, nonatomic) NSMutableArray *completionBlocks; @property (class, nonatomic) NSString *reportFilePath; +@property (class, nonatomic) id networker; +@property (class, nonatomic) id reporter; + (void)enable; diff --git a/FBAEMKit/FBAEMKitTests/FBAEMReporterTests.swift b/FBAEMKit/FBAEMKitTests/FBAEMReporterTests.swift index 37f1cc14ab..d57c1994ce 100644 --- a/FBAEMKit/FBAEMKitTests/FBAEMReporterTests.swift +++ b/FBAEMKit/FBAEMKitTests/FBAEMReporterTests.swift @@ -48,6 +48,7 @@ class FBAEMReporterTests: XCTestCase { } let networker = TestAEMNetworker() + let reporter = TestSKAdNetworkReporter() let date = Calendar.current.date( byAdding: .day, value: -2, @@ -67,7 +68,7 @@ class FBAEMReporterTests: XCTestCase { super.setUp() removeReportFile() - AEMReporter.configure(withNetworker: networker, appID: "123") + AEMReporter.configure(withNetworker: networker, appID: "123", reporter: reporter) // Actual queue doesn't matter as long as it's not the same as the designated queue name in the class AEMReporter.queue = DispatchQueue(label: name, qos: .background) AEMReporter.isEnabled = true @@ -89,6 +90,19 @@ class FBAEMReporterTests: XCTestCase { XCTAssertTrue(AEMReporter.isEnabled, "AEM Report should be enabled") } + func testConfigure() { + XCTAssertEqual( + networker, + AEMReporter.networker as? TestAEMNetworker, + "Should configure with the expected AEM networker" + ) + XCTAssertEqual( + reporter, + AEMReporter.reporter as? TestSKAdNetworkReporter, + "Should configure with the expected SKAdNetwork reporter" + ) + } + func testParseURL() { var url: URL? XCTAssertNil(AEMReporter.parseURL(url)) diff --git a/FBAEMKit/FBAEMKitTests/Helpers/TestSKAdNetworkRepoter.swift b/FBAEMKit/FBAEMKitTests/Helpers/TestSKAdNetworkRepoter.swift new file mode 100644 index 0000000000..9795ea4d49 --- /dev/null +++ b/FBAEMKit/FBAEMKitTests/Helpers/TestSKAdNetworkRepoter.swift @@ -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. + +public class TestSKAdNetworkReporter: NSObject, SKAdNetworkReporting { + + public var cutOff: Bool = false + public var reportingEvents: Set = [] + + public func shouldCutoff() -> Bool { + cutOff + } + + public func isReportingEvent(_ event: String) -> Bool { + reportingEvents.contains(event) + } +} diff --git a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/SKAdNetwork/FBSDKSKAdNetworkReporter.h b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/SKAdNetwork/FBSDKSKAdNetworkReporter.h index ebffe42069..c868719634 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/SKAdNetwork/FBSDKSKAdNetworkReporter.h +++ b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/SKAdNetwork/FBSDKSKAdNetworkReporter.h @@ -22,10 +22,16 @@ #import +#if defined FBSDKCOCOAPODS || defined BUCK + #import "FBSDKCoreKitAEMImport.h" +#else + #import "../../../Internal/FBSDKCoreKitAEMImport.h" +#endif + NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(SKAdNetworkReporter) -@interface FBSDKSKAdNetworkReporter : NSObject +@interface FBSDKSKAdNetworkReporter : NSObject - (void)enable; diff --git a/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m b/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m index decd19d849..ca4201481b 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m +++ b/FBSDKCoreKit/FBSDKCoreKit/FBSDKApplicationDelegate.m @@ -733,7 +733,9 @@ - (void)configureDependencies conversionValueUpdatable:SKAdNetwork.class]; } if (@available(iOS 14.0, *)) { - [FBAEMReporter configureWithNetworker:[FBSDKAEMNetworker new] appID:[FBSDKSettings appID]]; + [FBAEMReporter configureWithNetworker:[FBSDKAEMNetworker new] + appID:[FBSDKSettings appID] + reporter:self.skAdNetworkReporter]; } [FBSDKProfile configureWithStore:store accessTokenProvider:FBSDKAccessToken.class diff --git a/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKCoreKitAEMImport.h b/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKCoreKitAEMImport.h index c8f046a338..29fd4226ad 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKCoreKitAEMImport.h +++ b/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKCoreKitAEMImport.h @@ -25,6 +25,7 @@ #else #import #import + #import #endif #endif diff --git a/Sources/FBAEMKit/FBAEMReporter.m b/Sources/FBAEMKit/FBAEMReporter.m index 1e76db4eb2..8ef0612722 100644 --- a/Sources/FBAEMKit/FBAEMReporter.m +++ b/Sources/FBAEMKit/FBAEMReporter.m @@ -62,6 +62,7 @@ static NSDate *g_configRefreshTimestamp; static NSMutableArray *g_completionBlocks; static _Nullable id _networker = nil; +static _Nullable id _reporter = nil; static NSString *_appId; @implementation FBAEMReporter @@ -70,10 +71,18 @@ @implementation FBAEMReporter + (void)configureWithNetworker:(nullable id)networker appID:(NSString *)appID +{ + [self configureWithNetworker:networker appID:appID reporter:nil]; +} + ++ (void)configureWithNetworker:(nullable id)networker + appID:(NSString *)appID + reporter:(nullable id)reporter { if (self == [FBAEMReporter class]) { _networker = networker; _appId = appID; + _reporter = reporter; } } @@ -82,6 +91,11 @@ + (void)configureWithNetworker:(nullable id)networker return _networker; } ++ (id)reporter +{ + return _reporter; +} + + (void)enable { if (@available(iOS 14.0, *)) { diff --git a/Sources/FBAEMKit/include/FBAEMKit.h b/Sources/FBAEMKit/include/FBAEMKit.h index 703c40a0e0..9a2def2951 100644 --- a/Sources/FBAEMKit/include/FBAEMKit.h +++ b/Sources/FBAEMKit/include/FBAEMKit.h @@ -38,5 +38,6 @@ #import "FBAEMNetworking.h" #import "FBAEMReporter.h" + #import "FBSKAdNetworkReporting.h" #endif diff --git a/Sources/FBAEMKit/include/FBAEMReporter.h b/Sources/FBAEMKit/include/FBAEMReporter.h index b1c4353cb0..7ab95e830c 100644 --- a/Sources/FBAEMKit/include/FBAEMReporter.h +++ b/Sources/FBAEMKit/include/FBAEMReporter.h @@ -22,6 +22,7 @@ #import #import "FBAEMNetworking.h" + #import "FBSKAdNetworkReporting.h" NS_ASSUME_NONNULL_BEGIN @@ -42,6 +43,23 @@ NS_SWIFT_NAME(AEMReporter) + (void)configureWithNetworker:(nullable id)networker appID:(NSString *)appID; +/** + + Configure networker used for calling Facebook AEM Graph API endpoint + and Facebook App ID + + This function should be called in application(_:open:options:) from ApplicationDelegate + and BEFORE [FBAEMReporter enable] function. We will use SKAdNetwork reporter to prevent + double counting. + + @param networker An optional networker conforms to FBAEMNetworking which handles Graph API request + @param appID The Facebook app ID + @param reporter The SKAdNetwork repoter + */ ++ (void)configureWithNetworker:(nullable id)networker + appID:(NSString *)appID + reporter:(nullable id)reporter; + /** Enable AEM reporting diff --git a/Sources/FBAEMKit/include/FBSKAdNetworkReporting.h b/Sources/FBAEMKit/include/FBSKAdNetworkReporting.h new file mode 100644 index 0000000000..1da422fae8 --- /dev/null +++ b/Sources/FBAEMKit/include/FBSKAdNetworkReporting.h @@ -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 + +NS_ASSUME_NONNULL_BEGIN + +NS_SWIFT_NAME(SKAdNetworkReporting) +@protocol FBSKAdNetworkReporting + +- (BOOL)shouldCutoff; + +- (BOOL)isReportingEvent:(NSString *)event; + +@end + +NS_ASSUME_NONNULL_END + +#endif