From 18cbbda1730eabe724d1e05710bc37b4eddcf0e5 Mon Sep 17 00:00:00 2001 From: Pete Smith Date: Thu, 21 Mar 2024 17:41:56 +0000 Subject: [PATCH] Improve Data Reporting for Chromium Keychain User Actions (#2469) Task/Issue URL: https://app.asana.com/0/1206488453854252/1206886138223449/f **Description**: * Stop firing an error Pixel when the user cancels Keychain password entry * Add new non-error pixel for user being prompted for Keychain password entry * Add new non-error pixel for user denying keychain access event --- .../Logins/Chromium/ChromiumKeychainPrompt.swift | 4 ++++ DuckDuckGo/DataImport/Model/DataImportViewModel.swift | 2 +- DuckDuckGo/Statistics/PixelEvent.swift | 8 ++++++++ DuckDuckGo/Statistics/PixelParameters.swift | 4 +++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo/DataImport/Logins/Chromium/ChromiumKeychainPrompt.swift b/DuckDuckGo/DataImport/Logins/Chromium/ChromiumKeychainPrompt.swift index 3c30a50f90..4e473eada8 100644 --- a/DuckDuckGo/DataImport/Logins/Chromium/ChromiumKeychainPrompt.swift +++ b/DuckDuckGo/DataImport/Logins/Chromium/ChromiumKeychainPrompt.swift @@ -43,6 +43,10 @@ final class ChromiumKeychainPrompt: ChromiumKeychainPrompting { kSecMatchLimit as String: kSecMatchLimitOne] as [String: Any] var dataFromKeychain: AnyObject? + + // Fire Pixel to help measure rate of password prompt denied actions + Pixel.fire(.passwordImportKeychainPrompt) + let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataFromKeychain) if status == noErr, let passwordData = dataFromKeychain as? Data { diff --git a/DuckDuckGo/DataImport/Model/DataImportViewModel.swift b/DuckDuckGo/DataImport/Model/DataImportViewModel.swift index c0c7f1343e..1a2d1eef7b 100644 --- a/DuckDuckGo/DataImport/Model/DataImportViewModel.swift +++ b/DuckDuckGo/DataImport/Model/DataImportViewModel.swift @@ -286,7 +286,7 @@ struct DataImportViewModel { switch error { // chromium user denied keychain prompt error case let error as ChromiumLoginReader.ImportError where error.type == .userDeniedKeychainPrompt: - Pixel.fire(.dataImportFailed(source: importSource, sourceVersion: importSource.installedAppsMajorVersionDescription(selectedProfile: selectedProfile), error: error)) + Pixel.fire(.passwordImportKeychainPromptDenied) // stay on the same screen return true diff --git a/DuckDuckGo/Statistics/PixelEvent.swift b/DuckDuckGo/Statistics/PixelEvent.swift index bd576d9bf0..80a43dc6b8 100644 --- a/DuckDuckGo/Statistics/PixelEvent.swift +++ b/DuckDuckGo/Statistics/PixelEvent.swift @@ -269,6 +269,10 @@ extension Pixel { case toggleReportDoNotSend case toggleReportDismiss + // Password Import Keychain Prompt + case passwordImportKeychainPrompt + case passwordImportKeychainPromptDenied + enum Debug { /// This is a convenience pixel that allows us to fire `PixelKitEvents` using our /// regular `Pixel.fire()` calls. This is a convenience intermediate step to help ensure @@ -694,6 +698,10 @@ extension Pixel.Event { case .toggleReportDoNotSend: return "m_mac_toggle-report-do-not-send" case .toggleReportDismiss: return "m_mac_toggle-report-dismiss" + // Password Import Keychain Prompt + case .passwordImportKeychainPrompt: return "m_mac_password_import_keychain_prompt" + case .passwordImportKeychainPromptDenied: return "m_mac_password_import_keychain_prompt_denied" + } } } diff --git a/DuckDuckGo/Statistics/PixelParameters.swift b/DuckDuckGo/Statistics/PixelParameters.swift index bca6af9060..9238a76d77 100644 --- a/DuckDuckGo/Statistics/PixelParameters.swift +++ b/DuckDuckGo/Statistics/PixelParameters.swift @@ -209,7 +209,9 @@ extension Pixel.Event { .privacyProOfferMonthlyPriceClick, .privacyProOfferYearlyPriceClick, .privacyProAddEmailSuccess, - .privacyProWelcomeFAQClick: + .privacyProWelcomeFAQClick, + .passwordImportKeychainPrompt, + .passwordImportKeychainPromptDenied: return nil } }