diff options
Diffstat (limited to 'chrome/browser')
24 files changed, 1516 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: diff --git a/chrome/browser/cocoa/disclosure_view_controller.h b/chrome/browser/cocoa/disclosure_view_controller.h new file mode 100644 index 0000000..71a2c5f --- /dev/null +++ b/chrome/browser/cocoa/disclosure_view_controller.h @@ -0,0 +1,30 @@ +// 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_COCOA_DISCLOSURE_VIEW_CONTROLLER_ +#define CHROME_BROWSER_COCOA_DISCLOSURE_VIEW_CONTROLLER_ + +#import <Cocoa/Cocoa.h> + +@class DisclosureViewState; + +// A view class that provides a disclosure triangle that controls the size +// of the view. Toggling the disclosure triangle animates the change in +// size of the view. The |openHeight| is initialized from the initial size +// of the view. |disclosureState| is initialized as |NSOnState| (of type +// NSCellStateValue) which corresponds to "open". +@interface DisclosureViewController : NSViewController { + @private + // The |disclosureState_| is instantiated from within |awakeFromNib|. + // We do not hold it as a scoped_nsobject because it is exposed as a KVO + // compliant property. + DisclosureViewState* disclosureState_; // strong reference + CGFloat openHeight_; +} + +@property (nonatomic, retain) DisclosureViewState* disclosureState; + +@end + +#endif // CHROME_BROWSER_COCOA_DISCLOSURE_VIEW_CONTROLLER_ diff --git a/chrome/browser/cocoa/disclosure_view_controller.mm b/chrome/browser/cocoa/disclosure_view_controller.mm new file mode 100644 index 0000000..f41acd5 --- /dev/null +++ b/chrome/browser/cocoa/disclosure_view_controller.mm @@ -0,0 +1,189 @@ +// 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/cocoa/disclosure_view_controller.h" +#include "base/logging.h" +#include "base/scoped_nsobject.h" + +const NSCellStateValue kInitialDisclosureState = NSOffState; +const NSInteger kClosedBoxHeight = 20; +NSString* const kKVODisclosedKey = @"disclosed"; + +// This class externalizes the state of the disclosure control. When the +// disclosure control is pressed it changes the state of this object. In turn +// the KVO machinery detects the change to |disclosed| and signals the +// |observeValueForKeyPath| call in the |DisclosureViewController|. +@interface DisclosureViewState : NSObject { + @private + NSCellStateValue disclosed; +} +@end + +@implementation DisclosureViewState +@end + +@interface DisclosureViewController(PrivateMethods) + +- (void)initDisclosureState:(NSCellStateValue)state; +- (NSRect)openStateFrameSize:(NSRect)startFrame; +- (NSRect)closedStateFrameSize:(NSRect)startFrame; + +- (void)startAnimations:(NSView*)view + start:(NSRect)startFrame + end:(NSRect)endFrame; + +- (void)discloseDetails:(NSCellStateValue)state; + +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context; + +@end + +@implementation DisclosureViewController + +@synthesize disclosureState = disclosureState_; + +- (void)awakeFromNib { + // Create the disclosure state. + [self setDisclosureState:[[[DisclosureViewState alloc] init] autorelease]]; + + // Set up the initial disclosure state before we install the observer. + // We don't want our animations firing before we're done initializing. + [disclosureState_ setValue:[NSNumber numberWithInt:kInitialDisclosureState] + forKey:kKVODisclosedKey]; + + // Pick up "open" height from the initial state of the view in the nib. + openHeight_ = [[self view] frame].size.height; + + // Set frame size according to initial disclosure state. + [self initDisclosureState:kInitialDisclosureState]; + + // Setup observers so that when disclosure state changes we resize frame + // accordingly. + [disclosureState_ addObserver:self forKeyPath:kKVODisclosedKey + options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld + context:nil]; +} + +- (void)dealloc { + [disclosureState_ removeObserver:self forKeyPath:kKVODisclosedKey]; + [disclosureState_ release]; + [super dealloc]; +} + +@end + +@implementation DisclosureViewController(PrivateMethods) + +// Initializes the view's frame geometry based on the input |state|. +// If the |state| is NSOnState then the frame size corresponds to "open". +// If the |state| is NSOffState then the frame size corresponds to "closed". +// The |origin.x| and |size.width| remain unchanged, but the |origin.y| and +// |size.height| may vary. +- (void)initDisclosureState:(NSCellStateValue)state { + if (state == NSOnState) { + [[self view] setFrame:[self openStateFrameSize:[[self view] frame]]]; + } + else if (state == NSOffState) { + [[self view] setFrame:[self closedStateFrameSize:[[self view] frame]]]; + } + else { + NOTREACHED(); + } +} + +// Computes the frame geometry during the "open" state of the disclosure view. +- (NSRect)openStateFrameSize:(NSRect)startFrame { + return NSMakeRect(startFrame.origin.x, + startFrame.size.height - openHeight_ + + startFrame.origin.y, + startFrame.size.width, + openHeight_); +} + +// Computes the frame geometry during the "closed" state of the disclosure view. +- (NSRect)closedStateFrameSize:(NSRect)startFrame { + return NSMakeRect(startFrame.origin.x, + startFrame.size.height - kClosedBoxHeight + + startFrame.origin.y, + startFrame.size.width, + kClosedBoxHeight); +} + +// Animates the opening or closing of the disclosure view. The |startFrame| +// specifies the frame geometry at the beginning of the animation and the +// |endFrame| specifies the geometry at the end of the animation. The input +// |view| is view managed by this controller. +- (void)startAnimations:(NSView*)view + start:(NSRect)startFrame + end:(NSRect)endFrame +{ + // Setup dictionary describing animation. + // Create the attributes dictionary for the first view. + NSMutableDictionary* dictionary; + dictionary = [NSDictionary dictionaryWithObjectsAndKeys: + // Specify which view to modify. + view, NSViewAnimationTargetKey, + // Specify the starting position of the view. + [NSValue valueWithRect:startFrame], NSViewAnimationStartFrameKey, + // Change the ending position of the view. + [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, + nil]; + + // Create the view animation object. + scoped_nsobject<NSViewAnimation> animation; + animation.reset([[NSViewAnimation alloc] initWithViewAnimations: + [NSArray arrayWithObject:dictionary]]); + + // Set some additional attributes for the animation. + [animation.get() setDuration:.2]; + [animation.get() setAnimationCurve:NSAnimationEaseIn]; + + // Run the animation. + [animation.get() startAnimation]; +} + +// This method is invoked when the disclosure state changes. It computes +// the appropriate view frame geometry and then initiates the animation to +// change that geometry. +- (void)discloseDetails:(NSCellStateValue)state { + NSRect startFrame = [[self view] frame]; + NSRect endFrame = startFrame; + + if (state == NSOnState) { + endFrame = [self openStateFrameSize:startFrame]; + } else if (state == NSOffState) { + endFrame = [self closedStateFrameSize:startFrame]; + } else { + NOTREACHED(); + return; + } + + [self startAnimations:[self view] start:startFrame end:endFrame]; +} + +// The |DisclosureViewController| is an observer of an instance of a +// |DisclosureViewState| object. This object lives within the controller's +// nib file. When the KVO machinery detects a change to the state +// it triggers this call and we initiate the change in frame geometry of the +// view. +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + if ([keyPath isEqualToString:kKVODisclosedKey]) { + NSCellStateValue newValue = + [[change objectForKey:NSKeyValueChangeNewKey] intValue]; + NSCellStateValue oldValue = + [[change objectForKey:NSKeyValueChangeOldKey] intValue]; + + if (newValue != oldValue) { + [self discloseDetails:newValue]; + } + } +} + +@end diff --git a/chrome/browser/cocoa/preferences_window_controller.h b/chrome/browser/cocoa/preferences_window_controller.h index e29047e..352f6d8 100644 --- a/chrome/browser/cocoa/preferences_window_controller.h +++ b/chrome/browser/cocoa/preferences_window_controller.h @@ -126,6 +126,7 @@ class ProfileSyncService; // User Data panel - (IBAction)showSavedPasswords:(id)sender; +- (IBAction)showAutoFillSettings:(id)sender; - (IBAction)importData:(id)sender; - (IBAction)clearData:(id)sender; - (IBAction)resetThemeToDefault:(id)sender; diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm index 56e369f..357824d 100644 --- a/chrome/browser/cocoa/preferences_window_controller.mm +++ b/chrome/browser/cocoa/preferences_window_controller.mm @@ -12,6 +12,9 @@ #include "base/string16.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" +#include "chrome/browser/autofill/autofill_dialog.h" +#include "chrome/browser/autofill/autofill_type.h" +#include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" @@ -1145,6 +1148,28 @@ const int kDisabledIndex = 1; [self launchKeychainAccess]; } +// Called to show the Auto Fill Settings dialog. +- (IBAction)showAutoFillSettings:(id)sender { + [self recordUserAction:"Options_ShowAutoFillSettings"]; + + // TODO(dhollowa): Need "n" of these. Create single entry for now. + // See http://crbug.com/33029. + std::vector<AutoFillProfile*> profiles; + AutoFillProfile profile(ASCIIToUTF16(""), 0); + profiles.push_back(&profile); + + // TODO(dhollowa): Need "n" of these. Create single entry for now. + // See http://crbug.com/33029. + std::vector<CreditCard*> creditCards; + CreditCard creditCard(ASCIIToUTF16(""), 0); + creditCards.push_back(&creditCard); + + // TODO(dhollowa): There are outstanding assertions in autofill back end. + // Hooking up with UI only until those issues are resolved. + // See http://crbug.com/33029. + ShowAutoFillDialog(NULL, profiles, creditCards); +} + // Called to import data from other browsers (Safari, Firefox, etc). - (IBAction)importData:(id)sender { UserMetrics::RecordAction("Import_ShowDlg", profile_); diff --git a/chrome/browser/cocoa/section_separator_view.h b/chrome/browser/cocoa/section_separator_view.h new file mode 100644 index 0000000..22a9412 --- /dev/null +++ b/chrome/browser/cocoa/section_separator_view.h @@ -0,0 +1,32 @@ +// 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_COCOA_SECTION_SEPARATOR_VIEW_ +#define CHROME_BROWSER_COCOA_SECTION_SEPARATOR_VIEW_ + +#import <Cocoa/Cocoa.h> + +// A view class that renders a gradient "section" separator. The visual +// style is modelled similarly to iPhone table view separators. This view +// paints a simple top-to-bottom gradient in its bounds of fixed gray values. +// Optionally, it also paints a "topline" and "baseline". Default is to +// draw both topline and baseline, but these can be overridden. +// The user of the class can override the color of the base line and top line +// using the |baselineSeparatorColor| and |toplineSeparatorColor| properties. +@interface SectionSeparatorView : NSView { + @private + BOOL showBaseLine_; + NSColor* baselineSeparatorColor_; + BOOL showTopLine_; + NSColor* toplineSeparatorColor_; +} + +@property (nonatomic, assign) BOOL showBaseLine; +@property (nonatomic, retain) NSColor* baselineSeparatorColor; +@property (nonatomic, assign) BOOL showTopLine; +@property (nonatomic, retain) NSColor* toplineSeparatorColor; + +@end + +#endif // CHROME_BROWSER_COCOA_SECTION_SEPARATOR_VIEW_ diff --git a/chrome/browser/cocoa/section_separator_view.mm b/chrome/browser/cocoa/section_separator_view.mm new file mode 100644 index 0000000..a7968bc --- /dev/null +++ b/chrome/browser/cocoa/section_separator_view.mm @@ -0,0 +1,106 @@ +// 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/cocoa/section_separator_view.h" + +@interface SectionSeparatorView (PrivateMethods) +- (void)drawGradientRect:(NSRect)rect; +- (void)drawBaseLineRect:(NSRect)rect; +- (void)drawTopLineRect:(NSRect)rect; +@end + +@implementation SectionSeparatorView + +@synthesize showBaseLine = showBaseLine_; +@synthesize baselineSeparatorColor = baselineSeparatorColor_; +@synthesize showTopLine = showTopLine_; +@synthesize toplineSeparatorColor = toplineSeparatorColor_; + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setShowBaseLine:YES]; + [self setBaselineSeparatorColor:[NSColor grayColor]]; + [self setShowTopLine:YES]; + [self setToplineSeparatorColor:[NSColor lightGrayColor]]; + } + return self; +} + +- (void)dealloc { + [baselineSeparatorColor_ release]; + [toplineSeparatorColor_ release]; + [super dealloc]; +} + +- (void)drawRect:(NSRect)rect { + NSRect gradientBounds = [self bounds]; + NSRect baselineRect = gradientBounds; + NSRect toplineRect = gradientBounds; + gradientBounds.size.height -= 1; + gradientBounds.origin.y += 1; + baselineRect.size.height = 1; + baselineRect.origin.y = 0; + toplineRect.size.height = 1; + toplineRect.origin.y = gradientBounds.size.height; + [self drawGradientRect:gradientBounds]; + if ([self showBaseLine]) + [self drawBaseLineRect:baselineRect]; + if ([self showTopLine]) + [self drawTopLineRect:toplineRect]; +} + +@end + +@implementation SectionSeparatorView (PrivateMethods) + +// This method draws the gradient fill of the "separator" bar. The input +// |rect| designates the bounds that will be filled with the the gradient. +// The gradient has two stops, lighter gray blending to +// darker gray, descending from the top of the |rect| to the bottom. +- (void)drawGradientRect:(NSRect)rect { + // Compute start and end points where to draw the gradient. + CGPoint startPoint = CGPointMake(NSMinX(rect), NSMinY(rect)); + CGPoint endPoint = CGPointMake(NSMinX(rect), NSMaxY(rect)); + + // Setup the context and colorspace. + CGContextRef context = + (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(context); + CGColorSpaceRef colorspace = + CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + + // Create the gradient. + const size_t stopCount = 2; + CGFloat stops[stopCount] = { 0.0, 1.0 }; + CGFloat components[8] = { + 0.75, 0.75, 0.75, 1.0, // start color + 0.95, 0.95, 0.95, 1.0 }; // end color + + CGGradientRef gradient = CGGradientCreateWithColorComponents( + colorspace, components, stops, stopCount); + + CGContextClipToRect(context, *(CGRect*)&rect); + CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); + + CGGradientRelease(gradient); + CGColorSpaceRelease(colorspace); + CGContextRestoreGState(context); +} + +// Draws the base line of the separator bar using the |baselineSeparatorColor_| +// designated color. +- (void)drawBaseLineRect:(NSRect)rect { + [baselineSeparatorColor_ set]; + NSFrameRect(rect); +} + +// Draws the top line of the separator bar using the |toplineSeparatorColor_| +// designated color. +- (void)drawTopLineRect:(NSRect)rect { + [toplineSeparatorColor_ set]; + NSFrameRect(rect); +} + +@end diff --git a/chrome/browser/cocoa/vertical_layout_view.h b/chrome/browser/cocoa/vertical_layout_view.h new file mode 100644 index 0000000..56e9954 --- /dev/null +++ b/chrome/browser/cocoa/vertical_layout_view.h @@ -0,0 +1,22 @@ +// 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_COCOA_VERTICAL_LAYOUT_VIEW_ +#define CHROME_BROWSER_COCOA_VERTICAL_LAYOUT_VIEW_ + +#import <Cocoa/Cocoa.h> + +// A view class that automatically performs layout of child views based +// on paint order of the children in the view hierarchy. The children are +// arranged top-to-bottom (in y-order) based on each child's height. +// Horizontal (x) positions are left as specified. Layout is performed when +// children are added, removed, or have their frames changed. Layout is also +// performed when this view (|self|) has its frame changed. +// Autoresizing is disabled for |VerticalLayoutView|s. +@interface VerticalLayoutView : NSView { +} + +@end + +#endif // CHROME_BROWSER_COCOA_VERTICAL_LAYOUT_VIEW_ diff --git a/chrome/browser/cocoa/vertical_layout_view.mm b/chrome/browser/cocoa/vertical_layout_view.mm new file mode 100644 index 0000000..b4e6a5e --- /dev/null +++ b/chrome/browser/cocoa/vertical_layout_view.mm @@ -0,0 +1,73 @@ +// 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/cocoa/vertical_layout_view.h" + +@interface VerticalLayoutView(PrivateMethods) +- (void)layoutChildren; +@end + +@implementation VerticalLayoutView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Turn auto resizing off, we'll be laying out our children programatically. + [self setAutoresizesSubviews:NO]; + [self setAutoresizingMask:NSViewNotSizable]; + } + + return self; +} + +// Flip the coordinate system to arrange child views from top to bottom +// with top at 0, increasing down. This simplifies the logic and plays +// well with containing scroll views. +- (BOOL)isFlipped { + return YES; +} + +// Override the default |viewWillDraw| to indicate to drawing machinery proper +// arrangement of subvies. +- (void)viewWillDraw { + // Reposition child views prior to super's descent into its |viewWillDraw| + // pass. + [self layoutChildren]; + + // Default descent into subviews. + [super viewWillDraw]; + + // Adjust children again to account for any modifications made during the + // prior descent. Most importantly we resize our own frame to properly + // adjust any containing scroll view. + [self layoutChildren]; +} + +@end + +@implementation VerticalLayoutView(PrivateMethods) + +// This method traverses the immediate subviews measuring their height and +// adjusting their frames so they are arranged vertically ordered relative +// to their sibling views. Note the dependency here on the |isFlipped| +// state. This code assumes |isFlipped| is YES. +- (void)layoutChildren { + NSArray* children = [self subviews]; + int childCount = [children count]; + + CGFloat yPosition = 0.0; + for (int i = childCount-1; i >= 0; --i) { + NSView* child = [children objectAtIndex:i]; + [child setFrameOrigin:NSMakePoint([child frame].origin.x, yPosition)]; + yPosition += [child frame].size.height; + } + + // Resize self to reflect vertical extent of children. + [self setFrame:NSMakeRect([self frame].origin.x, + [self frame].origin.y, + [self frame].size.width, + yPosition)]; +} + +@end |