Commit ad71401e authored by Nohemi Fernandez's avatar Nohemi Fernandez Committed by Commit Bot

[iOS][MICE] Add sync error states to Sync Settings page.

Moves the Sync errors item out of Google Services into the Sync settings
page for the MICE experiment.

Bug: 1125631
Change-Id: I4f373a14e967e76d55f7d0aa7b8ed02a53c495df
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2461266
Commit-Queue: Nohemi Fernandez <fernandex@chromium.org>
Reviewed-by: default avatarJérôme Lebel <jlebel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816172}
parent 6c09107f
......@@ -28,6 +28,7 @@ source_set("google_services") {
"manage_sync_settings_table_view_controller.h",
"manage_sync_settings_table_view_controller.mm",
"manage_sync_settings_view_controller_model_delegate.h",
"sync_error_settings_command_handler.h",
]
deps = [
":constants",
......@@ -58,6 +59,7 @@ source_set("google_services") {
"//ios/chrome/browser/ui/alert_coordinator",
"//ios/chrome/browser/ui/authentication",
"//ios/chrome/browser/ui/authentication/cells",
"//ios/chrome/browser/ui/authentication/signin:signin_protected",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/icons",
......
......@@ -8,15 +8,6 @@
// Protocol to communicate user actions from the mediator to its coordinator.
@protocol GoogleServicesSettingsCommandHandler <NSObject>
// Restarts the authentication flow.
- (void)restartAuthenticationFlow;
// Opens the reauth sync dialog.
- (void)openReauthDialogAsSyncIsInAuthError;
// Opens the passphrase dialog.
- (void)openPassphraseDialog;
// Presents the sign-in dialog to the user.
- (void)showSignIn;
......@@ -33,9 +24,6 @@
// TODO(crbug.com/1043080): Remove web page API once MyGoogle UI is launched.
- (void)openManageGoogleAccountWebPage;
// Opens the trusted vault reauthentication dialog.
- (void)openTrustedVaultReauth;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_GOOGLE_SERVICES_SETTINGS_COMMAND_HANDLER_H_
......@@ -28,6 +28,7 @@
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.h"
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.h"
#import "ios/chrome/browser/ui/settings/google_services/sync_error_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
......@@ -42,7 +43,8 @@ using signin_metrics::PromoAction;
@interface GoogleServicesSettingsCoordinator () <
GoogleServicesSettingsCommandHandler,
GoogleServicesSettingsViewControllerPresentationDelegate,
ManageSyncSettingsCoordinatorDelegate>
ManageSyncSettingsCoordinatorDelegate,
SyncErrorSettingsCommandHandler>
// Google services settings mode.
@property(nonatomic, assign, readonly) GoogleServicesSettingsMode mode;
......@@ -111,6 +113,7 @@ using signin_metrics::PromoAction;
self.mediator.identityManager = IdentityManagerFactory::GetForBrowserState(
self.browser->GetBrowserState());
self.mediator.commandHandler = self;
self.mediator.syncErrorHandler = self;
self.mediator.syncService = ProfileSyncServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
viewController.modelDelegate = self.mediator;
......@@ -170,7 +173,7 @@ using signin_metrics::PromoAction;
isEqual:self.baseNavigationController.topViewController];
}
#pragma mark - GoogleServicesSettingsCommandHandler
#pragma mark - SyncErrorSettingsCommandHandler
- (void)restartAuthenticationFlow {
ChromeIdentity* authenticatedIdentity =
......@@ -222,6 +225,20 @@ using signin_metrics::PromoAction;
[self.baseNavigationController pushViewController:controller animated:YES];
}
- (void)openTrustedVaultReauth {
id<ApplicationCommands> applicationCommands =
static_cast<id<ApplicationCommands>>(
self.browser->GetCommandDispatcher());
[applicationCommands
showTrustedVaultReauthenticationFromViewController:
self.googleServicesSettingsViewController
retrievalTrigger:
syncer::KeyRetrievalTriggerForUMA::
kSettings];
}
#pragma mark - GoogleServicesSettingsCommandHandler
- (void)showSignIn {
__weak __typeof(self) weakSelf = self;
DCHECK(self.handler);
......@@ -287,18 +304,6 @@ using signin_metrics::PromoAction;
[handler closeSettingsUIAndOpenURL:command];
}
- (void)openTrustedVaultReauth {
id<ApplicationCommands> applicationCommands =
static_cast<id<ApplicationCommands>>(
self.browser->GetCommandDispatcher());
[applicationCommands
showTrustedVaultReauthenticationFromViewController:
self.googleServicesSettingsViewController
retrievalTrigger:
syncer::KeyRetrievalTriggerForUMA::
kSettings];
}
#pragma mark - GoogleServicesSettingsViewControllerPresentationDelegate
- (void)googleServicesSettingsViewControllerDidRemove:
......
......@@ -17,6 +17,7 @@ class AuthenticationService;
@protocol GoogleServicesSettingsCommandHandler;
@class GoogleServicesSettingsViewController;
class PrefService;
@protocol SyncErrorSettingsCommandHandler;
class SyncSetupService;
namespace syncer {
......@@ -41,6 +42,8 @@ class IdentityManager;
// Command handler.
@property(nonatomic, weak) id<GoogleServicesSettingsCommandHandler>
commandHandler;
// Sync error handler.
@property(nonatomic, weak) id<SyncErrorSettingsCommandHandler> syncErrorHandler;
// Sync service.
@property(nonatomic, assign) syncer::SyncService* syncService;
// Identity manager;
......
......@@ -30,6 +30,7 @@
#import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h"
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_constants.h"
#import "ios/chrome/browser/ui/settings/google_services/sync_error_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h"
#import "ios/chrome/browser/ui/settings/utils/observable_boolean.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
......@@ -323,6 +324,11 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
// Updates the sync section. If |notifyConsumer| is YES, the consumer is
// notified about model changes.
- (void)updateSyncSection:(BOOL)notifyConsumer {
if (base::FeatureList::IsEnabled(signin::kMobileIdentityConsistency)) {
// Chrome adds the sync section within "Manage Your Settings" for the MICE
// experiment.
return;
}
BOOL needsAccountSigninItemUpdate = [self updateAccountSignInItem];
BOOL needsSyncErrorItemsUpdate = [self updateSyncErrorItems];
BOOL needsSyncChromeDataItemUpdate = [self updateSyncChromeDataItem];
......@@ -596,12 +602,7 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
}
- (BOOL)shouldDisplaySync {
BOOL experimentEnabled =
base::FeatureList::IsEnabled(signin::kMobileIdentityConsistency);
BOOL firstSetupWithExperiment =
!self.syncSetupService->IsFirstSetupComplete() && experimentEnabled;
return (firstSetupWithExperiment || !experimentEnabled) &&
self.isAuthenticated && !self.isSyncDisabledByAdministrator;
return self.isAuthenticated && !self.isSyncDisabledByAdministrator;
}
- (ItemArray)nonPersonalizedItems {
......@@ -815,7 +816,11 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
(GoogleServicesSettingsViewController*)controller {
DCHECK_EQ(self.consumer, controller);
[self loadIdentitySection];
[self loadSyncSection];
// For the MICE experiment Chrome will display the Sync section within "Manage
// Sync Settings".
if (!base::FeatureList::IsEnabled(signin::kMobileIdentityConsistency)) {
[self loadSyncSection];
}
[self loadNonPersonalizedSection];
_identityManagerObserverBridge.reset(
new signin::IdentityManagerObserverBridge(self.identityManager, self));
......@@ -905,16 +910,16 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
[self.commandHandler showSignIn];
break;
case RestartAuthenticationFlowErrorItemType:
[self.commandHandler restartAuthenticationFlow];
[self.syncErrorHandler restartAuthenticationFlow];
break;
case ReauthDialogAsSyncIsInAuthErrorItemType:
[self.commandHandler openReauthDialogAsSyncIsInAuthError];
[self.syncErrorHandler openReauthDialogAsSyncIsInAuthError];
break;
case ShowPassphraseDialogErrorItemType:
[self.commandHandler openPassphraseDialog];
[self.syncErrorHandler openPassphraseDialog];
break;
case SyncNeedsTrustedVaultKeyErrorItemType:
[self.commandHandler openTrustedVaultReauth];
[self.syncErrorHandler openTrustedVaultReauth];
break;
case ManageSyncItemType:
[self.commandHandler openManageSyncSettings];
......
......@@ -10,12 +10,9 @@
// Protocol to communicate user actions from the mediator to its coordinator.
@protocol ManageSyncSettingsCommandHandler <NSObject>
// Opens the passphrase dialog.
- (void)openPassphraseDialog;
// Opens the trusted vault reauthentication dialog.
- (void)openTrustedVaultReauth;
// Opens the "Web & App Activity" dialog.
- (void)openWebAppActivityDialog;
// Opens the "Data from Chrome sync" web page.
- (void)openDataFromChromeSyncWebPage;
......
......@@ -20,6 +20,9 @@
// yet.
- (void)reloadItem:(TableViewItem*)item;
// Reloads |sections|. Does nothing if the model is not loaded yet.
- (void)reloadSections:(NSIndexSet*)sections;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_MANAGE_SYNC_SETTINGS_CONSUMER_H_
......@@ -20,13 +20,16 @@
#include "ios/chrome/browser/sync/profile_sync_service_factory.h"
#include "ios/chrome/browser/sync/sync_observer_bridge.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/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browsing_data_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/icons/chrome_icon.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/google_services/sync_error_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/sync/sync_encryption_table_view_controller.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
......@@ -38,9 +41,13 @@
#error "This file requires ARC support."
#endif
using signin_metrics::AccessPoint;
using signin_metrics::PromoAction;
@interface ManageSyncSettingsCoordinator () <
ChromeIdentityBrowserOpener,
ManageSyncSettingsCommandHandler,
SyncErrorSettingsCommandHandler,
ManageSyncSettingsTableViewControllerPresentationDelegate,
SyncObserverModelBridge> {
// Sync observer.
......@@ -54,9 +61,13 @@
@property(nonatomic, strong) ManageSyncSettingsMediator* mediator;
// Sync service.
@property(nonatomic, assign, readonly) syncer::SyncService* syncService;
// Authentication service.
@property(nonatomic, assign, readonly) AuthenticationService* authService;
// Dismiss callback for Web and app setting details view.
@property(nonatomic, copy) ios::DismissASMViewControllerBlock
dismissWebAndAppSettingDetailsControllerBlock;
// Manages the authentication flow for a given identity.
@property(nonatomic, strong) AuthenticationFlow* authenticationFlow;
@end
......@@ -81,7 +92,9 @@
userPrefService:self.browser->GetBrowserState()->GetPrefs()];
self.mediator.syncSetupService = SyncSetupServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
self.mediator.authService = self.authService;
self.mediator.commandHandler = self;
self.mediator.syncErrorHandler = self;
self.viewController = [[ManageSyncSettingsTableViewController alloc]
initWithStyle:UITableViewStyleGrouped];
self.viewController.serviceDelegate = self.mediator;
......@@ -100,6 +113,11 @@
self.browser->GetBrowserState());
}
- (AuthenticationService*)authService {
return AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
}
#pragma mark - Private
// Closes the Manage sync settings view controller.
......@@ -137,6 +155,32 @@
#pragma mark - ManageSyncSettingsCommandHandler
- (void)openWebAppActivityDialog {
AuthenticationService* authService =
AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
base::RecordAction(base::UserMetricsAction(
"Signin_AccountSettings_GoogleActivityControlsClicked"));
self.dismissWebAndAppSettingDetailsControllerBlock =
ios::GetChromeBrowserProvider()
->GetChromeIdentityService()
->PresentWebAndAppSettingDetailsController(
authService->GetAuthenticatedIdentity(), self.viewController,
YES);
}
- (void)openDataFromChromeSyncWebPage {
GURL url = google_util::AppendGoogleLocaleParam(
GURL(kSyncGoogleDashboardURL),
GetApplicationContext()->GetApplicationLocale());
OpenNewTabCommand* command = [OpenNewTabCommand commandWithURLFromChrome:url];
id<ApplicationCommands> handler = HandlerForProtocol(
self.browser->GetCommandDispatcher(), ApplicationCommands);
[handler closeSettingsUIAndOpenURL:command];
}
#pragma mark - SyncErrorSettingsCommandHandler
- (void)openPassphraseDialog {
DCHECK(self.mediator.shouldEncryptionItemBeEnabled);
UIViewController<SettingsRootViewControlling>* controllerToPush;
......@@ -169,28 +213,44 @@
kSettings];
}
- (void)openWebAppActivityDialog {
AuthenticationService* authService =
- (void)restartAuthenticationFlow {
ChromeIdentity* authenticatedIdentity =
AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
base::RecordAction(base::UserMetricsAction(
"Signin_AccountSettings_GoogleActivityControlsClicked"));
self.dismissWebAndAppSettingDetailsControllerBlock =
ios::GetChromeBrowserProvider()
->GetChromeIdentityService()
->PresentWebAndAppSettingDetailsController(
authService->GetAuthenticatedIdentity(), self.viewController,
YES);
self.browser->GetBrowserState())
->GetAuthenticatedIdentity();
[self.viewController preventUserInteraction];
DCHECK(!self.authenticationFlow);
self.authenticationFlow =
[[AuthenticationFlow alloc] initWithBrowser:self.browser
identity:authenticatedIdentity
shouldClearData:SHOULD_CLEAR_DATA_USER_CHOICE
postSignInAction:POST_SIGNIN_ACTION_START_SYNC
presentingViewController:self.viewController];
self.authenticationFlow.dispatcher = HandlerForProtocol(
self.browser->GetCommandDispatcher(), BrowsingDataCommands);
__weak ManageSyncSettingsCoordinator* weakSelf = self;
[self.authenticationFlow startSignInWithCompletion:^(BOOL success) {
// TODO(crbug.com/889919): Needs to add histogram for |success|.
DCHECK(weakSelf.authenticationFlow);
weakSelf.authenticationFlow = nil;
[weakSelf.viewController allowUserInteraction];
}];
}
- (void)openDataFromChromeSyncWebPage {
GURL url = google_util::AppendGoogleLocaleParam(
GURL(kSyncGoogleDashboardURL),
GetApplicationContext()->GetApplicationLocale());
OpenNewTabCommand* command = [OpenNewTabCommand commandWithURLFromChrome:url];
id<ApplicationCommands> handler = HandlerForProtocol(
self.browser->GetCommandDispatcher(), ApplicationCommands);
[handler closeSettingsUIAndOpenURL:command];
- (void)openReauthDialogAsSyncIsInAuthError {
ChromeIdentity* identity = self.authService->GetAuthenticatedIdentity();
if (self.authService->HasCachedMDMErrorForIdentity(identity)) {
self.authService->ShowMDMErrorDialogForIdentity(identity);
return;
}
// Sync enters in a permanent auth error state when fetching an access token
// fails with invalid credentials. This corresponds to Gaia responding with an
// "invalid grant" error. The current implementation of the iOS SSOAuth
// library user by Chrome removes the identity from the device when receiving
// an "invalid grant" response, which leads to the account being also signed
// out of Chrome. So the sync permanent auth error is a transient state on
// iOS. The decision was to avoid handling this error in the UI, which means
// that the reauth dialog is not actually presented on iOS.
}
#pragma mark - SyncObserverModelBridge
......
......@@ -10,8 +10,10 @@
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_service_delegate.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_view_controller_model_delegate.h"
@protocol SyncErrorSettingsCommandHandler;
@protocol ManageSyncSettingsCommandHandler;
@protocol ManageSyncSettingsConsumer;
class AuthenticationService;
class PrefService;
class SyncSetupService;
namespace syncer {
......@@ -27,8 +29,12 @@ class SyncService;
@property(nonatomic, weak) id<ManageSyncSettingsConsumer> consumer;
// Sync setup service.
@property(nonatomic, assign) SyncSetupService* syncSetupService;
// Authentication service.
@property(nonatomic, assign) AuthenticationService* authService;
// Command handler.
@property(nonatomic, weak) id<ManageSyncSettingsCommandHandler> commandHandler;
// Error command handler.
@property(nonatomic, weak) id<SyncErrorSettingsCommandHandler> syncErrorHandler;
// Returns YES if the encryption item should be enabled.
@property(nonatomic, assign, readonly) BOOL shouldEncryptionItemBeEnabled;
......
......@@ -9,16 +9,21 @@
#include "base/mac/foundation_util.h"
#include "base/notreached.h"
#include "components/autofill/core/common/autofill_prefs.h"
#import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/driver/sync_service.h"
#import "ios/chrome/browser/signin/authentication_service.h"
#include "ios/chrome/browser/sync/profile_sync_service_factory.h"
#include "ios/chrome/browser/sync/sync_observer_bridge.h"
#include "ios/chrome/browser/sync/sync_setup_service.h"
#import "ios/chrome/browser/ui/list_model/list_model.h"
#import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
#import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h"
#import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h"
#import "ios/chrome/browser/ui/settings/google_services/sync_error_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_image_item.h"
......@@ -43,6 +48,8 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
SyncDataTypeSectionIdentifier = kSectionIdentifierEnumZero,
// Advanced settings.
AdvancedSettingsSectionIdentifier,
// Sync errors.
SyncErrorsSectionIdentifier,
};
// List of items. For implementation details in
......@@ -77,13 +84,23 @@ typedef NS_ENUM(NSInteger, ItemType) {
GoogleActivityControlsItemType,
// Data from Chrome sync.
DataFromChromeSync,
// Sync errors.
RestartAuthenticationFlowErrorItemType,
ReauthDialogAsSyncIsInAuthErrorItemType,
ShowPassphraseDialogErrorItemType,
SyncNeedsTrustedVaultKeyErrorItemType,
SyncDisabledByAdministratorErrorItemType,
SyncSettingsNotCofirmedErrorItemType,
};
// Enterprise icon.
NSString* kGoogleServicesEnterpriseImage = @"google_services_enterprise";
// Sync error icon.
NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
} // namespace
@interface ManageSyncSettingsMediator () <BooleanObserver,
IdentityManagerObserverBridgeDelegate,
SyncObserverModelBridge> {
// Sync observer.
std::unique_ptr<SyncObserverBridge> _syncObserver;
......@@ -104,10 +121,16 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
@property(nonatomic, strong) SyncSwitchItem* autocompleteWalletItem;
// Encryption item.
@property(nonatomic, strong) TableViewImageItem* encryptionItem;
// Sync error item.
@property(nonatomic, strong) TableViewItem* syncErrorItem;
// Returns YES if the sync data items should be enabled.
@property(nonatomic, assign, readonly) BOOL shouldSyncDataItemEnabled;
// Returns whether the Sync settings should be disabled because of a Sync error.
@property(nonatomic, assign, readonly) BOOL disabledBecauseOfSyncError;
// Returns YES if the user cannot turn on sync for enterprise policy reasons.
@property(nonatomic, assign, readonly) BOOL isSyncDisabledByAdministrator;
// Returns YES if the user is authenticated.
@property(nonatomic, assign, readonly) BOOL isAuthenticated;
@end
......@@ -392,6 +415,7 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
- (void)manageSyncSettingsTableViewControllerLoadModel:
(id<ManageSyncSettingsConsumer>)controller {
DCHECK_EQ(self.consumer, controller);
[self loadSyncErrorsSection];
[self loadSyncDataTypeSection];
[self loadAdvancedSettingsSection];
}
......@@ -409,11 +433,23 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
// The UI should not updated so the switch animations can run smoothly.
return;
}
[self updateSyncErrorsSection:YES];
[self updateSyncEverythingItemNotifyConsumer:YES];
[self updateSyncItemsNotifyConsumer:YES];
[self updateEncryptionItem:YES];
}
#pragma mark - IdentityManagerObserverBridgeDelegate
- (void)onPrimaryAccountSet:(const CoreAccountInfo&)primaryAccountInfo {
[self updateSyncErrorsSection:YES];
}
- (void)onPrimaryAccountCleared:
(const CoreAccountInfo&)previousPrimaryAccountInfo {
[self updateSyncErrorsSection:YES];
}
#pragma mark - ManageSyncSettingsServiceDelegate
- (void)toggleSwitchItem:(TableViewItem*)item withValue:(BOOL)value {
......@@ -465,6 +501,12 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
case EncryptionItemType:
case GoogleActivityControlsItemType:
case DataFromChromeSync:
case RestartAuthenticationFlowErrorItemType:
case ReauthDialogAsSyncIsInAuthErrorItemType:
case ShowPassphraseDialogErrorItemType:
case SyncNeedsTrustedVaultKeyErrorItemType:
case SyncDisabledByAdministratorErrorItemType:
case SyncSettingsNotCofirmedErrorItemType:
NOTREACHED();
break;
}
......@@ -479,10 +521,10 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
case EncryptionItemType:
if (self.syncSetupService->GetSyncServiceState() ==
SyncSetupService::kSyncServiceNeedsTrustedVaultKey) {
[self.commandHandler openTrustedVaultReauth];
[self.syncErrorHandler openTrustedVaultReauth];
break;
}
[self.commandHandler openPassphraseDialog];
[self.syncErrorHandler openPassphraseDialog];
break;
case GoogleActivityControlsItemType:
[self.commandHandler openWebAppActivityDialog];
......@@ -490,6 +532,18 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
case DataFromChromeSync:
[self.commandHandler openDataFromChromeSyncWebPage];
break;
case RestartAuthenticationFlowErrorItemType:
[self.syncErrorHandler restartAuthenticationFlow];
break;
case ReauthDialogAsSyncIsInAuthErrorItemType:
[self.syncErrorHandler openReauthDialogAsSyncIsInAuthError];
break;
case ShowPassphraseDialogErrorItemType:
[self.syncErrorHandler openPassphraseDialog];
break;
case SyncNeedsTrustedVaultKeyErrorItemType:
[self.syncErrorHandler openTrustedVaultReauth];
break;
case SyncEverythingItemType:
case AutofillDataTypeItemType:
case BookmarksDataTypeItemType:
......@@ -499,9 +553,165 @@ NSString* kGoogleServicesSyncErrorImage = @"google_services_sync_error";
case ReadingListDataTypeItemType:
case SettingsDataTypeItemType:
case AutocompleteWalletItemType:
case SyncDisabledByAdministratorErrorItemType:
case SyncSettingsNotCofirmedErrorItemType:
// Nothing to do.
break;
}
}
// Creates an item to display the sync error. |itemType| should only be one of
// those types:
// + RestartAuthenticationFlowErrorItemType
// + ReauthDialogAsSyncIsInAuthErrorItemType
// + ShowPassphraseDialogErrorItemType
// + SyncNeedsTrustedVaultKeyErrorItemType
// + SyncSettingsNotCofirmedErrorItemType
- (TableViewItem*)createSyncErrorItemWithItemType:(NSInteger)itemType {
DCHECK(itemType == RestartAuthenticationFlowErrorItemType ||
itemType == ReauthDialogAsSyncIsInAuthErrorItemType ||
itemType == ShowPassphraseDialogErrorItemType ||
itemType == SyncNeedsTrustedVaultKeyErrorItemType ||
itemType == SyncSettingsNotCofirmedErrorItemType);
SettingsImageDetailTextItem* syncErrorItem =
[[SettingsImageDetailTextItem alloc] initWithType:itemType];
syncErrorItem.text = GetNSString(IDS_IOS_SYNC_ERROR_TITLE);
syncErrorItem.detailText =
GetSyncErrorDescriptionForSyncSetupService(self.syncSetupService);
if (itemType == SyncSettingsNotCofirmedErrorItemType) {
// Special case for the sync error title.
syncErrorItem.text = GetNSString(IDS_IOS_SYNC_SETUP_NOT_CONFIRMED_TITLE);
} else if (itemType == ShowPassphraseDialogErrorItemType) {
// Special case only for the sync passphrase error message. The regular
// error message should be still be displayed in the first settings screen.
syncErrorItem.detailText = GetNSString(
IDS_IOS_GOOGLE_SERVICES_SETTINGS_ENTER_PASSPHRASE_TO_START_SYNC);
} else if (itemType == SyncNeedsTrustedVaultKeyErrorItemType) {
// Special case only for the sync encryption key error message. The regular
// error message should be still be displayed in the first settings screen.
syncErrorItem.detailText =
GetNSString(IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_ENCRYPTION_FIX_NOW);
// Also override the title to be more accurate, if only passwords are being
// encrypted.
if (!self.syncSetupService->IsEncryptEverythingEnabled()) {
syncErrorItem.text = GetNSString(IDS_IOS_SYNC_PASSWORDS_ERROR_TITLE);
}
}
syncErrorItem.image = [UIImage imageNamed:kGoogleServicesSyncErrorImage];
return syncErrorItem;
}
// Loads the sync errors section.
- (void)loadSyncErrorsSection {
[self.consumer.tableViewModel
addSectionWithIdentifier:SyncErrorsSectionIdentifier];
[self updateSyncErrorsSection:NO];
}
// Updates the sync errors section. If |notifyConsumer| is YES, the consumer is
// notified about model changes.
- (void)updateSyncErrorsSection:(BOOL)notifyConsumer {
if (!base::FeatureList::IsEnabled(signin::kMobileIdentityConsistency)) {
return;
}
BOOL needsSyncErrorItemsUpdate = [self updateSyncErrorItems];
if (notifyConsumer && needsSyncErrorItemsUpdate) {
NSUInteger sectionIndex = [self.consumer.tableViewModel
sectionForSectionIdentifier:SyncErrorsSectionIdentifier];
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:sectionIndex];
[self.consumer reloadSections:indexSet];
}
}
// Adds, removes and updates the sync error item in the model as needed. Returns
// YES if the consumer should be notified.
- (BOOL)updateSyncErrorItems {
TableViewModel* model = self.consumer.tableViewModel;
BOOL hasError = NO;
ItemType type;
if (self.isSyncDisabledByAdministrator) {
type = SyncDisabledByAdministratorErrorItemType;
hasError = YES;
} else if (self.isAuthenticated && self.syncSetupService->IsSyncEnabled()) {
switch (self.syncSetupService->GetSyncServiceState()) {
case SyncSetupService::kSyncServiceUnrecoverableError:
type = RestartAuthenticationFlowErrorItemType;
hasError = YES;
break;
case SyncSetupService::kSyncServiceSignInNeedsUpdate:
type = ReauthDialogAsSyncIsInAuthErrorItemType;
hasError = YES;
break;
case SyncSetupService::kSyncServiceNeedsPassphrase:
type = ShowPassphraseDialogErrorItemType;
hasError = YES;
break;
case SyncSetupService::kSyncServiceNeedsTrustedVaultKey:
type = SyncNeedsTrustedVaultKeyErrorItemType;
hasError = YES;
break;
case SyncSetupService::kSyncSettingsNotConfirmed:
type = SyncSettingsNotCofirmedErrorItemType;
hasError = YES;
break;
case SyncSetupService::kNoSyncServiceError:
case SyncSetupService::kSyncServiceCouldNotConnect:
case SyncSetupService::kSyncServiceServiceUnavailable:
break;
}
}
if ((!hasError && !self.syncErrorItem) ||
(hasError && self.syncErrorItem && type == self.syncErrorItem.type)) {
// Nothing to update.
return NO;
}
if (self.syncErrorItem) {
// Remove the previous sync error item, since it is either the wrong error
// (if hasError is YES), or there is no error anymore.
[model removeItemWithType:self.syncErrorItem.type
fromSectionWithIdentifier:SyncErrorsSectionIdentifier];
self.syncErrorItem = nil;
if (!hasError)
return YES;
}
// Add the sync error item and its section.
if (type == SyncDisabledByAdministratorErrorItemType) {
self.syncErrorItem = [self createSyncDisabledByAdministratorErrorItem];
} else {
self.syncErrorItem = [self createSyncErrorItemWithItemType:type];
}
[model insertItem:self.syncErrorItem
inSectionWithIdentifier:SyncErrorsSectionIdentifier
atIndex:0];
return YES;
}
// Returns an item to show to the user the sync cannot be turned on for an
// enterprise policy reason.
- (TableViewItem*)createSyncDisabledByAdministratorErrorItem {
TableViewImageItem* item = [[TableViewImageItem alloc]
initWithType:SyncDisabledByAdministratorErrorItemType];
item.image = [UIImage imageNamed:kGoogleServicesEnterpriseImage];
item.title = GetNSString(
IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_DISABLBED_BY_ADMINISTRATOR_TITLE);
item.enabled = NO;
item.textColor = UIColor.cr_secondaryLabelColor;
return item;
}
#pragma mark - Properties
- (BOOL)isSyncDisabledByAdministrator {
return self.syncService->GetDisableReasons().Has(
syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
}
- (BOOL)isAuthenticated {
return self.authService->IsAuthenticated();
}
@end
......@@ -90,6 +90,15 @@
withRowAnimation:UITableViewRowAnimationNone];
}
- (void)reloadSections:(NSIndexSet*)sections {
if (!self.tableViewModel) {
// No need to reload since the model has not been loaded yet.
return;
}
[self.tableView reloadSections:sections
withRowAnimation:UITableViewRowAnimationNone];
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView*)tableView
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SYNC_ERROR_SETTINGS_COMMAND_HANDLER_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SYNC_ERROR_SETTINGS_COMMAND_HANDLER_H_
// Protocol to communicate actions following Sync errors from the mediator to
// its coordinator.
@protocol SyncErrorSettingsCommandHandler <NSObject>
// Restarts the authentication flow.
- (void)restartAuthenticationFlow;
// Opens the reauth sync dialog.
- (void)openReauthDialogAsSyncIsInAuthError;
// Opens the passphrase dialog.
- (void)openPassphraseDialog;
// Opens the trusted vault reauthentication dialog.
- (void)openTrustedVaultReauth;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SYNC_ERROR_SETTINGS_COMMAND_HANDLER_H_
......@@ -1482,6 +1482,9 @@ NSString* kDevViewSourceKey = @"DevViewSource";
[_privacyCoordinator stop];
_privacyCoordinator = nil;
[_manageSyncSettingsCoordinator stop];
_manageSyncSettingsCoordinator = nil;
_settingsHasBeenDismissed = YES;
DCHECK(!self.isSigninInProgress);
[_signinPromoViewMediator signinPromoViewIsRemoved];
......
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