diff --git a/Core/UserDefaultsPropertyWrapper.swift b/Core/UserDefaultsPropertyWrapper.swift index e5316c4e73..2cd47169db 100644 --- a/Core/UserDefaultsPropertyWrapper.swift +++ b/Core/UserDefaultsPropertyWrapper.swift @@ -57,6 +57,7 @@ public struct UserDefaultsWrapper { case legacyCovidInfo = "com.duckduckgo.ios.home.covidInfo" case lastConfigurationRefreshDate = "com.duckduckgo.ios.lastConfigurationRefreshDate" + case lastConfigurationUpdateDate = "com.duckduckgo.ios.lastConfigurationUpdateDate" case lastRemoteMessagingRefreshDate = "com.duckduckgo.ios.lastRemoteMessagingRefreshDate" case doNotSell = "com.duckduckgo.ios.sendDoNotSell" @@ -106,12 +107,16 @@ public struct UserDefaultsWrapper { case syncIsEligibleForFaviconsFetcherOnboarding = "com.duckduckgo.ios.sync-is-eligible-for-favicons-fetcher-onboarding" case syncDidPresentFaviconsFetcherOnboarding = "com.duckduckgo.ios.sync-did-present-favicons-fetcher-onboarding" case syncDidMigrateToImprovedListsHandling = "com.duckduckgo.ios.sync-did-migrate-to-improved-lists-handling" + case syncDidShowSyncPausedByFeatureFlagAlert = "com.duckduckgo.ios.sync-did-show-sync-paused-by-feature-flag-alert" case networkProtectionDebugOptionAlwaysOnDisabled = "com.duckduckgo.network-protection.always-on.disabled" case networkProtectionWaitlistTermsAndConditionsAccepted = "com.duckduckgo.ios.vpn.terms-and-conditions-accepted" case addressBarPosition = "com.duckduckgo.ios.addressbarposition" case showFullSiteAddress = "com.duckduckgo.ios.showfullsiteaddress" + + case privacyConfigCustomURL = "com.duckduckgo.ios.privacyConfigCustomURL" + } private let key: Key diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index ee67435747..8c42096ede 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -538,6 +538,7 @@ 9830A06325ED0DB900DB64DE /* BrowsingMenu.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9830A06225ED0DB900DB64DE /* BrowsingMenu.xcassets */; }; 9833913727AC400800DAF119 /* AppTrackerDataSetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9833913627AC400800DAF119 /* AppTrackerDataSetProvider.swift */; }; 9838059F2228208E00385F1A /* PositiveFeedbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9838059E2228208E00385F1A /* PositiveFeedbackViewController.swift */; }; + 983BD6B52B34760600AAC78E /* MockPrivacyConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B0F6412AB08BE9001EAF05 /* MockPrivacyConfiguration.swift */; }; 983D71B12A286E810072E26D /* SyncDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983D71B02A286E810072E26D /* SyncDebugViewController.swift */; }; 983EABB8236198F6003948D1 /* DatabaseMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983EABB7236198F6003948D1 /* DatabaseMigration.swift */; }; 984147A824F0259000362052 /* Onboarding.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 984147AA24F0259000362052 /* Onboarding.storyboard */; }; @@ -719,7 +720,6 @@ C18ED43A2AB6F77600BF3805 /* AutofillSettingsEnableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18ED4392AB6F77600BF3805 /* AutofillSettingsEnableFooterView.swift */; }; C18ED43C2AB8364400BF3805 /* FileTextPreviewDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18ED43B2AB8364400BF3805 /* FileTextPreviewDebugViewController.swift */; }; C1963863283794A000298D4D /* BookmarksCachingSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1963862283794A000298D4D /* BookmarksCachingSearch.swift */; }; - C1B0F6422AB08BE9001EAF05 /* MockPrivacyConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B0F6412AB08BE9001EAF05 /* MockPrivacyConfiguration.swift */; }; C1B7B51C28941E980098FD6A /* HomeMessageViewModelBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B51B28941E980098FD6A /* HomeMessageViewModelBuilder.swift */; }; C1B7B52328941F2A0098FD6A /* RemoteMessagingStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B51F28941F2A0098FD6A /* RemoteMessagingStore.swift */; }; C1B7B52428941F2A0098FD6A /* RemoteMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B52028941F2A0098FD6A /* RemoteMessageRequest.swift */; }; @@ -766,6 +766,7 @@ CBDD5DDF29A6736A00832877 /* APIHeadersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDD5DDE29A6736A00832877 /* APIHeadersTests.swift */; }; CBDD5DE129A6741300832877 /* MockBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDD5DE029A6741300832877 /* MockBundle.swift */; }; CBEFB9142AE0844700DEDE7B /* CriticalAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBEFB9102ADFFE7900DEDE7B /* CriticalAlerts.swift */; }; + CBFCB30E2B2CD47800253E9E /* ConfigurationURLDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBFCB30D2B2CD47800253E9E /* ConfigurationURLDebugViewController.swift */; }; D63657192A7BAE7C001AF19D /* EmailManagerRequestDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63657182A7BAE7C001AF19D /* EmailManagerRequestDelegate.swift */; }; EA39B7E2268A1A35000C62CD /* privacy-reference-tests in Resources */ = {isa = PBXBuildFile; fileRef = EA39B7E1268A1A35000C62CD /* privacy-reference-tests */; }; EAB19EDA268963510015D3EA /* DomainMatchingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB19ED9268963510015D3EA /* DomainMatchingTests.swift */; }; @@ -2365,6 +2366,7 @@ CBF14FC227970072001D94D0 /* HomeMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeMessageView.swift; sourceTree = ""; }; CBF14FC427970AB0001D94D0 /* HomeMessageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeMessageViewModel.swift; sourceTree = ""; }; CBF14FC627970C8A001D94D0 /* HomeMessageCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeMessageCollectionViewCell.swift; sourceTree = ""; }; + CBFCB30D2B2CD47800253E9E /* ConfigurationURLDebugViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationURLDebugViewController.swift; sourceTree = ""; }; D63657182A7BAE7C001AF19D /* EmailManagerRequestDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailManagerRequestDelegate.swift; sourceTree = ""; }; EA39B7E1268A1A35000C62CD /* privacy-reference-tests */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "privacy-reference-tests"; path = "submodules/privacy-reference-tests"; sourceTree = SOURCE_ROOT; }; EAB19ED9268963510015D3EA /* DomainMatchingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DomainMatchingTests.swift; sourceTree = ""; }; @@ -3839,6 +3841,7 @@ F46FEC5627987A5F0061D9DF /* KeychainItemsDebugViewController.swift */, 983D71B02A286E810072E26D /* SyncDebugViewController.swift */, EE72CA842A862D000043B5B3 /* NetworkProtectionDebugViewController.swift */, + CBFCB30D2B2CD47800253E9E /* ConfigurationURLDebugViewController.swift */, ); name = Debug; sourceTree = ""; @@ -6428,6 +6431,7 @@ 85582E0029D7409700E9AE35 /* SyncSettingsViewController+PDFRendering.swift in Sources */, EE0153EF2A70021E002A8B26 /* NetworkProtectionInviteView.swift in Sources */, 9888F77B2224980500C46159 /* FeedbackViewController.swift in Sources */, + CBFCB30E2B2CD47800253E9E /* ConfigurationURLDebugViewController.swift in Sources */, 982686AD2600C0850011A8D6 /* ActionMessageView.swift in Sources */, F446B9B5251150AC00324016 /* HomeMessageViewSectionRenderer.swift in Sources */, 98D98A8225ED88E300D8E3DF /* BrowsingMenuSeparatorViewCell.swift in Sources */, @@ -6623,7 +6627,6 @@ C1B7B52428941F2A0098FD6A /* RemoteMessageRequest.swift in Sources */, EE9D68DA2AE1659F00B55EF4 /* NetworkProtectionVPNNotificationsViewModel.swift in Sources */, 1E8AD1D727C2E24E00ABA377 /* DownloadsListRowViewModel.swift in Sources */, - C1B0F6422AB08BE9001EAF05 /* MockPrivacyConfiguration.swift in Sources */, 1E865AF0272042DB001C74F3 /* TextSizeSettingsViewController.swift in Sources */, 8524CC9A246DA81700E59D45 /* FullscreenDaxDialogViewController.swift in Sources */, F17669D71E43401C003D3222 /* MainViewController.swift in Sources */, @@ -6705,6 +6708,7 @@ 8341D807212D5E8D000514C2 /* HashExtensionTest.swift in Sources */, C1D21E2F293A599C006E5A05 /* AutofillLoginSessionTests.swift in Sources */, 85D2187924BF6B8B004373D2 /* FaviconSourcesProviderTests.swift in Sources */, + 983BD6B52B34760600AAC78E /* MockPrivacyConfiguration.swift in Sources */, 1E8146AD28C8ABF000D1AF63 /* TrackerAnimationLogicTests.swift in Sources */, C1CDA31E2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift in Sources */, B6AD9E3A28D456820019CDE9 /* PrivacyConfigurationManagerMock.swift in Sources */, @@ -9224,7 +9228,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 97.0.0; + version = 99.0.0; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5eb1e13d46..cdee4384e6 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "d671accf1bf7097c4e7f5cd55cd1c6dfa005cf92", - "version" : "97.0.0" + "revision" : "2c1c2bb0aad5a23524e298fa9bea9b890ae43e23", + "version" : "99.0.0" } }, { @@ -122,8 +122,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser", "state" : { - "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41", - "version" : "1.3.0" + "revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531", + "version" : "1.2.3" } }, { diff --git a/DuckDuckGo/AppConfigurationFetch.swift b/DuckDuckGo/AppConfigurationFetch.swift index b40b56d92c..fcf1664d94 100644 --- a/DuckDuckGo/AppConfigurationFetch.swift +++ b/DuckDuckGo/AppConfigurationFetch.swift @@ -98,6 +98,7 @@ class AppConfigurationFetch { } func start(isBackgroundFetch: Bool = false, + isDebug: Bool = false, completion: AppConfigurationFetchCompletion?) { guard Self.shouldRefresh else { // Statistics are not sent after a successful background refresh in order to reduce the time spent in the background, so they are checked @@ -113,7 +114,7 @@ class AppConfigurationFetch { type(of: self).fetchQueue.async { let taskID = UIApplication.shared.beginBackgroundTask(withName: Constants.backgroundTaskName) - self.fetchConfigurationFiles(isBackground: isBackgroundFetch) { result in + self.fetchConfigurationFiles(isBackground: isBackgroundFetch, isDebug: isDebug) { result in if !isBackgroundFetch { type(of: self).fetchQueue.async { self.sendStatistics { @@ -165,10 +166,10 @@ class AppConfigurationFetch { #endif } - private func fetchConfigurationFiles(isBackground: Bool, onDidComplete: @escaping AppConfigurationFetchCompletion) { + private func fetchConfigurationFiles(isBackground: Bool, isDebug: Bool = false, onDidComplete: @escaping AppConfigurationFetchCompletion) { Task { self.markFetchStarted(isBackground: isBackground) - let result = await AppDependencyProvider.shared.configurationManager.update() + let result = await AppDependencyProvider.shared.configurationManager.update(isDebug: isDebug) switch result { case .noData: diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index 3f916036b4..66ca786016 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -84,6 +84,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // MARK: lifecycle + @UserDefaultsWrapper(key: .privacyConfigCustomURL, defaultValue: nil) + private var privacyConfigCustomURL: String? + // swiftlint:disable:next function_body_length cyclomatic_complexity func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { @@ -105,7 +108,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { cleanUpIncrementalRolloutPixelTest() APIRequest.Headers.setUserAgent(DefaultUserAgentManager.duckDuckGoUserAgent) - Configuration.setURLProvider(AppConfigurationURLProvider()) + + if isDebugBuild, let privacyConfigCustomURL, let url = URL(string: privacyConfigCustomURL) { + Configuration.setURLProvider(CustomConfigurationURLProvider(customPrivacyConfigurationURL: url)) + } else { + Configuration.setURLProvider(AppConfigurationURLProvider()) + } CrashCollection.start { Pixel.fire(pixel: .dbCrashDetected, withAdditionalParameters: $0, includedParameters: []) diff --git a/DuckDuckGo/AppDependencyProvider.swift b/DuckDuckGo/AppDependencyProvider.swift index 5f7854281c..b23caebde0 100644 --- a/DuckDuckGo/AppDependencyProvider.swift +++ b/DuckDuckGo/AppDependencyProvider.swift @@ -46,7 +46,7 @@ class AppDependencyProvider: DependencyProvider { let appSettings: AppSettings = AppUserDefaults() let variantManager: VariantManager = DefaultVariantManager() - let internalUserDecider: InternalUserDecider = DefaultInternalUserDecider(store: InternalUserStore()) + let internalUserDecider: InternalUserDecider = ContentBlocking.shared.privacyConfigurationManager.internalUserDecider private lazy var privacyConfig: PrivacyConfiguration = ContentBlocking.shared.privacyConfigurationManager.privacyConfig lazy var featureFlagger: FeatureFlagger = DefaultFeatureFlagger(internalUserDecider: internalUserDecider, privacyConfig: privacyConfig) diff --git a/DuckDuckGo/Base.lproj/Settings.storyboard b/DuckDuckGo/Base.lproj/Settings.storyboard index 5f66405727..69c60efd61 100644 --- a/DuckDuckGo/Base.lproj/Settings.storyboard +++ b/DuckDuckGo/Base.lproj/Settings.storyboard @@ -101,7 +101,7 @@ - +