Commit 3d14d788 authored by Moe Ahmadi's avatar Moe Ahmadi Committed by Commit Bot

[AF][IOS] Add fine-grained profile & credit card toggles to Autofill settings

screenshot: https://drive.google.com/open?id=1td8sD7YO_VwIlY8WTW5xRc4es7bOslxu

Bug: 860526
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I9d2f1a589d9ae1bb5bac45c04ceb973f88385a84
Reviewed-on: https://chromium-review.googlesource.com/1145484
Commit-Queue: Moe Ahmadi <mahmadi@chromium.org>
Reviewed-by: default avataredchin <edchin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577697}
parent 586af386
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/browser/personal_data_manager_observer.h"
// PersonalDataManagerObserverBridgeDelegate is used by PersonalDataManager to // PersonalDataManagerObserver is used by PersonalDataManager to informs its
// informs its client implemented in Objective-C when it has finished loading // client implemented in Objective-C when it has finished loading personal data
// personal data from the web database. // from the web database.
@protocol PersonalDataManagerObserverBridgeDelegate<NSObject> @protocol PersonalDataManagerObserver<NSObject>
// Called when the PersonalDataManager changed in some way. // Called when the PersonalDataManager changed in some way.
- (void)onPersonalDataChanged; - (void)onPersonalDataChanged;
...@@ -32,7 +32,7 @@ namespace autofill { ...@@ -32,7 +32,7 @@ namespace autofill {
class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver { class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver {
public: public:
explicit PersonalDataManagerObserverBridge( explicit PersonalDataManagerObserverBridge(
id<PersonalDataManagerObserverBridgeDelegate> delegate); id<PersonalDataManagerObserver> delegate);
~PersonalDataManagerObserverBridge() override; ~PersonalDataManagerObserverBridge() override;
// PersonalDataManagerObserver implementation. // PersonalDataManagerObserver implementation.
...@@ -40,7 +40,7 @@ class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver { ...@@ -40,7 +40,7 @@ class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver {
void OnInsufficientFormData() override; void OnInsufficientFormData() override;
private: private:
__unsafe_unretained id<PersonalDataManagerObserverBridgeDelegate> delegate_; __weak id<PersonalDataManagerObserver> delegate_;
DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerObserverBridge); DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerObserverBridge);
}; };
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
namespace autofill { namespace autofill {
PersonalDataManagerObserverBridge::PersonalDataManagerObserverBridge( PersonalDataManagerObserverBridge::PersonalDataManagerObserverBridge(
id<PersonalDataManagerObserverBridgeDelegate> delegate) id<PersonalDataManagerObserver> delegate)
: delegate_(delegate) { : delegate_(delegate) {
DCHECK(delegate_); DCHECK(delegate_);
} }
......
...@@ -222,6 +222,12 @@ locale. The strings in this file are specific to iOS. ...@@ -222,6 +222,12 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_AUTOFILL" desc="Title for the view in Settings for enabling/disabling Autofill. [Length: 15em] [iOS only]"> <message name="IDS_IOS_AUTOFILL" desc="Title for the view in Settings for enabling/disabling Autofill. [Length: 15em] [iOS only]">
Autofill Forms Autofill Forms
</message> </message>
<message name="IDS_IOS_ENABLE_AUTOFILL_PROFILES" desc="Title for the the toggle in Autofill Settings for enabling/disabling Autofill Addresses. Title case. [Length: unlimited] [iOS only]">
Save and Fill Addresses
</message>
<message name="IDS_IOS_ENABLE_AUTOFILL_CREDIT_CARDS" desc="Title for the toggle in Autofill Settings for enabling/disabling Autofill Credit Cards. Title case. [Length: unlimited] [iOS only]">
Save and Fill Credit Cards
</message>
<message name="IDS_IOS_AUTOFILL_ACCNAME_HIDE_KEYBOARD" desc="The accessible name for the hide keyboard button in the keyboard accessory shown when filling out forms. [Length: unlimited] [iOS only]"> <message name="IDS_IOS_AUTOFILL_ACCNAME_HIDE_KEYBOARD" desc="The accessible name for the hide keyboard button in the keyboard accessory shown when filling out forms. [Length: unlimited] [iOS only]">
Hide keyboard Hide keyboard
</message> </message>
......
...@@ -373,6 +373,8 @@ source_set("eg_tests") { ...@@ -373,6 +373,8 @@ source_set("eg_tests") {
":settings", ":settings",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//components/autofill/core/browser",
"//components/autofill/core/browser:test_support",
"//components/autofill/core/common", "//components/autofill/core/common",
"//components/browser_sync", "//components/browser_sync",
"//components/browsing_data/core", "//components/browsing_data/core",
...@@ -389,6 +391,7 @@ source_set("eg_tests") { ...@@ -389,6 +391,7 @@ source_set("eg_tests") {
"//ios/chrome/app/strings", "//ios/chrome/app/strings",
"//ios/chrome/app/theme", "//ios/chrome/app/theme",
"//ios/chrome/browser", "//ios/chrome/browser",
"//ios/chrome/browser/autofill",
"//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state",
"//ios/chrome/browser/browsing_data:feature_flags", "//ios/chrome/browser/browsing_data:feature_flags",
"//ios/chrome/browser/content_settings", "//ios/chrome/browser/content_settings",
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/personal_data_manager.h"
...@@ -39,6 +40,8 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) { ...@@ -39,6 +40,8 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
typedef NS_ENUM(NSInteger, ItemType) { typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeAutofillSwitch = kItemTypeEnumZero, ItemTypeAutofillSwitch = kItemTypeEnumZero,
ItemTypeAutofillAddressSwitch,
ItemTypeAutofillCardSwitch,
ItemTypeAddress, ItemTypeAddress,
ItemTypeCard, ItemTypeCard,
ItemTypeHeader, ItemTypeHeader,
...@@ -48,23 +51,27 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -48,23 +51,27 @@ typedef NS_ENUM(NSInteger, ItemType) {
#pragma mark - AutofillCollectionViewController #pragma mark - AutofillCollectionViewController
@interface AutofillCollectionViewController ()< @interface AutofillCollectionViewController ()<PersonalDataManagerObserver> {
PersonalDataManagerObserverBridgeDelegate> {
std::string _locale; // User locale. std::string _locale; // User locale.
autofill::PersonalDataManager* _personalDataManager; autofill::PersonalDataManager* _personalDataManager;
ios::ChromeBrowserState* _browserState; ios::ChromeBrowserState* _browserState;
std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer; std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer;
BOOL _deletionInProgress;
// Writing user-initiated switch state changes to the pref service results in // Deleting profiles and credit cards updates PersonalDataManager resulting in
// an observer callback, which handles general data updates with a reloadData. // an observer callback, which handles general data updates with a reloadData.
// It is better to handle user-initiated changes with more specific actions // It is better to handle user-initiated changes with more specific actions
// such as inserting or removing items/sections. This boolean is used to // such as inserting or removing items/sections. This boolean is used to
// stop the observer callback from acting on user-initiated changes. // stop the observer callback from acting on user-initiated changes.
BOOL _userInteractionInProgress; BOOL _deletionInProgress;
} }
@property(nonatomic, getter=isAutofillEnabled) BOOL autofillEnabled;
@property(nonatomic, getter=isAutofillProfileEnabled)
BOOL autofillProfileEnabled;
@property(nonatomic, getter=isAutofillCreditCardEnabled)
BOOL autofillCreditCardEnabled;
@end @end
@implementation AutofillCollectionViewController @implementation AutofillCollectionViewController
...@@ -106,11 +113,13 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -106,11 +113,13 @@ typedef NS_ENUM(NSInteger, ItemType) {
[model addSectionWithIdentifier:SectionIdentifierSwitches]; [model addSectionWithIdentifier:SectionIdentifierSwitches];
[model addItem:[self autofillSwitchItem] [model addItem:[self autofillSwitchItem]
toSectionWithIdentifier:SectionIdentifierSwitches]; toSectionWithIdentifier:SectionIdentifierSwitches];
[model addItem:[self addressSwitchItem]
toSectionWithIdentifier:SectionIdentifierSwitches];
[model addItem:[self cardSwitchItem]
toSectionWithIdentifier:SectionIdentifierSwitches];
if ([self isAutofillEnabled]) { [self populateProfileSection];
[self populateProfileSection]; [self populateCardSection];
[self populateCardSection];
}
} }
#pragma mark - LoadModel Helpers #pragma mark - LoadModel Helpers
...@@ -158,6 +167,25 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -158,6 +167,25 @@ typedef NS_ENUM(NSInteger, ItemType) {
return switchItem; return switchItem;
} }
- (CollectionViewItem*)addressSwitchItem {
SettingsSwitchItem* switchItem =
[[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillAddressSwitch];
switchItem.text = l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_PROFILES);
switchItem.on = [self isAutofillProfileEnabled];
switchItem.accessibilityIdentifier = @"addressItem_switch";
return switchItem;
}
- (CollectionViewItem*)cardSwitchItem {
SettingsSwitchItem* switchItem =
[[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillCardSwitch];
switchItem.text =
l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_CREDIT_CARDS);
switchItem.on = [self isAutofillCreditCardEnabled];
switchItem.accessibilityIdentifier = @"cardItem_switch";
return switchItem;
}
- (CollectionViewItem*)profileSectionHeader { - (CollectionViewItem*)profileSectionHeader {
SettingsTextItem* header = [self genericHeader]; SettingsTextItem* header = [self genericHeader];
header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME); header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME);
...@@ -229,7 +257,7 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -229,7 +257,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
#pragma mark - SettingsRootCollectionViewController #pragma mark - SettingsRootCollectionViewController
- (BOOL)shouldShowEditButton { - (BOOL)shouldShowEditButton {
return [self isAutofillEnabled]; return YES;
} }
- (BOOL)editButtonEnabled { - (BOOL)editButtonEnabled {
...@@ -246,41 +274,56 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -246,41 +274,56 @@ typedef NS_ENUM(NSInteger, ItemType) {
ItemType itemType = static_cast<ItemType>( ItemType itemType = static_cast<ItemType>(
[self.collectionViewModel itemTypeForIndexPath:indexPath]); [self.collectionViewModel itemTypeForIndexPath:indexPath]);
if (itemType == ItemTypeAutofillSwitch) { if (![cell isKindOfClass:[SettingsSwitchCell class]])
SettingsSwitchCell* switchCell = return cell;
base::mac::ObjCCastStrict<SettingsSwitchCell>(cell);
[switchCell.switchView addTarget:self SEL action = nil;
action:@selector(autofillSwitchChanged:) switch (itemType) {
forControlEvents:UIControlEventValueChanged]; case ItemTypeAutofillSwitch:
action = @selector(autofillSwitchChanged:);
break;
case ItemTypeAutofillAddressSwitch:
action = @selector(autofillAddressSwitchChanged:);
break;
case ItemTypeAutofillCardSwitch:
action = @selector(autofillCardSwitchChanged:);
break;
default:
NOTREACHED() << "Unknown Switch cell item type.";
break;
} }
SettingsSwitchCell* switchCell =
base::mac::ObjCCastStrict<SettingsSwitchCell>(cell);
[switchCell.switchView addTarget:self
action:action
forControlEvents:UIControlEventValueChanged];
return cell; return cell;
} }
#pragma mark - Switch Callbacks #pragma mark - Switch Callbacks
- (void)autofillSwitchChanged:(UISwitch*)switchView { - (void)autofillSwitchChanged:(UISwitch*)switchView {
[self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillSwitch]; BOOL switchIsOn = [switchView isOn];
_userInteractionInProgress = YES; [self setSwitchItemOn:switchIsOn itemType:ItemTypeAutofillSwitch];
[self setAutofillEnabled:[switchView isOn]]; [self setAutofillEnabled:switchIsOn];
_userInteractionInProgress = NO; [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillAddressSwitch];
[self updateEditButton]; [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillCardSwitch];
if (switchIsOn) {
[self autofillAddressSwitchChanged:switchView];
[self autofillCardSwitchChanged:switchView];
}
}
// Avoid reference cycle in block. - (void)autofillAddressSwitchChanged:(UISwitch*)switchView {
__weak AutofillCollectionViewController* weakSelf = self; [self setSwitchItemOn:[switchView isOn]
[self.collectionView performBatchUpdates:^{ itemType:ItemTypeAutofillAddressSwitch];
// Obtain strong reference again. [self setAutofillProfileEnabled:[switchView isOn]];
AutofillCollectionViewController* strongSelf = weakSelf; }
if (!strongSelf) {
return;
}
if ([switchView isOn]) { - (void)autofillCardSwitchChanged:(UISwitch*)switchView {
[strongSelf insertProfileAndCardSections]; [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch];
} else { [self setAutofillCreditCardEnabled:[switchView isOn]];
[strongSelf removeProfileAndCardSections];
}
}
completion:nil];
} }
#pragma mark - Switch Helpers #pragma mark - Switch Helpers
...@@ -317,59 +360,15 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -317,59 +360,15 @@ typedef NS_ENUM(NSInteger, ItemType) {
[self reconfigureCellsForItems:@[ switchItem ]]; [self reconfigureCellsForItems:@[ switchItem ]];
} }
#pragma mark - Insert or Delete Items and Sections
- (void)insertProfileAndCardSections {
[self populateProfileSection];
[self populateCardSection];
NSIndexSet* sections = [self indexSetForExistingProfileAndCardSections];
[self.collectionView insertSections:sections];
}
- (void)removeProfileAndCardSections {
// It is important to build the section indexSet before removing sections.
NSIndexSet* sections = [self indexSetForExistingProfileAndCardSections];
if ([self.collectionViewModel
hasSectionForSectionIdentifier:SectionIdentifierProfiles]) {
[self.collectionViewModel
removeSectionWithIdentifier:SectionIdentifierProfiles];
}
if ([self.collectionViewModel
hasSectionForSectionIdentifier:SectionIdentifierCards]) {
[self.collectionViewModel
removeSectionWithIdentifier:SectionIdentifierCards];
}
[self.collectionView deleteSections:sections];
}
- (NSIndexSet*)indexSetForExistingProfileAndCardSections {
NSMutableIndexSet* sections = [[NSMutableIndexSet alloc] init];
if ([self.collectionViewModel
hasSectionForSectionIdentifier:SectionIdentifierProfiles]) {
[sections
addIndex:[self.collectionViewModel
sectionForSectionIdentifier:SectionIdentifierProfiles]];
}
if ([self.collectionViewModel
hasSectionForSectionIdentifier:SectionIdentifierCards]) {
[sections addIndex:[self.collectionViewModel
sectionForSectionIdentifier:SectionIdentifierCards]];
}
return sections;
}
#pragma mark - MDCCollectionViewStylingDelegate #pragma mark - MDCCollectionViewStylingDelegate
- (CGFloat)collectionView:(UICollectionView*)collectionView - (CGFloat)collectionView:(UICollectionView*)collectionView
cellHeightAtIndexPath:(NSIndexPath*)indexPath { cellHeightAtIndexPath:(NSIndexPath*)indexPath {
CollectionViewItem* item = CollectionViewItem* item =
[self.collectionViewModel itemAtIndexPath:indexPath]; [self.collectionViewModel itemAtIndexPath:indexPath];
if (item.type == ItemTypeAddress || item.type == ItemTypeCard) { return [MDCCollectionViewCell
return [MDCCollectionViewCell cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) forItem:item];
forItem:item];
}
return MDCCellDefaultOneLineHeight;
} }
- (BOOL)collectionView:(UICollectionView*)collectionView - (BOOL)collectionView:(UICollectionView*)collectionView
...@@ -377,6 +376,8 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -377,6 +376,8 @@ typedef NS_ENUM(NSInteger, ItemType) {
NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
switch (type) { switch (type) {
case ItemTypeAutofillSwitch: case ItemTypeAutofillSwitch:
case ItemTypeAutofillAddressSwitch:
case ItemTypeAutofillCardSwitch:
return YES; return YES;
default: default:
return NO; return NO;
...@@ -435,12 +436,16 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -435,12 +436,16 @@ typedef NS_ENUM(NSInteger, ItemType) {
[super collectionViewWillBeginEditing:collectionView]; [super collectionViewWillBeginEditing:collectionView];
[self setSwitchItemEnabled:NO itemType:ItemTypeAutofillSwitch]; [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillSwitch];
[self setSwitchItemEnabled:NO itemType:ItemTypeAutofillAddressSwitch];
[self setSwitchItemEnabled:NO itemType:ItemTypeAutofillCardSwitch];
} }
- (void)collectionViewWillEndEditing:(UICollectionView*)collectionView { - (void)collectionViewWillEndEditing:(UICollectionView*)collectionView {
[super collectionViewWillEndEditing:collectionView]; [super collectionViewWillEndEditing:collectionView];
[self setSwitchItemEnabled:YES itemType:ItemTypeAutofillSwitch]; [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillSwitch];
[self setSwitchItemEnabled:YES itemType:ItemTypeAutofillAddressSwitch];
[self setSwitchItemEnabled:YES itemType:ItemTypeAutofillCardSwitch];
} }
- (BOOL)collectionView:(UICollectionView*)collectionView - (BOOL)collectionView:(UICollectionView*)collectionView
...@@ -524,20 +529,12 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -524,20 +529,12 @@ typedef NS_ENUM(NSInteger, ItemType) {
} }
} }
#pragma mark PersonalDataManagerObserverBridgeDelegate #pragma mark PersonalDataManagerObserver
- (void)onPersonalDataChanged { - (void)onPersonalDataChanged {
// If the change is due to local editing, or if local editing is happening
// concurrently, updates are handled by collection view editing callbacks.
// Data is reloaded at the end of deletion to make sure entries are in sync.
if (_deletionInProgress) if (_deletionInProgress)
return; return;
// If the change is due to user-initiated switch state changes, updates
// are handled by the switch callbacks.
if (_userInteractionInProgress)
return;
if (![self localProfilesOrCreditCardsExist] && [self.editor isEditing]) { if (![self localProfilesOrCreditCardsExist] && [self.editor isEditing]) {
// Turn off edit mode if there exists nothing to edit. // Turn off edit mode if there exists nothing to edit.
[self.editor setEditing:NO]; [self.editor setEditing:NO];
...@@ -547,7 +544,7 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -547,7 +544,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
[self reloadData]; [self reloadData];
} }
#pragma mark - Pref Helpers #pragma mark - Getters and Setter
- (BOOL)isAutofillEnabled { - (BOOL)isAutofillEnabled {
return _browserState->GetPrefs()->GetBoolean( return _browserState->GetPrefs()->GetBoolean(
...@@ -559,4 +556,24 @@ typedef NS_ENUM(NSInteger, ItemType) { ...@@ -559,4 +556,24 @@ typedef NS_ENUM(NSInteger, ItemType) {
isEnabled); isEnabled);
} }
- (BOOL)isAutofillProfileEnabled {
return _browserState->GetPrefs()->GetBoolean(
autofill::prefs::kAutofillProfileEnabled);
}
- (void)setAutofillProfileEnabled:(BOOL)isEnabled {
_browserState->GetPrefs()->SetBoolean(
autofill::prefs::kAutofillProfileEnabled, isEnabled);
}
- (BOOL)isAutofillCreditCardEnabled {
return _browserState->GetPrefs()->GetBoolean(
autofill::prefs::kAutofillCreditCardEnabled);
}
- (void)setAutofillCreditCardEnabled:(BOOL)isEnabled {
_browserState->GetPrefs()->SetBoolean(
autofill::prefs::kAutofillCreditCardEnabled, isEnabled);
}
@end @end
...@@ -72,8 +72,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestInitialization) { ...@@ -72,8 +72,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestInitialization) {
// Expect one header section. // Expect one header section.
EXPECT_EQ(1, NumberOfSections()); EXPECT_EQ(1, NumberOfSections());
// Expect header section to contain one row. // Expect header section to contain three rows.
EXPECT_EQ(1, NumberOfItemsInSection(0)); EXPECT_EQ(3, NumberOfItemsInSection(0));
} }
// Adding a single address results in an address section. // Adding a single address results in an address section.
...@@ -82,8 +82,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfile) { ...@@ -82,8 +82,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfile) {
CreateController(); CreateController();
// Expect two sections (header and addresses section). // Expect two sections (header and addresses section).
EXPECT_EQ(2, NumberOfSections()); EXPECT_EQ(2, NumberOfSections());
// Expect header section to contain one row. // Expect header section to contain three rows.
EXPECT_EQ(1, NumberOfItemsInSection(0)); EXPECT_EQ(3, NumberOfItemsInSection(0));
// Expect address section to contain 1 row (the address itself). // Expect address section to contain 1 row (the address itself).
EXPECT_EQ(1, NumberOfItemsInSection(1)); EXPECT_EQ(1, NumberOfItemsInSection(1));
} }
...@@ -107,8 +107,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneCreditCard) { ...@@ -107,8 +107,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneCreditCard) {
CreateController(); CreateController();
// Expect two sections (header and credit card section). // Expect two sections (header and credit card section).
EXPECT_EQ(2, NumberOfSections()); EXPECT_EQ(2, NumberOfSections());
// Expect header section to contain one row. // Expect header section to contain three rows.
EXPECT_EQ(1, NumberOfItemsInSection(0)); EXPECT_EQ(3, NumberOfItemsInSection(0));
// Expect credit card section to contain 1 row (the credit card itself). // Expect credit card section to contain 1 row (the credit card itself).
EXPECT_EQ(1, NumberOfItemsInSection(1)); EXPECT_EQ(1, NumberOfItemsInSection(1));
} }
...@@ -119,8 +119,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfileItemDeleted) { ...@@ -119,8 +119,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfileItemDeleted) {
CreateController(); CreateController();
// Expect two sections (header and addresses section). // Expect two sections (header and addresses section).
EXPECT_EQ(2, NumberOfSections()); EXPECT_EQ(2, NumberOfSections());
// Expect header section to contain one row. // Expect header section to contain three rows.
EXPECT_EQ(1, NumberOfItemsInSection(0)); EXPECT_EQ(3, NumberOfItemsInSection(0));
// Expect address section to contain 1 row (the address itself). // Expect address section to contain 1 row (the address itself).
EXPECT_EQ(1, NumberOfItemsInSection(1)); EXPECT_EQ(1, NumberOfItemsInSection(1));
...@@ -158,8 +158,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfileItemDeleted) { ...@@ -158,8 +158,8 @@ TEST_F(AutofillCollectionViewControllerTest, TestOneProfileItemDeleted) {
// Verify the resulting UI. // Verify the resulting UI.
// Expect one header section. // Expect one header section.
EXPECT_EQ(1, NumberOfSections()); EXPECT_EQ(1, NumberOfSections());
// Expect header section to contain one row. // Expect header section to contain three rows.
EXPECT_EQ(1, NumberOfItemsInSection(0)); EXPECT_EQ(3, NumberOfItemsInSection(0));
} }
} // namespace } // namespace
...@@ -4,10 +4,18 @@ ...@@ -4,10 +4,18 @@
#import <XCTest/XCTest.h> #import <XCTest/XCTest.h>
#import "base/test/ios/wait_util.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
#include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h" #include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h"
#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/app/chrome_test_util.h"
#import "ios/chrome/test/app/web_view_interaction_test_util.h" #import "ios/chrome/test/app/web_view_interaction_test_util.h"
#include "ios/chrome/test/earl_grey/accessibility_util.h" #include "ios/chrome/test/earl_grey/accessibility_util.h"
#import "ios/chrome/test/earl_grey/chrome_actions.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h"
...@@ -84,7 +92,59 @@ NSString* GetTextFieldForID(int categoryId) { ...@@ -84,7 +92,59 @@ NSString* GetTextFieldForID(int categoryId) {
@interface AutofillSettingsTestCase : ChromeTestCase @interface AutofillSettingsTestCase : ChromeTestCase
@end @end
@implementation AutofillSettingsTestCase @implementation AutofillSettingsTestCase {
// The PersonalDataManager instance for the current browser state.
autofill::PersonalDataManager* _personalDataManager;
}
- (void)setUp {
[super setUp];
_personalDataManager =
autofill::PersonalDataManagerFactory::GetForBrowserState(
chrome_test_util::GetOriginalBrowserState());
_personalDataManager->SetSyncingForTest(true);
}
- (void)tearDown {
// Clear existing profiles and credit cards.
for (const auto* profile : _personalDataManager->GetProfiles()) {
_personalDataManager->RemoveByGUID(profile->guid());
}
for (const auto* creditCard : _personalDataManager->GetCreditCards()) {
_personalDataManager->RemoveByGUID(creditCard->guid());
}
[super tearDown];
}
- (autofill::AutofillProfile)addAutofillProfile {
autofill::AutofillProfile profile = autofill::test::GetFullProfile();
size_t profileCount = _personalDataManager->GetProfiles().size();
_personalDataManager->AddProfile(profile);
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForActionTimeout,
^bool() {
return profileCount <
_personalDataManager->GetProfiles().size();
}),
@"Failed to add profile.");
return profile;
}
- (autofill::CreditCard)addCreditCard {
autofill::CreditCard creditCard = autofill::test::GetCreditCard(); // Visa.
size_t cardCount = _personalDataManager->GetCreditCards().size();
_personalDataManager->AddCreditCard(creditCard);
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForActionTimeout,
^bool() {
return cardCount <
_personalDataManager->GetCreditCards().size();
}),
@"Failed to add credit card.");
return creditCard;
}
// Helper to load a page with an address form and submit it. // Helper to load a page with an address form and submit it.
- (void)loadAndSubmitTheForm { - (void)loadAndSubmitTheForm {
...@@ -103,6 +163,7 @@ NSString* GetTextFieldForID(int categoryId) { ...@@ -103,6 +163,7 @@ NSString* GetTextFieldForID(int categoryId) {
// Helper to open the settings page for the record with |address|. // Helper to open the settings page for the record with |address|.
- (void)openEditAddress:(NSString*)address { - (void)openEditAddress:(NSString*)address {
// Go to Autofill Settings.
[ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI openSettingsMenu];
NSString* label = l10n_util::GetNSString(IDS_IOS_AUTOFILL); NSString* label = l10n_util::GetNSString(IDS_IOS_AUTOFILL);
[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(label)] [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(label)]
...@@ -202,10 +263,12 @@ NSString* GetTextFieldForID(int categoryId) { ...@@ -202,10 +263,12 @@ NSString* GetTextFieldForID(int categoryId) {
} }
// Checks that if the autofill profiles and credit cards list view is in edit // Checks that if the autofill profiles and credit cards list view is in edit
// mode, the "autofill" and "wallet" switch items are disabled. // mode, the Autofill, address, and credit card switches are disabled.
- (void)testListViewEditMode { - (void)testListViewEditMode {
[self loadAndSubmitTheForm]; autofill::AutofillProfile profile = [self addAutofillProfile];
autofill::CreditCard creditCard = [self addCreditCard];
// Go to Autofill Settings.
[ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI openSettingsMenu];
[[EarlGrey [[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel( selectElementWithMatcher:ButtonWithAccessibilityLabel(
...@@ -217,10 +280,130 @@ NSString* GetTextFieldForID(int categoryId) { ...@@ -217,10 +280,130 @@ NSString* GetTextFieldForID(int categoryId) {
IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)]
performAction:grey_tap()]; performAction:grey_tap()];
// Check the "autofill" switch is disabled. Disabled switches are toggled off. // Check the Autofill, address, and credit card switches are disabled.
// Disabled switches are toggled off.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"autofillItem_switch", NO, NO)] @"autofillItem_switch", NO, NO)]
assertWithMatcher:grey_notNil()]; assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"addressItem_switch", NO, NO)]
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"cardItem_switch", NO, NO)]
assertWithMatcher:grey_notNil()];
}
// Checks that the autofill address switch can be toggled on/off independently
// and the list of autofill profiles is not affected by it.
- (void)testToggleAutofillAddressSwitch {
autofill::AutofillProfile profile = [self addAutofillProfile];
// Go to Autofill Settings.
[ChromeEarlGreyUI openSettingsMenu];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_AUTOFILL))]
performAction:grey_tap()];
// Toggle the Autofill address switch off.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"addressItem_switch", YES, YES)]
performAction:chrome_test_util::TurnSettingsSwitchOn(NO)];
// Expect Autofill profiles to remain visible.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
@"John H. Doe, 666 Erebus St.")]
assertWithMatcher:grey_notNil()];
// Toggle the Autofill address switch back on.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"addressItem_switch", NO, YES)]
performAction:chrome_test_util::TurnSettingsSwitchOn(YES)];
// Expect Autofill profiles to remain visible.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
@"John H. Doe, 666 Erebus St.")]
assertWithMatcher:grey_notNil()];
}
// Checks that the autofill credit card switch can be toggled on/off
// independently and the list of autofill credit cards is not affected by it.
- (void)testToggleAutofillCreditCardSwitch {
autofill::CreditCard creditCard = [self addCreditCard];
// Go to Autofill Settings.
[ChromeEarlGreyUI openSettingsMenu];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_AUTOFILL))]
performAction:grey_tap()];
// Toggle the Autofill credit card switch off.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"cardItem_switch", YES, YES)]
performAction:chrome_test_util::TurnSettingsSwitchOn(NO)];
// Expect Autofill credit cards to remain visible.
[[EarlGrey selectElementWithMatcher:
grey_accessibilityLabel(
@"Test User, Visa ‪• • • • 1111‬")]
assertWithMatcher:grey_notNil()];
// Toggle the Autofill credit card switch back on.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"cardItem_switch", NO, YES)]
performAction:chrome_test_util::TurnSettingsSwitchOn(YES)];
// Expect Autofill credit cards to remain visible.
[[EarlGrey selectElementWithMatcher:
grey_accessibilityLabel(
@"Test User, Visa ‪• • • • 1111‬")]
assertWithMatcher:grey_notNil()];
}
// Tests that toggling the Autofill switch on and off disables and enables the
// Autofill address and credit card switches respectively and that the list of
// autofill addresses and credit cards is not affected by it.
- (void)testToggleAutofillSwitches {
autofill::AutofillProfile profile = [self addAutofillProfile];
autofill::CreditCard creditCard = [self addCreditCard];
// Go to Autofill Settings.
[ChromeEarlGreyUI openSettingsMenu];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_AUTOFILL))]
performAction:grey_tap()];
// Toggle the Autofill switch off and back on.
for (BOOL expectedState : {YES, NO}) {
// Toggle the Autofill switch.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"autofillItem_switch",
expectedState, YES)]
performAction:chrome_test_util::TurnSettingsSwitchOn(!expectedState)];
// Expect Autofill address and credit card switches to be disabled when
// Autofill toggle is off and enabled when it is on. Disabled switches are
// toggled off.
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"addressItem_switch",
!expectedState, !expectedState)]
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
@"cardItem_switch", !expectedState,
!expectedState)]
assertWithMatcher:grey_notNil()];
// Expect Autofill addresses and credit cards to remain visible.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
@"John H. Doe, 666 Erebus St.")]
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:
grey_accessibilityLabel(
@"Test User, Visa ‪• • • • 1111‬")]
assertWithMatcher:grey_notNil()];
}
} }
@end @end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment