Skip to content

Commit

Permalink
Manage Private Email Addresses (#396)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/72649045549333/1204615490114675/f
iOS PR: duckduckgo/iOS#1828
macOS PR: duckduckgo/macos-browser#1319
What kind of version bump will this require?: Minor

Description:
Allows users to manage their Private Email addresses from the browser.
  • Loading branch information
afterxleep authored Aug 3, 2023
1 parent 005949a commit 2931fce
Show file tree
Hide file tree
Showing 10 changed files with 892 additions and 313 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state" : {
"revision" : "44cd844b6bb5d8ccfefbd6e025817d800c26ad76",
"version" : "7.2.0"
"branch" : "8.0.0",
"revision" : "b1160df954eea20cd4cdf9356afc369751981b16"
}
},
{
Expand Down
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ let package = Package(
.library(name: "NetworkProtectionTestUtils", targets: ["NetworkProtectionTestUtils"]),
.library(name: "SecureStorage", targets: ["SecureStorage"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "7.2.0"),
dependencies: [
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", branch: "8.0.0"),
.package(url: "https://github.com/duckduckgo/GRDB.swift.git", exact: "2.2.0"),
.package(url: "https://github.com/duckduckgo/TrackerRadarKit.git", exact: "1.2.1"),
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "1.2.1"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.2.0"),
.package(url: "https://github.com/gumob/PunycodeSwift.git", exact: "2.1.0"),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "4.30.0"),
Expand Down
29 changes: 20 additions & 9 deletions Sources/BrowserServicesKit/Autofill/AutofillUserScript+Email.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public protocol AutofillEmailDelegate: AnyObject {
func autofillUserScript(_: AutofillUserScript,
didRequestAliasAndRequiresUserPermission requiresUserPermission: Bool,
shouldConsumeAliasIfProvided: Bool,
completionHandler: @escaping AliasCompletion)
completionHandler: @escaping AliasAutosaveCompletion)
func autofillUserScriptDidRequestRefreshAlias(_ : AutofillUserScript)
func autofillUserScript(_: AutofillUserScript, didRequestStoreToken token: String, username: String, cohort: String?)
func autofillUserScriptDidRequestUsernameAndAlias(_ : AutofillUserScript, completionHandler: @escaping UsernameAndAliasCompletion)
Expand Down Expand Up @@ -66,17 +66,28 @@ extension AutofillUserScript {
guard let dict = message.messageBody as? [String: Any],
let requiresUserPermission = dict["requiresUserPermission"] as? Bool,
let shouldConsumeAliasIfProvided = dict["shouldConsumeAliasIfProvided"] as? Bool else { return }

emailDelegate?.autofillUserScript(self,
didRequestAliasAndRequiresUserPermission: requiresUserPermission,
shouldConsumeAliasIfProvided: shouldConsumeAliasIfProvided) { alias, _ in
guard let alias = alias else { return }

replyHandler("""
{
"alias": "\(alias)"
shouldConsumeAliasIfProvided: shouldConsumeAliasIfProvided) { alias, autosave, _ in
guard let alias = alias else { return }
let domain = self.hostProvider.hostForMessage(message)

// Fetch the data in order to validate whether the alias is the personal email adress or not
self.emailDelegate?.autofillUserScriptDidRequestUserData(self) { username, _, _, _ in
if let username = username {
let autogenerated = alias != username && autosave // Only consider private emails as autogenerated
let credentials = AutofillUserScript.IncomingCredentials(username: "\(alias)@\(EmailManager.emailDomain)", password: nil, autogenerated: autogenerated)
let data = DetectedAutofillData(identity: nil, credentials: credentials, creditCard: nil, trigger: .emailProtection)
self.vaultDelegate?.autofillUserScript(self, didRequestStoreDataForDomain: domain, data: data)

replyHandler("""
{
"alias": "\(alias)"
}
""")
}
}
""")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,24 +195,23 @@ extension AutofillUserScript {
}

let username: String?
let password: String
let autogenerated: Bool
let password: String?
var autogenerated: Bool

init(username: String?, password: String, autogenerated: Bool = false) {
init(username: String?, password: String?, autogenerated: Bool = false) {
self.username = username
self.password = password
self.autogenerated = autogenerated
}

init?(autofillDictionary: [String: Any]) {
guard let credentialsDictionary = autofillDictionary[Constants.credentialsKey] as? [String: Any],
let password = credentialsDictionary[Constants.passwordKey] as? String else {
return nil
}
guard let credentialsDictionary = autofillDictionary[Constants.credentialsKey] as? [String: Any] else {
return nil
}

// Usernames are optional, as the Autofill script can pass a generated password through without a corresponding username.
self.init(username: credentialsDictionary[Constants.usernameKey] as? String,
password: password,
password: credentialsDictionary[Constants.passwordKey] as? String,
autogenerated: (credentialsDictionary[Constants.autogeneratedKey] as? Bool) ?? false)
}

Expand All @@ -229,11 +228,11 @@ extension AutofillUserScript {
}

public let identity: SecureVaultModels.Identity?
public let credentials: IncomingCredentials?
public var credentials: IncomingCredentials?
public let creditCard: SecureVaultModels.CreditCard?
public let trigger: GetTriggerType?

var hasAutogeneratedPassword: Bool {
var hasAutogeneratedCredentials: Bool {
return credentials?.autogenerated ?? false
}

Expand Down Expand Up @@ -468,6 +467,7 @@ extension AutofillUserScript {
case autoprompt
case formSubmission
case passwordGeneration
case emailProtection
}

// https://github.com/duckduckgo/duckduckgo-autofill/blob/main/src/deviceApiCalls/schemas/getAutofillData.params.json
Expand All @@ -483,11 +483,8 @@ extension AutofillUserScript {
}

let domain = hostForMessage(message)

if request.mainType == .credentials, request.subType == .password, let generatedPassword = request.generatedPassword?.value, !generatedPassword.isEmpty {
vaultDelegate?.autofillUserScriptDidOfferGeneratedPassword(self,
password: generatedPassword) { useGeneratedPassword in

vaultDelegate?.autofillUserScriptDidOfferGeneratedPassword(self, password: generatedPassword) { useGeneratedPassword in
let action = useGeneratedPassword ? RequestGeneratedPasswordResponse.GeneratedPasswordResponseAction.acceptGeneratedPassword : RequestGeneratedPasswordResponse.GeneratedPasswordResponseAction.rejectGeneratedPassword

Check failure on line 488 in Sources/BrowserServicesKit/Autofill/AutofillUserScript+SecureVault.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Line Length Violation: Line should be 200 characters or less; currently it has 231 characters (line_length)
let response = RequestGeneratedPasswordResponse(success: RequestGeneratedPasswordResponse.GeneratedPasswordResponseContents(action: action))
if let json = try? JSONEncoder().encode(response), let jsonString = String(data: json, encoding: .utf8) {
Expand Down
Loading

0 comments on commit 2931fce

Please sign in to comment.