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/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/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 e8634921d8..efe8934aaf 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9176,7 +9176,7 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProvider.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9214,8 +9214,8 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9305,8 +9305,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9333,8 +9333,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9482,7 +9482,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; @@ -9506,8 +9506,8 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGo.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; INFOPLIST_FILE = DuckDuckGo/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9574,7 +9574,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; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; @@ -9608,8 +9608,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9641,8 +9641,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9672,8 +9672,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9988,7 +9988,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; @@ -10019,8 +10019,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10048,8 +10048,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10082,8 +10082,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10112,8 +10112,8 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProviderAlpha.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -10146,11 +10146,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"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Core/Info.plist; @@ -10384,7 +10384,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; @@ -10411,8 +10411,8 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10444,8 +10444,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10482,8 +10482,8 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10517,8 +10517,8 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + CURRENT_PROJECT_VERSION = 0; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10553,11 +10553,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"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Core/Info.plist; @@ -10732,11 +10732,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"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Core/Info.plist; @@ -10767,11 +10767,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + 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"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Core/Info.plist; @@ -10983,7 +10983,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/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 e9ad217140..dba5c2a78e 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -536,8 +536,6 @@ import os.log } private func reportAdAttribution() { - guard AdAttributionPixelReporter.isAdAttributionReportingEnabled else { return } - Task.detached(priority: .background) { await AdAttributionPixelReporter.shared.reportAttributionIfNeeded() } 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/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 } } 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