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

Side by Side Diff: chrome/browser/autofill/autofill_dialog_controller_mac.mm

Issue 6621076: [Mac] Remove native/Cocoa preferences. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase switch removal Created 9 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #include "base/lazy_instance.h"
6 #include "base/mac/mac_util.h"
7 #include "base/sys_string_conversions.h"
8 #import "chrome/browser/autofill/autofill-inl.h"
9 #import "chrome/browser/autofill/autofill_address_model_mac.h"
10 #import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h"
11 #import "chrome/browser/autofill/autofill_credit_card_model_mac.h"
12 #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h"
13 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
14 #import "chrome/browser/autofill/personal_data_manager.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #import "chrome/browser/ui/cocoa/window_size_autosaver.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/common/notification_details.h"
23 #include "content/common/notification_observer.h"
24 #include "grit/app_resources.h"
25 #include "grit/generated_resources.h"
26 #include "grit/theme_resources.h"
27 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/resource/resource_bundle.h"
29 #include "ui/gfx/image.h"
30
31 namespace {
32
33 // Type for singleton object that contains the instance of the visible
34 // dialog.
35 typedef std::map<Profile*, AutoFillDialogController*> ProfileControllerMap;
36
37 static base::LazyInstance<ProfileControllerMap> g_profile_controller_map(
38 base::LINKER_INITIALIZED);
39
40 } // namespace
41
42 // Delegate protocol that needs to be in place for the AutoFillTableView's
43 // handling of delete and backspace keys.
44 @protocol DeleteKeyDelegate
45 - (IBAction)deleteSelection:(id)sender;
46 @end
47
48 // A subclass of NSTableView that allows for deleting selected elements using
49 // the delete or backspace keys.
50 @interface AutoFillTableView : NSTableView {
51 }
52 @end
53
54 @implementation AutoFillTableView
55
56 // We override the keyDown method to dispatch the |deleteSelection:| action
57 // when the user presses the delete or backspace keys. Note a delegate must
58 // be present that conforms to the DeleteKeyDelegate protocol.
59 - (void)keyDown:(NSEvent *)event {
60 id object = [self delegate];
61 unichar c = [[event characters] characterAtIndex: 0];
62
63 // If the user pressed delete and the delegate supports deleteSelection:
64 if ((c == NSDeleteFunctionKey ||
65 c == NSDeleteCharFunctionKey ||
66 c == NSDeleteCharacter) &&
67 [object respondsToSelector:@selector(deleteSelection:)]) {
68 id <DeleteKeyDelegate> delegate = (id <DeleteKeyDelegate>) object;
69
70 [delegate deleteSelection:self];
71 } else {
72 [super keyDown:event];
73 }
74 }
75
76 @end
77
78 // Private interface.
79 @interface AutoFillDialogController (PrivateMethods)
80 // Save profiles and credit card information after user modification.
81 - (void)save;
82
83 // Asyncronous handler for when PersonalDataManager data loads. The
84 // personal data manager notifies the dialog with this method when the
85 // data loading is complete and ready to be used.
86 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
87 creditCards:(const std::vector<CreditCard*>&)creditCards;
88
89 // Asyncronous handler for when PersonalDataManager data changes. The
90 // personal data manager notifies the dialog with this method when the
91 // data has changed.
92 - (void)onPersonalDataChanged:(const std::vector<AutoFillProfile*>&)profiles
93 creditCards:(const std::vector<CreditCard*>&)creditCards;
94
95 // Called upon changes to AutoFill preferences that should be reflected in the
96 // UI.
97 - (void)preferenceDidChange:(const std::string&)preferenceName;
98
99 // Adjust the selected index when underlying data changes.
100 // Selects the previous row if possible, else current row, else deselect all.
101 - (void) adjustSelectionOnDelete:(NSInteger)selectedRow;
102
103 // Adjust the selected index when underlying data changes.
104 // Selects the current row if possible, else previous row, else deselect all.
105 - (void) adjustSelectionOnReload:(NSInteger)selectedRow;
106
107 // Returns true if |row| is an index to a valid profile in |tableView_|, and
108 // false otherwise.
109 - (BOOL)isProfileRow:(NSInteger)row;
110
111 // Returns true if |row| is an index to the profile group row in |tableView_|,
112 // and false otherwise.
113 - (BOOL)isProfileGroupRow:(NSInteger)row;
114
115 // Returns true if |row| is an index to a valid credit card in |tableView_|, and
116 // false otherwise.
117 - (BOOL)isCreditCardRow:(NSInteger)row;
118
119 // Returns true if |row| is the index to the credit card group row in
120 // |tableView_|, and false otherwise.
121 - (BOOL)isCreditCardGroupRow:(NSInteger)row;
122
123 // Returns the index to |profiles_| of the corresponding |row| in |tableView_|.
124 - (size_t)profileIndexFromRow:(NSInteger)row;
125
126 // Returns the index to |creditCards_| of the corresponding |row| in
127 // |tableView_|.
128 - (size_t)creditCardIndexFromRow:(NSInteger)row;
129
130 // Returns the |row| in |tableView_| that corresponds to the index |i| into
131 // |profiles_|.
132 - (NSInteger)rowFromProfileIndex:(size_t)i;
133
134 // Returns the |row| in |tableView_| that corresponds to the index |i| into
135 // |creditCards_|.
136 - (NSInteger)rowFromCreditCardIndex:(size_t)row;
137
138 @end
139
140 namespace AutoFillDialogControllerInternal {
141
142 // PersonalDataManagerObserver facilitates asynchronous loading of
143 // PersonalDataManager data before showing the AutoFill settings data to the
144 // user. It acts as a C++-based delegate for the |AutoFillDialogController|.
145 class PersonalDataManagerObserver : public PersonalDataManager::Observer {
146 public:
147 explicit PersonalDataManagerObserver(
148 AutoFillDialogController* controller,
149 PersonalDataManager* personal_data_manager,
150 Profile* profile)
151 : controller_(controller),
152 personal_data_manager_(personal_data_manager),
153 profile_(profile) {
154 }
155
156 virtual ~PersonalDataManagerObserver();
157
158 // Notifies the observer that the PersonalDataManager has finished loading.
159 virtual void OnPersonalDataLoaded();
160
161 // Notifies the observer that the PersonalDataManager data has changed.
162 virtual void OnPersonalDataChanged();
163
164 private:
165 // Utility method to remove |this| from |personal_data_manager_| as an
166 // observer.
167 void RemoveObserver();
168
169 // The dialog controller to be notified when the data loading completes.
170 // Weak reference.
171 AutoFillDialogController* controller_;
172
173 // The object in which we are registered as an observer. We hold on to
174 // it to facilitate un-registering ourself in the destructor and in the
175 // |OnPersonalDataLoaded| method. This may be NULL.
176 // Weak reference.
177 PersonalDataManager* personal_data_manager_;
178
179 // Profile of caller. Held as weak reference. May not be NULL.
180 Profile* profile_;
181
182 private:
183 DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerObserver);
184 };
185
186 // During destruction ensure that we are removed from the
187 // |personal_data_manager_| as an observer.
188 PersonalDataManagerObserver::~PersonalDataManagerObserver() {
189 RemoveObserver();
190 }
191
192 void PersonalDataManagerObserver::RemoveObserver() {
193 if (personal_data_manager_) {
194 personal_data_manager_->RemoveObserver(this);
195 }
196 }
197
198 // The data has been loaded, notify the controller.
199 void PersonalDataManagerObserver::OnPersonalDataLoaded() {
200 [controller_ onPersonalDataLoaded:personal_data_manager_->web_profiles()
201 creditCards:personal_data_manager_->credit_cards()];
202 }
203
204 // The data has changed, notify the controller.
205 void PersonalDataManagerObserver::OnPersonalDataChanged() {
206 [controller_ onPersonalDataChanged:personal_data_manager_->web_profiles()
207 creditCards:personal_data_manager_->credit_cards()];
208 }
209
210 // Bridges preference changed notifications to the dialog controller.
211 class PreferenceObserver : public NotificationObserver {
212 public:
213 explicit PreferenceObserver(AutoFillDialogController* controller)
214 : controller_(controller) {}
215
216 // Overridden from NotificationObserver:
217 virtual void Observe(NotificationType type,
218 const NotificationSource& source,
219 const NotificationDetails& details) {
220 if (type == NotificationType::PREF_CHANGED) {
221 const std::string* pref = Details<std::string>(details).ptr();
222 if (pref) {
223 [controller_ preferenceDidChange:*pref];
224 }
225 }
226 }
227
228 private:
229 AutoFillDialogController* controller_;
230
231 DISALLOW_COPY_AND_ASSIGN(PreferenceObserver);
232 };
233
234 } // namespace AutoFillDialogControllerInternal
235
236 @implementation AutoFillDialogController
237
238 @synthesize autoFillManaged = autoFillManaged_;
239 @synthesize autoFillManagedAndDisabled = autoFillManagedAndDisabled_;
240 @synthesize itemIsSelected = itemIsSelected_;
241 @synthesize multipleSelected = multipleSelected_;
242
243 + (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer
244 profile:(Profile*)profile {
245 AutoFillDialogController* controller =
246 [AutoFillDialogController controllerWithObserver:observer
247 profile:profile];
248 [controller runModelessDialog];
249 }
250
251 - (void)awakeFromNib {
252 PersonalDataManager* personal_data_manager =
253 profile_->GetPersonalDataManager();
254 DCHECK(personal_data_manager);
255
256 if (personal_data_manager->IsDataLoaded()) {
257 // |personalDataManager| data is loaded, we can proceed with the contents.
258 [self onPersonalDataLoaded:personal_data_manager->web_profiles()
259 creditCards:personal_data_manager->credit_cards()];
260 }
261
262 // Register as listener to listen to subsequent data change notifications.
263 personalDataManagerObserver_.reset(
264 new AutoFillDialogControllerInternal::PersonalDataManagerObserver(
265 self, personal_data_manager, profile_));
266 personal_data_manager->SetObserver(personalDataManagerObserver_.get());
267
268 // Explicitly load the data in the table before window displays to avoid
269 // nasty flicker as tables update.
270 [tableView_ reloadData];
271
272 // Set up edit when double-clicking on a table row.
273 [tableView_ setDoubleAction:@selector(editSelection:)];
274 }
275
276 // NSWindow Delegate callback. When the window closes the controller can
277 // be released.
278 - (void)windowWillClose:(NSNotification *)notification {
279 [tableView_ setDataSource:nil];
280 [tableView_ setDelegate:nil];
281 [self autorelease];
282
283 // Remove ourself from the map.
284 ProfileControllerMap* map = g_profile_controller_map.Pointer();
285 ProfileControllerMap::iterator it = map->find(profile_);
286 if (it != map->end()) {
287 map->erase(it);
288 }
289 }
290
291 // Invokes the "Add" sheet for address information. If user saves then the new
292 // information is added to |profiles_| in |addressAddDidEnd:| method.
293 - (IBAction)addNewAddress:(id)sender {
294 DCHECK(!addressSheetController.get());
295
296 // Create a new default address.
297 AutoFillProfile newAddress;
298
299 // Create a new address sheet controller in "Add" mode.
300 addressSheetController.reset(
301 [[AutoFillAddressSheetController alloc]
302 initWithProfile:newAddress
303 mode:kAutoFillAddressAddMode]);
304
305 // Show the sheet.
306 [NSApp beginSheet:[addressSheetController window]
307 modalForWindow:[self window]
308 modalDelegate:self
309 didEndSelector:@selector(addressAddDidEnd:returnCode:contextInfo:)
310 contextInfo:NULL];
311 }
312
313 // Invokes the "Add" sheet for credit card information. If user saves then the
314 // new information is added to |creditCards_| in |creditCardAddDidEnd:| method.
315 - (IBAction)addNewCreditCard:(id)sender {
316 DCHECK(!creditCardSheetController.get());
317
318 // Create a new default credit card.
319 CreditCard newCreditCard;
320
321 // Create a new address sheet controller in "Add" mode.
322 creditCardSheetController.reset(
323 [[AutoFillCreditCardSheetController alloc]
324 initWithCreditCard:newCreditCard
325 mode:kAutoFillCreditCardAddMode]);
326
327 // Show the sheet.
328 [NSApp beginSheet:[creditCardSheetController window]
329 modalForWindow:[self window]
330 modalDelegate:self
331 didEndSelector:@selector(creditCardAddDidEnd:returnCode:contextInfo:)
332 contextInfo:NULL];
333 }
334
335 // Add address sheet was dismissed. Non-zero |returnCode| indicates a save.
336 - (void)addressAddDidEnd:(NSWindow*)sheet
337 returnCode:(int)returnCode
338 contextInfo:(void*)contextInfo {
339 DCHECK(!contextInfo);
340
341 if (returnCode) {
342 // Create a new address and save it to the |profiles_| list.
343 AutoFillProfile newAddress;
344 [addressSheetController copyModelToProfile:&newAddress];
345 if (!newAddress.IsEmpty() && !FindByContents(profiles_, newAddress)) {
346 profiles_.push_back(newAddress);
347
348 // Saving will save to the PDM and the table will refresh when PDM sends
349 // notification that the underlying model has changed.
350 [self save];
351
352 // Update the selection to the newly added item.
353 NSInteger row = [self rowFromProfileIndex:profiles_.size() - 1];
354 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
355 byExtendingSelection:NO];
356 }
357 }
358 [sheet orderOut:self];
359 addressSheetController.reset(nil);
360 }
361
362 // Add credit card sheet was dismissed. Non-zero |returnCode| indicates a save.
363 - (void)creditCardAddDidEnd:(NSWindow*)sheet
364 returnCode:(int)returnCode
365 contextInfo:(void*)contextInfo {
366 DCHECK(!contextInfo);
367
368 if (returnCode) {
369 // Create a new credit card and save it to the |creditCards_| list.
370 CreditCard newCreditCard;
371 [creditCardSheetController copyModelToCreditCard:&newCreditCard];
372 if (!newCreditCard.IsEmpty() &&
373 !FindByContents(creditCards_, newCreditCard)) {
374 creditCards_.push_back(newCreditCard);
375
376 // Saving will save to the PDM and the table will refresh when PDM sends
377 // notification that the underlying model has changed.
378 [self save];
379
380 // Update the selection to the newly added item.
381 NSInteger row = [self rowFromCreditCardIndex:creditCards_.size() - 1];
382 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
383 byExtendingSelection:NO];
384 }
385 }
386 [sheet orderOut:self];
387 creditCardSheetController.reset(nil);
388 }
389
390 // Deletes selected items; either addresses, credit cards, or a mixture of the
391 // two depending on the items selected.
392 - (IBAction)deleteSelection:(id)sender {
393 NSIndexSet* selection = [tableView_ selectedRowIndexes];
394 NSInteger selectedRow = [tableView_ selectedRow];
395
396 // Loop through from last to first deleting selected items as we go.
397 for (NSUInteger i = [selection lastIndex];
398 i != NSNotFound;
399 i = [selection indexLessThanIndex:i]) {
400 // We keep track of the "top most" selection in the list so we know where
401 // to set new selection below.
402 selectedRow = i;
403
404 if ([self isProfileRow:i]) {
405 profiles_.erase(
406 profiles_.begin() + [self profileIndexFromRow:i]);
407 } else if ([self isCreditCardRow:i]) {
408 creditCards_.erase(
409 creditCards_.begin() + [self creditCardIndexFromRow:i]);
410 }
411 }
412
413 // Select the previous row if possible, else current row, else deselect all.
414 [self adjustSelectionOnDelete:selectedRow];
415
416 // Saving will save to the PDM and the table will refresh when PDM sends
417 // notification that the underlying model has changed.
418 [self save];
419 }
420
421 // Edits the selected item, either address or credit card depending on the item
422 // selected.
423 - (IBAction)editSelection:(id)sender {
424 NSInteger selectedRow = [tableView_ selectedRow];
425 if ([self isProfileRow:selectedRow]) {
426 if (!addressSheetController.get()) {
427 int i = [self profileIndexFromRow:selectedRow];
428
429 // Create a new address sheet controller in "Edit" mode.
430 addressSheetController.reset(
431 [[AutoFillAddressSheetController alloc]
432 initWithProfile:profiles_[i]
433 mode:kAutoFillAddressEditMode]);
434
435 // Show the sheet.
436 [NSApp beginSheet:[addressSheetController window]
437 modalForWindow:[self window]
438 modalDelegate:self
439 didEndSelector:@selector(addressEditDidEnd:returnCode:contextInfo:)
440 contextInfo:&profiles_[i]];
441 }
442 } else if ([self isCreditCardRow:selectedRow]) {
443 if (!creditCardSheetController.get()) {
444 int i = [self creditCardIndexFromRow:selectedRow];
445
446 // Create a new credit card sheet controller in "Edit" mode.
447 creditCardSheetController.reset(
448 [[AutoFillCreditCardSheetController alloc]
449 initWithCreditCard:creditCards_[i]
450 mode:kAutoFillCreditCardEditMode]);
451
452 // Show the sheet.
453 [NSApp beginSheet:[creditCardSheetController window]
454 modalForWindow:[self window]
455 modalDelegate:self
456 didEndSelector:@selector(creditCardEditDidEnd:returnCode:contextInfo:)
457 contextInfo:&creditCards_[i]];
458 }
459 }
460 }
461
462 // Navigates to the AutoFill help url.
463 - (IBAction)openHelp:(id)sender {
464 Browser* browser = BrowserList::GetLastActive();
465
466 if (!browser || !browser->GetSelectedTabContents())
467 browser = Browser::Create(profile_);
468 browser->OpenAutoFillHelpTabAndActivate();
469 }
470
471 // Edit address sheet was dismissed. Non-zero |returnCode| indicates a save.
472 - (void)addressEditDidEnd:(NSWindow *)sheet
473 returnCode:(int)returnCode
474 contextInfo:(void *)contextInfo {
475 DCHECK(contextInfo != NULL);
476 if (returnCode) {
477 AutoFillProfile* profile = static_cast<AutoFillProfile*>(contextInfo);
478 [addressSheetController copyModelToProfile:profile];
479
480 if (profile->IsEmpty())
481 [tableView_ deselectAll:self];
482 profiles_.erase(
483 std::remove_if(profiles_.begin(), profiles_.end(),
484 std::mem_fun_ref(&AutoFillProfile::IsEmpty)),
485 profiles_.end());
486
487 // Saving will save to the PDM and the table will refresh when PDM sends
488 // notification that the underlying model has changed.
489 [self save];
490 }
491 [sheet orderOut:self];
492 addressSheetController.reset(nil);
493 }
494
495 // Edit credit card sheet was dismissed. Non-zero |returnCode| indicates a
496 // save.
497 - (void)creditCardEditDidEnd:(NSWindow *)sheet
498 returnCode:(int)returnCode
499 contextInfo:(void *)contextInfo {
500 DCHECK(contextInfo != NULL);
501 if (returnCode) {
502 CreditCard* creditCard = static_cast<CreditCard*>(contextInfo);
503 [creditCardSheetController copyModelToCreditCard:creditCard];
504
505 if (creditCard->IsEmpty())
506 [tableView_ deselectAll:self];
507 creditCards_.erase(
508 std::remove_if(
509 creditCards_.begin(), creditCards_.end(),
510 std::mem_fun_ref(&CreditCard::IsEmpty)),
511 creditCards_.end());
512
513 // Saving will save to the PDM and the table will refresh when PDM sends
514 // notification that the underlying model has changed.
515 [self save];
516 }
517 [sheet orderOut:self];
518 creditCardSheetController.reset(nil);
519 }
520
521 // NSTableView Delegate method.
522 - (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row {
523 if ([self isProfileGroupRow:row] || [self isCreditCardGroupRow:row])
524 return YES;
525 return NO;
526 }
527
528 // NSTableView Delegate method.
529 - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row {
530 return [self isProfileRow:row] || [self isCreditCardRow:row];
531 }
532
533 // NSTableView Delegate method.
534 - (id)tableView:(NSTableView *)tableView
535 objectValueForTableColumn:(NSTableColumn *)tableColumn
536 row:(NSInteger)row {
537 if ([[tableColumn identifier] isEqualToString:@"Spacer"])
538 return @"";
539
540 // Check that we're initialized before supplying data.
541 if (tableView != tableView_)
542 return @"";
543
544 // Section label.
545 if ([self isProfileGroupRow:row]) {
546 if ([[tableColumn identifier] isEqualToString:@"Summary"])
547 return l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES_GROUP_NAME);
548 else
549 return @"";
550 }
551
552 if (row < 0)
553 return @"";
554
555 // Data row.
556 if ([self isProfileRow:row]) {
557 if ([[tableColumn identifier] isEqualToString:@"Summary"]) {
558 return SysUTF16ToNSString(
559 profiles_[[self profileIndexFromRow:row]].Label());
560 }
561
562 return @"";
563 }
564
565 // Section label.
566 if ([self isCreditCardGroupRow:row]) {
567 if ([[tableColumn identifier] isEqualToString:@"Summary"])
568 return l10n_util::GetNSString(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME);
569 else
570 return @"";
571 }
572
573 // Data row.
574 if ([self isCreditCardRow:row]) {
575 if ([[tableColumn identifier] isEqualToString:@"Summary"]) {
576 return SysUTF16ToNSString(
577 creditCards_[
578 [self creditCardIndexFromRow:row]].PreviewSummary());
579 }
580
581 return @"";
582 }
583
584 return @"";
585 }
586
587 // We implement this delegate method to update our |itemIsSelected| and
588 // |multipleSelected| properties.
589 // The "Edit..." and "Remove" buttons' enabled state depends on having a
590 // valid selection in the table. The "Edit..." button depends on having
591 // exactly one item selected.
592 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification {
593 if ([tableView_ selectedRow] >= 0)
594 [self setItemIsSelected:YES];
595 else
596 [self setItemIsSelected:NO];
597
598 [self setMultipleSelected:([[tableView_ selectedRowIndexes] count] > 1UL)];
599 }
600
601 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
602 if (tableView == tableView_) {
603 // 1 section header, the profiles, 1 section header, the credit cards.
604 return 1 + profiles_.size() + 1 + creditCards_.size();
605 }
606
607 return 0;
608 }
609
610 // Accessor for |autoFillEnabled| preference state. Note: a checkbox in Nib
611 // is bound to this via KVO.
612 - (BOOL)autoFillEnabled {
613 return autoFillEnabled_.GetValue();
614 }
615
616 // Setter for |autoFillEnabled| preference state.
617 - (void)setAutoFillEnabled:(BOOL)value {
618 autoFillEnabled_.SetValueIfNotManaged(value ? true : false);
619 }
620
621 // Accessor for |auxiliaryEnabled| preference state. Note: a checkbox in Nib
622 // is bound to this via KVO.
623 - (BOOL)auxiliaryEnabled {
624 return auxiliaryEnabled_.GetValue();
625 }
626
627 // Setter for |auxiliaryEnabled| preference state.
628 - (void)setAuxiliaryEnabled:(BOOL)value {
629 if ([self autoFillEnabled])
630 auxiliaryEnabled_.SetValueIfNotManaged(value ? true : false);
631 }
632
633 @end
634
635 @implementation AutoFillDialogController (ExposedForUnitTests)
636
637 + (AutoFillDialogController*)
638 controllerWithObserver:(AutoFillDialogObserver*)observer
639 profile:(Profile*)profile {
640 profile = profile->GetOriginalProfile();
641
642 ProfileControllerMap* map = g_profile_controller_map.Pointer();
643 DCHECK(map != NULL);
644 ProfileControllerMap::iterator it = map->find(profile);
645 if (it == map->end()) {
646 // We should have exactly 1 or 0 entry in the map, no more. That is,
647 // only one profile can have the AutoFill dialog up at a time.
648 DCHECK_EQ(map->size(), 0U);
649
650 // Deallocation is done upon window close. See |windowWillClose:|.
651 AutoFillDialogController* controller =
652 [[self alloc] initWithObserver:observer profile:profile];
653 it = map->insert(std::make_pair(profile, controller)).first;
654 }
655
656 return it->second;
657 }
658
659
660 // This is the designated initializer for this class.
661 // |profiles| are non-retained immutable list of AutoFill profiles.
662 // |creditCards| are non-retained immutable list of credit card info.
663 - (id)initWithObserver:(AutoFillDialogObserver*)observer
664 profile:(Profile*)profile {
665 DCHECK(profile);
666 // Use initWithWindowNibPath: instead of initWithWindowNibName: so we
667 // can override it in a unit test.
668 NSString* nibpath = [base::mac::MainAppBundle()
669 pathForResource:@"AutoFillDialog"
670 ofType:@"nib"];
671 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
672 // Initialize member variables based on input.
673 observer_ = observer;
674 profile_ = profile;
675
676 // Initialize the preference observer and watch kAutoFillEnabled.
677 preferenceObserver_.reset(
678 new AutoFillDialogControllerInternal::PreferenceObserver(self));
679 autoFillEnabled_.Init(prefs::kAutoFillEnabled, profile_->GetPrefs(),
680 preferenceObserver_.get());
681
682 // Call |preferenceDidChange| in order to initialize UI state of the
683 // checkbox.
684 [self preferenceDidChange:prefs::kAutoFillEnabled];
685
686 // Initialize the preference observer and watch
687 // kAutoFillAuxiliaryProfilesEnabled.
688 auxiliaryEnabled_.Init(prefs::kAutoFillAuxiliaryProfilesEnabled,
689 profile_->GetPrefs(),
690 preferenceObserver_.get());
691
692 // Call |preferenceDidChange| in order to initialize UI state of the
693 // checkbox.
694 [self preferenceDidChange:prefs::kAutoFillAuxiliaryProfilesEnabled];
695
696 // Do not use [NSMutableArray array] here; we need predictable destruction
697 // which will be prevented by having a reference held by an autorelease
698 // pool.
699 }
700 return self;
701 }
702
703 // Run modeless.
704 - (void)runModelessDialog {
705 // Use stored window geometry if it exists.
706 if (g_browser_process && g_browser_process->local_state()) {
707 sizeSaver_.reset([[WindowSizeAutosaver alloc]
708 initWithWindow:[self window]
709 prefService:g_browser_process->local_state()
710 path:prefs::kAutoFillDialogPlacement]);
711 }
712
713 [self showWindow:nil];
714 }
715
716 // Close the dialog.
717 - (void)closeDialog {
718 [[self window] performClose:self];
719 }
720
721 - (AutoFillAddressSheetController*)addressSheetController {
722 return addressSheetController.get();
723 }
724
725 - (AutoFillCreditCardSheetController*)creditCardSheetController {
726 return creditCardSheetController.get();
727 }
728
729 - (void)selectAddressAtIndex:(size_t)i {
730 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
731 [self rowFromProfileIndex:i]]
732 byExtendingSelection:NO];
733 }
734
735 - (void)selectCreditCardAtIndex:(size_t)i {
736 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
737 [self rowFromCreditCardIndex:i]]
738 byExtendingSelection:NO];
739 }
740
741 - (void)addSelectedAddressAtIndex:(size_t)i {
742 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
743 [self rowFromProfileIndex:i]]
744 byExtendingSelection:YES];
745 }
746
747 - (void)addSelectedCreditCardAtIndex:(size_t)i {
748 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
749 [self rowFromCreditCardIndex:i]]
750 byExtendingSelection:YES];
751 }
752
753 - (BOOL)editButtonEnabled {
754 return [editButton_ isEnabled];
755 }
756
757 - (std::vector<AutoFillProfile>&)profiles {
758 return profiles_;
759 }
760
761 - (std::vector<CreditCard>&)creditCards {
762 return creditCards_;
763 }
764
765 @end
766
767 @implementation AutoFillDialogController (PrivateMethods)
768
769 // Called when the user modifies the profiles or credit card information.
770 - (void)save {
771 // If we have an |observer_| then communicate the changes back, unless
772 // AutoFill has been disabled through policy in the mean time.
773 if (observer_ && !autoFillManagedAndDisabled_) {
774 // Make a working copy of profiles. |OnAutoFillDialogApply| can mutate
775 // |profiles_|.
776 std::vector<AutoFillProfile> profiles = profiles_;
777
778 // Make a working copy of credit cards. |OnAutoFillDialogApply| can mutate
779 // |creditCards_|.
780 std::vector<CreditCard> creditCards = creditCards_;
781
782 observer_->OnAutoFillDialogApply(&profiles, &creditCards);
783 }
784 }
785
786 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
787 creditCards:(const std::vector<CreditCard*>&)creditCards {
788 [self onPersonalDataChanged:profiles creditCards:creditCards];
789 }
790
791 - (void)onPersonalDataChanged:(const std::vector<AutoFillProfile*>&)profiles
792 creditCards:(const std::vector<CreditCard*>&)creditCards {
793 // Make local copy of |profiles|.
794 profiles_.clear();
795 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
796 iter != profiles.end(); ++iter)
797 profiles_.push_back(**iter);
798
799 // Make local copy of |creditCards|.
800 creditCards_.clear();
801 for (std::vector<CreditCard*>::const_iterator iter = creditCards.begin();
802 iter != creditCards.end(); ++iter)
803 creditCards_.push_back(**iter);
804
805 [self adjustSelectionOnReload:[tableView_ selectedRow]];
806 [tableView_ reloadData];
807 }
808
809 - (void)preferenceDidChange:(const std::string&)preferenceName {
810 if (preferenceName == prefs::kAutoFillEnabled) {
811 [self setAutoFillEnabled:autoFillEnabled_.GetValue()];
812 [self setAutoFillManaged:autoFillEnabled_.IsManaged()];
813 [self setAutoFillManagedAndDisabled:
814 autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue()];
815 } else if (preferenceName == prefs::kAutoFillAuxiliaryProfilesEnabled) {
816 [self setAuxiliaryEnabled:auxiliaryEnabled_.GetValue()];
817 } else {
818 NOTREACHED();
819 }
820 }
821
822 - (void) adjustSelectionOnDelete:(NSInteger)selectedRow {
823 if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) {
824 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1]
825 byExtendingSelection:NO];
826 } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) {
827 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
828 byExtendingSelection:NO];
829 } else {
830 [tableView_ deselectAll:self];
831 }
832 }
833
834 - (void) adjustSelectionOnReload:(NSInteger)selectedRow {
835 if ([self tableView:tableView_ shouldSelectRow:selectedRow]) {
836 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
837 byExtendingSelection:NO];
838 } else if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) {
839 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1]
840 byExtendingSelection:NO];
841 } else {
842 [tableView_ deselectAll:self];
843 }
844 }
845
846 - (BOOL)isProfileRow:(NSInteger)row {
847 if (row > 0 && static_cast<size_t>(row) <= profiles_.size())
848 return YES;
849 return NO;
850 }
851
852 - (BOOL)isProfileGroupRow:(NSInteger)row {
853 if (row == 0)
854 return YES;
855 return NO;
856 }
857
858 - (BOOL)isCreditCardRow:(NSInteger)row {
859 if (row > 0 &&
860 static_cast<size_t>(row) >= profiles_.size() + 2 &&
861 static_cast<size_t>(row) <= profiles_.size() + creditCards_.size() + 1)
862 return YES;
863 return NO;
864 }
865
866 - (BOOL)isCreditCardGroupRow:(NSInteger)row {
867 if (row > 0 && static_cast<size_t>(row) == profiles_.size() + 1)
868 return YES;
869 return NO;
870 }
871
872 - (size_t)profileIndexFromRow:(NSInteger)row {
873 DCHECK([self isProfileRow:row]);
874 return static_cast<size_t>(row) - 1;
875 }
876
877 - (size_t)creditCardIndexFromRow:(NSInteger)row {
878 DCHECK([self isCreditCardRow:row]);
879 return static_cast<size_t>(row) - (profiles_.size() + 2);
880 }
881
882 - (NSInteger)rowFromProfileIndex:(size_t)i {
883 return 1 + i;
884 }
885
886 - (NSInteger)rowFromCreditCardIndex:(size_t)i {
887 return 1 + profiles_.size() + 1 + i;
888 }
889
890 @end
891
892 // An NSValueTransformer subclass for use in validation of phone number
893 // fields. Transforms an invalid phone number string into a warning image.
894 // This data transformer is used in the credit card sheet for invalid phone and
895 // fax numbers.
896 @interface InvalidPhoneTransformer : NSValueTransformer {
897 }
898 @end
899
900 @implementation InvalidPhoneTransformer
901 + (Class)transformedValueClass {
902 return [NSImage class];
903 }
904
905 + (BOOL)allowsReverseTransformation {
906 return NO;
907 }
908
909 - (id)transformedValue:(id)string {
910 NSImage* image = nil;
911 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
912
913 // We display no validation icon when input has not yet been entered.
914 if (string == nil || [string length] == 0)
915 return nil;
916
917 // If we have input then display alert icon if we have an invalid number.
918 if (string != nil && [string length] != 0) {
919 // TODO(dhollowa): Using SetInfo() call to validate phone number. Should
920 // have explicit validation method. More robust validation is needed as
921 // well eventually.
922 AutoFillProfile profile;
923 profile.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
924 base::SysNSStringToUTF16(string));
925 if (profile.GetFieldText(AutofillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
926 image = rb.GetNativeImageNamed(IDR_INPUT_ALERT);
927 DCHECK(image);
928 return image;
929 }
930 }
931
932 // No alert icon, so must be valid input.
933 if (!image) {
934 image = rb.GetNativeImageNamed(IDR_INPUT_GOOD);
935 DCHECK(image);
936 return image;
937 }
938
939 return nil;
940 }
941
942 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698