Chromium Code Reviews| Index: chrome/browser/chromeos/arc/arc_auth_service.cc |
| diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc |
| index 82ae12c6a39b44efa83fb7bf27512b0beff118a3..003de893c8fbf5bb2d1554f0516cf87d2a134e22 100644 |
| --- a/chrome/browser/chromeos/arc/arc_auth_service.cc |
| +++ b/chrome/browser/chromeos/arc/arc_auth_service.cc |
| @@ -7,11 +7,19 @@ |
| #include <utility> |
| #include "chrome/browser/chromeos/arc/arc_auth_ui.h" |
| +#include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| +#include "chrome/browser/signin/signin_manager_factory.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/arc/arc_bridge_service.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| #include "components/prefs/pref_service.h" |
| +#include "components/signin/core/browser/profile_oauth2_token_service.h" |
| +#include "components/signin/core/browser/signin_manager_base.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "google_apis/gaia/gaia_constants.h" |
| +#include "net/url_request/url_request_context.h" |
| namespace arc { |
| @@ -20,6 +28,40 @@ namespace { |
| // Weak pointer. This class is owned by ArcServiceManager. |
| ArcAuthService* arc_auth_service = nullptr; |
| +const int kMaxRetryCnt = 2; |
| +const int kRetryDelayMs = 500; |
| + |
| +const char kSID[] = "SID"; |
| +const char kSSID[] = "SSID"; |
| +const char kLSID[] = "LSID"; |
| +const char kHSID[] = "HSID"; |
| + |
| +const char kArcSID[] = "ARC_SID"; |
| +const char kArcSSID[] = "ARC_SSID"; |
| +const char kArcLSID[] = "ARC_LSID"; |
| +const char kArcHSID[] = "ARC_HSID"; |
| + |
| +bool CopyCookieAsync(const std::string& source_name, |
| + const std::string& target_name, |
| + const GURL& url, |
| + const net::CookieList& cookie_list, |
| + net::CookieStore* cookie_store) { |
| + for (const auto& cookie : cookie_list) { |
| + if (cookie.Name() != source_name) |
| + continue; |
| + base::Callback<void(bool success)> cb; |
| + cookie_store->SetCookieWithDetailsAsync( |
| + url, target_name, cookie.Value(), cookie.Domain(), cookie.Path(), |
| + cookie.CreationDate(), cookie.ExpiryDate(), cookie.IsSecure(), |
| + cookie.IsHttpOnly(), cookie.IsSameSite(), |
| + false, // enforce_strict_secure |
| + cookie.Priority(), cb); |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| // Skip creating UI in unit tests |
| bool disable_ui_for_testing = false; |
| @@ -27,6 +69,7 @@ const char kStateDisable[] = "DISABLE"; |
| const char kStateFetchingCode[] = "FETCHING_CODE"; |
| const char kStateNoCode[] = "NO_CODE"; |
| const char kStateEnable[] = "ENABLE"; |
| + |
| } // namespace |
| ArcAuthService::ArcAuthService(ArcBridgeService* bridge_service) |
| @@ -96,11 +139,14 @@ void ArcAuthService::OnPrimaryUserProfilePrepared(Profile* profile) { |
| Shutdown(); |
| profile_ = profile; |
| + signin_profile_ = chromeos::ProfileHelper::Get()->GetSigninProfile(); |
| + CHECK(signin_profile_); |
| pref_change_registrar_.Init(profile_->GetPrefs()); |
| pref_change_registrar_.Add( |
| prefs::kArcEnabled, base::Bind(&ArcAuthService::OnOptInPreferenceChanged, |
| base::Unretained(this))); |
| + |
| OnOptInPreferenceChanged(); |
| } |
| @@ -110,6 +156,30 @@ void ArcAuthService::Shutdown() { |
| pref_change_registrar_.RemoveAll(); |
| } |
| +void ArcAuthService::OnMergeSessionSuccess(const std::string& data) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + auth_ui_ = new ArcAuthUI(signin_profile_, this); |
| +} |
| + |
| +void ArcAuthService::OnMergeSessionFailure( |
| + const GoogleServiceAuthError& error) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + OnAuthCodeFailed(); |
| +} |
| + |
| +void ArcAuthService::OnUbertokenSuccess(const std::string& token) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + merger_fetcher_.reset( |
| + new GaiaAuthFetcher(this, GaiaConstants::kChromeOSSource, |
| + signin_profile_->GetRequestContext())); |
| + merger_fetcher_->StartMergeSession(token, std::string()); |
| +} |
| + |
| +void ArcAuthService::OnUbertokenFailure(const GoogleServiceAuthError& error) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + OnAuthCodeFailed(); |
| +} |
| + |
| void ArcAuthService::OnOptInPreferenceChanged() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(profile_); |
| @@ -133,7 +203,10 @@ void ArcAuthService::OnOptInPreferenceChanged() { |
| void ArcAuthService::ShutdownBridgeAndCloseUI() { |
| CloseUI(); |
| auth_fetcher_.reset(); |
| + ubertoken_fethcher_.reset(); |
| + merger_fetcher_.reset(); |
| ArcBridgeService::Get()->Shutdown(); |
| + CleanupSigninProfile(); |
| SetState(State::DISABLE); |
| } |
| @@ -157,16 +230,90 @@ void ArcAuthService::CloseUI() { |
| void ArcAuthService::SetAuthCodeAndStartArc(const std::string& auth_code) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(!auth_code.empty()); |
| - DCHECK_NE(state_, State::ENABLE); |
| - |
| ShutdownBridgeAndCloseUI(); |
| + if (state_ != State::FETCHING_CODE) |
| + return; |
| + |
| auth_code_ = auth_code; |
| ArcBridgeService::Get()->HandleStartup(); |
| SetState(State::ENABLE); |
| } |
| +void ArcAuthService::CleanupSigninProfile() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (signin_profile_dirty_) { |
| + chromeos::ProfileHelper::Get()->ClearSigninProfile(base::Closure()); |
| + signin_profile_dirty_ = false; |
| + } |
| +} |
| + |
| +void ArcAuthService::StartFetcherOnUIThread() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (state_ != State::FETCHING_CODE) |
| + return; |
| + |
| + auth_fetcher_.reset( |
| + new ArcAuthFetcher(signin_profile_->GetRequestContext(), this)); |
| +} |
| + |
| +void ArcAuthService::CopyFromArcCookiesOnIOThread( |
| + net::URLRequestContextGetter* context_getter, |
| + const net::CookieList& cookie_list) { |
| + GURL url = ArcAuthFetcher::CreateURL(); |
| + net::CookieStore* cookie_store = |
| + context_getter->GetURLRequestContext()->cookie_store(); |
| + if (!CopyCookieAsync(kArcSID, kSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kArcSSID, kSSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kArcHSID, kHSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kArcLSID, kLSID, url, cookie_list, cookie_store)) { |
| + VLOG(2) << "No ARC cookies were found, proceed to UI."; |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ArcAuthService::ShowUI, base::Unretained(this))); |
| + return; |
| + } |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ArcAuthService::StartFetcherOnUIThread, |
| + base::Unretained(this))); |
| +} |
| + |
| +void ArcAuthService::CopyToArcCookiesOnIOThread( |
| + const std::string& auth_code, |
| + net::URLRequestContextGetter* context_getter, |
| + const net::CookieList& cookie_list) { |
| + const GURL url = ArcAuthFetcher::CreateURL(); |
| + net::CookieStore* cookie_store = |
| + context_getter->GetURLRequestContext()->cookie_store(); |
| + |
| + if (!CopyCookieAsync(kSID, kArcSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kSSID, kArcSSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kHSID, kArcHSID, url, cookie_list, cookie_store) || |
| + !CopyCookieAsync(kLSID, kArcLSID, url, cookie_list, cookie_store)) { |
| + VLOG(2) << "No required cookies were found."; |
| + return; |
| + } |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ArcAuthService::SetAuthCodeAndStartArc, |
| + base::Unretained(this), auth_code)); |
| +} |
| + |
| +void ArcAuthService::StartCopyFromArcCookiesOnIOThread( |
| + net::URLRequestContextGetter* context_getter_from, |
| + net::URLRequestContextGetter* context_getter_to) { |
| + context_getter_from->GetURLRequestContext() |
| + ->cookie_store() |
| + ->GetAllCookiesForURLAsync( |
| + ArcAuthFetcher::CreateURL(), |
| + base::Bind(&ArcAuthService::CopyFromArcCookiesOnIOThread, |
| + base::Unretained(this), context_getter_to)); |
| +} |
| + |
| void ArcAuthService::FetchAuthCode() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(state_ == State::DISABLE || state_ == State::NO_CODE); |
| @@ -176,7 +323,22 @@ void ArcAuthService::FetchAuthCode() { |
| SetState(State::FETCHING_CODE); |
| - auth_fetcher_.reset(new ArcAuthFetcher(profile_->GetRequestContext(), this)); |
| + retry_cnt_ = 0; |
| + CopyCookiesAndStartFetching(); |
| +} |
| + |
| +void ArcAuthService::CopyCookiesAndStartFetching() { |
| + signin_profile_dirty_ = true; |
| + // Copy cookies from user profile to signin profile. |
| + net::URLRequestContextGetter* context_getter_from = |
| + profile_->GetRequestContext(); |
| + net::URLRequestContextGetter* context_getter_to = |
| + signin_profile_->GetRequestContext(); |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ArcAuthService::StartCopyFromArcCookiesOnIOThread, |
| + base::Unretained(this), context_getter_from, |
| + context_getter_to)); |
| } |
| void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { |
| @@ -184,10 +346,44 @@ void ArcAuthService::OnAuthCodeFetched(const std::string& auth_code) { |
| SetAuthCodeAndStartArc(auth_code); |
| } |
| +void ArcAuthService::ShowUI() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + // Get auth token to continue. |
| + OAuth2TokenService::ScopeSet scopes; |
| + scopes.insert(GaiaConstants::kOAuth1LoginScope); |
|
xiyuan
2016/02/09 22:39:35
not used.
|
| + ProfileOAuth2TokenService* token_service = |
| + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| + |
| + SigninManagerBase* signin_manager = |
| + SigninManagerFactory::GetForProfile(profile_); |
| + CHECK(signin_manager); |
| + const std::string& account_id = signin_manager->GetAuthenticatedAccountId(); |
| + |
| + signin_profile_dirty_ = true; |
| + ubertoken_fethcher_.reset( |
| + new UbertokenFetcher(token_service, this, GaiaConstants::kChromeOSSource, |
| + signin_profile_->GetRequestContext())); |
| + ubertoken_fethcher_->StartFetchingToken(account_id); |
| +} |
| + |
| void ArcAuthService::OnAuthCodeNeedUI() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| CloseUI(); |
| - if (!disable_ui_for_testing) |
| - auth_ui_ = new ArcAuthUI(profile_, this); |
| + if (disable_ui_for_testing) |
| + return; |
| + |
| + if (retry_cnt_ >= kMaxRetryCnt) { |
| + ShowUI(); |
| + return; |
| + } |
| + |
| + ++retry_cnt_; |
| + content::BrowserThread::PostDelayedTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&ArcAuthService::CopyCookiesAndStartFetching, |
| + base::Unretained(this)), |
| + base::TimeDelta::FromMilliseconds(kRetryDelayMs)); |
| } |
| void ArcAuthService::OnAuthCodeFailed() { |
| @@ -197,9 +393,34 @@ void ArcAuthService::OnAuthCodeFailed() { |
| SetState(State::NO_CODE); |
| } |
| +void ArcAuthService::StartCopyToArcCookiesOnIOThread( |
| + const std::string& auth_code, |
| + net::URLRequestContextGetter* context_getter_from, |
| + net::URLRequestContextGetter* context_getter_to) { |
| + context_getter_from->GetURLRequestContext() |
| + ->cookie_store() |
| + ->GetAllCookiesForURLAsync( |
| + ArcAuthFetcher::CreateURL(), |
| + base::Bind(&ArcAuthService::CopyToArcCookiesOnIOThread, |
| + base::Unretained(this), auth_code, context_getter_to)); |
| +} |
| + |
| +void ArcAuthService::OnAuthCodeFetchedFromUI(const std::string& auth_code) { |
| + net::URLRequestContextGetter* context_getter_to = |
| + profile_->GetRequestContext(); |
| + net::URLRequestContextGetter* context_getter_from = |
| + signin_profile_->GetRequestContext(); |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ArcAuthService::StartCopyToArcCookiesOnIOThread, |
| + base::Unretained(this), auth_code, context_getter_from, |
| + context_getter_to)); |
| +} |
| + |
| void ArcAuthService::OnAuthUIClosed() { |
| DCHECK(auth_ui_); |
| auth_ui_ = nullptr; |
| + CleanupSigninProfile(); |
| } |
| std::ostream& operator<<(std::ostream& os, const ArcAuthService::State& state) { |