diff options
Diffstat (limited to 'chrome/browser')
3 files changed, 126 insertions, 41 deletions
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.h b/chrome/browser/autofill/autofill_dialog_controller_mac.h index 3318443..7a7faa7 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.h +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.h @@ -34,6 +34,9 @@ class Profile; // cards with section headers for both. IBOutlet AutoFillTableView* tableView_; + // Outlet to "Edit..." button. Here for unit testing purposes. + IBOutlet NSButton* editButton_; + // This observer is passed in by the caller of the dialog. When the dialog // is dismissed |observer_| is called with new values for the addresses and // credit cards. @@ -68,6 +71,10 @@ class Profile; // "Remove" buttons. BOOL itemIsSelected_; + // State for |multipleSelected| property used in bindings for "Edit..." + // button. + BOOL multipleSelected_; + // Utility object to save and restore dialog position. scoped_nsobject<WindowSizeAutosaver> sizeSaver_; @@ -97,6 +104,10 @@ class Profile; // edit and delete buttons are bound to this property. @property (nonatomic) BOOL itemIsSelected; +// Property representing multiple selection state in |tableView_|. Enabled +// state of edit button is bound to this property. +@property (nonatomic) BOOL multipleSelected; + // Main interface for displaying an application modal AutoFill dialog on screen. // This class method creates a new |AutoFillDialogController| and runs it as a // modal dialog. The controller autoreleases itself when the dialog is closed. @@ -168,6 +179,9 @@ class Profile; - (AutoFillCreditCardSheetController*)creditCardSheetController; - (void)selectAddressAtIndex:(size_t)i; - (void)selectCreditCardAtIndex:(size_t)i; +- (void)addSelectedAddressAtIndex:(size_t)i; +- (void)addSelectedCreditCardAtIndex:(size_t)i; +- (BOOL)editButtonEnabled; @end #endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_MAC_ diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm index 377e1cd..d0e16ae 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm @@ -191,6 +191,7 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() { @synthesize autoFillEnabled = autoFillEnabled_; @synthesize auxiliaryEnabled = auxiliaryEnabled_; @synthesize itemIsSelected = itemIsSelected_; +@synthesize multipleSelected = multipleSelected_; + (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer profile:(Profile*)profile @@ -356,43 +357,45 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() { creditCardSheetController.reset(nil); } -// Deletes selected item, either address or credit card depending on the item -// selected. +// Deletes selected items; either addresses, credit cards, or a mixture of the +// two depending on the items selected. - (IBAction)deleteSelection:(id)sender { + NSIndexSet* selectedRows = [tableView_ selectedRowIndexes]; NSInteger selectedRow = [tableView_ selectedRow]; - if ([self isProfileRow:selectedRow]) { - profiles_.erase(profiles_.begin() + [self profileIndexFromRow:selectedRow]); - - // Select the previous row if possible, else current row, else deselect all. - if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1] - byExtendingSelection:NO]; - } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow] - byExtendingSelection:NO]; - } else { - [tableView_ selectRowIndexes:[NSIndexSet indexSet] - byExtendingSelection:NO]; + NSInteger rowCount = [tableView_ numberOfRows]; + + // Loop through from last to first deleting selected items as we go. + for (NSInteger i = rowCount-1; i>=0; --i) { + if (![selectedRows containsIndex:i]) + continue; + + // We keep track of the "top most" selection in the list so we know where + // to to set new selection below. + if (i < selectedRow) + selectedRow = i; + + if ([self isProfileRow:i]) { + profiles_.erase( + profiles_.begin() + [self profileIndexFromRow:i]); + } else if ([self isCreditCardRow:i]) { + creditCards_.erase( + creditCards_.begin() + [self creditCardIndexFromRow:i]); } - UpdateProfileLabels(&profiles_); - [tableView_ reloadData]; - } else if ([self isCreditCardRow:selectedRow]) { - creditCards_.erase( - creditCards_.begin() + [self creditCardIndexFromRow:selectedRow]); - - // Select the previous row if possible, else current row, else deselect all. - if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1] - byExtendingSelection:NO]; - } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow] - byExtendingSelection:NO]; - } else { - [tableView_ selectRowIndexes:[NSIndexSet indexSet] - byExtendingSelection:NO]; - } - [tableView_ reloadData]; } + + // Select the previous row if possible, else current row, else deselect all. + if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) { + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1] + byExtendingSelection:NO]; + } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) { + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow] + byExtendingSelection:NO]; + } else { + [tableView_ selectRowIndexes:[NSIndexSet indexSet] byExtendingSelection:NO]; + } + + UpdateProfileLabels(&profiles_); + [tableView_ reloadData]; } // Edits the selected item, either address or credit card depending on the item @@ -542,14 +545,18 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() { return @""; } -// We implement this delegate method to update our |itemIsSelected| property. +// We implement this delegate method to update our |itemIsSelected| and +// |multipleSelected| properties. // The "Edit..." and "Remove" buttons' enabled state depends on having a -// valid selection in the table. +// valid selection in the table. The "Edit..." button depends on having +// exactly one item selected. - (void)tableViewSelectionDidChange:(NSNotification *)aNotification { if ([tableView_ selectedRow] >= 0) [self setItemIsSelected:YES]; else [self setItemIsSelected:NO]; + + [self setMultipleSelected:([[tableView_ selectedRowIndexes] count] > 1UL)]; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { @@ -654,6 +661,22 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() { byExtendingSelection:NO]; } +- (void)addSelectedAddressAtIndex:(size_t)i { + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex: + [self rowFromProfileIndex:i]] + byExtendingSelection:YES]; +} + +- (void)addSelectedCreditCardAtIndex:(size_t)i { + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex: + [self rowFromCreditCardIndex:i]] + byExtendingSelection:YES]; +} + +- (BOOL)editButtonEnabled { + return [editButton_ isEnabled]; +} + @end @implementation AutoFillDialogController (PrivateMethods) diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm index d3e2550..80678077 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm @@ -389,7 +389,7 @@ TEST_F(AutoFillDialogControllerTest, AddNewProfile) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 2. + // Sizes should be different. New size should be 2. ASSERT_NE(observer_.profiles_.size(), profiles().size()); ASSERT_EQ(observer_.profiles_.size(), 2UL); @@ -413,7 +413,7 @@ TEST_F(AutoFillDialogControllerTest, AddNewCreditCard) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 2. + // Sizes should be different. New size should be 2. ASSERT_NE(observer_.credit_cards_.size(), credit_cards().size()); ASSERT_EQ(observer_.credit_cards_.size(), 2UL); @@ -434,7 +434,7 @@ TEST_F(AutoFillDialogControllerTest, DeleteProfile) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 0. + // Sizes should be different. New size should be 0. ASSERT_NE(observer_.profiles_.size(), profiles().size()); ASSERT_EQ(observer_.profiles_.size(), 0UL); } @@ -451,7 +451,7 @@ TEST_F(AutoFillDialogControllerTest, DeleteCreditCard) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 0. + // Sizes should be different. New size should be 0. ASSERT_NE(observer_.credit_cards_.size(), credit_cards().size()); ASSERT_EQ(observer_.credit_cards_.size(), 0UL); } @@ -471,7 +471,7 @@ TEST_F(AutoFillDialogControllerTest, TwoProfilesDeleteOne) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 0. + // Sizes should be different. New size should be 1. ASSERT_NE(observer_.profiles_.size(), profiles().size()); ASSERT_EQ(observer_.profiles_.size(), 1UL); @@ -499,7 +499,7 @@ TEST_F(AutoFillDialogControllerTest, TwoCreditCardsDeleteOne) { // Should hit our observer. ASSERT_TRUE(observer_.hit_); - // Sizes should match be different. New size should be 0. + // Sizes should be different. New size should be 1. ASSERT_NE(observer_.credit_cards_.size(), credit_cards().size()); ASSERT_EQ(observer_.credit_cards_.size(), 1UL); @@ -508,6 +508,54 @@ TEST_F(AutoFillDialogControllerTest, TwoCreditCardsDeleteOne) { ASSERT_EQ(observer_.credit_cards_[0], credit_card); } +TEST_F(AutoFillDialogControllerTest, DeleteMultiple) { + AutoFillProfile profile(ASCIIToUTF16("One"), 1); + profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Joe")); + profiles().push_back(&profile); + AutoFillProfile profile2(ASCIIToUTF16("Two"), 2); + profile2.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Bob")); + profiles().push_back(&profile2); + + CreditCard credit_card(ASCIIToUTF16("Visa"), 1); + credit_card.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Joe")); + credit_cards().push_back(&credit_card); + CreditCard credit_card2(ASCIIToUTF16("Mastercard"), 2); + credit_card2.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Bob")); + credit_cards().push_back(&credit_card2); + + LoadDialog(); + [controller_ selectAddressAtIndex:1]; + [controller_ addSelectedCreditCardAtIndex:0]; + ASSERT_FALSE([controller_ editButtonEnabled]); + [controller_ deleteSelection:nil]; + [controller_ selectAddressAtIndex:0]; + ASSERT_TRUE([controller_ editButtonEnabled]); + [controller_ save:nil]; + + // Should hit our observer. + ASSERT_TRUE(observer_.hit_); + + // Sizes should be different. New size should be 1. + ASSERT_NE(observer_.profiles_.size(), profiles().size()); + ASSERT_EQ(observer_.profiles_.size(), 1UL); + + // Sizes should be different. New size should be 1. + ASSERT_NE(observer_.credit_cards_.size(), credit_cards().size()); + ASSERT_EQ(observer_.credit_cards_.size(), 1UL); + + // First address should match. + profiles()[0]->set_unique_id(observer_.profiles_[0].unique_id()); + + // Do not compare labels. Label is a derived field. + observer_.profiles_[0].set_label(string16()); + profile.set_label(string16()); + ASSERT_EQ(observer_.profiles_[0], profile); + + // Second credit card should match. + credit_cards()[0]->set_unique_id(observer_.credit_cards_[0].unique_id()); + ASSERT_EQ(observer_.credit_cards_[0], credit_card2); +} + // Auxilliary profiles are enabled by default. TEST_F(AutoFillDialogControllerTest, AuxiliaryProfilesTrue) { LoadDialog(); |