Skip to content

Commit

Permalink
Fire pixel when autoprompt is dismissed (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
GioSensation committed Aug 11, 2022
1 parent 09209cc commit 538436f
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Expand Up @@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state": {
"branch": null,
"revision": "27a4cff621893ef9d1b96ec62c99b137a3a73450",
"version": "4.7.1"
"revision": "d29c5abc7f473b69f3d81d8a15e137ed3aab029d",
"version": "5.0.1"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Expand Up @@ -14,7 +14,7 @@ let package = Package(
.library(name: "BrowserServicesKit", targets: ["BrowserServicesKit"])
],
dependencies: [
.package(name: "Autofill", url: "https://github.com/duckduckgo/duckduckgo-autofill.git", .exact("4.7.1")),
.package(name: "Autofill", url: "https://github.com/duckduckgo/duckduckgo-autofill.git", .exact("5.0.1")),
.package(name: "GRDB", url: "https://github.com/duckduckgo/GRDB.swift.git", .exact("1.1.0")),
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", .exact("1.1.1")),
.package(name: "Punycode", url: "https://github.com/gumob/PunycodeSwift.git", .exact("2.1.0")),
Expand Down
Expand Up @@ -41,6 +41,7 @@ public protocol AutofillSecureVaultDelegate: AnyObject {
completionHandler: @escaping ([SecureVaultModels.WebsiteAccount]) -> Void)
func autofillUserScript(_: AutofillUserScript, didRequestCredentialsForDomain: String,
subType: AutofillUserScript.GetAutofillDataSubType,
trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteCredentials?, RequestVaultCredentialsAction) -> Void)

func autofillUserScript(_: AutofillUserScript, didRequestCredentialsForAccount accountId: Int64,
Expand Down Expand Up @@ -329,6 +330,7 @@ extension AutofillUserScript {
struct GetAutofillDataRequest: Codable {
let mainType: GetAutofillDataMainType
let subType: GetAutofillDataSubType
let trigger: GetTriggerType
}

// https://github.com/duckduckgo/duckduckgo-autofill/blob/main/src/deviceApiCalls/schemas/getAutofillData.params.json
Expand All @@ -342,6 +344,12 @@ extension AutofillUserScript {
case username
case password
}

// https://github.com/duckduckgo/duckduckgo-autofill/blob/main/src/deviceApiCalls/schemas/getAutofillData.params.json
public enum GetTriggerType: String, Codable {
case userInitiated
case autoprompt
}

// https://github.com/duckduckgo/duckduckgo-autofill/blob/main/docs/runtime.ios.md#getautofilldatarequest
func getAutofillData(_ message: AutofillMessage, _ replyHandler: @escaping MessageReplyHandler) {
Expand All @@ -350,7 +358,7 @@ extension AutofillUserScript {
}

let domain = hostForMessage(message)
vaultDelegate?.autofillUserScript(self, didRequestCredentialsForDomain: domain, subType: request.subType) { credentials, action in
vaultDelegate?.autofillUserScript(self, didRequestCredentialsForDomain: domain, subType: request.subType, trigger: request.trigger) { credentials, action in
let response = RequestVaultCredentialsForDomainResponse.responseFromSecureVaultWebsiteCredentials(credentials, action: action)

if let json = try? JSONEncoder().encode(response), let jsonString = String(data: json, encoding: .utf8) {
Expand Down
Expand Up @@ -41,6 +41,7 @@ public protocol SecureVaultManagerDelegate: SecureVaultErrorReporting {
func secureVaultManager(_: SecureVaultManager,
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void)

func secureVaultManagerShouldAutomaticallyUpdateCredentialsWithoutUsername(_: SecureVaultManager) -> Bool
Expand Down Expand Up @@ -127,6 +128,7 @@ extension SecureVaultManager: AutofillSecureVaultDelegate {
public func autofillUserScript(_: AutofillUserScript,
didRequestCredentialsForDomain domain: String,
subType: AutofillUserScript.GetAutofillDataSubType,
trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteCredentials?, RequestVaultCredentialsAction) -> Void) {
do {
let vault = try self.vault ?? SecureVaultFactory.default.makeVault(errorReporter: self.delegate)
Expand All @@ -146,7 +148,7 @@ extension SecureVaultManager: AutofillSecureVaultDelegate {
return
}

delegate?.secureVaultManager(self, promptUserToAutofillCredentialsForDomain: domain, withAccounts: accounts) { account in
delegate?.secureVaultManager(self, promptUserToAutofillCredentialsForDomain: domain, withAccounts: accounts, withTrigger: trigger) { account in

guard let accountID = account?.id else {
completionHandler(nil, .none)
Expand Down
Expand Up @@ -353,11 +353,21 @@ class AutofillVaultUserScriptTests: XCTestCase {
var body = encryptedMessagingParams
body["mainType"] = "credentials"
body["subType"] = "username"
body["trigger"] = "userInitiated"

let mockWebView = MockWebView()
let message = MockAutofillMessage(name: "getAutofillData", body: body, host: "example.com", webView: mockWebView)

userScript.processMessage(userContentController, didReceive: message)

let predicate = NSPredicate(block: { _, _ -> Bool in
return !delegate.receivedCallbacks.isEmpty
})

let expectation = XCTNSPredicateExpectation(predicate: predicate, object: delegate.receivedCallbacks)

wait(for: [expectation], timeout: 5)

XCTAssertEqual(delegate.lastSubtype, AutofillUserScript.GetAutofillDataSubType.username)
}

Expand All @@ -369,6 +379,7 @@ class AutofillVaultUserScriptTests: XCTestCase {
var body = encryptedMessagingParams
body["mainType"] = "creditCards" // <- unsupported main type
body["subType"] = "username"
body["trigger"] = "userInitiated"

let mockWebView = MockWebView()
let message = MockAutofillMessage(name: "getAutofillData", body: body, host: "example.com", webView: mockWebView)
Expand All @@ -385,6 +396,7 @@ class AutofillVaultUserScriptTests: XCTestCase {
var body = encryptedMessagingParams
body["mainType"] = "credentials"
body["subType"] = "anything_else"
body["trigger"] = "userInitiated"

let mockWebView = MockWebView()
let message = MockAutofillMessage(name: "getAutofillData", body: body, host: "example.com", webView: mockWebView)
Expand All @@ -396,35 +408,43 @@ class AutofillVaultUserScriptTests: XCTestCase {

class MockSecureVaultDelegate: AutofillSecureVaultDelegate {

enum CallbackType {
case didRequestPasswordManagerForDomain
case didRequestStoreDataForDomain
case didRequestAccountsForDomain
case didRequestCredentialsForDomain
}

var receivedCallbacks: [CallbackType] = []

var lastDomain: String?
var lastUsername: String?
var lastPassword: String?
var lastSubtype: AutofillUserScript.GetAutofillDataSubType?

func autofillUserScript(_: AutofillUserScript, didRequestPasswordManagerForDomain domain: String) {
lastDomain = domain
receivedCallbacks.append(.didRequestPasswordManagerForDomain)
}

func autofillUserScript(_: AutofillUserScript, didRequestStoreDataForDomain domain: String, data: AutofillUserScript.DetectedAutofillData) {
lastDomain = domain
lastUsername = data.credentials?.username
lastPassword = data.credentials?.password
receivedCallbacks.append(.didRequestStoreDataForDomain)
}

func autofillUserScript(_: AutofillUserScript,
didRequestAccountsForDomain domain: String,
completionHandler: @escaping ([SecureVaultModels.WebsiteAccount]) -> Void) {
lastDomain = domain
receivedCallbacks.append(.didRequestAccountsForDomain)
}

func autofillUserScript(_: AutofillUserScript,
didRequestCredentialsForAccount accountId: Int64,
completionHandler: @escaping (SecureVaultModels.WebsiteCredentials?) -> Void) {
}

func autofillUserScript(_: AutofillUserScript, didRequestCredentialsForDomain: String,
completionHandler: @escaping (SecureVaultModels.WebsiteCredentials?, RequestVaultCredentialsAction) -> Void) {
}

func autofillUserScript(_: AutofillUserScript,
didRequestAutoFillInitDataForDomain domain: String,
Expand All @@ -446,8 +466,12 @@ class MockSecureVaultDelegate: AutofillSecureVaultDelegate {
func autofillUserScript(_ script: AutofillUserScript,
didRequestCredentialsForDomain: String,
subType: AutofillUserScript.GetAutofillDataSubType,
trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteCredentials?, RequestVaultCredentialsAction) -> Void) {
lastSubtype = subType
receivedCallbacks.append(.didRequestCredentialsForDomain)

completionHandler(nil, .none)
}
}

Expand Down
Expand Up @@ -182,6 +182,8 @@ class SecureVaultManagerTests: XCTestCase {
}

func testWhenRequestingCredentialsWithEmptyUsername_ThenNonActionIsReturned() throws {
let triggerType = AutofillUserScript.GetTriggerType.userInitiated

// account
let domain = "domain.com"
let username = "" // <- this is a valid scenario
Expand All @@ -194,7 +196,7 @@ class SecureVaultManagerTests: XCTestCase {

let subType = AutofillUserScript.GetAutofillDataSubType.username
let expect = expectation(description: #function)
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType) { credentials, action in
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType, trigger: triggerType) { credentials, action in
XCTAssertEqual(action, .none)
XCTAssertNil(credentials)
expect.fulfill()
Expand All @@ -207,6 +209,7 @@ class SecureVaultManagerTests: XCTestCase {
override func secureVaultManager(_ manager: SecureVaultManager,
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void) {
XCTAssertEqual(accounts.count, 1, "The empty username should have been filtered so that it's not shown as an option")
completionHandler(accounts[0])
Expand All @@ -215,6 +218,8 @@ class SecureVaultManagerTests: XCTestCase {

self.secureVaultManagerDelegate = SecureVaultDelegate()
self.manager.delegate = self.secureVaultManagerDelegate

let triggerType = AutofillUserScript.GetTriggerType.userInitiated

// account 1 (empty username)
let domain = "domain.com"
Expand All @@ -234,7 +239,7 @@ class SecureVaultManagerTests: XCTestCase {

let subType = AutofillUserScript.GetAutofillDataSubType.username
let expect = expectation(description: #function)
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType) { credentials, action in
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType, trigger: triggerType) { credentials, action in
XCTAssertEqual(action, .fill)
XCTAssertEqual(credentials!.password, "password".data(using: .utf8)!)
XCTAssertEqual(credentials!.account.username, "dax2")
Expand All @@ -248,6 +253,7 @@ class SecureVaultManagerTests: XCTestCase {
override func secureVaultManager(_ manager: SecureVaultManager,
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void) {
XCTAssertEqual(accounts.count, 2, "Both accounts should be shown since the subType was `password`")
completionHandler(accounts[1])
Expand All @@ -256,6 +262,8 @@ class SecureVaultManagerTests: XCTestCase {

self.secureVaultManagerDelegate = SecureVaultDelegate()
self.manager.delegate = self.secureVaultManagerDelegate

let triggerType = AutofillUserScript.GetTriggerType.userInitiated

// account 1 (empty username)
let domain = "domain.com"
Expand All @@ -275,7 +283,7 @@ class SecureVaultManagerTests: XCTestCase {

let subType = AutofillUserScript.GetAutofillDataSubType.password
let expect = expectation(description: #function)
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType) { credentials, action in
manager.autofillUserScript(mockAutofillUserScript, didRequestCredentialsForDomain: domain, subType: subType, trigger: triggerType) { credentials, action in
XCTAssertEqual(action, .fill)
XCTAssertEqual(credentials!.password, "password".data(using: .utf8)!)
XCTAssertEqual(credentials!.account.username, "dax2")
Expand Down Expand Up @@ -336,6 +344,7 @@ private class MockSecureVaultManagerDelegate: SecureVaultManagerDelegate {
func secureVaultManager(_: SecureVaultManager,
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void) {}

func secureVaultManager(_: SecureVaultManager, didAutofill type: AutofillType, withObjectId objectId: Int64) {}
Expand Down

0 comments on commit 538436f

Please sign in to comment.