diff --git a/Core/UserAgentManager.swift b/Core/UserAgentManager.swift index 7e3571c0b0..5f57b7807a 100644 --- a/Core/UserAgentManager.swift +++ b/Core/UserAgentManager.swift @@ -113,7 +113,7 @@ struct UserAgent { static let ddgFixedUserAgentConfigKey = "ddgFixedUserAgent" static let uaVersionsKey = "versions" - static let uaStateKey = "state" // todo: do we need it? + static let uaStateKey = "state" // swiftlint:enable line_length } @@ -128,14 +128,15 @@ struct UserAgent { private let versionComponent: String private let safariComponent: String private let applicationComponent = "DuckDuckGo/\(AppVersion.shared.majorVersionNumber)" - private let statistics: StatisticsUserDefaults = StatisticsUserDefaults() + private let statistics: StatisticsStore private let isTesting: Bool = ProcessInfo().arguments.contains("testing") - init(defaultAgent: String = Constants.fallbackDefaultAgent) { + init(defaultAgent: String = Constants.fallbackDefaultAgent, statistics: StatisticsStore = StatisticsUserDefaults()) { versionComponent = UserAgent.createVersionComponent(fromAgent: defaultAgent) baseAgent = UserAgent.createBaseAgent(fromAgent: defaultAgent, versionComponent: versionComponent) baseDesktopAgent = UserAgent.createBaseDesktopAgent(fromAgent: defaultAgent, versionComponent: versionComponent) safariComponent = UserAgent.createSafariComponent(fromAgent: baseAgent) + self.statistics = statistics } private func omitApplicationSites(forConfig config: PrivacyConfiguration) -> [String] { @@ -168,16 +169,16 @@ struct UserAgent { private func closestUserAgentVersions(forConfig config: PrivacyConfiguration) -> [String] { let uaSettings = config.settings(for: .customUserAgent) - let closestUserAgentObjs = uaSettings[Constants.closestUserAgentConfigKey] as? [[String: String]] ?? [] - return [""] -// return closestUserAgentObjs.map { $0[Constants.uaOmitDomainConfigKey] ?? "" } + let closestUserAgent = uaSettings[Constants.closestUserAgentConfigKey] as? [String: Any] ?? [:] + let versions = closestUserAgent[Constants.uaVersionsKey] as? [String] ?? [] + return versions } private func ddgFixedUserAgentVersions(forConfig config: PrivacyConfiguration) -> [String] { let uaSettings = config.settings(for: .customUserAgent) - let closestUserAgentObjs = uaSettings[Constants.closestUserAgentConfigKey] as? [[String: String]] ?? [] - return [""] -// return closestUserAgentObjs.map { $0[Constants.uaOmitDomainConfigKey] ?? "" } + let fixedUserAgent = uaSettings[Constants.ddgFixedUserAgentConfigKey] as? [String: Any] ?? [:] + let versions = fixedUserAgent[Constants.uaVersionsKey] as? [String] ?? [] + return versions } public func agent(forUrl url: URL?, @@ -196,6 +197,14 @@ struct UserAgent { url?.isPart(ofDomain: domain) ?? false }) { return ddgFixedLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) } + if closestUserAgentVersions(forConfig: privacyConfig).contains(statistics.atb ?? "") { + return closestLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) + } + + if ddgFixedUserAgentVersions(forConfig: privacyConfig).contains(statistics.atb ?? "") { + return ddgFixedLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) + } + switch defaultPolicy(forConfig: privacyConfig) { case .ddg: return oldLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) case .ddgFixed: return ddgFixedLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) diff --git a/DuckDuckGoTests/UserAgentTests.swift b/DuckDuckGoTests/UserAgentTests.swift index be7bb014fd..0b1f73475f 100644 --- a/DuckDuckGoTests/UserAgentTests.swift +++ b/DuckDuckGoTests/UserAgentTests.swift @@ -22,7 +22,8 @@ import XCTest import BrowserServicesKit @testable import Core -class UserAgentTests: XCTestCase { +// swiftlint:disable file_length type_body_length +final class UserAgentTests: XCTestCase { private struct DefaultAgent { static let mobile = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" @@ -362,4 +363,61 @@ class UserAgentTests: XCTestCase { XCTAssertEqual(ExpectedAgent.mobileFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: false, privacyConfig: config)) } + let configWithVersions = """ + { + "features": { + "customUserAgent": { + "state": "enabled", + "settings": { + "defaultPolicy": "ddg", + "omitApplicationSites": [ + { + "domain": "cvs.com", + "reason": "Site reports browser not supported" + } + ], + "closestUserAgent": { + "versions": ["v350-1", "v360-1"] + }, + "ddgFixedUserAgent": { + "versions": ["v351-1", "v361-1"] + } + }, + "exceptions": [] + } + }, + "unprotectedTemporary": [] + } + """.data(using: .utf8)! + + func testWhenAtbDoesNotMatchVersionFromConfigThenDefaultUAIsUsed() { + let statisticsStore = MockStatisticsStore() + statisticsStore.atb = "v300-1" + let testee = UserAgent(defaultAgent: DefaultAgent.mobile, statistics: statisticsStore) + let config = makePrivacyConfig(from: configWithVersions) + XCTAssertEqual(ExpectedAgent.mobile, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenAtbMatchesVersionInClosestUserAgentThenClosestUAIsUsed() { + let statisticsStore = MockStatisticsStore() + statisticsStore.atb = "v360-1" + let testee = UserAgent(defaultAgent: DefaultAgent.mobile, statistics: statisticsStore) + let config = makePrivacyConfig(from: configWithVersions) + XCTAssertEqual(ExpectedAgent.mobileClosest, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenAtbMatchesVersionInDDGFixedUserAgentThenDDGFixedUAIsUsed() { + let statisticsStore = MockStatisticsStore() + statisticsStore.atb = "v361-1" + let testee = UserAgent(defaultAgent: DefaultAgent.mobile, statistics: statisticsStore) + let config = makePrivacyConfig(from: configWithVersions) + XCTAssertEqual(ExpectedAgent.mobileFixed, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + } + + + + + +