From 556b858a0b0c07c152183b06c5dd52d1262ed38e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20=C5=9Apiewak?= Date: Mon, 4 Nov 2024 11:49:32 +0100 Subject: [PATCH 1/2] Add Privacy Config feature to control ad attribution reporting (#3506) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task/Issue URL: https://app.asana.com/0/0/1208638248015576/f Tech Design URL: CC: **Description**: Adds the ability to use remote config to control `AdAttributionPixelReporter` and whether the token is added as parameter. **Steps to test this PR**: ⚠️ Device is required to fully test this change. Attribution is not available on simulator. 1. Modify remote config URL to `https://www.jsonblob.com/api/1301173210350215168`. Put app in the background and reactivate. 2. Verify attribution pixel is fired including token parameter. 4. Remove the app, change `includeToken` setting to `false` in the linked configuration json file or remove setting object completely, verify attribution pixel is fired without token parameter. 5. Turn off the feature in configuration json, verify no attribution pixel is fired. **Definition of Done (Internal Only)**: * [ ] Does this PR satisfy our [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)? **Copy Testing**: * [ ] Use of correct apostrophes in new copy, ie `’` rather than `'` **Orientation Testing**: * [ ] Portrait * [ ] Landscape **Device Testing**: * [ ] iPhone SE (1st Gen) * [ ] iPhone 8 * [ ] iPhone X * [ ] iPhone 14 Pro * [ ] iPad **OS Testing**: * [ ] iOS 15 * [ ] iOS 16 * [ ] iOS 17 **Theme Testing**: * [ ] Light theme * [ ] Dark theme --- ###### Internal references: [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) --- Core/FeatureFlag.swift | 3 + DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../AdAttributionPixelReporter.swift | 34 +++++++++-- DuckDuckGo/AppDelegate.swift | 2 - .../AdAttributionPixelReporterTests.swift | 58 ++++++++++++++++++- 6 files changed, 91 insertions(+), 12 deletions(-) diff --git a/Core/FeatureFlag.swift b/Core/FeatureFlag.swift index 3a63769bb9..b877485851 100644 --- a/Core/FeatureFlag.swift +++ b/Core/FeatureFlag.swift @@ -45,6 +45,7 @@ public enum FeatureFlag: String { case onboardingAddToDock case autofillSurveys case autcompleteTabs + case adAttributionReporting /// https://app.asana.com/0/72649045549333/1208231259093710/f case networkProtectionUserTips @@ -103,6 +104,8 @@ extension FeatureFlag: FeatureFlagSourceProviding { return .remoteReleasable(.feature(.autocompleteTabs)) case .networkProtectionUserTips: return .remoteReleasable(.subfeature(NetworkProtectionSubfeature.userTips)) + case .adAttributionReporting: + return .remoteReleasable(.feature(.adAttributionReporting)) } } } diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 187e92d283..4a4cbaa73f 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -10970,7 +10970,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 203.0.0; + version = 203.1.0; }; }; 9F8FE9472BAE50E50071E372 /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 80a835b202..0be6bd842d 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "45261df2963fc89094e169f9f2d0d9aa098093f3", - "version" : "203.0.0" + "revision" : "19f1e5c945aa92562ad2d087e8d6c99801edf656", + "version" : "203.1.0" } }, { diff --git a/DuckDuckGo/AdAttribution/AdAttributionPixelReporter.swift b/DuckDuckGo/AdAttribution/AdAttributionPixelReporter.swift index a09eb9d693..c5c5f8a3cd 100644 --- a/DuckDuckGo/AdAttribution/AdAttributionPixelReporter.swift +++ b/DuckDuckGo/AdAttribution/AdAttributionPixelReporter.swift @@ -19,28 +19,37 @@ import Foundation import Core +import BrowserServicesKit final actor AdAttributionPixelReporter { - - static let isAdAttributionReportingEnabled = false - + static var shared = AdAttributionPixelReporter() private var fetcherStorage: AdAttributionReporterStorage private let attributionFetcher: AdAttributionFetcher + private let featureFlagger: FeatureFlagger + private let privacyConfigurationManager: PrivacyConfigurationManaging private let pixelFiring: PixelFiringAsync.Type private var isSendingAttribution: Bool = false init(fetcherStorage: AdAttributionReporterStorage = UserDefaultsAdAttributionReporterStorage(), attributionFetcher: AdAttributionFetcher = DefaultAdAttributionFetcher(), + featureFlagger: FeatureFlagger = AppDependencyProvider.shared.featureFlagger, + privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, pixelFiring: PixelFiringAsync.Type = Pixel.self) { self.fetcherStorage = fetcherStorage self.attributionFetcher = attributionFetcher self.pixelFiring = pixelFiring + self.featureFlagger = featureFlagger + self.privacyConfigurationManager = privacyConfigurationManager } @discardableResult func reportAttributionIfNeeded() async -> Bool { + guard featureFlagger.isFeatureOn(.adAttributionReporting) else { + return false + } + guard await fetcherStorage.wasAttributionReportSuccessful == false else { return false } @@ -57,7 +66,8 @@ final actor AdAttributionPixelReporter { if let (token, attributionData) = await self.attributionFetcher.fetch() { if attributionData.attribution { - let parameters = self.pixelParametersForAttribution(attributionData, attributionToken: token) + let settings = AdAttributionReporterSettings(privacyConfigurationManager.privacyConfig) + let parameters = self.pixelParametersForAttribution(attributionData, attributionToken: settings.includeToken ? token : nil) do { try await pixelFiring.fire( pixel: .appleAdAttribution, @@ -77,7 +87,7 @@ final actor AdAttributionPixelReporter { return false } - private func pixelParametersForAttribution(_ attribution: AdServicesAttributionResponse, attributionToken: String) -> [String: String] { + private func pixelParametersForAttribution(_ attribution: AdServicesAttributionResponse, attributionToken: String?) -> [String: String] { var params: [String: String] = [:] params[PixelParameters.adAttributionAdGroupID] = attribution.adGroupId.map(String.init) @@ -93,3 +103,17 @@ final actor AdAttributionPixelReporter { return params } } + +private struct AdAttributionReporterSettings { + var includeToken: Bool + + init(_ configuration: PrivacyConfiguration) { + let featureSettings = configuration.settings(for: .adAttributionReporting) + + self.includeToken = featureSettings[Key.includeToken] as? Bool ?? false + } + + private enum Key { + static let includeToken = "includeToken" + } +} diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index b5448d7b67..a585a0cbee 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -540,8 +540,6 @@ import os.log } private func reportAdAttribution() { - guard AdAttributionPixelReporter.isAdAttributionReportingEnabled else { return } - Task.detached(priority: .background) { await AdAttributionPixelReporter.shared.reportAttributionIfNeeded() } diff --git a/DuckDuckGoTests/AdAttributionPixelReporterTests.swift b/DuckDuckGoTests/AdAttributionPixelReporterTests.swift index 0a553d07b0..f8846346bd 100644 --- a/DuckDuckGoTests/AdAttributionPixelReporterTests.swift +++ b/DuckDuckGoTests/AdAttributionPixelReporterTests.swift @@ -26,15 +26,24 @@ final class AdAttributionPixelReporterTests: XCTestCase { private var attributionFetcher: AdAttributionFetcherMock! private var fetcherStorage: AdAttributionReporterStorageMock! + private var featureFlagger: MockFeatureFlagger! + private var privacyConfigurationManager: PrivacyConfigurationManagerMock! override func setUpWithError() throws { attributionFetcher = AdAttributionFetcherMock() fetcherStorage = AdAttributionReporterStorageMock() + featureFlagger = MockFeatureFlagger() + privacyConfigurationManager = PrivacyConfigurationManagerMock() + + featureFlagger.enabledFeatureFlags.append(.adAttributionReporting) } override func tearDownWithError() throws { attributionFetcher = nil fetcherStorage = nil + featureFlagger = nil + privacyConfigurationManager = nil + PixelFiringMock.tearDown() } @@ -59,7 +68,7 @@ final class AdAttributionPixelReporterTests: XCTestCase { XCTAssertFalse(result) } - func testPixelname() async { + func testPixelName() async { let sut = createSUT() attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true)) @@ -72,6 +81,7 @@ final class AdAttributionPixelReporterTests: XCTestCase { func testPixelAttributesNaming() async throws { let sut = createSUT() attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true)) + (privacyConfigurationManager.privacyConfig as? PrivacyConfigurationMock)?.settings[.adAttributionReporting] = ["includeToken": true] await sut.reportAttributionIfNeeded() @@ -157,9 +167,50 @@ final class AdAttributionPixelReporterTests: XCTestCase { XCTAssertFalse(result) } + func testDoesNotReportIfFeatureDisabled() async { + let sut = createSUT() + attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true)) + featureFlagger.enabledFeatureFlags = [] + + await fetcherStorage.markAttributionReportSuccessful() + let result = await sut.reportAttributionIfNeeded() + + XCTAssertNil(PixelFiringMock.lastPixelName) + XCTAssertFalse(result) + XCTAssertFalse(attributionFetcher.wasFetchCalled) + } + + func testDoesNotIncludeTokenWhenSettingMissing() async throws { + let sut = createSUT() + attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true)) + featureFlagger.enabledFeatureFlags = [.adAttributionReporting] + + await sut.reportAttributionIfNeeded() + + let pixelAttributes = try XCTUnwrap(PixelFiringMock.lastParams) + + XCTAssertNil(pixelAttributes["attribution_token"]) + } + + func testIncludesTokenWhenSettingEnabled() async throws { + let sut = createSUT() + attributionFetcher.fetchResponse = ("example", AdServicesAttributionResponse(attribution: true)) + featureFlagger.enabledFeatureFlags = [.adAttributionReporting] + + (privacyConfigurationManager.privacyConfig as? PrivacyConfigurationMock)?.settings[.adAttributionReporting] = ["includeToken": true] + + await sut.reportAttributionIfNeeded() + + let pixelAttributes = try XCTUnwrap(PixelFiringMock.lastParams) + + XCTAssertNotNil(pixelAttributes["attribution_token"]) + } + private func createSUT() -> AdAttributionPixelReporter { AdAttributionPixelReporter(fetcherStorage: fetcherStorage, attributionFetcher: attributionFetcher, + featureFlagger: featureFlagger, + privacyConfigurationManager: privacyConfigurationManager, pixelFiring: PixelFiringMock.self) } } @@ -173,9 +224,12 @@ class AdAttributionReporterStorageMock: AdAttributionReporterStorage { } class AdAttributionFetcherMock: AdAttributionFetcher { + var wasFetchCalled: Bool = false + var fetchResponse: (String, AdServicesAttributionResponse)? func fetch() async -> (String, AdServicesAttributionResponse)? { - fetchResponse + wasFetchCalled = true + return fetchResponse } } From 1c2abb9f69ebd76ebc3c45196bc7097fd286ac88 Mon Sep 17 00:00:00 2001 From: Michal Smaga Date: Mon, 4 Nov 2024 12:51:08 +0100 Subject: [PATCH 2/2] Release 7.144.0-0 (#3528) Please make sure all GH checks passed before merging. It can take around 20 minutes. Briefly review this PR to see if there are no issues or red flags and then merge it. --- Configuration/Version.xcconfig | 2 +- .../AppPrivacyConfigurationDataProvider.swift | 4 +- Core/ios-config.json | 238 ++++++++---------- DuckDuckGo.xcodeproj/project.pbxproj | 56 ++--- DuckDuckGo/Settings.bundle/Root.plist | 2 +- fastlane/README.md | 8 + 6 files changed, 141 insertions(+), 169 deletions(-) diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index e99711a2c3..40ae091e7d 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 7.143.0 +MARKETING_VERSION = 7.144.0 diff --git a/Core/AppPrivacyConfigurationDataProvider.swift b/Core/AppPrivacyConfigurationDataProvider.swift index 15f2c36375..3036ae8a6a 100644 --- a/Core/AppPrivacyConfigurationDataProvider.swift +++ b/Core/AppPrivacyConfigurationDataProvider.swift @@ -23,8 +23,8 @@ import BrowserServicesKit final public class AppPrivacyConfigurationDataProvider: EmbeddedDataProvider { public struct Constants { - public static let embeddedDataETag = "\"f8b9cfd5f1eb7b77c21d4476f85bd177\"" - public static let embeddedDataSHA = "c26c97714d73a9e1e99dbd341d5890da42b49d34a296672be3d3cea00bdd37a0" + public static let embeddedDataETag = "\"516f95a16f7a556c58e14ee6f193cc30\"" + public static let embeddedDataSHA = "87314e1ac02784472a722844a27b443b0387a164ac72afaac00d9a70731fc572" } public var embeddedDataEtag: String { diff --git a/Core/ios-config.json b/Core/ios-config.json index edd16be36c..b7d7ecc0d0 100644 --- a/Core/ios-config.json +++ b/Core/ios-config.json @@ -1,6 +1,6 @@ { "readme": "https://github.com/duckduckgo/privacy-configuration", - "version": 1730109523334, + "version": 1730481067679, "features": { "adClickAttribution": { "readme": "https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/#3rd-party-tracker-loading-protection", @@ -93,9 +93,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -122,7 +119,7 @@ ] }, "state": "enabled", - "hash": "d9703d9553194bc54e66db1f2a4ec1f8" + "hash": "fa5f86bac5946c528cd6bc7449a2718a" }, "androidBrowserConfig": { "exceptions": [], @@ -363,6 +360,36 @@ { "domain": "la-becanerie.com" }, + { + "domain": "thrifty.com" + }, + { + "domain": "dollar.com" + }, + { + "domain": "ethicalconsumer.org" + }, + { + "domain": "diroots.com" + }, + { + "domain": "arbeitsagentur.de" + }, + { + "domain": "melawear.de" + }, + { + "domain": "dnb.com" + }, + { + "domain": "bookings.ltmuseum.co.uk" + }, + { + "domain": "famillemary.fr" + }, + { + "domain": "manoloblahnik.com" + }, { "domain": "marvel.com" }, @@ -377,9 +404,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -407,7 +431,7 @@ } } }, - "hash": "8392e127a3bcaee5c2913df355a7d254" + "hash": "c2885a67db26958bdb316564d5c94878" }, "autofillBreakageReporter": { "state": "enabled", @@ -505,12 +529,15 @@ }, { "percent": 50 + }, + { + "percent": 100 } ] } } }, - "hash": "9de8e4b066aa23f7c20ca638ee0d9f1a" + "hash": "91e54b0d57fbf1cf8668c9a929631432" }, "bookmarks": { "state": "enabled", @@ -534,12 +561,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "3766f6af346d3fffdf1e8ffce682c66e" + "hash": "37e0cf88badfc8b01b6394f0884502f6" }, "brokenSitePrompt": { "state": "enabled", @@ -1243,9 +1267,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -1263,7 +1284,7 @@ } }, "state": "disabled", - "hash": "3973e9d924c9a054df7f5dffad1f1d19" + "hash": "cb1f114a9e0314393b2a0f789cba163f" }, "clickToPlay": { "exceptions": [ @@ -1281,9 +1302,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -1296,7 +1314,7 @@ } }, "state": "disabled", - "hash": "31a06101df1dc362bfcef2d7a6320f80" + "hash": "894fb86c1f058aee9db47cfcdf3637de" }, "clientBrandHint": { "exceptions": [], @@ -1340,16 +1358,13 @@ "domain": "flexmls.com" }, { - "domain": "humana.com" + "domain": "centerwellpharmacy.com" }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "980bf875526f3cc7892c001a7d2e5a74" + "hash": "1cc80acd10d985c950e40c5b876c581b" }, "contextualOnboarding": { "exceptions": [], @@ -1372,6 +1387,10 @@ { "domain": "payments.google.com", "reason": "After sign-in for Google Pay flows (after flickering is resolved), blocking this causes the loading spinner to spin indefinitely, and the payment flow cannot proceed." + }, + { + "domain": "docs.google.com", + "reason": "Embedded Google docs get into redirect loop if signed into a Google account" } ], "firstPartyTrackerCookiePolicy": { @@ -1419,13 +1438,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "cef2b67a9df0d36b0875e7b54d33a4d0" + "hash": "fce0a9ccd7ae060d25e7debe4d8905fb" }, "customUserAgent": { "settings": { @@ -1446,6 +1462,10 @@ { "domain": "ihg.com", "reason": "https://github.com/duckduckgo/privacy-configuration/pull/2383" + }, + { + "domain": "humana.com", + "reason": "https://github.com/duckduckgo/privacy-configuration/pull/2408" } ], "ddgDefaultSites": [ @@ -1475,7 +1495,7 @@ }, "exceptions": [], "state": "enabled", - "hash": "e577ccb473bdb7ada49c4d3c6e79cf01" + "hash": "345d837217e74afd3f9e5fd04b208fa7" }, "dbp": { "state": "disabled", @@ -1617,9 +1637,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -4169,6 +4186,15 @@ } ] }, + { + "domain": "salon.com", + "rules": [ + { + "selector": ".fc-ab-root", + "type": "hide" + } + ] + }, { "domain": "scmp.com", "rules": [ @@ -4939,7 +4965,7 @@ ] }, "state": "enabled", - "hash": "9518158b11d290809536a99f637f467e" + "hash": "d8fb8089fcfbd527940703c8e2665966" }, "exceptionHandler": { "exceptions": [ @@ -4957,13 +4983,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "a214254da3cc914ed5bfc0a2d893b589" + "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" }, "extendedOnboarding": { "exceptions": [], @@ -4990,12 +5013,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "008c61cd03c28287a7f86b598c37078b" + "hash": "7f042650922da2636492e77ed1101bce" }, "fingerprintingBattery": { "exceptions": [ @@ -5016,13 +5036,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "enabled", - "hash": "d05606a02ffd6ce5e223bc26e748a203" + "hash": "fcc2138fa97c35ded544b39708fda919" }, "fingerprintingCanvas": { "settings": { @@ -5127,13 +5144,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "b0eef1a098ab8c6cc9d6da35a9cfb7ad" + "hash": "49a3d497835bf5715aaaa73f87dd974f" }, "fingerprintingHardware": { "settings": { @@ -5199,13 +5213,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "enabled", - "hash": "25a38bd7ccbca83ce0899548608235a7" + "hash": "cd4a8461973d1c1648dd20e6d1f532a7" }, "fingerprintingScreenSize": { "settings": { @@ -5259,13 +5270,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "enabled", - "hash": "c22a6e9f1c03693516589c47970d7a04" + "hash": "046340bb9287a20efed6189525ec5fed" }, "fingerprintingTemporaryStorage": { "exceptions": [ @@ -5292,13 +5300,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "enabled", - "hash": "48b1d8e96ee94825378d12a8d5a66895" + "hash": "14b7fe3d276b52109c59f0c71aee4f71" }, "googleRejected": { "exceptions": [ @@ -5316,13 +5321,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "a214254da3cc914ed5bfc0a2d893b589" + "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" }, "gpc": { "state": "enabled", @@ -5371,9 +5373,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -5385,7 +5384,7 @@ "privacy-test-pages.site" ] }, - "hash": "37630ab090682ee7d004120a42031281" + "hash": "501bbc6471eb079cb27fa8a2a47467a5" }, "harmfulApis": { "settings": { @@ -5501,13 +5500,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "f255e336420119584b7000846be6d456" + "hash": "fb598c4167ff166d85dd49c701cc5579" }, "history": { "state": "enabled", @@ -5558,12 +5554,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "7407fc43cbd260f9aaca7cb7dab15bf4" + "hash": "b47d255c6f836ecb7ae0b3e61cc2c025" }, "incontextSignup": { "exceptions": [], @@ -5622,9 +5615,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -5635,7 +5625,7 @@ ] }, "state": "enabled", - "hash": "a1100eac5ecca0a11501df9f4dafa31a" + "hash": "d14f6e3a9aa4139ee1d517016b59691e" }, "networkProtection": { "state": "enabled", @@ -5682,13 +5672,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "5646a778c1cb6ec6e9c0da2c7dbd4bdb" + "hash": "82088db85ca7f64418fbfd57db25ade1" }, "performanceMetrics": { "state": "enabled", @@ -5707,12 +5694,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "60c3c3eed29e1e0c092fad8775483210" + "hash": "6792064606a5a72c5cd44addb4d40bda" }, "phishingDetection": { "state": "disabled", @@ -5731,12 +5715,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "3766f6af346d3fffdf1e8ffce682c66e" + "hash": "37e0cf88badfc8b01b6394f0884502f6" }, "pluginPointFocusedViewPlugin": { "state": "disabled", @@ -5853,13 +5834,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "68eb25a9461b134838100eecb0271905" + "hash": "138c3b2409f6b3bf967b804ab9bf2ce2" }, "remoteMessaging": { "state": "enabled", @@ -5883,15 +5861,12 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { "windowInMs": 0 }, - "hash": "13d2723b0c33943f086acb8c239e22e8" + "hash": "baf19d9e0f506ed09f46c95b1849adee" }, "runtimeChecks": { "state": "disabled", @@ -5910,13 +5885,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": {}, - "hash": "568cf394681d38683d1aeb8f0d0e6a7c" + "hash": "dfede9f06b9e322e198736703d013d15" }, "sendFullPackageInstallSource": { "state": "enabled", @@ -5940,13 +5912,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "a214254da3cc914ed5bfc0a2d893b589" + "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" }, "sslCertificates": { "state": "enabled", @@ -5991,6 +5960,11 @@ "minSupportedVersion": "7.104.0", "hash": "d7dca6ee484eadebb5133e3f15fd9f41" }, + "textZoom": { + "exceptions": [], + "state": "enabled", + "hash": "52857469413a66e8b0c7b00de5589162" + }, "toggleReports": { "state": "enabled", "exceptions": [], @@ -6813,6 +6787,13 @@ "history.com" ] }, + { + "rule": "doubleclick.net/ondemand/dash/content/", + "domains": [ + "cbs.com", + "paramountplus.com" + ] + }, { "rule": "securepubads.g.doubleclick.net/gampad/ads", "domains": [ @@ -7425,7 +7406,8 @@ "piedmontng.com", "thesimsresource.com", "tradersync.com", - "vanguardplan.com" + "vanguardplan.com", + "xpn.org" ] } ] @@ -9363,12 +9345,9 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], - "hash": "434130223ee6493827d477d0171521da" + "hash": "c28128dee65a2aa7fef1528b73f33c7f" }, "trackingCookies1p": { "settings": { @@ -9392,13 +9371,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "a5c95510cb55fbe69cbff10e55a982dd" + "hash": "763f56424b0827b5731927a043219912" }, "trackingCookies3p": { "settings": { @@ -9419,13 +9395,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "5646a778c1cb6ec6e9c0da2c7dbd4bdb" + "hash": "82088db85ca7f64418fbfd57db25ade1" }, "trackingParameters": { "exceptions": [ @@ -9449,9 +9422,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "settings": { @@ -9484,7 +9454,7 @@ ] }, "state": "enabled", - "hash": "e530308726226930ff9a058fa064a39f" + "hash": "3805ecfb8a129f70a99e73a364b38f38" }, "userAgentRotation": { "settings": { @@ -9505,13 +9475,10 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "disabled", - "hash": "dd373ef0993c7ca9d9fa949db6d6aca0" + "hash": "9225b8785d6973db37abde99d81d219c" }, "voiceSearch": { "exceptions": [], @@ -9542,9 +9509,6 @@ }, { "domain": "instructure.com" - }, - { - "domain": "centerwellpharmacy.com" } ], "state": "enabled", @@ -9617,7 +9581,7 @@ } ] }, - "hash": "ed17f6ff342f200305eb4bbe544efec0" + "hash": "2853748f3ebb813d59f4db4a7bb13c83" }, "webViewBlobDownload": { "exceptions": [], diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 4a4cbaa73f..42d05b4f6c 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9185,7 +9185,7 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProvider.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -9222,7 +9222,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9312,7 +9312,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9339,7 +9339,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9488,7 +9488,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGo.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -9513,7 +9513,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGo.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; INFOPLIST_FILE = DuckDuckGo/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9582,7 +9582,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; @@ -9616,7 +9616,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -9649,7 +9649,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9679,7 +9679,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9989,7 +9989,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGoAlpha.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -10020,7 +10020,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10048,7 +10048,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10081,7 +10081,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; @@ -10111,7 +10111,7 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProviderAlpha.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -10144,11 +10144,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 2; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -10381,7 +10381,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGoAlpha.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -10408,7 +10408,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10440,7 +10440,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10477,7 +10477,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -10512,7 +10512,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10547,11 +10547,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 2; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -10724,11 +10724,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 2; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -10757,10 +10757,10 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 2; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/DuckDuckGo/Settings.bundle/Root.plist b/DuckDuckGo/Settings.bundle/Root.plist index a7f84961db..6e1c6ef73b 100644 --- a/DuckDuckGo/Settings.bundle/Root.plist +++ b/DuckDuckGo/Settings.bundle/Root.plist @@ -6,7 +6,7 @@ DefaultValue - 7.143.0 + 7.144.0 Key version Title diff --git a/fastlane/README.md b/fastlane/README.md index 195f7f9607..bb3195509a 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -69,6 +69,14 @@ Makes Ad-Hoc build with a specified name and release bundle ID in a given direct Makes Ad-Hoc build for alpha with a specified name and alpha bundle ID in a given directory +### promote_latest_testflight_to_appstore + +```sh +[bundle exec] fastlane promote_latest_testflight_to_appstore +``` + +Promotes the latest TestFlight build to App Store without submitting for review + ### release_appstore ```sh