Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[WEB-862] AppTrackingTransparency Authorization #1772

Merged
merged 6 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Kickstarter-iOS/AppDelegateViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AppboyKit
import AppTrackingTransparency
import KsApi
import Library
import Prelude
Expand Down Expand Up @@ -180,6 +181,9 @@ public protocol AppDelegateViewModelOutputs {
/// Emits when we should register the device push token in Segment Analytics.
var registerPushTokenInSegment: Signal<Data, Never> { get }

/// Emits when application didFinishLaunchingWithOptions.
var requestATTrackingAuthorizationStatus: Signal<ATTrackingAuthorizationStatus, Never> { get }

/// Emits when our config updates with the enabled state for Semgent Analytics.
var segmentIsEnabled: Signal<Bool, Never> { get }

Expand Down Expand Up @@ -785,6 +789,14 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
self.brazeWillDisplayInAppMessageReturnProperty <~ self.brazeWillDisplayInAppMessageProperty.signal
.skipNil()
.map { _ in .displayInAppMessageNow }

self.requestATTrackingAuthorizationStatus = self.applicationLaunchOptionsProperty.signal
.skipNil()
.ksr_delay(.seconds(1), on: AppEnvironment.current.scheduler)
.map { _ -> ATTrackingAuthorizationStatus in
guard featureConsentManagementDialogEnabled() else { return .notDetermined }
return atTrackingAuthorizationStatus()
}
}

public var inputs: AppDelegateViewModelInputs { return self }
Expand Down Expand Up @@ -956,6 +968,7 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
public let pushTokenRegistrationStarted: Signal<(), Never>
public let pushTokenSuccessfullyRegistered: Signal<String, Never>
public let registerPushTokenInSegment: Signal<Data, Never>
public let requestATTrackingAuthorizationStatus: Signal<ATTrackingAuthorizationStatus, Never>
public let segmentIsEnabled: Signal<Bool, Never>
public let setApplicationShortcutItems: Signal<[ShortcutItem], Never>
public let showAlert: Signal<Notification, Never>
Expand All @@ -965,6 +978,27 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
public let updateConfigInEnvironment: Signal<Config, Never>
}

private func atTrackingAuthorizationStatus() -> ATTrackingAuthorizationStatus {
var authorizationStatus: ATTrackingAuthorizationStatus = .notDetermined

ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
switch status {
case .notDetermined:
authorizationStatus = .notDetermined
case .authorized:
authorizationStatus = .authorized
case .denied:
authorizationStatus = .denied
case .restricted:
authorizationStatus = .restricted
@unknown default:
authorizationStatus = .notDetermined
}
})

return authorizationStatus
}

