OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |