diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 6c065c61a0..aa8833b98c 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -2933,6 +2933,8 @@ B6FA893D269C423100588ECD /* PrivacyDashboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */; }; B6FA893F269C424500588ECD /* PrivacyDashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6FA893E269C424500588ECD /* PrivacyDashboardViewController.swift */; }; B6FA8941269C425400588ECD /* PrivacyDashboardPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6FA8940269C425400588ECD /* PrivacyDashboardPopover.swift */; }; + BB5789722B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5789712B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift */; }; + BB5789732B2CC0300009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5789712B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift */; }; BBDFDC5A2B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */; }; BBDFDC5C2B2B8D7000F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */; }; BBDFDC5D2B2B8E2100F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */; }; @@ -4222,6 +4224,7 @@ B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PrivacyDashboard.storyboard; sourceTree = ""; }; B6FA893E269C424500588ECD /* PrivacyDashboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardViewController.swift; sourceTree = ""; }; B6FA8940269C425400588ECD /* PrivacyDashboardPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardPopover.swift; sourceTree = ""; }; + BB5789712B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBrokerProtectionSubscriptionEventHandler.swift; sourceTree = ""; }; BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBrokerProtectionExternalWaitlistPixels.swift; sourceTree = ""; }; CB24F70B29A3D9CB006DCC58 /* AppConfigurationURLProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConfigurationURLProvider.swift; sourceTree = ""; }; CB6BCDF827C6BEFF00CC76DC /* PrivacyFeatures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyFeatures.swift; sourceTree = ""; }; @@ -4673,6 +4676,7 @@ 3199C6F82AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift */, 3199C6FC2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift */, BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */, + BB5789712B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift */, ); path = DBP; sourceTree = ""; @@ -10907,6 +10911,7 @@ 4B957B8F2AC7AE700062CA31 /* Assertions.swift in Sources */, 4B957B902AC7AE700062CA31 /* BookmarkViewModel.swift in Sources */, 4B957B912AC7AE700062CA31 /* DaxSpeech.swift in Sources */, + BB5789732B2CC0300009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift in Sources */, 4B957B922AC7AE700062CA31 /* DuckPlayerSchemeHandler.swift in Sources */, 4B957B932AC7AE700062CA31 /* FirePopoverViewModel.swift in Sources */, 4B957B942AC7AE700062CA31 /* BWCommand.swift in Sources */, @@ -11473,6 +11478,7 @@ 4B9DB04A2A983B24000927DB /* NotificationService.swift in Sources */, 3775912D29AAC72700E26367 /* SyncPreferences.swift in Sources */, 1DB9618329F67F6200CF5568 /* FaviconNullStore.swift in Sources */, + BB5789722B2CA70F0009DFE2 /* DataBrokerProtectionSubscriptionEventHandler.swift in Sources */, B693954F26F04BEB0015B914 /* PaddedImageButton.swift in Sources */, 4BA1A6B8258B081600F6F690 /* EncryptionKeyStoring.swift in Sources */, B65783E725F8AAFB00D8DB33 /* String+Punycode.swift in Sources */, diff --git a/DuckDuckGo/Application/AppDelegate.swift b/DuckDuckGo/Application/AppDelegate.swift index bf83796dcf..c636f37de9 100644 --- a/DuckDuckGo/Application/AppDelegate.swift +++ b/DuckDuckGo/Application/AppDelegate.swift @@ -74,6 +74,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel private var emailCancellables = Set() let bookmarksManager = LocalBookmarkManager.shared +#if DBP && SUBSCRIPTION + private let dataBrokerProtectionSubscriptionEventHandler = DataBrokerProtectionSubscriptionEventHandler() +#endif + private var didFinishLaunching = false #if SPARKLE @@ -243,6 +247,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel UNUserNotificationCenter.current().delegate = self #endif +#if DBP && SUBSCRIPTION + dataBrokerProtectionSubscriptionEventHandler.registerForSubscriptionAccountManagerEvents() +#endif + #if DBP DataBrokerProtectionAppEvents().applicationDidFinishLaunching() #endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift b/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift new file mode 100644 index 0000000000..783c900d12 --- /dev/null +++ b/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift @@ -0,0 +1,55 @@ +// +// DataBrokerProtectionSubscriptionEventHandler.swift +// +// Copyright © 2023 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#if DBP && SUBSCRIPTION + +import Foundation +import Account +import DataBrokerProtection + +final class DataBrokerProtectionSubscriptionEventHandler { + + private let accountManager: Account.AccountManaging + private let authRepository: AuthenticationRepository + + init(accountManager: Account.AccountManaging = Account.AccountManager(), + authRepository: AuthenticationRepository = KeychainAuthenticationData()) { + self.accountManager = accountManager + self.authRepository = authRepository + } + + func registerForSubscriptionAccountManagerEvents() { + NotificationCenter.default.addObserver(self, selector: #selector(handleAccountDidSignIn), name: .accountDidSignIn, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handleAccountDidSignOut), name: .accountDidSignOut, object: nil) + } + + @objc private func handleAccountDidSignIn() { + guard let token = accountManager.token else { + Pixel.fire(.dataBrokerProtectionErrorWhenFetchingSubscriptionAuthTokenAfterSignIn) + assertionFailure("[DBP Subscription] AccountManager signed in but token could not be retrieved") + return + } + + authRepository.save(accessToken: token) + } + + @objc private func handleAccountDidSignOut() { + // Going to be defined here: https://app.asana.com/0/1204006570077678/1206206961074916/f + } +} + +#endif diff --git a/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift b/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift index f4d0faec88..1b1aad17d4 100644 --- a/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift +++ b/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift @@ -149,11 +149,15 @@ final class MoreOptionsMenu: NSMenu { #if DBP @objc func openDataBrokerProtection(_ sender: NSMenuItem) { - if !DefaultDataBrokerProtectionFeatureVisibility.bypassWaitlist && DataBrokerProtectionWaitlistViewControllerPresenter.shouldPresentWaitlist() { + #if SUBSCRIPTION + actionDelegate?.optionsButtonMenuRequestedDataBrokerProtection(self) + #else + if !DefaultDataBrokerProtectionFeatureVisibility.bypassWaitlist && DataBrokerProtectionWaitlistViewControllerPresenter.shouldPresentWaitlist() { DataBrokerProtectionWaitlistViewControllerPresenter.show() } else { actionDelegate?.optionsButtonMenuRequestedDataBrokerProtection(self) } + #endif } #endif // DBP diff --git a/DuckDuckGo/Statistics/PixelEvent.swift b/DuckDuckGo/Statistics/PixelEvent.swift index 5694bb4432..407567a01b 100644 --- a/DuckDuckGo/Statistics/PixelEvent.swift +++ b/DuckDuckGo/Statistics/PixelEvent.swift @@ -197,6 +197,9 @@ extension Pixel { case dataBrokerProtectionWaitlistTermsAndConditionsDisplayed case dataBrokerProtectionWaitlistTermsAndConditionsAccepted + // DataBrokerProtection Other + case dataBrokerProtectionErrorWhenFetchingSubscriptionAuthTokenAfterSignIn + // 28-day Home Button case homeButtonHidden case homeButtonLeft @@ -538,6 +541,8 @@ extension Pixel.Event { return "m_mac_dbp_imp_terms" case .dataBrokerProtectionWaitlistTermsAndConditionsAccepted: return "m_mac_dbp_ev_terms_accepted" + case .dataBrokerProtectionErrorWhenFetchingSubscriptionAuthTokenAfterSignIn: + return "m_mac_dbp_error_when_fetching_subscription_auth_token_after_sign_in" // 28-day Home Button case .homeButtonHidden: diff --git a/DuckDuckGo/Statistics/PixelParameters.swift b/DuckDuckGo/Statistics/PixelParameters.swift index 1bdc5b26d6..a2c30e5bd7 100644 --- a/DuckDuckGo/Statistics/PixelParameters.swift +++ b/DuckDuckGo/Statistics/PixelParameters.swift @@ -149,6 +149,7 @@ extension Pixel.Event { .dataBrokerProtectionWaitlistCardUITapped, .dataBrokerProtectionWaitlistTermsAndConditionsDisplayed, .dataBrokerProtectionWaitlistTermsAndConditionsAccepted, + .dataBrokerProtectionErrorWhenFetchingSubscriptionAuthTokenAfterSignIn, .homeButtonLeft, .homeButtonRight, .homeButtonHidden: diff --git a/LocalPackages/Account/Sources/Account/AccountManager.swift b/LocalPackages/Account/Sources/Account/AccountManager.swift index b03c409908..8c3fe49ba3 100644 --- a/LocalPackages/Account/Sources/Account/AccountManager.swift +++ b/LocalPackages/Account/Sources/Account/AccountManager.swift @@ -29,7 +29,13 @@ public protocol AccountManagerKeychainAccessDelegate: AnyObject { func accountManagerKeychainAccessFailed(accessType: AccountKeychainAccessType, error: AccountKeychainAccessError) } -public class AccountManager { +public protocol AccountManaging { + + var token: String? { get } + +} + +public class AccountManager: AccountManaging { private let storage: AccountStorage public weak var delegate: AccountManagerKeychainAccessDelegate? diff --git a/LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/InputFilesChecker.swift b/LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/InputFilesChecker.swift index ad2b491fc6..0db71533d6 100644 --- a/LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/InputFilesChecker.swift +++ b/LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/InputFilesChecker.swift @@ -44,7 +44,8 @@ let nonSandboxedExtraInputFiles: Set = [ .init("VPNMetadataCollector.swift", .source), .init("VPNFeedbackCategory.swift", .source), .init("VPNFeedbackSender.swift", .source), - .init("DuckDuckGoDBPBackgroundAgent.app", .unknown) + .init("DuckDuckGoDBPBackgroundAgent.app", .unknown), + .init("DataBrokerProtectionSubscriptionEventHandler.swift", .source) ] /**