From 9f62aacd878a0c05bff7256eb25b8776aa4e917f Mon Sep 17 00:00:00 2001 From: Graeme Arthur Date: Mon, 21 Oct 2024 11:50:44 +0200 Subject: [PATCH] Enable credentials import promo for all users (#1014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Please review the release process for BrowserServicesKit [here](https://app.asana.com/0/1200194497630846/1200837094583426). **Required**: Task/Issue URL: https://app.asana.com/0/1202926619870900/1208282574906775/f iOS PR: https://github.com/duckduckgo/iOS/pull/3427 macOS PR: https://github.com/duckduckgo/macos-browser/pull/3383 What kind of version bump will this require?: Major **Optional**: Task/Issue URL: https://app.asana.com/0/1202926619870900/1208282574906775/f Tech Design URL: https://app.asana.com/0/1202926619870900/1208502988382869/f **Description**: - We're rolling out [✓ Promote password import in autofill menu [2w]](https://app.asana.com/0/0/1201480346793878) and the conversion rate seems pretty decent. If we expand the addressable userbase we're likely to improve the user experience of many more users. - With [✓ Promote password import in autofill menu [2w]](https://app.asana.com/0/0/1201480346793878) we're promoting import to <7 days users with less than 10 passwords saved. - To make this promotion even more impactful, we can expand the coverage to existing users, but to make it impactful we'll need more lax heuristics and a way for users to dismiss this promo. **Steps to test this PR**: [Test Instructions](https://app.asana.com/0/1202926619870900/1208543152554655) **OS Testing**: * [ ] iOS 14 * [ ] iOS 15 * [ ] iOS 16 * [ ] macOS 10.15 * [ ] macOS 11 * [ ] macOS 12 --- ###### Internal references: [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) --- Package.resolved | 4 +- Package.swift | 2 +- .../AutofillUserScript+SecureVault.swift | 51 ++---- .../Autofill/AutofillUserScript.swift | 12 +- .../Autofill/OverlayAutofillUserScript.swift | 4 +- .../Autofill/WebsiteAutofillUserScript.swift | 5 +- .../Features/PrivacyFeature.swift | 1 + .../AutofillEmailUserScriptTests.swift | 2 +- .../AutofillVaultUserScriptTests.swift | 2 +- .../Email/EmailManagerTests.swift | 2 +- .../SecureVault/AutofillUserScriptTests.swift | 148 ++++-------------- .../SecureVault/SecureVaultManagerTests.swift | 2 +- 12 files changed, 60 insertions(+), 175 deletions(-) diff --git a/Package.resolved b/Package.resolved index cc5482ef4..a2fa8119d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -23,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/duckduckgo-autofill.git", "state" : { - "revision" : "1fee787458d13f8ed07f9fe81aecd6e59609339e", - "version" : "13.1.0" + "revision" : "945ac09a0189dc6736db617867fde193ea984b20", + "version" : "15.0.0" } }, { diff --git a/Package.swift b/Package.swift index d5241f75e..0281a8266 100644 --- a/Package.swift +++ b/Package.swift @@ -46,7 +46,7 @@ let package = Package( .library(name: "Onboarding", targets: ["Onboarding"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "13.1.0"), + .package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "15.0.0"), .package(url: "https://github.com/duckduckgo/GRDB.swift.git", exact: "2.4.0"), .package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "3.0.0"), .package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.2.0"), diff --git a/Sources/BrowserServicesKit/Autofill/AutofillUserScript+SecureVault.swift b/Sources/BrowserServicesKit/Autofill/AutofillUserScript+SecureVault.swift index 94dd3fc7a..fbe167ad6 100644 --- a/Sources/BrowserServicesKit/Autofill/AutofillUserScript+SecureVault.swift +++ b/Sources/BrowserServicesKit/Autofill/AutofillUserScript+SecureVault.swift @@ -78,18 +78,12 @@ public protocol AutofillSecureVaultDelegate: AnyObject { } -public protocol AutofillLoginImportStateProvider { - var isNewDDGUser: Bool { get } - var hasImportedLogins: Bool { get } - var credentialsImportPromptPresentationCount: Int { get } - var isAutofillEnabled: Bool { get } - func hasNeverPromptWebsitesFor(_ domain: String) -> Bool -} - public protocol AutofillPasswordImportDelegate: AnyObject { + func autofillUserScriptShouldShowPasswordImportDialog(domain: String, credentials: [SecureVaultModels.WebsiteCredentials], credentialsProvider: SecureVaultModels.CredentialsProvider, totalCredentialsCount: Int) -> Bool func autofillUserScriptDidRequestPasswordImportFlow(_ completion: @escaping () -> Void) func autofillUserScriptDidFinishImportWithImportedCredentialForCurrentDomain() - func autofillUserScriptWillDisplayOverlay(_ serializedInputContext: String) + func autofillUserScriptShouldDisplayOverlay(_ serializedInputContext: String, for domain: String) -> Bool + func autofillUserScriptDidRequestPermanentCredentialsImportPromptDismissal() } extension AutofillUserScript { @@ -458,7 +452,7 @@ extension AutofillUserScript { replyHandler("") return } - let credentialsImport = self.shouldShowPasswordImportDialog(domain: domain, credentials: credentials, credentialsProvider: credentialsProvider, totalCredentialsCount: totalCredentialsCount) + let credentialsImport = self.passwordImportDelegate?.autofillUserScriptShouldShowPasswordImportDialog(domain: domain, credentials: credentials, credentialsProvider: credentialsProvider, totalCredentialsCount: totalCredentialsCount) ?? false let response = RequestAvailableInputTypesResponse(credentials: credentials, identities: identities, cards: cards, @@ -471,37 +465,6 @@ extension AutofillUserScript { } } - private func shouldShowPasswordImportDialog(domain: String, credentials: [SecureVaultModels.WebsiteCredentials], credentialsProvider: SecureVaultModels.CredentialsProvider, totalCredentialsCount: Int) -> Bool { - guard loginImportStateProvider.isAutofillEnabled else { - return false - } - guard credentialsProvider.name != .bitwarden else { - return false - } - guard !isBurnerWindow else { - return false - } - guard loginImportStateProvider.credentialsImportPromptPresentationCount < 5 else { - return false - } - guard credentials.isEmpty else { - return false - } - guard totalCredentialsCount < 10 else { - return false - } - guard !loginImportStateProvider.hasImportedLogins else { - return false - } - guard loginImportStateProvider.isNewDDGUser else { - return false - } - guard !loginImportStateProvider.hasNeverPromptWebsitesFor(domain) else { - return false - } - return true - } - // https://github.com/duckduckgo/duckduckgo-autofill/blob/main/src/deviceApiCalls/schemas/getAutofillData.params.json struct GetAutofillDataRequest: Codable { let mainType: GetAutofillDataMainType @@ -790,6 +753,12 @@ extension AutofillUserScript { } } + func credentialsImportFlowPermanentlyDismissed(_ message: UserScriptMessage, replyHandler: @escaping MessageReplyHandler) { + passwordImportDelegate?.autofillUserScriptDidRequestPermanentCredentialsImportPromptDismissal() + replyHandler(nil) + NotificationCenter.default.post(name: .passwordImportDidCloseImportDialog, object: nil) + } + // MARK: Pixels public struct JSPixel: Equatable { diff --git a/Sources/BrowserServicesKit/Autofill/AutofillUserScript.swift b/Sources/BrowserServicesKit/Autofill/AutofillUserScript.swift index 92248aa6b..8dfba18e2 100644 --- a/Sources/BrowserServicesKit/Autofill/AutofillUserScript.swift +++ b/Sources/BrowserServicesKit/Autofill/AutofillUserScript.swift @@ -63,6 +63,7 @@ public class AutofillUserScript: NSObject, UserScript, UserScriptMessageEncrypti case closeEmailProtectionTab case startCredentialsImportFlow + case credentialsImportFlowPermanentlyDismissed } /// Represents if the autofill is loaded into the top autofill context. @@ -80,7 +81,6 @@ public class AutofillUserScript: NSObject, UserScript, UserScriptMessageEncrypti public weak var vaultDelegate: AutofillSecureVaultDelegate? public weak var passwordImportDelegate: AutofillPasswordImportDelegate? - internal let loginImportStateProvider: AutofillLoginImportStateProvider internal var scriptSourceProvider: AutofillUserScriptSourceProvider internal lazy var autofillDomainNameUrlMatcher: AutofillDomainNameUrlMatcher = { @@ -167,6 +167,7 @@ public class AutofillUserScript: NSObject, UserScript, UserScriptMessageEncrypti case .startEmailProtectionSignup: return startEmailProtectionSignup case .closeEmailProtectionTab: return closeEmailProtectionTab case .startCredentialsImportFlow: return startCredentialsImportFlow + case .credentialsImportFlowPermanentlyDismissed: return credentialsImportFlowPermanentlyDismissed } } @@ -178,22 +179,19 @@ public class AutofillUserScript: NSObject, UserScript, UserScriptMessageEncrypti return hostProvider.hostForMessage(message) } - public convenience init(scriptSourceProvider: AutofillUserScriptSourceProvider, loginImportStateProvider: AutofillLoginImportStateProvider) { + public convenience init(scriptSourceProvider: AutofillUserScriptSourceProvider) { self.init(scriptSourceProvider: scriptSourceProvider, encrypter: AESGCMUserScriptEncrypter(), - hostProvider: SecurityOriginHostProvider(), - loginImportStateProvider: loginImportStateProvider) + hostProvider: SecurityOriginHostProvider()) } init(scriptSourceProvider: AutofillUserScriptSourceProvider, encrypter: UserScriptEncrypter = AESGCMUserScriptEncrypter(), - hostProvider: UserScriptHostProvider = SecurityOriginHostProvider(), - loginImportStateProvider: AutofillLoginImportStateProvider) { + hostProvider: UserScriptHostProvider = SecurityOriginHostProvider()) { self.scriptSourceProvider = scriptSourceProvider self.hostProvider = hostProvider self.encrypter = encrypter self.isTopAutofillContext = false - self.loginImportStateProvider = loginImportStateProvider } } diff --git a/Sources/BrowserServicesKit/Autofill/OverlayAutofillUserScript.swift b/Sources/BrowserServicesKit/Autofill/OverlayAutofillUserScript.swift index d46066985..43fbc780a 100644 --- a/Sources/BrowserServicesKit/Autofill/OverlayAutofillUserScript.swift +++ b/Sources/BrowserServicesKit/Autofill/OverlayAutofillUserScript.swift @@ -83,8 +83,8 @@ public class OverlayAutofillUserScript: AutofillUserScript { } /// Used to create a top autofill context script for injecting into a ContentOverlay - public convenience init(scriptSourceProvider: AutofillUserScriptSourceProvider, overlay: OverlayAutofillUserScriptPresentationDelegate, loginImportStateProvider: AutofillLoginImportStateProvider) { - self.init(scriptSourceProvider: scriptSourceProvider, encrypter: AESGCMUserScriptEncrypter(), hostProvider: SecurityOriginHostProvider(), loginImportStateProvider: loginImportStateProvider) + public convenience init(scriptSourceProvider: AutofillUserScriptSourceProvider, overlay: OverlayAutofillUserScriptPresentationDelegate) { + self.init(scriptSourceProvider: scriptSourceProvider, encrypter: AESGCMUserScriptEncrypter(), hostProvider: SecurityOriginHostProvider()) self.isTopAutofillContext = true self.contentOverlay = overlay } diff --git a/Sources/BrowserServicesKit/Autofill/WebsiteAutofillUserScript.swift b/Sources/BrowserServicesKit/Autofill/WebsiteAutofillUserScript.swift index 61e4472e3..d99717272 100644 --- a/Sources/BrowserServicesKit/Autofill/WebsiteAutofillUserScript.swift +++ b/Sources/BrowserServicesKit/Autofill/WebsiteAutofillUserScript.swift @@ -91,7 +91,10 @@ public class WebsiteAutofillUserScript: AutofillUserScript { } // Sets the last message host, so we can check when it messages back lastOpenHost = hostProvider.hostForMessage(message) - passwordImportDelegate?.autofillUserScriptWillDisplayOverlay(serializedInputContext) + if passwordImportDelegate?.autofillUserScriptShouldDisplayOverlay(serializedInputContext, for: hostForMessage(message)) != true { + replyHandler(nil) + return + } currentOverlayTab.websiteAutofillUserScript(self, willDisplayOverlayAtClick: clickPoint, diff --git a/Sources/BrowserServicesKit/PrivacyConfig/Features/PrivacyFeature.swift b/Sources/BrowserServicesKit/PrivacyConfig/Features/PrivacyFeature.swift index a55aea837..bcc17c273 100644 --- a/Sources/BrowserServicesKit/PrivacyConfig/Features/PrivacyFeature.swift +++ b/Sources/BrowserServicesKit/PrivacyConfig/Features/PrivacyFeature.swift @@ -84,6 +84,7 @@ public enum AutofillSubfeature: String, PrivacySubfeature { case onByDefault case onForExistingUsers case unknownUsernameCategorization + case credentialsImportPromotionForExistingUsers } public enum DBPSubfeature: String, Equatable, PrivacySubfeature { diff --git a/Tests/BrowserServicesKitTests/Autofill/AutofillEmailUserScriptTests.swift b/Tests/BrowserServicesKitTests/Autofill/AutofillEmailUserScriptTests.swift index 777909aa0..7d42b6804 100644 --- a/Tests/BrowserServicesKitTests/Autofill/AutofillEmailUserScriptTests.swift +++ b/Tests/BrowserServicesKitTests/Autofill/AutofillEmailUserScriptTests.swift @@ -42,7 +42,7 @@ class AutofillEmailUserScriptTests: XCTestCase { properties: properties) .withJSLoading() .build() - return AutofillUserScript(scriptSourceProvider: sourceProvider, encrypter: MockEncrypter(), hostProvider: SecurityOriginHostProvider(), loginImportStateProvider: MockAutofillLoginImportStateProvider()) + return AutofillUserScript(scriptSourceProvider: sourceProvider, encrypter: MockEncrypter(), hostProvider: SecurityOriginHostProvider()) }() let userContentController = WKUserContentController() diff --git a/Tests/BrowserServicesKitTests/Autofill/AutofillVaultUserScriptTests.swift b/Tests/BrowserServicesKitTests/Autofill/AutofillVaultUserScriptTests.swift index a16cfa328..f146e9447 100644 --- a/Tests/BrowserServicesKitTests/Autofill/AutofillVaultUserScriptTests.swift +++ b/Tests/BrowserServicesKitTests/Autofill/AutofillVaultUserScriptTests.swift @@ -46,7 +46,7 @@ class AutofillVaultUserScriptTests: XCTestCase { let sourceProvider = DefaultAutofillSourceProvider(privacyConfigurationManager: privacyConfig, properties: properties, isDebug: false) - return AutofillUserScript(scriptSourceProvider: sourceProvider, hostProvider: hostProvider, loginImportStateProvider: MockAutofillLoginImportStateProvider()) + return AutofillUserScript(scriptSourceProvider: sourceProvider, hostProvider: hostProvider) }() let userContentController = WKUserContentController() diff --git a/Tests/BrowserServicesKitTests/Email/EmailManagerTests.swift b/Tests/BrowserServicesKitTests/Email/EmailManagerTests.swift index 63afb606c..0ec6c1934 100644 --- a/Tests/BrowserServicesKitTests/Email/EmailManagerTests.swift +++ b/Tests/BrowserServicesKitTests/Email/EmailManagerTests.swift @@ -51,7 +51,7 @@ class EmailManagerTests: XCTestCase { sessionKey: "1234", featureToggles: ContentScopeFeatureToggles.allTogglesOn), isDebug: false) - let userScript = AutofillUserScript(scriptSourceProvider: sourceProvider, loginImportStateProvider: MockAutofillLoginImportStateProvider()) + let userScript = AutofillUserScript(scriptSourceProvider: sourceProvider) return userScript } diff --git a/Tests/BrowserServicesKitTests/SecureVault/AutofillUserScriptTests.swift b/Tests/BrowserServicesKitTests/SecureVault/AutofillUserScriptTests.swift index 165ab9f11..d6cb6fa2c 100644 --- a/Tests/BrowserServicesKitTests/SecureVault/AutofillUserScriptTests.swift +++ b/Tests/BrowserServicesKitTests/SecureVault/AutofillUserScriptTests.swift @@ -106,80 +106,13 @@ class AutofillUserScriptTests: XCTestCase { XCTAssertEqual(responseFromCredentials.success.credentials.password, true) } - func testWhenProviderNameIsBitwarden_ThenAvailableInputTypesCredentialsImportIsFalse() { - let credentialsProvider = SecureVaultModels.CredentialsProvider(name: .bitwarden, locked: false) - - guard let response = getAvailableInputTypesResponse( - credentialsProvider: credentialsProvider - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } - - func testWhenCredentialsForDomainAreNotEmpty_ThenAvailableInputTypesCredentialsImportIsFalse() { - let credentialsList = createListOfCredentials(withPassword: nil) - - guard let response = getAvailableInputTypesResponse( - credentialsList: credentialsList - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } - - func testWhenTotalCredentialsCountIsTenOrMore_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - totalCredentialsCount: 10 - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } - - func testWhenUserHasImportedLogins_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - hasUserImportedLogins: true - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } - - func testWhenUserIsNOTNew_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - isNewDDGUser: false - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } - - func testWhenAutofillIsDisabled_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - isAutofillEnabled: false - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } + func testWhenPasswordImportDelegateReturnsFalse_ThenAvailableInputTypesCredentialsImportIsFalse() { + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()) + let passwordImportDelegate = MockAutofillPasswordImportDelegate() + userScript.passwordImportDelegate = passwordImportDelegate + passwordImportDelegate.stubAutofillUserScriptShouldShowPasswordImportDialog = false - func testWhenHasNeverPromptWebsitesIsTrue_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - hasNeverPromptWebsites: true - ) else { + guard let response = getAvailableInputTypesResponse(userScript: userScript) else { XCTFail("No getAvailableInputTypes response") return } @@ -187,19 +120,13 @@ class AutofillUserScriptTests: XCTestCase { XCTAssertFalse(response.success.credentialsImport) } - func testWhenCredentialsImportPresentationCountIs5_ThenAvailableInputTypesCredentialsImportIsFalse() { - guard let response = getAvailableInputTypesResponse( - credentialsImportPresentationCount: 5 - ) else { - XCTFail("No getAvailableInputTypes response") - return - } - - XCTAssertFalse(response.success.credentialsImport) - } + func testWhenPasswordImportDelegateReturnsTrue_ThenAvailableInputTypesCredentialsImportIsTrue() { + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()) + let passwordImportDelegate = MockAutofillPasswordImportDelegate() + userScript.passwordImportDelegate = passwordImportDelegate + passwordImportDelegate.stubAutofillUserScriptShouldShowPasswordImportDialog = true - func testWhenAllOtherCredentialsImportConditionsAreMet_ThenAvailableInputTypesCredentialsImportIsTrue() { - guard let response = getAvailableInputTypesResponse() else { + guard let response = getAvailableInputTypesResponse(userScript: userScript) else { XCTFail("No getAvailableInputTypes response") return } @@ -210,7 +137,7 @@ class AutofillUserScriptTests: XCTestCase { func testStartCredentialsImportFlow_passesDomainFromLastGetAvailableInputsCall() { let getAvailableInputsHost = "example.com" let hostProvider = MockHostProvider(host: getAvailableInputsHost) - let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), hostProvider: hostProvider, loginImportStateProvider: MockAutofillLoginImportStateProvider()) + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), hostProvider: hostProvider) let vaultDelegate = MockSecureVaultDelegate() let passwordImportDelegate = MockAutofillPasswordImportDelegate() @@ -222,7 +149,7 @@ class AutofillUserScriptTests: XCTestCase { } func testStartCredentialsImportFlow_onPasswordImportFlowCompletion_firesDidCloseImportDialogNotification() { - let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), loginImportStateProvider: MockAutofillLoginImportStateProvider()) + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()) let passwordImportDelegate = MockAutofillPasswordImportDelegate() userScript.passwordImportDelegate = passwordImportDelegate @@ -234,7 +161,7 @@ class AutofillUserScriptTests: XCTestCase { } func testStartCredentialsImportFlow_accountsForDomainIsNOTEmpty_callsDidFinishImport() { - let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), loginImportStateProvider: MockAutofillLoginImportStateProvider()) + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()) let vaultDelegate = MockSecureVaultDelegate() let passwordImportDelegate = MockAutofillPasswordImportDelegate() @@ -246,7 +173,7 @@ class AutofillUserScriptTests: XCTestCase { } func testStartCredentialsImportFlow_credentialsForDomainIsEmpty_doesNOTCallDidFinishImport() { - let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), loginImportStateProvider: MockAutofillLoginImportStateProvider()) + let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()) let vaultDelegate = MockSecureVaultDelegate() let passwordImportDelegate = MockAutofillPasswordImportDelegate() @@ -259,24 +186,12 @@ class AutofillUserScriptTests: XCTestCase { // MARK: Private - // Default vaules here are those that will result in a `true` value for credentialsImport. Override to test `false` case. - private func getAvailableInputTypesResponse(credentialsList: [SecureVaultModels.WebsiteCredentials] = [], + private func getAvailableInputTypesResponse(userScript: AutofillUserScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider()), + credentialsList: [SecureVaultModels.WebsiteCredentials] = [], credentialsProvider: SecureVaultModels.CredentialsProvider = .init(name: .duckduckgo, locked: false), - totalCredentialsCount: Int = 9, - hasUserImportedLogins: Bool = false, - isNewDDGUser: Bool = true, - hasNeverPromptWebsites: Bool = false, - isAutofillEnabled: Bool = true, - credentialsImportPresentationCount: Int = 0, + totalCredentialsCount: Int = 0, file: StaticString = #filePath, line: UInt = #line) -> AutofillUserScript.RequestAvailableInputTypesResponse? { - let loginImportStateProvider = MockAutofillLoginImportStateProvider() - loginImportStateProvider.hasImportedLogins = hasUserImportedLogins - loginImportStateProvider.isNewDDGUser = isNewDDGUser - loginImportStateProvider.stubHasNeverPromptWebsitesForDomain = hasNeverPromptWebsites - loginImportStateProvider.isAutofillEnabled = isAutofillEnabled - loginImportStateProvider.credentialsImportPromptPresentationCount = credentialsImportPresentationCount - let userScript = AutofillUserScript(scriptSourceProvider: MockAutofillUserScriptSourceProvider(), loginImportStateProvider: loginImportStateProvider) let userScriptMessage = MockWKScriptMessage(name: "getAvailableInputTypes", body: "") let vaultDelegate = MockSecureVaultDelegate() userScript.vaultDelegate = vaultDelegate @@ -321,25 +236,24 @@ class AutofillUserScriptTests: XCTestCase { } } -class MockAutofillLoginImportStateProvider: AutofillLoginImportStateProvider { - var credentialsImportPromptPresentationCount: Int = 0 +class MockAutofillUserScriptSourceProvider: AutofillUserScriptSourceProvider { + var source: String = "" +} - var isAutofillEnabled: Bool = false +class MockAutofillPasswordImportDelegate: AutofillPasswordImportDelegate { - var stubHasNeverPromptWebsitesForDomain: Bool = false - func hasNeverPromptWebsitesFor(_ domain: String) -> Bool { - stubHasNeverPromptWebsitesForDomain + var stubAutofillUserScriptShouldShowPasswordImportDialog = false + func autofillUserScriptShouldShowPasswordImportDialog(domain: String, credentials: [BrowserServicesKit.SecureVaultModels.WebsiteCredentials], credentialsProvider: BrowserServicesKit.SecureVaultModels.CredentialsProvider, totalCredentialsCount: Int) -> Bool { + return stubAutofillUserScriptShouldShowPasswordImportDialog } - var isNewDDGUser: Bool = false - var hasImportedLogins: Bool = false -} + func autofillUserScriptShouldDisplayOverlay(_ serializedInputContext: String, for domain: String) -> Bool { + return false + } -class MockAutofillUserScriptSourceProvider: AutofillUserScriptSourceProvider { - var source: String = "" -} + func autofillUserScriptDidRequestPermanentCredentialsImportPromptDismissal() { + } -class MockAutofillPasswordImportDelegate: AutofillPasswordImportDelegate { var serializedInputContext: String? func autofillUserScriptWillDisplayOverlay(_ serializedInputContext: String) { self.serializedInputContext = serializedInputContext diff --git a/Tests/BrowserServicesKitTests/SecureVault/SecureVaultManagerTests.swift b/Tests/BrowserServicesKitTests/SecureVault/SecureVaultManagerTests.swift index 0e9f586c7..b4b910998 100644 --- a/Tests/BrowserServicesKitTests/SecureVault/SecureVaultManagerTests.swift +++ b/Tests/BrowserServicesKitTests/SecureVault/SecureVaultManagerTests.swift @@ -49,7 +49,7 @@ class SecureVaultManagerTests: XCTestCase { let sourceProvider = DefaultAutofillSourceProvider(privacyConfigurationManager: privacyConfig, properties: properties, isDebug: false) - return AutofillUserScript(scriptSourceProvider: sourceProvider, encrypter: MockEncrypter(), hostProvider: SecurityOriginHostProvider(), loginImportStateProvider: MockAutofillLoginImportStateProvider()) + return AutofillUserScript(scriptSourceProvider: sourceProvider, encrypter: MockEncrypter(), hostProvider: SecurityOriginHostProvider()) }() private var testVault: (any AutofillSecureVault)!