| Index: ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm
|
| diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a3839aefd10e9f9938942739af9734022ee96133
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm
|
| @@ -0,0 +1,629 @@
|
| +// Copyright 2015 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 "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h"
|
| +
|
| +#include "base/ios/weak_nsobject.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/mac/objc_property_releaser.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "components/autofill/core/browser/personal_data_manager.h"
|
| +#include "components/autofill/core/common/autofill_pref_names.h"
|
| +#include "components/autofill/ios/browser/credit_card_util.h"
|
| +#import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
|
| +#include "components/prefs/pref_service.h"
|
| +#include "ios/chrome/browser/application_context.h"
|
| +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
|
| +#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
|
| +#import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.h"
|
| +#import "ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.h"
|
| +#import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +namespace {
|
| +
|
| +typedef NS_ENUM(NSInteger, SectionIdentifier) {
|
| + SectionIdentifierSwitches = kSectionIdentifierEnumZero,
|
| + SectionIdentifierProfiles,
|
| + SectionIdentifierCards,
|
| +};
|
| +
|
| +typedef NS_ENUM(NSInteger, ItemType) {
|
| + ItemTypeAutofillSwitch = kItemTypeEnumZero,
|
| + ItemTypeWalletSwitch,
|
| + ItemTypeAddress,
|
| + ItemTypeCard,
|
| + ItemTypeHeader,
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +#pragma mark - AutofillCollectionViewController
|
| +
|
| +@interface AutofillCollectionViewController ()<
|
| + PersonalDataManagerObserverBridgeDelegate> {
|
| + std::string _locale; // User locale.
|
| + autofill::PersonalDataManager* _personalDataManager;
|
| + base::mac::ObjCPropertyReleaser
|
| + _propertyReleaser_AutofillCollectionViewController;
|
| + ios::ChromeBrowserState* _browserState;
|
| + std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer;
|
| + BOOL _deletionInProgress;
|
| +
|
| + // Writing user-initiated switch state changes to the pref service results in
|
| + // an observer callback, which handles general data updates with a reloadData.
|
| + // It is better to handle user-initiated changes with more specific actions
|
| + // such as inserting or removing items/sections. This boolean is used to
|
| + // stop the observer callback from acting on user-initiated changes.
|
| + BOOL _userInteractionInProgress;
|
| +}
|
| +
|
| +@end
|
| +
|
| +@implementation AutofillCollectionViewController
|
| +
|
| +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState {
|
| + DCHECK(browserState);
|
| + self = [super initWithStyle:CollectionViewControllerStyleAppBar];
|
| + if (self) {
|
| + self.collectionViewAccessibilityIdentifier = @"kAutofillCollectionViewId";
|
| + self.title = l10n_util::GetNSString(IDS_IOS_AUTOFILL);
|
| + self.shouldHideDoneButton = YES;
|
| + _browserState = browserState;
|
| + _locale = GetApplicationContext()->GetApplicationLocale();
|
| + _personalDataManager =
|
| + autofill::PersonalDataManagerFactory::GetForBrowserState(_browserState);
|
| + _observer.reset(new autofill::PersonalDataManagerObserverBridge(self));
|
| + _personalDataManager->AddObserver(_observer.get());
|
| +
|
| + [self updateEditButton];
|
| + [self loadModel];
|
| +
|
| + _propertyReleaser_AutofillCollectionViewController.Init(
|
| + self, [AutofillCollectionViewController class]);
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + _personalDataManager->RemoveObserver(_observer.get());
|
| + [super dealloc];
|
| +}
|
| +
|
| +#pragma mark - CollectionViewController
|
| +
|
| +- (void)loadModel {
|
| + [super loadModel];
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + [model addSectionWithIdentifier:SectionIdentifierSwitches];
|
| + [model addItem:[self autofillSwitchItem]
|
| + toSectionWithIdentifier:SectionIdentifierSwitches];
|
| +
|
| + if ([self isAutofillEnabled]) {
|
| + [model addItem:[self walletSwitchItem]
|
| + toSectionWithIdentifier:SectionIdentifierSwitches];
|
| +
|
| + [self populateProfileSection];
|
| + [self populateCardSection];
|
| + }
|
| +}
|
| +
|
| +#pragma mark - LoadModel Helpers
|
| +
|
| +// Populates profile section using personalDataManager.
|
| +- (void)populateProfileSection {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| + const std::vector<autofill::AutofillProfile*> autofillProfiles =
|
| + _personalDataManager->GetProfiles();
|
| + if (!autofillProfiles.empty()) {
|
| + [model addSectionWithIdentifier:SectionIdentifierProfiles];
|
| + [model setHeader:[self profileSectionHeader]
|
| + forSectionWithIdentifier:SectionIdentifierProfiles];
|
| + for (autofill::AutofillProfile* autofillProfile : autofillProfiles) {
|
| + DCHECK(autofillProfile);
|
| + [model addItem:[self itemForProfile:*autofillProfile]
|
| + toSectionWithIdentifier:SectionIdentifierProfiles];
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Populates card section using personalDataManager.
|
| +- (void)populateCardSection {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| + const std::vector<autofill::CreditCard*>& creditCards =
|
| + _personalDataManager->GetCreditCards();
|
| + if (!creditCards.empty()) {
|
| + [model addSectionWithIdentifier:SectionIdentifierCards];
|
| + [model setHeader:[self cardSectionHeader]
|
| + forSectionWithIdentifier:SectionIdentifierCards];
|
| + for (autofill::CreditCard* creditCard : creditCards) {
|
| + DCHECK(creditCard);
|
| + [model addItem:[self itemForCreditCard:*creditCard]
|
| + toSectionWithIdentifier:SectionIdentifierCards];
|
| + }
|
| + }
|
| +}
|
| +
|
| +- (CollectionViewItem*)autofillSwitchItem {
|
| + CollectionViewSwitchItem* switchItem = [[[CollectionViewSwitchItem alloc]
|
| + initWithType:ItemTypeAutofillSwitch] autorelease];
|
| + switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL);
|
| + switchItem.on = [self isAutofillEnabled];
|
| + return switchItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)walletSwitchItem {
|
| + CollectionViewSwitchItem* switchItem = [[[CollectionViewSwitchItem alloc]
|
| + initWithType:ItemTypeWalletSwitch] autorelease];
|
| + switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_USE_WALLET_DATA);
|
| + switchItem.on = [self isWalletEnabled];
|
| + return switchItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)profileSectionHeader {
|
| + CollectionViewTextItem* header = [
|
| + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease];
|
| + header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME);
|
| + return header;
|
| +}
|
| +
|
| +- (CollectionViewItem*)cardSectionHeader {
|
| + CollectionViewTextItem* header = [
|
| + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease];
|
| + header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_CREDITCARDS_GROUP_NAME);
|
| + return header;
|
| +}
|
| +
|
| +- (CollectionViewItem*)itemForProfile:
|
| + (const autofill::AutofillProfile&)autofillProfile {
|
| + std::string guid(autofillProfile.guid());
|
| + NSString* title = base::SysUTF16ToNSString(autofillProfile.GetInfo(
|
| + autofill::AutofillType(autofill::NAME_FULL), _locale));
|
| + NSString* subTitle = base::SysUTF16ToNSString(autofillProfile.GetInfo(
|
| + autofill::AutofillType(autofill::ADDRESS_HOME_LINE1), _locale));
|
| + bool isServerProfile = autofillProfile.record_type() ==
|
| + autofill::AutofillProfile::SERVER_PROFILE;
|
| +
|
| + AutofillDataItem* item =
|
| + [[[AutofillDataItem alloc] initWithType:ItemTypeAddress] autorelease];
|
| + item.text = title;
|
| + item.leadingDetailText = subTitle;
|
| + item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
|
| + item.accessibilityIdentifier = title;
|
| + item.GUID = guid;
|
| + item.deletable = !isServerProfile;
|
| + if (isServerProfile) {
|
| + item.trailingDetailText =
|
| + l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME);
|
| + }
|
| + return item;
|
| +}
|
| +
|
| +- (CollectionViewItem*)itemForCreditCard:
|
| + (const autofill::CreditCard&)creditCard {
|
| + std::string guid(creditCard.guid());
|
| + NSString* creditCardName = autofill::GetCreditCardName(creditCard, _locale);
|
| +
|
| + AutofillDataItem* item =
|
| + [[[AutofillDataItem alloc] initWithType:ItemTypeCard] autorelease];
|
| + item.text = creditCardName;
|
| + item.leadingDetailText = autofill::GetCreditCardObfuscatedNumber(creditCard);
|
| + item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
|
| + item.accessibilityIdentifier = creditCardName;
|
| + item.deletable = autofill::IsCreditCardLocal(creditCard);
|
| + item.GUID = guid;
|
| + if (![item isDeletable]) {
|
| + item.trailingDetailText =
|
| + l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME);
|
| + }
|
| + return item;
|
| +}
|
| +
|
| +- (BOOL)localProfilesOrCreditCardsExist {
|
| + return !_personalDataManager->web_profiles().empty() ||
|
| + !_personalDataManager->GetLocalCreditCards().empty();
|
| +}
|
| +
|
| +#pragma mark - SettingsRootCollectionViewController
|
| +
|
| +- (BOOL)shouldShowEditButton {
|
| + return [self isAutofillEnabled];
|
| +}
|
| +
|
| +- (BOOL)editButtonEnabled {
|
| + return [self localProfilesOrCreditCardsExist];
|
| +}
|
| +
|
| +#pragma mark - UICollectionViewDataSource
|
| +
|
| +- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
|
| + cellForItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + UICollectionViewCell* cell =
|
| + [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
| +
|
| + ItemType itemType = static_cast<ItemType>(
|
| + [self.collectionViewModel itemTypeForIndexPath:indexPath]);
|
| +
|
| + if (itemType == ItemTypeAutofillSwitch) {
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(autofillSwitchChanged:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + } else if (itemType == ItemTypeWalletSwitch) {
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(walletSwitchChanged:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + }
|
| + return cell;
|
| +}
|
| +
|
| +- (UICollectionReusableView*)collectionView:(UICollectionView*)collectionView
|
| + viewForSupplementaryElementOfKind:(NSString*)kind
|
| + atIndexPath:(NSIndexPath*)indexPath {
|
| + UICollectionReusableView* view = [super collectionView:collectionView
|
| + viewForSupplementaryElementOfKind:kind
|
| + atIndexPath:indexPath];
|
| + MDCCollectionViewTextCell* textCell =
|
| + base::mac::ObjCCast<MDCCollectionViewTextCell>(view);
|
| + if (textCell) {
|
| + textCell.textLabel.textColor = [[MDCPalette greyPalette] tint500];
|
| + }
|
| + return view;
|
| +}
|
| +
|
| +#pragma mark - Switch Callbacks
|
| +
|
| +- (void)autofillSwitchChanged:(UISwitch*)switchView {
|
| + [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillSwitch];
|
| + _userInteractionInProgress = YES;
|
| + [self setAutofillEnabled:[switchView isOn]];
|
| + _userInteractionInProgress = NO;
|
| + [self updateEditButton];
|
| +
|
| + // Avoid reference cycle in block.
|
| + base::WeakNSObject<AutofillCollectionViewController> weakSelf(self);
|
| + [self.collectionView performBatchUpdates:^{
|
| + // Obtain strong reference again.
|
| + base::scoped_nsobject<AutofillCollectionViewController> strongSelf(
|
| + [weakSelf retain]);
|
| + if (!strongSelf) {
|
| + return;
|
| + }
|
| +
|
| + if ([switchView isOn]) {
|
| + [strongSelf insertWalletSwitchItem];
|
| + [strongSelf insertProfileAndCardSections];
|
| + } else {
|
| + [strongSelf removeWalletSwitchItem];
|
| + [strongSelf removeProfileAndCardSections];
|
| + }
|
| + }
|
| + completion:nil];
|
| +}
|
| +
|
| +- (void)walletSwitchChanged:(UISwitch*)switchView {
|
| + [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeWalletSwitch];
|
| + _userInteractionInProgress = YES;
|
| + [self setWalletEnabled:[switchView isOn]];
|
| + _userInteractionInProgress = NO;
|
| + if ([switchView isOn]) {
|
| + [self insertCardSection];
|
| + } else {
|
| + [self removeCardSection];
|
| + }
|
| +}
|
| +
|
| +#pragma mark - Switch Helpers
|
| +
|
| +// Sets switchItem's state to |on|. It is important that there is only one item
|
| +// of |switchItemType| in SectionIdentifierSwitches.
|
| +- (void)setSwitchItemOn:(BOOL)on itemType:(ItemType)switchItemType {
|
| + NSIndexPath* switchPath =
|
| + [self.collectionViewModel indexPathForItemType:switchItemType
|
| + sectionIdentifier:SectionIdentifierSwitches];
|
| + CollectionViewSwitchItem* switchItem =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:switchPath]);
|
| + switchItem.on = on;
|
| +}
|
| +
|
| +#pragma mark - Insert or Delete Items and Sections
|
| +
|
| +- (void)insertWalletSwitchItem {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| + [model addItem:[self walletSwitchItem]
|
| + toSectionWithIdentifier:SectionIdentifierSwitches];
|
| + NSIndexPath* indexPath =
|
| + [self.collectionViewModel indexPathForItemType:ItemTypeWalletSwitch
|
| + sectionIdentifier:SectionIdentifierSwitches];
|
| + [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]];
|
| +}
|
| +
|
| +- (void)removeWalletSwitchItem {
|
| + if (![self.collectionViewModel
|
| + hasItemForItemType:ItemTypeWalletSwitch
|
| + sectionIdentifier:SectionIdentifierSwitches]) {
|
| + return;
|
| + }
|
| + NSIndexPath* indexPath =
|
| + [self.collectionViewModel indexPathForItemType:ItemTypeWalletSwitch
|
| + sectionIdentifier:SectionIdentifierSwitches];
|
| + [self.collectionViewModel removeItemWithType:ItemTypeWalletSwitch
|
| + fromSectionWithIdentifier:SectionIdentifierSwitches];
|
| + [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]];
|
| +}
|
| +
|
| +- (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] autorelease];
|
| + if ([self.collectionViewModel
|
| + hasSectionForSectionIdentifier:SectionIdentifierProfiles]) {
|
| + [sections
|
| + addIndex:[self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierProfiles]];
|
| + }
|
| + if ([self.collectionViewModel
|
| + hasSectionForSectionIdentifier:SectionIdentifierCards]) {
|
| + [sections addIndex:[self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierCards]];
|
| + }
|
| + return sections;
|
| +}
|
| +
|
| +- (void)insertCardSection {
|
| + [self populateCardSection];
|
| + if ([self.collectionViewModel
|
| + hasSectionForSectionIdentifier:SectionIdentifierCards]) {
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierCards];
|
| + [self.collectionView insertSections:[NSIndexSet indexSetWithIndex:section]];
|
| + }
|
| +}
|
| +
|
| +- (void)removeCardSection {
|
| + if (![self.collectionViewModel
|
| + hasSectionForSectionIdentifier:SectionIdentifierCards]) {
|
| + return;
|
| + }
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierCards];
|
| + [self.collectionViewModel removeSectionWithIdentifier:SectionIdentifierCards];
|
| + [self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:section]];
|
| +}
|
| +
|
| +#pragma mark - MDCCollectionViewStylingDelegate
|
| +
|
| +- (CGFloat)collectionView:(UICollectionView*)collectionView
|
| + cellHeightAtIndexPath:(NSIndexPath*)indexPath {
|
| + CollectionViewItem* item =
|
| + [self.collectionViewModel itemAtIndexPath:indexPath];
|
| + if (item.type == ItemTypeAddress || item.type == ItemTypeCard ||
|
| + item.type == ItemTypeWalletSwitch) {
|
| + return [MDCCollectionViewCell
|
| + cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
|
| + forItem:item];
|
| + }
|
| + return MDCCellDefaultOneLineHeight;
|
| +}
|
| +
|
| +- (BOOL)collectionView:(UICollectionView*)collectionView
|
| + hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
|
| + NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (type) {
|
| + case ItemTypeAutofillSwitch:
|
| + case ItemTypeWalletSwitch:
|
| + return YES;
|
| + default:
|
| + return NO;
|
| + }
|
| +}
|
| +
|
| +#pragma mark - UICollectionViewDelegate
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
|
| +
|
| + // Edit mode is the state where the user can select and delete entries. In
|
| + // edit mode, selection is handled by the superclass. When not in edit mode
|
| + // selection presents the editing controller for the selected entry.
|
| + if ([self.editor isEditing]) {
|
| + return;
|
| + }
|
| +
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| + base::scoped_nsobject<UIViewController> controller;
|
| + switch ([model itemTypeForIndexPath:indexPath]) {
|
| + case ItemTypeAddress: {
|
| + const std::vector<autofill::AutofillProfile*> autofillProfiles =
|
| + _personalDataManager->GetProfiles();
|
| + controller.reset([[AutofillProfileEditCollectionViewController
|
| + controllerWithProfile:*autofillProfiles[indexPath.item]
|
| + personalDataManager:_personalDataManager] retain]);
|
| + break;
|
| + }
|
| + case ItemTypeCard: {
|
| + const std::vector<autofill::CreditCard*>& creditCards =
|
| + _personalDataManager->GetCreditCards();
|
| + controller.reset([[AutofillCreditCardEditCollectionViewController alloc]
|
| + initWithCreditCard:*creditCards[indexPath.item]
|
| + personalDataManager:_personalDataManager]);
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + if (controller.get()) {
|
| + [self.navigationController pushViewController:controller animated:YES];
|
| + }
|
| +}
|
| +
|
| +#pragma mark - MDCCollectionViewEditingDelegate
|
| +
|
| +- (BOOL)collectionViewAllowsEditing:(UICollectionView*)collectionView {
|
| + return YES;
|
| +}
|
| +
|
| +- (BOOL)collectionView:(UICollectionView*)collectionView
|
| + canEditItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + // Only autofill data cells are editable.
|
| + CollectionViewItem* item =
|
| + [self.collectionViewModel itemAtIndexPath:indexPath];
|
| + if ([item isKindOfClass:[AutofillDataItem class]]) {
|
| + AutofillDataItem* autofillItem =
|
| + base::mac::ObjCCastStrict<AutofillDataItem>(item);
|
| + return [autofillItem isDeletable];
|
| + }
|
| + return NO;
|
| +}
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + willDeleteItemsAtIndexPaths:(NSArray*)indexPaths {
|
| + _deletionInProgress = YES;
|
| + for (NSIndexPath* indexPath in indexPaths) {
|
| + AutofillDataItem* item = base::mac::ObjCCastStrict<AutofillDataItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + _personalDataManager->RemoveByGUID([item GUID]);
|
| + }
|
| + // Must call super at the end of the child implementation.
|
| + [super collectionView:collectionView willDeleteItemsAtIndexPaths:indexPaths];
|
| +}
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + didDeleteItemsAtIndexPaths:(NSArray*)indexPaths {
|
| + // If there are no index paths, return early. This can happen if the user
|
| + // presses the Delete button twice in quick succession.
|
| + if (![indexPaths count])
|
| + return;
|
| +
|
| + // TODO(crbug.com/650390) Generalize removing empty sections
|
| + [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierProfiles];
|
| + [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierCards];
|
| +}
|
| +
|
| +// Remove the section from the model and collectionView if there are no more
|
| +// items in the section.
|
| +- (void)removeSectionIfEmptyForSectionWithIdentifier:
|
| + (SectionIdentifier)sectionIdentifier {
|
| + if (![self.collectionViewModel
|
| + hasSectionForSectionIdentifier:sectionIdentifier]) {
|
| + return;
|
| + }
|
| + NSInteger section =
|
| + [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier];
|
| + if ([self.collectionView numberOfItemsInSection:section] == 0) {
|
| + // Avoid reference cycle in block.
|
| + base::WeakNSObject<AutofillCollectionViewController> weakSelf(self);
|
| + [self.collectionView performBatchUpdates:^{
|
| + // Obtain strong reference again.
|
| + base::scoped_nsobject<AutofillCollectionViewController> strongSelf(
|
| + [weakSelf retain]);
|
| + if (!strongSelf) {
|
| + return;
|
| + }
|
| +
|
| + // Remove section from model and collectionView.
|
| + [[strongSelf collectionViewModel]
|
| + removeSectionWithIdentifier:sectionIdentifier];
|
| + [[strongSelf collectionView]
|
| + deleteSections:[NSIndexSet indexSetWithIndex:section]];
|
| + }
|
| + completion:^(BOOL finished) {
|
| + // Obtain strong reference again.
|
| + base::scoped_nsobject<AutofillCollectionViewController> strongSelf(
|
| + [weakSelf retain]);
|
| + if (!strongSelf) {
|
| + return;
|
| + }
|
| +
|
| + // Turn off edit mode if there is nothing to edit.
|
| + if (![strongSelf localProfilesOrCreditCardsExist]) {
|
| + [[strongSelf editor] setEditing:NO];
|
| + }
|
| + [strongSelf updateEditButton];
|
| + strongSelf.get()->_deletionInProgress = NO;
|
| + }];
|
| + }
|
| +}
|
| +
|
| +#pragma mark PersonalDataManagerObserverBridgeDelegate
|
| +
|
| +- (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)
|
| + 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]) {
|
| + // Turn off edit mode if there exists nothing to edit.
|
| + [self.editor setEditing:NO];
|
| + }
|
| +
|
| + [self updateEditButton];
|
| + [self reloadData];
|
| +}
|
| +
|
| +#pragma mark - Pref Helpers
|
| +
|
| +- (BOOL)isAutofillEnabled {
|
| + return _browserState->GetPrefs()->GetBoolean(
|
| + autofill::prefs::kAutofillEnabled);
|
| +}
|
| +
|
| +- (void)setAutofillEnabled:(BOOL)isEnabled {
|
| + _browserState->GetPrefs()->SetBoolean(autofill::prefs::kAutofillEnabled,
|
| + isEnabled);
|
| +}
|
| +
|
| +- (BOOL)isWalletEnabled {
|
| + return _browserState->GetPrefs()->GetBoolean(
|
| + autofill::prefs::kAutofillWalletImportEnabled);
|
| +}
|
| +
|
| +- (void)setWalletEnabled:(BOOL)isEnabled {
|
| + _browserState->GetPrefs()->SetBoolean(
|
| + autofill::prefs::kAutofillWalletImportEnabled, isEnabled);
|
| +}
|
| +
|
| +@end
|
|
|