| Index: ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm
|
| diff --git a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..14905c796b625a7f0dbcf5794eb8c70a58c9c03f
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm
|
| @@ -0,0 +1,996 @@
|
| +// 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/sync_settings_collection_view_controller.h"
|
| +
|
| +#include <memory>
|
| +
|
| +#include "base/auto_reset.h"
|
| +#include "base/mac/foundation_util.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#include "components/browser_sync/profile_sync_service.h"
|
| +#include "components/google/core/browser/google_util.h"
|
| +#include "components/signin/core/browser/account_tracker_service.h"
|
| +#include "components/signin/core/browser/profile_oauth2_token_service.h"
|
| +#include "components/signin/ios/browser/oauth2_token_service_observer_bridge.h"
|
| +#include "components/strings/grit/components_strings.h"
|
| +#include "components/sync/base/model_type.h"
|
| +#include "ios/chrome/browser/application_context.h"
|
| +#include "ios/chrome/browser/chrome_url_constants.h"
|
| +#include "ios/chrome/browser/experimental_flags.h"
|
| +#include "ios/chrome/browser/signin/account_tracker_service_factory.h"
|
| +#import "ios/chrome/browser/signin/authentication_service.h"
|
| +#import "ios/chrome/browser/signin/authentication_service_factory.h"
|
| +#include "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h"
|
| +#include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
|
| +#include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
|
| +#include "ios/chrome/browser/sync/sync_setup_service.h"
|
| +#include "ios/chrome/browser/sync/sync_setup_service_factory.h"
|
| +#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_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/colors/MDCPalette+CrAdditions.h"
|
| +#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
|
| +#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
|
| +#import "ios/chrome/browser/ui/commands/open_url_command.h"
|
| +#import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h"
|
| +#import "ios/chrome/browser/ui/settings/cells/text_and_error_item.h"
|
| +#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
|
| +#import "ios/chrome/browser/ui/settings/sync_encryption_collection_view_controller.h"
|
| +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h"
|
| +#import "ios/chrome/browser/ui/settings/utils/resized_avatar_cache.h"
|
| +#import "ios/chrome/browser/ui/sync/sync_util.h"
|
| +#import "ios/chrome/browser/ui/uikit_ui_util.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
|
| +#import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
|
| +#import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
|
| +#include "ui/base/l10n/l10n_util_mac.h"
|
| +#include "url/gurl.h"
|
| +
|
| +// The a11y identifier of the view controller's view.
|
| +NSString* const kSettingsSyncId = @"kSettingsSyncId";
|
| +// Notification when a switch account operation will start.
|
| +NSString* const kSwitchAccountWillStartNotification =
|
| + @"kSwitchAccountWillStartNotification";
|
| +// Notification when a switch account operation did finish.
|
| +NSString* const kSwitchAccountDidFinishNotification =
|
| + @"kSwitchAccountDidFinishNotification";
|
| +// Used to tag and retrieve ItemTypeSyncableDataType cell tags.
|
| +const NSInteger kTagShift = 1000;
|
| +
|
| +namespace {
|
| +
|
| +typedef NS_ENUM(NSInteger, SectionIdentifier) {
|
| + SectionIdentifierSyncError = kSectionIdentifierEnumZero,
|
| + SectionIdentifierEnableSync,
|
| + SectionIdentifierSyncAccounts,
|
| + SectionIdentifierSyncServices,
|
| + SectionIdentifierEncryptionAndFooter,
|
| +};
|
| +
|
| +typedef NS_ENUM(NSInteger, ItemType) {
|
| + ItemTypeSyncError = kItemTypeEnumZero,
|
| + ItemTypeSyncSwitch,
|
| + ItemTypeAccount,
|
| + ItemTypeSyncEverything,
|
| + ItemTypeSyncableDataType,
|
| + ItemTypeEncryption,
|
| + ItemTypeManageSyncedData,
|
| + ItemTypeHeader,
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +@interface SyncSettingsCollectionViewController ()<
|
| + ChromeIdentityServiceObserver,
|
| + OAuth2TokenServiceObserverBridgeDelegate,
|
| + SettingsControllerProtocol,
|
| + SyncObserverModelBridge> {
|
| + ios::ChromeBrowserState* _browserState; // Weak.
|
| + SyncSetupService* _syncSetupService; // Weak.
|
| + std::unique_ptr<SyncObserverBridge> _syncObserver;
|
| + std::unique_ptr<OAuth2TokenServiceObserverBridge> _tokenServiceObserver;
|
| + base::scoped_nsobject<AuthenticationFlow> _authenticationFlow;
|
| + // Whether switching sync account is allowed on the screen.
|
| + BOOL _allowSwitchSyncAccount;
|
| + // Whether an authentication operation is in progress (e.g switch accounts).
|
| + BOOL _authenticationOperationInProgress;
|
| + // Whether Sync State changes should be currently ignored.
|
| + BOOL _ignoreSyncStateChanges;
|
| +
|
| + // Cache for Identity items avatar images.
|
| + base::scoped_nsobject<ResizedAvatarCache> _avatarCache;
|
| + std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver;
|
| + // Enable lookup of item corresponding to a given identity GAIA ID string.
|
| + base::scoped_nsobject<NSDictionary<NSString*, CollectionViewItem*>>
|
| + _identityMap;
|
| +}
|
| +
|
| +// Stops observing browser state services.
|
| +- (void)stopBrowserStateServiceObservers;
|
| +// Pops the view if user is signed out and not authentication operation is in
|
| +// progress. Returns YES if the view was popped.
|
| +- (BOOL)popViewIfSignedOut;
|
| +
|
| +// Returns a switch item for sync, set to on if |isOn| is YES.
|
| +- (CollectionViewItem*)syncSwitchItem:(BOOL)isOn;
|
| +// Returns an item for sync errors other than sync encryption.
|
| +- (CollectionViewItem*)syncErrorItem;
|
| +// Returns a switch item for sync everything, set to on if |isOn| is YES.
|
| +- (CollectionViewItem*)syncEverythingSwitchItem:(BOOL)isOn;
|
| +// Returns a switch item for the syncable data type |dataType|, set to on if
|
| +// |IsDataTypeEnabled| for that type returns true.
|
| +- (CollectionViewItem*)switchItemForDataType:
|
| + (SyncSetupService::SyncableDatatype)dataType;
|
| +// Returns an item for Encryption.
|
| +- (CollectionViewItem*)encryptionCellItem;
|
| +// Returns an item to open a link to manage the synced data.
|
| +- (CollectionViewItem*)manageSyncedDataItem;
|
| +
|
| +// Action method for sync switch.
|
| +- (void)changeSyncStatusToOn:(UISwitch*)sender;
|
| +// Action method for the sync error cell.
|
| +- (void)fixSyncErrorIfPossible;
|
| +// Action method for the account cells.
|
| +- (void)startSwitchAccountForIdentity:(ChromeIdentity*)identity
|
| + postSignInAction:(PostSignInAction)postSigninAction;
|
| +// Callback for switch account action method.
|
| +- (void)didSwitchAccountWithSuccess:(BOOL)success;
|
| +// Action method for the Sync Everything switch.
|
| +- (void)changeSyncEverythingStatusToOn:(UISwitch*)sender;
|
| +// Action method for the data type switches.
|
| +- (void)changeDataTypeSyncStatusToOn:(UISwitch*)sender;
|
| +// Action method for the encryption cell.
|
| +- (void)showEncryption;
|
| +
|
| +// Updates the visual status of the screen (i.e. whether cells are enabled,
|
| +// whether errors are displayed, ...).
|
| +- (void)updateCollectionView;
|
| +// Ensures the Sync error cell is shown when there is an error.
|
| +- (void)updateSyncError;
|
| +// Ensures the encryption cell displays an error if needed.
|
| +- (void)updateEncryptionCell;
|
| +// Updates the account item so it can reflect the latest state of the identity.
|
| +- (void)updateAccountItem:(CollectionViewAccountItem*)item
|
| + withIdentity:(ChromeIdentity*)identity;
|
| +
|
| +// Returns whether the Sync Settings screen has an Accounts section, allowing
|
| +// users to choose to which account they want to sync to.
|
| +- (BOOL)hasAccountsSection;
|
| +// Returns whether a sync error cell should be displayed.
|
| +- (BOOL)shouldDisplaySyncError;
|
| +// Returns whether the Sync settings should be disabled because of a Sync error.
|
| +- (BOOL)shouldDisableSettingsOnSyncError;
|
| +// Returns whether an error should be displayed on the encryption cell.
|
| +- (BOOL)shouldDisplayEncryptionError;
|
| +// Returns whether the existing sync error is fixable by a user action.
|
| +- (BOOL)isSyncErrorFixableByUserAction;
|
| +// Returns the ID to use to access the l10n string for the given data type.
|
| +- (int)titleIdForSyncableDataType:(SyncSetupService::SyncableDatatype)datatype;
|
| +// Returns whether the encryption item should be enabled.
|
| +- (BOOL)shouldEncryptionItemBeEnabled;
|
| +// Returns whether the sync everything item should be enabled.
|
| +- (BOOL)shouldSyncEverythingItemBeEnabled;
|
| +// Returns whether the data type items should be enabled.
|
| +- (BOOL)shouldSyncableItemsBeEnabled;
|
| +// Returns the tag for a data type switch based on its index path.
|
| +- (NSInteger)tagForIndexPath:(NSIndexPath*)indexPath;
|
| +// Returns the indexPath for a data type switch based on its tag.
|
| +- (NSIndexPath*)indexPathForTag:(NSInteger)shiftedTag;
|
| +
|
| +@end
|
| +
|
| +@implementation SyncSettingsCollectionViewController
|
| +
|
| +#pragma mark Initialization
|
| +
|
| +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
|
| + allowSwitchSyncAccount:(BOOL)allowSwitchSyncAccount {
|
| + DCHECK(browserState);
|
| + self = [super initWithStyle:CollectionViewControllerStyleAppBar];
|
| + if (self) {
|
| + _allowSwitchSyncAccount = allowSwitchSyncAccount;
|
| + _browserState = browserState;
|
| + _syncSetupService =
|
| + SyncSetupServiceFactory::GetForBrowserState(_browserState);
|
| + self.title = l10n_util::GetNSString(IDS_IOS_SYNC_SETTING_TITLE);
|
| + browser_sync::ProfileSyncService* syncService =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
|
| + _syncObserver.reset(new SyncObserverBridge(self, syncService));
|
| + _tokenServiceObserver.reset(new OAuth2TokenServiceObserverBridge(
|
| + OAuth2TokenServiceFactory::GetForBrowserState(_browserState), self));
|
| + self.collectionViewAccessibilityIdentifier = kSettingsSyncId;
|
| + _avatarCache.reset([[ResizedAvatarCache alloc] init]);
|
| + _identityServiceObserver.reset(
|
| + new ChromeIdentityServiceObserverBridge(self));
|
| + [self loadModel];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)stopBrowserStateServiceObservers {
|
| + _syncObserver.reset();
|
| + _tokenServiceObserver.reset();
|
| + _identityServiceObserver.reset();
|
| +}
|
| +
|
| +- (BOOL)popViewIfSignedOut {
|
| + if (AuthenticationServiceFactory::GetForBrowserState(_browserState)
|
| + ->IsAuthenticated()) {
|
| + return NO;
|
| + }
|
| + if (_authenticationOperationInProgress) {
|
| + // The signed out state might be temporary (e.g. account switch, ...).
|
| + // Don't pop this view based on intermediary values.
|
| + return NO;
|
| + }
|
| + [self.navigationController popToViewController:self animated:NO];
|
| + [base::mac::ObjCCastStrict<SettingsNavigationController>(
|
| + self.navigationController) popViewControllerOrCloseSettingsAnimated:NO];
|
| + return YES;
|
| +}
|
| +
|
| +#pragma mark View lifecycle
|
| +
|
| +- (void)viewWillAppear:(BOOL)animated {
|
| + [super viewWillAppear:animated];
|
| + [self updateEncryptionCell];
|
| +}
|
| +
|
| +#pragma mark SettingsRootCollectionViewController
|
| +
|
| +- (void)loadModel {
|
| + [super loadModel];
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + // SyncError section.
|
| + if ([self shouldDisplaySyncError]) {
|
| + [model addSectionWithIdentifier:SectionIdentifierSyncError];
|
| + [model addItem:[self syncErrorItem]
|
| + toSectionWithIdentifier:SectionIdentifierSyncError];
|
| + }
|
| +
|
| + // Sync Section.
|
| + BOOL syncEnabled = _syncSetupService->IsSyncEnabled();
|
| + [model addSectionWithIdentifier:SectionIdentifierEnableSync];
|
| + [model addItem:[self syncSwitchItem:syncEnabled]
|
| + toSectionWithIdentifier:SectionIdentifierEnableSync];
|
| +
|
| + // Sync to Section.
|
| + if ([self hasAccountsSection]) {
|
| + NSMutableDictionary<NSString*, CollectionViewItem*>* mutableIdentityMap =
|
| + [[[NSMutableDictionary alloc] init] autorelease];
|
| + // Accounts section. Cells enabled if sync is on.
|
| + [model addSectionWithIdentifier:SectionIdentifierSyncAccounts];
|
| + CollectionViewTextItem* syncToHeader = [[[CollectionViewTextItem alloc]
|
| + initWithType:ItemTypeHeader] autorelease];
|
| + syncToHeader.text = l10n_util::GetNSString(IDS_IOS_SYNC_TO_TITLE);
|
| + [model setHeader:syncToHeader
|
| + forSectionWithIdentifier:SectionIdentifierSyncAccounts];
|
| + ProfileOAuth2TokenService* oauth2_service =
|
| + OAuth2TokenServiceFactory::GetForBrowserState(_browserState);
|
| + AccountTrackerService* accountTracker =
|
| + ios::AccountTrackerServiceFactory::GetForBrowserState(_browserState);
|
| +
|
| + for (const std::string& account_id : oauth2_service->GetAccounts()) {
|
| + AccountInfo account = accountTracker->GetAccountInfo(account_id);
|
| + ChromeIdentity* identity = ios::GetChromeBrowserProvider()
|
| + ->GetChromeIdentityService()
|
| + ->GetIdentityWithGaiaID(account.gaia);
|
| + CollectionViewItem* accountItem = [self accountItem:identity];
|
| + [model addItem:accountItem
|
| + toSectionWithIdentifier:SectionIdentifierSyncAccounts];
|
| + [mutableIdentityMap setObject:accountItem forKey:identity.gaiaID];
|
| + }
|
| + _identityMap.reset([mutableIdentityMap retain]);
|
| + }
|
| +
|
| + // Data Types to sync. Enabled if sync is on.
|
| + [model addSectionWithIdentifier:SectionIdentifierSyncServices];
|
| + CollectionViewTextItem* syncServicesHeader = [
|
| + [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader] autorelease];
|
| + syncServicesHeader.text =
|
| + l10n_util::GetNSString(IDS_IOS_SYNC_DATA_TYPES_TITLE);
|
| + [model setHeader:syncServicesHeader
|
| + forSectionWithIdentifier:SectionIdentifierSyncServices];
|
| + BOOL syncEverythingEnabled = _syncSetupService->IsSyncingAllDataTypes();
|
| + [model addItem:[self syncEverythingSwitchItem:syncEverythingEnabled]
|
| + toSectionWithIdentifier:SectionIdentifierSyncServices];
|
| + // Specific Data Types to sync. Enabled if Sync Everything is off.
|
| + for (int i = 0; i < SyncSetupService::kNumberOfSyncableDatatypes; ++i) {
|
| + SyncSetupService::SyncableDatatype dataType =
|
| + static_cast<SyncSetupService::SyncableDatatype>(i);
|
| + if (!experimental_flags::IsReadingListEnabled() &&
|
| + dataType == SyncSetupService::kSyncReadingList) {
|
| + // Display Reading List only if it is enabled.
|
| + continue;
|
| + }
|
| + [model addItem:[self switchItemForDataType:dataType]
|
| + toSectionWithIdentifier:SectionIdentifierSyncServices];
|
| + }
|
| +
|
| + // Encryption section. Enabled if sync is on.
|
| + [model addSectionWithIdentifier:SectionIdentifierEncryptionAndFooter];
|
| + [model addItem:[self encryptionCellItem]
|
| + toSectionWithIdentifier:SectionIdentifierEncryptionAndFooter];
|
| + [model addItem:[self manageSyncedDataItem]
|
| + toSectionWithIdentifier:SectionIdentifierEncryptionAndFooter];
|
| +}
|
| +
|
| +#pragma mark - Model items
|
| +
|
| +- (CollectionViewItem*)syncSwitchItem:(BOOL)isOn {
|
| + SyncSwitchItem* syncSwitchItem = [self
|
| + switchItemWithType:ItemTypeSyncSwitch
|
| + title:l10n_util::GetNSString(IDS_IOS_SYNC_SETTING_TITLE)
|
| + subTitle:l10n_util::GetNSString(
|
| + IDS_IOS_SIGN_IN_TO_CHROME_SETTING_SUBTITLE)];
|
| + syncSwitchItem.on = isOn;
|
| + return syncSwitchItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)syncErrorItem {
|
| + DCHECK([self shouldDisplaySyncError]);
|
| + CollectionViewAccountItem* syncErrorItem = [[[CollectionViewAccountItem alloc]
|
| + initWithType:ItemTypeSyncError] autorelease];
|
| + syncErrorItem.text = l10n_util::GetNSString(IDS_IOS_SYNC_ERROR_TITLE);
|
| + syncErrorItem.image = [UIImage imageNamed:@"settings_error"];
|
| + syncErrorItem.detailText =
|
| + ios_internal::sync::GetSyncErrorMessageForBrowserState(_browserState);
|
| + return syncErrorItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)accountItem:(ChromeIdentity*)identity {
|
| + CollectionViewAccountItem* identityAccountItem =
|
| + [[[CollectionViewAccountItem alloc] initWithType:ItemTypeAccount]
|
| + autorelease];
|
| + [self updateAccountItem:identityAccountItem withIdentity:identity];
|
| +
|
| + identityAccountItem.enabled = _syncSetupService->IsSyncEnabled();
|
| + ChromeIdentity* authenticatedIdentity =
|
| + AuthenticationServiceFactory::GetForBrowserState(_browserState)
|
| + ->GetAuthenticatedIdentity();
|
| + if (identity == authenticatedIdentity) {
|
| + identityAccountItem.accessoryType = MDCCollectionViewCellAccessoryCheckmark;
|
| + }
|
| + return identityAccountItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)syncEverythingSwitchItem:(BOOL)isOn {
|
| + SyncSwitchItem* syncSwitchItem = [self
|
| + switchItemWithType:ItemTypeSyncEverything
|
| + title:l10n_util::GetNSString(IDS_IOS_SYNC_EVERYTHING_TITLE)
|
| + subTitle:nil];
|
| + syncSwitchItem.on = isOn;
|
| + syncSwitchItem.enabled = [self shouldSyncEverythingItemBeEnabled];
|
| + return syncSwitchItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)switchItemForDataType:
|
| + (SyncSetupService::SyncableDatatype)dataType {
|
| + syncer::ModelType modelType = _syncSetupService->GetModelType(dataType);
|
| + BOOL isOn = _syncSetupService->IsDataTypeEnabled(modelType);
|
| +
|
| + SyncSwitchItem* syncDataTypeItem =
|
| + [self switchItemWithType:ItemTypeSyncableDataType
|
| + title:l10n_util::GetNSString(
|
| + [self titleIdForSyncableDataType:dataType])
|
| + subTitle:nil];
|
| + syncDataTypeItem.dataType = dataType;
|
| + syncDataTypeItem.on = isOn;
|
| + syncDataTypeItem.enabled = [self shouldSyncableItemsBeEnabled];
|
| + return syncDataTypeItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)encryptionCellItem {
|
| + TextAndErrorItem* encryptionCellItem =
|
| + [[[TextAndErrorItem alloc] initWithType:ItemTypeEncryption] autorelease];
|
| + encryptionCellItem.text =
|
| + l10n_util::GetNSString(IDS_IOS_SYNC_ENCRYPTION_TITLE);
|
| + encryptionCellItem.accessoryType =
|
| + MDCCollectionViewCellAccessoryDisclosureIndicator;
|
| + encryptionCellItem.shouldDisplayError = [self shouldDisplayEncryptionError];
|
| + encryptionCellItem.enabled = [self shouldEncryptionItemBeEnabled];
|
| + return encryptionCellItem;
|
| +}
|
| +
|
| +- (CollectionViewItem*)manageSyncedDataItem {
|
| + CollectionViewTextItem* manageSyncedDataItem =
|
| + [[[CollectionViewTextItem alloc] initWithType:ItemTypeManageSyncedData]
|
| + autorelease];
|
| + manageSyncedDataItem.text =
|
| + l10n_util::GetNSString(IDS_IOS_SYNC_RESET_GOOGLE_DASHBOARD_NO_LINK);
|
| + manageSyncedDataItem.accessibilityTraits |= UIAccessibilityTraitButton;
|
| + return manageSyncedDataItem;
|
| +}
|
| +
|
| +#pragma mark Item Constructors
|
| +
|
| +- (SyncSwitchItem*)switchItemWithType:(NSInteger)type
|
| + title:(NSString*)title
|
| + subTitle:(NSString*)detailText {
|
| + SyncSwitchItem* switchItem =
|
| + [[[SyncSwitchItem alloc] initWithType:type] autorelease];
|
| + switchItem.text = title;
|
| + switchItem.detailText = detailText;
|
| + return switchItem;
|
| +}
|
| +
|
| +#pragma mark - UICollectionViewDataSource
|
| +
|
| +- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
|
| + cellForItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + UICollectionViewCell* cell =
|
| + [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
| + NSInteger itemType =
|
| + [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| +
|
| + switch (itemType) {
|
| + case ItemTypeSyncError: {
|
| + CollectionViewAccountCell* accountCell =
|
| + base::mac::ObjCCastStrict<CollectionViewAccountCell>(cell);
|
| + accountCell.textLabel.textColor = [[MDCPalette redPalette] tint700];
|
| + accountCell.detailTextLabel.numberOfLines = 1;
|
| + break;
|
| + }
|
| + case ItemTypeSyncSwitch: {
|
| + SyncSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<SyncSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(changeSyncStatusToOn:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + break;
|
| + }
|
| + case ItemTypeSyncEverything: {
|
| + SyncSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<SyncSwitchCell>(cell);
|
| + [switchCell.switchView
|
| + addTarget:self
|
| + action:@selector(changeSyncEverythingStatusToOn:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + break;
|
| + }
|
| + case ItemTypeSyncableDataType: {
|
| + SyncSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<SyncSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(changeDataTypeSyncStatusToOn:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + switchCell.switchView.tag = [self tagForIndexPath:indexPath];
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| + return cell;
|
| +}
|
| +
|
| +// Method for overriding the header view of a section. Used to set the header
|
| +// text color to gray.
|
| +- (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 UICollectionViewDelegate
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
|
| +
|
| + NSInteger itemType =
|
| + [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (itemType) {
|
| + case ItemTypeSyncError:
|
| + [self fixSyncErrorIfPossible];
|
| + break;
|
| + case ItemTypeAccount: {
|
| + CollectionViewAccountItem* accountItem =
|
| + base::mac::ObjCCastStrict<CollectionViewAccountItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + if (!accountItem.accessoryType) {
|
| + [self startSwitchAccountForIdentity:accountItem.chromeIdentity
|
| + postSignInAction:POST_SIGNIN_ACTION_NONE];
|
| + }
|
| + break;
|
| + }
|
| + case ItemTypeEncryption:
|
| + [self showEncryption];
|
| + break;
|
| + case ItemTypeManageSyncedData: {
|
| + GURL learnMoreUrl = google_util::AppendGoogleLocaleParam(
|
| + GURL(kSyncGoogleDashboardURL),
|
| + GetApplicationContext()->GetApplicationLocale());
|
| + base::scoped_nsobject<OpenUrlCommand> command(
|
| + [[OpenUrlCommand alloc] initWithURLFromChrome:learnMoreUrl]);
|
| + [command setTag:IDC_CLOSE_SETTINGS_AND_OPEN_URL];
|
| + [self chromeExecuteCommand:command];
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +}
|
| +
|
| +#pragma mark MDCCollectionViewStylingDelegate
|
| +
|
| +- (CGFloat)collectionView:(UICollectionView*)collectionView
|
| + cellHeightAtIndexPath:(NSIndexPath*)indexPath {
|
| + CollectionViewItem* item =
|
| + [self.collectionViewModel itemAtIndexPath:indexPath];
|
| + switch (item.type) {
|
| + case ItemTypeAccount:
|
| + return MDCCellDefaultTwoLineHeight;
|
| + case ItemTypeSyncSwitch:
|
| + return [MDCCollectionViewCell
|
| + cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
|
| + forItem:item];
|
| + case ItemTypeSyncError:
|
| + return MDCCellDefaultOneLineWithAvatarHeight;
|
| + default:
|
| + return MDCCellDefaultOneLineHeight;
|
| + }
|
| +}
|
| +
|
| +- (BOOL)collectionView:(UICollectionView*)collectionView
|
| + hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
|
| + NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (type) {
|
| + case ItemTypeSyncSwitch:
|
| + case ItemTypeSyncEverything:
|
| + case ItemTypeSyncableDataType:
|
| + return YES;
|
| + default:
|
| + return NO;
|
| + }
|
| +}
|
| +
|
| +#pragma mark - Actions
|
| +
|
| +- (void)changeSyncStatusToOn:(UISwitch*)sender {
|
| + if (self.navigationController.topViewController != self) {
|
| + // Workaround for timing issue when taping on a switch and the error or
|
| + // encryption cells. See crbug.com/647678.
|
| + return;
|
| + }
|
| +
|
| + BOOL isOn = sender.isOn;
|
| + BOOL wasOn = _syncSetupService->IsSyncEnabled();
|
| + if (wasOn == isOn)
|
| + return;
|
| +
|
| + base::AutoReset<BOOL> autoReset(&_ignoreSyncStateChanges, YES);
|
| + _syncSetupService->SetSyncEnabled(isOn);
|
| +
|
| + BOOL isNowOn = _syncSetupService->IsSyncEnabled();
|
| + if (isNowOn == wasOn) {
|
| + DLOG(WARNING) << "Call to SetSyncEnabled(" << (isOn ? "YES" : "NO")
|
| + << ") failed.";
|
| + // This shouldn't happen, but in case there was an underlying sync problem,
|
| + // make sure the UI reflects sync's reality.
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncSwitch
|
| + sectionIdentifier:SectionIdentifierEnableSync];
|
| +
|
| + SyncSwitchItem* item = base::mac::ObjCCastStrict<SyncSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + item.on = isNowOn;
|
| + }
|
| + [self updateCollectionView];
|
| +}
|
| +
|
| +- (void)fixSyncErrorIfPossible {
|
| + if (![self isSyncErrorFixableByUserAction] || ![self shouldDisplaySyncError])
|
| + return;
|
| +
|
| + // Unrecoverable errors are special-cased to only do the signing out and back
|
| + // in from the Sync settings screen (where user interaction can safely be
|
| + // prevented).
|
| + if (_syncSetupService->GetSyncServiceState() ==
|
| + SyncSetupService::kSyncServiceUnrecoverableError) {
|
| + ChromeIdentity* authenticatedIdentity =
|
| + AuthenticationServiceFactory::GetForBrowserState(_browserState)
|
| + ->GetAuthenticatedIdentity();
|
| + [self startSwitchAccountForIdentity:authenticatedIdentity
|
| + postSignInAction:POST_SIGNIN_ACTION_START_SYNC];
|
| + return;
|
| + }
|
| +
|
| + base::scoped_nsobject<GenericChromeCommand> command(
|
| + [ios_internal::sync::GetSyncCommandForBrowserState(_browserState)
|
| + retain]);
|
| + [self chromeExecuteCommand:command];
|
| +}
|
| +
|
| +- (void)startSwitchAccountForIdentity:(ChromeIdentity*)identity
|
| + postSignInAction:(PostSignInAction)postSignInAction {
|
| + if (!_syncSetupService->IsSyncEnabled())
|
| + return;
|
| +
|
| + _authenticationOperationInProgress = YES;
|
| + [[NSNotificationCenter defaultCenter]
|
| + postNotificationName:kSwitchAccountWillStartNotification
|
| + object:self];
|
| + [self preventUserInteraction];
|
| + DCHECK(!_authenticationFlow);
|
| + _authenticationFlow.reset([[AuthenticationFlow alloc]
|
| + initWithBrowserState:_browserState
|
| + identity:identity
|
| + shouldClearData:SHOULD_CLEAR_DATA_USER_CHOICE
|
| + postSignInAction:postSignInAction
|
| + presentingViewController:self]);
|
| +
|
| + base::WeakNSObject<SyncSettingsCollectionViewController> weakSelf(self);
|
| + [_authenticationFlow startSignInWithCompletion:^(BOOL success) {
|
| + [weakSelf didSwitchAccountWithSuccess:success];
|
| + }];
|
| +}
|
| +
|
| +- (void)didSwitchAccountWithSuccess:(BOOL)success {
|
| + _authenticationFlow.reset();
|
| + [self allowUserInteraction];
|
| + [[NSNotificationCenter defaultCenter]
|
| + postNotificationName:kSwitchAccountDidFinishNotification
|
| + object:self];
|
| + _authenticationOperationInProgress = NO;
|
| + if (![self popViewIfSignedOut]) {
|
| + // Only reload the view if it wasn't popped.
|
| + [self reloadData];
|
| + }
|
| +}
|
| +
|
| +- (void)changeSyncEverythingStatusToOn:(UISwitch*)sender {
|
| + if (!_syncSetupService->IsSyncEnabled() ||
|
| + [self shouldDisableSettingsOnSyncError])
|
| + return;
|
| + BOOL isOn = sender.isOn;
|
| + BOOL wasOn = _syncSetupService->IsSyncingAllDataTypes();
|
| + if (wasOn == isOn)
|
| + return;
|
| +
|
| + base::AutoReset<BOOL> autoReset(&_ignoreSyncStateChanges, YES);
|
| + _syncSetupService->SetSyncingAllDataTypes(isOn);
|
| +
|
| + // Base the UI on the actual sync value, not the toggle.
|
| + BOOL isNowOn = _syncSetupService->IsSyncingAllDataTypes();
|
| + if (isNowOn == wasOn) {
|
| + DLOG(WARNING) << "Call to SetSyncingAllDataTypes(" << (isOn ? "YES" : "NO")
|
| + << ") failed";
|
| + // No change - there was a sync-level problem that didn't allow the change.
|
| + // This really shouldn't happen, but just in case, make sure the UI reflects
|
| + // sync's reality.
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncEverything
|
| + sectionIdentifier:SectionIdentifierSyncServices];
|
| + SyncSwitchItem* item = base::mac::ObjCCastStrict<SyncSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + item.on = isNowOn;
|
| + }
|
| + [self updateCollectionView];
|
| +}
|
| +
|
| +- (void)changeDataTypeSyncStatusToOn:(UISwitch*)sender {
|
| + if (!_syncSetupService->IsSyncEnabled() ||
|
| + _syncSetupService->IsSyncingAllDataTypes() ||
|
| + [self shouldDisableSettingsOnSyncError])
|
| + return;
|
| +
|
| + BOOL isOn = sender.isOn;
|
| +
|
| + SyncSwitchItem* syncSwitchItem =
|
| + base::mac::ObjCCastStrict<SyncSwitchItem>([self.collectionViewModel
|
| + itemAtIndexPath:[self indexPathForTag:sender.tag]]);
|
| + SyncSetupService::SyncableDatatype dataType =
|
| + (SyncSetupService::SyncableDatatype)syncSwitchItem.dataType;
|
| + syncer::ModelType modelType = _syncSetupService->GetModelType(dataType);
|
| +
|
| + base::AutoReset<BOOL> autoReset(&_ignoreSyncStateChanges, YES);
|
| + _syncSetupService->SetDataTypeEnabled(modelType, isOn);
|
| +}
|
| +
|
| +- (void)showEncryption {
|
| + browser_sync::ProfileSyncService* syncService =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
|
| + if (!syncService->IsEngineInitialized() ||
|
| + !_syncSetupService->IsSyncEnabled() ||
|
| + [self shouldDisableSettingsOnSyncError])
|
| + return;
|
| +
|
| + base::scoped_nsobject<UIViewController> controllerToPush;
|
| + // If there was a sync error, prompt the user to enter the passphrase.
|
| + // Otherwise, show the full encryption options.
|
| + if (syncService->IsPassphraseRequired()) {
|
| + controllerToPush.reset(
|
| + [[SyncEncryptionPassphraseCollectionViewController alloc]
|
| + initWithBrowserState:_browserState]);
|
| + } else {
|
| + controllerToPush.reset([[SyncEncryptionCollectionViewController alloc]
|
| + initWithBrowserState:_browserState]);
|
| + }
|
| + [self.navigationController pushViewController:controllerToPush animated:YES];
|
| +}
|
| +
|
| +#pragma mark Updates
|
| +
|
| +- (void)updateCollectionView {
|
| + base::WeakNSObject<SyncSettingsCollectionViewController> weakSelf(self);
|
| + [self.collectionView performBatchUpdates:^{
|
| + [weakSelf updateCollectionViewInternal];
|
| + }
|
| + completion:nil];
|
| +}
|
| +
|
| +- (void)updateCollectionViewInternal {
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncSwitch
|
| + sectionIdentifier:SectionIdentifierEnableSync];
|
| +
|
| + SyncSwitchItem* syncItem = base::mac::ObjCCastStrict<SyncSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + syncItem.on = _syncSetupService->IsSyncEnabled();
|
| + [self reconfigureCellsForItems:@[ syncItem ]
|
| + inSectionWithIdentifier:SectionIdentifierEnableSync];
|
| +
|
| + // Update Sync Accounts section.
|
| + if ([self hasAccountsSection]) {
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierSyncAccounts];
|
| + NSInteger itemsCount =
|
| + [self.collectionViewModel numberOfItemsInSection:section];
|
| + NSMutableArray* accountsToReconfigure =
|
| + [[[NSMutableArray alloc] init] autorelease];
|
| + for (NSInteger item = 0; item < itemsCount; ++item) {
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeAccount
|
| + sectionIdentifier:SectionIdentifierSyncAccounts
|
| + atIndex:item];
|
| + CollectionViewAccountItem* accountItem =
|
| + base::mac::ObjCCastStrict<CollectionViewAccountItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + accountItem.enabled = _syncSetupService->IsSyncEnabled();
|
| + [accountsToReconfigure addObject:accountItem];
|
| + }
|
| + [self reconfigureCellsForItems:accountsToReconfigure
|
| + inSectionWithIdentifier:SectionIdentifierSyncAccounts];
|
| + }
|
| +
|
| + // Update Sync Services section.
|
| + indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncEverything
|
| + sectionIdentifier:SectionIdentifierSyncServices];
|
| + SyncSwitchItem* syncEverythingItem =
|
| + base::mac::ObjCCastStrict<SyncSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + syncEverythingItem.on = _syncSetupService->IsSyncingAllDataTypes();
|
| + syncEverythingItem.enabled = [self shouldSyncEverythingItemBeEnabled];
|
| + [self reconfigureCellsForItems:@[ syncEverythingItem ]
|
| + inSectionWithIdentifier:SectionIdentifierSyncServices];
|
| +
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierSyncServices];
|
| + NSInteger itemsCount =
|
| + [self.collectionViewModel numberOfItemsInSection:section];
|
| + // Syncable data types cells are offset by the Sync Everything cell.
|
| + NSMutableArray* switchsToReconfigure =
|
| + [[[NSMutableArray alloc] init] autorelease];
|
| + for (NSInteger item = 1; item < itemsCount; ++item) {
|
| + NSUInteger index = item - 1;
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncableDataType
|
| + sectionIdentifier:SectionIdentifierSyncServices
|
| + atIndex:index];
|
| + SyncSwitchItem* syncSwitchItem = base::mac::ObjCCastStrict<SyncSwitchItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + SyncSetupService::SyncableDatatype dataType =
|
| + (SyncSetupService::SyncableDatatype)syncSwitchItem.dataType;
|
| + syncer::ModelType modelType = _syncSetupService->GetModelType(dataType);
|
| + syncSwitchItem.on = _syncSetupService->IsDataTypeEnabled(modelType);
|
| + syncSwitchItem.enabled = [self shouldSyncableItemsBeEnabled];
|
| + [switchsToReconfigure addObject:syncSwitchItem];
|
| + }
|
| + [self reconfigureCellsForItems:switchsToReconfigure
|
| + inSectionWithIdentifier:SectionIdentifierSyncServices];
|
| +
|
| + // Update Encryption cell.
|
| + [self updateEncryptionCell];
|
| +
|
| + // Add/Remove the Sync Error. This is the only update that can change index
|
| + // paths. It is done last because self.collectionViewModel isn't aware of
|
| + // the performBatchUpdates:completion: order of update/remove/delete.
|
| + [self updateSyncError];
|
| +}
|
| +
|
| +- (void)updateSyncError {
|
| + BOOL shouldDisplayError = [self shouldDisplaySyncError];
|
| + BOOL isDisplayingError =
|
| + [self.collectionViewModel hasItemForItemType:ItemTypeSyncError
|
| + sectionIdentifier:SectionIdentifierSyncError];
|
| + if (shouldDisplayError && !isDisplayingError) {
|
| + [self.collectionViewModel
|
| + insertSectionWithIdentifier:SectionIdentifierSyncError
|
| + atIndex:0];
|
| + [self.collectionViewModel addItem:[self syncErrorItem]
|
| + toSectionWithIdentifier:SectionIdentifierSyncError];
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierSyncError];
|
| + [self.collectionView insertSections:[NSIndexSet indexSetWithIndex:section]];
|
| + } else if (!shouldDisplayError && isDisplayingError) {
|
| + NSInteger section = [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierSyncError];
|
| + [self.collectionViewModel
|
| + removeSectionWithIdentifier:SectionIdentifierSyncError];
|
| + [self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:section]];
|
| + }
|
| +}
|
| +
|
| +- (void)updateEncryptionCell {
|
| + BOOL shouldDisplayEncryptionError = [self shouldDisplayEncryptionError];
|
| + NSIndexPath* indexPath = [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeEncryption
|
| + sectionIdentifier:SectionIdentifierEncryptionAndFooter];
|
| + TextAndErrorItem* item = base::mac::ObjCCastStrict<TextAndErrorItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| + item.shouldDisplayError = shouldDisplayEncryptionError;
|
| + item.enabled = [self shouldEncryptionItemBeEnabled];
|
| + [self reconfigureCellsForItems:@[ item ]
|
| + inSectionWithIdentifier:SectionIdentifierEncryptionAndFooter];
|
| +}
|
| +
|
| +- (void)updateAccountItem:(CollectionViewAccountItem*)item
|
| + withIdentity:(ChromeIdentity*)identity {
|
| + item.image = [_avatarCache resizedAvatarForIdentity:identity];
|
| + item.text = identity.userEmail;
|
| + item.chromeIdentity = identity;
|
| +}
|
| +
|
| +#pragma mark Helpers
|
| +
|
| +- (BOOL)hasAccountsSection {
|
| + OAuth2TokenService* tokenService =
|
| + OAuth2TokenServiceFactory::GetForBrowserState(_browserState);
|
| + return _allowSwitchSyncAccount && tokenService->GetAccounts().size() > 1;
|
| +}
|
| +
|
| +- (BOOL)shouldDisplaySyncError {
|
| + SyncSetupService::SyncServiceState state =
|
| + _syncSetupService->GetSyncServiceState();
|
| + return state != SyncSetupService::kNoSyncServiceError;
|
| +}
|
| +
|
| +- (BOOL)shouldDisableSettingsOnSyncError {
|
| + SyncSetupService::SyncServiceState state =
|
| + _syncSetupService->GetSyncServiceState();
|
| + return state != SyncSetupService::kNoSyncServiceError &&
|
| + state != SyncSetupService::kSyncServiceNeedsPassphrase;
|
| +}
|
| +
|
| +- (BOOL)shouldDisplayEncryptionError {
|
| + return _syncSetupService->GetSyncServiceState() ==
|
| + SyncSetupService::kSyncServiceNeedsPassphrase;
|
| +}
|
| +
|
| +- (BOOL)isSyncErrorFixableByUserAction {
|
| + SyncSetupService::SyncServiceState state =
|
| + _syncSetupService->GetSyncServiceState();
|
| + return state == SyncSetupService::kSyncServiceNeedsPassphrase ||
|
| + state == SyncSetupService::kSyncServiceSignInNeedsUpdate ||
|
| + state == SyncSetupService::kSyncServiceUnrecoverableError;
|
| +}
|
| +
|
| +- (int)titleIdForSyncableDataType:(SyncSetupService::SyncableDatatype)datatype {
|
| + switch (datatype) {
|
| + case SyncSetupService::kSyncBookmarks:
|
| + return IDS_SYNC_DATATYPE_BOOKMARKS;
|
| + case SyncSetupService::kSyncOmniboxHistory:
|
| + return IDS_SYNC_DATATYPE_TYPED_URLS;
|
| + case SyncSetupService::kSyncPasswords:
|
| + return IDS_SYNC_DATATYPE_PASSWORDS;
|
| + case SyncSetupService::kSyncOpenTabs:
|
| + return IDS_SYNC_DATATYPE_TABS;
|
| + case SyncSetupService::kSyncAutofill:
|
| + return IDS_SYNC_DATATYPE_AUTOFILL;
|
| + case SyncSetupService::kSyncPreferences:
|
| + return IDS_SYNC_DATATYPE_PREFERENCES;
|
| + case SyncSetupService::kSyncReadingList:
|
| + return IDS_SYNC_DATATYPE_READING_LIST;
|
| + case SyncSetupService::kNumberOfSyncableDatatypes:
|
| + NOTREACHED();
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +- (BOOL)shouldEncryptionItemBeEnabled {
|
| + browser_sync::ProfileSyncService* syncService =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
|
| + return (syncService->IsEngineInitialized() &&
|
| + _syncSetupService->IsSyncEnabled() &&
|
| + ![self shouldDisableSettingsOnSyncError]);
|
| +}
|
| +
|
| +- (BOOL)shouldSyncEverythingItemBeEnabled {
|
| + return (_syncSetupService->IsSyncEnabled() &&
|
| + ![self shouldDisableSettingsOnSyncError]);
|
| +}
|
| +
|
| +- (BOOL)shouldSyncableItemsBeEnabled {
|
| + return (!_syncSetupService->IsSyncingAllDataTypes() &&
|
| + _syncSetupService->IsSyncEnabled() &&
|
| + ![self shouldDisableSettingsOnSyncError]);
|
| +}
|
| +
|
| +- (NSInteger)tagForIndexPath:(NSIndexPath*)indexPath {
|
| + DCHECK(indexPath.section ==
|
| + [self.collectionViewModel
|
| + sectionForSectionIdentifier:SectionIdentifierSyncServices]);
|
| + NSInteger index =
|
| + [self.collectionViewModel indexInItemTypeForIndexPath:indexPath];
|
| + return index + kTagShift;
|
| +}
|
| +
|
| +- (NSIndexPath*)indexPathForTag:(NSInteger)shiftedTag {
|
| + NSInteger unshiftedTag = shiftedTag - kTagShift;
|
| + return [self.collectionViewModel
|
| + indexPathForItemType:ItemTypeSyncableDataType
|
| + sectionIdentifier:SectionIdentifierSyncServices
|
| + atIndex:unshiftedTag];
|
| +}
|
| +
|
| +#pragma mark SyncObserverModelBridge
|
| +
|
| +- (void)onSyncStateChanged {
|
| + if (_ignoreSyncStateChanges || _authenticationOperationInProgress) {
|
| + return;
|
| + }
|
| + [self updateCollectionView];
|
| +}
|
| +
|
| +#pragma mark OAuth2TokenServiceObserverBridgeDelegate
|
| +
|
| +- (void)onEndBatchChanges {
|
| + if (_authenticationOperationInProgress) {
|
| + return;
|
| + }
|
| + if (![self popViewIfSignedOut]) {
|
| + // Only reload the view if it wasn't popped.
|
| + [self reloadData];
|
| + }
|
| +}
|
| +
|
| +#pragma mark SettingsControllerProtocol callbacks
|
| +
|
| +- (void)settingsWillBeDismissed {
|
| + [self stopBrowserStateServiceObservers];
|
| + [_authenticationFlow cancelAndDismiss];
|
| +}
|
| +
|
| +#pragma mark - ChromeIdentityServiceObserver
|
| +
|
| +- (void)onProfileUpdate:(ChromeIdentity*)identity {
|
| + CollectionViewAccountItem* item =
|
| + base::mac::ObjCCastStrict<CollectionViewAccountItem>(
|
| + [_identityMap objectForKey:identity.gaiaID]);
|
| + [self updateAccountItem:item withIdentity:identity];
|
| + [self reconfigureCellsForItems:@[ item ]
|
| + inSectionWithIdentifier:SectionIdentifierSyncAccounts];
|
| +}
|
| +
|
| +- (void)onChromeIdentityServiceWillBeDestroyed {
|
| + _identityServiceObserver.reset();
|
| +}
|
| +
|
| +@end
|
|
|