blob: f5af2b827fc3ad89c4a7cb431e61b5de8bcc0a78 [file] [log] [blame]
// Copyright 2018 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/google_services_settings_coordinator.h"
#include "base/mac/foundation_util.h"
#include "ios/chrome/browser/application_context.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/signin/authentication_service.h"
#import "ios/chrome/browser/signin/authentication_service_factory.h"
#include "ios/chrome/browser/sync/profile_sync_service_factory.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/settings/google_services_settings_command_handler.h"
#import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h"
#import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h"
#include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h"
#include "net/base/mac/url_conversions.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface GoogleServicesSettingsCoordinator () <
GoogleServicesSettingsCommandHandler,
GoogleServicesSettingsViewControllerPresentationDelegate>
// Google services settings mediator.
@property(nonatomic, strong) GoogleServicesSettingsMediator* mediator;
// Returns the authentication service.
@property(nonatomic, assign, readonly) AuthenticationService* authService;
// Manages the authentication flow for a given identity.
@property(nonatomic, strong) AuthenticationFlow* authenticationFlow;
// View controller presented by this coordinator.
@property(nonatomic, strong, readonly)
GoogleServicesSettingsViewController* googleServicesSettingsViewController;
@end
@implementation GoogleServicesSettingsCoordinator
- (void)start {
GoogleServicesSettingsViewController* viewController =
[[GoogleServicesSettingsViewController alloc]
initWithTableViewStyle:UITableViewStyleGrouped
appBarStyle:ChromeTableViewControllerStyleNoAppBar];
viewController.presentationDelegate = self;
self.viewController = viewController;
SyncSetupService* syncSetupService =
SyncSetupServiceFactory::GetForBrowserState(self.browserState);
unified_consent::UnifiedConsentService* unifiedConsentService =
UnifiedConsentServiceFactory::GetForBrowserState(self.browserState);
self.mediator = [[GoogleServicesSettingsMediator alloc]
initWithUserPrefService:self.browserState->GetPrefs()
localPrefService:GetApplicationContext()->GetLocalState()
syncSetupService:syncSetupService
unifiedConsentService:unifiedConsentService];
self.mediator.consumer = viewController;
self.mediator.authService = self.authService;
self.mediator.commandHandler = self;
viewController.modelDelegate = self.mediator;
viewController.serviceDelegate = self.mediator;
DCHECK(self.navigationController);
[self.navigationController pushViewController:self.viewController
animated:YES];
}
#pragma mark - Private
- (void)closeGoogleActivitySettings:(id)sender {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Properties
- (AuthenticationService*)authService {
return AuthenticationServiceFactory::GetForBrowserState(self.browserState);
}
- (GoogleServicesSettingsViewController*)googleServicesSettingsViewController {
return base::mac::ObjCCast<GoogleServicesSettingsViewController>(
self.viewController);
}
#pragma mark - GoogleServicesSettingsCommandHandler
- (void)restartAuthenticationFlow {
ChromeIdentity* authenticatedIdentity =
AuthenticationServiceFactory::GetForBrowserState(self.browserState)
->GetAuthenticatedIdentity();
[self.googleServicesSettingsViewController preventUserInteraction];
DCHECK(!self.authenticationFlow);
self.authenticationFlow = [[AuthenticationFlow alloc]
initWithBrowserState:self.browserState
identity:authenticatedIdentity
shouldClearData:SHOULD_CLEAR_DATA_USER_CHOICE
postSignInAction:POST_SIGNIN_ACTION_START_SYNC
presentingViewController:self.viewController];
self.authenticationFlow.dispatcher = self.dispatcher;
__weak GoogleServicesSettingsCoordinator* weakSelf = self;
[self.authenticationFlow startSignInWithCompletion:^(BOOL success) {
// TODO(crbug.com/889919): Needs to add histogram for |success|.
[weakSelf.googleServicesSettingsViewController allowUserInteraction];
}];
}
- (void)openReauthDialogAsSyncIsInAuthError {
// 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.
}
- (void)openPassphraseDialog {
[self.dispatcher
showSyncPassphraseSettingsFromViewController:self.viewController];
}
#pragma mark - GoogleServicesSettingsViewControllerPresentationDelegate
- (void)googleServicesSettingsViewControllerDidRemove:
(GoogleServicesSettingsViewController*)controller {
DCHECK_EQ(self.viewController, controller);
[self.delegate googleServicesSettingsCoordinatorDidRemove:self];
}
@end