Skip to content

Commit

Permalink
Post international Privacy Pro launch cleanup (#1151)
Browse files Browse the repository at this point in the history
Please review the release process for BrowserServicesKit
[here](https://app.asana.com/0/1200194497630846/1200837094583426).

**Required**:

Task/Issue URL:
https://app.asana.com/0/1203936086921904/1208836865988474/f
iOS PR: duckduckgo/iOS#3778
macOS PR: duckduckgo/macos-browser#3714
What kind of version bump will this require?: Major/Minor/Patch

**Optional**:
CC: @federicocappelli 

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

**Steps to test this PR**:
See client PRs, no functional changes.


**OS Testing**:

* [ ] iOS
* [ ] macOS

---
###### Internal references:
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
  • Loading branch information
miasma13 authored Jan 9, 2025
1 parent 2eddeb9 commit a877908
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,10 @@ public enum AutoconsentSubfeature: String, PrivacySubfeature {
public enum PrivacyProSubfeature: String, Equatable, PrivacySubfeature {
public var parent: PrivacyFeature { .privacyPro }

case isLaunched
case isLaunchedStripe
case allowPurchase
case allowPurchaseStripe
case isLaunchedOverride
case isLaunchedOverrideStripe
case useUnifiedFeedback
case setAccessTokenCookieForSubscriptionDomains
case isLaunchedROW
case isLaunchedROWOverride
case freeTrials
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import Foundation
import Subscription

public protocol SubscriptionFeatureAvailability {
var isFeatureAvailable: Bool { get }
var isSubscriptionPurchaseAllowed: Bool { get }
var usesUnifiedFeedbackForm: Bool { get }
}
Expand All @@ -36,10 +35,6 @@ public final class DefaultSubscriptionFeatureAvailability: SubscriptionFeatureAv
self.purchasePlatform = purchasePlatform
}

public var isFeatureAvailable: Bool {
isInternalUser || isSubscriptionLaunched || isSubscriptionLaunchedOverride
}

public var isSubscriptionPurchaseAllowed: Bool {
let isPurchaseAllowed: Bool

Expand All @@ -62,22 +57,4 @@ public final class DefaultSubscriptionFeatureAvailability: SubscriptionFeatureAv
private var isInternalUser: Bool {
privacyConfigurationManager.internalUserDecider.isInternalUser
}

private var isSubscriptionLaunched: Bool {
switch purchasePlatform {
case .appStore:
privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched)
case .stripe:
privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe)
}
}

private var isSubscriptionLaunchedOverride: Bool {
switch purchasePlatform {
case .appStore:
privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride)
case .stripe:
privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import Foundation

public enum SubscriptionFeatureFlags {
case isLaunchedROW
case isLaunchedROWOverride
case usePrivacyProUSARegionOverride
case usePrivacyProROWRegionOverride
}
Expand All @@ -29,8 +27,6 @@ public extension SubscriptionFeatureFlags {

var defaultState: Bool {
switch self {
case .isLaunchedROW, .isLaunchedROWOverride:
return true
case .usePrivacyProUSARegionOverride, .usePrivacyProROWRegionOverride:
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,16 @@ public final class DefaultStorePurchaseManager: ObservableObject, StorePurchaseM
let storefrontCountryCode: String?
let storefrontRegion: SubscriptionRegion

if let featureFlagger = subscriptionFeatureFlagger, featureFlagger.isFeatureOn(.isLaunchedROW) || featureFlagger.isFeatureOn(.isLaunchedROWOverride) {
if let subscriptionFeatureFlagger, subscriptionFeatureFlagger.isFeatureOn(.usePrivacyProUSARegionOverride) {
storefrontCountryCode = "USA"
} else if let subscriptionFeatureFlagger, subscriptionFeatureFlagger.isFeatureOn(.usePrivacyProROWRegionOverride) {
storefrontCountryCode = "POL"
} else {
storefrontCountryCode = await Storefront.current?.countryCode
}

storefrontRegion = SubscriptionRegion.matchingRegion(for: storefrontCountryCode ?? "USA") ?? .usa // Fallback to USA
} else {
if let subscriptionFeatureFlagger, subscriptionFeatureFlagger.isFeatureOn(.usePrivacyProUSARegionOverride) {
storefrontCountryCode = "USA"
storefrontRegion = .usa
} else if let subscriptionFeatureFlagger, subscriptionFeatureFlagger.isFeatureOn(.usePrivacyProROWRegionOverride) {
storefrontCountryCode = "POL"
} else {
storefrontCountryCode = await Storefront.current?.countryCode
}

storefrontRegion = SubscriptionRegion.matchingRegion(for: storefrontCountryCode ?? "USA") ?? .usa // Fallback to USA

self.currentStorefrontRegion = storefrontRegion
let applicableProductIdentifiers = storeSubscriptionConfiguration.subscriptionIdentifiers(for: storefrontRegion)
let availableProducts = try await productFetcher.products(for: applicableProductIdentifiers)
Expand Down Expand Up @@ -304,14 +299,7 @@ public final class DefaultStorePurchaseManager: ObservableObject, StorePurchaseM
let options: [SubscriptionOption] = await [.init(from: monthly, withRecurrence: "monthly"),
.init(from: yearly, withRecurrence: "yearly")]

let features: [SubscriptionFeature]

if let featureFlagger = subscriptionFeatureFlagger, featureFlagger.isFeatureOn(.isLaunchedROW) || featureFlagger.isFeatureOn(.isLaunchedROWOverride) {
features = await subscriptionFeatureMappingCache.subscriptionFeatures(for: monthly.id).compactMap { SubscriptionFeature(name: $0) }
} else {
let allFeatures: [Entitlement.ProductName] = [.networkProtection, .dataBrokerProtection, .identityTheftRestoration]
features = allFeatures.compactMap { SubscriptionFeature(name: $0) }
}
let features: [SubscriptionFeature] = await subscriptionFeatureMappingCache.subscriptionFeatures(for: monthly.id).compactMap { SubscriptionFeature(name: $0) }

return SubscriptionOptions(platform: platform,
options: options,
Expand Down
31 changes: 7 additions & 24 deletions Sources/Subscription/Managers/SubscriptionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,18 @@ public final class DefaultSubscriptionManager: SubscriptionManager {
public let subscriptionFeatureMappingCache: SubscriptionFeatureMappingCache
public let currentEnvironment: SubscriptionEnvironment

private let subscriptionFeatureFlagger: FeatureFlaggerMapping<SubscriptionFeatureFlags>

public init(storePurchaseManager: StorePurchaseManager? = nil,
accountManager: AccountManager,
subscriptionEndpointService: SubscriptionEndpointService,
authEndpointService: AuthEndpointService,
subscriptionFeatureMappingCache: SubscriptionFeatureMappingCache,
subscriptionEnvironment: SubscriptionEnvironment,
subscriptionFeatureFlagger: FeatureFlaggerMapping<SubscriptionFeatureFlags>) {
subscriptionEnvironment: SubscriptionEnvironment) {
self._storePurchaseManager = storePurchaseManager
self.accountManager = accountManager
self.subscriptionEndpointService = subscriptionEndpointService
self.authEndpointService = authEndpointService
self.subscriptionFeatureMappingCache = subscriptionFeatureMappingCache
self.currentEnvironment = subscriptionEnvironment
self.subscriptionFeatureFlagger = subscriptionFeatureFlagger

switch currentEnvironment.purchasePlatform {
case .appStore:
Expand All @@ -80,16 +76,7 @@ public final class DefaultSubscriptionManager: SubscriptionManager {
public var canPurchase: Bool {
guard let storePurchaseManager = _storePurchaseManager else { return false }

switch storePurchaseManager.currentStorefrontRegion {
case .usa:
return storePurchaseManager.areProductsAvailable
case .restOfWorld:
if subscriptionFeatureFlagger.isFeatureOn(.isLaunchedROW) || subscriptionFeatureFlagger.isFeatureOn(.isLaunchedROWOverride) {
return storePurchaseManager.areProductsAvailable
} else {
return false
}
}
return storePurchaseManager.areProductsAvailable
}

@available(macOS 12.0, iOS 15.0, *)
Expand Down Expand Up @@ -176,15 +163,11 @@ public final class DefaultSubscriptionManager: SubscriptionManager {
public func currentSubscriptionFeatures() async -> [Entitlement.ProductName] {
guard let token = accountManager.accessToken else { return [] }

if subscriptionFeatureFlagger.isFeatureOn(.isLaunchedROW) || subscriptionFeatureFlagger.isFeatureOn(.isLaunchedROWOverride) {
switch await subscriptionEndpointService.getSubscription(accessToken: token, cachePolicy: .returnCacheDataElseLoad) {
case .success(let subscription):
return await subscriptionFeatureMappingCache.subscriptionFeatures(for: subscription.productId)
case .failure:
return []
}
} else {
return [.networkProtection, .dataBrokerProtection, .identityTheftRestoration]
switch await subscriptionEndpointService.getSubscription(accessToken: token, cachePolicy: .returnCacheDataElseLoad) {
case .success(let subscription):
return await subscriptionFeatureMappingCache.subscriptionFeatures(for: subscription.productId)
case .failure:
return []
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,157 +47,75 @@ final class SubscriptionFeatureAvailabilityTests: XCTestCase {

// MARK: - Tests for App Store

func testSubscriptionFeatureNotAvailableWhenAllFlagsDisabledAndNotInternalUser() {
func testSubscriptionPurchaseNotAllowedWhenAllFlagsDisabledAndNotInternalUser() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchase))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .appStore)
XCTAssertFalse(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertFalse(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testSubscriptionFeatureAvailableWhenIsLaunchedFlagEnabled() {
func testSubscriptionPurchaseAllowedWhenAllowPurchaseFlagEnabled() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunched, .allowPurchase])
privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.allowPurchase])

XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchase))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .appStore)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testSubscriptionFeatureAvailableWhenIsLaunchedOverrideFlagEnabled() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunchedOverride, .allowPurchase])

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchase))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .appStore)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testSubscriptionFeatureAvailableAndPurchaseNotAllowed() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunched])

XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchase))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .appStore)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertFalse(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testSubscriptionFeatureAvailableWhenAllFlagsDisabledAndInternalUser() {
func testSubscriptionPurchaseAllowedWhenAllFlagsDisabledAndInternalUser() {
internalUserDeciderStore.isInternalUser = true
XCTAssertTrue(internalUserDeciderStore.isInternalUser)

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunched))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverride))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchase))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .appStore)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

