Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Bundle-Specfic Autofill Secure Vault Keychain Items #2652

Merged
merged 14 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@
3706FC71293F65D500E42796 /* NSColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41D174025CB131900472416 /* NSColorExtension.swift */; };
3706FC73293F65D500E42796 /* AddressBarButtonsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC5E4F525D6BF2C007F5990 /* AddressBarButtonsViewController.swift */; };
3706FC77293F65D500E42796 /* PageObserverUserScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 853014D525E671A000FB8205 /* PageObserverUserScript.swift */; };
3706FC78293F65D500E42796 /* SecureVaultErrorReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */; };
3706FC78293F65D500E42796 /* SecureVaultReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B642738127B65BAC0005DFD1 /* SecureVaultReporter.swift */; };
3706FC79293F65D500E42796 /* NSImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B139AFC26B60BD800894F82 /* NSImageExtensions.swift */; };
3706FC7B293F65D500E42796 /* PasswordManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85625995269C953C00EE44BC /* PasswordManagementViewController.swift */; };
3706FC7C293F65D500E42796 /* ImportedBookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CFA26FE191E001E4761 /* ImportedBookmarks.swift */; };
Expand Down Expand Up @@ -2054,7 +2054,7 @@
B63ED0E026AFE32F00A9DAD1 /* GeolocationProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0DF26AFE32F00A9DAD1 /* GeolocationProviderMock.swift */; };
B63ED0E326B3E7FA00A9DAD1 /* CLLocationManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0E226B3E7FA00A9DAD1 /* CLLocationManagerMock.swift */; };
B63ED0E526BB8FB900A9DAD1 /* SharingMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0E426BB8FB900A9DAD1 /* SharingMenu.swift */; };
B642738227B65BAC0005DFD1 /* SecureVaultErrorReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */; };
B642738227B65BAC0005DFD1 /* SecureVaultReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B642738127B65BAC0005DFD1 /* SecureVaultReporter.swift */; };
B643BF1427ABF772000BACEC /* NSWorkspaceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */; };
B644B43D29D56829003FA9AB /* SearchNonexistentDomainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B644B43929D565DB003FA9AB /* SearchNonexistentDomainTests.swift */; };
B644B43E29D5682B003FA9AB /* SearchNonexistentDomainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B644B43929D565DB003FA9AB /* SearchNonexistentDomainTests.swift */; };
Expand Down Expand Up @@ -3660,7 +3660,7 @@
B63ED0DF26AFE32F00A9DAD1 /* GeolocationProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeolocationProviderMock.swift; sourceTree = "<group>"; };
B63ED0E226B3E7FA00A9DAD1 /* CLLocationManagerMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLLocationManagerMock.swift; sourceTree = "<group>"; };
B63ED0E426BB8FB900A9DAD1 /* SharingMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingMenu.swift; sourceTree = "<group>"; };
B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureVaultErrorReporter.swift; sourceTree = "<group>"; };
B642738127B65BAC0005DFD1 /* SecureVaultReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureVaultReporter.swift; sourceTree = "<group>"; };
B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceExtension.swift; sourceTree = "<group>"; };
B644B43929D565DB003FA9AB /* SearchNonexistentDomainTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchNonexistentDomainTests.swift; sourceTree = "<group>"; };
B645D8F529FA95440024461F /* WKProcessPoolExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKProcessPoolExtension.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5934,7 +5934,7 @@
85CC1D7826A05E790062F04E /* Model */,
85CC1D7F26A05F6C0062F04E /* Services */,
85CC1D7926A05E820062F04E /* View */,
B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */,
B642738127B65BAC0005DFD1 /* SecureVaultReporter.swift */,
);
path = SecureVault;
sourceTree = "<group>";
Expand Down Expand Up @@ -9952,7 +9952,7 @@
C1372EF52BBC5BAD003F8793 /* SecureTextField.swift in Sources */,
3706FC77293F65D500E42796 /* PageObserverUserScript.swift in Sources */,
4BF0E5132AD25A2600FFEC9E /* DuckDuckGoUserAgent.swift in Sources */,
3706FC78293F65D500E42796 /* SecureVaultErrorReporter.swift in Sources */,
3706FC78293F65D500E42796 /* SecureVaultReporter.swift in Sources */,
3706FC79293F65D500E42796 /* NSImageExtensions.swift in Sources */,
3706FEBD293F6EFF00E42796 /* BWCommand.swift in Sources */,
3706FC7B293F65D500E42796 /* PasswordManagementViewController.swift in Sources */,
Expand Down Expand Up @@ -11263,7 +11263,7 @@
1D2DC0072901679C008083A1 /* BWError.swift in Sources */,
853014D625E671A000FB8205 /* PageObserverUserScript.swift in Sources */,
B677FC4F2B06376B0099EB04 /* ReportFeedbackView.swift in Sources */,
B642738227B65BAC0005DFD1 /* SecureVaultErrorReporter.swift in Sources */,
B642738227B65BAC0005DFD1 /* SecureVaultReporter.swift in Sources */,
4B139AFD26B60BD800894F82 /* NSImageExtensions.swift in Sources */,
B62B48392ADE46FC000DECE5 /* Application.swift in Sources */,
4B9DB02C2A983B24000927DB /* WaitlistKeychainStorage.swift in Sources */,
Expand Down Expand Up @@ -12564,8 +12564,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 137.0.0;
kind = revision;
revision = c06709ba8a586f6a40190bacaaaaa96b2d55e540;
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "4ce049682cb47a9fb510237070666e5e8bf1e07b",
"version" : "137.0.0"
"revision" : "c06709ba8a586f6a40190bacaaaaa96b2d55e540"
}
},
{
Expand Down Expand Up @@ -138,7 +137,7 @@
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
"version" : "509.1.1"
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Autofill/AutofillActionBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extension AutofillActionBuilder {
struct AutofillDeleteAllPasswordsBuilder: AutofillActionBuilder {
@MainActor
func buildExecutor() -> AutofillActionExecutor? {
guard let secureVault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared),
guard let secureVault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared),
let syncService = NSApp.delegateTyped.syncService else { return nil }

return AutofillDeleteAllPasswordsExecutor(userAuthenticator: DeviceAuthenticator.shared,
Expand Down
4 changes: 2 additions & 2 deletions DuckDuckGo/Autofill/ContentOverlayViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ extension ContentOverlayViewController: SecureVaultManagerDelegate {
}
}

public func secureVaultInitFailed(_ error: SecureStorageError) {
SecureVaultErrorReporter.shared.secureVaultInitFailed(error)
public func secureVaultError(_ error: SecureStorageError) {
SecureVaultReporter.shared.secureVaultError(error)
}

public func secureVaultManager(_: BrowserServicesKit.SecureVaultManager, didReceivePixel pixel: AutofillUserScript.JSPixel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import SecureStorage
final class SecureVaultLoginImporter: LoginImporter {

func importLogins(_ logins: [ImportedLoginCredential], progressCallback: @escaping (Int) throws -> Void) throws -> DataImport.DataTypeSummary {
let vault = try AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)
let vault = try AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)

var successful: [String] = []
var duplicates: [String] = []
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Fire/Model/Fire.swift
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ final class Fire {
// MARK: - Favicons

private func autofillDomains() -> Set<String> {
guard let vault = try? secureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared),
guard let vault = try? secureVaultFactory.makeVault(reporter: SecureVaultReporter.shared),
let accounts = try? vault.accounts() else {
return []
}
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/HomePage/Model/DataImportStatusProviding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class BookmarksAndPasswordsImportStatusProvider: DataImportStatusProviding
let secureVault: (any AutofillSecureVault)?
let bookmarkManager: BookmarkManager

init(secureVault: (any AutofillSecureVault)? = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared),
init(secureVault: (any AutofillSecureVault)? = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared),
bookmarkManager: BookmarkManager = LocalBookmarkManager.shared) {
self.secureVault = secureVault
self.bookmarkManager = bookmarkManager
Expand Down
6 changes: 3 additions & 3 deletions DuckDuckGo/Menus/MainMenuActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ extension AppDelegate {
savePanel.beginSheetModal(for: window) { response in
guard response == .OK, let selectedURL = savePanel.url else { return }

let vault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)
let vault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)
aataraxiaa marked this conversation as resolved.
Show resolved Hide resolved
let exporter = CSVLoginExporter(secureVault: vault!)
do {
try exporter.exportVaultLogins(to: selectedURL)
Expand Down Expand Up @@ -664,7 +664,7 @@ extension MainViewController {
}

@objc func resetSecureVaultData(_ sender: Any?) {
let vault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)
let vault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)

let accounts = (try? vault?.accounts()) ?? []
for accountID in accounts.compactMap(\.id) {
Expand Down Expand Up @@ -1045,7 +1045,7 @@ extension AppDelegate: NSMenuItemValidation {
}

private var areTherePasswords: Bool {
let vault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)
let vault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)
guard let vault else {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class AutofillNeverPromptWebsitesManager {

private let secureVault: (any AutofillSecureVault)?

public init(secureVault: (any AutofillSecureVault)? = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)) {
public init(secureVault: (any AutofillSecureVault)? = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)) {
self.secureVault = secureVault

fetchNeverPromptWebsites()
Expand Down
65 changes: 65 additions & 0 deletions DuckDuckGo/SecureVault/SecureVaultReporter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// SecureVaultReporter.swift
//
// Copyright © 2022 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 Common
import Foundation
import BrowserServicesKit
import PixelKit
import SecureStorage

final class SecureVaultKeyStoreEventMapper: EventMapping<SecureStorageKeyStoreEvent> {
public init() {
super.init { event, _, _, _ in
switch event {
case .l1KeyMigration:
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultKeystoreEventL1KeyMigration))
case .l2KeyMigration:
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultKeystoreEventL2KeyMigration))
case .l2KeyPasswordMigration:
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultKeystoreEventL2KeyPasswordMigration))
}
}
}

override init(mapping: @escaping EventMapping<SecureStorageKeyStoreEvent>.Mapping) {
fatalError("Use init()")
}
}

final class SecureVaultReporter: SecureVaultReporting {
static let shared = SecureVaultReporter()
private var keyStoreMapper: SecureVaultKeyStoreEventMapper
private init(keyStoreMapper: SecureVaultKeyStoreEventMapper = SecureVaultKeyStoreEventMapper()) {
self.keyStoreMapper = keyStoreMapper
}

func secureVaultError(_ error: SecureStorageError) {
guard NSApp.runType.requiresEnvironment else { return }

switch error {
case .initFailed, .failedToOpenDatabase:
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultInitError(error: error)))
default:
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultError(error: error)))
}
}

