Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,6 @@ public enum SetAsDefaultAndAddToDockSubfeature: String, PrivacySubfeature {

// https://app.asana.com/1/137249556945/project/492600419927320/task/1210863200265479?focus=true
case scheduledDefaultBrowserAndDockPromptsInactiveUser // macOS

// https://app.asana.com/1/137249556945/project/1206329551987282/task/1209304767941984?focus=true
case scheduledDefaultBrowserPrompts // iOS

// https://app.asana.com/1/137249556945/project/1206329551987282/task/1210716028790591?focus=true
case scheduledDefaultBrowserPromptsInactiveUser // iOS
}

public enum OnboardingSubfeature: String, PrivacySubfeature {
Expand Down
12 changes: 0 additions & 12 deletions iOS/Core/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,6 @@ public enum FeatureFlag: String {
/// https://app.asana.com/1/137249556945/project/1211834678943996/task/1211866463389447
case showSettingsCompleteSetupSection

/// https://app.asana.com/1/137249556945/project/1211834678943996/task/1211866611125558
case scheduledSetDefaultBrowserPrompts

/// https://app.asana.com/1/137249556945/project/1211834678943996/task/1211866470962985
case scheduledSetDefaultBrowserPromptsForInactiveUsers

/// https://app.asana.com/1/137249556945/project/1211834678943996/task/1211866607644644
case canPromoteImportPasswordsInPasswordManagement

Expand Down Expand Up @@ -318,8 +312,6 @@ extension FeatureFlag: FeatureFlagDescribing {
.supportsAlternateStripePaymentFlow,
.personalInformationRemoval,
.createFireproofFaviconUpdaterSecureVaultInBackground,
.scheduledSetDefaultBrowserPrompts,
.scheduledSetDefaultBrowserPromptsForInactiveUsers,
.duckAISearchParameter,
.inactivityNotification,
.daxEasterEggLogos,
Expand Down Expand Up @@ -488,10 +480,6 @@ extension FeatureFlag: FeatureFlagDescribing {
return .remoteReleasable(.subfeature(AIChatSubfeature.keepSession))
case .showSettingsCompleteSetupSection:
return .remoteReleasable(.subfeature(OnboardingSubfeature.showSettingsCompleteSetupSection))
case .scheduledSetDefaultBrowserPrompts:
return .remoteReleasable(.subfeature(SetAsDefaultAndAddToDockSubfeature.scheduledDefaultBrowserPrompts))
case .scheduledSetDefaultBrowserPromptsForInactiveUsers:
return .remoteReleasable(.subfeature(SetAsDefaultAndAddToDockSubfeature.scheduledDefaultBrowserPromptsInactiveUser))
case .supportsAlternateStripePaymentFlow:
return .remoteReleasable(.subfeature(PrivacyProSubfeature.supportsAlternateStripePaymentFlow))
case .personalInformationRemoval:
Expand Down
6 changes: 0 additions & 6 deletions iOS/DuckDuckGo/AppServices/DefaultBrowserPromptService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ final class DefaultBrowserPromptService {
let promptActivityPixelHandler = DefaultBrowserPromptPixelHandler()

presenter = DefaultBrowserPromptFactory.makeDefaultBrowserPromptPresenter(
featureFlagProvider: featureFlagAdapter,
featureFlagSettingsProvider: featureFlagAdapter,
promptActivityStore: promptTypeKeyValueFilesStore,
userTypeProviding: userTypeManager,
Expand All @@ -74,15 +73,10 @@ final class DefaultBrowserPromptService {

func resume() {
// Application has been launched or brought to foreground.
guard shouldRecordActivity() else { return }
Logger.defaultBrowserPrompt.debug("[Default Browser Prompt] - Record User Activity If Needed.")
userActivityManager.recordActivity()
}

private func shouldRecordActivity() -> Bool {
// True if either active/inactive prompt features is enabled
featureFlagAdapter.isDefaultBrowserPromptsForActiveUsersFeatureEnabled || featureFlagAdapter.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled
}
}

// MARK: - Adapters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Core
import BrowserServicesKit
import SetDefaultBrowserCore

final class DefaultBrowserPromptFeatureFlagAdapter: DefaultBrowserPromptFeatureFlagProvider, DefaultBrowserPromptFeatureFlagSettingsProvider {
final class DefaultBrowserPromptFeatureFlagAdapter: DefaultBrowserPromptFeatureFlagSettingsProvider {

private let featureFlagger: FeatureFlagger
private let privacyConfigurationManager: PrivacyConfigurationManaging
Expand All @@ -32,14 +32,6 @@ final class DefaultBrowserPromptFeatureFlagAdapter: DefaultBrowserPromptFeatureF
self.privacyConfigurationManager = privacyConfigurationManager
}

public var isDefaultBrowserPromptsForActiveUsersFeatureEnabled: Bool {
featureFlagger.isFeatureOn(FeatureFlag.scheduledSetDefaultBrowserPrompts)
}

public var isDefaultBrowserPromptsForInactiveUsersFeatureEnabled: Bool {
featureFlagger.isFeatureOn(FeatureFlag.scheduledSetDefaultBrowserPromptsForInactiveUsers)
}

public var defaultBrowserPromptFeatureSettings: [String: Any] {
privacyConfigurationManager.privacyConfig.settings(for: .setAsDefaultAndAddToDock)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ struct DefaultBrowserPromptDebugView: View {
}

var body: some View {
if model.isFeatureEnabled {
settingsView
} else {
Text(verbatim: "Feature Disabled. Ensure Internal user is On")
}
settingsView
}

@ViewBuilder
Expand Down Expand Up @@ -99,7 +95,6 @@ struct DefaultBrowserPromptDebugView: View {
}
}
}
.disabled(!model.isFeatureEnabled)
.navigationTitle("Default Browser Prompt")
}
}
Expand All @@ -121,7 +116,6 @@ final class DefaultBrowserPromptDebugViewModel: ObservableObject {
return formatter
}()

@Published private(set) var isFeatureEnabled: Bool
@Published private(set) var activeDaysCount: Int
@Published private(set) var debugLog: DebugLog = .init()
@Published var defaultBrowserPromptUserType: DefaultBrowserPromptUserType? {
Expand Down Expand Up @@ -155,7 +149,6 @@ final class DefaultBrowserPromptDebugViewModel: ObservableObject {
currentDate = currentDateDebugStore.simulatedTodayDate
formattedCurrentDate = Self.dateFormatter.string(from: currentDateDebugStore.simulatedTodayDate)
activeDaysCount = userActivityStore.currentActivity().numberOfActiveDays
isFeatureEnabled = self.featureFlagger.isDefaultBrowserPromptsForActiveUsersFeatureEnabled
makeDebugLog()
}

Expand All @@ -180,7 +173,6 @@ final class DefaultBrowserPromptDebugViewModel: ObservableObject {
defaultBrowserPromptUserType = userTypeDebugStore.userType()
currentDate = currentDateDebugStore.simulatedTodayDate
activeDaysCount = userActivityStore.currentActivity().numberOfActiveDays
isFeatureEnabled = self.featureFlagger.isDefaultBrowserPromptsForActiveUsersFeatureEnabled
makeDebugLog()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,6 @@ struct DefaultBrowserPromptFeatureFlagAdapterTests {
private var featureFlaggerMock = MockFeatureFlagger(internalUserDecider: MockInternalUserDecider())
private var privacyConfigurationManagerMock = MockPrivacyConfigurationManager()

@Test("Check Default Browser Prompts For Active Users Method Is Forwarded To Feature Flagger")
func checkIsActiveUsersFeatureOnIsForwardedToFeatureFlagger() {
// GIVEN
featureFlaggerMock.enabledFeatureFlags = [.scheduledSetDefaultBrowserPrompts]
let sut = DefaultBrowserPromptFeatureFlagAdapter(featureFlagger: featureFlaggerMock, privacyConfigurationManager: privacyConfigurationManagerMock)

// WHEN
let result = sut.isDefaultBrowserPromptsForActiveUsersFeatureEnabled

// THEN
#expect(result)
}

@Test("Check Default Browser Prompts For Inactive Users Method Is Forwarded To Feature Flagger")
func checkIsInactiveUsersFeatureOnIsForwardedToFeatureFlagger() {
// GIVEN
featureFlaggerMock.enabledFeatureFlags = [.scheduledSetDefaultBrowserPromptsForInactiveUsers]
let sut = DefaultBrowserPromptFeatureFlagAdapter(featureFlagger: featureFlaggerMock, privacyConfigurationManager: privacyConfigurationManagerMock)

// WHEN
let result = sut.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled

// THEN
#expect(result)
}

@Test("Check Method is Dispatched To Feature Flagger")
func checkMethodIsDispatchedToPrivacyConfigurationManager() throws {
// GIVEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@

import Foundation

public protocol DefaultBrowserPromptActiveUserFeatureFlagProvider {
/// A Boolean value indicating whether Set Default Browser Prompts are enabled for active users.
/// - Returns: `true` if the feature is enabled; otherwise, `false`.
var isDefaultBrowserPromptsForActiveUsersFeatureEnabled: Bool { get }
}

public protocol DefaultBrowserPromptInactiveUserFeatureFlagProvider {
/// A Boolean value indicating whether Set Default Browser Prompts are enabled for inactive users.
/// - Returns: `true` if the feature is enabled; otherwise, `false`.
var isDefaultBrowserPromptsForInactiveUsersFeatureEnabled: Bool { get }
}

public typealias DefaultBrowserPromptFeatureFlagProvider = DefaultBrowserPromptActiveUserFeatureFlagProvider & DefaultBrowserPromptInactiveUserFeatureFlagProvider

public protocol DefaultBrowserPromptFeatureFlagSettingsProvider {
// A dictionary representing the settings for the feature.
var defaultBrowserPromptFeatureSettings: [String: Any] { get }
Expand Down Expand Up @@ -62,7 +48,7 @@ public enum DefaultBrowserPromptFeatureSettings: String {
}
}

package protocol DefaultBrowserPromptActiveUserFeatureFlagger: DefaultBrowserPromptActiveUserFeatureFlagProvider {
package protocol DefaultBrowserPromptActiveUserFeatureFlagger {
/// The number of active days to wait after app installation before showing the first modal for active users. Default is 1.
var firstActiveModalDelayDays: Int { get }
/// The number of active days to wait after the first modal has been shown before displaying the second modal for active users. Default is 4.
Expand All @@ -71,7 +57,7 @@ package protocol DefaultBrowserPromptActiveUserFeatureFlagger: DefaultBrowserPro
var subsequentActiveModalRepeatIntervalDays: Int { get }
}

package protocol DefaultBrowserPromptInactiveUserFeatureFlagger: DefaultBrowserPromptInactiveUserFeatureFlagProvider {
package protocol DefaultBrowserPromptInactiveUserFeatureFlagger {
/// The setting for the number of days to wait after app installation before showing the modal to inactive users. Default to 28.
var inactiveModalNumberOfDaysSinceInstall: Int { get }
/// The setting for the number of inactive days to wait before showing the modal to inactive users. Default to 7.
Expand All @@ -82,26 +68,16 @@ package typealias DefaultBrowserPromptFeatureFlagger = DefaultBrowserPromptActiv

package final class DefaultBrowserPromptFeatureFlag {
private let settingsProvider: DefaultBrowserPromptFeatureFlagSettingsProvider
private let featureFlagProvider: DefaultBrowserPromptFeatureFlagProvider

package init(settingsProvider: DefaultBrowserPromptFeatureFlagSettingsProvider, featureFlagProvider: DefaultBrowserPromptFeatureFlagProvider) {
package init(settingsProvider: DefaultBrowserPromptFeatureFlagSettingsProvider) {
self.settingsProvider = settingsProvider
self.featureFlagProvider = featureFlagProvider
}
}

// MARK: - DefaultBrowserPromptFeatureFlagger

extension DefaultBrowserPromptFeatureFlag: DefaultBrowserPromptFeatureFlagger {

public var isDefaultBrowserPromptsForActiveUsersFeatureEnabled: Bool {
featureFlagProvider.isDefaultBrowserPromptsForActiveUsersFeatureEnabled
}

public var isDefaultBrowserPromptsForInactiveUsersFeatureEnabled: Bool {
featureFlagProvider.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled
}

package var firstActiveModalDelayDays: Int {
getSettings(.firstActiveModalDelayDays)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ extension DefaultBrowserPromptTypeDecider {


func promptType() -> DefaultBrowserPromptType? {
// If Feature is disabled return nil
guard featureFlagger.isDefaultBrowserPromptsForActiveUsersFeatureEnabled else {
Logger.defaultBrowserPrompt.debug("[Default Browser Prompt] - Feature disabled.")
return nil
}

guard let userType = userTypeProvider.currentUserType() else {
Logger.defaultBrowserPrompt.debug("[Default Browser Prompt] - Failed to determine Active user type. Will not show prompt.")
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ extension DefaultBrowserPromptTypeDecider {
}

func promptType() -> DefaultBrowserPromptType? {
guard featureFlagger.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled else { return nil }

// Conditions to show prompt for inactive users:
// 1. The user has not seen this modal ever.
// 2. User has been inactive for at least seven days.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ import SetDefaultBrowserCore
public final class MockDefaultBrowserPromptFeatureFlag: DefaultBrowserPromptFeatureFlagger {
public init() {}

public var isDefaultBrowserPromptsForActiveUsersFeatureEnabled: Bool = true

public var isDefaultBrowserPromptsForInactiveUsersFeatureEnabled: Bool = true

public var firstActiveModalDelayDays: Int = 1

public var secondActiveModalDelayDays: Int = 2
Expand All @@ -38,14 +34,6 @@ public final class MockDefaultBrowserPromptFeatureFlag: DefaultBrowserPromptFeat
public var inactiveModalNumberOfInactiveDays: Int = 7
}

package final class MockDefaultBrowserPromptFeatureFlagProvider: DefaultBrowserPromptFeatureFlagProvider {
package var isDefaultBrowserPromptsForActiveUsersFeatureEnabled: Bool = true

package var isDefaultBrowserPromptsForInactiveUsersFeatureEnabled: Bool = true

package init() {}
}

package final class MockDefaultBrowserPromptFeatureFlagSettingsProvider: DefaultBrowserPromptFeatureFlagSettingsProvider {
package var defaultBrowserPromptFeatureSettings: [String: Any] = [:]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import UIKit
public enum DefaultBrowserPromptFactory {

public static func makeDefaultBrowserPromptPresenter(
featureFlagProvider: DefaultBrowserPromptFeatureFlagProvider,
featureFlagSettingsProvider: DefaultBrowserPromptFeatureFlagSettingsProvider,
promptActivityStore: DefaultBrowserPromptStorage,
userTypeProviding: DefaultBrowserPromptUserTypeProviding,
Expand All @@ -40,8 +39,7 @@ public enum DefaultBrowserPromptFactory {
) -> DefaultBrowserPromptPresenting {

let featureFlagger = DefaultBrowserPromptFeatureFlag(
settingsProvider: featureFlagSettingsProvider,
featureFlagProvider: featureFlagProvider
settingsProvider: featureFlagSettingsProvider
)

let defaultBrowserManager = DefaultBrowserManager(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,6 @@ final class DefaultBrowserPromptDeciderActiveUserTests {
)
}

@Test("Check No Modal Is Presented When Feature Is Disabled")
func checkPromptIsNilWhenFeatureFlagIsDisabled() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForActiveUsersFeatureEnabled = false
makeSUT()
#expect(!userTypeProviderMock.didCallCurrentUserType)

// WHEN
let result = sut.promptType()

// THEN
#expect(result == nil)
#expect(!userTypeProviderMock.didCallCurrentUserType)
}

@Test(
"Check First Modal is Presented When No Modal Have Shown And Installation Date Is >= 1 day",
arguments: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,9 @@ struct DefaultBrowserPromptDeciderInactiveUserTests {
)
}

@Test("Check Prompt Type Is Nil When It Should Show But Feature Flag Is Off")
func whenFeatureFlagIsOffThenReturnNil() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = false
storeMock.hasInactiveModalShown = false
userActivityProviderMock.numberOfInactiveDaysPassed = 40
let numberOfDaysSinceInstall: Int = 30
let sut = makeSUT(daysSinceInstall: numberOfDaysSinceInstall)

// WHEN
let result = sut.promptType()

// THEN
#expect(result == nil)
}

@Test("Check Prompt Type Is Nil When It Has Already Shown")
func whenHasInactiveModalShownStoreValueIsTrueThenReturnFalse() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
storeMock.hasInactiveModalShown = true
userActivityProviderMock.numberOfInactiveDaysPassed = 40
let numberOfDaysSinceInstall: Int = 30
Expand All @@ -73,7 +56,6 @@ struct DefaultBrowserPromptDeciderInactiveUserTests {
@Test("Check Prompt Type Is Nil When Number Of Inactive Days Is Less Than 7")
func whenNumberOfInactiveDaysIsLessThan7ThenReturnFalse() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
storeMock.hasInactiveModalShown = false
userActivityProviderMock.numberOfInactiveDaysPassed = 5
let numberOfDaysSinceInstall: Int = 30
Expand All @@ -89,7 +71,6 @@ struct DefaultBrowserPromptDeciderInactiveUserTests {
@Test("Check Prompt Type Is Nil When Number Of Days Since Install Is Less Than 28")
func whenNumberOfDaysSinceInstallIsLessThan28ThenReturnFalse() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
storeMock.hasInactiveModalShown = false
userActivityProviderMock.numberOfInactiveDaysPassed = 10
let numberOfDaysSinceInstall: Int = 27
Expand All @@ -105,7 +86,6 @@ struct DefaultBrowserPromptDeciderInactiveUserTests {
@Test("Check Prompt Type Is Inactive When Modal Has Not Shown, Number Of Inactive Days Is Greater Than 7 And Number Of Days Since Install Is Greater Than 28")
func checkPromptTypeIsInactive() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
storeMock.hasInactiveModalShown = false
userActivityProviderMock.numberOfInactiveDaysPassed = 10
let numberOfDaysSinceInstall: Int = 28
Expand All @@ -121,7 +101,6 @@ struct DefaultBrowserPromptDeciderInactiveUserTests {
@Test("Check Prompt Type Is Inactive When Modal Has Not Shown, Number Of Inactive Days Is Greater Than 7 And Number Of Days Since Install Is Greater Than 28")
func checkRulesToShowThePromptAreReadFromFeatureFlaggerSettings() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
featureFlaggerMock.inactiveModalNumberOfInactiveDays = 1
featureFlaggerMock.inactiveModalNumberOfDaysSinceInstall = 2
storeMock.hasInactiveModalShown = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ final class DefaultBrowserPromptDeciderTests {
@Test("Check No Modal Is Presented When Prompt Is Permanently Dismissed")
func checkPromptIsNilWhenPromptIsPermanentlyDismissed() {
// GIVEN
featureFlaggerMock.isDefaultBrowserPromptsForActiveUsersFeatureEnabled = true
featureFlaggerMock.isDefaultBrowserPromptsForInactiveUsersFeatureEnabled = true
storeMock.isPromptPermanentlyDismissed = true
makeSUT()
#expect(!userTypeProviderMock.didCallCurrentUserType)
Expand Down
Loading
Loading