Commit 3084c793 authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Change CWVSyncController to support regular sync instead of butter

- Remove flag for account wallet.
- Add API for users to give consent.
- Change CWVSyncControllerDataSource to be class property so that
  the sync/auth stack will be able to ask for tokens during setup.
- Add method to CWVSyncControllerDataSource to return all accounts.
  This is required by chromium to maintain the freshness of tokens.
- Clear all local data when sync stops until we can handle data
  migration situations.
- Simplify CWVSyncControllerDelegate's did stop sync method.

Change-Id: I1773c270958ecffa21aa5196c94c1510bc7084a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1816641
Commit-Queue: John Wu <jzw@chromium.org>
Reviewed-by: default avatarHiroshi Ichikawa <ichikawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699944}
parent 80e4879a
...@@ -19,9 +19,7 @@ ...@@ -19,9 +19,7 @@
#import "ios/web_view/internal/cwv_user_content_controller_internal.h" #import "ios/web_view/internal/cwv_user_content_controller_internal.h"
#import "ios/web_view/internal/cwv_web_view_internal.h" #import "ios/web_view/internal/cwv_web_view_internal.h"
#include "ios/web_view/internal/passwords/web_view_password_store_factory.h" #include "ios/web_view/internal/passwords/web_view_password_store_factory.h"
#include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
#include "ios/web_view/internal/signin/web_view_identity_manager_factory.h" #include "ios/web_view/internal/signin/web_view_identity_manager_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_client_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_error_controller_factory.h" #include "ios/web_view/internal/signin/web_view_signin_error_controller_factory.h"
#import "ios/web_view/internal/sync/cwv_sync_controller_internal.h" #import "ios/web_view/internal/sync/cwv_sync_controller_internal.h"
#import "ios/web_view/internal/sync/web_view_profile_sync_service_factory.h" #import "ios/web_view/internal/sync/web_view_profile_sync_service_factory.h"
...@@ -162,18 +160,15 @@ CWVWebViewConfiguration* gIncognitoConfiguration = nil; ...@@ -162,18 +160,15 @@ CWVWebViewConfiguration* gIncognitoConfiguration = nil;
SigninErrorController* signinErrorController = SigninErrorController* signinErrorController =
ios_web_view::WebViewSigninErrorControllerFactory::GetForBrowserState( ios_web_view::WebViewSigninErrorControllerFactory::GetForBrowserState(
self.browserState); self.browserState);
autofill::PersonalDataManager* personalDataManager =
ios_web_view::WebViewPersonalDataManagerFactory::GetForBrowserState(
self.browserState);
_syncController = _syncController =
[[CWVSyncController alloc] initWithSyncService:syncService [[CWVSyncController alloc] initWithSyncService:syncService
identityManager:identityManager identityManager:identityManager
signinErrorController:signinErrorController]; signinErrorController:signinErrorController
personalDataManager:personalDataManager];
// Set the newly created CWVSyncController on IOSWebViewSigninClient to
// so access tokens can be fetched.
IOSWebViewSigninClient* signinClient =
ios_web_view::WebViewSigninClientFactory::GetForBrowserState(
self.browserState);
signinClient->SetSyncController(_syncController);
} }
return _syncController; return _syncController;
} }
......
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
#include "net/cookies/cookie_change_dispatcher.h" #include "net/cookies/cookie_change_dispatcher.h"
#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
@class CWVSyncController;
namespace ios_web_view { namespace ios_web_view {
class WebViewBrowserState; class WebViewBrowserState;
} }
...@@ -54,10 +52,6 @@ class IOSWebViewSigninClient : public SigninClient { ...@@ -54,10 +52,6 @@ class IOSWebViewSigninClient : public SigninClient {
GaiaAuthConsumer* consumer, GaiaAuthConsumer* consumer,
gaia::GaiaSource source) override; gaia::GaiaSource source) override;
// CWVSyncController setter/getter.
void SetSyncController(CWVSyncController* sync_controller);
CWVSyncController* GetSyncController() const;
private: private:
// Helper to delay callbacks until connection becomes online again. // Helper to delay callbacks until connection becomes online again.
std::unique_ptr<WaitForNetworkCallbackHelper> network_callback_helper_; std::unique_ptr<WaitForNetworkCallbackHelper> network_callback_helper_;
...@@ -68,10 +62,6 @@ class IOSWebViewSigninClient : public SigninClient { ...@@ -68,10 +62,6 @@ class IOSWebViewSigninClient : public SigninClient {
scoped_refptr<content_settings::CookieSettings> cookie_settings_; scoped_refptr<content_settings::CookieSettings> cookie_settings_;
// Used to add and remove content settings observers. // Used to add and remove content settings observers.
scoped_refptr<HostContentSettingsMap> host_content_settings_map_; scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
// Used by WebViewDeviceAccountsProviderImpl to fetch access
// tokens. Also used to notify of signout events. Held weak so this class
// does not determine |sync_controller_|'s lifetime.
__weak CWVSyncController* sync_controller_ = nil;
DISALLOW_COPY_AND_ASSIGN(IOSWebViewSigninClient); DISALLOW_COPY_AND_ASSIGN(IOSWebViewSigninClient);
}; };
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "components/signin/core/browser/cookie_settings_util.h" #include "components/signin/core/browser/cookie_settings_util.h"
#include "google_apis/gaia/gaia_auth_fetcher.h" #include "google_apis/gaia/gaia_auth_fetcher.h"
#import "ios/web_view/internal/sync/cwv_sync_controller_internal.h"
#include "ios/web_view/internal/web_view_browser_state.h" #include "ios/web_view/internal/web_view_browser_state.h"
#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
...@@ -70,7 +69,6 @@ void IOSWebViewSigninClient::PreSignOut( ...@@ -70,7 +69,6 @@ void IOSWebViewSigninClient::PreSignOut(
base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached,
signin_metrics::ProfileSignout signout_source_metric) { signin_metrics::ProfileSignout signout_source_metric) {
std::move(on_signout_decision_reached).Run(SignoutDecision::ALLOW_SIGNOUT); std::move(on_signout_decision_reached).Run(SignoutDecision::ALLOW_SIGNOUT);
[sync_controller_ didSignoutWithSourceMetric:signout_source_metric];
} }
void IOSWebViewSigninClient::DelayNetworkCall(base::OnceClosure callback) { void IOSWebViewSigninClient::DelayNetworkCall(base::OnceClosure callback) {
...@@ -84,11 +82,3 @@ std::unique_ptr<GaiaAuthFetcher> IOSWebViewSigninClient::CreateGaiaAuthFetcher( ...@@ -84,11 +82,3 @@ std::unique_ptr<GaiaAuthFetcher> IOSWebViewSigninClient::CreateGaiaAuthFetcher(
GetURLLoaderFactory()); GetURLLoaderFactory());
} }
void IOSWebViewSigninClient::SetSyncController(
CWVSyncController* sync_controller) {
sync_controller_ = sync_controller;
}
CWVSyncController* IOSWebViewSigninClient::GetSyncController() const {
return sync_controller_;
}
...@@ -12,14 +12,10 @@ ...@@ -12,14 +12,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "components/signin/public/identity_manager/ios/device_accounts_provider.h" #include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
class IOSWebViewSigninClient;
// Implementation of DeviceAccountsProvider. // Implementation of DeviceAccountsProvider.
class WebViewDeviceAccountsProviderImpl : public DeviceAccountsProvider { class WebViewDeviceAccountsProviderImpl : public DeviceAccountsProvider {
public: public:
// |signin_client| used to fetch access tokens. WebViewDeviceAccountsProviderImpl();
explicit WebViewDeviceAccountsProviderImpl(
IOSWebViewSigninClient* signin_client);
~WebViewDeviceAccountsProviderImpl() override; ~WebViewDeviceAccountsProviderImpl() override;
// ios::DeviceAccountsProvider // ios::DeviceAccountsProvider
...@@ -33,9 +29,6 @@ class WebViewDeviceAccountsProviderImpl : public DeviceAccountsProvider { ...@@ -33,9 +29,6 @@ class WebViewDeviceAccountsProviderImpl : public DeviceAccountsProvider {
NSError* error) const override; NSError* error) const override;
private: private:
// Used to obtain access tokens in |GetAccessToken|.
IOSWebViewSigninClient* const signin_client_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebViewDeviceAccountsProviderImpl); DISALLOW_COPY_AND_ASSIGN(WebViewDeviceAccountsProviderImpl);
}; };
......
...@@ -6,17 +6,16 @@ ...@@ -6,17 +6,16 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
#import "ios/web_view/internal/sync/cwv_sync_controller_internal.h" #import "ios/web_view/internal/sync/cwv_sync_controller_internal.h"
#import "ios/web_view/public/cwv_identity.h" #import "ios/web_view/public/cwv_identity.h"
#import "ios/web_view/public/cwv_sync_controller_data_source.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
WebViewDeviceAccountsProviderImpl::WebViewDeviceAccountsProviderImpl( WebViewDeviceAccountsProviderImpl::WebViewDeviceAccountsProviderImpl() =
IOSWebViewSigninClient* signin_client) default;
: signin_client_(signin_client) {}
WebViewDeviceAccountsProviderImpl::~WebViewDeviceAccountsProviderImpl() = WebViewDeviceAccountsProviderImpl::~WebViewDeviceAccountsProviderImpl() =
default; default;
...@@ -26,27 +25,42 @@ void WebViewDeviceAccountsProviderImpl::GetAccessToken( ...@@ -26,27 +25,42 @@ void WebViewDeviceAccountsProviderImpl::GetAccessToken(
const std::string& client_id, const std::string& client_id,
const std::set<std::string>& scopes, const std::set<std::string>& scopes,
AccessTokenCallback callback) { AccessTokenCallback callback) {
// |sync_controller| may still be nil if this is called too early so NSMutableArray<NSString*>* scopes_array = [NSMutableArray array];
// |callback| will not be invoked. That's OK because this will be called again for (const auto& scope : scopes) {
// after |sync_controller| has been set. [scopes_array addObject:base::SysUTF8ToNSString(scope)];
CWVSyncController* sync_controller = signin_client_->GetSyncController(); }
[sync_controller fetchAccessTokenForScopes:scopes
callback:std::move(callback)]; // AccessTokenCallback is non-copyable. Using __block allocates the memory
// directly in the block object at compilation time (instead of doing a
// copy). This is required to have correct interaction between move-only
// types and Objective-C blocks.
__block AccessTokenCallback scoped_callback = std::move(callback);
CWVIdentity* identity =
[[CWVIdentity alloc] initWithEmail:nil
fullName:nil
gaiaID:base::SysUTF8ToNSString(gaia_id)];
[CWVSyncController.dataSource
fetchAccessTokenForIdentity:identity
scopes:scopes_array
completionHandler:^(NSString* access_token,
NSDate* expiration_date, NSError* error) {
std::move(scoped_callback)
.Run(access_token, expiration_date, error);
}];
} }
std::vector<DeviceAccountsProvider::AccountInfo> std::vector<DeviceAccountsProvider::AccountInfo>
WebViewDeviceAccountsProviderImpl::GetAllAccounts() const { WebViewDeviceAccountsProviderImpl::GetAllAccounts() const {
// |sync_controller| may still be nil if this is called too early. That's OK NSArray<CWVIdentity*>* identities =
// because this will be called again after it has been set. [CWVSyncController.dataSource allKnownIdentities];
CWVSyncController* sync_controller = signin_client_->GetSyncController(); std::vector<AccountInfo> account_infos;
CWVIdentity* current_identity = sync_controller.currentIdentity; for (CWVIdentity* identity in identities) {
if (current_identity) {
AccountInfo account_info; AccountInfo account_info;
account_info.email = base::SysNSStringToUTF8(current_identity.email); account_info.email = base::SysNSStringToUTF8(identity.email);
account_info.gaia = base::SysNSStringToUTF8(current_identity.gaiaID); account_info.gaia = base::SysNSStringToUTF8(identity.gaiaID);
return {account_info}; account_infos.push_back(account_info);
} }
return {}; return account_infos;
} }
AuthenticationErrorCategory AuthenticationErrorCategory
......
...@@ -61,22 +61,16 @@ WebViewIdentityManagerFactory::BuildServiceInstanceFor( ...@@ -61,22 +61,16 @@ WebViewIdentityManagerFactory::BuildServiceInstanceFor(
WebViewBrowserState* browser_state = WebViewBrowserState* browser_state =
WebViewBrowserState::FromBrowserState(context); WebViewBrowserState::FromBrowserState(context);
// Clearing the sign in state on start up greatly simplifies the management of
// ChromeWebView's signin state.
PrefService* pref_service = browser_state->GetPrefs();
pref_service->ClearPref(prefs::kGoogleServicesAccountId);
pref_service->ClearPref(prefs::kGoogleServicesConsentedToSync);
IOSWebViewSigninClient* client = IOSWebViewSigninClient* client =
WebViewSigninClientFactory::GetForBrowserState(browser_state); WebViewSigninClientFactory::GetForBrowserState(browser_state);
signin::IdentityManagerBuildParams params; signin::IdentityManagerBuildParams params;
params.account_consistency = signin::AccountConsistencyMethod::kDisabled; params.account_consistency = signin::AccountConsistencyMethod::kDisabled;
params.device_accounts_provider = params.device_accounts_provider =
std::make_unique<WebViewDeviceAccountsProviderImpl>(client); std::make_unique<WebViewDeviceAccountsProviderImpl>();
params.image_decoder = image_fetcher::CreateIOSImageDecoder(); params.image_decoder = image_fetcher::CreateIOSImageDecoder();
params.local_state = ApplicationContext::GetInstance()->GetLocalState(); params.local_state = ApplicationContext::GetInstance()->GetLocalState();
params.pref_service = pref_service; params.pref_service = browser_state->GetPrefs();
params.profile_path = base::FilePath(); params.profile_path = base::FilePath();
params.signin_client = client; params.signin_client = client;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/signin_error_controller.h"
#include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/device_accounts_synchronizer.h" #include "components/signin/public/identity_manager/device_accounts_synchronizer.h"
...@@ -24,8 +25,6 @@ ...@@ -24,8 +25,6 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
using AccessTokenCallback = DeviceAccountsProvider::AccessTokenCallback;
NSErrorDomain const CWVSyncErrorDomain = NSErrorDomain const CWVSyncErrorDomain =
@"org.chromium.chromewebview.SyncErrorDomain"; @"org.chromium.chromewebview.SyncErrorDomain";
...@@ -65,6 +64,8 @@ CWVSyncError CWVConvertGoogleServiceAuthErrorStateToCWVSyncError( ...@@ -65,6 +64,8 @@ CWVSyncError CWVConvertGoogleServiceAuthErrorStateToCWVSyncError(
- (void)didShutdownSync; - (void)didShutdownSync;
// Called by WebViewSyncControllerObserverBridge's |OnErrorChanged|. // Called by WebViewSyncControllerObserverBridge's |OnErrorChanged|.
- (void)didUpdateAuthError; - (void)didUpdateAuthError;
// Called by WebViewSyncControllerObserverBridge's |OnPrimaryAccountCleared|.
- (void)didClearPrimaryAccount;
// Call to refresh access tokens for |currentIdentity|. // Call to refresh access tokens for |currentIdentity|.
- (void)reloadCredentials; - (void)reloadCredentials;
...@@ -77,6 +78,7 @@ namespace ios_web_view { ...@@ -77,6 +78,7 @@ namespace ios_web_view {
// methods on CWVSyncController. // methods on CWVSyncController.
class WebViewSyncControllerObserverBridge class WebViewSyncControllerObserverBridge
: public syncer::SyncServiceObserver, : public syncer::SyncServiceObserver,
public signin::IdentityManager::Observer,
public SigninErrorController::Observer { public SigninErrorController::Observer {
public: public:
explicit WebViewSyncControllerObserverBridge( explicit WebViewSyncControllerObserverBridge(
...@@ -92,6 +94,12 @@ class WebViewSyncControllerObserverBridge ...@@ -92,6 +94,12 @@ class WebViewSyncControllerObserverBridge
[sync_controller_ didShutdownSync]; [sync_controller_ didShutdownSync];
} }
// signin::IdentityManager::Observer
void OnPrimaryAccountCleared(
const CoreAccountInfo& previous_primary_account_info) override {
[sync_controller_ didClearPrimaryAccount];
}
// SigninErrorController::Observer: // SigninErrorController::Observer:
void OnErrorChanged() override { [sync_controller_ didUpdateAuthError]; } void OnErrorChanged() override { [sync_controller_ didUpdateAuthError]; }
...@@ -106,29 +114,51 @@ class WebViewSyncControllerObserverBridge ...@@ -106,29 +114,51 @@ class WebViewSyncControllerObserverBridge
signin::IdentityManager* _identityManager; signin::IdentityManager* _identityManager;
SigninErrorController* _signinErrorController; SigninErrorController* _signinErrorController;
std::unique_ptr<ios_web_view::WebViewSyncControllerObserverBridge> _observer; std::unique_ptr<ios_web_view::WebViewSyncControllerObserverBridge> _observer;
autofill::PersonalDataManager* _personalDataManager;
// Data source that can provide access tokens.
__weak id<CWVSyncControllerDataSource> _dataSource;
} }
@synthesize delegate = _delegate;
@synthesize currentIdentity = _currentIdentity; @synthesize currentIdentity = _currentIdentity;
@synthesize delegate = _delegate;
namespace {
// Data source that can provide access tokens.
__weak id<CWVSyncControllerDataSource> gSyncDataSource;
}
- (instancetype)initWithSyncService:(syncer::SyncService*)syncService + (void)setDataSource:(id<CWVSyncControllerDataSource>)dataSource {
identityManager:(signin::IdentityManager*)identityManager gSyncDataSource = dataSource;
signinErrorController: }
(SigninErrorController*)signinErrorController {
+ (id<CWVSyncControllerDataSource>)dataSource {
return gSyncDataSource;
}
- (instancetype)
initWithSyncService:(syncer::SyncService*)syncService
identityManager:(signin::IdentityManager*)identityManager
signinErrorController:(SigninErrorController*)signinErrorController
personalDataManager:(autofill::PersonalDataManager*)personalDataManager {
self = [super init]; self = [super init];
if (self) { if (self) {
_syncService = syncService; _syncService = syncService;
_identityManager = identityManager; _identityManager = identityManager;
_signinErrorController = signinErrorController; _signinErrorController = signinErrorController;
_personalDataManager = personalDataManager;
_observer = _observer =
std::make_unique<ios_web_view::WebViewSyncControllerObserverBridge>( std::make_unique<ios_web_view::WebViewSyncControllerObserverBridge>(
self); self);
_syncService->AddObserver(_observer.get()); _syncService->AddObserver(_observer.get());
_identityManager->AddObserver(_observer.get());
_signinErrorController->AddObserver(_observer.get()); _signinErrorController->AddObserver(_observer.get());
if (_identityManager->HasPrimaryAccount()) {
CoreAccountInfo accountInfo = _identityManager->GetPrimaryAccountInfo();
_currentIdentity = [[CWVIdentity alloc]
initWithEmail:base::SysUTF8ToNSString(accountInfo.email)
fullName:nil
gaiaID:base::SysUTF8ToNSString(accountInfo.gaia)];
}
// Refresh access tokens on foreground to extend expiration dates. // Refresh access tokens on foreground to extend expiration dates.
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
...@@ -141,6 +171,7 @@ class WebViewSyncControllerObserverBridge ...@@ -141,6 +171,7 @@ class WebViewSyncControllerObserverBridge
- (void)dealloc { - (void)dealloc {
_syncService->RemoveObserver(_observer.get()); _syncService->RemoveObserver(_observer.get());
_identityManager->RemoveObserver(_observer.get());
_signinErrorController->RemoveObserver(_observer.get()); _signinErrorController->RemoveObserver(_observer.get());
} }
...@@ -150,17 +181,15 @@ class WebViewSyncControllerObserverBridge ...@@ -150,17 +181,15 @@ class WebViewSyncControllerObserverBridge
return _syncService->GetUserSettings()->IsPassphraseRequiredForDecryption(); return _syncService->GetUserSettings()->IsPassphraseRequiredForDecryption();
} }
- (void)startSyncWithIdentity:(CWVIdentity*)identity - (BOOL)isConsentNeeded {
dataSource: return !_syncService->GetUserSettings()->IsFirstSetupComplete();
(__weak id<CWVSyncControllerDataSource>)dataSource { }
DCHECK(!_dataSource);
DCHECK(!_currentIdentity);
_dataSource = dataSource; - (void)startSyncWithIdentity:(CWVIdentity*)identity {
_currentIdentity = identity; DCHECK(!_currentIdentity)
<< "Already syncing! Call -stopSyncAndClearIdentity first.";
DCHECK(_dataSource); _currentIdentity = identity;
DCHECK(_currentIdentity);
const CoreAccountId accountId = _identityManager->PickAccountIdForAccount( const CoreAccountId accountId = _identityManager->PickAccountIdForAccount(
base::SysNSStringToUTF8(identity.gaiaID), base::SysNSStringToUTF8(identity.gaiaID),
...@@ -172,16 +201,23 @@ class WebViewSyncControllerObserverBridge ...@@ -172,16 +201,23 @@ class WebViewSyncControllerObserverBridge
_identityManager->GetPrimaryAccountMutator()->SetPrimaryAccount(accountId); _identityManager->GetPrimaryAccountMutator()->SetPrimaryAccount(accountId);
CHECK_EQ(_identityManager->GetPrimaryAccountId(), accountId); CHECK_EQ(_identityManager->GetPrimaryAccountId(), accountId);
_syncService->GetUserSettings()->SetSyncRequested(true);
} }
- (void)stopSyncAndClearIdentity { - (void)stopSyncAndClearIdentity {
_syncService->StopAndClear();
auto* primaryAccountMutator = _identityManager->GetPrimaryAccountMutator(); auto* primaryAccountMutator = _identityManager->GetPrimaryAccountMutator();
primaryAccountMutator->ClearPrimaryAccount( primaryAccountMutator->ClearPrimaryAccount(
signin::PrimaryAccountMutator::ClearAccountsAction::kDefault, signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS, signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS,
signin_metrics::SignoutDelete::IGNORE_METRIC); signin_metrics::SignoutDelete::IGNORE_METRIC);
// Clear all local data because we do not support data migration.
_personalDataManager->ClearAllLocalData();
_currentIdentity = nil; _currentIdentity = nil;
_dataSource = nil;
} }
- (BOOL)unlockWithPassphrase:(NSString*)passphrase { - (BOOL)unlockWithPassphrase:(NSString*)passphrase {
...@@ -189,6 +225,11 @@ class WebViewSyncControllerObserverBridge ...@@ -189,6 +225,11 @@ class WebViewSyncControllerObserverBridge
base::SysNSStringToUTF8(passphrase)); base::SysNSStringToUTF8(passphrase));
} }
- (void)consent {
_syncService->GetUserSettings()->SetFirstSetupComplete(
syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
}
#pragma mark - Private Methods #pragma mark - Private Methods
- (void)didCompleteSyncConfiguration { - (void)didCompleteSyncConfiguration {
...@@ -203,50 +244,17 @@ class WebViewSyncControllerObserverBridge ...@@ -203,50 +244,17 @@ class WebViewSyncControllerObserverBridge
} }
- (void)reloadCredentials { - (void)reloadCredentials {
if (_currentIdentity != nil) { _identityManager->GetDeviceAccountsSynchronizer()
_identityManager->GetDeviceAccountsSynchronizer() ->ReloadAllAccountsFromSystem();
->ReloadAllAccountsFromSystem();
}
} }
#pragma mark - Internal Methods #pragma mark - Internal Methods
- (void)fetchAccessTokenForScopes:(const std::set<std::string>&)scopes - (void)didClearPrimaryAccount {
callback:(AccessTokenCallback)callback { if (![_delegate respondsToSelector:@selector(syncControllerDidStopSync:)]) {
DCHECK(!callback.is_null());
NSMutableArray<NSString*>* scopesArray = [NSMutableArray array];
for (const auto& scope : scopes) {
[scopesArray addObject:base::SysUTF8ToNSString(scope)];
}
// AccessTokenCallback is non-copyable. Using __block allocates the memory
// directly in the block object at compilation time (instead of doing a
// copy). This is required to have correct interaction between move-only
// types and Objective-C blocks.
__block AccessTokenCallback scopedCallback = std::move(callback);
[_dataSource syncController:self
getAccessTokenForScopes:[scopesArray copy]
completionHandler:^(NSString* accessToken, NSDate* expirationDate,
NSError* error) {
std::move(scopedCallback).Run(accessToken, expirationDate, error);
}];
}
- (void)didSignoutWithSourceMetric:(signin_metrics::ProfileSignout)metric {
if (![_delegate respondsToSelector:@selector
(syncController:didStopSyncWithReason:)]) {
return;
}
CWVStopSyncReason reason;
if (metric == signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS) {
reason = CWVStopSyncReasonClient;
} else if (metric == signin_metrics::ProfileSignout::SERVER_FORCED_DISABLE) {
reason = CWVStopSyncReasonServer;
} else {
NOTREACHED();
return; return;
} }
[_delegate syncController:self didStopSyncWithReason:reason]; [_delegate syncControllerDidStopSync:self];
} }
- (void)didUpdateAuthError { - (void)didUpdateAuthError {
......
...@@ -5,15 +5,14 @@ ...@@ -5,15 +5,14 @@
#ifndef IOS_WEB_VIEW_INTERNAL_SYNC_CWV_SYNC_CONTROLLER_INTERNAL_H_ #ifndef IOS_WEB_VIEW_INTERNAL_SYNC_CWV_SYNC_CONTROLLER_INTERNAL_H_
#define IOS_WEB_VIEW_INTERNAL_SYNC_CWV_SYNC_CONTROLLER_INTERNAL_H_ #define IOS_WEB_VIEW_INTERNAL_SYNC_CWV_SYNC_CONTROLLER_INTERNAL_H_
#include <set>
#include "components/signin/public/base/signin_metrics.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "ios/web_view/internal/signin/web_view_device_accounts_provider_impl.h"
#import "ios/web_view/public/cwv_sync_controller.h" #import "ios/web_view/public/cwv_sync_controller.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
namespace autofill {
class PersonalDataManager;
} // autofill
namespace syncer { namespace syncer {
class SyncService; class SyncService;
} // namespace syncer } // namespace syncer
...@@ -27,21 +26,13 @@ class SigninErrorController; ...@@ -27,21 +26,13 @@ class SigninErrorController;
@interface CWVSyncController () @interface CWVSyncController ()
// All dependencies must out live this class. // All dependencies must out live this class.
- (instancetype)initWithSyncService:(syncer::SyncService*)syncService - (instancetype)
identityManager:(signin::IdentityManager*)identityManager initWithSyncService:(syncer::SyncService*)syncService
signinErrorController: identityManager:(signin::IdentityManager*)identityManager
(SigninErrorController*)SigninErrorController signinErrorController:(SigninErrorController*)signinErrorController
personalDataManager:(autofill::PersonalDataManager*)personalDataManager
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
// Called by WebViewDeviceAccountsProviderImpl to obtain
// access tokens for |scopes| to be passed back in |callback|.
- (void)fetchAccessTokenForScopes:(const std::set<std::string>&)scopes
callback:(DeviceAccountsProvider::AccessTokenCallback)
callback;
// Called by IOSWebViewSigninClient when signing out.
- (void)didSignoutWithSourceMetric:(signin_metrics::ProfileSignout)metric;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
......
...@@ -11,9 +11,12 @@ ...@@ -11,9 +11,12 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/signin_error_controller.h"
#include "components/signin/public/base/account_consistency_method.h" #include "components/signin/public/base/account_consistency_method.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "components/sync/driver/mock_sync_service.h" #include "components/sync/driver/mock_sync_service.h"
#include "components/sync/driver/sync_service_observer.h" #include "components/sync/driver/sync_service_observer.h"
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
...@@ -21,6 +24,7 @@ ...@@ -21,6 +24,7 @@
#include "ios/web/public/test/web_task_environment.h" #include "ios/web/public/test/web_task_environment.h"
#include "ios/web_view/internal/app/application_context.h" #include "ios/web_view/internal/app/application_context.h"
#include "ios/web_view/internal/signin/ios_web_view_signin_client.h" #include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
#include "ios/web_view/internal/signin/web_view_device_accounts_provider_impl.h"
#include "ios/web_view/internal/signin/web_view_identity_manager_factory.h" #include "ios/web_view/internal/signin/web_view_identity_manager_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_client_factory.h" #include "ios/web_view/internal/signin/web_view_signin_client_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_error_controller_factory.h" #include "ios/web_view/internal/signin/web_view_signin_error_controller_factory.h"
...@@ -64,23 +68,31 @@ std::unique_ptr<KeyedService> BuildMockSyncService(web::BrowserState* context) { ...@@ -64,23 +68,31 @@ std::unique_ptr<KeyedService> BuildMockSyncService(web::BrowserState* context) {
class CWVSyncControllerTest : public TestWithLocaleAndResources { class CWVSyncControllerTest : public TestWithLocaleAndResources {
protected: protected:
CWVSyncControllerTest() : browser_state_(/*off_the_record=*/false) { CWVSyncControllerTest() : browser_state_(/*off_the_record=*/false) {
// Clear account info before each test.
PrefService* pref_service = browser_state_.GetPrefs();
pref_service->ClearPref(prefs::kGoogleServicesAccountId);
pref_service->ClearPref(prefs::kGoogleServicesConsentedToSync);
pref_service->ClearPref(prefs::kAccountInfo);
WebViewProfileSyncServiceFactory::GetInstance()->SetTestingFactory( WebViewProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
&browser_state_, base::BindRepeating(&BuildMockSyncService)); &browser_state_, base::BindRepeating(&BuildMockSyncService));
EXPECT_CALL(*mock_sync_service(), AddObserver(_)) EXPECT_CALL(*mock_sync_service(), AddObserver(_))
.WillOnce(Invoke(this, &CWVSyncControllerTest::AddObserver)); .WillOnce(Invoke(this, &CWVSyncControllerTest::AddObserver));
personal_data_manager_ =
std::make_unique<autofill::TestPersonalDataManager>();
sync_controller_ = [[CWVSyncController alloc] sync_controller_ = [[CWVSyncController alloc]
initWithSyncService:mock_sync_service() initWithSyncService:mock_sync_service()
identityManager:identity_manager() identityManager:identity_manager()
signinErrorController:signin_error_controller()]; signinErrorController:signin_error_controller()
personalDataManager:personal_data_manager_.get()];
WebViewSigninClientFactory::GetForBrowserState(&browser_state_)
->SetSyncController(sync_controller_);
} }
~CWVSyncControllerTest() override { ~CWVSyncControllerTest() override {
EXPECT_CALL(*mock_sync_service(), RemoveObserver(_)); EXPECT_CALL(*mock_sync_service(), RemoveObserver(_));
EXPECT_CALL(*mock_sync_service(), Shutdown());
} }
void AddObserver(syncer::SyncServiceObserver* observer) { void AddObserver(syncer::SyncServiceObserver* observer) {
...@@ -103,6 +115,7 @@ class CWVSyncControllerTest : public TestWithLocaleAndResources { ...@@ -103,6 +115,7 @@ class CWVSyncControllerTest : public TestWithLocaleAndResources {
web::WebTaskEnvironment task_environment_; web::WebTaskEnvironment task_environment_;
ios_web_view::WebViewBrowserState browser_state_; ios_web_view::WebViewBrowserState browser_state_;
std::unique_ptr<autofill::TestPersonalDataManager> personal_data_manager_;
CWVSyncController* sync_controller_ = nil; CWVSyncController* sync_controller_ = nil;
syncer::SyncServiceObserver* sync_service_observer_ = nullptr; syncer::SyncServiceObserver* sync_service_observer_ = nullptr;
}; };
...@@ -114,23 +127,23 @@ TEST_F(CWVSyncControllerTest, DataSourceCallbacks) { ...@@ -114,23 +127,23 @@ TEST_F(CWVSyncControllerTest, DataSourceCallbacks) {
// destroyed before this test exits to avoid holding on to |sync_controller_|. // destroyed before this test exits to avoid holding on to |sync_controller_|.
@autoreleasepool { @autoreleasepool {
id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource)); id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource));
CWVSyncController.dataSource = data_source;
[[data_source expect] [[data_source expect]
syncController:sync_controller_ fetchAccessTokenForIdentity:[OCMArg checkWithBlock:^BOOL(
getAccessTokenForScopes:[OCMArg checkWithBlock:^BOOL(NSArray* scopes) { CWVIdentity* identity) {
return [scopes containsObject:@(kTestScope1)] && return [identity.gaiaID isEqualToString:@(kTestGaiaId)];
[scopes containsObject:@(kTestScope2)];
}] }]
completionHandler:[OCMArg any]]; scopes:[OCMArg checkWithBlock:^BOOL(
NSArray* scopes) {
CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:@(kTestEmail) return [scopes containsObject:@(kTestScope1)] &&
fullName:@(kTestFullName) [scopes containsObject:@(kTestScope2)];
gaiaID:@(kTestGaiaId)]; }]
[sync_controller_ startSyncWithIdentity:identity dataSource:data_source]; completionHandler:[OCMArg any]];
WebViewDeviceAccountsProviderImpl accounts_provider;
std::set<std::string> scopes = {kTestScope1, kTestScope2}; std::set<std::string> scopes = {kTestScope1, kTestScope2};
[sync_controller_ fetchAccessTokenForScopes:scopes accounts_provider.GetAccessToken(kTestGaiaId, "dummy-client-id", scopes,
callback:base::DoNothing()]; base::DoNothing());
[data_source verify]; [data_source verify];
} }
...@@ -142,8 +155,15 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) { ...@@ -142,8 +155,15 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) {
// [delegate expect] returns an autoreleased object, but it must be destroyed // [delegate expect] returns an autoreleased object, but it must be destroyed
// before this test exits to avoid holding on to |sync_controller_|. // before this test exits to avoid holding on to |sync_controller_|.
@autoreleasepool { @autoreleasepool {
CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:@(kTestEmail)
fullName:@(kTestFullName)
gaiaID:@(kTestGaiaId)];
id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource));
[[[data_source stub] andReturn:@[ identity ]] allKnownIdentities];
CWVSyncController.dataSource = data_source;
id delegate = OCMProtocolMock(@protocol(CWVSyncControllerDelegate)); id delegate = OCMProtocolMock(@protocol(CWVSyncControllerDelegate));
sync_controller_.delegate = delegate; sync_controller_.delegate = delegate;
[sync_controller_ startSyncWithIdentity:identity];
[[delegate expect] syncControllerDidStartSync:sync_controller_]; [[delegate expect] syncControllerDidStartSync:sync_controller_];
sync_service_observer_->OnSyncConfigurationCompleted(mock_sync_service()); sync_service_observer_->OnSyncConfigurationCompleted(mock_sync_service());
...@@ -153,13 +173,6 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) { ...@@ -153,13 +173,6 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) {
return error.code == CWVSyncErrorInvalidGAIACredentials; return error.code == CWVSyncErrorInvalidGAIACredentials;
}]]; }]];
id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource));
CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:@(kTestEmail)
fullName:@(kTestFullName)
gaiaID:@(kTestGaiaId)];
[sync_controller_ startSyncWithIdentity:identity dataSource:data_source];
// Create authentication error. // Create authentication error.
GoogleServiceAuthError auth_error( GoogleServiceAuthError auth_error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
...@@ -167,11 +180,12 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) { ...@@ -167,11 +180,12 @@ TEST_F(CWVSyncControllerTest, DelegateCallbacks) {
identity_manager(), identity_manager()->GetPrimaryAccountId(), identity_manager(), identity_manager()->GetPrimaryAccountId(),
auth_error); auth_error);
[[delegate expect] syncController:sync_controller_ [[delegate expect] syncControllerDidStopSync:sync_controller_];
didStopSyncWithReason:CWVStopSyncReasonServer]; identity_manager()->GetPrimaryAccountMutator()->ClearPrimaryAccount(
[sync_controller_ signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
didSignoutWithSourceMetric:signin_metrics::ProfileSignout:: signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS,
SERVER_FORCED_DISABLE]; signin_metrics::SignoutDelete::IGNORE_METRIC);
[delegate verify]; [delegate verify];
} }
} }
...@@ -181,18 +195,36 @@ TEST_F(CWVSyncControllerTest, CurrentIdentity) { ...@@ -181,18 +195,36 @@ TEST_F(CWVSyncControllerTest, CurrentIdentity) {
CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:@(kTestEmail) CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:@(kTestEmail)
fullName:@(kTestFullName) fullName:@(kTestFullName)
gaiaID:@(kTestGaiaId)]; gaiaID:@(kTestGaiaId)];
id unused_mock = OCMProtocolMock(@protocol(CWVSyncControllerDataSource)); id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource));
[sync_controller_ startSyncWithIdentity:identity dataSource:unused_mock]; [[[data_source stub] andReturn:@[ identity ]] allKnownIdentities];
CWVSyncController.dataSource = data_source;
[sync_controller_ startSyncWithIdentity:identity];
CWVIdentity* currentIdentity = sync_controller_.currentIdentity; CWVIdentity* currentIdentity = sync_controller_.currentIdentity;
EXPECT_TRUE(currentIdentity); EXPECT_TRUE(currentIdentity);
EXPECT_NSEQ(identity.email, currentIdentity.email); EXPECT_NSEQ(identity.email, currentIdentity.email);
EXPECT_NSEQ(identity.fullName, currentIdentity.fullName); EXPECT_NSEQ(identity.fullName, currentIdentity.fullName);
EXPECT_NSEQ(identity.gaiaID, currentIdentity.gaiaID); EXPECT_NSEQ(identity.gaiaID, currentIdentity.gaiaID);
EXPECT_CALL(*mock_sync_service(), StopAndClear());
[sync_controller_ stopSyncAndClearIdentity]; [sync_controller_ stopSyncAndClearIdentity];
EXPECT_FALSE(sync_controller_.currentIdentity); EXPECT_FALSE(sync_controller_.currentIdentity);
} }
// Verifies CWVSyncController's consent API.
TEST_F(CWVSyncControllerTest, Consent) {
EXPECT_CALL(*mock_sync_service()->GetMockUserSettings(),
IsFirstSetupComplete())
.WillOnce(Return(false));
EXPECT_TRUE(sync_controller_.consentNeeded);
EXPECT_CALL(*mock_sync_service()->GetMockUserSettings(),
SetFirstSetupComplete(_));
[sync_controller_ consent];
EXPECT_CALL(*mock_sync_service()->GetMockUserSettings(),
IsFirstSetupComplete())
.WillOnce(Return(true));
EXPECT_FALSE(sync_controller_.consentNeeded);
}
// Verifies CWVSyncController's passphrase API. // Verifies CWVSyncController's passphrase API.
TEST_F(CWVSyncControllerTest, Passphrase) { TEST_F(CWVSyncControllerTest, Passphrase) {
EXPECT_CALL(*mock_sync_service()->GetMockUserSettings(), EXPECT_CALL(*mock_sync_service()->GetMockUserSettings(),
......
...@@ -46,12 +46,11 @@ namespace ios_web_view { ...@@ -46,12 +46,11 @@ namespace ios_web_view {
namespace { namespace {
syncer::ModelTypeSet GetDisabledTypes() { syncer::ModelTypeSet GetDisabledTypes() {
// Only want credit card autofill for now.
// TODO(crbug.com/906910): Remove syncer::AUTOFILL_PROFILE and
// syncer::PASSWORDS as well once they are ready.
syncer::ModelTypeSet disabled_types = syncer::UserTypes(); syncer::ModelTypeSet disabled_types = syncer::UserTypes();
disabled_types.Remove(syncer::AUTOFILL_WALLET_DATA); disabled_types.Remove(syncer::AUTOFILL_WALLET_DATA);
disabled_types.Remove(syncer::AUTOFILL_WALLET_METADATA); disabled_types.Remove(syncer::AUTOFILL_WALLET_METADATA);
disabled_types.Remove(syncer::AUTOFILL_PROFILE);
disabled_types.Remove(syncer::PASSWORDS);
return disabled_types; return disabled_types;
} }
} // namespace } // namespace
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "components/signin/ios/browser/active_state_manager.h" #include "components/signin/ios/browser/active_state_manager.h"
#include "components/sync/base/pref_names.h" #include "components/sync/base/pref_names.h"
#include "components/sync/base/sync_prefs.h" #include "components/sync/base/sync_prefs.h"
#include "components/sync_device_info/device_info_prefs.h"
#include "components/sync_sessions/session_sync_prefs.h" #include "components/sync_sessions/session_sync_prefs.h"
#include "components/translate/core/browser/translate_pref_names.h" #include "components/translate/core/browser/translate_pref_names.h"
#include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/browser/translate_prefs.h"
...@@ -179,6 +180,7 @@ void WebViewBrowserState::RegisterPrefs( ...@@ -179,6 +180,7 @@ void WebViewBrowserState::RegisterPrefs(
gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(pref_registry); gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(pref_registry);
sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(pref_registry); sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(pref_registry);
syncer::SyncPrefs::RegisterProfilePrefs(pref_registry); syncer::SyncPrefs::RegisterProfilePrefs(pref_registry);
syncer::DeviceInfoPrefs::RegisterProfilePrefs(pref_registry);
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
// Instantiate all factories to setup dependency graph for pref registration. // Instantiate all factories to setup dependency graph for pref registration.
......
...@@ -50,10 +50,8 @@ void WebViewWebMainParts::PreCreateThreads() { ...@@ -50,10 +50,8 @@ void WebViewWebMainParts::PreCreateThreads() {
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
std::string enable_features = base::JoinString( std::string enable_features =
{autofill::features::kAutofillEnableAccountWalletStorage.name, base::JoinString({autofill::features::kAutofillUpstream.name}, ",");
autofill::features::kAutofillUpstream.name},
",");
std::string disabled_features = base::JoinString( std::string disabled_features = base::JoinString(
{// Allows form_structure.cc to run heuristics on single field forms. {// Allows form_structure.cc to run heuristics on single field forms.
// This is needed to find autofillable password forms with less than 3 // This is needed to find autofillable password forms with less than 3
......
...@@ -15,14 +15,14 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -15,14 +15,14 @@ NS_ASSUME_NONNULL_BEGIN
CWV_EXPORT CWV_EXPORT
@interface CWVIdentity : NSObject @interface CWVIdentity : NSObject
- (instancetype)initWithEmail:(NSString*)email - (instancetype)initWithEmail:(nullable NSString*)email
fullName:(nullable NSString*)fullName fullName:(nullable NSString*)fullName
gaiaID:(NSString*)gaiaID NS_DESIGNATED_INITIALIZER; gaiaID:(NSString*)gaiaID NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
// The user's email address. e.g. john.doe@chromium.org. // The user's email address. e.g. john.doe@chromium.org.
@property(nonatomic, copy, readonly) NSString* email; @property(nonatomic, copy, readonly, nullable) NSString* email;
// The user's full name. e.g. John Doe. // The user's full name. e.g. John Doe.
@property(nonatomic, copy, readonly, nullable) NSString* fullName; @property(nonatomic, copy, readonly, nullable) NSString* fullName;
......
...@@ -42,14 +42,16 @@ typedef NS_ENUM(NSInteger, CWVSyncError) { ...@@ -42,14 +42,16 @@ typedef NS_ENUM(NSInteger, CWVSyncError) {
}; };
// Used to manage syncing for autofill and password data. Usage: // Used to manage syncing for autofill and password data. Usage:
// 1. Call |startSyncWithIdentity:dataSource:| to start syncing with identity. // 1. Set the |dataSource| and |delegate|.
// 2. Call |stopSyncAndClearIdentity| to stop syncing. // 2. Call |startSyncWithIdentity:| to start syncing with identity.
// It is necessary to call |startSyncWithIdentity:dataSource:| once per cold app // 3. Call |stopSyncAndClearIdentity| to stop syncing.
// launch to keep |currentIdentity| syncing. Remember to set the |delegate| to
// listen to sync start and stop events.
CWV_EXPORT CWV_EXPORT
@interface CWVSyncController : NSObject @interface CWVSyncController : NSObject
// The data source of CWVSyncController.
@property(class, nonatomic, weak, nullable) id<CWVSyncControllerDataSource>
dataSource;
// The delegate of CWVSyncController. // The delegate of CWVSyncController.
@property(nonatomic, weak, nullable) id<CWVSyncControllerDelegate> delegate; @property(nonatomic, weak, nullable) id<CWVSyncControllerDelegate> delegate;
...@@ -61,24 +63,36 @@ CWV_EXPORT ...@@ -61,24 +63,36 @@ CWV_EXPORT
// is invoked in |delegate|. // is invoked in |delegate|.
@property(nonatomic, readonly, getter=isPassphraseNeeded) BOOL passphraseNeeded; @property(nonatomic, readonly, getter=isPassphraseNeeded) BOOL passphraseNeeded;
// Whether or not |currentIdentity| has opted into sync. Not meaningful
// until |currentIdentity| is set and |syncControllerDidStartSync:| callback in
// is invoked in |delegate|.
@property(nonatomic, readonly, getter=isConsentNeeded) BOOL consentNeeded;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
// Start syncing with |identity|. |dataSource| is used to obtain access tokens. // Start syncing with |identity|.
// |identity| will be persisted as |currentIdentity| and continue syncing until // |identity| will be persisted as |currentIdentity| and continue syncing until
// |stopSyncAndClearIdentity| is called or the app is restarted. // |stopSyncAndClearIdentity| is called.
- (void)startSyncWithIdentity:(CWVIdentity*)identity // Make sure |dataSource| is set so access tokens can be fetched.
dataSource: - (void)startSyncWithIdentity:(CWVIdentity*)identity;
(__weak id<CWVSyncControllerDataSource>)dataSource;
// Stops syncs and nils out |currentIdentity|. This method is idempotent. // Stops syncs and nils out |currentIdentity|. This method is idempotent.
- (void)stopSyncAndClearIdentity; - (void)stopSyncAndClearIdentity;
// If |passphraseNeeded| is |YES|. Call this to unlock the sync data. // If |passphraseNeeded| is |YES|. Call this to unlock the sync data.
// Only call after calling |startSyncWithIdentity:dataSource:| and receiving // Only call after calling |startSyncWithIdentity:| and receiving
// |syncControllerDidStartSync:| callback in |delegate|. // |syncControllerDidStartSync:| callback in |delegate|.
// No op if |passphraseNeeded| is |NO|. Returns |YES| if successful. // No op if |passphraseNeeded| is |NO|. Returns |YES| if successful.
- (BOOL)unlockWithPassphrase:(NSString*)passphrase; - (BOOL)unlockWithPassphrase:(NSString*)passphrase;
// If |consentNeeded| is |YES|, call this method to opt the |currentIdentity|
// into sync. Notes:
// - Only call after calling |startSyncWithIdentity:| and receiving
// |syncControllerDidStartSync:| callback in |delegate|.
// - Only call after receiving explicit consent from the user. For example,
// user accepts an opt-in UI prompt.
- (void)consent;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
......
...@@ -9,22 +9,27 @@ ...@@ -9,22 +9,27 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class CWVSyncController; @class CWVIdentity;
// Data source of CWVSyncController. // Data source of CWVSyncController.
@protocol CWVSyncControllerDataSource<NSObject> @protocol CWVSyncControllerDataSource<NSObject>
// Called when access tokens are requested. // Called when access tokens are requested.
// |identity| The user whose access tokens are requested.
// |scopes| OAuth scopes requested. // |scopes| OAuth scopes requested.
// |completionHandler| Use to pass back token information. // |completionHandler| Use to pass back token information.
// If successful, only |accessToken| and |expirationDate| should be non-nil. // If successful, only |accessToken| and |expirationDate| will be non-nil.
// If unsuccessful, only |error| should be non-nil. // If unsuccessful, only |error| will be non-nil.
- (void)syncController:(CWVSyncController*)syncController - (void)fetchAccessTokenForIdentity:(CWVIdentity*)identity
getAccessTokenForScopes:(NSArray<NSString*>*)scopes scopes:(NSArray<NSString*>*)scopes
completionHandler: completionHandler:
(void (^)(NSString* _Nullable accessToken, (void (^)(NSString* _Nullable accessToken,
NSDate* _Nullable expirationDate, NSDate* _Nullable expirationDate,
NSError* _Nullable error))completionHandler; NSError* _Nullable error))completionHandler;
// Return all available identities. This is used internally to track if accounts
// become stale and need to be removed.
- (NSArray<CWVIdentity*>*)allKnownIdentities;
@end @end
......
...@@ -9,13 +9,6 @@ ...@@ -9,13 +9,6 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, CWVStopSyncReason) {
// When sync is stopped explicitly via |stopSyncAndClearIdentity|.
CWVStopSyncReasonClient = 0,
// When sync was reset from another device.
CWVStopSyncReasonServer = 1
};
@class CWVSyncController; @class CWVSyncController;
// Delegate of CWVSyncController. // Delegate of CWVSyncController.
...@@ -23,8 +16,9 @@ typedef NS_ENUM(NSInteger, CWVStopSyncReason) { ...@@ -23,8 +16,9 @@ typedef NS_ENUM(NSInteger, CWVStopSyncReason) {
@optional @optional
// Called when sync has been started. Check |syncController|'s |needsPassphrase| // Called when sync has started. Check |syncController|'s |passphraseNeeded|
// property to see if |unlockWithPassphrase:| is necessary. // property to see if |unlockWithPassphrase:| is necessary, and also check
// |consentNeeded| to see if |consent| is necessary.
- (void)syncControllerDidStartSync:(CWVSyncController*)syncController; - (void)syncControllerDidStartSync:(CWVSyncController*)syncController;
// Called when sync fails. |error|'s code is a CWVSyncError. // Called when sync fails. |error|'s code is a CWVSyncError.
...@@ -32,9 +26,8 @@ typedef NS_ENUM(NSInteger, CWVStopSyncReason) { ...@@ -32,9 +26,8 @@ typedef NS_ENUM(NSInteger, CWVStopSyncReason) {
- (void)syncController:(CWVSyncController*)syncController - (void)syncController:(CWVSyncController*)syncController
didFailWithError:(NSError*)error; didFailWithError:(NSError*)error;
// Called after sync was stopped. |reason| Indicates why sync was stopped. // Called after sync has stopped.
- (void)syncController:(CWVSyncController*)syncController - (void)syncControllerDidStopSync:(CWVSyncController*)syncController;
didStopSyncWithReason:(CWVStopSyncReason)reason;
@end @end
......
...@@ -17,11 +17,12 @@ ...@@ -17,11 +17,12 @@
#pragma mark CWVSyncControllerDataSource #pragma mark CWVSyncControllerDataSource
- (void)syncController:(CWVSyncController*)syncController - (void)fetchAccessTokenForIdentity:(CWVIdentity*)identity
getAccessTokenForScopes:(NSArray<NSString*>*)scopes scopes:(NSArray<NSString*>*)scopes
completionHandler:(void (^)(NSString* accessToken, completionHandler:
NSDate* expirationDate, (void (^)(NSString* _Nullable accessToken,
NSError* error))completionHandler { NSDate* _Nullable expirationDate,
NSError* _Nullable error))completionHandler {
// Always returns an error. // Always returns an error.
if (completionHandler) { if (completionHandler) {
completionHandler( completionHandler(
...@@ -32,4 +33,8 @@ ...@@ -32,4 +33,8 @@
} }
} }
- (NSArray<CWVIdentity*>*)allKnownIdentities {
return [self identities];
}
@end @end
...@@ -350,9 +350,7 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier = ...@@ -350,9 +350,7 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier =
CWVSyncController* syncController = CWVSyncController* syncController =
weakSelf.webView.configuration weakSelf.webView.configuration
.syncController; .syncController;
[syncController [syncController startSyncWithIdentity:identity];
startSyncWithIdentity:identity
dataSource:_authService];
}]]; }]];
} }
...@@ -745,9 +743,8 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier = ...@@ -745,9 +743,8 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier =
NSLog(@"%@:%@", NSStringFromSelector(_cmd), error); NSLog(@"%@:%@", NSStringFromSelector(_cmd), error);
} }
- (void)syncController:(CWVSyncController*)syncController - (void)syncControllerDidStopSync:(CWVSyncController*)syncController {
didStopSyncWithReason:(CWVStopSyncReason)reason { NSLog(@"%@", NSStringFromSelector(_cmd));
NSLog(@"%@:%ld", NSStringFromSelector(_cmd), (long)reason);
} }
@end @end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment