Commit f8b43fee authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Implementation for CWVSyncController.

- Placed behind sync flag.
- Hooked up signinclient and tokenprovider to use CWVSyncController.
- Don't persist signin state between cold launches.

Bug: 867548
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
Change-Id: Icf49e985aadec33b690552ff9973aadb4a5d1dba
Reviewed-on: https://chromium-review.googlesource.com/1211976
Commit-Queue: John Wu <jzw@chromium.org>
Reviewed-by: default avatarHiroshi Ichikawa <ichikawa@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594992}
parent b6b590ae
......@@ -213,7 +213,11 @@ ios_web_view_sources = [
]
ios_web_view_sources += ios_web_view_public_headers
if (ios_web_view_enable_sync) {
ios_web_view_sources += [ "internal/signin/cwv_identity.mm" ]
ios_web_view_sources += [
"internal/signin/cwv_identity.mm",
"internal/sync/cwv_sync_controller.mm",
"internal/sync/cwv_sync_controller_internal.h",
]
}
if (ios_web_view_enable_autofill) {
ios_web_view_sources += [
......
......@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "components/browser_sync/profile_sync_service.h"
#include "ios/web_view/cwv_web_view_features.h"
#include "ios/web_view/internal/app/application_context.h"
#import "ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h"
......@@ -15,6 +16,13 @@
#import "ios/web_view/internal/cwv_preferences_internal.h"
#import "ios/web_view/internal/cwv_user_content_controller_internal.h"
#import "ios/web_view/internal/cwv_web_view_internal.h"
#include "ios/web_view/internal/signin/ios_web_view_signin_client.h"
#include "ios/web_view/internal/signin/web_view_account_tracker_service_factory.h"
#include "ios/web_view/internal/signin/web_view_oauth2_token_service_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_client_factory.h"
#include "ios/web_view/internal/signin/web_view_signin_manager_factory.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"
#include "ios/web_view/internal/web_view_browser_state.h"
#include "ios/web_view/internal/web_view_global_state_util.h"
......@@ -40,6 +48,12 @@
CWVAutofillDataManager* autofillDataManager;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
// This web view configuration's sync controller.
// nil if CWVWebViewConfiguration is created with +incognitoConfiguration.
@property(nonatomic, readonly, nullable) CWVSyncController* syncController;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
// Initializes configuration with the specified browser state mode.
- (instancetype)initWithBrowserState:
(std::unique_ptr<ios_web_view::WebViewBrowserState>)browserState;
......@@ -52,6 +66,9 @@
@synthesize autofillDataManager = _autofillDataManager;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
@synthesize preferences = _preferences;
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
@synthesize syncController = _syncController;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
@synthesize userContentController = _userContentController;
namespace {
......@@ -118,7 +135,6 @@ CWVWebViewConfiguration* gIncognitoConfiguration = nil;
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
#pragma mark - Autofill
- (CWVAutofillDataManager*)autofillDataManager {
if (!_autofillDataManager && self.persistent) {
autofill::PersonalDataManager* personalDataManager =
......@@ -129,9 +145,42 @@ CWVWebViewConfiguration* gIncognitoConfiguration = nil;
}
return _autofillDataManager;
}
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
#pragma mark - Sync
- (CWVSyncController*)syncController {
if (!_syncController && self.persistent) {
browser_sync::ProfileSyncService* profileSyncService =
ios_web_view::WebViewProfileSyncServiceFactory::GetForBrowserState(
self.browserState);
AccountTrackerService* accountTrackerService =
ios_web_view::WebViewAccountTrackerServiceFactory::GetForBrowserState(
self.browserState);
SigninManager* signinManager =
ios_web_view::WebViewSigninManagerFactory::GetForBrowserState(
self.browserState);
ProfileOAuth2TokenService* tokenService =
ios_web_view::WebViewOAuth2TokenServiceFactory::GetForBrowserState(
self.browserState);
_syncController = [[CWVSyncController alloc]
initWithProfileSyncService:profileSyncService
accountTrackerService:accountTrackerService
signinManager:signinManager
tokenService:tokenService];
// 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;
}
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC)
#pragma mark - Public Methods
- (BOOL)isPersistent {
......
......@@ -16,6 +16,8 @@
#include "net/cookies/cookie_change_dispatcher.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@class CWVSyncController;
// iOS WebView specific signin client.
class IOSWebViewSigninClient : public SigninClient,
public SigninErrorController::Observer {
......@@ -46,6 +48,9 @@ class IOSWebViewSigninClient : public SigninClient,
content_settings::Observer* observer) override;
void RemoveContentSettingsObserver(
content_settings::Observer* observer) override;
void PreSignOut(
const base::RepeatingClosure& sign_out,
signin_metrics::ProfileSignout signout_source_metric) override;
void DelayNetworkCall(const base::Closure& callback) override;
std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
GaiaAuthConsumer* consumer,
......@@ -57,6 +62,10 @@ class IOSWebViewSigninClient : public SigninClient,
// SigninErrorController::Observer implementation.
void OnErrorChanged() override;
// CWVSyncController setter/getter.
void SetSyncController(CWVSyncController* sync_controller);
CWVSyncController* GetSyncController() const;
private:
// Helper to delay callbacks until connection becomes online again.
std::unique_ptr<WaitForNetworkCallbackHelper> network_callback_helper_;
......@@ -70,6 +79,10 @@ class IOSWebViewSigninClient : public SigninClient,
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
// Used to add and remove content settings observers.
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
// Used by WebViewProfileOAuth2TokenServiceIOSProviderImpl 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);
};
......
......@@ -7,6 +7,7 @@
#include "components/signin/core/browser/cookie_settings_util.h"
#include "components/signin/core/browser/device_id_helper.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#import "ios/web_view/internal/sync/cwv_sync_controller_internal.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -84,6 +85,13 @@ void IOSWebViewSigninClient::RemoveContentSettingsObserver(
host_content_settings_map_->RemoveObserver(observer);
}
void IOSWebViewSigninClient::PreSignOut(
const base::RepeatingClosure& sign_out,
signin_metrics::ProfileSignout signout_source_metric) {
sign_out.Run();
[sync_controller_ didSignoutWithSourceMetric:signout_source_metric];
}
void IOSWebViewSigninClient::DelayNetworkCall(const base::Closure& callback) {
network_callback_helper_->HandleCallback(callback);
}
......@@ -97,3 +105,12 @@ std::unique_ptr<GaiaAuthFetcher> IOSWebViewSigninClient::CreateGaiaAuthFetcher(
}
void IOSWebViewSigninClient::OnErrorChanged() {}
void IOSWebViewSigninClient::SetSyncController(
CWVSyncController* sync_controller) {
sync_controller_ = sync_controller;
}
CWVSyncController* IOSWebViewSigninClient::GetSyncController() const {
return sync_controller_;
}
......@@ -56,7 +56,8 @@ WebViewOAuth2TokenServiceFactory::BuildServiceInstanceFor(
IOSWebViewSigninClient* signin_client =
WebViewSigninClientFactory::GetForBrowserState(browser_state);
auto token_service_provider =
std::make_unique<WebViewProfileOAuth2TokenServiceIOSProviderImpl>();
std::make_unique<WebViewProfileOAuth2TokenServiceIOSProviderImpl>(
signin_client);
auto delegate = std::make_unique<ProfileOAuth2TokenServiceIOSDelegate>(
signin_client, std::move(token_service_provider),
WebViewAccountTrackerServiceFactory::GetForBrowserState(browser_state),
......
......@@ -11,11 +11,15 @@
#include "base/macros.h"
#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
class IOSWebViewSigninClient;
// Implementation of ProfileOAuth2TokenServiceIOSProvider.
class WebViewProfileOAuth2TokenServiceIOSProviderImpl
: public ProfileOAuth2TokenServiceIOSProvider {
public:
WebViewProfileOAuth2TokenServiceIOSProviderImpl();
// |signin_client| used to fetch access tokens.
explicit WebViewProfileOAuth2TokenServiceIOSProviderImpl(
IOSWebViewSigninClient* signin_client);
~WebViewProfileOAuth2TokenServiceIOSProviderImpl() override;
// ios::ProfileOAuth2TokenServiceIOSProvider
......@@ -29,6 +33,9 @@ class WebViewProfileOAuth2TokenServiceIOSProviderImpl
NSError* error) const override;
private:
// Used to obtain access tokens in |GetAccessToken|.
IOSWebViewSigninClient* const signin_client_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebViewProfileOAuth2TokenServiceIOSProviderImpl);
};
......
......@@ -7,6 +7,7 @@
#include "base/logging.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/public/cwv_identity.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -14,7 +15,9 @@
#endif
WebViewProfileOAuth2TokenServiceIOSProviderImpl::
WebViewProfileOAuth2TokenServiceIOSProviderImpl() {}
WebViewProfileOAuth2TokenServiceIOSProviderImpl(
IOSWebViewSigninClient* signin_client)
: signin_client_(signin_client) {}
WebViewProfileOAuth2TokenServiceIOSProviderImpl::
~WebViewProfileOAuth2TokenServiceIOSProviderImpl() = default;
......@@ -24,10 +27,25 @@ void WebViewProfileOAuth2TokenServiceIOSProviderImpl::GetAccessToken(
const std::string& client_id,
const std::set<std::string>& scopes,
const AccessTokenCallback& callback) {
// |sync_controller| may still be nil if this is called too early so
// |callback| will not be invoked. That's OK because this will be called again
// after |sync_controller| has been set.
CWVSyncController* sync_controller = signin_client_->GetSyncController();
[sync_controller fetchAccessTokenForScopes:scopes callback:callback];
}
std::vector<ProfileOAuth2TokenServiceIOSProvider::AccountInfo>
WebViewProfileOAuth2TokenServiceIOSProviderImpl::GetAllAccounts() const {
// |sync_controller| may still be nil if this is called too early. That's OK
// because this will be called again after it has been set.
CWVSyncController* sync_controller = signin_client_->GetSyncController();
CWVIdentity* current_identity = sync_controller.currentIdentity;
if (current_identity) {
AccountInfo account_info;
account_info.email = base::SysNSStringToUTF8(current_identity.email);
account_info.gaia = base::SysNSStringToUTF8(current_identity.gaiaID);
return {account_info};
}
return {};
}
......
// 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/web_view/internal/sync/cwv_sync_controller_internal.h"
#import <UIKit/UIKit.h>
#include <memory>
#include "base/strings/sys_string_conversions.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
#include "ios/web/public/web_thread.h"
#import "ios/web_view/public/cwv_identity.h"
#import "ios/web_view/public/cwv_sync_controller_data_source.h"
#import "ios/web_view/public/cwv_sync_controller_delegate.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface CWVSyncController ()
// Called by WebViewSyncServiceObserverBridge's |OnSyncConfigurationCompleted|.
- (void)didCompleteSyncConfiguration;
// Called by WebViewSyncServiceObserverBridge's |OnSyncShutdown|.
- (void)didShutdownSync;
// Call to refresh access tokens for |currentIdentity|.
- (void)reloadCredentials;
@end
namespace ios_web_view {
// Bridge that observes browser_sync::ProfileSyncService and calls analagous
// methods on CWVSyncController.
class WebViewSyncServiceObserverBridge : public syncer::SyncServiceObserver {
public:
explicit WebViewSyncServiceObserverBridge(CWVSyncController* sync_controller)
: sync_controller_(sync_controller) {}
void OnStateChanged(syncer::SyncService* sync) override {
// No op.
}
void OnSyncCycleCompleted(syncer::SyncService* sync) override {
// No op.
}
void OnSyncConfigurationCompleted(syncer::SyncService* sync) override {
[sync_controller_ didCompleteSyncConfiguration];
}
void OnForeignSessionUpdated(syncer::SyncService* sync) override {
// No op.
}
void OnSyncShutdown(syncer::SyncService* sync) override {
[sync_controller_ didShutdownSync];
}
private:
__weak CWVSyncController* sync_controller_;
};
} // namespace ios_web_view
@implementation CWVSyncController {
browser_sync::ProfileSyncService* _profileSyncService;
AccountTrackerService* _accountTrackerService;
SigninManager* _signinManager;
IOSWebViewSigninClient* _signinClient;
ProfileOAuth2TokenService* _tokenService;
std::unique_ptr<ios_web_view::WebViewSyncServiceObserverBridge> _observer;
// Data source that can provide access tokens.
__weak id<CWVSyncControllerDataSource> _dataSource;
}
@synthesize delegate = _delegate;
- (instancetype)
initWithProfileSyncService:(browser_sync::ProfileSyncService*)profileSyncService
accountTrackerService:(AccountTrackerService*)accountTrackerService
signinManager:(SigninManager*)signinManager
tokenService:(ProfileOAuth2TokenService*)tokenService {
self = [super init];
if (self) {
_profileSyncService = profileSyncService;
_accountTrackerService = accountTrackerService;
_signinManager = signinManager;
_tokenService = tokenService;
_observer =
std::make_unique<ios_web_view::WebViewSyncServiceObserverBridge>(self);
_profileSyncService->AddObserver(_observer.get());
// Refresh access tokens on foreground to extend expiration dates.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(reloadCredentials)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
}
- (void)dealloc {
_profileSyncService->RemoveObserver(_observer.get());
}
#pragma mark - Public Methods
- (CWVIdentity*)currentIdentity {
std::string authenticatedID = _signinManager->GetAuthenticatedAccountId();
if (authenticatedID.empty()) {
return nil;
}
AccountInfo accountInfo =
_accountTrackerService->GetAccountInfo(authenticatedID);
NSString* email = base::SysUTF8ToNSString(accountInfo.email);
NSString* fullName = base::SysUTF8ToNSString(accountInfo.full_name);
NSString* gaiaID = base::SysUTF8ToNSString(accountInfo.gaia);
return
[[CWVIdentity alloc] initWithEmail:email fullName:fullName gaiaID:gaiaID];
}
- (BOOL)isPassphraseNeeded {
return _profileSyncService->IsPassphraseRequiredForDecryption();
}
- (void)startSyncWithIdentity:(CWVIdentity*)identity
dataSource:
(__weak id<CWVSyncControllerDataSource>)dataSource {
DCHECK(!_dataSource);
_dataSource = dataSource;
AccountInfo info;
info.gaia = base::SysNSStringToUTF8(identity.gaiaID);
info.email = base::SysNSStringToUTF8(identity.email);
info.full_name = base::SysNSStringToUTF8(identity.fullName);
std::string newAuthenticatedAccountID =
_accountTrackerService->SeedAccountInfo(info);
_signinManager->OnExternalSigninCompleted(info.email);
[self reloadCredentials];
_profileSyncService->RequestStart();
_profileSyncService->SetFirstSetupComplete();
}
- (void)stopSyncAndClearIdentity {
_profileSyncService->RequestStop(syncer::SyncService::CLEAR_DATA);
_signinManager->SignOut(
signin_metrics::ProfileSignout::USER_CLICKED_SIGNOUT_SETTINGS,
signin_metrics::SignoutDelete::IGNORE_METRIC);
_dataSource = nil;
}
- (BOOL)unlockWithPassphrase:(NSString*)passphrase {
return _profileSyncService->SetDecryptionPassphrase(
base::SysNSStringToUTF8(passphrase));
}
#pragma mark - Private Methods
- (void)didCompleteSyncConfiguration {
if ([_delegate respondsToSelector:@selector(syncControllerDidStartSync:)]) {
[_delegate syncControllerDidStartSync:self];
}
}
- (void)didShutdownSync {
_profileSyncService->RemoveObserver(_observer.get());
}
- (void)reloadCredentials {
std::string authenticatedID = _signinManager->GetAuthenticatedAccountId();
if (!authenticatedID.empty()) {
ProfileOAuth2TokenServiceIOSDelegate* tokenDelegate =
static_cast<ProfileOAuth2TokenServiceIOSDelegate*>(
_tokenService->GetDelegate());
tokenDelegate->LoadCredentials(authenticatedID);
}
}
#pragma mark - Internal Methods
- (void)fetchAccessTokenForScopes:(const std::set<std::string>&)scopes
callback:(const ProfileOAuth2TokenServiceIOSProvider::
AccessTokenCallback&)callback {
NSMutableArray<NSString*>* scopesArray = [NSMutableArray array];
for (const auto& scope : scopes) {
[scopesArray addObject:base::SysUTF8ToNSString(scope)];
}
ProfileOAuth2TokenServiceIOSProvider::AccessTokenCallback scopedCallback =
callback;
[_dataSource syncController:self
getAccessTokenForScopes:[scopesArray copy]
completionHandler:^(NSString* accessToken, NSDate* expirationDate,
NSError* error) {
if (!scopedCallback.is_null()) {
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;
}
[_delegate syncController:self didStopSyncWithReason:reason];
}
@end
// 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.
#ifndef 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/core/browser/signin_metrics.h"
#include "ios/web_view/internal/signin/web_view_profile_oauth2_token_service_ios_provider_impl.h"
#import "ios/web_view/public/cwv_sync_controller.h"
namespace browser_sync {
class ProfileSyncService;
} // namespace browser_sync
class AccountTrackerService;
class SigninManager;
class ProfileOAuth2TokenService;
@interface CWVSyncController ()
// All dependencies must out live this class.
- (instancetype)
initWithProfileSyncService:(browser_sync::ProfileSyncService*)profileSyncService
accountTrackerService:(AccountTrackerService*)accountTrackerService
signinManager:(SigninManager*)signinManager
tokenService:(ProfileOAuth2TokenService*)tokenService
NS_DESIGNATED_INITIALIZER;
// Called by WebViewProfileOAuth2TokenServiceIOSProviderImpl to obtain
// access tokens for |scopes| to be passed back in |callback|.
- (void)fetchAccessTokenForScopes:(const std::set<std::string>&)scopes
callback:(const ProfileOAuth2TokenServiceIOSProvider::
AccessTokenCallback&)callback;
// Called by IOSWebViewSigninClient when signing out.
- (void)didSignoutWithSourceMetric:(signin_metrics::ProfileSignout)metric;
@end
#endif // IOS_WEB_VIEW_INTERNAL_SYNC_CWV_SYNC_CONTROLLER_INTERNAL_H_
......@@ -29,6 +29,13 @@ void InitializeGlobalState() {
web_main_delegate =
std::make_unique<ios_web_view::WebViewWebMainDelegate>();
web::WebMainParams params(web_main_delegate.get());
params.argc = 2;
const char* executable = "ios-web-view";
// This is used in SigninManagerBase to clear the tokens on startup. This
// greatly simplifies the management of ChromeWebView's signin state.
const char* clear_token = "--clear-token-service";
const char* argv[] = {executable, clear_token};
params.argv = argv;
web_main = std::make_unique<web::WebMain>(std::move(params));
});
}
......
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