Chromium Code Reviews| Index: chrome/browser/chromeos/arc/arc_auth_context.cc |
| diff --git a/chrome/browser/chromeos/arc/arc_auth_context.cc b/chrome/browser/chromeos/arc/arc_auth_context.cc |
| index a7d7747fde8a9a083dd71b317979e411e68b02d5..5236f5eed6bda4dc7a0ef42b9c69f4e9ae2a914a 100644 |
| --- a/chrome/browser/chromeos/arc/arc_auth_context.cc |
| +++ b/chrome/browser/chromeos/arc/arc_auth_context.cc |
| @@ -4,43 +4,64 @@ |
| #include "chrome/browser/chromeos/arc/arc_auth_context.h" |
| +#include "base/json/json_string_value_serializer.h" |
| +#include "base/json/json_writer.h" |
| #include "base/strings/stringprintf.h" |
| +#include "base/values.h" |
| #include "chrome/browser/chromeos/arc/arc_auth_context_delegate.h" |
| #include "chrome/browser/chromeos/arc/arc_support_host.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/browser/ui/ash/multi_user/multi_user_util.h" |
| +#include "components/signin/core/account_id/account_id.h" |
| #include "components/signin/core/browser/profile_oauth2_token_service.h" |
| #include "components/signin/core/browser/signin_manager_base.h" |
| +#include "components/user_manager/known_user.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/url_constants.h" |
| #include "google_apis/gaia/gaia_auth_fetcher.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/http/http_status_code.h" |
| namespace arc { |
| namespace { |
| constexpr int kRefreshTokenTimeoutSeconds = 10; |
| +constexpr int kGetAuthCodeNetworkRetry = 3; |
| + |
| +constexpr char kConsumerName[] = "ArcAuthContext"; |
| +constexpr char kToken[] = "token"; |
| +constexpr char kDeviceId[] = "device_id"; |
| +constexpr char kDeviceType[] = "device_type"; |
| +constexpr char kDeviceTypeArc[] = "arc_plus_plus"; |
| +constexpr char kLoginScopedToken[] = "login_scoped_token"; |
| +constexpr char kGetAuthCodeHeaders[] = |
| + "Content-Type: application/json; charset=utf-8"; |
| +constexpr char kContentTypeJSON[] = "application/json"; |
| } // namespace |
| ArcAuthContext::ArcAuthContext(ArcAuthContextDelegate* delegate, |
| Profile* profile) |
| - : delegate_(delegate) { |
| + : OAuth2TokenService::Consumer(kConsumerName), |
| + delegate_(delegate), |
| + profile_(profile) { |
| // Reuse storage used in ARC OptIn platform app. |
| const std::string site_url = base::StringPrintf( |
| "%s://%s/persist?%s", content::kGuestScheme, ArcSupportHost::kHostAppId, |
| ArcSupportHost::kStorageId); |
| storage_partition_ = content::BrowserContext::GetStoragePartitionForSite( |
| - profile, GURL(site_url)); |
| + profile_, GURL(site_url)); |
| CHECK(storage_partition_); |
| // Get token service and account ID to fetch auth tokens. |
| - token_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(profile); |
| + token_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| const SigninManagerBase* const signin_manager = |
| - SigninManagerFactory::GetForProfile(profile); |
| + SigninManagerFactory::GetForProfile(profile_); |
| CHECK(token_service_ && signin_manager); |
| account_id_ = signin_manager->GetAuthenticatedAccountId(); |
| } |
| @@ -67,18 +88,103 @@ void ArcAuthContext::OnRefreshTokenTimeout() { |
| delegate_->OnPrepareContextFailed(); |
| } |
| +void ArcAuthContext::OnGetTokenSuccess( |
| + const OAuth2TokenService::Request* request, |
| + const std::string& access_token, |
| + const base::Time& expiration_time) { |
| + ResetFetchers(); |
| + |
| + const std::string device_id = user_manager::known_user::GetDeviceId( |
| + multi_user_util::GetAccountIdFromProfile(profile_)); |
| + DCHECK(!device_id.empty()); |
| + |
| + base::DictionaryValue request_data; |
| + request_data.SetString(kLoginScopedToken, access_token); |
| + request_data.SetString(kDeviceType, kDeviceTypeArc); |
| + request_data.SetString(kDeviceId, device_id); |
| + std::string request_string; |
| + base::JSONWriter::Write(request_data, &request_string); |
| + |
| + DCHECK(!auth_endpoint_.empty()); |
| + auth_code_fetcher_ = net::URLFetcher::Create(0, GURL(auth_endpoint_), |
| + net::URLFetcher::POST, this); |
| + auth_code_fetcher_->SetRequestContext( |
| + storage_partition_->GetURLRequestContext()); |
| + auth_code_fetcher_->SetUploadData(kContentTypeJSON, request_string); |
| + auth_code_fetcher_->SetLoadFlags(net::LOAD_NORMAL); |
|
xiyuan
2016/09/07 21:07:55
We might want to use LOAD_DISABLE_CACHE | LOAD_BYP
khmel
2016/09/07 23:08:53
Done
|
| + auth_code_fetcher_->SetAutomaticallyRetryOnNetworkChanges( |
| + kGetAuthCodeNetworkRetry); |
| + auth_code_fetcher_->SetExtraRequestHeaders(kGetAuthCodeHeaders); |
| + auth_code_fetcher_->Start(); |
| +} |
| + |
| +void ArcAuthContext::OnGetTokenFailure( |
| + const OAuth2TokenService::Request* request, |
| + const GoogleServiceAuthError& error) { |
| + VLOG(2) << "Failed to get LST " << error.ToString() << "."; |
| + ResetFetchers(); |
| + |
| + delegate_->OnAuthCodeFailed(); |
| +} |
| + |
| +void ArcAuthContext::OnURLFetchComplete(const net::URLFetcher* source) { |
| + const int response_code = source->GetResponseCode(); |
| + std::string json_string; |
| + source->GetResponseAsString(&json_string); |
| + |
| + ResetFetchers(); |
| + |
| + if (response_code != net::HTTP_OK) { |
| + VLOG(2) << "Server returned wrong response code: " << response_code << "."; |
| + delegate_->OnAuthCodeFailed(); |
| + return; |
| + } |
| + |
| + JSONStringValueDeserializer deserializer(json_string); |
| + std::string error_msg; |
| + std::unique_ptr<base::Value> auth_code_info = |
| + deserializer.Deserialize(nullptr, &error_msg); |
| + if (!auth_code_info) { |
| + VLOG(2) << "Unable to deserialize auth code json data: " << error_msg |
| + << "."; |
| + delegate_->OnAuthCodeFailed(); |
| + return; |
| + } |
| + |
| + std::unique_ptr<base::DictionaryValue> auth_code_dictionary = |
| + base::DictionaryValue::From(std::move(auth_code_info)); |
| + if (!auth_code_dictionary) { |
| + NOTREACHED(); |
| + delegate_->OnAuthCodeFailed(); |
| + return; |
| + } |
| + |
| + std::string auth_code; |
| + if (!auth_code_dictionary->GetString(kToken, &auth_code) || |
| + auth_code.empty()) { |
| + VLOG(2) << "Response does not contain auth code."; |
| + delegate_->OnAuthCodeFailed(); |
| + return; |
| + } |
| + |
| + delegate_->OnAuthCodeRequested(auth_code); |
| +} |
| + |
| void ArcAuthContext::OnMergeSessionSuccess(const std::string& data) { |
| context_prepared_ = true; |
| + ResetFetchers(); |
| delegate_->OnContextReady(); |
| } |
| void ArcAuthContext::OnMergeSessionFailure( |
| const GoogleServiceAuthError& error) { |
| VLOG(2) << "Failed to merge gaia session " << error.ToString() << "."; |
| + ResetFetchers(); |
| delegate_->OnPrepareContextFailed(); |
| } |
| void ArcAuthContext::OnUbertokenSuccess(const std::string& token) { |
| + ResetFetchers(); |
| merger_fetcher_.reset( |
| new GaiaAuthFetcher(this, GaiaConstants::kChromeOSSource, |
| storage_partition_->GetURLRequestContext())); |
| @@ -87,6 +193,7 @@ void ArcAuthContext::OnUbertokenSuccess(const std::string& token) { |
| void ArcAuthContext::OnUbertokenFailure(const GoogleServiceAuthError& error) { |
| VLOG(2) << "Failed to get ubertoken " << error.ToString() << "."; |
| + ResetFetchers(); |
| delegate_->OnPrepareContextFailed(); |
| } |
| @@ -110,13 +217,32 @@ void ArcAuthContext::PrepareContext() { |
| StartFetchers(); |
| } |
| +void ArcAuthContext::FetchAuthCode(const std::string& auth_endpoint) { |
| + DCHECK(context_prepared_); |
| + |
| + ResetFetchers(); |
| + auth_endpoint_ = auth_endpoint; |
| + |
| + OAuth2TokenService::ScopeSet scopes; |
| + scopes.insert(GaiaConstants::kOAuth1LoginScope); |
| + login_token_request_.reset( |
| + token_service_->StartRequest(account_id_, scopes, this).release()); |
| +} |
| + |
| void ArcAuthContext::StartFetchers() { |
| DCHECK(!refresh_token_timeout_.IsRunning()); |
| - merger_fetcher_.reset(); |
| + ResetFetchers(); |
| ubertoken_fetcher_.reset( |
| new UbertokenFetcher(token_service_, this, GaiaConstants::kChromeOSSource, |
| storage_partition_->GetURLRequestContext())); |
| ubertoken_fetcher_->StartFetchingToken(account_id_); |
| } |
| +void ArcAuthContext::ResetFetchers() { |
| + merger_fetcher_.reset(); |
| + login_token_request_.reset(); |
| + auth_code_fetcher_.reset(); |
| + ubertoken_fetcher_.reset(); |
| +} |
| + |
| } // namespace arc |