Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit ef2c2ed

Browse files
authored
Handle “waitlist over” state (#1810)
Task/Issue URL: https://app.asana.com/0/0/1205742396614588/f **Description**: Handle waitlist over state for DBP Agent should be stopped Data should be removed
1 parent 9739cc8 commit ef2c2ed

File tree

8 files changed

+181
-27
lines changed

8 files changed

+181
-27
lines changed

DuckDuckGo.xcodeproj/project.pbxproj

+12
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,8 @@
816816
3192A2622A4C4CFF0084EA89 /* DuckDuckGo Notifications.app in Embed Login Items */ = {isa = PBXBuildFile; fileRef = 4B4BEC202A11B4E2001D9AC5 /* DuckDuckGo Notifications.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
817817
3192EC882A4DCF21001E97A5 /* DBPHomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3192EC872A4DCF21001E97A5 /* DBPHomeViewController.swift */; };
818818
3198FCAC2A5D8A3C002EF5F8 /* AppLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEAD7A6E2A1D3E1F002A24E7 /* AppLauncher.swift */; };
819+
3199C6F92AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3199C6F82AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift */; };
820+
3199C6FD2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3199C6FC2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift */; };
819821
31A031A6288191230090F792 /* CookieConsentAnimationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A031A5288191230090F792 /* CookieConsentAnimationView.swift */; };
820822
31A031A928819D920090F792 /* CookieConsentAnimationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A031A828819D920090F792 /* CookieConsentAnimationModel.swift */; };
821823
31A93F512A5D8AF0008BB88D /* DataBrokerProtection in Frameworks */ = {isa = PBXBuildFile; productRef = 31A93F502A5D8AF0008BB88D /* DataBrokerProtection */; };
@@ -3901,6 +3903,10 @@
39013903
3192A2702A4C4E330084EA89 /* DataBrokerProtection */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = DataBrokerProtection; sourceTree = "<group>"; };
39023904
3192A2712A4CBD3A0084EA89 /* DuckDuckGoDBP.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBP.xcconfig; sourceTree = "<group>"; };
39033905
3192EC872A4DCF21001E97A5 /* DBPHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBPHomeViewController.swift; sourceTree = "<group>"; };
3906+
3199C6F82AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBrokerProtectionFeatureDisabler.swift; sourceTree = "<group>"; };
3907+
3199C6FA2AF96F7C002A7BA1 /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../DBP/BrowserServicesKit; sourceTree = "<group>"; };
3908+
3199C6FB2AF97037002A7BA1 /* content-scope-scripts */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "content-scope-scripts"; path = "../DBP/content-scope-scripts"; sourceTree = "<group>"; };
3909+
3199C6FC2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBrokerProtectionAppEvents.swift; sourceTree = "<group>"; };
39043910
31A031A5288191230090F792 /* CookieConsentAnimationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieConsentAnimationView.swift; sourceTree = "<group>"; };
39053911
31A031A828819D920090F792 /* CookieConsentAnimationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieConsentAnimationModel.swift; sourceTree = "<group>"; };
39063912
31B4AF522901A4F20013585E /* NSEventExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEventExtension.swift; sourceTree = "<group>"; };
@@ -5386,6 +5392,8 @@
53865392
7B6D98662ADEB4B000CD35FE /* DataBrokerProtectionLoginItemScheduler.swift */,
53875393
9D8FA00B2AC5BDCE005DD0D0 /* LoginItem+DataBrokerProtection.swift */,
53885394
31C5FFB82AF64D120008A79F /* DataBrokerProtectionFeatureVisibility.swift */,
5395+
3199C6F82AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift */,
5396+
3199C6FC2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift */,
53895397
);
53905398
path = DBP;
53915399
sourceTree = "<group>";
@@ -7053,6 +7061,8 @@
70537061
AA585D75248FD31100E9A3E2 = {
70547062
isa = PBXGroup;
70557063
children = (
7064+
3199C6FB2AF97037002A7BA1 /* content-scope-scripts */,
7065+
3199C6FA2AF96F7C002A7BA1 /* BrowserServicesKit */,
70567066
378B5886295CF2A4002C0CC0 /* Configuration */,
70577067
378E279C2970217400FCADA2 /* LocalPackages */,
70587068
7BB108552A43375D000AB95F /* LocalThirdParty */,
@@ -10028,6 +10038,7 @@
1002810038
4B9DB0222A983B24000927DB /* ProductWaitlistRequest.swift in Sources */,
1002910039
31929FAA2A4C4CFF0084EA89 /* AppStateChangedPublisher.swift in Sources */,
1003010040
31929FAB2A4C4CFF0084EA89 /* BookmarkTableCellView.swift in Sources */,
10041+
3199C6F92AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift in Sources */,
1003110042
31929FAC2A4C4CFF0084EA89 /* BookmarkManagementSidebarViewController.swift in Sources */,
1003210043
31929FAD2A4C4CFF0084EA89 /* NSStackViewExtension.swift in Sources */,
1003310044
31929FAF2A4C4CFF0084EA89 /* OptionalExtension.swift in Sources */,
@@ -10494,6 +10505,7 @@
1049410505
3192A15C2A4C4CFF0084EA89 /* NSAttributedStringExtension.swift in Sources */,
1049510506
3192A15D2A4C4CFF0084EA89 /* AnimationView.swift in Sources */,
1049610507
3192A15E2A4C4CFF0084EA89 /* NSRectExtension.swift in Sources */,
10508+
3199C6FD2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift in Sources */,
1049710509
3192A15F2A4C4CFF0084EA89 /* YoutubeOverlayUserScript.swift in Sources */,
1049810510
3192A1602A4C4CFF0084EA89 /* DictionaryExtension.swift in Sources */,
1049910511
3192A1612A4C4CFF0084EA89 /* Publishers.NestedObjectChanges.swift in Sources */,

DuckDuckGo/Application/AppDelegate.swift

+3-10
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel
220220
#endif
221221

222222
#if DBP
223-
Task {
224-
try? await DataBrokerProtectionWaitlist().redeemDataBrokerProtectionInviteCodeIfAvailable()
225-
}
223+
DataBrokerProtectionAppEvents().applicationDidFinishLaunching()
226224
#endif
227225
}
228226

@@ -241,9 +239,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel
241239
#endif
242240

243241
#if DBP
244-
Task {
245-
try? await DataBrokerProtectionWaitlist().redeemDataBrokerProtectionInviteCodeIfAvailable()
246-
}
242+
DataBrokerProtectionAppEvents().applicationDidBecomeActive()
247243
#endif
248244
}
249245

