1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/signin/mutable_profile_oauth2_token_service.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/webdata/token_web_data.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/webdata/common/web_data_service_base.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(ENABLE_MANAGED_USERS) 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/managed_mode/managed_user_constants.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kAccountIdPrefix[] = "AccountId-"; 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const size_t kAccountIdPrefixLength = 10; 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool IsLegacyRefreshTokenId(const std::string& service_id) { 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return service_id == GaiaConstants::kGaiaOAuth2LoginRefreshToken; 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool IsLegacyServiceId(const std::string& account_id) { 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return account_id.compare(0u, kAccountIdPrefixLength, kAccountIdPrefix) != 0; 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) { 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return prefixed_account_id.substr(kAccountIdPrefixLength); 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MutableProfileOAuth2TokenService::MutableProfileOAuth2TokenService() 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : web_data_service_request_(0) { 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MutableProfileOAuth2TokenService::~MutableProfileOAuth2TokenService() { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MutableProfileOAuth2TokenService::Shutdown() { 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (web_data_service_request_ != 0) { 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<TokenWebData> token_web_data = 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TokenWebData::FromBrowserContext(profile()); 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(token_web_data.get()); 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token_web_data->CancelRequest(web_data_service_request_); 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) web_data_service_request_ = 0; 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ProfileOAuth2TokenService::Shutdown(); 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MutableProfileOAuth2TokenService::LoadCredentials() { 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_EQ(0, web_data_service_request_); 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CancelAllRequests(); 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) refresh_tokens().clear(); 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<TokenWebData> token_web_data = 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TokenWebData::FromBrowserContext(profile()); 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (token_web_data.get()) 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) web_data_service_request_ = token_web_data->GetAllTokens(this); 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MutableProfileOAuth2TokenService::OnWebDataServiceRequestDone( 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebDataServiceBase::Handle handle, 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const WDTypedResult* result) { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_EQ(web_data_service_request_, handle); 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) web_data_service_request_ = 0; 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result) { 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(result->GetType() == TOKEN_RESULT); 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const WDResult<std::map<std::string, std::string> > * token_result = 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<const WDResult<std::map<std::string, std::string> > * > ( 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result); 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LoadAllCredentialsIntoMemory(token_result->GetValue()); 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string account_id = GetPrimaryAccountId(); 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If |account_id| is not empty, make sure that we have an entry in the 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // map for it. The entry could be missing if there is a corruption in 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the token DB while this profile is connected to an account. 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!account_id.empty() && refresh_tokens().count(account_id) == 0) { 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) refresh_tokens()[account_id].reset( 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new AccountInfo(this, account_id, std::string())); 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If we don't have a refresh token for the primary account, signal a signin 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // error. 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!account_id.empty() && !RefreshTokenIsAvailable(account_id)) { 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UpdateAuthError( 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) account_id, 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GoogleServiceAuthError( 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MutableProfileOAuth2TokenService::LoadAllCredentialsIntoMemory( 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::map<std::string, std::string>& db_tokens) { 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string old_login_token; 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (std::map<std::string, std::string>::const_iterator iter = 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) db_tokens.begin(); 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) iter != db_tokens.end(); 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++iter) { 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string prefixed_account_id = iter->first; 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string refresh_token = iter->second; 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IsLegacyRefreshTokenId(prefixed_account_id) && !refresh_token.empty()) 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) old_login_token = refresh_token; 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IsLegacyServiceId(prefixed_account_id)) { 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<TokenWebData> token_web_data = 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TokenWebData::FromBrowserContext(profile()); 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (token_web_data.get()) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token_web_data->RemoveTokenForService(prefixed_account_id); 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!refresh_token.empty()); 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string account_id = RemoveAccountIdPrefix(prefixed_account_id); 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) refresh_tokens()[account_id].reset( 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new AccountInfo(this, account_id, refresh_token)); 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FireRefreshTokenAvailable(account_id); 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(fgorski): Notify diagnostic observers. 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!old_login_token.empty()) { 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string account_id = GetAccountIdForMigratingRefreshToken(); 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (refresh_tokens().count(account_id) == 0) 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UpdateCredentials(account_id, old_login_token); 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FireRefreshTokensLoaded(); 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MutableProfileOAuth2TokenService::GetAccountIdForMigratingRefreshToken() { 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(ENABLE_MANAGED_USERS) 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(bauerb): Make sure that only services that can deal with supervised 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // users see the supervised user token. 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (profile()->IsManaged()) 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return managed_users::kManagedUserPseudoEmail; 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return GetPrimaryAccountId(); 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 148