Skip to content

Commit

Permalink
Subscription refactoring (#2764)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/72649045549333/1206805455884775/f
Tech Design URL:
https://app.asana.com/0/481882893211075/1207147511614062/f

Subscription refactoring for allowing unit testing.
- DI
- Removal of all singletons
- Removal of all static functions use
  • Loading branch information
federicocappelli authored May 22, 2024
1 parent e63699c commit 8876562
Show file tree
Hide file tree
Showing 68 changed files with 1,335 additions and 666 deletions.
194 changes: 167 additions & 27 deletions DuckDuckGo.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "a49bbac8aa58033981a5a946d220886366dd471b",
"version" : "145.3.3"
"branch" : "fcappelli/subscription_refactoring_2",
"revision" : "874ae4269db821797742655e134e72199c2813c8"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@
<Test
Identifier = "CoreDataEncryptionTests/testSavingIncorrectValueTypes()">
</Test>
<Test
Identifier = "DownloadsIntegrationTests/testWhenDownloadIsStartedInNewTab_tabIsClosed()">
</Test>
<Test
Identifier = "EncryptionKeyStoreTests">
</Test>
Expand Down
138 changes: 66 additions & 72 deletions DuckDuckGo/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ import ServiceManagement
import SyncDataProviders
import UserNotifications
import Lottie

import NetworkProtection
import Subscription
import NetworkProtectionIPC
import DataBrokerProtection

@MainActor
// @MainActor
final class AppDelegate: NSObject, NSApplicationDelegate {

#if DEBUG
Expand Down Expand Up @@ -86,20 +86,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
let bookmarksManager = LocalBookmarkManager.shared
var privacyDashboardWindow: NSWindow?

// Needs to be lazy as indirectly depends on AppDelegate
private lazy var networkProtectionSubscriptionEventHandler: NetworkProtectionSubscriptionEventHandler = {

let ipcClient = TunnelControllerIPCClient()
let tunnelController = NetworkProtectionIPCTunnelController(ipcClient: ipcClient)
let vpnUninstaller = VPNUninstaller(ipcClient: ipcClient)

return NetworkProtectionSubscriptionEventHandler(
tunnelController: tunnelController,
vpnUninstaller: vpnUninstaller)
}()
private var accountManager: AccountManaging {
subscriptionManager.accountManager
}
public let subscriptionManager: SubscriptionManaging
public let vpnSettings = VPNSettings(defaults: .netP)

private var networkProtectionSubscriptionEventHandler: NetworkProtectionSubscriptionEventHandler?
#if DBP
private let dataBrokerProtectionSubscriptionEventHandler = DataBrokerProtectionSubscriptionEventHandler()
private var dataBrokerProtectionSubscriptionEventHandler: DataBrokerProtectionSubscriptionEventHandler?
#endif

private var didFinishLaunching = false
Expand Down Expand Up @@ -188,19 +183,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
privacyConfigManager: AppPrivacyFeatures.shared.contentBlocking.privacyConfigurationManager
)

#if APPSTORE || !STRIPE
SubscriptionPurchaseEnvironment.current = .appStore
#else
SubscriptionPurchaseEnvironment.current = .stripe
#endif
}
// Configure Subscription
subscriptionManager = SubscriptionManager()

static func configurePixelKit() {
#if DEBUG
Self.setUpPixelKit(dryRun: true)
#else
Self.setUpPixelKit(dryRun: false)
#endif
// Update VPN environment and match the Subscription environment
vpnSettings.alignTo(subscriptionEnvironment: subscriptionManager.currentEnvironment)

// Update DBP environment and match the Subscription environment
DataBrokerProtectionSettings().alignTo(subscriptionEnvironment: subscriptionManager.currentEnvironment)
}

func applicationWillFinishLaunching(_ notification: Notification) {
Expand All @@ -217,6 +207,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
#endif

appIconChanger = AppIconChanger(internalUserDecider: internalUserDecider)

// Configure Event handlers
let ipcClient = TunnelControllerIPCClient()
let tunnelController = NetworkProtectionIPCTunnelController(ipcClient: ipcClient)
let vpnUninstaller = VPNUninstaller(ipcClient: ipcClient)

networkProtectionSubscriptionEventHandler = NetworkProtectionSubscriptionEventHandler(subscriptionManager: subscriptionManager,
tunnelController: tunnelController,
vpnUninstaller: vpnUninstaller)
#if DBP
dataBrokerProtectionSubscriptionEventHandler = DataBrokerProtectionSubscriptionEventHandler(subscriptionManager: subscriptionManager)
#endif
}

