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

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

Issue 3302015: AutoFill Mac dialog should be non-modal (Closed)
Patch Set: Indent. Created 10 years, 3 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 (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/autofill/autofill_dialog_controller_mac.h" 5 #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
6 #include "app/l10n_util.h" 6 #include "app/l10n_util.h"
7 #include "app/resource_bundle.h" 7 #include "app/resource_bundle.h"
8 #include "base/mac_util.h" 8 #include "base/mac_util.h"
9 #include "base/singleton.h"
9 #include "base/sys_string_conversions.h" 10 #include "base/sys_string_conversions.h"
10 #include "chrome/browser/browser.h" 11 #include "chrome/browser/browser.h"
11 #include "chrome/browser/browser_list.h" 12 #include "chrome/browser/browser_list.h"
12 #import "chrome/browser/autofill/autofill_address_model_mac.h" 13 #import "chrome/browser/autofill/autofill_address_model_mac.h"
13 #import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h" 14 #import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h"
14 #import "chrome/browser/autofill/autofill_credit_card_model_mac.h" 15 #import "chrome/browser/autofill/autofill_credit_card_model_mac.h"
15 #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h" 16 #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h"
16 #import "chrome/browser/autofill/personal_data_manager.h" 17 #import "chrome/browser/autofill/personal_data_manager.h"
17 #include "chrome/browser/browser_process.h" 18 #include "chrome/browser/browser_process.h"
18 #import "chrome/browser/cocoa/window_size_autosaver.h" 19 #import "chrome/browser/cocoa/window_size_autosaver.h"
19 #include "chrome/browser/prefs/pref_service.h" 20 #include "chrome/browser/prefs/pref_service.h"
20 #include "chrome/browser/profile.h" 21 #include "chrome/browser/profile.h"
21 #include "chrome/common/notification_details.h" 22 #include "chrome/common/notification_details.h"
22 #include "chrome/common/notification_observer.h" 23 #include "chrome/common/notification_observer.h"
23 #include "chrome/common/pref_names.h" 24 #include "chrome/common/pref_names.h"
24 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
25 #include "grit/app_resources.h" 26 #include "grit/app_resources.h"
26 #include "grit/theme_resources.h" 27 #include "grit/theme_resources.h"
27 28
28 namespace { 29 namespace {
29 30
31 // Type for singleton object that contains the instance of the visible
32 // dialog.
33 typedef std::map<Profile*, AutoFillDialogController*> ProfileControllerMap;
34
30 // Update profile labels passed as |input|. When profile data changes as a 35 // Update profile labels passed as |input|. When profile data changes as a
31 // result of adding new profiles, edititing existing profiles, or deleting a 36 // result of adding new profiles, edititing existing profiles, or deleting a
32 // profile, then the list of profiles need to have their derived labels 37 // profile, then the list of profiles need to have their derived labels
33 // recomputed. 38 // recomputed.
34 void UpdateProfileLabels(std::vector<AutoFillProfile>* input) { 39 void UpdateProfileLabels(std::vector<AutoFillProfile>* input) {
35 DCHECK(input); 40 DCHECK(input);
36 std::vector<AutoFillProfile*> profiles; 41 std::vector<AutoFillProfile*> profiles;
37 profiles.resize(input->size()); 42 profiles.resize(input->size());
38 for (size_t i = 0; i < input->size(); ++i) { 43 for (size_t i = 0; i < input->size(); ++i) {
39 profiles[i] = &(*input)[i]; 44 profiles[i] = &(*input)[i];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 [delegate deleteSelection:self]; 79 [delegate deleteSelection:self];
75 } else { 80 } else {
76 [super keyDown:event]; 81 [super keyDown:event];
77 } 82 }
78 } 83 }
79 84
80 @end 85 @end
81 86
82 // Private interface. 87 // Private interface.
83 @interface AutoFillDialogController (PrivateMethods) 88 @interface AutoFillDialogController (PrivateMethods)
89 // Save profiles and credit card information after user modification.
90 - (void)save;
91
84 // Asyncronous handler for when PersonalDataManager data loads. The 92 // Asyncronous handler for when PersonalDataManager data loads. The
85 // personal data manager notifies the dialog with this method when the 93 // personal data manager notifies the dialog with this method when the
86 // data loading is complete and ready to be used. 94 // data loading is complete and ready to be used.
87 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles 95 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
88 creditCards:(const std::vector<CreditCard*>&)creditCards; 96 creditCards:(const std::vector<CreditCard*>&)creditCards;
89 97
98 // Asyncronous handler for when PersonalDataManager data changes. The
99 // personal data manager notifies the dialog with this method when the
100 // data has changed.
101 - (void)onPersonalDataChanged:(const std::vector<AutoFillProfile*>&)profiles
102 creditCards:(const std::vector<CreditCard*>&)creditCards;
103
90 // Called upon changes to AutoFill preferences that should be reflected in the 104 // Called upon changes to AutoFill preferences that should be reflected in the
91 // UI. 105 // UI.
92 - (void)onPrefChanged:(const std::string&)prefName; 106 - (void)preferenceDidChange:(const std::string&)preferenceName;
93 107
94 // Returns true if |row| is an index to a valid profile in |tableView_|, and 108 // Returns true if |row| is an index to a valid profile in |tableView_|, and
95 // false otherwise. 109 // false otherwise.
96 - (BOOL)isProfileRow:(NSInteger)row; 110 - (BOOL)isProfileRow:(NSInteger)row;
97 111
98 // Returns true if |row| is an index to the profile group row in |tableView_|, 112 // Returns true if |row| is an index to the profile group row in |tableView_|,
99 // and false otherwise. 113 // and false otherwise.
100 - (BOOL)isProfileGroupRow:(NSInteger)row; 114 - (BOOL)isProfileGroupRow:(NSInteger)row;
101 115
102 // Returns true if |row| is an index to a valid credit card in |tableView_|, and 116 // Returns true if |row| is an index to a valid credit card in |tableView_|, and
(...skipping 12 matching lines...) Expand all
115 - (size_t)creditCardIndexFromRow:(NSInteger)row; 129 - (size_t)creditCardIndexFromRow:(NSInteger)row;
116 130
117 // Returns the |row| in |tableView_| that corresponds to the index |i| into 131 // Returns the |row| in |tableView_| that corresponds to the index |i| into
118 // |profiles_|. 132 // |profiles_|.
119 - (NSInteger)rowFromProfileIndex:(size_t)i; 133 - (NSInteger)rowFromProfileIndex:(size_t)i;
120 134
121 // Returns the |row| in |tableView_| that corresponds to the index |i| into 135 // Returns the |row| in |tableView_| that corresponds to the index |i| into
122 // |creditCards_|. 136 // |creditCards_|.
123 - (NSInteger)rowFromCreditCardIndex:(size_t)row; 137 - (NSInteger)rowFromCreditCardIndex:(size_t)row;
124 138
125 // Invokes the modal dialog.
126 - (void)runModalDialog;
127
128 @end 139 @end
129 140
130 namespace AutoFillDialogControllerInternal { 141 namespace AutoFillDialogControllerInternal {
131 142
132 // PersonalDataManagerObserver facilitates asynchronous loading of 143 // PersonalDataManagerObserver facilitates asynchronous loading of
133 // PersonalDataManager data before showing the AutoFill settings data to the 144 // PersonalDataManager data before showing the AutoFill settings data to the
134 // user. It acts as a C++-based delegate for the |AutoFillDialogController|. 145 // user. It acts as a C++-based delegate for the |AutoFillDialogController|.
135 class PersonalDataManagerObserver : public PersonalDataManager::Observer { 146 class PersonalDataManagerObserver : public PersonalDataManager::Observer {
136 public: 147 public:
137 explicit PersonalDataManagerObserver( 148 explicit PersonalDataManagerObserver(
138 AutoFillDialogController* controller, 149 AutoFillDialogController* controller,
139 PersonalDataManager* personal_data_manager, 150 PersonalDataManager* personal_data_manager,
140 Profile* profile) 151 Profile* profile)
141 : controller_(controller), 152 : controller_(controller),
142 personal_data_manager_(personal_data_manager), 153 personal_data_manager_(personal_data_manager),
143 profile_(profile) { 154 profile_(profile) {
144 } 155 }
145 156
146 virtual ~PersonalDataManagerObserver(); 157 virtual ~PersonalDataManagerObserver();
147 158
148 // Notifies the observer that the PersonalDataManager has finished loading. 159 // Notifies the observer that the PersonalDataManager has finished loading.
149 virtual void OnPersonalDataLoaded(); 160 virtual void OnPersonalDataLoaded();
150 161
162 // Notifies the observer that the PersonalDataManager data has changed.
163 virtual void OnPersonalDataChanged();
164
151 private: 165 private:
152 // Utility method to remove |this| from |personal_data_manager_| as an 166 // Utility method to remove |this| from |personal_data_manager_| as an
153 // observer. 167 // observer.
154 void RemoveObserver(); 168 void RemoveObserver();
155 169
156 // The dialog controller to be notified when the data loading completes. 170 // The dialog controller to be notified when the data loading completes.
157 // Weak reference. 171 // Weak reference.
158 AutoFillDialogController* controller_; 172 AutoFillDialogController* controller_;
159 173
160 // The object in which we are registered as an observer. We hold on to 174 // The object in which we are registered as an observer. We hold on to
(...skipping 14 matching lines...) Expand all
175 PersonalDataManagerObserver::~PersonalDataManagerObserver() { 189 PersonalDataManagerObserver::~PersonalDataManagerObserver() {
176 RemoveObserver(); 190 RemoveObserver();
177 } 191 }
178 192
179 void PersonalDataManagerObserver::RemoveObserver() { 193 void PersonalDataManagerObserver::RemoveObserver() {
180 if (personal_data_manager_) { 194 if (personal_data_manager_) {
181 personal_data_manager_->RemoveObserver(this); 195 personal_data_manager_->RemoveObserver(this);
182 } 196 }
183 } 197 }
184 198
185 // The data is ready so display our data. Notify the dialog controller that 199 // The data has been loaded, notify the controller.
186 // the data is ready. Once done we clear the observer.
187 void PersonalDataManagerObserver::OnPersonalDataLoaded() { 200 void PersonalDataManagerObserver::OnPersonalDataLoaded() {
188 RemoveObserver();
189 [controller_ onPersonalDataLoaded:personal_data_manager_->web_profiles() 201 [controller_ onPersonalDataLoaded:personal_data_manager_->web_profiles()
190 creditCards:personal_data_manager_->credit_cards()]; 202 creditCards:personal_data_manager_->credit_cards()];
191 } 203 }
192 204
205 // The data has changed, notify the controller.
206 void PersonalDataManagerObserver::OnPersonalDataChanged() {
207 [controller_ onPersonalDataChanged:personal_data_manager_->web_profiles()
208 creditCards:personal_data_manager_->credit_cards()];
209 }
210
193 // Bridges preference changed notifications to the dialog controller. 211 // Bridges preference changed notifications to the dialog controller.
194 class PrefObserver : public NotificationObserver { 212 class PreferenceObserver : public NotificationObserver {
195 public: 213 public:
196 explicit PrefObserver(AutoFillDialogController* controller) 214 explicit PreferenceObserver(AutoFillDialogController* controller)
197 : controller_(controller) {} 215 : controller_(controller) {}
198 216
199 // Overridden from NotificationObserver: 217 // Overridden from NotificationObserver:
200 virtual void Observe(NotificationType type, 218 virtual void Observe(NotificationType type,
201 const NotificationSource& source, 219 const NotificationSource& source,
202 const NotificationDetails& details) { 220 const NotificationDetails& details) {
203 if (type == NotificationType::PREF_CHANGED) { 221 if (type == NotificationType::PREF_CHANGED) {
204 const std::string* pref = Details<std::string>(details).ptr(); 222 const std::string* pref = Details<std::string>(details).ptr();
205 if (pref) { 223 if (pref) {
206 [controller_ onPrefChanged:*pref]; 224 [controller_ preferenceDidChange:*pref];
207 } 225 }
208 } 226 }
209 } 227 }
210 228
211 private: 229 private:
212 AutoFillDialogController* controller_; 230 AutoFillDialogController* controller_;
213 231
214 DISALLOW_COPY_AND_ASSIGN(PrefObserver); 232 DISALLOW_COPY_AND_ASSIGN(PreferenceObserver);
215 }; 233 };
216 234
217 } // namespace AutoFillDialogControllerInternal 235 } // namespace AutoFillDialogControllerInternal
218 236
219 @implementation AutoFillDialogController 237 @implementation AutoFillDialogController
220 238
221 @synthesize autoFillEnabled = autoFillEnabled_;
222 @synthesize autoFillManaged = autoFillManaged_; 239 @synthesize autoFillManaged = autoFillManaged_;
223 @synthesize autoFillManagedAndDisabled = autoFillManagedAndDisabled_; 240 @synthesize autoFillManagedAndDisabled = autoFillManagedAndDisabled_;
224 @synthesize auxiliaryEnabled = auxiliaryEnabled_;
225 @synthesize itemIsSelected = itemIsSelected_; 241 @synthesize itemIsSelected = itemIsSelected_;
226 @synthesize multipleSelected = multipleSelected_; 242 @synthesize multipleSelected = multipleSelected_;
227 243
228 + (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer 244 + (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer
229 profile:(Profile*)profile 245 profile:(Profile*)profile {
230 importedProfile:(AutoFillProfile*) importedProfile
231 importedCreditCard:(CreditCard*) importedCreditCard {
232 AutoFillDialogController* controller = 246 AutoFillDialogController* controller =
233 [AutoFillDialogController controllerWithObserver:observer 247 [AutoFillDialogController controllerWithObserver:observer
234 profile:profile 248 profile:profile];
235 importedProfile:importedProfile 249 [controller runModelessDialog];
236 importedCreditCard:importedCreditCard];
237
238 // Only run modal dialog if it is not already being shown.
239 if (![controller isWindowLoaded]) {
240 [controller runModalDialog];
241 }
242 } 250 }
243 251
244 - (void)awakeFromNib { 252 - (void)awakeFromNib {
245 PersonalDataManager* personal_data_manager = 253 PersonalDataManager* personal_data_manager =
246 profile_->GetPersonalDataManager(); 254 profile_->GetPersonalDataManager();
247 DCHECK(personal_data_manager); 255 DCHECK(personal_data_manager);
248 256
249 if (personal_data_manager->IsDataLoaded()) { 257 if (personal_data_manager->IsDataLoaded()) {
250 // |personalDataManager| data is loaded, we can proceed with the contents. 258 // |personalDataManager| data is loaded, we can proceed with the contents.
251 [self onPersonalDataLoaded:personal_data_manager->web_profiles() 259 [self onPersonalDataLoaded:personal_data_manager->web_profiles()
252 creditCards:personal_data_manager->credit_cards()]; 260 creditCards:personal_data_manager->credit_cards()];
253 } else {
254 // |personalDataManager| data is NOT loaded, so we load it here, installing
255 // our observer.
256 personalDataManagerObserver_.reset(
257 new AutoFillDialogControllerInternal::PersonalDataManagerObserver(
258 self, personal_data_manager, profile_));
259 personal_data_manager->SetObserver(personalDataManagerObserver_.get());
260 } 261 }
261 262
263 // Register as listener to listen to subsequent data change notifications.
264 personalDataManagerObserver_.reset(
265 new AutoFillDialogControllerInternal::PersonalDataManagerObserver(
266 self, personal_data_manager, profile_));
267 personal_data_manager->SetObserver(personalDataManagerObserver_.get());
268
262 // Explicitly load the data in the table before window displays to avoid 269 // Explicitly load the data in the table before window displays to avoid
263 // nasty flicker as tables update. 270 // nasty flicker as tables update.
264 [tableView_ reloadData]; 271 [tableView_ reloadData];
265 272
266 // Set up edit when double-clicking on a table row. 273 // Set up edit when double-clicking on a table row.
267 [tableView_ setDoubleAction:@selector(editSelection:)]; 274 [tableView_ setDoubleAction:@selector(editSelection:)];
268 } 275 }
269 276
270 // NSWindow Delegate callback. When the window closes the controller can 277 // NSWindow Delegate callback. When the window closes the controller can
271 // be released. 278 // be released.
272 - (void)windowWillClose:(NSNotification *)notification { 279 - (void)windowWillClose:(NSNotification *)notification {
273 [tableView_ setDataSource:nil]; 280 [tableView_ setDataSource:nil];
274 [tableView_ setDelegate:nil]; 281 [tableView_ setDelegate:nil];
275 [self autorelease]; 282 [self autorelease];
276 }
277 283
278 // Called when the user clicks the save button. 284 // Remove ourself from the map.
279 - (IBAction)save:(id)sender { 285 ProfileControllerMap* map = Singleton<ProfileControllerMap>::get();
280 // If we have an |observer_| then communicate the changes back, unless 286 ProfileControllerMap::iterator it = map->find(profile_);
281 // AutoFill has been disabled through policy in the mean time. 287 if (it != map->end()) {
282 if (observer_ && !autoFillManagedAndDisabled_) { 288 map->erase(it);
283 prefAutoFillEnabled_.SetValueIfNotManaged(autoFillEnabled_);
284 profile_->GetPrefs()->SetBoolean(prefs::kAutoFillAuxiliaryProfilesEnabled,
285 auxiliaryEnabled_);
286 observer_->OnAutoFillDialogApply(&profiles_, &creditCards_);
287 } 289 }
288 [self closeDialog];
289 }
290
291 // Called when the user clicks the cancel button. All we need to do is stop
292 // the modal session.
293 - (IBAction)cancel:(id)sender {
294 [self closeDialog];
295 } 290 }
296 291
297 // Invokes the "Add" sheet for address information. If user saves then the new 292 // Invokes the "Add" sheet for address information. If user saves then the new
298 // information is added to |profiles_| in |addressAddDidEnd:| method. 293 // information is added to |profiles_| in |addressAddDidEnd:| method.
299 - (IBAction)addNewAddress:(id)sender { 294 - (IBAction)addNewAddress:(id)sender {
300 DCHECK(!addressSheetController.get()); 295 DCHECK(!addressSheetController.get());
301 296
302 // Create a new default address. 297 // Create a new default address.
303 string16 newName = l10n_util::GetStringUTF16(IDS_AUTOFILL_NEW_ADDRESS); 298 string16 newName = l10n_util::GetStringUTF16(IDS_AUTOFILL_NEW_ADDRESS);
304 AutoFillProfile newAddress(newName, 0); 299 AutoFillProfile newAddress(newName, 0);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 contextInfo:(void*)contextInfo { 342 contextInfo:(void*)contextInfo {
348 DCHECK(contextInfo == NULL); 343 DCHECK(contextInfo == NULL);
349 344
350 if (returnCode) { 345 if (returnCode) {
351 // Create a new address and save it to the |profiles_| list. 346 // Create a new address and save it to the |profiles_| list.
352 AutoFillProfile newAddress(string16(), 0); 347 AutoFillProfile newAddress(string16(), 0);
353 [addressSheetController copyModelToProfile:&newAddress]; 348 [addressSheetController copyModelToProfile:&newAddress];
354 if (!newAddress.IsEmpty()) { 349 if (!newAddress.IsEmpty()) {
355 profiles_.push_back(newAddress); 350 profiles_.push_back(newAddress);
356 351
357 // Refresh the view based on new data. 352 // Saving will save to the PDM and the table will refresh when PDM sends
358 UpdateProfileLabels(&profiles_); 353 // notification that the underlying model has changed.
359 [tableView_ reloadData]; 354 [self save];
360 355
361 // Update the selection to the newly added item. 356 // Update the selection to the newly added item.
362 NSInteger row = [self rowFromProfileIndex:profiles_.size() - 1]; 357 NSInteger row = [self rowFromProfileIndex:profiles_.size() - 1];
363 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row] 358 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
364 byExtendingSelection:NO]; 359 byExtendingSelection:NO];
365 } 360 }
366 } 361 }
367 [sheet orderOut:self]; 362 [sheet orderOut:self];
368 addressSheetController.reset(nil); 363 addressSheetController.reset(nil);
369 } 364 }
370 365
371 // Add credit card sheet was dismissed. Non-zero |returnCode| indicates a save. 366 // Add credit card sheet was dismissed. Non-zero |returnCode| indicates a save.
372 - (void)creditCardAddDidEnd:(NSWindow *)sheet 367 - (void)creditCardAddDidEnd:(NSWindow *)sheet
373 returnCode:(int)returnCode 368 returnCode:(int)returnCode
374 contextInfo:(void *)contextInfo { 369 contextInfo:(void *)contextInfo {
375 DCHECK(contextInfo == NULL); 370 DCHECK(contextInfo == NULL);
376 371
377 if (returnCode) { 372 if (returnCode) {
378 // Create a new credit card and save it to the |creditCards_| list. 373 // Create a new credit card and save it to the |creditCards_| list.
379 CreditCard newCreditCard(string16(), 0); 374 CreditCard newCreditCard(string16(), 0);
380 [creditCardSheetController copyModelToCreditCard:&newCreditCard]; 375 [creditCardSheetController copyModelToCreditCard:&newCreditCard];
381 if (!newCreditCard.IsEmpty()) { 376 if (!newCreditCard.IsEmpty()) {
382 creditCards_.push_back(newCreditCard); 377 creditCards_.push_back(newCreditCard);
383 378
384 // Refresh the view based on new data. 379 // Saving will save to the PDM and the table will refresh when PDM sends
385 [tableView_ reloadData]; 380 // notification that the underlying model has changed.
381 [self save];
386 382
387 // Update the selection to the newly added item. 383 // Update the selection to the newly added item.
388 NSInteger row = [self rowFromCreditCardIndex:creditCards_.size() - 1]; 384 NSInteger row = [self rowFromCreditCardIndex:creditCards_.size() - 1];
389 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row] 385 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
390 byExtendingSelection:NO]; 386 byExtendingSelection:NO];
391 } 387 }
392 } 388 }
393 [sheet orderOut:self]; 389 [sheet orderOut:self];
394 creditCardSheetController.reset(nil); 390 creditCardSheetController.reset(nil);
395 } 391 }
(...skipping 25 matching lines...) Expand all
421 if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) { 417 if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) {
422 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1] 418 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1]
423 byExtendingSelection:NO]; 419 byExtendingSelection:NO];
424 } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) { 420 } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) {
425 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow] 421 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
426 byExtendingSelection:NO]; 422 byExtendingSelection:NO];
427 } else { 423 } else {
428 [tableView_ deselectAll:self]; 424 [tableView_ deselectAll:self];
429 } 425 }
430 426
431 UpdateProfileLabels(&profiles_); 427 // Saving will save to the PDM and the table will refresh when PDM sends
432 [tableView_ reloadData]; 428 // notification that the underlying model has changed.
429 [self save];
433 } 430 }
434 431
435 // Edits the selected item, either address or credit card depending on the item 432 // Edits the selected item, either address or credit card depending on the item
436 // selected. 433 // selected.
437 - (IBAction)editSelection:(id)sender { 434 - (IBAction)editSelection:(id)sender {
438 NSInteger selectedRow = [tableView_ selectedRow]; 435 NSInteger selectedRow = [tableView_ selectedRow];
439 if ([self isProfileRow:selectedRow]) { 436 if ([self isProfileRow:selectedRow]) {
440 if (!addressSheetController.get()) { 437 if (!addressSheetController.get()) {
441 int i = [self profileIndexFromRow:selectedRow]; 438 int i = [self profileIndexFromRow:selectedRow];
442 439
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 AutoFillProfile* profile = static_cast<AutoFillProfile*>(contextInfo); 489 AutoFillProfile* profile = static_cast<AutoFillProfile*>(contextInfo);
493 [addressSheetController copyModelToProfile:profile]; 490 [addressSheetController copyModelToProfile:profile];
494 491
495 if (profile->IsEmpty()) 492 if (profile->IsEmpty())
496 [tableView_ deselectAll:self]; 493 [tableView_ deselectAll:self];
497 profiles_.erase( 494 profiles_.erase(
498 std::remove_if(profiles_.begin(), profiles_.end(), 495 std::remove_if(profiles_.begin(), profiles_.end(),
499 std::mem_fun_ref(&AutoFillProfile::IsEmpty)), 496 std::mem_fun_ref(&AutoFillProfile::IsEmpty)),
500 profiles_.end()); 497 profiles_.end());
501 498
502 UpdateProfileLabels(&profiles_); 499 // Saving will save to the PDM and the table will refresh when PDM sends
503 [tableView_ reloadData]; 500 // notification that the underlying model has changed.
501 [self save];
504 } 502 }
505 [sheet orderOut:self]; 503 [sheet orderOut:self];
506 addressSheetController.reset(nil); 504 addressSheetController.reset(nil);
507 } 505 }
508 506
509 // Edit credit card sheet was dismissed. Non-zero |returnCode| indicates a 507 // Edit credit card sheet was dismissed. Non-zero |returnCode| indicates a
510 // save. 508 // save.
511 - (void)creditCardEditDidEnd:(NSWindow *)sheet 509 - (void)creditCardEditDidEnd:(NSWindow *)sheet
512 returnCode:(int)returnCode 510 returnCode:(int)returnCode
513 contextInfo:(void *)contextInfo { 511 contextInfo:(void *)contextInfo {
514 DCHECK(contextInfo != NULL); 512 DCHECK(contextInfo != NULL);
515 if (returnCode) { 513 if (returnCode) {
516 CreditCard* creditCard = static_cast<CreditCard*>(contextInfo); 514 CreditCard* creditCard = static_cast<CreditCard*>(contextInfo);
517 [creditCardSheetController copyModelToCreditCard:creditCard]; 515 [creditCardSheetController copyModelToCreditCard:creditCard];
518 516
519 if (creditCard->IsEmpty()) 517 if (creditCard->IsEmpty())
520 [tableView_ deselectAll:self]; 518 [tableView_ deselectAll:self];
521 creditCards_.erase( 519 creditCards_.erase(
522 std::remove_if( 520 std::remove_if(
523 creditCards_.begin(), creditCards_.end(), 521 creditCards_.begin(), creditCards_.end(),
524 std::mem_fun_ref(&CreditCard::IsEmpty)), 522 std::mem_fun_ref(&CreditCard::IsEmpty)),
525 creditCards_.end()); 523 creditCards_.end());
526 [tableView_ reloadData]; 524
525 // Saving will save to the PDM and the table will refresh when PDM sends
526 // notification that the underlying model has changed.
527 [self save];
527 } 528 }
528 [sheet orderOut:self]; 529 [sheet orderOut:self];
529 creditCardSheetController.reset(nil); 530 creditCardSheetController.reset(nil);
530 } 531 }
531 532
532 // NSTableView Delegate method. 533 // NSTableView Delegate method.
533 - (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row { 534 - (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row {
534 if ([self isProfileGroupRow:row] || [self isCreditCardGroupRow:row]) 535 if ([self isProfileGroupRow:row] || [self isCreditCardGroupRow:row])
535 return YES; 536 return YES;
536 return NO; 537 return NO;
537 } 538 }
538 539
539 // NSTableView Delegate method. 540 // NSTableView Delegate method.
540 - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row { 541 - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row {
541 return ![self tableView:tableView isGroupRow:row]; 542 return [self isProfileRow:row] || [self isCreditCardRow:row];
542 } 543 }
543 544
544 // NSTableView Delegate method. 545 // NSTableView Delegate method.
545 - (id)tableView:(NSTableView *)tableView 546 - (id)tableView:(NSTableView *)tableView
546 objectValueForTableColumn:(NSTableColumn *)tableColumn 547 objectValueForTableColumn:(NSTableColumn *)tableColumn
547 row:(NSInteger)row { 548 row:(NSInteger)row {
548 if ([[tableColumn identifier] isEqualToString:@"Spacer"]) 549 if ([[tableColumn identifier] isEqualToString:@"Spacer"])
549 return @""; 550 return @"";
550 551
551 // Check that we're initialized before supplying data. 552 // Check that we're initialized before supplying data.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 // No address information in this profile; it's useless as a billing 637 // No address information in this profile; it's useless as a billing
637 // address. 638 // address.
638 continue; 639 continue;
639 } 640 }
640 [array addObject:SysUTF16ToNSString(i->Label())]; 641 [array addObject:SysUTF16ToNSString(i->Label())];
641 } 642 }
642 643
643 return array; 644 return array;
644 } 645 }
645 646
647 // Accessor for |autoFillEnabled| preference state. Note: a checkbox in Nib
648 // is bound to this via KVO.
649 - (BOOL)autoFillEnabled {
650 return autoFillEnabled_.GetValue();
651 }
652
653 // Setter for |autoFillEnabled| preference state.
654 - (void)setAutoFillEnabled:(BOOL)value {
655 autoFillEnabled_.SetValueIfNotManaged(value ? true : false);
656 }
657
658 // Accessor for |auxiliaryEnabled| preference state. Note: a checkbox in Nib
659 // is bound to this via KVO.
660 - (BOOL)auxiliaryEnabled {
661 return auxiliaryEnabled_.GetValue();
662 }
663
664 // Setter for |auxiliaryEnabled| preference state.
665 - (void)setAuxiliaryEnabled:(BOOL)value {
666 if ([self autoFillEnabled])
667 auxiliaryEnabled_.SetValueIfNotManaged(value ? true : false);
668 }
669
646 @end 670 @end
647 671
648 @implementation AutoFillDialogController (ExposedForUnitTests) 672 @implementation AutoFillDialogController (ExposedForUnitTests)
649 673
650 + (AutoFillDialogController*)controllerWithObserver: 674 + (AutoFillDialogController*)
651 (AutoFillDialogObserver*)observer 675 controllerWithObserver:(AutoFillDialogObserver*)observer
652 profile:(Profile*)profile 676 profile:(Profile*)profile {
653 importedProfile:(AutoFillProfile*)importedProfile 677 profile = profile->GetOriginalProfile();
654 importedCreditCard:(CreditCard*)importedCreditCard { 678
679 ProfileControllerMap* map = Singleton<ProfileControllerMap>::get();
680 DCHECK(map != NULL);
681 ProfileControllerMap::iterator it = map->find(profile);
682 if (it == map->end()) {
683 // We should have exactly 1 or 0 entry in the map, no more. That is,
684 // only one profile can have the AutoFill dialog up at a time.
685 DCHECK_EQ(map->size(), 0U);
655 686
656 // Deallocation is done upon window close. See |windowWillClose:|. 687 // Deallocation is done upon window close. See |windowWillClose:|.
657 AutoFillDialogController* controller = 688 AutoFillDialogController* controller =
658 [[self alloc] initWithObserver:observer 689 [[self alloc] initWithObserver:observer profile:profile];
659 profile:profile 690 it = map->insert(std::make_pair(profile, controller)).first;
660 importedProfile:importedProfile 691 }
661 importedCreditCard:importedCreditCard]; 692
662 return controller; 693 return it->second;
663 } 694 }
664 695
665 696
666 // This is the designated initializer for this class. 697 // This is the designated initializer for this class.
667 // |profiles| are non-retained immutable list of AutoFill profiles. 698 // |profiles| are non-retained immutable list of AutoFill profiles.
668 // |creditCards| are non-retained immutable list of credit card info. 699 // |creditCards| are non-retained immutable list of credit card info.
669 - (id)initWithObserver:(AutoFillDialogObserver*)observer 700 - (id)initWithObserver:(AutoFillDialogObserver*)observer
670 profile:(Profile*)profile 701 profile:(Profile*)profile {
671 importedProfile:(AutoFillProfile*)importedProfile
672 importedCreditCard:(CreditCard*)importedCreditCard {
673 DCHECK(profile); 702 DCHECK(profile);
674 // Use initWithWindowNibPath: instead of initWithWindowNibName: so we 703 // Use initWithWindowNibPath: instead of initWithWindowNibName: so we
675 // can override it in a unit test. 704 // can override it in a unit test.
676 NSString* nibpath = [mac_util::MainAppBundle() 705 NSString* nibpath = [mac_util::MainAppBundle()
677 pathForResource:@"AutoFillDialog" 706 pathForResource:@"AutoFillDialog"
678 ofType:@"nib"]; 707 ofType:@"nib"];
679 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 708 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
680 // Initialize member variables based on input. 709 // Initialize member variables based on input.
681 observer_ = observer; 710 observer_ = observer;
682 profile_ = profile; 711 profile_ = profile;
683 importedProfile_ = importedProfile;
684 importedCreditCard_ = importedCreditCard;
685 712
686 // Initialize the preference observer and watch kAutoFillEnabled. 713 // Initialize the preference observer and watch kAutoFillEnabled.
687 prefObserver_.reset( 714 preferenceObserver_.reset(
688 new AutoFillDialogControllerInternal::PrefObserver(self)); 715 new AutoFillDialogControllerInternal::PreferenceObserver(self));
689 prefAutoFillEnabled_.Init(prefs::kAutoFillEnabled, profile_->GetPrefs(), 716 autoFillEnabled_.Init(prefs::kAutoFillEnabled, profile_->GetPrefs(),
690 prefObserver_.get()); 717 preferenceObserver_.get());
691 718
692 // Call onPrefChanged in order to initialize UI state of the checkbox and 719 // Call |preferenceDidChange| in order to initialize UI state of the
693 // save button. 720 // checkbox.
694 [self onPrefChanged:prefs::kAutoFillEnabled]; 721 [self preferenceDidChange:prefs::kAutoFillEnabled];
695 722
696 // Use property here to trigger KVO binding. 723 // Initialize the preference observer and watch
697 [self setAuxiliaryEnabled:profile_->GetPrefs()->GetBoolean( 724 // kAutoFillAuxiliaryProfilesEnabled.
698 prefs::kAutoFillAuxiliaryProfilesEnabled)]; 725 auxiliaryEnabled_.Init(prefs::kAutoFillAuxiliaryProfilesEnabled,
726 profile_->GetPrefs(),
727 preferenceObserver_.get());
728
729 // Call |preferenceDidChange| in order to initialize UI state of the
730 // checkbox.
731 [self preferenceDidChange:prefs::kAutoFillAuxiliaryProfilesEnabled];
699 732
700 // Do not use [NSMutableArray array] here; we need predictable destruction 733 // Do not use [NSMutableArray array] here; we need predictable destruction
701 // which will be prevented by having a reference held by an autorelease 734 // which will be prevented by having a reference held by an autorelease
702 // pool. 735 // pool.
703 } 736 }
704 return self; 737 return self;
705 } 738 }
706 739
740 // Run modeless.
741 - (void)runModelessDialog {
742 // Use stored window geometry if it exists.
743 if (g_browser_process && g_browser_process->local_state()) {
744 sizeSaver_.reset([[WindowSizeAutosaver alloc]
745 initWithWindow:[self window]
746 prefService:g_browser_process->local_state()
747 path:prefs::kAutoFillDialogPlacement]);
748 }
749
750 [self showWindow:nil];
751 }
752
707 // Close the dialog. 753 // Close the dialog.
708 - (void)closeDialog { 754 - (void)closeDialog {
709 [[self window] close]; 755 [[self window] performClose:self];
710 [NSApp stopModal];
711 } 756 }
712 757
713 - (AutoFillAddressSheetController*)addressSheetController { 758 - (AutoFillAddressSheetController*)addressSheetController {
714 return addressSheetController.get(); 759 return addressSheetController.get();
715 } 760 }
716 761
717 - (AutoFillCreditCardSheetController*)creditCardSheetController { 762 - (AutoFillCreditCardSheetController*)creditCardSheetController {
718 return creditCardSheetController.get(); 763 return creditCardSheetController.get();
719 } 764 }
720 765
(...skipping 18 matching lines...) Expand all
739 - (void)addSelectedCreditCardAtIndex:(size_t)i { 784 - (void)addSelectedCreditCardAtIndex:(size_t)i {
740 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex: 785 [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
741 [self rowFromCreditCardIndex:i]] 786 [self rowFromCreditCardIndex:i]]
742 byExtendingSelection:YES]; 787 byExtendingSelection:YES];
743 } 788 }
744 789
745 - (BOOL)editButtonEnabled { 790 - (BOOL)editButtonEnabled {
746 return [editButton_ isEnabled]; 791 return [editButton_ isEnabled];
747 } 792 }
748 793
794 - (std::vector<AutoFillProfile>&)profiles {
795 return profiles_;
796 }
797
798 - (std::vector<CreditCard>&)creditCards {
799 return creditCards_;
800 }
801
749 @end 802 @end
750 803
751 @implementation AutoFillDialogController (PrivateMethods) 804 @implementation AutoFillDialogController (PrivateMethods)
752 805
753 // Run application modal. 806 // Called when the user modifies the profiles or credit card information.
754 - (void)runModalDialog { 807 - (void)save {
755 // Use stored window geometry if it exists. 808 // If we have an |observer_| then communicate the changes back, unless
756 if (g_browser_process && g_browser_process->local_state()) { 809 // AutoFill has been disabled through policy in the mean time.
757 sizeSaver_.reset([[WindowSizeAutosaver alloc] 810 if (observer_ && !autoFillManagedAndDisabled_) {
758 initWithWindow:[self window] 811 // Make a working copy of profiles. |OnAutoFillDialogApply| can mutate
759 prefService:g_browser_process->local_state() 812 // |profiles_|.
760 path:prefs::kAutoFillDialogPlacement]); 813 std::vector<AutoFillProfile> profiles = profiles_;
814
815 // Make a working copy of credit cards. |OnAutoFillDialogApply| can mutate
816 // |creditCards_|.
817 std::vector<CreditCard> creditCards = creditCards_;
818
819 observer_->OnAutoFillDialogApply(&profiles, &creditCards);
761 } 820 }
762
763 [NSApp runModalForWindow:[self window]];
764 } 821 }
765 822
766 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles 823 - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
767 creditCards:(const std::vector<CreditCard*>&)creditCards { 824 creditCards:(const std::vector<CreditCard*>&)creditCards {
768 if (importedProfile_) { 825 [self onPersonalDataChanged:profiles creditCards:creditCards];
769 profiles_.push_back(*importedProfile_); 826 }
770 }
771 827
772 if (importedCreditCard_) { 828 - (void)onPersonalDataChanged:(const std::vector<AutoFillProfile*>&)profiles
773 creditCards_.push_back(*importedCreditCard_); 829 creditCards:(const std::vector<CreditCard*>&)creditCards {
774 } 830 // Make local copy of |profiles|.
831 profiles_.clear();
832 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
833 iter != profiles.end(); ++iter)
834 profiles_.push_back(**iter);
775 835
776 // If we're not using imported data then use the data fetch from the web db. 836 // Make local copy of |creditCards|.
777 if (!importedProfile_ && !importedCreditCard_) { 837 creditCards_.clear();
778 // Make local copy of |profiles|. 838 for (std::vector<CreditCard*>::const_iterator iter = creditCards.begin();
779 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin(); 839 iter != creditCards.end(); ++iter)
780 iter != profiles.end(); ++iter) 840 creditCards_.push_back(**iter);
781 profiles_.push_back(**iter);
782
783 // Make local copy of |creditCards|.
784 for (std::vector<CreditCard*>::const_iterator iter = creditCards.begin();
785 iter != creditCards.end(); ++iter)
786 creditCards_.push_back(**iter);
787 }
788 841
789 UpdateProfileLabels(&profiles_); 842 UpdateProfileLabels(&profiles_);
843 [tableView_ reloadData];
790 } 844 }
791 845
792 - (void)onPrefChanged:(const std::string&)prefName { 846 - (void)preferenceDidChange:(const std::string&)preferenceName {
793 if (prefName == prefs::kAutoFillEnabled) { 847 if (preferenceName == prefs::kAutoFillEnabled) {
794 [self setAutoFillEnabled:prefAutoFillEnabled_.GetValue()]; 848 [self setAutoFillEnabled:autoFillEnabled_.GetValue()];
795 [self setAutoFillManaged:prefAutoFillEnabled_.IsManaged()]; 849 [self setAutoFillManaged:autoFillEnabled_.IsManaged()];
796 [self setAutoFillManagedAndDisabled: 850 [self setAutoFillManagedAndDisabled:
797 prefAutoFillEnabled_.IsManaged() && !prefAutoFillEnabled_.GetValue()]; 851 autoFillEnabled_.IsManaged() && !autoFillEnabled_.GetValue()];
852 } else if (preferenceName == prefs::kAutoFillAuxiliaryProfilesEnabled) {
853 [self setAuxiliaryEnabled:auxiliaryEnabled_.GetValue()];
798 } else { 854 } else {
799 NOTREACHED(); 855 NOTREACHED();
800 } 856 }
801 } 857 }
802 858
803 - (BOOL)isProfileRow:(NSInteger)row { 859 - (BOOL)isProfileRow:(NSInteger)row {
804 if (row > 0 && static_cast<size_t>(row) <= profiles_.size()) 860 if (row > 0 && static_cast<size_t>(row) <= profiles_.size())
805 return YES; 861 return YES;
806 return NO; 862 return NO;
807 } 863 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 if (!image) { 946 if (!image) {
891 image = rb.GetNSImageNamed(IDR_INPUT_GOOD); 947 image = rb.GetNSImageNamed(IDR_INPUT_GOOD);
892 DCHECK(image); 948 DCHECK(image);
893 return image; 949 return image;
894 } 950 }
895 951
896 return nil; 952 return nil;
897 } 953 }
898 954
899 @end 955 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698