diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-09 23:23:07 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-09 23:23:07 +0000 |
commit | 2b0693fee3d1211723b461b9adb78a49d00699cc (patch) | |
tree | 7308e307fbf915d164a6a0bdb4cf94cc78a1499f | |
parent | f5a723719c2df2ba09915e6afcf1d54c5e445fa0 (diff) | |
download | chromium_src-2b0693fee3d1211723b461b9adb78a49d00699cc.zip chromium_src-2b0693fee3d1211723b461b9adb78a49d00699cc.tar.gz chromium_src-2b0693fee3d1211723b461b9adb78a49d00699cc.tar.bz2 |
Add "Use as default" checkboxes to the autofill dialogs on the Mac.
Nib change: in each nib, added a checkbox with the correct title and bindings to the file owner of enabled<=>canAlterDefault and value<=>isDefault
BUG=http://crbug.com/38263
TEST=as in bug
Review URL: http://codereview.chromium.org/1527022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44158 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 539 insertions, 41 deletions
diff --git a/chrome/app/nibs/AutoFillAddressFormView.xib b/chrome/app/nibs/AutoFillAddressFormView.xib index f0fad15..39ea924 100644 --- a/chrome/app/nibs/AutoFillAddressFormView.xib +++ b/chrome/app/nibs/AutoFillAddressFormView.xib @@ -3,7 +3,7 @@ <data> <int key="IBDocument.SystemTarget">1050</int> <string key="IBDocument.SystemVersion">9L31a</string> - <string key="IBDocument.InterfaceBuilderVersion">680</string> + <string key="IBDocument.InterfaceBuilderVersion">677</string> <string key="IBDocument.AppKitVersion">949.54</string> <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> @@ -700,6 +700,33 @@ <int key="NSPeriodicInterval">25</int> </object> </object> + <object class="NSButton" id="484404016"> + <reference key="NSNextResponder" ref="195575826"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{175, 350}, {240, 18}}</string> + <reference key="NSSuperview" ref="195575826"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="252380842"> + <int key="NSCellFlags">-2080244224</int> + <int key="NSCellFlags2">131072</int> + <string key="NSContents">^IDS_AUTOFILL_DIALOG_MAKE_DEFAULT</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="484404016"/> + <int key="NSButtonFlags">1211912703</int> + <int key="NSButtonFlags2">130</int> + <object class="NSCustomResource" key="NSNormalImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSSwitch</string> + </object> + <object class="NSButtonImageSource" key="NSAlternateImage"> + <string key="NSImageName">NSSwitch</string> + </object> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> </object> <string key="NSFrame">{{1, 1}, {482, 399}}</string> <reference key="NSSuperview" ref="556992356"/> @@ -1133,6 +1160,38 @@ </object> <int key="connectionID">217</int> </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">enabled: canAlterDefault</string> + <reference key="source" ref="484404016"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="484404016"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">enabled: canAlterDefault</string> + <string key="NSBinding">enabled</string> + <string key="NSKeyPath">canAlterDefault</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">221</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">value: isDefault</string> + <reference key="source" ref="484404016"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="484404016"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">value: isDefault</string> + <string key="NSBinding">value</string> + <string key="NSKeyPath">isDefault</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">223</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -1255,6 +1314,7 @@ <reference ref="467266453"/> <reference ref="115971484"/> <reference ref="164512976"/> + <reference ref="484404016"/> </object> <reference key="parent" ref="70311064"/> </object> @@ -1725,6 +1785,20 @@ <reference key="object" ref="787258833"/> <reference key="parent" ref="164512976"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">218</int> + <reference key="object" ref="484404016"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="252380842"/> + </object> + <reference key="parent" ref="556992356"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">219</int> + <reference key="object" ref="252380842"/> + <reference key="parent" ref="484404016"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -1749,6 +1823,8 @@ <string>21.IBPluginDependency</string> <string>215.IBPluginDependency</string> <string>216.IBPluginDependency</string> + <string>218.IBPluginDependency</string> + <string>219.IBPluginDependency</string> <string>22.CustomClassName</string> <string>22.IBPluginDependency</string> <string>23.IBPluginDependency</string> @@ -1849,6 +1925,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>AutoFillTextField</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -1952,7 +2030,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">217</int> + <int key="maxID">223</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -2024,6 +2102,13 @@ <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> + <string key="minorKey">../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> <string key="minorKey">browser/cocoa/status_bubble_mac.h</string> </object> </object> diff --git a/chrome/app/nibs/AutoFillCreditCardFormView.xib b/chrome/app/nibs/AutoFillCreditCardFormView.xib index 1b26ce6..34e6674 100644 --- a/chrome/app/nibs/AutoFillCreditCardFormView.xib +++ b/chrome/app/nibs/AutoFillCreditCardFormView.xib @@ -521,6 +521,33 @@ <int key="NSPeriodicInterval">25</int> </object> </object> + <object class="NSButton" id="953837558"> + <reference key="NSNextResponder" ref="1034866434"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{173, 248}, {240, 18}}</string> + <reference key="NSSuperview" ref="1034866434"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="183105156"> + <int key="NSCellFlags">-2080244224</int> + <int key="NSCellFlags2">131072</int> + <string key="NSContents">^IDS_AUTOFILL_DIALOG_MAKE_DEFAULT</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="953837558"/> + <int key="NSButtonFlags">1211912703</int> + <int key="NSButtonFlags2">130</int> + <object class="NSCustomResource" key="NSNormalImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSSwitch</string> + </object> + <object class="NSButtonImageSource" key="NSAlternateImage"> + <string key="NSImageName">NSSwitch</string> + </object> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> </object> <string key="NSFrame">{{1, 1}, {482, 297}}</string> <reference key="NSSuperview" ref="436522406"/> @@ -851,6 +878,38 @@ </object> <int key="connectionID">200</int> </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">enabled: canAlterDefault</string> + <reference key="source" ref="953837558"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="953837558"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">enabled: canAlterDefault</string> + <string key="NSBinding">enabled</string> + <string key="NSKeyPath">canAlterDefault</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">206</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBBindingConnection" key="connection"> + <string key="label">value: isDefault</string> + <reference key="source" ref="953837558"/> + <reference key="destination" ref="1001"/> + <object class="NSNibBindingConnector" key="connector"> + <reference key="NSSource" ref="953837558"/> + <reference key="NSDestination" ref="1001"/> + <string key="NSLabel">value: isDefault</string> + <string key="NSBinding">value</string> + <string key="NSKeyPath">isDefault</string> + <int key="NSNibBindingConnectorVersion">2</int> + </object> + </object> + <int key="connectionID">208</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -956,6 +1015,7 @@ <reference ref="731633316"/> <reference ref="289669180"/> <reference ref="415706256"/> + <reference ref="953837558"/> </object> <reference key="parent" ref="70311064"/> </object> @@ -1253,6 +1313,20 @@ <reference key="object" ref="632393829"/> <reference key="parent" ref="1002"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">201</int> + <reference key="object" ref="953837558"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="183105156"/> + </object> + <reference key="parent" ref="436522406"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">202</int> + <reference key="object" ref="183105156"/> + <reference key="parent" ref="953837558"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -1288,6 +1362,8 @@ <string>183.IBPluginDependency</string> <string>19.IBPluginDependency</string> <string>20.IBPluginDependency</string> + <string>201.IBPluginDependency</string> + <string>202.IBPluginDependency</string> <string>21.IBPluginDependency</string> <string>22.CustomClassName</string> <string>22.IBPluginDependency</string> @@ -1351,6 +1427,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>AutoFillTextField</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -1404,7 +1482,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">200</int> + <int key="maxID">208</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -1505,6 +1583,13 @@ <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> + <string key="minorKey">../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> <string key="minorKey">browser/cocoa/status_bubble_mac.h</string> </object> </object> diff --git a/chrome/browser/autofill/autofill_address_view_controller_mac.h b/chrome/browser/autofill/autofill_address_view_controller_mac.h index 2a1db94..cdbb899 100644 --- a/chrome/browser/autofill/autofill_address_view_controller_mac.h +++ b/chrome/browser/autofill/autofill_address_view_controller_mac.h @@ -31,13 +31,15 @@ class AutoFillProfile; AutoFillDialogController* parentController_; } +@property (readonly) BOOL canAlterDefault; +@property BOOL isDefault; @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 - disclosure:(NSCellStateValue)disclosureState - controller:(AutoFillDialogController*) parentController; + disclosure:(NSCellStateValue)disclosureState + controller:(AutoFillDialogController*) parentController; // Action to remove this address from the dialog. Forwards the request to // |parentController_| which does all the actual work. We have the action diff --git a/chrome/browser/autofill/autofill_address_view_controller_mac.mm b/chrome/browser/autofill/autofill_address_view_controller_mac.mm index aa77644..dcf8a12 100644 --- a/chrome/browser/autofill/autofill_address_view_controller_mac.mm +++ b/chrome/browser/autofill/autofill_address_view_controller_mac.mm @@ -8,17 +8,24 @@ #import "chrome/browser/autofill/autofill_address_model_mac.h" #import "chrome/browser/autofill/autofill_dialog_controller_mac.h" #include "chrome/browser/autofill/autofill_profile.h" +#import "third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h" + +@interface AutoFillAddressViewController (PrivateMethods) +- (void)labelChanged:(GTMKeyValueChangeNotification*)notification; +- (void)addressesChanged:(GTMKeyValueChangeNotification*)notification; +- (void)defaultChanged:(GTMKeyValueChangeNotification*)notification; +@end @implementation AutoFillAddressViewController @synthesize addressModel = addressModel_; - (id)initWithProfile:(const AutoFillProfile&)profile - disclosure:(NSCellStateValue)disclosureState - controller:(AutoFillDialogController*) parentController { + disclosure:(NSCellStateValue)disclosureState + controller:(AutoFillDialogController*) parentController { self = [super initWithNibName:@"AutoFillAddressFormView" - bundle:mac_util::MainAppBundle() - disclosure:disclosureState]; + bundle:mac_util::MainAppBundle() + disclosure:disclosureState]; if (self) { // Pull in the view for initialization. [self view]; @@ -32,32 +39,53 @@ // Register |self| as observer so we can notify parent controller. See // |observeValueForKeyPath:| for details. - [addressModel_ addObserver:self forKeyPath:@"label" - options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) - context:NULL]; + [addressModel_ gtm_addObserver:self + forKeyPath:@"label" + selector:@selector(labelChanged:) + userInfo:nil + options:0]; + [parentController_ gtm_addObserver:self + forKeyPath:@"addressLabels" + selector:@selector(addressesChanged:) + userInfo:nil + options:0]; + [parentController_ gtm_addObserver:self + forKeyPath:@"defaultAddressLabel" + selector:@selector(defaultChanged:) + userInfo:nil + options:0]; } return self; } - (void)dealloc { - [addressModel_ removeObserver:self forKeyPath:@"label"]; + [addressModel_ gtm_removeObserver:self + forKeyPath:@"label" + selector:@selector(labelChanged:)]; + [parentController_ gtm_removeObserver:self + forKeyPath:@"addressLabels" + selector:@selector(addressesChanged:)]; + [parentController_ gtm_removeObserver:self + forKeyPath:@"defaultAddressLabel" + selector:@selector(defaultChanged:)]; [addressModel_ release]; [super dealloc]; } // Override KVO method to notify parent controller when the address "label" // changes. Credit card UI updates accordingly. -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary*)change - context:(void *)context { - if ([keyPath isEqual:@"label"]) { - [parentController_ notifyAddressChange:self]; - } +- (void)labelChanged:(GTMKeyValueChangeNotification*)notification { + [parentController_ notifyAddressChange:self]; +} + +- (void)addressesChanged:(GTMKeyValueChangeNotification*)notification { + [self willChangeValueForKey:@"canAlterDefault"]; + [self didChangeValueForKey:@"canAlterDefault"]; +} - // Propagate KVO up to super. - [super observeValueForKeyPath:keyPath - ofObject:object change:change context:context]; +- (void)defaultChanged:(GTMKeyValueChangeNotification*)notification { + [self willChangeValueForKey:@"isDefault"]; + [self didChangeValueForKey:@"isDefault"]; } - (IBAction)deleteAddress:(id)sender { @@ -68,6 +96,19 @@ [addressModel_ copyModelToProfile:profile]; } +- (BOOL)canAlterDefault { + return [[parentController_ addressLabels] count] > 1; +} + +- (BOOL)isDefault { + return + [[addressModel_ label] isEqual:[parentController_ defaultAddressLabel]]; +} + +- (void)setIsDefault:(BOOL)def { + [parentController_ setDefaultAddressLabel:def ? [addressModel_ label] : nil]; +} + @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 index c836176..ba62e7a 100644 --- a/chrome/browser/autofill/autofill_credit_card_view_controller_mac.h +++ b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.h @@ -44,6 +44,8 @@ class CreditCard; AutoFillDialogController* parentController_; } +@property (readonly) BOOL canAlterDefault; +@property BOOL isDefault; @property (nonatomic, retain) AutoFillCreditCardModel* creditCardModel; @property (nonatomic, retain) NSArray* billingAddressContents; @property (nonatomic, retain) NSArray* shippingAddressContents; @@ -51,8 +53,8 @@ class CreditCard; // Designated initializer. Takes a copy of the data in |creditCard|, // it is not held as a reference. - (id)initWithCreditCard:(const CreditCard&)creditCard - disclosure:(NSCellStateValue)disclosureState - controller:(AutoFillDialogController*)parentController; + disclosure:(NSCellStateValue)disclosureState + controller:(AutoFillDialogController*)parentController; // Action to remove this credit card from the dialog. Forwards the request to // |parentController_| which does all the actual work. We have the action diff --git a/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm index 026c661..0151869 100644 --- a/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm +++ b/chrome/browser/autofill/autofill_credit_card_view_controller_mac.mm @@ -10,11 +10,14 @@ #import "chrome/browser/autofill/autofill_dialog_controller_mac.h" #include "chrome/browser/autofill/credit_card.h" #include "grit/generated_resources.h" +#import "third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h" // Private methods for the |AutoFillCreditCardViewController| class. @interface AutoFillCreditCardViewController (PrivateMethods) - (void)rebuildBillingAddressContents; - (void)rebuildShippingAddressContents; +- (void)creditCardsChanged:(GTMKeyValueChangeNotification*)notification; +- (void)defaultChanged:(GTMKeyValueChangeNotification*)notification; @end @implementation AutoFillCreditCardViewController @@ -24,11 +27,11 @@ @synthesize shippingAddressContents = shippingAddressContents_; - (id)initWithCreditCard:(const CreditCard&)creditCard - disclosure:(NSCellStateValue)disclosureState - controller:(AutoFillDialogController*)parentController { + disclosure:(NSCellStateValue)disclosureState + controller:(AutoFillDialogController*)parentController { self = [super initWithNibName:@"AutoFillCreditCardFormView" - bundle:mac_util::MainAppBundle() - disclosure:disclosureState]; + bundle:mac_util::MainAppBundle() + disclosure:disclosureState]; if (self) { // Pull in the view for initialization. [self view]; @@ -42,11 +45,28 @@ // Setup initial state of popups. [self onAddressesChanged:self]; + + [parentController_ gtm_addObserver:self + forKeyPath:@"creditCardLabels" + selector:@selector(creditCardsChanged:) + userInfo:nil + options:0]; + [parentController_ gtm_addObserver:self + forKeyPath:@"defaultCreditCardLabel" + selector:@selector(defaultChanged:) + userInfo:nil + options:0]; } return self; } - (void)dealloc { + [parentController_ gtm_removeObserver:self + forKeyPath:@"creditCardLabels" + selector:@selector(creditCardsChanged:)]; + [parentController_ gtm_removeObserver:self + forKeyPath:@"defaultCreditCardLabel" + selector:@selector(defaultChanged:)]; [creditCardModel_ release]; [billingAddressContents_ release]; [shippingAddressContents_ release]; @@ -81,9 +101,29 @@ creditCard->set_shipping_address(string16()); } -@end +- (void)creditCardsChanged:(GTMKeyValueChangeNotification*)notification { + [self willChangeValueForKey:@"canAlterDefault"]; + [self didChangeValueForKey:@"canAlterDefault"]; +} + +- (void)defaultChanged:(GTMKeyValueChangeNotification*)notification { + [self willChangeValueForKey:@"isDefault"]; + [self didChangeValueForKey:@"isDefault"]; +} -@implementation AutoFillCreditCardViewController (PrivateMethods) +- (BOOL)canAlterDefault { + return [[parentController_ creditCardLabels] count] > 1; +} + +- (BOOL)isDefault { + return [[creditCardModel_ label] isEqual: + [parentController_ defaultCreditCardLabel]]; +} + +- (void)setIsDefault:(BOOL)def { + [parentController_ setDefaultCreditCardLabel: + def ? [creditCardModel_ label] : nil]; +} // Builds the |billingAddressContents_| array of strings from the list of // addresses returned by the |parentController_| and additional UI string. @@ -93,7 +133,7 @@ IDS_AUTOFILL_DIALOG_CHOOSE_EXISTING_ADDRESS); // Build the menu array and set it. - NSArray* addressStrings = [parentController_ addressStrings]; + NSArray* addressStrings = [parentController_ addressLabels]; NSArray* newArray = [[NSArray arrayWithObject:menuString] arrayByAddingObjectsFromArray:addressStrings]; [self setBillingAddressContents:newArray]; @@ -116,7 +156,7 @@ IDS_AUTOFILL_DIALOG_SAME_AS_BILLING); // Build the menu array and set it. - NSArray* addressStrings = [parentController_ addressStrings]; + NSArray* addressStrings = [parentController_ addressLabels]; NSArray* newArray = [[NSArray arrayWithObject:menuString] arrayByAddingObjectsFromArray:addressStrings]; [self setShippingAddressContents:newArray]; diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.h b/chrome/browser/autofill/autofill_dialog_controller_mac.h index 3f60b3c..1d90836e 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.h +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.h @@ -29,7 +29,7 @@ class Profile; IBOutlet NSView* creditCardSection_; // Note on ownership: the controllers are strongly owned by the dialog - // controller. Their views are inserted into the dialog's view hierarcy + // controller. Their views are inserted into the dialog's view hierarchy // but are retained by these controllers as well. // Array of |AutoFillAddressViewController|. @@ -38,6 +38,9 @@ class Profile; // Array of |AutoFillCreditCardViewController|. scoped_nsobject<NSMutableArray> creditCardFormViewControllers_; + scoped_nsobject<NSString> defaultAddressLabel_; + scoped_nsobject<NSString> defaultCreditCardLabel_; + AutoFillDialogObserver* observer_; // Weak, not retained. std::vector<AutoFillProfile> profiles_; std::vector<CreditCard> creditCards_; @@ -50,6 +53,10 @@ class Profile; // bound to this in nib. @property (nonatomic) BOOL auxiliaryEnabled; +// Property representing the default profile and credit card. +@property (nonatomic, copy) NSString* defaultAddressLabel; +@property (nonatomic, copy) NSString* defaultCreditCardLabel; + // 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. @@ -81,9 +88,13 @@ class Profile; // IBAction for sender to alert dialog that an address label has changed. - (IBAction)notifyAddressChange:(id)sender; -// Returns an array of strings representing the addresses in the +// Returns an array of labels representing the addresses in the // |addressFormViewControllers_|. -- (NSArray*)addressStrings; +- (NSArray*)addressLabels; + +// Returns an array of labels representing the credit cards in the +// |creditCardFormViewControllers_|. +- (NSArray*)creditCardLabels; @end diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm index 775274f..2618044 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm @@ -5,6 +5,7 @@ #import "chrome/browser/autofill/autofill_dialog_controller_mac.h" #include "app/l10n_util.h" #include "base/mac_util.h" +#include "base/sys_string_conversions.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" @@ -51,6 +52,9 @@ // NSWindow Delegate callback. When the window closes the controller can // be released. - (void)windowWillClose:(NSNotification *)notification { + // Force views to go away so they properly remove their observations. + addressFormViewControllers_.reset(); + creditCardFormViewControllers_.reset(); [self autorelease]; } @@ -85,6 +89,13 @@ } profile_->GetPrefs()->SetBoolean(prefs::kAutoFillAuxiliaryProfilesEnabled, auxiliaryEnabled_); + // Make sure to use accessors here to save what the user sees. + profile_->GetPrefs()->SetString( + prefs::kAutoFillDefaultProfile, + base::SysNSStringToWide([self defaultAddressLabel])); + profile_->GetPrefs()->SetString( + prefs::kAutoFillDefaultCreditCard, + base::SysNSStringToWide([self defaultCreditCardLabel])); observer_->OnAutoFillDialogApply(&profiles_, &creditCards_); } [self closeDialog]; @@ -118,7 +129,12 @@ initWithProfile:newProfile disclosure:NSOnState controller:self]); + [self willChangeValueForKey:@"addressLabels"]; [addressFormViewControllers_.get() addObject:addressViewController]; + [self didChangeValueForKey:@"addressLabels"]; + // Might need to reset the default if added. + [self willChangeValueForKey:@"defaultAddressLabel"]; + [self didChangeValueForKey:@"defaultAddressLabel"]; // Embed the new address into our target view. [childView_ addSubview:[addressViewController view] @@ -153,7 +169,12 @@ initWithCreditCard:newCreditCard disclosure:NSOnState controller:self]); + [self willChangeValueForKey:@"creditCardLabels"]; [creditCardFormViewControllers_.get() addObject:creditCardViewController]; + [self didChangeValueForKey:@"creditCardLabels"]; + // Might need to reset the default if added. + [self willChangeValueForKey:@"defaultCreditCardLabel"]; + [self didChangeValueForKey:@"defaultCreditCardLabel"]; // Embed the new address into our target view. [childView_ addSubview:[creditCardViewController view] @@ -174,7 +195,12 @@ // controller which in-turn decrement refcount of view. Both should dealloc // at this point. [[sender view] removeFromSuperview]; + [self willChangeValueForKey:@"addressLabels"]; [addressFormViewControllers_.get() removeObjectAtIndex:i]; + [self didChangeValueForKey:@"addressLabels"]; + // Might need to reset the default if deleted. + [self willChangeValueForKey:@"defaultAddressLabel"]; + [self didChangeValueForKey:@"defaultAddressLabel"]; [self notifyAddressChange:self]; @@ -192,7 +218,12 @@ // controller which in-turn decrement refcount of view. Both should dealloc // at this point. [[sender view] removeFromSuperview]; + [self willChangeValueForKey:@"creditCardLabels"]; [creditCardFormViewControllers_.get() removeObjectAtIndex:i]; + [self didChangeValueForKey:@"creditCardLabels"]; + // Might need to reset the default if deleted. + [self willChangeValueForKey:@"defaultCreditCardLabel"]; + [self didChangeValueForKey:@"defaultCreditCardLabel"]; // Recalculate key view loop to account for change in view tree. [[self window] recalculateKeyViewLoop]; @@ -207,9 +238,7 @@ } } -// Returns an array of strings representing the addresses in the -// |addressFormViewControllers_|. -- (NSArray*)addressStrings { +- (NSArray*)addressLabels { NSUInteger capacity = [addressFormViewControllers_ count]; NSMutableArray* array = [NSMutableArray arrayWithCapacity:capacity]; @@ -221,6 +250,116 @@ return array; } +- (NSArray*)creditCardLabels { + NSUInteger capacity = [creditCardFormViewControllers_ count]; + NSMutableArray* array = [NSMutableArray arrayWithCapacity:capacity]; + + for (AutoFillCreditCardViewController* creditCardFormViewController in + creditCardFormViewControllers_.get()) { + [array addObject:[[creditCardFormViewController creditCardModel] label]]; + } + + return array; +} + +- (NSString*)defaultAddressLabel { + NSArray* labels = [self addressLabels]; + NSString* def = defaultAddressLabel_.get(); + if ([def length] && [labels containsObject:def]) + return def; + + // No valid default; pick the first item. + if ([labels count]) { + return [labels objectAtIndex:0]; + } else { + return @""; + } +} + +- (void)setDefaultAddressLabel:(NSString*)label { + if (!label) { + // Setting nil means the user un-checked an item. Find a new default. + NSUInteger itemCount = [addressFormViewControllers_ count]; + if (itemCount == 0) { + DCHECK(false) << "Attempt to set default when there are no items."; + return; + } else if (itemCount == 1) { + DCHECK(false) << "Attempt to set default when there is only one item, so " + "it should have been disabled."; + AutoFillAddressViewController* controller = + [addressFormViewControllers_ objectAtIndex:0]; + label = [[controller addressModel] label]; + } else { + AutoFillAddressViewController* controller = + [addressFormViewControllers_ objectAtIndex:0]; + NSString* firstItemsLabel = [[controller addressModel] label]; + + // If they unchecked an item that wasn't the first item, make the first + // item default. + if (![defaultAddressLabel_ isEqual:firstItemsLabel]) { + label = firstItemsLabel; + } else { + // Otherwise they unchecked the first item. Pick the second one for 'em. + AutoFillAddressViewController* controller = + [addressFormViewControllers_ objectAtIndex:1]; + label = [[controller addressModel] label]; + } + } + } + + defaultAddressLabel_.reset([label copy]); + return; +} + +- (NSString*)defaultCreditCardLabel { + NSArray* labels = [self creditCardLabels]; + NSString* def = defaultCreditCardLabel_.get(); + if ([def length] && [labels containsObject:def]) + return def; + + // No valid default; pick the first item. + if ([labels count]) { + return [labels objectAtIndex:0]; + } else { + return @""; + } +} + +- (void)setDefaultCreditCardLabel:(NSString*)label { + if (!label) { + // Setting nil means the user un-checked an item. Find a new default. + NSUInteger itemCount = [creditCardFormViewControllers_ count]; + if (itemCount == 0) { + DCHECK(false) << "Attempt to set default when there are no items."; + return; + } else if (itemCount == 1) { + DCHECK(false) << "Attempt to set default when there is only one item, so " + "it should have been disabled."; + AutoFillCreditCardViewController* controller = + [creditCardFormViewControllers_ objectAtIndex:0]; + label = [[controller creditCardModel] label]; + } else { + AutoFillCreditCardViewController* controller = + [creditCardFormViewControllers_ objectAtIndex:0]; + NSString* firstItemsLabel = [[controller creditCardModel] label]; + + // If they unchecked an item that wasn't the first item, make the first + // item default. + if (![defaultCreditCardLabel_ isEqual:firstItemsLabel]) { + label = firstItemsLabel; + } else { + // Otherwise they unchecked the first item. Pick the second one for 'em. + AutoFillCreditCardViewController* controller = + [creditCardFormViewControllers_ objectAtIndex:1]; + label = [[controller creditCardModel] label]; + } + } + } + + defaultCreditCardLabel_.reset([label copy]); + return; +} + @end @implementation AutoFillDialogController (ExposedForUnitTests) @@ -273,11 +412,25 @@ [self setAuxiliaryEnabled:profile_->GetPrefs()->GetBoolean( prefs::kAutoFillAuxiliaryProfilesEnabled)]; + // Do not use [NSMutableArray array] here; we need predictable destruction + // which will be prevented by having a reference held by an autorelease + // pool. + // Initialize array of sub-controllers. - addressFormViewControllers_.reset([[NSMutableArray array] retain]); + addressFormViewControllers_.reset( + [[NSMutableArray alloc] initWithCapacity:0]); // Initialize array of sub-controllers. - creditCardFormViewControllers_.reset([[NSMutableArray array] retain]); + creditCardFormViewControllers_.reset( + [[NSMutableArray alloc] initWithCapacity:0]); + + NSString* defaultAddressLabel = base::SysWideToNSString( + profile_->GetPrefs()->GetString(prefs::kAutoFillDefaultProfile)); + defaultAddressLabel_.reset([defaultAddressLabel retain]); + + NSString* defaultCreditCardLabel = base::SysWideToNSString( + profile_->GetPrefs()->GetString(prefs::kAutoFillDefaultCreditCard)); + defaultCreditCardLabel_.reset([defaultCreditCardLabel retain]); } return self; } @@ -330,7 +483,9 @@ initWithProfile:profiles_[i] disclosure:disclosureState controller:self]); + [self willChangeValueForKey:@"addressLabels"]; [addressFormViewControllers_.get() addObject:addressViewController]; + [self didChangeValueForKey:@"addressLabels"]; // Embed the child view into our (owned by us) target view. [childView_ addSubview:[addressViewController view] @@ -346,7 +501,9 @@ initWithCreditCard:creditCards_[i] disclosure:NSOffState controller:self]); + [self willChangeValueForKey:@"creditCardLabels"]; [creditCardFormViewControllers_.get() addObject:creditCardViewController]; + [self didChangeValueForKey:@"creditCardLabels"]; // Embed the child view into our (owned by us) target view. [childView_ addSubview:[creditCardViewController view] @@ -354,6 +511,13 @@ insertionPoint = [creditCardViewController view]; [[creditCardViewController view] setFrameOrigin:NSMakePoint(0, 0)]; } + + // During initialization the default accessors were returning faulty values + // since the controller arrays weren't set up. Poke our observers. + [self willChangeValueForKey:@"defaultAddressLabel"]; + [self didChangeValueForKey:@"defaultAddressLabel"]; + [self willChangeValueForKey:@"defaultCreditCardLabel"]; + [self didChangeValueForKey:@"defaultCreditCardLabel"]; } @end diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm index ca2ee93..0022862 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac_unittest.mm @@ -437,4 +437,70 @@ TEST_F(AutoFillDialogControllerTest, AuxiliaryProfilesChanged) { prefs::kAutoFillAuxiliaryProfilesEnabled)); } +TEST_F(AutoFillDialogControllerTest, DefaultsChangingLogic) { + // Two profiles, two credit cards. + AutoFillProfile profile(ASCIIToUTF16("One"), 1); + profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Joe")); + profiles_.push_back(&profile); + AutoFillProfile profile2(ASCIIToUTF16("Two"), 2); + profile2.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Bob")); + profiles_.push_back(&profile2); + CreditCard credit_card(ASCIIToUTF16("Visa"), 1); + credit_card.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Joe")); + credit_cards_.push_back(&credit_card); + CreditCard credit_card2(ASCIIToUTF16("Mastercard"), 2); + credit_card2.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Bob")); + credit_cards_.push_back(&credit_card2); + + // Invalid defaults for each. + helper_.profile()->GetPrefs()->SetString( + prefs::kAutoFillDefaultProfile, L"xxxx"); + helper_.profile()->GetPrefs()->SetString( + prefs::kAutoFillDefaultCreditCard, L"yyyy"); + + // Start 'em up. + LoadDialog(); + + // With invalid default values, the first item should be the default. + EXPECT_TRUE([[controller_ defaultAddressLabel] isEqualToString:@"One"]); + EXPECT_TRUE([[controller_ defaultCreditCardLabel] isEqualToString:@"Visa"]); + + // Explicitly set the second to be default and make sure it sticks. + [controller_ setDefaultAddressLabel:@"Two"]; + [controller_ setDefaultCreditCardLabel:@"Mastercard"]; + ASSERT_TRUE([[controller_ defaultAddressLabel] isEqualToString:@"Two"]); + ASSERT_TRUE([[controller_ defaultCreditCardLabel] + isEqualToString:@"Mastercard"]); + + // Deselect the second and the first should become default. + [controller_ setDefaultAddressLabel:nil]; + [controller_ setDefaultCreditCardLabel:nil]; + ASSERT_TRUE([[controller_ defaultAddressLabel] isEqualToString:@"One"]); + ASSERT_TRUE([[controller_ defaultCreditCardLabel] isEqualToString:@"Visa"]); + + // Deselect the first and the second should be come default. + [controller_ setDefaultAddressLabel:nil]; + [controller_ setDefaultCreditCardLabel:nil]; + ASSERT_TRUE([[controller_ defaultAddressLabel] isEqualToString:@"Two"]); + ASSERT_TRUE([[controller_ defaultCreditCardLabel] + isEqualToString:@"Mastercard"]); + + // Delete the second and the first should end up as default. + [controller_ deleteAddress:[[controller_ addressFormViewControllers] + lastObject]]; + [controller_ deleteCreditCard:[[controller_ creditCardFormViewControllers] + lastObject]]; + ASSERT_TRUE([[controller_ defaultAddressLabel] isEqualToString:@"One"]); + ASSERT_TRUE([[controller_ defaultCreditCardLabel] isEqualToString:@"Visa"]); + + // Save and that should end up in the prefs. + [controller_ save:nil]; + ASSERT_TRUE(observer_.hit_); + + ASSERT_EQ(L"One", helper_.profile()->GetPrefs()-> + GetString(prefs::kAutoFillDefaultProfile)); + ASSERT_EQ(L"Visa", helper_.profile()->GetPrefs()-> + GetString(prefs::kAutoFillDefaultCreditCard)); +} + } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 7545f735..a84f164 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2588,6 +2588,8 @@ '../third_party/GTM/AppKit/GTMNSAnimation+Duration.h', '../third_party/GTM/Foundation/GTMNSNumber+64Bit.h', '../third_party/GTM/Foundation/GTMNSNumber+64Bit.m', + '../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h', + '../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.m', # Build necessary Mozilla sources '../third_party/mozilla/include/NSPasteboard+Utils.h', '../third_party/mozilla/include/NSPasteboard+Utils.mm', |