user_policy_identity_strategy.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/policy/user_policy_identity_strategy.h" 6 7#include "base/file_util.h" 8#include "chrome/browser/browser_signin.h" 9#include "chrome/browser/net/gaia/token_service.h" 10#include "chrome/browser/policy/proto/device_management_backend.pb.h" 11#include "chrome/browser/policy/proto/device_management_constants.h" 12#include "chrome/browser/policy/proto/device_management_local.pb.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/guid.h" 15#include "chrome/common/net/gaia/gaia_constants.h" 16#include "chrome/common/notification_details.h" 17#include "chrome/common/notification_service.h" 18#include "chrome/common/notification_source.h" 19#include "content/browser/browser_thread.h" 20 21#if defined(OS_CHROMEOS) 22#include "chrome/browser/chromeos/login/user_manager.h" 23#endif 24 25namespace policy { 26 27namespace em = enterprise_management; 28 29// Responsible for managing the on-disk token cache. 30class UserPolicyIdentityStrategy::TokenCache 31 : public base::RefCountedThreadSafe< 32 UserPolicyIdentityStrategy::TokenCache> { 33 public: 34 TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy, 35 const FilePath& cache_file); 36 37 void Load(); 38 void Store(const std::string& token, const std::string& device_id); 39 40 private: 41 friend class base::RefCountedThreadSafe< 42 UserPolicyIdentityStrategy::TokenCache>; 43 ~TokenCache() {} 44 void LoadOnFileThread(); 45 void NotifyOnUIThread(const std::string& token, 46 const std::string& device_id); 47 void StoreOnFileThread(const std::string& token, 48 const std::string& device_id); 49 50 const base::WeakPtr<UserPolicyIdentityStrategy> identity_strategy_; 51 const FilePath cache_file_; 52 53 DISALLOW_COPY_AND_ASSIGN(TokenCache); 54}; 55 56UserPolicyIdentityStrategy::TokenCache::TokenCache( 57 const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy, 58 const FilePath& cache_file) 59 : identity_strategy_(identity_strategy), 60 cache_file_(cache_file) {} 61 62void UserPolicyIdentityStrategy::TokenCache::Load() { 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 64 BrowserThread::PostTask( 65 BrowserThread::FILE, FROM_HERE, 66 NewRunnableMethod( 67 this, &UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread)); 68} 69 70void UserPolicyIdentityStrategy::TokenCache::Store( 71 const std::string& token, 72 const std::string& device_id) { 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 74 BrowserThread::PostTask( 75 BrowserThread::FILE, FROM_HERE, 76 NewRunnableMethod( 77 this, 78 &UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread, 79 token, 80 device_id)); 81} 82 83void UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread() { 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 85 std::string device_token; 86 std::string device_id; 87 88 if (file_util::PathExists(cache_file_)) { 89 std::string data; 90 em::DeviceCredentials device_credentials; 91 if (file_util::ReadFileToString(cache_file_, &data) && 92 device_credentials.ParseFromArray(data.c_str(), data.size())) { 93 device_token = device_credentials.device_token(); 94 device_id = device_credentials.device_id(); 95 } 96 } 97 98 BrowserThread::PostTask( 99 BrowserThread::UI, FROM_HERE, 100 NewRunnableMethod( 101 this, 102 &UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread, 103 device_token, 104 device_id)); 105} 106 107void UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread( 108 const std::string& token, 109 const std::string& device_id) { 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 111 if (identity_strategy_.get()) 112 identity_strategy_->OnCacheLoaded(token, device_id); 113} 114 115void UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread( 116 const std::string& token, 117 const std::string& device_id) { 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 119 em::DeviceCredentials device_credentials; 120 device_credentials.set_device_token(token); 121 device_credentials.set_device_id(device_id); 122 std::string data; 123 bool success = device_credentials.SerializeToString(&data); 124 if (!success) { 125 LOG(WARNING) << "Failed serialize device token data, will not write " 126 << cache_file_.value(); 127 return; 128 } 129 130 file_util::WriteFile(cache_file_, data.c_str(), data.length()); 131} 132 133UserPolicyIdentityStrategy::UserPolicyIdentityStrategy( 134 Profile* profile, 135 const FilePath& cache_file) 136 : profile_(profile), 137 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 138 cache_ = new TokenCache(weak_ptr_factory_.GetWeakPtr(), cache_file); 139 registrar_.Add(this, 140 NotificationType::TOKEN_AVAILABLE, 141 Source<TokenService>(profile->GetTokenService())); 142 143 // Register for the event of user login. The device management token won't 144 // be fetched until we know the domain of the currently logged in user. 145#if defined(OS_CHROMEOS) 146 registrar_.Add(this, 147 NotificationType::LOGIN_USER_CHANGED, 148 NotificationService::AllSources()); 149#else 150 registrar_.Add(this, 151 NotificationType::GOOGLE_SIGNIN_SUCCESSFUL, 152 Source<Profile>(profile_)); 153#endif 154 155 cache_->Load(); 156} 157 158UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {} 159 160std::string UserPolicyIdentityStrategy::GetDeviceToken() { 161 return device_token_; 162} 163 164std::string UserPolicyIdentityStrategy::GetDeviceID() { 165 return device_id_; 166} 167 168std::string UserPolicyIdentityStrategy::GetMachineID() { 169 return ""; 170} 171 172em::DeviceRegisterRequest_Type 173UserPolicyIdentityStrategy::GetPolicyRegisterType() { 174 return em::DeviceRegisterRequest::USER; 175} 176 177std::string UserPolicyIdentityStrategy::GetPolicyType() { 178 return kChromeUserPolicyType; 179} 180 181 182bool UserPolicyIdentityStrategy::GetCredentials(std::string* username, 183 std::string* auth_token) { 184 *username = GetCurrentUser(); 185 *auth_token = profile_->GetTokenService()->GetTokenForService( 186 GaiaConstants::kDeviceManagementService); 187 188 return !username->empty() && !auth_token->empty() && !device_id_.empty(); 189} 190 191void UserPolicyIdentityStrategy::OnDeviceTokenAvailable( 192 const std::string& token) { 193 DCHECK(!device_id_.empty()); 194 device_token_ = token; 195 cache_->Store(device_token_, device_id_); 196 NotifyDeviceTokenChanged(); 197} 198 199std::string UserPolicyIdentityStrategy::GetCurrentUser() { 200#if defined(OS_CHROMEOS) 201 // TODO(mnissler) On CrOS it seems impossible to figure out what user belongs 202 // to a profile. Revisit after multi-profile support landed. 203 return chromeos::UserManager::Get()->logged_in_user().email(); 204#else 205 return profile_->GetBrowserSignin()->GetSignedInUsername(); 206#endif 207} 208 209void UserPolicyIdentityStrategy::CheckAndTriggerFetch() { 210 if (!GetCurrentUser().empty() && 211 profile_->GetTokenService()->HasTokenForService( 212 GaiaConstants::kDeviceManagementService)) { 213 // For user tokens, there is no actual identifier. We generate a random 214 // identifier instead each time we ask for the token. 215 device_id_ = guid::GenerateGUID(); 216 NotifyAuthChanged(); 217 } 218} 219 220void UserPolicyIdentityStrategy::OnCacheLoaded(const std::string& token, 221 const std::string& device_id) { 222 if (!token.empty() && !device_id.empty()) { 223 device_token_ = token; 224 device_id_ = device_id; 225 NotifyDeviceTokenChanged(); 226 } else { 227 CheckAndTriggerFetch(); 228 } 229} 230 231void UserPolicyIdentityStrategy::Observe(NotificationType type, 232 const NotificationSource& source, 233 const NotificationDetails& details) { 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 235 if (type == NotificationType::TOKEN_AVAILABLE) { 236 if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) { 237 const TokenService::TokenAvailableDetails* token_details = 238 Details<const TokenService::TokenAvailableDetails>(details).ptr(); 239 if (token_details->service() == GaiaConstants::kDeviceManagementService) 240 if (device_token_.empty()) { 241 // Request a new device management server token, but only in case we 242 // don't already have it. 243 CheckAndTriggerFetch(); 244 } 245 } 246#if defined(OS_CHROMEOS) 247 } else if (type == NotificationType::LOGIN_USER_CHANGED) { 248 CheckAndTriggerFetch(); 249#else 250 } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) { 251 if (profile_ == Source<Profile>(source).ptr()) 252 CheckAndTriggerFetch(); 253#endif 254 } else { 255 NOTREACHED(); 256 } 257} 258 259} // namespace policy 260