@@ -411,10 +407,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
411407

412408
#if DBP
413409
if response.notification.request.identifier == DataBrokerProtectionWaitlist.notificationIdentifier {
414-
if DataBrokerProtectionWaitlist().readyToAcceptTermsAndConditions {
415-
DailyPixel.fire(pixel: .dataBrokerProtectionWaitlistNotificationTapped, frequency: .dailyAndCount, includeAppVersionParameter: true)
416-
DataBrokerProtectionWaitlistViewControllerPresenter.show()
417-
}
410+
DataBrokerProtectionAppEvents().handleNotification()
418411
}
419412
#endif
420413
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//
2+
// DataBrokerProtectionAppEvents.swift
3+
//
4+
// Copyright © 2023 DuckDuckGo. All rights reserved.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
import Foundation
20+
21+
struct DataBrokerProtectionAppEvents {
22+
23+
func applicationDidFinishLaunching() {
24+
let featureVisibility = DefaultDataBrokerProtectionFeatureVisibility()
25+
26+
guard featureVisibility.isFeatureVisible() else {
27+
featureVisibility.disableAndDeleteForWaitlistUsers()
28+
return
29+
}
30+
31+
Task {
32+
try? await DataBrokerProtectionWaitlist().redeemDataBrokerProtectionInviteCodeIfAvailable()
33+
}
34+
}
35+
36+
func applicationDidBecomeActive() {
37+
let featureVisibility = DefaultDataBrokerProtectionFeatureVisibility()
38+
39+
guard featureVisibility.isFeatureVisible() else {
40+
featureVisibility.disableAndDeleteForWaitlistUsers()
41+
return
42+
}
43+
44+
Task {
45+
try? await DataBrokerProtectionWaitlist().redeemDataBrokerProtectionInviteCodeIfAvailable()
46+
}
47+
}
48+
49+
@MainActor
50+
func handleNotification() {
51+
if DataBrokerProtectionWaitlist().readyToAcceptTermsAndConditions {
52+
DailyPixel.fire(pixel: .dataBrokerProtectionWaitlistNotificationTapped,
53+
frequency: .dailyAndCount,
54+
includeAppVersionParameter: true)
55+
DataBrokerProtectionWaitlistViewControllerPresenter.show()
56+
}
57+
}
58+
59+
func windowDidBecomeMain() {
60+
sendActiveDataBrokerProtectionWaitlistUserPixel()
61+
}
62+
63+
private func sendActiveDataBrokerProtectionWaitlistUserPixel() {
64+
if DefaultDataBrokerProtectionFeatureVisibility().waitlistIsOngoing {
65+
DailyPixel.fire(pixel: .dataBrokerProtectionWaitlistUserActive,
66+
frequency: .dailyOnly,
67+
includeAppVersionParameter: true)
68+
}
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// DataBrokerProtectionFeatureDisabler.swift
3+
//
4+
// Copyright © 2023 DuckDuckGo. All rights reserved.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
import Foundation
20+
import DataBrokerProtection
21+
22+
protocol DataBrokerProtectionFeatureDisabling {
23+
func disableAndDelete()
24+
}
25+
26+
struct DataBrokerProtectionFeatureDisabler: DataBrokerProtectionFeatureDisabling {
27+
private let scheduler: DataBrokerProtectionLoginItemScheduler
28+
private let dataManager: InMemoryDataCacheDelegate
29+
30+
init(scheduler: DataBrokerProtectionLoginItemScheduler = DataBrokerProtectionManager.shared.scheduler,
31+
dataManager: InMemoryDataCacheDelegate = DataBrokerProtectionDataManager()) {
32+
self.dataManager = dataManager
33+
self.scheduler = scheduler
34+
}
35+
36+
func disableAndDelete() {
37+
scheduler.stopScheduler()
38+
39+
scheduler.disableLoginItem()
40+
41+
dataManager.removeAllData()
42+
}
43+
}

DuckDuckGo/DBP/DataBrokerProtectionFeatureVisibility.swift

+48-9
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,26 @@
1818

1919
import Foundation
2020
import BrowserServicesKit
21+
import Common
2122

2223
protocol DataBrokerProtectionFeatureVisibility {
2324
func isFeatureVisible() -> Bool
25+
func disableAndDeleteForAllUsers()
26+
func disableAndDeleteForWaitlistUsers()
2427
}
2528

2629
struct DefaultDataBrokerProtectionFeatureVisibility: DataBrokerProtectionFeatureVisibility {
2730
private let privacyConfigurationManager: PrivacyConfigurationManaging
31+
private let featureDisabler: DataBrokerProtectionFeatureDisabling
2832

29-
init(privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager) {
33+
init(privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager,
34+
featureDisabler: DataBrokerProtectionFeatureDisabling = DataBrokerProtectionFeatureDisabler()) {
3035
self.privacyConfigurationManager = privacyConfigurationManager
36+
self.featureDisabler = featureDisabler
3137
}
3238

33-
func isFeatureVisible() -> Bool {
34-
isUserLocaleAllowed && isFeatureEnabled
39+
var waitlistIsOngoing: Bool {
40+
isWaitlistEnabled && isWaitlistBetaActive
3541
}
3642

3743
private var isUserLocaleAllowed: Bool {
@@ -49,14 +55,47 @@ struct DefaultDataBrokerProtectionFeatureVisibility: DataBrokerProtectionFeature
4955
return (regionCode ?? "US") == "US"
5056
}
5157

52-
private var isFeatureEnabled: Bool {
53-
// We should check for the feature flag
54-
return true
58+
private var isWaitlistBetaActive: Bool {
59+
// Check privacy config
60+
// return privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DBPSubfeature.waitlistBetaActive)
61+
true
62+
}
63+
64+
private var isWaitlistEnabled: Bool {
65+
// Check privacy config
66+
// return privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DBPSubfeature.waitlist)
67+
true
68+
}
69+
70+
private var isWaitlistUser: Bool {
71+
DataBrokerProtectionWaitlist().waitlistStorage.isWaitlistUser
5572
}
5673

57-
var isWaitlistEnabled: Bool {
58-
// We should check for the privacy config waitlist flag
74+
func disableAndDeleteForAllUsers() {
75+
featureDisabler.disableAndDelete()
76+
77+
os_log("Disabling and removing DBP for all users", log: .dataBrokerProtection)
78+
}
5979

60-
return true
80+
func disableAndDeleteForWaitlistUsers() {
81+
guard isWaitlistUser else {
82+
return
83+
}
84+
85+
os_log("Disabling and removing DBP for waitlist users", log: .dataBrokerProtection)
86+
featureDisabler.disableAndDelete()
87+
}
88+
89+
/// If we want to prevent new users from joining the waitlist while still allowing waitlist users to continue using it,
90+
/// we should set isWaitlistEnabled to false and isWaitlistBetaActive to true.
91+
/// To remove it from everyone, isWaitlistBetaActive should be set to false
92+
func isFeatureVisible() -> Bool {
93+
guard isUserLocaleAllowed else { return false }
94+
95+
if isWaitlistUser {
96+
return isWaitlistBetaActive
97+
} else {
98+
return isWaitlistEnabled && isWaitlistBetaActive
99+
}
61100
}
62101
}

DuckDuckGo/MainWindow/MainViewController.swift

+1-8
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ final class MainViewController: NSViewController {
141141
#endif
142142

143143
#if DBP
144-
sendActiveDataBrokerProtectionWaitlistUserPixel()
144+
DataBrokerProtectionAppEvents().windowDidBecomeMain()
145145
#endif
146146
}
147147

@@ -418,13 +418,6 @@ final class MainViewController: NSViewController {
418418
}
419419
#endif
420420

421-
#if DBP
422-
private func sendActiveDataBrokerProtectionWaitlistUserPixel() {
423-
if DefaultDataBrokerProtectionFeatureVisibility().isWaitlistEnabled {
424-
DailyPixel.fire(pixel: .dataBrokerProtectionWaitlistUserActive, frequency: .dailyOnly, includeAppVersionParameter: true)
425-
}
426-
}
427-
#endif
428421
// MARK: - First responder
429422

430423
func adjustFirstResponder() {

DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift

+2
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ final class MoreOptionsMenu: NSMenu {
342342

343343
DailyPixel.fire(pixel: .dataBrokerProtectionWaitlistEntryPointMenuItemDisplayed, frequency: .dailyAndCount, includeAppVersionParameter: true)
344344

345+
} else {
346+
DefaultDataBrokerProtectionFeatureVisibility().disableAndDeleteForWaitlistUsers()
345347
}
346348

347349
#endif // DBP

LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/InputFilesChecker.swift

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ let extraInputFiles: [TargetName: Set<InputFile>] = [
5757
.init("LoginItem+DataBrokerProtection.swift", .source),
5858
.init("DataBrokerProtectionDebugMenu.swift", .source),
5959
.init("DataBrokerProtectionFeatureVisibility.swift", .source),
60+
.init("DataBrokerProtectionFeatureDisabler.swift", .source),
61+
.init("DataBrokerProtectionAppEvents.swift", .source),
6062
.init("DuckDuckGoDBPBackgroundAgent.app", .unknown),
6163
]),
6264

0 commit comments

Comments
 (0)