Skip to content

Commit

Permalink
Post international Privacy Pro launch cleanup (#3714)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1203936086921904/1208836865988474/f

CC: @federicocappelli 

**Description**:
Post launch remove isLaunchedROW and isLaunchedROWOverride feature flags
and clean related business logic

**Steps to test this PR**:
- Verify purchase paths for both US and non-US Privacy Pro variants work
correctly (no functional changes expected)

**Definition of Done**:

* [ ] Does this PR satisfy our [Definition of
Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)?

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)
  • Loading branch information
miasma13 authored Jan 9, 2025
1 parent b160924 commit 2f9cf27
Show file tree
Hide file tree
Showing 29 changed files with 64 additions and 150 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15342,7 +15342,7 @@
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 223.0.0;
version = "223.0.0-1";
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
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" : "e8f94cf597f4a447f86f39f461b736ac9ea280ce",
"version" : "223.0.0"
"revision" : "a87790835c140e4399ac85bb5b3c39d4c5f4ff03",
"version" : "223.0.0-1"
}
},
{
Expand Down
15 changes: 0 additions & 15 deletions DuckDuckGo/Menus/MainMenuActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -909,21 +909,6 @@ extension MainViewController {
guard let internalUserDecider = NSApp.delegateTyped.internalUserDecider as? DefaultInternalUserDecider else { return }
let state = internalUserDecider.isInternalUser
internalUserDecider.debugSetInternalUserState(!state)

if !DefaultSubscriptionFeatureAvailability().isFeatureAvailable {
// We only clear PPro state when it's not available, as otherwise
// there should be no state to clear. Clearing PPro state can
// trigger notifications which we want to avoid unless
// necessary.
clearPrivacyProState()
}
}

/// Clears the PrivacyPro state to make testing easier.
///
private func clearPrivacyProState() {
Application.appDelegate.subscriptionManager.accountManager.signOut()
UserDefaults.netP.networkProtectionEntitlementsExpired = false
}

@objc func resetDailyPixels(_ sender: Any?) {
Expand Down
15 changes: 7 additions & 8 deletions DuckDuckGo/NavigationBar/View/AddressBarTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -421,14 +421,13 @@ final class AddressBarTextField: NSTextField {
}
#endif

if DefaultSubscriptionFeatureAvailability().isFeatureAvailable {
let baseURL = Application.appDelegate.subscriptionManager.url(for: .baseURL)
let identityTheftRestorationURL = Application.appDelegate.subscriptionManager.url(for: .identityTheftRestoration)
if providedUrl.isChild(of: baseURL) || providedUrl.isChild(of: identityTheftRestorationURL) {
self.updateValue(selectedTabViewModel: nil, addressBarString: nil) // reset
self.window?.makeFirstResponder(nil)
return
}
// Prevent typing in subscription URLs directly in the address bar
let baseURL = Application.appDelegate.subscriptionManager.url(for: .baseURL)
let identityTheftRestorationURL = Application.appDelegate.subscriptionManager.url(for: .identityTheftRestoration)
if providedUrl.isChild(of: baseURL) || providedUrl.isChild(of: identityTheftRestorationURL) {
self.updateValue(selectedTabViewModel: nil, addressBarString: nil) // reset
self.window?.makeFirstResponder(nil)
return
}

self.window?.makeFirstResponder(nil)
Expand Down
4 changes: 1 addition & 3 deletions DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,6 @@ final class MoreOptionsMenu: NSMenu, NSMenuDelegate {

@MainActor
private func addSubscriptionItems() {
guard subscriptionFeatureAvailability.isFeatureAvailable else { return }

func shouldHideDueToNoProduct() -> Bool {
let platform = subscriptionManager.currentEnvironment.purchasePlatform
return platform == .appStore && subscriptionManager.canPurchase == false
Expand Down Expand Up @@ -966,7 +964,7 @@ final class SubscriptionSubMenu: NSMenu, NSMenuDelegate {
}

private func refreshAvailabilityBasedOnEntitlements() {
guard subscriptionFeatureAvailability.isFeatureAvailable, subscriptionManager.accountManager.isUserAuthenticated else { return }
guard subscriptionManager.accountManager.isUserAuthenticated else { return }

@Sendable func hasEntitlement(for productName: Entitlement.ProductName) async -> Bool {
switch await self.subscriptionManager.accountManager.hasEntitlement(forProductName: productName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,7 @@ final class NavigationBarViewController: NSViewController {
}

private func toggleNetworkProtectionPopover() {
guard DefaultSubscriptionFeatureAvailability().isFeatureAvailable,
NetworkProtectionKeychainTokenStore().isFeatureActivated else {
guard NetworkProtectionKeychainTokenStore().isFeatureActivated else {
return
}

Expand Down
26 changes: 12 additions & 14 deletions DuckDuckGo/Preferences/Model/PreferencesSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,22 @@ struct PreferencesSection: Hashable, Identifiable {
.init(id: .about, panes: otherPanes)
]

if DefaultSubscriptionFeatureAvailability().isFeatureAvailable {
let subscriptionManager = Application.appDelegate.subscriptionManager
let platform = subscriptionManager.currentEnvironment.purchasePlatform
var shouldHidePrivacyProDueToNoProducts = platform == .appStore && subscriptionManager.canPurchase == false
let subscriptionManager = Application.appDelegate.subscriptionManager
let platform = subscriptionManager.currentEnvironment.purchasePlatform
var shouldHidePrivacyProDueToNoProducts = platform == .appStore && subscriptionManager.canPurchase == false

if subscriptionManager.accountManager.isUserAuthenticated {
shouldHidePrivacyProDueToNoProducts = false
}

if !shouldHidePrivacyProDueToNoProducts {
var subscriptionPanes: [PreferencePaneIdentifier] = [.subscription]
if subscriptionManager.accountManager.isUserAuthenticated {
shouldHidePrivacyProDueToNoProducts = false
}

if includingVPN {
subscriptionPanes.append(.vpn)
}
if !shouldHidePrivacyProDueToNoProducts {
var subscriptionPanes: [PreferencePaneIdentifier] = [.subscription]

sections.insert(.init(id: .privacyPro, panes: subscriptionPanes), at: 1)
if includingVPN {
subscriptionPanes.append(.vpn)
}

sections.insert(.init(id: .privacyPro, panes: subscriptionPanes), at: 1)
}

return sections
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ extension DefaultSubscriptionManager {
}

switch feature {
case .isLaunchedROW:
return featureFlagger.isFeatureOn(.isPrivacyProLaunchedROW)
case .isLaunchedROWOverride:
return featureFlagger.isFeatureOn(.isPrivacyProLaunchedROWOverride)
case .usePrivacyProUSARegionOverride:
return (featureFlagger.internalUserDecider.isInternalUser &&
subscriptionEnvironment.serviceEnvironment == .staging &&
Expand All @@ -76,15 +72,13 @@ extension DefaultSubscriptionManager {
subscriptionEndpointService: subscriptionEndpointService,
authEndpointService: authEndpointService,
subscriptionFeatureMappingCache: subscriptionFeatureMappingCache,
subscriptionEnvironment: subscriptionEnvironment,
subscriptionFeatureFlagger: subscriptionFeatureFlagger)
subscriptionEnvironment: subscriptionEnvironment)
} else {
self.init(accountManager: accountManager,
subscriptionEndpointService: subscriptionEndpointService,
authEndpointService: authEndpointService,
subscriptionFeatureMappingCache: subscriptionFeatureMappingCache,
subscriptionEnvironment: subscriptionEnvironment,
subscriptionFeatureFlagger: subscriptionFeatureFlagger)
subscriptionEnvironment: subscriptionEnvironment)
}

accountManager.delegate = self
Expand Down
8 changes: 2 additions & 6 deletions DuckDuckGo/Subscription/SubscriptionRedirectManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ protocol SubscriptionRedirectManager: AnyObject {

final class PrivacyProSubscriptionRedirectManager: SubscriptionRedirectManager {

private let featureAvailabiltyProvider: () -> Bool
private let subscriptionEnvironment: SubscriptionEnvironment
private let canPurchase: () -> Bool
private let baseURL: URL

init(featureAvailabiltyProvider: @escaping @autoclosure () -> Bool = DefaultSubscriptionFeatureAvailability().isFeatureAvailable,
subscriptionEnvironment: SubscriptionEnvironment,
init(subscriptionEnvironment: SubscriptionEnvironment,
baseURL: URL,
canPurchase: @escaping () -> Bool) {
self.featureAvailabiltyProvider = featureAvailabiltyProvider
self.subscriptionEnvironment = subscriptionEnvironment
self.canPurchase = canPurchase
self.baseURL = baseURL
Expand All @@ -45,9 +42,8 @@ final class PrivacyProSubscriptionRedirectManager: SubscriptionRedirectManager {
guard url.isPart(ofDomain: "duckduckgo.com") else { return nil }

if url.pathComponents == URL.privacyPro.pathComponents {
let isFeatureAvailable = featureAvailabiltyProvider()
let shouldHidePrivacyProDueToNoProducts = subscriptionEnvironment.purchasePlatform == .appStore && canPurchase() == false
let isPurchasePageRedirectActive = isFeatureAvailable && !shouldHidePrivacyProDueToNoProducts
let isPurchasePageRedirectActive = !shouldHidePrivacyProDueToNoProducts
// Redirect the `/pro` URL to `/subscriptions` URL. If there are any query items in the original URL it appends to the `/subscriptions` URL.
return isPurchasePageRedirectActive ? baseURL.addingQueryItems(from: url) : nil
}
Expand Down
16 changes: 0 additions & 16 deletions DuckDuckGo/Tab/Navigation/RedirectNavigationResponder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,4 @@ struct RedirectNavigationResponder: NavigationResponder {
navigator.load(request)
}
}

// private func redirectURL(for url: URL) -> URL? {
// guard url.isPart(ofDomain: "duckduckgo.com") else { return nil }
//
// if url.pathComponents == URL.privacyPro.pathComponents {
// let isFeatureAvailable = DefaultSubscriptionFeatureAvailability().isFeatureAvailable
// let subscriptionManager = Application.appDelegate.subscriptionManager
// let platform = subscriptionManager.currentEnvironment.purchasePlatform
// let shouldHidePrivacyProDueToNoProducts = platform == .appStore && subscriptionManager.canPurchase == false
// let isPurchasePageRedirectActive = isFeatureAvailable && !shouldHidePrivacyProDueToNoProducts
// let url = SubscriptionURL.baseURL.subscriptionURL(environment: subscriptionManager.currentEnvironment.serviceEnvironment)
// return isPurchasePageRedirectActive ? url : nil
// }
//
// return nil
// }
}
30 changes: 14 additions & 16 deletions DuckDuckGo/Tab/UserScripts/UserScripts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,20 @@ final class UserScripts: UserScriptsProvider {
userScripts.append(specialPages)
}

if DefaultSubscriptionFeatureAvailability().isFeatureAvailable {
let subscriptionManager = Application.appDelegate.subscriptionManager
let stripePurchaseFlow = DefaultStripePurchaseFlow(subscriptionEndpointService: subscriptionManager.subscriptionEndpointService,
authEndpointService: subscriptionManager.authEndpointService,
accountManager: subscriptionManager.accountManager)
let freemiumDBPPixelExperimentManager = FreemiumDBPPixelExperimentManager(subscriptionManager: subscriptionManager)
let delegate = SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager,
stripePurchaseFlow: stripePurchaseFlow,
uiHandler: Application.appDelegate.subscriptionUIHandler,
freemiumDBPPixelExperimentManager: freemiumDBPPixelExperimentManager)
subscriptionPagesUserScript.registerSubfeature(delegate: delegate)
userScripts.append(subscriptionPagesUserScript)

identityTheftRestorationPagesUserScript.registerSubfeature(delegate: IdentityTheftRestorationPagesFeature())
userScripts.append(identityTheftRestorationPagesUserScript)
}
let subscriptionManager = Application.appDelegate.subscriptionManager
let stripePurchaseFlow = DefaultStripePurchaseFlow(subscriptionEndpointService: subscriptionManager.subscriptionEndpointService,
authEndpointService: subscriptionManager.authEndpointService,
accountManager: subscriptionManager.accountManager)
let freemiumDBPPixelExperimentManager = FreemiumDBPPixelExperimentManager(subscriptionManager: subscriptionManager)
let delegate = SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager,
stripePurchaseFlow: stripePurchaseFlow,
uiHandler: Application.appDelegate.subscriptionUIHandler,
freemiumDBPPixelExperimentManager: freemiumDBPPixelExperimentManager)
subscriptionPagesUserScript.registerSubfeature(delegate: delegate)
userScripts.append(subscriptionPagesUserScript)

identityTheftRestorationPagesUserScript.registerSubfeature(delegate: IdentityTheftRestorationPagesFeature())
userScripts.append(identityTheftRestorationPagesUserScript)
}

lazy var userScripts: [UserScript] = [
Expand Down
17 changes: 2 additions & 15 deletions DuckDuckGo/Waitlist/VPNFeatureGatekeeper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ struct DefaultVPNFeatureGatekeeper: VPNFeatureGatekeeper {
/// For subscription users this means they have entitlements.
///
func canStartVPN() async throws -> Bool {
guard subscriptionFeatureAvailability.isFeatureAvailable else {
return false
}

switch await subscriptionManager.accountManager.hasEntitlement(forProductName: .networkProtection) {
case .success(let hasEntitlement):
return hasEntitlement
Expand All @@ -83,22 +79,13 @@ struct DefaultVPNFeatureGatekeeper: VPNFeatureGatekeeper {
/// For subscription users this means they are authenticated.
///
func isVPNVisible() -> Bool {
guard subscriptionFeatureAvailability.isFeatureAvailable else {
return false
}
return subscriptionManager.accountManager.isUserAuthenticated
}

/// We've had to add this method because accessing the singleton in app delegate is crashing the integration tests.
///
var subscriptionFeatureAvailability: DefaultSubscriptionFeatureAvailability {
DefaultSubscriptionFeatureAvailability()
subscriptionManager.accountManager.isUserAuthenticated
}

/// Returns whether the VPN should be uninstalled automatically.
/// This is only true when the user is not an Easter Egg user, the waitlist test has ended, and the user is onboarded.
func shouldUninstallAutomatically() -> Bool {
return subscriptionFeatureAvailability.isFeatureAvailable && !subscriptionManager.accountManager.isUserAuthenticated && LoginItem.vpnMenu.status.isInstalled
!subscriptionManager.accountManager.isUserAuthenticated && LoginItem.vpnMenu.status.isInstalled
}

/// Whether the user is fully onboarded
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DataBrokerProtection/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
targets: ["DataBrokerProtection"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0-1"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../AppKitExtensions"),
.package(path: "../XPCHelper"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/FeatureFlags/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let package = Package(
targets: ["FeatureFlags"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0-1"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand Down
13 changes: 2 additions & 11 deletions LocalPackages/FeatureFlags/Sources/FeatureFlags/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,13 @@ public enum FeatureFlag: String, CaseIterable {
/// https://app.asana.com/0/72649045549333/1208241266421040/f
case htmlNewTabPage

case isPrivacyProLaunchedROW
case isPrivacyProLaunchedROWOverride

case autofillPartialFormSaves
}

extension FeatureFlag: FeatureFlagDescribing {
public var supportsLocalOverriding: Bool {
switch self {
case .htmlNewTabPage,
.isPrivacyProLaunchedROWOverride:
case .htmlNewTabPage:
return true
case .maliciousSiteProtection:
return true
Expand All @@ -71,8 +67,7 @@ extension FeatureFlag: FeatureFlagDescribing {
.unknownUsernameCategorization,
.credentialsImportPromotionForExistingUsers,
.networkProtectionUserTips,
.networkProtectionEnforceRoutes,
.isPrivacyProLaunchedROW:
.networkProtectionEnforceRoutes:
return false
}
}
Expand Down Expand Up @@ -101,10 +96,6 @@ extension FeatureFlag: FeatureFlagDescribing {
return .remoteDevelopment(.subfeature(NetworkProtectionSubfeature.enforceRoutes))
case .htmlNewTabPage:
return .disabled
case .isPrivacyProLaunchedROW:
return .remoteReleasable(.subfeature(PrivacyProSubfeature.isLaunchedROW))
case .isPrivacyProLaunchedROWOverride:
return .remoteReleasable(.subfeature(PrivacyProSubfeature.isLaunchedROWOverride))
case .autofillPartialFormSaves:
return .remoteReleasable(.subfeature(AutofillSubfeature.partialFormSaves))
}
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NetworkProtectionMac/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let package = Package(
.library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0-1"),
.package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"),
.package(path: "../AppLauncher"),
.package(path: "../UDSHelper"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NewTabPage/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let package = Package(
targets: ["NewTabPage"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0-1"),
.package(path: "../WebKitExtensions"),
.package(path: "../Utilities"),
],
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/SubscriptionUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ let package = Package(
targets: ["SubscriptionUI"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "223.0.0-1"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../FeatureFlags")
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public final class PreferencesSubscriptionModel: ObservableObject {
var hasEmail: Bool { !(email?.isEmpty ?? true) }

let featureFlagger: FeatureFlagger
var isROWLaunched: Bool = false

private var subscriptionPlatform: Subscription.Platform?

Expand Down Expand Up @@ -165,7 +164,6 @@ public final class PreferencesSubscriptionModel: ObservableObject {
} else {
self.subscriptionStorefrontRegion = currentStorefrontRegion()
}
isROWLaunched = featureFlagger.isFeatureOn(.isPrivacyProLaunchedROW) || featureFlagger.isFeatureOn(.isPrivacyProLaunchedROWOverride)
}

private func updateUserAuthenticatedState(_ isUserAuthenticated: Bool) {
Expand Down
Loading

0 comments on commit 2f9cf27

Please sign in to comment.