Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm

Issue 2719023005: Provide Copy button for username in password settings (Closed)
Patch Set: Rebase and add EG test for the toast Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/browser/ui/settings/password_details_collection_view_control ler.h" 5 #import "ios/chrome/browser/ui/settings/password_details_collection_view_control ler.h"
6 6
7 #include "base/mac/foundation_util.h" 7 #include "base/mac/foundation_util.h"
8 #include "base/strings/sys_string_conversions.h" 8 #include "base/strings/sys_string_conversions.h"
9 #include "components/autofill/core/common/password_form.h" 9 #include "components/autofill/core/common/password_form.h"
10 #include "components/password_manager/core/browser/affiliation_utils.h" 10 #include "components/password_manager/core/browser/affiliation_utils.h"
(...skipping 21 matching lines...) Expand all
32 namespace { 32 namespace {
33 33
34 typedef NS_ENUM(NSInteger, SectionIdentifier) { 34 typedef NS_ENUM(NSInteger, SectionIdentifier) {
35 SectionIdentifierUsername = kSectionIdentifierEnumZero, 35 SectionIdentifierUsername = kSectionIdentifierEnumZero,
36 SectionIdentifierPassword, 36 SectionIdentifierPassword,
37 }; 37 };
38 38
39 typedef NS_ENUM(NSInteger, ItemType) { 39 typedef NS_ENUM(NSInteger, ItemType) {
40 ItemTypeHeader = kItemTypeEnumZero, 40 ItemTypeHeader = kItemTypeEnumZero,
41 ItemTypeUsername, 41 ItemTypeUsername,
42 ItemTypeCopyUsername,
42 ItemTypePassword, 43 ItemTypePassword,
43 ItemTypeShowHide, 44 ItemTypeShowHide,
44 ItemTypeCopy, 45 ItemTypeCopyPassword,
45 ItemTypeDelete, 46 ItemTypeDelete,
46 }; 47 };
47 48
48 } // namespace 49 } // namespace
49 50
50 @interface PasswordDetailsCollectionViewController () { 51 @interface PasswordDetailsCollectionViewController () {
51 // The username to which the saved password belongs. 52 // The username to which the saved password belongs.
52 NSString* _username; 53 NSString* _username;
53 // The saved password. 54 // The saved password.
54 NSString* _password; 55 NSString* _password;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME); 126 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME);
126 usernameHeader.textColor = [[MDCPalette greyPalette] tint500]; 127 usernameHeader.textColor = [[MDCPalette greyPalette] tint500];
127 [model setHeader:usernameHeader 128 [model setHeader:usernameHeader
128 forSectionWithIdentifier:SectionIdentifierUsername]; 129 forSectionWithIdentifier:SectionIdentifierUsername];
129 PasswordDetailsItem* usernameItem = 130 PasswordDetailsItem* usernameItem =
130 [[PasswordDetailsItem alloc] initWithType:ItemTypeUsername]; 131 [[PasswordDetailsItem alloc] initWithType:ItemTypeUsername];
131 usernameItem.text = _username; 132 usernameItem.text = _username;
132 usernameItem.showingText = YES; 133 usernameItem.showingText = YES;
133 [model addItem:usernameItem 134 [model addItem:usernameItem
134 toSectionWithIdentifier:SectionIdentifierUsername]; 135 toSectionWithIdentifier:SectionIdentifierUsername];
136 [model addItem:[self usernameCopyButtonItem]
137 toSectionWithIdentifier:SectionIdentifierUsername];
135 138
136 [model addSectionWithIdentifier:SectionIdentifierPassword]; 139 [model addSectionWithIdentifier:SectionIdentifierPassword];
137 CollectionViewTextItem* passwordHeader = 140 CollectionViewTextItem* passwordHeader =
138 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; 141 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader];
139 passwordHeader.text = 142 passwordHeader.text =
140 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD); 143 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
141 passwordHeader.textColor = [[MDCPalette greyPalette] tint500]; 144 passwordHeader.textColor = [[MDCPalette greyPalette] tint500];
142 [model setHeader:passwordHeader 145 [model setHeader:passwordHeader
143 forSectionWithIdentifier:SectionIdentifierPassword]; 146 forSectionWithIdentifier:SectionIdentifierPassword];
144 _passwordItem = [[PasswordDetailsItem alloc] initWithType:ItemTypePassword]; 147 _passwordItem = [[PasswordDetailsItem alloc] initWithType:ItemTypePassword];
(...skipping 11 matching lines...) Expand all
156 [model addItem:[self deletePasswordButtonItem] 159 [model addItem:[self deletePasswordButtonItem]
157 toSectionWithIdentifier:SectionIdentifierPassword]; 160 toSectionWithIdentifier:SectionIdentifierPassword];
158 } 161 }
159 162
160 - (void)dealloc { 163 - (void)dealloc {
161 [[NSNotificationCenter defaultCenter] removeObserver:self]; 164 [[NSNotificationCenter defaultCenter] removeObserver:self];
162 } 165 }
163 166
164 #pragma mark - Items 167 #pragma mark - Items
165 168
169 - (CollectionViewItem*)usernameCopyButtonItem {
170 CollectionViewTextItem* item =
171 [[CollectionViewTextItem alloc] initWithType:ItemTypeCopyUsername];
172 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_COPY_BUTTON);
lpromero 2017/05/02 15:04:52 This might not be sufficient for accessibility. I
vabr (Chromium) 2017/05/02 15:29:09 Oh, so if I set accessibilityLabel here to "Copy U
lpromero 2017/05/02 16:27:20 Indeed. This is an issue. The collection view text
173 item.textColor = [[MDCPalette cr_bluePalette] tint500];
174 item.accessibilityTraits |= UIAccessibilityTraitButton;
175 return item;
176 }
177
166 - (CollectionViewItem*)passwordCopyButtonItem { 178 - (CollectionViewItem*)passwordCopyButtonItem {
167 CollectionViewTextItem* item = 179 CollectionViewTextItem* item =
168 [[CollectionViewTextItem alloc] initWithType:ItemTypeCopy]; 180 [[CollectionViewTextItem alloc] initWithType:ItemTypeCopyPassword];
169 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON); 181 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON);
170 item.textColor = [[MDCPalette cr_bluePalette] tint500]; 182 item.textColor = [[MDCPalette cr_bluePalette] tint500];
171 item.accessibilityTraits |= UIAccessibilityTraitButton; 183 item.accessibilityTraits |= UIAccessibilityTraitButton;
172 return item; 184 return item;
173 } 185 }
174 186
175 - (CollectionViewItem*)showHidePasswordButtonItem { 187 - (CollectionViewItem*)showHidePasswordButtonItem {
176 CollectionViewTextItem* item = 188 CollectionViewTextItem* item =
177 [[CollectionViewTextItem alloc] initWithType:ItemTypeShowHide]; 189 [[CollectionViewTextItem alloc] initWithType:ItemTypeShowHide];
178 item.text = [self showHideButtonText]; 190 item.text = [self showHideButtonText];
179 item.textColor = [[MDCPalette cr_bluePalette] tint500]; 191 item.textColor = [[MDCPalette cr_bluePalette] tint500];
180 item.accessibilityTraits |= UIAccessibilityTraitButton; 192 item.accessibilityTraits |= UIAccessibilityTraitButton;
181 return item; 193 return item;
182 } 194 }
183 195
184 - (CollectionViewItem*)deletePasswordButtonItem { 196 - (CollectionViewItem*)deletePasswordButtonItem {
185 CollectionViewTextItem* item = 197 CollectionViewTextItem* item =
186 [[CollectionViewTextItem alloc] initWithType:ItemTypeDelete]; 198 [[CollectionViewTextItem alloc] initWithType:ItemTypeDelete];
187 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON); 199 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON);
188 item.textColor = [[MDCPalette cr_redPalette] tint500]; 200 item.textColor = [[MDCPalette cr_redPalette] tint500];
189 item.accessibilityTraits |= UIAccessibilityTraitButton; 201 item.accessibilityTraits |= UIAccessibilityTraitButton;
190 return item; 202 return item;
191 } 203 }
192 204
193 #pragma mark - Actions 205 #pragma mark - Actions
194 206
207 - (void)copyUsername {
208 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
209 generalPasteboard.string = _username;
210 [self showCopyResultToast:l10n_util::GetNSString(
211 IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE)];
212 }
213
195 - (NSString*)showHideButtonText { 214 - (NSString*)showHideButtonText {
196 if (_plainTextPasswordShown) { 215 if (_plainTextPasswordShown) {
197 return l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDE_BUTTON); 216 return l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDE_BUTTON);
198 } 217 }
199 return l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_SHOW_BUTTON); 218 return l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_SHOW_BUTTON);
200 } 219 }
201 220
202 // Changes the text on the Show/Hide button appropriately according to 221 // Changes the text on the Show/Hide button appropriately according to
203 // |_plainTextPasswordShown|. 222 // |_plainTextPasswordShown|.
204 - (void)toggleShowHideButton { 223 - (void)toggleShowHideButton {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } 274 }
256 275
257 - (void)copyPassword { 276 - (void)copyPassword {
258 // If the password is displayed in plain text, there is no need to 277 // If the password is displayed in plain text, there is no need to
259 // re-authenticate the user when copying the password because they are already 278 // re-authenticate the user when copying the password because they are already
260 // granted access to it. 279 // granted access to it.
261 if (_plainTextPasswordShown) { 280 if (_plainTextPasswordShown) {
262 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard]; 281 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
263 generalPasteboard.string = _password; 282 generalPasteboard.string = _password;
264 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); 283 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess);
265 [self showCopyPasswordResultToast: 284 [self
266 l10n_util::GetNSString( 285 showCopyResultToast:l10n_util::GetNSString(
267 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)]; 286 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)];
268 } else if ([_weakReauthenticationModule canAttemptReauth]) { 287 } else if ([_weakReauthenticationModule canAttemptReauth]) {
269 __weak PasswordDetailsCollectionViewController* weakSelf = self; 288 __weak PasswordDetailsCollectionViewController* weakSelf = self;
270 void (^copyPasswordHandler)(BOOL) = ^(BOOL success) { 289 void (^copyPasswordHandler)(BOOL) = ^(BOOL success) {
271 PasswordDetailsCollectionViewController* strongSelf = weakSelf; 290 PasswordDetailsCollectionViewController* strongSelf = weakSelf;
272 if (!strongSelf) 291 if (!strongSelf)
273 return; 292 return;
274 if (success) { 293 if (success) {
275 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard]; 294 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
276 generalPasteboard.string = strongSelf->_password; 295 generalPasteboard.string = strongSelf->_password;
277 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess); 296 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess);
278 [strongSelf showCopyPasswordResultToast: 297 [strongSelf showCopyResultToast:
279 l10n_util::GetNSString( 298 l10n_util::GetNSString(
280 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)]; 299 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)];
281 } else { 300 } else {
282 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeError); 301 TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeError);
283 [strongSelf showCopyPasswordResultToast: 302 [strongSelf showCopyResultToast:
284 l10n_util::GetNSString( 303 l10n_util::GetNSString(
285 IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE)]; 304 IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE)];
286 } 305 }
287 }; 306 };
288 [_weakReauthenticationModule 307 [_weakReauthenticationModule
289 attemptReauthWithLocalizedReason: 308 attemptReauthWithLocalizedReason:
290 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_COPY) 309 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_COPY)
291 handler:copyPasswordHandler]; 310 handler:copyPasswordHandler];
292 } 311 }
293 } 312 }
294 313
295 - (void)showCopyPasswordResultToast:(NSString*)message { 314 - (void)showCopyResultToast:(NSString*)message {
296 // TODO(crbug.com/159166): Route this through some delegate API to be able 315 // TODO(crbug.com/159166): Route this through some delegate API to be able
297 // to mock it in the unittest, and avoid having an EGTest just for that? 316 // to mock it in the unittest, and avoid having an EGTest just for that?
298 MDCSnackbarMessage* copyPasswordResultMessage = 317 MDCSnackbarMessage* copyPasswordResultMessage =
299 [MDCSnackbarMessage messageWithText:message]; 318 [MDCSnackbarMessage messageWithText:message];
300 [MDCSnackbarManager showMessage:copyPasswordResultMessage]; 319 [MDCSnackbarManager showMessage:copyPasswordResultMessage];
301 } 320 }
302 321
303 - (void)deletePassword { 322 - (void)deletePassword {
304 [_weakDelegate deletePassword:_passwordForm]; 323 [_weakDelegate deletePassword:_passwordForm];
305 } 324 }
306 325
307 #pragma mark - UICollectionViewDelegate 326 #pragma mark - UICollectionViewDelegate
308 327
309 - (void)collectionView:(UICollectionView*)collectionView 328 - (void)collectionView:(UICollectionView*)collectionView
310 didSelectItemAtIndexPath:(NSIndexPath*)indexPath { 329 didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
311 [super collectionView:collectionView didSelectItemAtIndexPath:indexPath]; 330 [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
312 NSInteger itemType = 331 NSInteger itemType =
313 [self.collectionViewModel itemTypeForIndexPath:indexPath]; 332 [self.collectionViewModel itemTypeForIndexPath:indexPath];
314 switch (itemType) { 333 switch (itemType) {
334 case ItemTypeCopyUsername:
335 [self copyUsername];
336 break;
315 case ItemTypeShowHide: 337 case ItemTypeShowHide:
316 if (_plainTextPasswordShown) { 338 if (_plainTextPasswordShown) {
317 [self hidePassword]; 339 [self hidePassword];
318 } else { 340 } else {
319 [self showPassword]; 341 [self showPassword];
320 } 342 }
321 break; 343 break;
322 case ItemTypeCopy: 344 case ItemTypeCopyPassword:
323 [self copyPassword]; 345 [self copyPassword];
324 break; 346 break;
325 case ItemTypeDelete: 347 case ItemTypeDelete:
326 [self deletePassword]; 348 [self deletePassword];
327 break; 349 break;
328 default: 350 default:
329 break; 351 break;
330 } 352 }
331 } 353 }
332 354
(...skipping 15 matching lines...) Expand all
348 } 370 }
349 371
350 #pragma mark - ForTesting 372 #pragma mark - ForTesting
351 373
352 - (void)setReauthenticationModule: 374 - (void)setReauthenticationModule:
353 (id<ReauthenticationProtocol>)reauthenticationModule { 375 (id<ReauthenticationProtocol>)reauthenticationModule {
354 _weakReauthenticationModule = reauthenticationModule; 376 _weakReauthenticationModule = reauthenticationModule;
355 } 377 }
356 378
357 @end 379 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698