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

Address autofill security concerns with copy changes #3211

Merged
merged 31 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ef2bca8
Add lock asset
graeme Aug 16, 2024
bc9faf9
Replace passwords subtitle with explainer view
graeme Aug 16, 2024
fd3f8ce
Add wip empty state text
graeme Aug 23, 2024
6da6b83
Show security info on clicking lock
graeme Sep 3, 2024
6b018eb
Fix empty state text
graeme Sep 4, 2024
104aee4
Update password explainer text
graeme Sep 4, 2024
3a39fd1
Add logic for showing import password explainer
graeme Sep 4, 2024
f8edc47
Hide security button based on autolock preferences
graeme Sep 4, 2024
5bf59bf
Make autolock off copy changes from Windows SR
graeme Sep 5, 2024
921da27
Fix crashy popover issue
graeme Sep 5, 2024
c6cb857
Fix settings link handling
graeme Sep 5, 2024
4d4560b
Fix settings link handing on Save info view
graeme Sep 5, 2024
d833a7a
Fix Settings casing
graeme Sep 5, 2024
2b3d5e1
Remove the and from the encrypted passwords message
graeme Sep 10, 2024
270bcda
More copy updates
graeme Sep 11, 2024
32d81a1
+ strings file
graeme Sep 11, 2024
f22aedd
Only show security button border when hovering
graeme Sep 11, 2024
e22b6f1
Make security info popover on hover
graeme Sep 13, 2024
2ce0c7a
Implement feedback on info tooltip view
graeme Sep 16, 2024
4ba21ba
Merge remote-tracking branch 'origin/main' into graeme/address-autofi…
graeme Sep 16, 2024
e857fdc
Remove duplicate string after main merge
graeme Sep 16, 2024
1cddd3b
Reduce auto-dismiss time
graeme Sep 16, 2024
cfbdd3d
Update lock hover view colours again
graeme Sep 17, 2024
e075a37
Fix dark mode by converting view to box
graeme Sep 18, 2024
cb88fc3
Lazy load the autolock var
graeme Sep 19, 2024
d0b7ece
Merge remote-tracking branch 'origin/main' into graeme/address-autofi…
graeme Sep 19, 2024
64e0d24
Use factory for autofill prefs to fix tests
graeme Sep 19, 2024
546e4d2
Revert "Use factory for autofill prefs to fix tests"
graeme Sep 19, 2024
93b1477
Revert "Lazy load the autolock var"
graeme Sep 19, 2024
2b10f74
Prevent Database assertion failure in dependencies
graeme Sep 19, 2024
664fb26
Prepend lock to empty screen message
graeme Sep 19, 2024
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
14 changes: 14 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2882,6 +2882,8 @@
EEC8EB402982CD550065AA39 /* JSAlertViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF53E172950CED5002D78F4 /* JSAlertViewModelTests.swift */; };
EECE10E529DD77E60044D027 /* FeatureFlag.swift in Sources */ = {isa = PBXBuildFile; fileRef = EECE10E429DD77E60044D027 /* FeatureFlag.swift */; };
EECE10E629DD77E60044D027 /* FeatureFlag.swift in Sources */ = {isa = PBXBuildFile; fileRef = EECE10E429DD77E60044D027 /* FeatureFlag.swift */; };
EED4D3D82C874AE200C79EEA /* PopoverInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED4D3D72C874AE200C79EEA /* PopoverInfoViewController.swift */; };
EED4D3D92C874AE200C79EEA /* PopoverInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED4D3D72C874AE200C79EEA /* PopoverInfoViewController.swift */; };
EED4D3DF2C8A298D00C79EEA /* AutofillPixelEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED4D3DE2C8A298D00C79EEA /* AutofillPixelEvent.swift */; };
EED4D3E02C8A298D00C79EEA /* AutofillPixelEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED4D3DE2C8A298D00C79EEA /* AutofillPixelEvent.swift */; };
EED735362BB46B6000F173D6 /* AutocompleteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED735352BB46B6000F173D6 /* AutocompleteTests.swift */; };
Expand Down Expand Up @@ -4616,6 +4618,7 @@
EEC4A6702B2C90AB00F7C0AA /* VPNLocationPreferenceItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNLocationPreferenceItem.swift; sourceTree = "<group>"; };
EEC7BE2D2BC6C09400F86835 /* AddressBarKeyboardShortcutsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressBarKeyboardShortcutsTests.swift; sourceTree = "<group>"; };
EECE10E429DD77E60044D027 /* FeatureFlag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlag.swift; sourceTree = "<group>"; };
EED4D3D72C874AE200C79EEA /* PopoverInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverInfoViewController.swift; sourceTree = "<group>"; };
EED4D3DE2C8A298D00C79EEA /* AutofillPixelEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillPixelEvent.swift; sourceTree = "<group>"; };
EED735352BB46B6000F173D6 /* AutocompleteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutocompleteTests.swift; sourceTree = "<group>"; };
EED9A6732C37FE6800E0FAB9 /* login_deduplication_test_data.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = login_deduplication_test_data.csv; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7415,6 +7418,7 @@
B65536902684409300085A79 /* Geolocation */,
AAE75275263B036300B973F8 /* History */,
AAE71DB225F66A0900D74437 /* HomePage */,
EED4D3D62C87480B00C79EEA /* InfoViews */,
56CEE9092B7A66C500CF10AA /* Info.plist */,
56CEE90D2B7A6DE100CF10AA /* InfoPlist.xcstrings */,
EEAEA3F4294D05CF00D04DF3 /* JSAlert */,
Expand Down Expand Up @@ -9168,6 +9172,14 @@
path = AppAndExtensionAndAgentTargets;
sourceTree = "<group>";
};
EED4D3D62C87480B00C79EEA /* InfoViews */ = {
isa = PBXGroup;
children = (
EED4D3D72C874AE200C79EEA /* PopoverInfoViewController.swift */,
);
path = InfoViews;
sourceTree = "<group>";
};
EEE0E1CB2C32F53C0058E148 /* DataImport */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -10656,6 +10668,7 @@
FD22255E2C64B68500199373 /* AutoconsentExperiment.swift in Sources */,
3706FAD7293F65D500E42796 /* Feedback.swift in Sources */,
1D0DE9422C3BB9CC0037ABC2 /* ReleaseNotesParser.swift in Sources */,
EED4D3D92C874AE200C79EEA /* PopoverInfoViewController.swift in Sources */,
3707C722294B5D2900682A9F /* WKWebViewExtension.swift in Sources */,
3706FAD9293F65D500E42796 /* FirefoxFaviconsReader.swift in Sources */,
3706FADB293F65D500E42796 /* ContentBlockingRulesUpdateObserver.swift in Sources */,
Expand Down Expand Up @@ -12564,6 +12577,7 @@
856CADF0271710F400E79BB0 /* HoverUserScript.swift in Sources */,
B6DE57F62B05EA9000CD54B9 /* SheetHostingWindow.swift in Sources */,
AA6EF9B525081B4C004754E6 /* MainMenuActions.swift in Sources */,
EED4D3D82C874AE200C79EEA /* PopoverInfoViewController.swift in Sources */,
56A0541F2C1CA1F5007D8FAB /* OnboardingTabExtension.swift in Sources */,
B63D466925BEB6C200874977 /* WKWebView+SessionState.swift in Sources */,
B6F1B0222BCE5658005E863C /* BrokenSiteInfoTabExtension.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.090",
"blue" : "0x00",
"green" : "0x00",
"red" : "0x00"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.090",
"blue" : "0xFF",
"green" : "0xFF",
"red" : "0xFF"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.180",
"blue" : "0x00",
"green" : "0x00",
"red" : "0x00"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.180",
"blue" : "0xFF",
"green" : "0xFF",
"red" : "0xFF"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Lock-Color-16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Lock-Solid-16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Binary file not shown.
4 changes: 4 additions & 0 deletions DuckDuckGo/Common/Extensions/URLExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ extension URL {
return URL(string: "https://duckduckgo.com/duckduckgo-help-pages/search-privacy/")!
}

static var passwordManagerLearnMore: URL {
return URL(string: "https://duckduckgo.com/duckduckgo-help-pages/sync-and-backup/password-manager-security/")!
}

static var searchSettings: URL {
return URL(string: "https://duckduckgo.com/settings/")!
}
Expand Down
2 changes: 2 additions & 0 deletions DuckDuckGo/Common/Localizables/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,8 @@ struct UserText {
}

static let importLoginsPasswords = NSLocalizedString("import.logins.passwords", value: "Passwords", comment: "Title text for the Passwords import option")
static let importLoginsPasswordsExplainer = NSLocalizedString("import.logins.passwords.explainer", value: "Passwords are encrypted. Viewing them or filling out forms requires Touch ID or a password. Nobody but you can see your passwords, not even us. Find Passwords in DuckDuckGo Settings > Passwords & Autofill.", comment: "Explanatory text for the Passwords import option to alleviate security concerns and explain usage.")
static let importLoginsPasswordsExplainerAutolockOff = NSLocalizedString("import.logins.passwords.explainer.autolock.off", value: "Passwords are encrypted. We recommend setting up Auto-lock to keep your passwords even more secure. Set it up in DuckDuckGo Settings > Passwords & Autofill.", comment: "Explanatory text for the Passwords import option to alleviate security concerns and explain usage when autolock is disabled")

static let importBookmarksButtonTitle = NSLocalizedString("bookmarks.import.button.title", value: "Import", comment: "Button text to open bookmark import dialog")
static let initiateImport = NSLocalizedString("import.data.initiate", value: "Import", comment: "Button text for importing data")
Expand Down
6 changes: 5 additions & 1 deletion DuckDuckGo/DataImport/Model/DataImportViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,14 @@ struct DataImportViewModel {

#endif

let isPasswordManagerAutolockEnabled: Bool

init(importSource: Source? = nil,
screen: Screen? = nil,
availableImportSources: [DataImport.Source] = Source.allCases.filter { $0.canImportData },
preferredImportSources: [Source] = [.chrome, .firefox, .safari],
summary: [DataTypeImportResult] = [],
isPasswordManagerAutolockEnabled: Bool = AutofillPreferences().isAutoLockEnabled,
loadProfiles: @escaping (ThirdPartyBrowser) -> BrowserProfileList = { $0.browserProfiles() },
dataImporterFactory: @escaping DataImporterFactory = dataImporter,
requestPrimaryPasswordCallback: @escaping @MainActor (Source) -> String? = Self.requestPrimaryPasswordCallback,
Expand All @@ -161,6 +164,7 @@ struct DataImportViewModel {
self.selectedDataTypes = importSource.supportedDataTypes

self.summary = summary
self.isPasswordManagerAutolockEnabled = isPasswordManagerAutolockEnabled

self.requestPrimaryPasswordCallback = requestPrimaryPasswordCallback
self.openPanelCallback = openPanelCallback
Expand Down Expand Up @@ -683,7 +687,7 @@ extension DataImportViewModel {
}

mutating func update(with importSource: Source) {
self = .init(importSource: importSource, loadProfiles: loadProfiles, dataImporterFactory: dataImporterFactory, requestPrimaryPasswordCallback: requestPrimaryPasswordCallback, reportSenderFactory: reportSenderFactory, onFinished: onFinished, onCancelled: onCancelled)
self = .init(importSource: importSource, isPasswordManagerAutolockEnabled: isPasswordManagerAutolockEnabled, loadProfiles: loadProfiles, dataImporterFactory: dataImporterFactory, requestPrimaryPasswordCallback: requestPrimaryPasswordCallback, reportSenderFactory: reportSenderFactory, onFinished: onFinished, onCancelled: onCancelled)
}

@MainActor
Expand Down
21 changes: 14 additions & 7 deletions DuckDuckGo/DataImport/View/DataImportView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct DataImportView: ModalView {
DataImportTypePicker(viewModel: $model)
.disabled(model.isImportSourcePickerDisabled)

importPasswordSubtitle()
passwordsExplainerView().padding(.top, 20)

case .moreInfo:
// you will be asked for your keychain password blah blah...
Expand Down Expand Up @@ -159,7 +159,7 @@ struct DataImportView: ModalView {
}

if dataType == .passwords {
importPasswordSubtitle()
passwordsExplainerView().padding(.top, 20)
}

case .summary(let dataTypes, let isFileImport):
Expand Down Expand Up @@ -208,11 +208,18 @@ struct DataImportView: ModalView {
}
}

private func importPasswordSubtitle() -> some View {
Text(UserText.importDataSubtitle)
.font(.subheadline)
.foregroundColor(Color(.greyText))
.padding(.top, 16)
private func passwordsExplainerView() -> some View {
HStack(alignment: .top, spacing: 8) {
Image(.lockColor16)
Text(model.isPasswordManagerAutolockEnabled ? UserText.importLoginsPasswordsExplainer : UserText.importLoginsPasswordsExplainerAutolockOff)
.font(.system(size: 12))
.foregroundColor(.secondary)
.frame(maxWidth: .infinity, alignment: .topLeading)
}
.frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .topLeading)
.padding(14)
.background(Color.blackWhite1)
.roundedBorder()
}

private func handleImportProgress(_ progress: TaskProgress<DataImportViewModel, Never, DataImportProgressEvent>) async {
Expand Down
Loading
Loading