// swiftlint:disable:next function_body_length
Expand Down Expand Up @@ -264,19 +266,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {

startupSync()

let defaultEnvironment = SubscriptionPurchaseEnvironment.ServiceEnvironment.default

let currentEnvironment = UserDefaultsWrapper(key: .subscriptionEnvironment,
defaultValue: defaultEnvironment).wrappedValue
SubscriptionPurchaseEnvironment.currentServiceEnvironment = currentEnvironment

Task {
let accountManager = AccountManager(subscriptionAppGroup: Bundle.main.appGroup(bundle: .subs))
if let token = accountManager.accessToken {
_ = await SubscriptionService.getSubscription(accessToken: token, cachePolicy: .reloadIgnoringLocalCacheData)
_ = await accountManager.fetchEntitlements(cachePolicy: .reloadIgnoringLocalCacheData)
}
}
subscriptionManager.loadInitialData()

if [.normal, .uiTests].contains(NSApp.runType) {
stateRestorationManager.applicationDidFinishLaunching()
Expand Down Expand Up @@ -314,13 +304,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate {

UserDefaultsWrapper<Any>.clearRemovedKeys()

networkProtectionSubscriptionEventHandler.registerForSubscriptionAccountManagerEvents()
networkProtectionSubscriptionEventHandler?.registerForSubscriptionAccountManagerEvents()

NetworkProtectionAppEvents().applicationDidFinishLaunching()
NetworkProtectionAppEvents(featureVisibility: DefaultNetworkProtectionVisibility(subscriptionManager: subscriptionManager)).applicationDidFinishLaunching()
UNUserNotificationCenter.current().delegate = self

#if DBP
dataBrokerProtectionSubscriptionEventHandler.registerForSubscriptionAccountManagerEvents()
dataBrokerProtectionSubscriptionEventHandler?.registerForSubscriptionAccountManagerEvents()
#endif

#if DBP
Expand All @@ -336,15 +326,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
syncService?.initializeIfNeeded()
syncService?.scheduler.notifyAppLifecycleEvent()

NetworkProtectionAppEvents().applicationDidBecomeActive()

NetworkProtectionAppEvents(featureVisibility: DefaultNetworkProtectionVisibility(subscriptionManager: subscriptionManager)).applicationDidBecomeActive()
#if DBP
DataBrokerProtectionAppEvents().applicationDidBecomeActive()
#endif

AppPrivacyFeatures.shared.contentBlocking.privacyConfigurationManager.toggleProtectionsCounter.sendEventsIfNeeded()

updateSubscriptionStatus()
subscriptionManager.updateSubscriptionStatus { isActive in
if isActive {
PixelKit.fire(PrivacyProPixel.privacyProSubscriptionActive, frequency: .daily)
}
}
}

func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
Expand Down Expand Up @@ -386,9 +379,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
urlEventHandler.handleFiles(files)
}

private func applyPreferredTheme() {
let appearancePreferences = AppearancePreferences()
appearancePreferences.updateUserInterfaceStyle()
// MARK: - PixelKit

static func configurePixelKit() {
#if DEBUG
Self.setUpPixelKit(dryRun: true)
#else
Self.setUpPixelKit(dryRun: false)
#endif
}

private static func setUpPixelKit(dryRun: Bool) {
Expand All @@ -415,6 +413,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
}
}

// MARK: - Theme

private func applyPreferredTheme() {
let appearancePreferences = AppearancePreferences()
appearancePreferences.updateUserInterfaceStyle()
}

// MARK: - Sync

private func startupSync() {
Expand Down Expand Up @@ -490,7 +495,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
switch response {
case .alertSecondButtonReturn:
alert.window.sheetParent?.endSheet(alert.window)
WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .sync)
DispatchQueue.main.async {
WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .sync)
}
default:
break
}
Expand Down Expand Up @@ -567,30 +574,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
}

private func setUpAutoClearHandler() {
autoClearHandler = AutoClearHandler(preferences: .shared,
fireViewModel: FireCoordinator.fireViewModel,
stateRestorationManager: stateRestorationManager)
autoClearHandler.handleAppLaunch()
autoClearHandler.onAutoClearCompleted = {
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
}

}

func updateSubscriptionStatus() {
Task {
let accountManager = AccountManager(subscriptionAppGroup: Bundle.main.appGroup(bundle: .subs))

guard let token = accountManager.accessToken else { return }

if case .success(let subscription) = await SubscriptionService.getSubscription(accessToken: token, cachePolicy: .reloadIgnoringLocalCacheData) {
if subscription.isActive {
PixelKit.fire(PrivacyProPixel.privacyProSubscriptionActive, frequency: .daily)
DispatchQueue.main.async {
self.autoClearHandler = AutoClearHandler(preferences: .shared,
fireViewModel: FireCoordinator.fireViewModel,
stateRestorationManager: self.stateRestorationManager)
self.autoClearHandler.handleAppLaunch()
self.autoClearHandler.onAutoClearCompleted = {
NSApplication.shared.reply(toApplicationShouldTerminate: true)
}
}

_ = await accountManager.fetchEntitlements(cachePolicy: .reloadIgnoringLocalCacheData)
}
}

Expand All @@ -609,7 +601,9 @@ extension AppDelegate: UNUserNotificationCenterDelegate {

#if DBP
if response.notification.request.identifier == DataBrokerProtectionWaitlist.notificationIdentifier {
DataBrokerProtectionAppEvents().handleWaitlistInvitedNotification(source: .localPush)
DispatchQueue.main.async {
DataBrokerProtectionAppEvents().handleWaitlistInvitedNotification(source: .localPush)
}
}
#endif
}
Expand Down
12 changes: 7 additions & 5 deletions DuckDuckGo/Application/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ import Foundation
final class Application: NSApplication {

private let copyHandler = CopyHandler()
private var _delegate: AppDelegate!
// private var _delegate: AppDelegate!
public static var appDelegate: AppDelegate!

override init() {
super.init()

_delegate = AppDelegate()
self.delegate = _delegate
let delegate = AppDelegate()
self.delegate = delegate
Application.appDelegate = delegate

let mainMenu = MainMenu(featureFlagger: _delegate.featureFlagger,
bookmarkManager: _delegate.bookmarksManager,
let mainMenu = MainMenu(featureFlagger: delegate.featureFlagger,
bookmarkManager: delegate.bookmarksManager,
faviconManager: FaviconManager.shared,
copyHandler: copyHandler)
self.mainMenu = mainMenu
Expand Down
Loading

0 comments on commit 8876562

Please sign in to comment.