diff --git a/Core/Pixel.swift b/Core/Pixel.swift index 9f87a0dec6..9b50dae725 100644 --- a/Core/Pixel.swift +++ b/Core/Pixel.swift @@ -84,6 +84,7 @@ public struct PixelParameters { public static let tabControllerCacheCount = "tab_controller_cache_count" public static let count = "count" + public static let source = "source" public static let textSizeInitial = "text_size_initial" public static let textSizeUpdated = "text_size_updated" @@ -147,6 +148,10 @@ public struct PixelParameters { // Privacy Dashboard public static let daysSinceInstall = "daysSinceInstall" public static let fromOnboarding = "from_onboarding" + + // Subscription + public static let privacyProKeychainAccessType = "access_type" + public static let privacyProKeychainError = "error" } public struct PixelValues { diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index 0ee619340d..fa146fdf3a 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -688,6 +688,7 @@ extension Pixel { case privacyProSubscriptionManagementRemoval case privacyProTransactionProgressNotHiddenAfter60s case privacyProSuccessfulSubscriptionAttribution + case privacyProKeychainAccessError // MARK: Pixel Experiment case pixelExperimentEnrollment @@ -1460,6 +1461,7 @@ extension Pixel.Event { case .privacyProSubscriptionManagementRemoval: return "m_privacy-pro_settings_remove-from-device_click" case .privacyProTransactionProgressNotHiddenAfter60s: return "m_privacy-pro_progress_not_hidden_after_60s" case .privacyProSuccessfulSubscriptionAttribution: return "m_subscribe" + case .privacyProKeychainAccessError: return "m_privacy-pro_keychain_access_error" // MARK: Pixel Experiment case .pixelExperimentEnrollment: return "pixel_experiment_enrollment" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 17e3b6058f..4fa2e17d10 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -67,6 +67,7 @@ 1E4F4A5A297193DE00625985 /* MainViewController+CookiesManaged.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4F4A59297193DE00625985 /* MainViewController+CookiesManaged.swift */; }; 1E4FAA6427D8DFB900ADC5B3 /* OngoingDownloadRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4FAA6327D8DFB900ADC5B3 /* OngoingDownloadRowViewModel.swift */; }; 1E4FAA6627D8DFC800ADC5B3 /* CompleteDownloadRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4FAA6527D8DFC800ADC5B3 /* CompleteDownloadRowViewModel.swift */; }; + 1E53508F2C7C9A1F00818DAA /* DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53508E2C7C9A1F00818DAA /* DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift */; }; 1E60989B290009C700A508F9 /* Common in Frameworks */ = {isa = PBXBuildFile; productRef = 1E7060BD28F88EE200E4CCDB /* Common */; }; 1E60989D290011E600A508F9 /* ContentBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 1E60989C290011E600A508F9 /* ContentBlocking */; }; 1E6098A1290011E600A508F9 /* UserScript in Frameworks */ = {isa = PBXBuildFile; productRef = 1E6098A0290011E600A508F9 /* UserScript */; }; @@ -1312,6 +1313,7 @@ 1E4F4A59297193DE00625985 /* MainViewController+CookiesManaged.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainViewController+CookiesManaged.swift"; sourceTree = ""; }; 1E4FAA6327D8DFB900ADC5B3 /* OngoingDownloadRowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingDownloadRowViewModel.swift; sourceTree = ""; }; 1E4FAA6527D8DFC800ADC5B3 /* CompleteDownloadRowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompleteDownloadRowViewModel.swift; sourceTree = ""; }; + 1E53508E2C7C9A1F00818DAA /* DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift"; sourceTree = ""; }; 1E61BC2927074BED00B2854D /* TextSizeUserScript.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextSizeUserScript.swift; sourceTree = ""; }; 1E6A4D682984208800A371D3 /* LocaleExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocaleExtension.swift; sourceTree = ""; }; 1E7A71162934EB6400B7EA19 /* OmniBarNotificationAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OmniBarNotificationAnimator.swift; sourceTree = ""; }; @@ -5079,6 +5081,7 @@ BDE91CD42C6292BF0005CB74 /* Feedback */, F1FDC92F2BF4E0B3006B1435 /* SubscriptionEnvironment+Default.swift */, D60170BB2BA32DD6001911B5 /* Subscription.swift */, + 1E53508E2C7C9A1F00818DAA /* DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift */, D6D95CE42B6DA3F200960317 /* AsyncHeadlessWebview */, D664C7952B289AA000CBFA76 /* Subscription.storekit */, D664C7932B289AA000CBFA76 /* ViewModel */, @@ -7457,6 +7460,7 @@ B6CB93E5286445AB0090FEB4 /* Base64DownloadSession.swift in Sources */, 1EEF387D285B1A1100383393 /* TrackerImageCache.swift in Sources */, 3151F0EC27357FEE00226F58 /* VoiceSearchFeedbackViewModel.swift in Sources */, + 1E53508F2C7C9A1F00818DAA /* DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift in Sources */, 1DDF402D2BA09482006850D9 /* SettingsMainSettingsView.swift in Sources */, 85010502292FB1000033978F /* FireproofFaviconUpdater.swift in Sources */, F1C4A70E1E57725800A6CA1B /* OmniBar.swift in Sources */, @@ -10627,7 +10631,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 188.0.0; + version = 188.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 036f584a2e..a184ff8d6b 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" : "faf25f57d1d61ff855216178c454616031585c07", - "version" : "188.0.0" + "revision" : "ce1b7228a38d2b18525590256051a012109cfee6", + "version" : "188.1.0" } }, { @@ -138,7 +138,7 @@ { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser", + "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { "revision" : "0fbc8848e389af3bb55c182bc19ca9d5dc2f255b", "version" : "1.4.0" diff --git a/DuckDuckGo/AppDependencyProvider.swift b/DuckDuckGo/AppDependencyProvider.swift index 9fb8e62f7c..2577e88ea6 100644 --- a/DuckDuckGo/AppDependencyProvider.swift +++ b/DuckDuckGo/AppDependencyProvider.swift @@ -112,11 +112,14 @@ class AppDependencyProvider: DependencyProvider { subscriptionEndpointService: subscriptionService, authEndpointService: authService) - subscriptionManager = DefaultSubscriptionManager(storePurchaseManager: DefaultStorePurchaseManager(), - accountManager: accountManager, - subscriptionEndpointService: subscriptionService, - authEndpointService: authService, - subscriptionEnvironment: subscriptionEnvironment) + let subscriptionManager = DefaultSubscriptionManager(storePurchaseManager: DefaultStorePurchaseManager(), + accountManager: accountManager, + subscriptionEndpointService: subscriptionService, + authEndpointService: authService, + subscriptionEnvironment: subscriptionEnvironment) + accountManager.delegate = subscriptionManager + + self.subscriptionManager = subscriptionManager let subscriptionFeatureAvailability: SubscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, diff --git a/DuckDuckGo/Subscription/DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift b/DuckDuckGo/Subscription/DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift new file mode 100644 index 0000000000..dbd2042c86 --- /dev/null +++ b/DuckDuckGo/Subscription/DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift @@ -0,0 +1,36 @@ +// +// DefaultSubscriptionManager+AccountManagerKeychainAccessDelegate.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import Core +import Subscription + +extension DefaultSubscriptionManager: AccountManagerKeychainAccessDelegate { + + public func accountManagerKeychainAccessFailed(accessType: AccountKeychainAccessType, error: AccountKeychainAccessError) { + let parameters = [ + PixelParameters.privacyProKeychainAccessType: accessType.rawValue, + PixelParameters.privacyProKeychainError: error.errorDescription, + PixelParameters.source: "browser" + ] + + DailyPixel.fireDailyAndCount(pixel: .privacyProKeychainAccessError, + withAdditionalParameters: parameters) + } +} diff --git a/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift b/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift index ea6020ff0e..c3ff764a5c 100644 --- a/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift +++ b/PacketTunnelProvider/NetworkProtection/NetworkProtectionPacketTunnelProvider.swift @@ -384,6 +384,8 @@ final class NetworkProtectionPacketTunnelProvider: PacketTunnelProvider { defaults: .networkProtectionGroupDefaults, isSubscriptionEnabled: true, entitlementCheck: { return await Self.entitlementCheck(accountManager: accountManager) }) + + accountManager.delegate = self startMonitoringMemoryPressureEvents() observeServerChanges() APIRequest.Headers.setUserAgent(DefaultUserAgentManager.duckDuckGoUserAgent) @@ -476,3 +478,17 @@ final class DefaultWireGuardInterface: WireGuardInterface { wgSetLogger(context, logFunction) } } + +extension NetworkProtectionPacketTunnelProvider: AccountManagerKeychainAccessDelegate { + + public func accountManagerKeychainAccessFailed(accessType: AccountKeychainAccessType, error: AccountKeychainAccessError) { + let parameters = [ + PixelParameters.privacyProKeychainAccessType: accessType.rawValue, + PixelParameters.privacyProKeychainError: error.errorDescription, + PixelParameters.source: "vpn" + ] + + DailyPixel.fireDailyAndCount(pixel: .privacyProKeychainAccessError, + withAdditionalParameters: parameters) + } +}