Skip to content

Commit

Permalink
Merge branch 'main' into dominik/c-s-s-7-4-0
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoy committed Jan 9, 2025
2 parents c65f8cf + 9d802fe commit 5bfd989
Show file tree
Hide file tree
Showing 17 changed files with 86 additions and 192 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state" : {
"revision" : "88982a3802ac504e2f1a118a73bfdf2d8f4a7735",
"version" : "16.0.0"
"revision" : "47c26dc32b94cdbcef3e6157497147917678c25c",
"version" : "16.1.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ let package = Package(
.library(name: "PrivacyStats", targets: ["PrivacyStats"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "16.0.0"),
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "16.1.0"),
.package(url: "https://github.com/duckduckgo/GRDB.swift.git", exact: "2.4.2"),
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.3.0"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public struct ContentScopeFeatureToggles: Encodable {

public let unknownUsernameCategorization: Bool

public let partialFormSaves: Bool

// Explicitly defined memberwise init only so it can be public
public init(emailProtection: Bool,
emailProtectionIncontextSignup: Bool,
Expand All @@ -92,7 +94,8 @@ public struct ContentScopeFeatureToggles: Encodable {
passwordGeneration: Bool,
inlineIconCredentials: Bool,
thirdPartyCredentialsProvider: Bool,
unknownUsernameCategorization: Bool) {
unknownUsernameCategorization: Bool,
partialFormSaves: Bool) {

self.emailProtection = emailProtection
self.emailProtectionIncontextSignup = emailProtectionIncontextSignup
Expand All @@ -104,6 +107,7 @@ public struct ContentScopeFeatureToggles: Encodable {
self.inlineIconCredentials = inlineIconCredentials
self.thirdPartyCredentialsProvider = thirdPartyCredentialsProvider
self.unknownUsernameCategorization = unknownUsernameCategorization
self.partialFormSaves = partialFormSaves
}

enum CodingKeys: String, CodingKey {
Expand All @@ -121,6 +125,7 @@ public struct ContentScopeFeatureToggles: Encodable {
case inlineIconCredentials = "inlineIcon_credentials"
case thirdPartyCredentialsProvider = "third_party_credentials_provider"
case unknownUsernameCategorization = "unknown_username_categorization"
case partialFormSaves = "partial_form_saves"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public enum PrivacyFeature: String {
case adAttributionReporting
case experimentTest
case forceOldAppDelegate
case htmlNewTabPage
}

/// An abstraction to be implemented by any "subfeature" of a given `PrivacyConfiguration` feature.
Expand Down Expand Up @@ -159,16 +160,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 All @@ -195,3 +190,8 @@ public enum ExperimentTestSubfeatures: String, PrivacySubfeature {
public var parent: PrivacyFeature { .experimentTest }
case experimentTestAA
}

public enum HTMLNewTabPageSubfeature: String, Equatable, PrivacySubfeature {
public var parent: PrivacyFeature { .htmlNewTabPage }
case isLaunched
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import Foundation
import AuthenticationServices
import Common
import SecureStorage
import os.log

public protocol AutofillCredentialIdentityStoreManaging {
Expand All @@ -32,14 +33,17 @@ public protocol AutofillCredentialIdentityStoreManaging {
final public class AutofillCredentialIdentityStoreManager: AutofillCredentialIdentityStoreManaging {

private let credentialStore: ASCredentialIdentityStoring
private let vault: (any AutofillSecureVault)?
private var vault: (any AutofillSecureVault)?
private let reporter: SecureVaultReporting
private let tld: TLD

public init(credentialStore: ASCredentialIdentityStoring = ASCredentialIdentityStore.shared,
vault: (any AutofillSecureVault)?,
vault: (any AutofillSecureVault)? = nil,
reporter: SecureVaultReporting,
tld: TLD) {
self.credentialStore = credentialStore
self.vault = vault
self.reporter = reporter
self.tld = tld
}

Expand Down Expand Up @@ -240,8 +244,15 @@ final public class AutofillCredentialIdentityStoreManager: AutofillCredentialIde

// MARK: - Private Secure Vault Operations

private func secureVault() -> (any AutofillSecureVault)? {
if vault == nil {
vault = try? AutofillSecureVaultFactory.makeVault(reporter: reporter)
}
return vault
}

private func fetchAccounts() throws -> [SecureVaultModels.WebsiteAccount] {
guard let vault = vault else {
guard let vault = secureVault() else {
Logger.autofill.error("Vault not created")
return []
}
Expand All @@ -256,7 +267,7 @@ final public class AutofillCredentialIdentityStoreManager: AutofillCredentialIde
}

private func fetchAccountsFor(domain: String) throws -> [SecureVaultModels.WebsiteAccount] {
guard let vault = vault else {
guard let vault = secureVault() else {
Logger.autofill.error("Vault not created")
return []
}
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)
}
}
}
20 changes: 19 additions & 1 deletion Sources/PrivacyDashboard/PrivacyDashboardController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {
@Published public var theme: PrivacyDashboardTheme?
@Published public var allowedPermissions: [AllowedPermission] = []
public var preferredLocale: String?
public var dashboardHtmlName: String {
#if os(iOS)
return "ios"
#else
return "macos"
#endif
}
public lazy var dashboardHtml: String = {
guard let file = Bundle.privacyDashboardResourcesBundle.path(forResource: dashboardHtmlName, ofType: "html", inDirectory: "html") else {
assertionFailure("HTML for the PrivacyDashboard was not found")
return ""
}
guard let html = try? String(contentsOfFile: file) else {
assertionFailure("Should be able to load HTML as a string")
return ""
}
return html
}()

public private(set) weak var privacyInfo: PrivacyInfo?
private let entryPoint: PrivacyDashboardEntryPoint
Expand Down Expand Up @@ -124,7 +142,7 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {

private func loadStartScreen() {
let url = PrivacyDashboardURLBuilder(configuration: .startScreen(entryPoint: entryPoint, variant: variant)).build()
webView?.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent().deletingLastPathComponent())
webView?.loadHTMLString(dashboardHtml, baseURL: url.deletingLastPathComponent())
}

public func updatePrivacyInfo(_ privacyInfo: PrivacyInfo?) {
Expand Down
5 changes: 1 addition & 4 deletions Sources/Subscription/API/SubscriptionEndpointService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,7 @@ public struct DefaultSubscriptionEndpointService: SubscriptionEndpointService {

let cachedSubscription: Subscription? = subscriptionCache.get()
if subscription != cachedSubscription {
let defaultExpiryDate = Date().addingTimeInterval(subscriptionCache.settings.defaultExpirationInterval)
let expiryDate = min(defaultExpiryDate, subscription.expiresOrRenewsAt)

subscriptionCache.set(subscription, expires: expiryDate)
subscriptionCache.set(subscription)
NotificationCenter.default.post(name: .subscriptionDidChange, object: self, userInfo: [UserDefaultsCacheKey.subscription: subscription])
}
}
Expand Down
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 @@ -28,5 +28,6 @@ extension ContentScopeFeatureToggles {
passwordGeneration: true,
inlineIconCredentials: true,
thirdPartyCredentialsProvider: false,
unknownUsernameCategorization: true)
unknownUsernameCategorization: true,
partialFormSaves: true)
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ final class FingerprintingReferenceTests: XCTestCase {
passwordGeneration: false,
inlineIconCredentials: false,
thirdPartyCredentialsProvider: false,
unknownUsernameCategorization: false)
unknownUsernameCategorization: false,
partialFormSaves: false)

let contentScopeProperties = ContentScopeProperties(gpcEnabled: false,
sessionKey: UUID().uuidString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final class AutofillCredentialIdentityStoreManagerTests: XCTestCase {
mockVault = DefaultAutofillSecureVault(providers: providers)

tld = TLD()
manager = AutofillCredentialIdentityStoreManager(credentialStore: mockStore, vault: mockVault, tld: tld)
manager = AutofillCredentialIdentityStoreManager(credentialStore: mockStore, vault: mockVault, reporter: MockSecureVaultReporting(), tld: tld)
}

override func tearDown() {
Expand Down Expand Up @@ -205,3 +205,7 @@ final class AutofillCredentialIdentityStoreManagerTests: XCTestCase {
}

}

private class MockSecureVaultReporting: SecureVaultReporting {
func secureVaultError(_ error: SecureStorage.SecureStorageError) {}
}
Loading

0 comments on commit 5bfd989

Please sign in to comment.