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

Refactor subscription configuration and dependency setup #2586

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 0 additions & 31 deletions Core/AccountManagerExtension.swift

This file was deleted.

18 changes: 2 additions & 16 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -705,9 +705,6 @@
BD862E072B30F5E30073E2EE /* VPNFeedbackSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD862E062B30F5E30073E2EE /* VPNFeedbackSender.swift */; };
BD862E092B30F63E0073E2EE /* VPNMetadataCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD862E082B30F63E0073E2EE /* VPNMetadataCollector.swift */; };
BD862E0B2B30F9300073E2EE /* VPNFeedbackFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD862E0A2B30F9300073E2EE /* VPNFeedbackFormView.swift */; };
BDA583872B98B6C700732FDC /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA583862B98B6C700732FDC /* AccountManagerExtension.swift */; };
BDA583882B98B92F00732FDC /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA583862B98B6C700732FDC /* AccountManagerExtension.swift */; };
BDA583892B98BA7600732FDC /* AccountManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDA583862B98B6C700732FDC /* AccountManagerExtension.swift */; };
BDC234F72B27F51100D3C798 /* UniquePixel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDC234F62B27F51100D3C798 /* UniquePixel.swift */; };
BDD3B3552B8EF8DB005857A8 /* NetworkProtectionUNNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */; };
BDFF031D2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */; };
Expand Down Expand Up @@ -1286,6 +1283,7 @@
1EA513772866039400493C6A /* TrackerAnimationLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackerAnimationLogic.swift; sourceTree = "<group>"; };
1EC458452948932500CB2B13 /* UIHostingControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIHostingControllerExtension.swift; sourceTree = "<group>"; };
1EC51CD828D8C0DF00E9D05A /* UIImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = "<group>"; };
1ED946B52BA03EED00819AEB /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../BrowserServicesKit; sourceTree = "<group>"; };
1EDE39D12705D4A100C99C72 /* FileSizeDebugViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSizeDebugViewController.swift; sourceTree = "<group>"; };
1EE411F02857C3640003FE64 /* TrackerAnimationImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackerAnimationImageProvider.swift; sourceTree = "<group>"; };
1EE411F22857C4A30003FE64 /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2366,7 +2364,6 @@
BD862E062B30F5E30073E2EE /* VPNFeedbackSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNFeedbackSender.swift; sourceTree = "<group>"; };
BD862E082B30F63E0073E2EE /* VPNMetadataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNMetadataCollector.swift; sourceTree = "<group>"; };
BD862E0A2B30F9300073E2EE /* VPNFeedbackFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNFeedbackFormView.swift; sourceTree = "<group>"; };
BDA583862B98B6C700732FDC /* AccountManagerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountManagerExtension.swift; sourceTree = "<group>"; };
BDC234F62B27F51100D3C798 /* UniquePixel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniquePixel.swift; sourceTree = "<group>"; };
BDFF03192BA39C5A00F324C9 /* NetworkProtectionFeatureVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibility.swift; sourceTree = "<group>"; };
BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultNetworkProtectionVisibility.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3727,6 +3724,7 @@
84E341891E2F7EFB00BDBA6F = {
isa = PBXGroup;
children = (
1ED946B52BA03EED00819AEB /* BrowserServicesKit */,
EE3B98EB2A963515002F63A0 /* WidgetsExtensionAlpha.entitlements */,
6FB030C7234331B400A10DB9 /* Configuration.xcconfig */,
EEB8FDB92A990AEE00EBEDCF /* Configuration-Alpha.xcconfig */,
Expand Down Expand Up @@ -4421,14 +4419,6 @@
path = Feedback;
sourceTree = "<group>";
};
BDA583852B98B69C00732FDC /* Subscription */ = {
isa = PBXGroup;
children = (
BDA583862B98B6C700732FDC /* AccountManagerExtension.swift */,
);
name = Subscription;
sourceTree = "<group>";
};
BDFF031F2BA3D3AD00F324C9 /* Feature Visibility */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -5133,7 +5123,6 @@
F143C2E51E4A4CD400CFDE3A /* Core */ = {
isa = PBXGroup;
children = (
BDA583852B98B69C00732FDC /* Subscription */,
4B470ED4299C484B0086EBDC /* AppTrackingProtection */,
F1CE42A71ECA0A520074A8DF /* Bookmarks */,
837774491F8E1ECE00E17A29 /* ContentBlocker */,
Expand Down Expand Up @@ -6490,7 +6479,6 @@
02025AD42988229800E694E7 /* ProxySocket.swift in Sources */,
02025AD62988229800E694E7 /* SocketProtocol.swift in Sources */,
02025AD82988229800E694E7 /* Tunnel.swift in Sources */,
BDA583892B98BA7600732FDC /* AccountManagerExtension.swift in Sources */,
02025ADA2988229800E694E7 /* Port.swift in Sources */,
02025ADB2988229800E694E7 /* HTTPStreamScanner.swift in Sources */,
02025ADC2988229800E694E7 /* UInt128.swift in Sources */,
Expand Down Expand Up @@ -6926,7 +6914,6 @@
85F98F92296F32BD00742F4A /* SyncSettingsViewController.swift in Sources */,
84E341961E2F7EFB00BDBA6F /* AppDelegate.swift in Sources */,
310D091D2799F57200DC0060 /* Download.swift in Sources */,
BDA583882B98B92F00732FDC /* AccountManagerExtension.swift in Sources */,
C13F3F6C2B7F88470083BE40 /* AuthConfirmationPromptViewModel.swift in Sources */,
1EEF124E2850EADE003DDE57 /* PrivacyIconView.swift in Sources */,
37FCAAAB29911BF1000E420A /* WaitlistExtensions.swift in Sources */,
Expand Down Expand Up @@ -7322,7 +7309,6 @@
B652DF0D287C2A6300C12A9C /* PrivacyFeatures.swift in Sources */,
F10E522D1E946F8800CE1253 /* NSAttributedStringExtension.swift in Sources */,
9887DC252354D2AA005C85F5 /* Database.swift in Sources */,
BDA583872B98B6C700732FDC /* AccountManagerExtension.swift in Sources */,
F143C3171E4A99D200CFDE3A /* AppURLs.swift in Sources */,
C1963863283794A000298D4D /* BookmarksCachingSearch.swift in Sources */,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@
"version" : "3.0.0"
}
},
{
"identity" : "browserserviceskit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/DuckDuckGo/BrowserServicesKit",
"state" : {
"revision" : "0c73586c2628381b8a63be65fd2bc1824e58d7f9",
"version" : "126.2.0"
}
},
{
"identity" : "cocoaasyncsocket",
"kind" : "remoteSourceControl",
Expand Down
16 changes: 6 additions & 10 deletions DuckDuckGo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
#if SUBSCRIPTION
private func setupSubscriptionsEnvironment() {
Task {
SubscriptionPurchaseEnvironment.currentServiceEnvironment = .staging
#if NETWORK_PROTECTION
if VPNSettings(defaults: .networkProtectionGroupDefaults).selectedEnvironment == .staging {
SubscriptionPurchaseEnvironment.currentServiceEnvironment = .staging
}
#endif
SubscriptionPurchaseEnvironment.current = .appStore
await AccountManager().checkSubscriptionState()
await AppDependencyProvider.shared.subscriptionManager.accountManager.checkSubscriptionState()
}
}
#endif
Expand Down Expand Up @@ -508,10 +501,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func updateSubscriptionStatus() {
#if SUBSCRIPTION
Task {
guard let token = AccountManager().accessToken else {
let subscriptionManager = AppDependencyProvider.shared.subscriptionManager
guard let token = subscriptionManager.tokenStorage.accessToken else {
return
}
let result = await SubscriptionService.getSubscription(accessToken: token)

let subscriptionService = subscriptionManager.serviceProvider.makeSubscriptionService()
let result = await subscriptionService.getSubscription(accessToken: token)

switch result {
case .success(let success):
Expand Down
30 changes: 30 additions & 0 deletions DuckDuckGo/AppDependencyProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
import Bookmarks
import Subscription

#if SUBSCRIPTION
import Subscription
#endif

#if NETWORK_PROTECTION
import NetworkProtection
#endif

protocol DependencyProvider {

var appSettings: AppSettings { get }
Expand All @@ -42,6 +50,10 @@
var userBehaviorMonitor: UserBehaviorMonitor { get }
var subscriptionFeatureAvailability: SubscriptionFeatureAvailability { get }

#if SUBSCRIPTION
var subscriptionManager: SubscriptionManaging { get }

Check failure on line 54 in DuckDuckGo/AppDependencyProvider.swift

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot find type 'SubscriptionManaging' in scope
#endif

}

/// Provides dependencies for objects that are not directly instantiated
Expand Down Expand Up @@ -75,4 +87,22 @@
privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager,
purchasePlatform: .appStore)

#if SUBSCRIPTION
let subscriptionManager: SubscriptionManaging = {

var serviceEnvironment: SubscriptionServiceEnvironment = .staging

#if NETWORK_PROTECTION
if VPNSettings(defaults: .networkProtectionGroupDefaults).selectedEnvironment == .staging {
serviceEnvironment = .staging
}
#endif

let configuration = DefaultSubscriptionConfiguration(subscriptionAppGroup: Bundle.main.appGroup(bundle: .subs),
purchasePlatform: .appStore,
serviceEnvironment: serviceEnvironment)

return SubscriptionManager(configuration: configuration)
}()
#endif
}
3 changes: 2 additions & 1 deletion DuckDuckGo/MainViewController+Segues.swift
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ extension MainViewController {
bookmarksDatabase: bookmarksDatabase,
tabManager: tabManager)
#if SUBSCRIPTION
let settingsViewModel = SettingsViewModel(legacyViewProvider: legacyViewProvider, accountManager: AccountManager())
let settingsViewModel = SettingsViewModel(legacyViewProvider: legacyViewProvider,
subscriptionManager: AppDependencyProvider.shared.subscriptionManager)
#else
let settingsViewModel = SettingsViewModel(legacyViewProvider: legacyViewProvider)
#endif
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/NetworkProtectionConvenienceInitialisers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ extension NetworkProtectionKeychainTokenStore {
let accessTokenProvider: () -> String? = {
#if SUBSCRIPTION
if featureVisibility.shouldMonitorEntitlement() {
return { AccountManager().accessToken }
return { AppDependencyProvider.shared.subscriptionManager.tokenStorage.accessToken }
}
#endif
return { nil }
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/NetworkProtectionDebugViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ shouldShowVPNShortcut: \(vpnVisibility.shouldShowVPNShortcut() ? "YES" : "NO")
if subscriptionOverrideEnabled {
defaults.subscriptionOverrideEnabled = false
#if SUBSCRIPTION
AccountManager().signOut()
AppDependencyProvider.shared.subscriptionManager.signOut()
#endif
} else {
defaults.resetsubscriptionOverrideEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ struct NetworkProtectionVisibilityForTunnelProvider: NetworkProtectionFeatureVis
// todo - https://app.asana.com/0/0/1206844038943626/f
func isPrivacyProLaunched() -> Bool {
#if SUBSCRIPTION
AccountManager().accessToken != nil
let subscriptionAppGroup = Bundle.main.appGroup(bundle: .subs)
let tokenStore = SubscriptionTokenKeychainStorage(keychainType: .dataProtection(.named(subscriptionAppGroup)))
return tokenStore.accessToken != nil
#else
false
#endif
Expand Down
26 changes: 14 additions & 12 deletions DuckDuckGo/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@
private let voiceSearchHelper: VoiceSearchHelperProtocol

#if SUBSCRIPTION
private var accountManager: AccountManager
private var subscriptionManager: SubscriptionManaging

Check failure on line 53 in DuckDuckGo/SettingsViewModel.swift

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot find type 'SubscriptionManaging' in scope
private var accountManager: AccountManaging { subscriptionManager.accountManager }
private lazy var subscriptionService = subscriptionManager.serviceProvider.makeSubscriptionService()
private var signOutObserver: Any?
private var isPrivacyProEnabled: Bool {
AppDependencyProvider.shared.subscriptionFeatureAvailability.isFeatureAvailable
Expand Down Expand Up @@ -215,13 +217,13 @@
// MARK: Default Init
init(state: SettingsState? = nil,
legacyViewProvider: SettingsLegacyViewProvider,
accountManager: AccountManager,
subscriptionManager: SubscriptionManaging,

Check failure on line 220 in DuckDuckGo/SettingsViewModel.swift

View workflow job for this annotation

GitHub Actions / Unit Tests

cannot find type 'SubscriptionManaging' in scope
voiceSearchHelper: VoiceSearchHelperProtocol = AppDependencyProvider.shared.voiceSearchHelper,
variantManager: VariantManager = AppDependencyProvider.shared.variantManager,
deepLink: SettingsDeepLinkSection? = nil) {
self.state = SettingsState.defaults
self.legacyViewProvider = legacyViewProvider
self.accountManager = accountManager
self.subscriptionManager = subscriptionManager
self.voiceSearchHelper = voiceSearchHelper
self.deepLinkTarget = deepLink

Expand Down Expand Up @@ -301,10 +303,10 @@
#if SUBSCRIPTION
if #available(iOS 15, *) {
enabled = isPrivacyProEnabled
canPurchase = SubscriptionPurchaseEnvironment.canPurchase
canPurchase = !PurchaseManager.shared.availableProducts.isEmpty
await setupSubscriptionEnvironment()
if let token = AccountManager().accessToken {
let subscriptionResult = await SubscriptionService.getSubscription(accessToken: token)
if let token = subscriptionManager.tokenStorage.accessToken {
let subscriptionResult = await subscriptionService.getSubscription(accessToken: token)
if case .success(let subscription) = subscriptionResult {
hasActiveSubscription = subscription.isActive
}
Expand Down Expand Up @@ -352,21 +354,21 @@
private func setupSubscriptionEnvironment() async {

// Active subscription check
guard let token = accountManager.accessToken else {
guard let token = subscriptionManager.tokenStorage.accessToken else {
setupSubscriptionPurchaseOptions()
return
}

isLoadingSubscriptionState = true
// Fetch available subscriptions from the backend (or sign out)
switch await SubscriptionService.getSubscription(accessToken: token) {
switch await subscriptionService.getSubscription(accessToken: token) {

case .success(let subscription) where subscription.isActive:

// Check entitlements and update UI accordingly
let entitlements: [Entitlement.ProductName] = [.networkProtection, .dataBrokerProtection, .identityTheftRestoration]
for entitlement in entitlements {
if case let .success(result) = await AccountManager().hasEntitlement(for: entitlement) {
if case let .success(result) = await accountManager.hasEntitlement(for: entitlement) {
switch entitlement {
case .identityTheftRestoration:
self.shouldShowITP = result
Expand All @@ -390,7 +392,7 @@

@available(iOS 15.0, *)
private func signOutUser() {
AccountManager().signOut()
subscriptionManager.signOut()
setupSubscriptionPurchaseOptions()
}

Expand All @@ -415,7 +417,7 @@
@available(iOS 15.0, *)
func restoreAccountPurchase() async {
DispatchQueue.main.async { self.isRestoringSubscription = true }
let result = await AppStoreRestoreFlow.restoreAccountFromPastPurchase(subscriptionAppGroup: Bundle.main.appGroup(bundle: .subs))
let result = await subscriptionManager.flowProvider.appStoreRestoreFlow.restoreAccountFromPastPurchase()
switch result {
case .success:
DispatchQueue.main.async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ final class IdentityTheftRestorationPagesFeature: Subfeature, ObservableObject {
struct Handlers {
static let getAccessToken = "getAccessToken"
}



private let tokenStorage: SubscriptionTokenStorage = AppDependencyProvider.shared.subscriptionManager.tokenStorage

weak var broker: UserScriptMessageBroker?
var featureName: String = Constants.featureName

Expand All @@ -68,7 +69,7 @@ final class IdentityTheftRestorationPagesFeature: Subfeature, ObservableObject {
}

func getAccessToken(params: Any, original: WKScriptMessage) async throws -> Encodable? {
if let accessToken = AccountManager().accessToken {
if let accessToken = tokenStorage.accessToken {
return [Constants.token: accessToken]
} else {
return [String: String]()
Expand Down