/// Handles the deeplink route with both an id and text based name for a deeplink to categories.
private func deepLinkCategories(rawParams: [String: String]) -> (Param?, Param?) {
let parentCategoryParams = rawParams["parent_category_id"]
Expand Down
13 changes: 13 additions & 0 deletions Kickstarter-iOS/AppDelegateViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ final class AppDelegateViewModelTests: TestCase {
private let pushRegistrationStarted = TestObserver<(), Never>()
private let pushTokenSuccessfullyRegistered = TestObserver<String, Never>()
private let registerPushTokenInSegment = TestObserver<Data, Never>()
private let requestATTrackingAuthorizationStatus = TestObserver<ATTrackingAuthorizationStatus, Never>()
private let setApplicationShortcutItems = TestObserver<[ShortcutItem], Never>()
private let segmentIsEnabled = TestObserver<Bool, Never>()
private let showAlert = TestObserver<Notification, Never>()
Expand Down Expand Up @@ -96,6 +97,8 @@ final class AppDelegateViewModelTests: TestCase {
self.vm.outputs.pushTokenRegistrationStarted.observe(self.pushRegistrationStarted.observer)
self.vm.outputs.pushTokenSuccessfullyRegistered.observe(self.pushTokenSuccessfullyRegistered.observer)
self.vm.outputs.registerPushTokenInSegment.observe(self.registerPushTokenInSegment.observer)
self.vm.outputs.requestATTrackingAuthorizationStatus
.observe(self.requestATTrackingAuthorizationStatus.observer)
self.vm.outputs.setApplicationShortcutItems.observe(self.setApplicationShortcutItems.observer)
self.vm.outputs.showAlert.observe(self.showAlert.observer)
self.vm.outputs.segmentIsEnabled.observe(self.segmentIsEnabled.observer)
Expand Down Expand Up @@ -3004,6 +3007,16 @@ final class AppDelegateViewModelTests: TestCase {
self.updateCurrentUserInEnvironment.assertValues([user, updatedUser])
}
}

func testRequestATTrackingAuthorizationStatus_CalledOnceOnDidFinishLaunching() {
self.requestATTrackingAuthorizationStatus.assertValueCount(0)

self.vm.inputs.applicationDidFinishLaunching(application: UIApplication.shared, launchOptions: nil)

self.scheduler.advance(by: .seconds(1))

self.requestATTrackingAuthorizationStatus.assertValueCount(1)
}
}

private let backingForCreatorPushData: [String: Any] = [
Expand Down
2 changes: 2 additions & 0 deletions Kickstarter-iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSUserTrackingUsageDescription</key>
<string>We use personal data to provide a good experience on Kickstarter, and to help connect you with projects you&apos;ll love.</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
Expand Down
4 changes: 4 additions & 0 deletions Kickstarter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@
6067BCE9293E49AC0036ABB1 /* FacebookResetPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6067BCE7293E48140036ABB1 /* FacebookResetPasswordViewController.swift */; };
6067BCEC293E49F00036ABB1 /* FacebookResetPasswordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6067BCEA293E49CB0036ABB1 /* FacebookResetPasswordViewModel.swift */; };
6067BCF2293FC3520036ABB1 /* FacebookResetPasswordViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6067BCEF293FC10E0036ABB1 /* FacebookResetPasswordViewModelTests.swift */; };
606F214429799A1200BA5CDF /* ATTrackingAuthorizationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 606F214229799A0000BA5CDF /* ATTrackingAuthorizationStatus.swift */; };
608E7A5328ABDBAE00289E92 /* SetYourPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608E7A5128ABD5E700289E92 /* SetYourPasswordViewController.swift */; };
608E7A5628ABE6CD00289E92 /* SetYourPasswordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608E7A5428ABE27400289E92 /* SetYourPasswordViewModel.swift */; };
60DA50EB28B689A4002E2DF1 /* SetYourPasswordViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60DA50E928B68990002E2DF1 /* SetYourPasswordViewModelTests.swift */; };
Expand Down Expand Up @@ -2069,6 +2070,7 @@
6067BCE7293E48140036ABB1 /* FacebookResetPasswordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookResetPasswordViewController.swift; sourceTree = "<group>"; };
6067BCEA293E49CB0036ABB1 /* FacebookResetPasswordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookResetPasswordViewModel.swift; sourceTree = "<group>"; };
6067BCEF293FC10E0036ABB1 /* FacebookResetPasswordViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookResetPasswordViewModelTests.swift; sourceTree = "<group>"; };
606F214229799A0000BA5CDF /* ATTrackingAuthorizationStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTrackingAuthorizationStatus.swift; sourceTree = "<group>"; };
608E7A5128ABD5E700289E92 /* SetYourPasswordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetYourPasswordViewController.swift; sourceTree = "<group>"; };
608E7A5428ABE27400289E92 /* SetYourPasswordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetYourPasswordViewModel.swift; sourceTree = "<group>"; };
60DA50E928B68990002E2DF1 /* SetYourPasswordViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetYourPasswordViewModelTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5971,6 +5973,7 @@
8A213CE4239EAEA400BBB4C7 /* TrackingClientType.swift */,
94BE15C125E857C4007CD9A4 /* TrackingHelpers.swift */,
94BE15C925E96F06007CD9A4 /* TrackingHelpersTests.swift */,
606F214229799A0000BA5CDF /* ATTrackingAuthorizationStatus.swift */,
);
path = Tracking;
sourceTree = "<group>";
Expand Down Expand Up @@ -7733,6 +7736,7 @@
8A6C58932475E5950098D5A2 /* UIRefreshControl+StartRefreshing.swift in Sources */,
D7A37CCF1E2FF93D00EA066D /* SearchEmptyStateCellViewModel.swift in Sources */,
80D73AF61D50F1A60099231F /* Navigation.swift in Sources */,
606F214429799A1200BA5CDF /* ATTrackingAuthorizationStatus.swift in Sources */,
473DE012273C502F0033331D /* ProjectRisksCellViewModel.swift in Sources */,
A755115F1C8642C3005355CF /* Format.swift in Sources */,
598D96CB1D42AE85003F3F66 /* ActivitySampleProjectCellViewModel.swift in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions Library/Tracking/ATTrackingAuthorizationStatus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public enum ATTrackingAuthorizationStatus {
case authorized
case denied
case notDetermined
case restricted
}