// MARK: - Tests for Stripe

func testStripeSubscriptionFeatureNotAvailableWhenAllFlagsDisabledAndNotInternalUser() {
func testStripeSubscriptionPurchaseNotAllowedWhenAllFlagsDisabledAndNotInternalUser() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchaseStripe))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .stripe)
XCTAssertFalse(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertFalse(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testStripeSubscriptionFeatureAvailableWhenIsLaunchedFlagEnabled() {
func testStripeSubscriptionPurchaseAllowedWhenAllowPurchaseFlagEnabled() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunchedStripe, .allowPurchaseStripe])
privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.allowPurchaseStripe])

XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchaseStripe))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .stripe)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testStripeSubscriptionFeatureAvailableWhenIsLaunchedOverrideFlagEnabled() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunchedOverrideStripe, .allowPurchaseStripe])

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe))
XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchaseStripe))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .stripe)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testStripeSubscriptionFeatureAvailableAndPurchaseNotAllowed() {
internalUserDeciderStore.isInternalUser = false
XCTAssertFalse(internalUserDeciderStore.isInternalUser)

privacyConfig.isSubfeatureEnabledCheck = makeSubfeatureEnabledCheck(for: [.isLaunchedStripe])

XCTAssertTrue(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchaseStripe))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .stripe)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertFalse(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

func testStripeSubscriptionFeatureAvailableWhenAllFlagsDisabledAndInternalUser() {
func testStripeSubscriptionPurchaseAllowedWhenAllFlagsDisabledAndInternalUser() {
internalUserDeciderStore.isInternalUser = true
XCTAssertTrue(internalUserDeciderStore.isInternalUser)

XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.isLaunchedOverrideStripe))
XCTAssertFalse(privacyConfig.isSubfeatureEnabled(PrivacyProSubfeature.allowPurchaseStripe))

let subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(privacyConfigurationManager: privacyConfigurationManager,
purchasePlatform: .stripe)
XCTAssertTrue(subscriptionFeatureAvailability.isFeatureAvailable)
XCTAssertTrue(subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed)
}

Expand Down
Loading

0 comments on commit a877908

Please sign in to comment.