func secureVaultKeyStoreEvent(_ event: SecureStorageKeyStoreEvent) {
keyStoreMapper.fire(event)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ final class PasswordManagementViewController: NSViewController {
}

var secureVault: (any AutofillSecureVault)? {
try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)
try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared)
}

private let passwordManagerCoordinator: PasswordManagerCoordinating = PasswordManagerCoordinator.shared
Expand Down Expand Up @@ -1074,7 +1074,7 @@ extension PasswordManagementViewController: NSMenuItemValidation {
}

private var haveDuckDuckGoPasswords: Bool {
guard let vault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared) else { return false }
guard let vault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared) else { return false }
let accounts = (try? vault.accounts()) ?? []
return !accounts.isEmpty
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ final class SaveCredentialsViewController: NSViewController {
}
}
} else {
_ = try AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared).storeWebsiteCredentials(credentials)
_ = try AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared).storeWebsiteCredentials(credentials)
NSApp.delegateTyped.syncService?.scheduler.notifyDataChanged()
os_log(.debug, log: OSLog.sync, "Requesting sync if enabled")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ final class SaveIdentityViewController: NSViewController {
identity.title = UserText.pmDefaultIdentityAutofillTitle

do {
try AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared).storeIdentity(identity)
try AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared).storeIdentity(identity)
PixelKit.fire(GeneralPixel.autofillItemSaved(kind: .identity))
} catch {
os_log("%s:%s: failed to store identity %s", type: .error, className, #function, error.localizedDescription)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ final class SavePaymentMethodViewController: NSViewController {
paymentMethod.title = CreditCardValidation.type(for: paymentMethod.cardNumber).displayName

do {
try AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared).storeCreditCard(paymentMethod)
try AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared).storeCreditCard(paymentMethod)
} catch {
os_log("%s:%s: failed to store payment method %s", type: .error, className, #function, error.localizedDescription)
PixelKit.fire(DebugEvent(GeneralPixel.secureVaultError(error: error)))
Expand Down
8 changes: 8 additions & 0 deletions DuckDuckGo/Statistics/GeneralPixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ enum GeneralPixel: PixelKitEventV2 {
// Tracks installation without tracking retention.
case installationAttribution

case secureVaultKeystoreEventL1KeyMigration
case secureVaultKeystoreEventL2KeyMigration
case secureVaultKeystoreEventL2KeyPasswordMigration

var name: String {
switch self {

Expand Down Expand Up @@ -764,6 +768,10 @@ enum GeneralPixel: PixelKitEventV2 {

// Installation Attribution
case .installationAttribution: return "m_mac_install"

case .secureVaultKeystoreEventL1KeyMigration: return "m_mac_secure_vault_keystore_event_l1-key-migration"
case .secureVaultKeystoreEventL2KeyMigration: return "m_mac_secure_vault_keystore_event_l2-key-migration"
case .secureVaultKeystoreEventL2KeyPasswordMigration: return "m_mac_secure_vault_keystore_event_l2-key-password-migration"
}
}

Expand Down
4 changes: 2 additions & 2 deletions DuckDuckGo/Sync/SyncCredentialsAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final class SyncCredentialsAdapter {
syncDidCompletePublisher = syncDidCompleteSubject.eraseToAnyPublisher()
databaseCleaner = CredentialsDatabaseCleaner(
secureVaultFactory: secureVaultFactory,
secureVaultErrorReporter: SecureVaultErrorReporter.shared,
secureVaultErrorReporter: SecureVaultReporter.shared,
errorEvents: CredentialsCleanupErrorHandling(),
log: .passwordManager
)
Expand All @@ -71,7 +71,7 @@ final class SyncCredentialsAdapter {
do {
let provider = try CredentialsProvider(
secureVaultFactory: secureVaultFactory,
secureVaultErrorReporter: SecureVaultErrorReporter.shared,
secureVaultErrorReporter: SecureVaultReporter.shared,
metadataStore: metadataStore,
metricsEvents: metricsEventsHandler,
log: OSLog.sync,
Expand Down
4 changes: 2 additions & 2 deletions DuckDuckGo/Tab/TabExtensions/AutofillTabExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ extension AutofillTabExtension: SecureVaultManagerDelegate {
}
}

func secureVaultInitFailed(_ error: SecureStorageError) {
SecureVaultErrorReporter.shared.secureVaultInitFailed(error)
func secureVaultError(_ error: SecureStorageError) {
SecureVaultReporter.shared.secureVaultError(error)
}

public func secureVaultManager(_: BrowserServicesKit.SecureVaultManager, didReceivePixel pixel: AutofillUserScript.JSPixel) {
Expand Down
Loading
Loading