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

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

Issue 2587023002: Upstream Chrome on iOS source code [8/11]. (Closed)
Patch Set: Created 4 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/settings/password_details_collection_view_control ler.h"
6
7 #import "base/ios/weak_nsobject.h"
8 #include "base/mac/foundation_util.h"
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "components/autofill/core/common/password_form.h"
12 #include "components/password_manager/core/browser/affiliation_utils.h"
13 #include "components/password_manager/core/browser/password_store.h"
14 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
15 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom e.h"
16 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
17 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h "
18 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
19 #import "ios/chrome/browser/ui/settings/cells/password_details_item.h"
20 #import "ios/chrome/browser/ui/settings/reauthentication_module.h"
21 #import "ios/chrome/browser/ui/settings/save_passwords_collection_view_controlle r.h"
22 #include "ios/chrome/grit/ios_strings.h"
23 #import "ios/third_party/material_components_ios/src/components/CollectionCells/ src/MaterialCollectionCells.h"
24 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h"
25 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat erialSnackbar.h"
26 #include "ui/base/l10n/l10n_util_mac.h"
27
28 namespace {
29
30 typedef NS_ENUM(NSInteger, SectionIdentifier) {
31 SectionIdentifierUsername = kSectionIdentifierEnumZero,
32 SectionIdentifierPassword,
33 };
34
35 typedef NS_ENUM(NSInteger, ItemType) {
36 ItemTypeHeader = kItemTypeEnumZero,
37 ItemTypeUsername,
38 ItemTypePassword,
39 ItemTypeShow,
40 ItemTypeHide,
41 ItemTypeCopy,
42 ItemTypeDelete,
43 };
44
45 } // namespace
46
47 @interface PasswordDetailsCollectionViewController () {
48 // The username to which the saved password belongs.
49 base::scoped_nsobject<NSString> _username;
50 // The saved password.
51 base::scoped_nsobject<NSString> _password;
52 // Whether the password is shown in plain text form or in obscured form.
53 BOOL _plainTextPasswordShown;
54 // The password form.
55 autofill::PasswordForm _passwordForm;
56 // Instance of the parent view controller needed in order to update the
57 // password list when a password is deleted.
58 base::WeakNSProtocol<id<PasswordDetailsCollectionViewControllerDelegate>>
59 _weakDelegate;
60 // Module containing the reauthentication mechanism for viewing and copying
61 // passwords.
62 base::WeakNSProtocol<id<ReauthenticationProtocol>>
63 _weakReauthenticationModule;
64 // The password item.
65 base::scoped_nsobject<PasswordDetailsItem> _passwordItem;
66 }
67
68 @end
69
70 @implementation PasswordDetailsCollectionViewController
71
72 - (instancetype)
73 initWithPasswordForm:(autofill::PasswordForm)passwordForm
74 delegate:
75 (id<PasswordDetailsCollectionViewControllerDelegate>)delegate
76 reauthenticationModule:(id<ReauthenticationProtocol>)reauthenticationModule
77 username:(NSString*)username
78 password:(NSString*)password
79 origin:(NSString*)origin {
80 DCHECK(delegate);
81 DCHECK(reauthenticationModule);
82 self = [super initWithStyle:CollectionViewControllerStyleAppBar];
83 if (self) {
84 _weakDelegate.reset(delegate);
85 _weakReauthenticationModule.reset(reauthenticationModule);
86 _passwordForm = passwordForm;
87 _username.reset([username copy]);
88 _password.reset([password copy]);
89 self.title =
90 [PasswordDetailsCollectionViewController simplifyOrigin:origin];
91 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
92 [defaultCenter addObserver:self
93 selector:@selector(hidePassword:)
94 name:UIApplicationDidEnterBackgroundNotification
95 object:nil];
96
97 [self loadModel];
98 }
99 return self;
100 }
101
102 + (NSString*)simplifyOrigin:(NSString*)origin {
103 NSString* originWithoutScheme = nil;
104 if (![origin rangeOfString:@"://"].length) {
105 originWithoutScheme = origin;
106 } else {
107 originWithoutScheme =
108 [[origin componentsSeparatedByString:@"://"] objectAtIndex:1];
109 }
110 return
111 [[originWithoutScheme componentsSeparatedByString:@"/"] objectAtIndex:0];
112 }
113
114 #pragma mark - SettingsRootCollectionViewController
115
116 - (void)loadModel {
117 [super loadModel];
118 CollectionViewModel* model = self.collectionViewModel;
119
120 [model addSectionWithIdentifier:SectionIdentifierUsername];
121 CollectionViewTextItem* usernameHeader = [
122 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease];
123 usernameHeader.text =
124 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME);
125 [model setHeader:usernameHeader
126 forSectionWithIdentifier:SectionIdentifierUsername];
127 PasswordDetailsItem* usernameItem =
128 [[[PasswordDetailsItem alloc] initWithType:ItemTypeUsername] autorelease];
129 usernameItem.text = _username;
130 usernameItem.showingText = YES;
131 [model addItem:usernameItem
132 toSectionWithIdentifier:SectionIdentifierUsername];
133
134 [model addSectionWithIdentifier:SectionIdentifierPassword];
135 CollectionViewTextItem* passwordHeader = [
136 [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease];
137 passwordHeader.text =
138 l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
139 [model setHeader:passwordHeader
140 forSectionWithIdentifier:SectionIdentifierPassword];
141 _passwordItem.reset(
142 [[PasswordDetailsItem alloc] initWithType:ItemTypePassword]);
143 _passwordItem.get().text = _password;
144 _passwordItem.get().showingText = NO;
145 [model addItem:_passwordItem
146 toSectionWithIdentifier:SectionIdentifierPassword];
147
148 // TODO(crbug.com/159166): Change the style of the buttons once there are
149 // final mocks.
150 [model addItem:[self showPasswordButtonItem]
151 toSectionWithIdentifier:SectionIdentifierPassword];
152 [model addItem:[self hidePasswordButtonItem]
153 toSectionWithIdentifier:SectionIdentifierPassword];
154 [model addItem:[self passwordCopyButtonItem]
155 toSectionWithIdentifier:SectionIdentifierPassword];
156 [model addItem:[self deletePasswordButtonItem]
157 toSectionWithIdentifier:SectionIdentifierPassword];
158 }
159
160 - (void)dealloc {
161 [[NSNotificationCenter defaultCenter] removeObserver:self];
162 [super dealloc];
163 }
164
165 #pragma mark - Items
166
167 - (CollectionViewItem*)showPasswordButtonItem {
168 CollectionViewTextItem* item =
169 [[[CollectionViewTextItem alloc] initWithType:ItemTypeShow] autorelease];
170 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_SHOW_BUTTON);
171 item.accessibilityTraits |= UIAccessibilityTraitButton;
172 return item;
173 }
174
175 - (CollectionViewItem*)passwordCopyButtonItem {
176 CollectionViewTextItem* item =
177 [[[CollectionViewTextItem alloc] initWithType:ItemTypeCopy] autorelease];
178 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON);
179 item.accessibilityTraits |= UIAccessibilityTraitButton;
180 return item;
181 }
182
183 - (CollectionViewItem*)hidePasswordButtonItem {
184 CollectionViewTextItem* item =
185 [[[CollectionViewTextItem alloc] initWithType:ItemTypeHide] autorelease];
186 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDE_BUTTON);
187 item.accessibilityTraits |= UIAccessibilityTraitButton;
188 return item;
189 }
190
191 - (CollectionViewItem*)deletePasswordButtonItem {
192 CollectionViewTextItem* item = [
193 [[CollectionViewTextItem alloc] initWithType:ItemTypeDelete] autorelease];
194 item.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON);
195 item.accessibilityTraits |= UIAccessibilityTraitButton;
196 return item;
197 }
198
199 #pragma mark - Actions
200
201 - (void)showPassword {
202 if (_plainTextPasswordShown) {
203 return;
204 }
205
206 if ([_weakReauthenticationModule canAttemptReauth]) {
207 base::WeakNSObject<PasswordDetailsCollectionViewController> weakSelf(self);
208 void (^showPasswordHandler)(BOOL) = ^(BOOL success) {
209 base::scoped_nsobject<PasswordDetailsCollectionViewController> strongSelf(
210 [weakSelf retain]);
211 if (!strongSelf || !success)
212 return;
213 PasswordDetailsItem* passwordItem = strongSelf.get()->_passwordItem.get();
214 passwordItem.showingText = YES;
215 [strongSelf reconfigureCellsForItems:@[ passwordItem ]
216 inSectionWithIdentifier:SectionIdentifierPassword];
217 [[strongSelf collectionView].collectionViewLayout invalidateLayout];
218 strongSelf.get()->_plainTextPasswordShown = YES;
219 };
220
221 [_weakReauthenticationModule
222 attemptReauthWithLocalizedReason:
223 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_SHOW)
224 handler:showPasswordHandler];
225 }
226 }
227
228 - (void)hidePassword {
229 if (!_plainTextPasswordShown) {
230 return;
231 }
232 _passwordItem.get().showingText = NO;
233 [self reconfigureCellsForItems:@[ _passwordItem ]
234 inSectionWithIdentifier:SectionIdentifierPassword];
235 [self.collectionView.collectionViewLayout invalidateLayout];
236 _plainTextPasswordShown = NO;
237 }
238
239 - (void)copyPassword {
240 // If the password is displayed in plain text, there is no need to
241 // re-authenticate the user when copying the password because they are already
242 // granted access to it.
243 if (_plainTextPasswordShown) {
244 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
245 generalPasteboard.string = _password;
246 [self showCopyPasswordResultToast:
247 l10n_util::GetNSString(
248 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)];
249 } else if ([_weakReauthenticationModule canAttemptReauth]) {
250 base::WeakNSObject<PasswordDetailsCollectionViewController> weakSelf(self);
251 void (^copyPasswordHandler)(BOOL) = ^(BOOL success) {
252 base::scoped_nsobject<PasswordDetailsCollectionViewController> strongSelf(
253 [weakSelf retain]);
254 if (!strongSelf)
255 return;
256 if (success) {
257 UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
258 generalPasteboard.string = strongSelf.get()->_password;
259 [strongSelf showCopyPasswordResultToast:
260 l10n_util::GetNSString(
261 IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)];
262 } else {
263 [strongSelf showCopyPasswordResultToast:
264 l10n_util::GetNSString(
265 IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE)];
266 }
267 };
268 [_weakReauthenticationModule
269 attemptReauthWithLocalizedReason:
270 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_COPY)
271 handler:copyPasswordHandler];
272 }
273 }
274
275 - (void)showCopyPasswordResultToast:(NSString*)message {
276 MDCSnackbarMessage* copyPasswordResultMessage =
277 [MDCSnackbarMessage messageWithText:message];
278 [MDCSnackbarManager showMessage:copyPasswordResultMessage];
279 }
280
281 - (void)deletePassword {
282 [_weakDelegate deletePassword:_passwordForm];
283 }
284
285 #pragma mark - UICollectionViewDataSource
286
287 - (UICollectionReusableView*)collectionView:(UICollectionView*)collectionView
288 viewForSupplementaryElementOfKind:(NSString*)kind
289 atIndexPath:(NSIndexPath*)indexPath {
290 UICollectionReusableView* view = [super collectionView:collectionView
291 viewForSupplementaryElementOfKind:kind
292 atIndexPath:indexPath];
293 MDCCollectionViewTextCell* textCell =
294 base::mac::ObjCCast<MDCCollectionViewTextCell>(view);
295 if (textCell) {
296 textCell.textLabel.textColor = [[MDCPalette greyPalette] tint500];
297 }
298 return view;
299 };
300
301 #pragma mark - UICollectionViewDelegate
302
303 - (void)collectionView:(UICollectionView*)collectionView
304 didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
305 [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
306 NSInteger itemType =
307 [self.collectionViewModel itemTypeForIndexPath:indexPath];
308 switch (itemType) {
309 case ItemTypeShow:
310 [self showPassword];
311 break;
312 case ItemTypeHide:
313 [self hidePassword];
314 break;
315 case ItemTypeCopy:
316 [self copyPassword];
317 break;
318 case ItemTypeDelete:
319 [self deletePassword];
320 break;
321 default:
322 break;
323 }
324 }
325
326 #pragma mark MDCCollectionViewStylingDelegate
327
328 - (CGFloat)collectionView:(UICollectionView*)collectionView
329 cellHeightAtIndexPath:(NSIndexPath*)indexPath {
330 CollectionViewItem* item =
331 [self.collectionViewModel itemAtIndexPath:indexPath];
332 switch (item.type) {
333 case ItemTypeUsername:
334 case ItemTypePassword:
335 return [MDCCollectionViewCell
336 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
337 forItem:item];
338 default:
339 return MDCCellDefaultOneLineHeight;
340 }
341 }
342
343 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698