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) { |