diff options
author | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 04:24:08 +0000 |
---|---|---|
committer | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 04:24:08 +0000 |
commit | 8ebfa3b67a5d756c9fba7f4f4925dd0c30d16e58 (patch) | |
tree | 91f07b26d01569dbc07f00ced3ca45ed3e9e959c /chrome/browser/autofill | |
parent | 8b6b3cf3e623d8f48069aa30a23bca58852d0b36 (diff) | |
download | chromium_src-8ebfa3b67a5d756c9fba7f4f4925dd0c30d16e58.zip chromium_src-8ebfa3b67a5d756c9fba7f4f4925dd0c30d16e58.tar.gz chromium_src-8ebfa3b67a5d756c9fba7f4f4925dd0c30d16e58.tar.bz2 |
Autofill dialog for the Mac. This is UI only at this point. The UI is not hooked up to the back end yet. The UI demonstrates manipulation of one address and one credit card record. Eventually buttons will be added to add and remove additional records. The additions in this CL are:
- Preferences dialog has a new "Change autofill settings" button that triggers an autofill settings dialog.
- The autofill settings dialog now exists and allows the user to manipulate form autofill data. Specifically address information and credit card information.
- Each address or credit card record is presented in a disclosure view to allow for summary or detailed views of each record.
- The autofill dialog is layed out dynamically in a vertical list (ordered by y) using the VerticalLayoutView.
- Sections are delimited visually with the SectionSeparatorView. There are currently two sections, one for addresses and one for credit cards.
- Unit tests are present that exercise the invocation of the dialog and check basic functionality. Checks are performed to see that data is flowing from core profile and credit card data structures into Cocoa model data structures used for bindings internally by the UI.
- There are three .xib files (AutoFillDialog.xib, AutoFillAddressFormView.xib, and AutoFillCreditCardFormView.xib) that partition the dialog UI into distinct views, controllers, and model objects.
- Cocoa databinding is utilized to syncronize dependent parts of the UI.
- All strings are stored in internationalized form in .grd files and .xib files (with one small TODO execption, see below).
The things remaining to do are:
- Hook the UI up to the backend model, specifically the PersonalDataManager data.
- Add support for arbitrary number of address and credit card records. I.e. Add and Delete buttons.
- Scroll-to-Point support for autoscrolling when tabbing between fields.
- Billing and shipping address popups in the credit card section.
- Any validation of input (need to circle back with UI folks on this).
- Input validation unit tests.
- String concatenation of the summary label needs to be internationalized.
BUG=33029
TEST=none
Review URL: http://codereview.chromium.org/558066
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill')
16 files changed, 1038 insertions, 5 deletions
diff --git a/chrome/browser/autofill/autofill_address_model_mac.h b/chrome/browser/autofill/autofill_address_model_mac.h new file mode 100644 index 0000000..92d02ae --- /dev/null +++ b/chrome/browser/autofill/autofill_address_model_mac.h @@ -0,0 +1,77 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_MODEL_MAC_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_MODEL_MAC_ + +#import <Cocoa/Cocoa.h> + +class AutoFillProfile; + +// A "model" class used with bindings mechanism and the +// |AutoFillAddressViewController| to achieve the form-like view +// of autofill data in the Chrome options UI. +// Note that |summary| is a derived property. +// Model objects are initialized from a given profile using the designated +// initializer |initWithProfile:|. +// Users of this class must be prepared to handle nil string return values. +// The KVO/bindings mechanisms expect this and deal with nil string values +// appropriately. +@interface AutoFillAddressModel : NSObject { + @private + // These are not scoped_nsobjects because we use them via KVO/bindings. + NSString* label_; + NSString* firstName_; + NSString* middleName_; + NSString* lastName_; + NSString* email_; + NSString* companyName_; + NSString* addressLine1_; + NSString* addressLine2_; + NSString* city_; + NSString* state_; + NSString* zip_; + NSString* country_; + NSString* phoneCountryCode_; + NSString* phoneAreaCode_; + NSString* phoneNumber_; + NSString* faxCountryCode_; + NSString* faxAreaCode_; + NSString* faxNumber_; +} + +// |summary| is a derived property based on |firstName|, |lastName| and +// |addressLine1|. KVO observers receive change notifications for |summary| +// when any of these properties change. +@property (readonly) NSString* summary; +@property (nonatomic, copy) NSString* label; +@property (nonatomic, copy) NSString* firstName; +@property (nonatomic, copy) NSString* middleName; +@property (nonatomic, copy) NSString* lastName; +@property (nonatomic, copy) NSString* email; +@property (nonatomic, copy) NSString* companyName; +@property (nonatomic, copy) NSString* addressLine1; +@property (nonatomic, copy) NSString* addressLine2; +@property (nonatomic, copy) NSString* city; +@property (nonatomic, copy) NSString* state; +@property (nonatomic, copy) NSString* zip; +@property (nonatomic, copy) NSString* country; +@property (nonatomic, copy) NSString* phoneCountryCode; +@property (nonatomic, copy) NSString* phoneAreaCode; +@property (nonatomic, copy) NSString* phoneNumber; +@property (nonatomic, copy) NSString* faxCountryCode; +@property (nonatomic, copy) NSString* faxAreaCode; +@property (nonatomic, copy) NSString* faxNumber; + +// The designated initializer. Initializes the property strings to values +// retrieved from the |profile|. +- (id)initWithProfile:(const AutoFillProfile&)profile; + +// This method copies internal NSString property values into the +// |profile| object's fields as appropriate. |profile| should never be NULL. +- (void)copyModelToProfile:(AutoFillProfile*)profile; + +@end + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_MODEL_MAC_ diff --git a/chrome/browser/autofill/autofill_address_model_mac.mm b/chrome/browser/autofill/autofill_address_model_mac.mm new file mode 100644 index 0000000..265b055 --- /dev/null +++ b/chrome/browser/autofill/autofill_address_model_mac.mm @@ -0,0 +1,181 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_address_model_mac.h" +#include "app/l10n_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/autofill/autofill_profile.h" +#include "grit/generated_resources.h" + +@implementation AutoFillAddressModel + +@dynamic summary; +@synthesize label = label_; +@synthesize firstName = firstName_; +@synthesize middleName = middleName_; +@synthesize lastName = lastName_; +@synthesize email = email_; +@synthesize companyName = companyName_; +@synthesize addressLine1 = addressLine1_; +@synthesize addressLine2 = addressLine2_; +@synthesize city = city_; +@synthesize state = state_; +@synthesize zip = zip_; +@synthesize country = country_; +@synthesize phoneCountryCode = phoneCountryCode_; +@synthesize phoneAreaCode = phoneAreaCode_; +@synthesize phoneNumber = phoneNumber_; +@synthesize faxCountryCode = faxCountryCode_; +@synthesize faxAreaCode = faxAreaCode_; +@synthesize faxNumber = faxNumber_; + +// Sets up the KVO dependency between "summary" and dependent fields. ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { + NSSet* keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; + + if ([key isEqualToString:@"summary"]) { + NSSet* affectingKeys = + [NSSet setWithObjects:@"firstName", @"lastName", @"addressLine1", nil]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKeys]; + } + return keyPaths; +} + +- (id)initWithProfile:(const AutoFillProfile&)profile { + if ((self = [super init])) { + [self setLabel:SysUTF16ToNSString(profile.Label())]; + [self setFirstName:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(NAME_FIRST)))]; + [self setMiddleName:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(NAME_MIDDLE)))]; + [self setLastName:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(NAME_LAST)))]; + [self setEmail:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(EMAIL_ADDRESS)))]; + [self setCompanyName:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(COMPANY_NAME)))]; + [self setAddressLine1:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)))]; + [self setAddressLine2:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)))]; + [self setCity:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_CITY)))]; + [self setState:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_STATE)))]; + [self setZip:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)))]; + [self setCountry:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY)))]; + [self setPhoneCountryCode:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_HOME_COUNTRY_CODE)))]; + [self setPhoneAreaCode:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_HOME_CITY_CODE)))]; + [self setPhoneNumber:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_HOME_NUMBER)))]; + [self setFaxCountryCode:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_FAX_COUNTRY_CODE)))]; + [self setFaxAreaCode:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_FAX_CITY_CODE)))]; + [self setFaxNumber:SysUTF16ToNSString( + profile.GetFieldText(AutoFillType(PHONE_FAX_NUMBER)))]; + } + return self; +} + +- (void)dealloc { + [label_ release]; + [firstName_ release]; + [middleName_ release]; + [lastName_ release]; + [email_ release]; + [companyName_ release]; + [addressLine1_ release]; + [addressLine2_ release]; + [city_ release]; + [state_ release]; + [zip_ release]; + [country_ release]; + [phoneCountryCode_ release]; + [phoneAreaCode_ release]; + [phoneNumber_ release]; + [faxCountryCode_ release]; + [faxAreaCode_ release]; + [faxNumber_ release]; + [super dealloc]; +} + +- (NSString*)summary { + // Bindings may set these to nil. We normalize here to @"". + if (firstName_ == nil) + firstName_ = @""; + if (lastName_ == nil) + lastName_ = @""; + if (addressLine1_ == nil) + addressLine1_ = @""; + + BOOL haveFirstName = [firstName_ length] > 0; + BOOL haveLastName = [lastName_ length] > 0; + BOOL haveAddress = [addressLine1_ length] > 0; + + NSString* nameSeparator = (haveFirstName && haveLastName) ? + l10n_util::GetNSString(IDS_AUTOFILL_DIALOG_ADDRESS_NAME_SEPARATOR) : + @""; + NSString* nameFormat = + l10n_util::GetNSStringF(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_NAME_FORMAT, + base::SysNSStringToUTF16(firstName_), + base::SysNSStringToUTF16(nameSeparator), + base::SysNSStringToUTF16(lastName_)); + NSString* summarySeparator = (haveFirstName || haveLastName) && haveAddress ? + l10n_util::GetNSString(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR) : + @""; + NSString* summaryFormat = + l10n_util::GetNSStringF(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT, + base::SysNSStringToUTF16(nameFormat), + base::SysNSStringToUTF16(summarySeparator), + base::SysNSStringToUTF16(addressLine1_)); + + return summaryFormat; +} + +- (void)copyModelToProfile:(AutoFillProfile*)profile { + DCHECK(profile); + profile->set_label(base::SysNSStringToUTF16([self label])); + + profile->SetInfo(AutoFillType(NAME_FIRST), + base::SysNSStringToUTF16([self firstName])); + profile->SetInfo(AutoFillType(NAME_MIDDLE), + base::SysNSStringToUTF16([self middleName])); + profile->SetInfo(AutoFillType(NAME_LAST), + base::SysNSStringToUTF16([self lastName])); + profile->SetInfo(AutoFillType(EMAIL_ADDRESS), + base::SysNSStringToUTF16([self email])); + profile->SetInfo(AutoFillType(COMPANY_NAME), + base::SysNSStringToUTF16([self companyName])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE1), + base::SysNSStringToUTF16([self addressLine1])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE2), + base::SysNSStringToUTF16([self addressLine2])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_CITY), + base::SysNSStringToUTF16([self city])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_STATE), + base::SysNSStringToUTF16([self state])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP), + base::SysNSStringToUTF16([self zip])); + profile->SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), + base::SysNSStringToUTF16([self country])); + profile->SetInfo(AutoFillType(PHONE_HOME_COUNTRY_CODE), + base::SysNSStringToUTF16([self phoneCountryCode])); + profile->SetInfo(AutoFillType(PHONE_HOME_CITY_CODE), + base::SysNSStringToUTF16([self phoneAreaCode])); + profile->SetInfo(AutoFillType(PHONE_HOME_NUMBER), + base::SysNSStringToUTF16([self phoneNumber])); + profile->SetInfo(AutoFillType(PHONE_FAX_COUNTRY_CODE), + base::SysNSStringToUTF16([self faxCountryCode])); + profile->SetInfo(AutoFillType(PHONE_FAX_CITY_CODE), + base::SysNSStringToUTF16([self faxAreaCode])); + profile->SetInfo(AutoFillType(PHONE_FAX_NUMBER), + base::SysNSStringToUTF16([self faxNumber])); +} + +@end diff --git a/chrome/browser/autofill/autofill_address_view_controller_mac.h b/chrome/browser/autofill/autofill_address_view_controller_mac.h new file mode 100644 index 0000000..40448d5 --- /dev/null +++ b/chrome/browser/autofill/autofill_address_view_controller_mac.h @@ -0,0 +1,37 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_VIEW_CONTROLLER_MAC_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_VIEW_CONTROLLER_MAC_ + +#import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/disclosure_view_controller.h" + +@class AutoFillAddressModel; +class AutoFillProfile; + +// A class that coordinates the |addressModel| and the associated view +// held in AutoFillAddressFormView.xib. +// |initWithProfile:| is the designated initializer. It takes |profile| +// and transcribes it to |addressModel| to which the view is bound. +@interface AutoFillAddressViewController : DisclosureViewController { + @private + // The primary model for this controller. The model is instantiated + // from within |initWithProfile:|. We do not hold it as a scoped_nsobject + // because it is exposed as a KVO compliant property. + AutoFillAddressModel* addressModel_; // strong reference +} + +@property (nonatomic, retain) AutoFillAddressModel* addressModel; + +// Designated initializer. Takes a copy of the data in |profile|, +// it is not held as a reference. +- (id)initWithProfile:(const AutoFillProfile&)profile; + +// Copy data from internal model to |profile|. +- (void)copyModelToProfile:(AutoFillProfile*)profile; + +@end + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_ADDRESS_VIEW_CONTROLLER_MAC_ diff --git a/chrome/browser/autofill/autofill_address_view_controller_mac.mm b/chrome/browser/autofill/autofill_address_view_controller_mac.mm new file mode 100644 index 0000000..2862ad9 --- /dev/null +++ b/chrome/browser/autofill/autofill_address_view_controller_mac.mm @@ -0,0 +1,40 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_address_view_controller_mac.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#import "chrome/browser/autofill/autofill_address_model_mac.h" +#include "chrome/browser/autofill/autofill_profile.h" + +@implementation AutoFillAddressViewController + +@synthesize addressModel = addressModel_; + +- (id)initWithProfile:(const AutoFillProfile&)profile { + self = [super initWithNibName:@"AutoFillAddressFormView" + bundle:mac_util::MainAppBundle()]; + if (self) { + // Pull in the view for initialization. + [self view]; + + // Create the model. + [self setAddressModel:[[[AutoFillAddressModel alloc] + initWithProfile:profile] autorelease]]; + } + return self; +} + +- (void)dealloc { + [addressModel_ release]; + [super dealloc]; +} + +- (void)copyModelToProfile:(AutoFillProfile*)profile { + [addressModel_ copyModelToProfile:profile]; +} + +@end + + diff --git a/chrome/browser/autofill/autofill_credit_card_model_mac.h b/chrome/browser/autofill/autofill_credit_card_model_mac.h new file mode 100644 index 0000000..97dfb67 --- /dev/null +++ b/chrome/browser/autofill/autofill_credit_card_model_mac.h @@ -0,0 +1,58 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_MODEL_MAC_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_MODEL_MAC_ + +#import <Cocoa/Cocoa.h> + +class CreditCard; + +// A "model" class used with bindings mechanism and the +// |AutoFillCreditCardViewController| to achieve the form-like view +// of autofill data in the Chrome options UI. +// Note that |summary| is a derived property. +// Model objects are initialized from the given |creditCard| using the +// designated initializer |initWithCreditCard:|. +// Users of this class must be prepared to handle nil string return values. +// The KVO/bindings mechanisms expect this and deal with nil string values +// appropriately. +@interface AutoFillCreditCardModel : NSObject { + @private + // These are not scoped_nsobjects because we use them via KVO/bindings. + NSString* label_; + NSString* nameOnCard_; + NSString* creditCardNumber_; + NSString* expirationMonth_; + NSString* expirationYear_; + NSString* cvcCode_; + NSString* billingAddress_; + NSString* shippingAddress_; +} + +// |summary| is a derived property based on |creditCardNumber|, +// |expirationMonth| and |expirationYear|. KVO observers receive change +// notifications for |summary| when any of these properties change. +@property (readonly) NSString* summary; +@property (nonatomic, copy) NSString* label; +@property (nonatomic, copy) NSString* nameOnCard; +@property (nonatomic, copy) NSString* creditCardNumber; +@property (nonatomic, copy) NSString* expirationMonth; +@property (nonatomic, copy) NSString* expirationYear; +@property (nonatomic, copy) NSString* cvcCode; +@property (nonatomic, copy) NSString* billingAddress; +@property (nonatomic, copy) NSString* shippingAddress; + +// Designated initializer. Initializes the property strings to values retrieved +// from the |creditCard| object. +- (id)initWithCreditCard:(const CreditCard&)creditCard; + +// This method copies internal NSString property values into the +// |creditCard| object's fields as appropriate. |creditCard| should never +// be NULL. +- (void)copyModelToCreditCard:(CreditCard*)creditCard; + +@end + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_MODEL_MAC_ diff --git a/chrome/browser/autofill/autofill_credit_card_model_mac.mm b/chrome/browser/autofill/autofill_credit_card_model_mac.mm new file mode 100644 index 0000000..f59cff9 --- /dev/null +++ b/chrome/browser/autofill/autofill_credit_card_model_mac.mm @@ -0,0 +1,86 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_credit_card_model_mac.h" +#include "app/l10n_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/autofill/credit_card.h" +#include "grit/generated_resources.h" + + +@implementation AutoFillCreditCardModel + +@dynamic summary; +@synthesize label = label_; +@synthesize nameOnCard = nameOnCard_; +@synthesize creditCardNumber = creditCardNumber_; +@synthesize expirationMonth = expirationMonth_; +@synthesize expirationYear = expirationYear_; +@synthesize cvcCode = cvcCode_; +@synthesize billingAddress = billingAddress_; +@synthesize shippingAddress = shippingAddress_; + +// Sets up the KVO dependency between "summary" and dependent fields. ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { + NSSet* keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; + + if ([key isEqualToString:@"summary"]) { + NSSet* affectingKeys = [NSSet setWithObjects:@"creditCardNumber", + @"expirationMonth", @"expirationYear", nil]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKeys]; + } + return keyPaths; +} + +- (id)initWithCreditCard:(const CreditCard&)creditCard { + if ((self = [super init])) { + [self setLabel:SysUTF16ToNSString(creditCard.Label())]; + [self setNameOnCard:SysUTF16ToNSString( + creditCard.GetFieldText(AutoFillType(CREDIT_CARD_NAME)))]; + [self setCreditCardNumber:SysUTF16ToNSString( + creditCard.GetFieldText(AutoFillType(CREDIT_CARD_NUMBER)))]; + [self setExpirationMonth:SysUTF16ToNSString( + creditCard.GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH)))]; + [self setExpirationYear:SysUTF16ToNSString( + creditCard.GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)))]; + [self setCvcCode:SysUTF16ToNSString( + creditCard.GetFieldText(AutoFillType(CREDIT_CARD_VERIFICATION_CODE)))]; + } + return self; +} + +- (void)dealloc { + [label_ release]; + [nameOnCard_ release]; + [creditCardNumber_ release]; + [expirationMonth_ release]; + [expirationYear_ release]; + [cvcCode_ release]; + [billingAddress_ release]; + [shippingAddress_ release]; + [super dealloc]; +} + +- (NSString*)summary { + // TODO(dhollowa): This has been pulled into cross platform code. + // Will hook up in separate CL. See http://crbug.com/33029. + return @""; +} + +- (void)copyModelToCreditCard:(CreditCard*)creditCard { + DCHECK(creditCard); + creditCard->set_label(base::SysNSStringToUTF16([self label])); + creditCard->SetInfo(AutoFillType(CREDIT_CARD_NAME), + base::SysNSStringToUTF16([self nameOnCard])); + creditCard->SetInfo(AutoFillType(CREDIT_CARD_NUMBER), + base::SysNSStringToUTF16([self creditCardNumber])); + creditCard->SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), + base::SysNSStringToUTF16([self expirationMonth])); + creditCard->SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), + base::SysNSStringToUTF16([self expirationYear])); + creditCard->SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE), + base::SysNSStringToUTF16([self cvcCode])); +} + +@end diff --git a/chrome/browser/autofill/autofill_credit_card_view_controller_mac.h b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.h new file mode 100644 index 0000000..05320c5 --- /dev/null +++ b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.h @@ -0,0 +1,41 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_VIEW_CONTROLLER_MAC_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_VIEW_CONTROLLER_MAC_ + +#import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/disclosure_view_controller.h" + +@class AutoFillCreditCardModel; +class CreditCard; + +// A class that coordinates the |creditCardModel| and the associated view +// held in AutoFillCreditCardFormView.xib. +// |initWithCreditCard:| is the designated initializer. It takes |creditCard| +// and transcribes it to |creditCardModel| to which the view is bound. +@interface AutoFillCreditCardViewController : DisclosureViewController { + @private + // TODO(dhollowa): temporary to disable until implementend. + // See http://crbug.com/33029. + IBOutlet NSTextField* billingAddressLabel_; + IBOutlet NSPopUpButton* billingAddressPopup_; + IBOutlet NSTextField* shippingAddressLabel_; + IBOutlet NSPopUpButton* shippingAddressPopup_; + + // The primary model for this controller. The model is instantiated + // from within |initWithCreditCard:|. We do not hold it as a scoped_nsobject + // because it is exposed as a KVO compliant property. + AutoFillCreditCardModel* creditCardModel_; +} + +@property (nonatomic, retain) AutoFillCreditCardModel* creditCardModel; + +// Designated initializer. Takes a copy of the data in |creditCard|, +// it is not held as a reference. +- (id)initWithCreditCard:(const CreditCard&)creditCard; + +@end + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_CREDIT_CARD_VIEW_CONTROLLER_MAC_ diff --git a/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm new file mode 100644 index 0000000..36ea721 --- /dev/null +++ b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm @@ -0,0 +1,51 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_credit_card_view_controller_mac.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#import "chrome/browser/autofill/autofill_credit_card_model_mac.h" +#include "chrome/browser/autofill/credit_card.h" + +@implementation AutoFillCreditCardViewController + +@synthesize creditCardModel = creditCardModel_; + +- (id)initWithCreditCard:(const CreditCard&)creditCard { + self = [super initWithNibName:@"AutoFillCreditCardFormView" + bundle:mac_util::MainAppBundle()]; + if (self) { + // Pull in the view for initialization. + [self view]; + + // Create the model. + [self setCreditCardModel:[[[AutoFillCreditCardModel alloc] + initWithCreditCard:creditCard] autorelease]]; + + // Setup initial state. + // TODO(dhollowa): not yet implemented, disabling controls for now. + // See http://crbug.com/33029. + [billingAddressLabel_ setEnabled:FALSE]; + [billingAddressLabel_ setTextColor:[NSColor secondarySelectedControlColor]]; + [billingAddressPopup_ removeAllItems]; + [billingAddressPopup_ setEnabled:FALSE]; + [shippingAddressLabel_ setEnabled:FALSE]; + [shippingAddressLabel_ setTextColor: + [NSColor secondarySelectedControlColor]]; + [shippingAddressPopup_ removeAllItems]; + [shippingAddressPopup_ setEnabled:FALSE]; + } + return self; +} + +- (void)dealloc { + [creditCardModel_ release]; + [super dealloc]; +} + +- (void)copyModelToCreditCard:(CreditCard*)creditCard { + [creditCardModel_ copyModelToCreditCard:creditCard]; +} + +@end diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.h b/chrome/browser/autofill/autofill_dialog_controller_mac.h new file mode 100644 index 0000000..6e1d8e3 --- /dev/null +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.h @@ -0,0 +1,82 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_MAC_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_MAC_ + +#import <Cocoa/Cocoa.h> +#include <vector> +#include "base/scoped_nsobject.h" +#include "chrome/browser/autofill/autofill_dialog.h" +#include "chrome/browser/autofill/autofill_profile.h" +#include "chrome/browser/autofill/credit_card.h" + +@class AutoFillAddressViewController; +@class AutoFillCreditCardViewController; +@class SectionSeparatorView; + +// A window controller for managing the autofill options dialog. +// Application modally presents a dialog allowing the user to store +// personal address and credit card information. +@interface AutoFillDialogController : NSWindowController { + @private + IBOutlet NSView* childView_; + IBOutlet NSView* addressSection_; + IBOutlet SectionSeparatorView* addressSectionBox_; + IBOutlet NSView* creditCardSection_; + + // TODO(dhollowa): one each of these for now. Will be n of each + // controller eventually, for n addresses and n credit cards. + // Note on ownership: the controllers are strongly owned by the dialog + // controller. Their views are inserted into the dialog's view hierarcy + // but are retained by these controllers as well. + // See http://crbug.com/33029. + scoped_nsobject<AutoFillAddressViewController> + addressFormViewController_; + scoped_nsobject<AutoFillCreditCardViewController> + creditCardFormViewController_; + + AutoFillDialogObserver* observer_; // (weak) not retained + std::vector<AutoFillProfile> profiles_; + std::vector<CreditCard> creditCards_; +} + +// 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. +// |observer| can be NULL, but if it is, then no notification is sent during +// call to |save|. If |observer| is non-NULL then its |OnAutoFillDialogApply| +// method is invoked during |save| with the new address and credit card +// information. +// |profiles| and |creditCards| must have non-NULL entries (zero or more). +// These provide the initial data that is presented to the user. ++ (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards; + +// IBActions for the dialog buttons. +- (IBAction)save:(id)sender; +- (IBAction)cancel:(id)sender; + +@end + +// Interface exposed for unit testing. +@interface AutoFillDialogController (ExposedForUnitTests) +// Returns an instance of AutoFillDialogController. See |-initWithObserver| +// for details about arguments. +// Note: controller is autoreleased when |-closeDialog| is called. ++ (AutoFillDialogController*)controllerWithObserver: + (AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards; + +- (id)initWithObserver:(AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards; +- (AutoFillAddressViewController*)addressFormViewController; +- (AutoFillCreditCardViewController*)creditCardFormViewController; +- (void)closeDialog; +@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 new file mode 100644 index 0000000..4288296 --- /dev/null +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm @@ -0,0 +1,162 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_dialog_controller_mac.h" +#include "base/mac_util.h" +#import "chrome/browser/autofill/autofill_address_model_mac.h" +#import "chrome/browser/autofill/autofill_address_view_controller_mac.h" +#import "chrome/browser/autofill/autofill_credit_card_model_mac.h" +#import "chrome/browser/autofill/autofill_credit_card_view_controller_mac.h" +#import "chrome/browser/cocoa/disclosure_view_controller.h" +#import "chrome/browser/cocoa/section_separator_view.h" +#include "chrome/browser/profile.h" + +@interface AutoFillDialogController (PrivateMethods) +- (void)runModalDialog; +- (void)installChildViews; +@end + +@implementation AutoFillDialogController + ++ (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards { + AutoFillDialogController* controller = + [AutoFillDialogController controllerWithObserver:observer + autoFillProfiles:profiles + creditCards:creditCards]; + + // Only run modal dialog if it is not already being shown. + if (![controller isWindowLoaded]) { + [controller runModalDialog]; + } +} + +- (void)awakeFromNib { + [addressSectionBox_ setShowTopLine:FALSE]; + [self installChildViews]; +} + +// NSWindow Delegate callback. When the window closes the controller can +// be released. +- (void)windowWillClose:(NSNotification *)notification { + [self autorelease]; +} + + +// Called when the user clicks the save button. +- (IBAction)save:(id)sender { + if (observer_) { + [addressFormViewController_ copyModelToProfile:&profiles_[0]]; + [creditCardFormViewController_ copyModelToCreditCard:&creditCards_[0]]; + observer_->OnAutoFillDialogApply(&profiles_, &creditCards_); + } + [self closeDialog]; +} + +// Called when the user clicks the cancel button. All we need to do is stop +// the modal session. +- (IBAction)cancel:(id)sender { + [self closeDialog]; +} + +@end + +@implementation AutoFillDialogController (ExposedForUnitTests) + ++ (AutoFillDialogController*)controllerWithObserver: + (AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards { + + // Deallocation is done upon window close. See |windowWillClose:|. + AutoFillDialogController* controller = + [[self alloc] initWithObserver:observer + autoFillProfiles:profiles + creditCards:creditCards]; + return controller; +} + + +// This is the designated initializer for this class. +// |profiles| are non-retained immutable list of autofill profiles. +// |creditCards| are non-retained immutable list of credit card info. +- (id)initWithObserver:(AutoFillDialogObserver*)observer + autoFillProfiles:(const std::vector<AutoFillProfile*>&)profiles + creditCards:(const std::vector<CreditCard*>&)creditCards { + // Use initWithWindowNibPath: instead of initWithWindowNibName: so we + // can override it in a unit test. + NSString* nibpath = [mac_util::MainAppBundle() + pathForResource:@"AutoFillDialog" + ofType:@"nib"]; + if ((self = [super initWithWindowNibPath:nibpath owner:self])) { + observer_ = observer; + + // Make local copy of |profiles|. + std::vector<AutoFillProfile*>::const_iterator i; + for (i = profiles.begin(); i != profiles.end(); ++i) + profiles_.push_back(**i); + + // Make local copy of |creditCards|. + std::vector<CreditCard*>::const_iterator j; + for (j = creditCards.begin(); j != creditCards.end(); ++j) + creditCards_.push_back(**j); + } + return self; +} + +// Close the dialog. +- (void)closeDialog { + [[self window] close]; + [NSApp stopModal]; +} + +- (AutoFillAddressViewController*)addressFormViewController { + return addressFormViewController_.get(); +} + +- (AutoFillCreditCardViewController*)creditCardFormViewController { + return creditCardFormViewController_.get(); +} + +@end + +@implementation AutoFillDialogController (PrivateMethods) + +// Run application modal. +- (void)runModalDialog { + [NSApp runModalForWindow:[self window]]; +} + +// Install controller and views for the address form and the credit card form. +// They are installed into the appropriate sibling order so that they can be +// arranged vertically by the VerticalLayoutView class. We insert the views +// into the |childView_| but we hold onto the controllers and release them in +// our dealloc once the dialog closes. +- (void)installChildViews { + if (profiles_.size() > 0) { + AutoFillAddressViewController* autoFillAddressViewController = + [[AutoFillAddressViewController alloc] initWithProfile:profiles_[0]]; + addressFormViewController_.reset(autoFillAddressViewController); + + // Embed the child view into our (owned by us) target view. + [childView_ addSubview:[addressFormViewController_ view] + positioned:NSWindowBelow relativeTo:addressSection_]; + [[addressFormViewController_ view] setFrameOrigin:NSMakePoint(0, 0)]; + } + + if (creditCards_.size() > 0) { + AutoFillCreditCardViewController* autoFillCreditCardViewController = + [[AutoFillCreditCardViewController alloc] + initWithCreditCard:creditCards_[0]]; + creditCardFormViewController_.reset(autoFillCreditCardViewController); + + // Embed the child view into our (owned by us) target view. + [childView_ addSubview:[creditCardFormViewController_ view] + positioned:NSWindowBelow relativeTo:creditCardSection_]; + [[creditCardFormViewController_ view] setFrameOrigin:NSMakePoint(0, 0)]; + } +} + +@end diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm new file mode 100644 index 0000000..907e2dc --- /dev/null +++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm @@ -0,0 +1,205 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/autofill/autofill_address_model_mac.h" +#import "chrome/browser/autofill/autofill_address_view_controller_mac.h" +#import "chrome/browser/autofill/autofill_credit_card_model_mac.h" +#import "chrome/browser/autofill/autofill_credit_card_view_controller_mac.h" +#import "chrome/browser/autofill/autofill_dialog_controller_mac.h" +#include "chrome/browser/autofill/autofill_profile.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/browser/profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +class AutoFillDialogObserverTester : public AutoFillDialogObserver { + public: + AutoFillDialogObserverTester() : hit_(false) {} + virtual ~AutoFillDialogObserverTester() {} + + virtual void OnAutoFillDialogApply( + std::vector<AutoFillProfile>* profiles, + std::vector<CreditCard>* credit_cards) { + hit_ = true; + + std::vector<AutoFillProfile>::iterator i; + profiles_.clear(); + for (i = profiles->begin(); i != profiles->end(); ++i) + profiles_.push_back(*i); + + std::vector<CreditCard>::iterator j; + credit_cards_.clear(); + for (j = credit_cards->begin(); j != credit_cards->end(); ++j) + credit_cards_.push_back(*j); + } + + bool hit_; + std::vector<AutoFillProfile> profiles_; + std::vector<CreditCard> credit_cards_; +}; + +class AutoFillDialogControllerTest : public CocoaTest { + public: + AutoFillDialogControllerTest() {} + + void LoadDialog() { + controller_ = [AutoFillDialogController + controllerWithObserver:&observer_ + autoFillProfiles:profiles_ + creditCards:credit_cards_]; + [controller_ window]; + } + + BrowserTestHelper helper_; + AutoFillDialogObserverTester observer_; + AutoFillDialogController* controller_; // weak reference + std::vector<AutoFillProfile*> profiles_; // weak references within vector + std::vector<CreditCard*> credit_cards_; // weak references within vector +}; + +TEST_F(AutoFillDialogControllerTest, SaveButtonInformsObserver) { + LoadDialog(); + [controller_ save:nil]; + ASSERT_TRUE(observer_.hit_); +} + +TEST_F(AutoFillDialogControllerTest, CancelButtonDoesNotInformObserver) { + LoadDialog(); + [controller_ cancel:nil]; + ASSERT_FALSE(observer_.hit_); +} + +TEST_F(AutoFillDialogControllerTest, NoEditsGiveBackOriginalProfile) { + AutoFillProfile profile; + profiles_.push_back(&profile); + LoadDialog(); + [controller_ save:nil]; + + // Should hit our observer. + ASSERT_TRUE(observer_.hit_); + + // Sizes should match. + ASSERT_EQ(observer_.profiles_.size(), profiles_.size()); + + // Contents should match. + size_t i = 0; + size_t count = profiles_.size(); + for (i = 0; i < count; i++) + ASSERT_EQ(observer_.profiles_[i], *profiles_[i]); + + // Contents should not match a different profile. + AutoFillProfile differentProfile; + differentProfile.set_label(ASCIIToUTF16("different")); + differentProfile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("joe")); + for (i = 0; i < count; i++) + ASSERT_NE(observer_.profiles_[i], differentProfile); +} + +TEST_F(AutoFillDialogControllerTest, NoEditsGiveBackOriginalCreditCard) { + CreditCard creditCard(ASCIIToUTF16("myCC"), 345); + credit_cards_.push_back(&creditCard); + LoadDialog(); + [controller_ save:nil]; + + // Should hit our observer. + ASSERT_TRUE(observer_.hit_); + + // Sizes should match. + ASSERT_EQ(observer_.credit_cards_.size(), credit_cards_.size()); + + // Contents should match. + size_t i = 0; + size_t count = credit_cards_.size(); + for (i = 0; i < count; i++) + ASSERT_EQ(observer_.credit_cards_[i], *credit_cards_[i]); + + // Contents should not match a different profile. + CreditCard differentCreditCard(ASCIIToUTF16("different"), 0); + differentCreditCard.SetInfo( + AutoFillType(CREDIT_CARD_NUMBER), ASCIIToUTF16("1234")); + for (i = 0; i < count; i++) + ASSERT_NE(observer_.credit_cards_[i], differentCreditCard); +} + +TEST_F(AutoFillDialogControllerTest, AutoFillDataMutation) { + AutoFillProfile profile(ASCIIToUTF16("Home"), 17); + profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("David")); + profile.SetInfo(AutoFillType(NAME_MIDDLE), ASCIIToUTF16("C")); + profile.SetInfo(AutoFillType(NAME_LAST), ASCIIToUTF16("Holloway")); + profile.SetInfo(AutoFillType(EMAIL_ADDRESS), + ASCIIToUTF16("dhollowa@chromium.org")); + profile.SetInfo(AutoFillType(COMPANY_NAME), ASCIIToUTF16("Google Inc.")); + profile.SetInfo( + AutoFillType(ADDRESS_HOME_LINE1), ASCIIToUTF16("1122 Mountain View Road")); + profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2), ASCIIToUTF16("Suite #1")); + profile.SetInfo(AutoFillType(ADDRESS_HOME_CITY), + ASCIIToUTF16("Mountain View")); + profile.SetInfo(AutoFillType(ADDRESS_HOME_STATE), ASCIIToUTF16("CA")); + profile.SetInfo(AutoFillType(ADDRESS_HOME_ZIP), ASCIIToUTF16("94111")); + profile.SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), ASCIIToUTF16("USA")); + profile.SetInfo(AutoFillType(PHONE_HOME_COUNTRY_CODE), ASCIIToUTF16("01")); + profile.SetInfo(AutoFillType(PHONE_HOME_CITY_CODE), ASCIIToUTF16("415")); + profile.SetInfo(AutoFillType(PHONE_HOME_NUMBER), ASCIIToUTF16("5552258")); + profile.SetInfo(AutoFillType(PHONE_FAX_COUNTRY_CODE), ASCIIToUTF16("02")); + profile.SetInfo(AutoFillType(PHONE_FAX_CITY_CODE), ASCIIToUTF16("408")); + profile.SetInfo(AutoFillType(PHONE_FAX_NUMBER), ASCIIToUTF16("7172258")); + profiles_.push_back(&profile); + + LoadDialog(); + + AutoFillAddressModel* am = [[controller_ addressFormViewController] + addressModel]; + EXPECT_TRUE([[am firstName] isEqualToString:@"David"]); + EXPECT_TRUE([[am middleName] isEqualToString:@"C"]); + EXPECT_TRUE([[am lastName] isEqualToString:@"Holloway"]); + EXPECT_TRUE([[am email] isEqualToString:@"dhollowa@chromium.org"]); + EXPECT_TRUE([[am companyName] isEqualToString:@"Google Inc."]); + EXPECT_TRUE([[am addressLine1] isEqualToString:@"1122 Mountain View Road"]); + EXPECT_TRUE([[am addressLine2] isEqualToString:@"Suite #1"]); + EXPECT_TRUE([[am city] isEqualToString:@"Mountain View"]); + EXPECT_TRUE([[am state] isEqualToString:@"CA"]); + EXPECT_TRUE([[am zip] isEqualToString:@"94111"]); + EXPECT_TRUE([[am phoneCountryCode] isEqualToString:@"01"]); + EXPECT_TRUE([[am phoneAreaCode] isEqualToString:@"415"]); + EXPECT_TRUE([[am phoneNumber] isEqualToString:@"5552258"]); + EXPECT_TRUE([[am faxCountryCode] isEqualToString:@"02"]); + EXPECT_TRUE([[am faxAreaCode] isEqualToString:@"408"]); + EXPECT_TRUE([[am faxNumber] isEqualToString:@"7172258"]); + + [controller_ save:nil]; + + ASSERT_TRUE(observer_.hit_); + ASSERT_TRUE(observer_.profiles_.size() == 1); +} + +TEST_F(AutoFillDialogControllerTest, CreditCardDataMutation) { + CreditCard creditCard(ASCIIToUTF16("myCC"), 345); + creditCard.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("DCH")); + creditCard.SetInfo( + AutoFillType(CREDIT_CARD_NUMBER), ASCIIToUTF16("1234 5678 9101 1121")); + creditCard.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("01")); + creditCard.SetInfo( + AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), ASCIIToUTF16("2012")); + creditCard.SetInfo( + AutoFillType(CREDIT_CARD_VERIFICATION_CODE), ASCIIToUTF16("222")); + credit_cards_.push_back(&creditCard); + + LoadDialog(); + + AutoFillCreditCardModel* cm = [[controller_ creditCardFormViewController] + creditCardModel]; + EXPECT_TRUE([[cm nameOnCard] isEqualToString:@"DCH"]); + EXPECT_TRUE([[cm creditCardNumber] isEqualToString:@"1234 5678 9101 1121"]); + EXPECT_TRUE([[cm expirationMonth] isEqualToString:@"01"]); + EXPECT_TRUE([[cm expirationYear] isEqualToString:@"2012"]); + EXPECT_TRUE([[cm cvcCode] isEqualToString:@"222"]); + + [controller_ save:nil]; + + ASSERT_TRUE(observer_.hit_); + ASSERT_TRUE(observer_.credit_cards_.size() == 1); +} + +} diff --git a/chrome/browser/autofill/autofill_dialog.cc b/chrome/browser/autofill/autofill_dialog_mac.mm index 44df062..912ced4 100644 --- a/chrome/browser/autofill/autofill_dialog.cc +++ b/chrome/browser/autofill/autofill_dialog_mac.mm @@ -2,13 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "chrome/browser/autofill/autofill_dialog_controller_mac.h" #include "chrome/browser/autofill/autofill_dialog.h" -// TODO(dhollowa): Remove these as each platform implements this -// function. The last one to implement the function should remove this file. -#if defined(OS_MACOSX) +// Mac implementation of |ShowAutoFillDialog| interface defined in +// |chrome/browser/autofill/autofill_dialog.h|. void ShowAutoFillDialog(AutoFillDialogObserver* observer, const std::vector<AutoFillProfile*>& profiles, const std::vector<CreditCard*>& credit_cards) { + [AutoFillDialogController + showAutoFillDialogWithObserver:observer + autoFillProfiles:profiles + creditCards:credit_cards]; } -#endif // defined(OS_WIN) || defined(OS_MACOSX) + diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc index caf335a..fc3b30c 100644 --- a/chrome/browser/autofill/autofill_profile.cc +++ b/chrome/browser/autofill/autofill_profile.cc @@ -158,6 +158,10 @@ bool AutoFillProfile::operator==(const AutoFillProfile& profile) const { return true; } +bool AutoFillProfile::operator!=(const AutoFillProfile& profile) const { + return !operator==(profile); +} + void AutoFillProfile::set_use_billing_address(bool use) { if (use_billing_address_ == use) return; diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h index 6142721..65182ec 100644 --- a/chrome/browser/autofill/autofill_profile.h +++ b/chrome/browser/autofill/autofill_profile.h @@ -56,6 +56,7 @@ class AutoFillProfile : public FormGroup { // Used by tests. // TODO(jhawkins): Move these to private and add the test as a friend. bool operator==(const AutoFillProfile& profile) const; + bool operator!=(const AutoFillProfile& profile) const; void set_label(const string16& label) { label_ = label; } private: diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc index d4e5589..e32ccf1 100644 --- a/chrome/browser/autofill/credit_card.cc +++ b/chrome/browser/autofill/credit_card.cc @@ -42,7 +42,6 @@ CreditCard::CreditCard() expiration_year_(0) { } - FormGroup* CreditCard::Clone() const { return new CreditCard(*this); } @@ -325,6 +324,10 @@ bool CreditCard::operator==(const CreditCard& creditcard) const { return true; } +bool CreditCard::operator!=(const CreditCard& creditcard) const { + return !operator==(creditcard); +} + bool CreditCard::FindInfoMatchesHelper(const AutoFillFieldType& field_type, const string16& info, string16* match) const { diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h index 1f99405..1c22d14 100644 --- a/chrome/browser/autofill/credit_card.h +++ b/chrome/browser/autofill/credit_card.h @@ -90,6 +90,7 @@ class CreditCard : public FormGroup { // Used by tests. bool operator==(const CreditCard& creditcard) const; + bool operator!=(const CreditCard& creditcard) const; void set_label(const string16& label) { label_ = label; } private: |