diff --git a/Sources/BrowserServicesKit/PrivacyConfig/AppPrivacyConfiguration.swift b/Sources/BrowserServicesKit/PrivacyConfig/AppPrivacyConfiguration.swift index 534ad6088..89e64093d 100644 --- a/Sources/BrowserServicesKit/PrivacyConfig/AppPrivacyConfiguration.swift +++ b/Sources/BrowserServicesKit/PrivacyConfig/AppPrivacyConfiguration.swift @@ -49,6 +49,10 @@ public struct AppPrivacyConfiguration: PrivacyConfiguration { self.installDate = installDate } + public var version: String? { + return data.version + } + public var userUnprotectedDomains: [String] { return Array(locallyUnprotected.unprotectedDomains).normalizedDomainsForContentBlocking().sorted() } diff --git a/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfiguration.swift b/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfiguration.swift index 48deca33f..37d5ace68 100644 --- a/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfiguration.swift +++ b/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfiguration.swift @@ -37,6 +37,9 @@ public protocol PrivacyConfiguration { /// Identifier of given Privacy Configuration, typically an ETag var identifier: String { get } + /// Version of config parsed from the `version` key + var version: String? { get } + /// Domains for which user has toggled protection off. /// /// Use `isUserUnprotected(domain:)` to check if given domain is unprotected. diff --git a/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfigurationData.swift b/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfigurationData.swift index 7deba1283..813c87503 100644 --- a/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfigurationData.swift +++ b/Sources/BrowserServicesKit/PrivacyConfig/PrivacyConfigurationData.swift @@ -27,6 +27,7 @@ public struct PrivacyConfigurationData { case features case unprotectedTemporary case trackerAllowlist + case version } public struct State { @@ -38,6 +39,7 @@ public struct PrivacyConfigurationData { public let features: [FeatureName: PrivacyFeature] public let trackerAllowlist: TrackerAllowlist public let unprotectedTemporary: [ExceptionEntry] + public let version: String? public init(data: Data) throws { guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { @@ -48,6 +50,12 @@ public struct PrivacyConfigurationData { internal init(json: [String: Any]) { + if let versionInt = json[CodingKeys.version.rawValue] as? Int { + version = String(versionInt) + } else { + version = json[CodingKeys.version.rawValue] as? String + } + if let tempListData = json[CodingKeys.unprotectedTemporary.rawValue] as? [[String: String]] { unprotectedTemporary = tempListData.compactMap({ ExceptionEntry(json: $0) }) } else { @@ -84,10 +92,12 @@ public struct PrivacyConfigurationData { public init(features: [FeatureName: PrivacyFeature], unprotectedTemporary: [ExceptionEntry], - trackerAllowlist: TrackerAllowlistData) { + trackerAllowlist: TrackerAllowlistData, + version: String? = nil) { self.features = features self.unprotectedTemporary = unprotectedTemporary self.trackerAllowlist = TrackerAllowlist(entries: trackerAllowlist, state: State.enabled) + self.version = version } public class PrivacyFeature { diff --git a/Sources/PrivacyDashboard/BrokenSiteReporting/BrokenSiteReport.swift b/Sources/PrivacyDashboard/BrokenSiteReporting/BrokenSiteReport.swift index 39a600d7f..b0d028048 100644 --- a/Sources/PrivacyDashboard/BrokenSiteReporting/BrokenSiteReport.swift +++ b/Sources/PrivacyDashboard/BrokenSiteReporting/BrokenSiteReport.swift @@ -81,6 +81,7 @@ public struct BrokenSiteReport { let manufacturer: String let upgradedHttps: Bool let tdsETag: String? + let configVersion: String? let blockedTrackerDomains: [String] let installedSurrogates: [String] let isGPCEnabled: Bool @@ -112,6 +113,7 @@ public struct BrokenSiteReport { manufacturer: String, upgradedHttps: Bool, tdsETag: String?, + configVersion: String?, blockedTrackerDomains: [String]?, installedSurrogates: [String]?, isGPCEnabled: Bool, @@ -134,6 +136,7 @@ public struct BrokenSiteReport { self.manufacturer = manufacturer self.upgradedHttps = upgradedHttps self.tdsETag = tdsETag + self.configVersion = configVersion self.blockedTrackerDomains = blockedTrackerDomains ?? [] self.installedSurrogates = installedSurrogates ?? [] self.isGPCEnabled = isGPCEnabled @@ -160,6 +163,7 @@ public struct BrokenSiteReport { manufacturer: String, upgradedHttps: Bool, tdsETag: String?, + configVersion: String?, blockedTrackerDomains: [String]?, installedSurrogates: [String]?, isGPCEnabled: Bool, @@ -186,6 +190,7 @@ public struct BrokenSiteReport { self.manufacturer = manufacturer self.upgradedHttps = upgradedHttps self.tdsETag = tdsETag + self.configVersion = configVersion self.blockedTrackerDomains = blockedTrackerDomains ?? [] self.installedSurrogates = installedSurrogates ?? [] self.isGPCEnabled = isGPCEnabled @@ -215,6 +220,7 @@ public struct BrokenSiteReport { "siteUrl": siteUrl.trimmingQueryItemsAndFragment().absoluteString, "upgradedHttps": upgradedHttps.description, "tds": tdsETag?.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) ?? "", + "remote_config_version": configVersion ?? "", "blockedTrackers": blockedTrackerDomains.joined(separator: ","), "surrogates": installedSurrogates.joined(separator: ","), "gpc": isGPCEnabled.description, diff --git a/Tests/BrowserServicesKitTests/ContentBlocker/UserContentControllerTests.swift b/Tests/BrowserServicesKitTests/ContentBlocker/UserContentControllerTests.swift index c14459a60..e1cb475cd 100644 --- a/Tests/BrowserServicesKitTests/ContentBlocker/UserContentControllerTests.swift +++ b/Tests/BrowserServicesKitTests/ContentBlocker/UserContentControllerTests.swift @@ -331,6 +331,7 @@ class PrivacyConfigurationMock: PrivacyConfiguration { } var identifier: String = "abcd" + var version: String? = "123456789" var userUnprotectedDomains: [String] = [] var tempUnprotectedDomains: [String] = [] var trackerAllowlist: PrivacyConfigurationData.TrackerAllowlist = .init(json: ["state": "disabled"])! diff --git a/Tests/BrowserServicesKitTests/PrivacyConfig/PrivacyConfigurationDataTests.swift b/Tests/BrowserServicesKitTests/PrivacyConfig/PrivacyConfigurationDataTests.swift index 94fcd1b6e..f4406afef 100644 --- a/Tests/BrowserServicesKitTests/PrivacyConfig/PrivacyConfigurationDataTests.swift +++ b/Tests/BrowserServicesKitTests/PrivacyConfig/PrivacyConfigurationDataTests.swift @@ -28,6 +28,8 @@ class PrivacyConfigurationDataTests: XCTestCase { let jsonData = data.fromJsonFile("Resources/privacy-config-example.json") let configData = try PrivacyConfigurationData(data: jsonData) + XCTAssertEqual(configData.version, "2021.6.7") + XCTAssertEqual(configData.unprotectedTemporary.count, 1) XCTAssertEqual(configData.unprotectedTemporary.first?.domain, "example.com") diff --git a/Tests/BrowserServicesKitTests/Subscription/SubscriptionFeatureAvailabilityTests.swift b/Tests/BrowserServicesKitTests/Subscription/SubscriptionFeatureAvailabilityTests.swift index cb3cfbc7f..a85dadc1e 100644 --- a/Tests/BrowserServicesKitTests/Subscription/SubscriptionFeatureAvailabilityTests.swift +++ b/Tests/BrowserServicesKitTests/Subscription/SubscriptionFeatureAvailabilityTests.swift @@ -233,6 +233,7 @@ class MockPrivacyConfiguration: PrivacyConfiguration { } var identifier: String = "abcd" + var version: String? = "123456789" var userUnprotectedDomains: [String] = [] var tempUnprotectedDomains: [String] = [] var trackerAllowlist: PrivacyConfigurationData.TrackerAllowlist = .init(json: ["state": "disabled"])! diff --git a/Tests/DDGSyncTests/Mocks/Mocks.swift b/Tests/DDGSyncTests/Mocks/Mocks.swift index 6a7b4c662..d2af3b0a4 100644 --- a/Tests/DDGSyncTests/Mocks/Mocks.swift +++ b/Tests/DDGSyncTests/Mocks/Mocks.swift @@ -181,6 +181,7 @@ class MockPrivacyConfiguration: PrivacyConfiguration { } var identifier: String = "abcd" + var version: String? = "123456789" var userUnprotectedDomains: [String] = [] var tempUnprotectedDomains: [String] = [] var trackerAllowlist: PrivacyConfigurationData.TrackerAllowlist = .init(json: ["state": "disabled"])! diff --git a/Tests/PrivacyDashboardTests/BrokenSiteReportMocks.swift b/Tests/PrivacyDashboardTests/BrokenSiteReportMocks.swift index 9721f5108..25e895659 100644 --- a/Tests/PrivacyDashboardTests/BrokenSiteReportMocks.swift +++ b/Tests/PrivacyDashboardTests/BrokenSiteReportMocks.swift @@ -30,6 +30,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true, @@ -55,6 +56,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true, @@ -80,6 +82,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true, @@ -105,6 +108,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true, @@ -130,6 +134,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true, @@ -155,6 +160,7 @@ struct BrokenSiteReportMocks { manufacturer: "Apple", upgradedHttps: true, tdsETag: "test", + configVersion: "123456789", blockedTrackerDomains: [], installedSurrogates: [], isGPCEnabled: true,