user_cloud_policy_manager_chromeos.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright (c) 2012 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/chromeos/policy/user_cloud_policy_manager_chromeos.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/logging.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "base/metrics/histogram.h" 12#include "base/metrics/sparse_histogram.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" 15#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 16#include "chrome/browser/chromeos/profiles/profile_helper.h" 17#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h" 18#include "chrome/browser/policy/cloud/resource_cache.h" 19#include "chrome/browser/policy/policy_bundle.h" 20#include "chrome/browser/policy/policy_domain_descriptor.h" 21#include "chrome/common/pref_names.h" 22#include "content/public/browser/browser_thread.h" 23#include "net/url_request/url_request_context_getter.h" 24 25namespace em = enterprise_management; 26 27namespace policy { 28 29namespace { 30 31// UMA histogram names. 32const char kUMADelayInitialization[] = 33 "Enterprise.UserPolicyChromeOS.DelayInitialization"; 34const char kUMAInitialFetchClientError[] = 35 "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError"; 36const char kUMAInitialFetchDelayClientRegister[] = 37 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister"; 38const char kUMAInitialFetchDelayOAuth2Token[] = 39 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token"; 40const char kUMAInitialFetchDelayPolicyFetch[] = 41 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch"; 42const char kUMAInitialFetchDelayTotal[] = 43 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal"; 44const char kUMAInitialFetchOAuth2Error[] = 45 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error"; 46const char kUMAInitialFetchOAuth2NetworkError[] = 47 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError"; 48 49} // namespace 50 51UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS( 52 scoped_ptr<CloudPolicyStore> store, 53 scoped_ptr<ResourceCache> resource_cache, 54 bool wait_for_policy_fetch, 55 base::TimeDelta initial_policy_fetch_timeout) 56 : CloudPolicyManager( 57 PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()), 58 store.get()), 59 store_(store.Pass()), 60 wait_for_policy_fetch_(wait_for_policy_fetch), 61 policy_fetch_timeout_(false, false) { 62 time_init_started_ = base::Time::Now(); 63 if (wait_for_policy_fetch_) { 64 policy_fetch_timeout_.Start( 65 FROM_HERE, 66 initial_policy_fetch_timeout, 67 base::Bind(&UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch, 68 base::Unretained(this))); 69 } 70 if (resource_cache) { 71 // TODO(joaodasilva): Move the backend from the FILE thread to the blocking 72 // pool. 73 component_policy_service_.reset(new ComponentCloudPolicyService( 74 this, 75 store_.get(), 76 resource_cache.Pass(), 77 content::BrowserThread::GetMessageLoopProxyForThread( 78 content::BrowserThread::FILE), 79 content::BrowserThread::GetMessageLoopProxyForThread( 80 content::BrowserThread::IO))); 81 } 82} 83 84UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {} 85 86void UserCloudPolicyManagerChromeOS::Connect( 87 PrefService* local_state, 88 DeviceManagementService* device_management_service, 89 scoped_refptr<net::URLRequestContextGetter> request_context, 90 UserAffiliation user_affiliation) { 91 DCHECK(device_management_service); 92 DCHECK(local_state); 93 local_state_ = local_state; 94 scoped_ptr<CloudPolicyClient> cloud_policy_client( 95 new CloudPolicyClient(std::string(), std::string(), user_affiliation, 96 NULL, device_management_service)); 97 core()->Connect(cloud_policy_client.Pass()); 98 client()->AddObserver(this); 99 100 if (component_policy_service_) 101 component_policy_service_->Connect(client(), request_context); 102 103 // Determine the next step after the CloudPolicyService initializes. 104 if (service()->IsInitializationComplete()) { 105 OnInitializationCompleted(service()); 106 } else { 107 service()->AddObserver(this); 108 } 109} 110 111void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable( 112 const std::string& access_token) { 113 access_token_ = access_token; 114 if (service() && service()->IsInitializationComplete() && 115 client() && !client()->is_registered()) { 116 OnOAuth2PolicyTokenFetched( 117 access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 118 } 119} 120 121bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const { 122 return client() && client()->is_registered(); 123} 124 125void UserCloudPolicyManagerChromeOS::Shutdown() { 126 if (client()) 127 client()->RemoveObserver(this); 128 if (service()) 129 service()->RemoveObserver(this); 130 token_fetcher_.reset(); 131 component_policy_service_.reset(); 132 CloudPolicyManager::Shutdown(); 133} 134 135bool UserCloudPolicyManagerChromeOS::IsInitializationComplete( 136 PolicyDomain domain) const { 137 if (!CloudPolicyManager::IsInitializationComplete(domain)) 138 return false; 139 if (domain == POLICY_DOMAIN_CHROME) 140 return !wait_for_policy_fetch_; 141 if (ComponentCloudPolicyService::SupportsDomain(domain) && 142 component_policy_service_) { 143 return component_policy_service_->is_initialized(); 144 } 145 return true; 146} 147 148void UserCloudPolicyManagerChromeOS::RegisterPolicyDomain( 149 scoped_refptr<const PolicyDomainDescriptor> descriptor) { 150 if (ComponentCloudPolicyService::SupportsDomain(descriptor->domain()) && 151 component_policy_service_) { 152 component_policy_service_->RegisterPolicyDomain(descriptor); 153 } 154} 155 156scoped_ptr<PolicyBundle> UserCloudPolicyManagerChromeOS::CreatePolicyBundle() { 157 scoped_ptr<PolicyBundle> bundle = CloudPolicyManager::CreatePolicyBundle(); 158 if (component_policy_service_) 159 bundle->MergeFrom(component_policy_service_->policy()); 160 return bundle.Pass(); 161} 162 163void UserCloudPolicyManagerChromeOS::OnInitializationCompleted( 164 CloudPolicyService* cloud_policy_service) { 165 DCHECK_EQ(service(), cloud_policy_service); 166 cloud_policy_service->RemoveObserver(this); 167 168 time_init_completed_ = base::Time::Now(); 169 UMA_HISTOGRAM_TIMES(kUMADelayInitialization, 170 time_init_completed_ - time_init_started_); 171 172 // If the CloudPolicyClient isn't registered at this stage then it needs an 173 // OAuth token for the initial registration. 174 // 175 // If |wait_for_policy_fetch_| is true then Profile initialization is blocking 176 // on the initial policy fetch, so the token must be fetched immediately. 177 // In that case, the signin Profile is used to authenticate a Gaia request to 178 // fetch a refresh token, and then the policy token is fetched. 179 // 180 // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder 181 // service will eventually call OnAccessTokenAvailable() once an access token 182 // is available. That call may have already happened while waiting for 183 // initialization of the CloudPolicyService, so in that case check if an 184 // access token is already available. 185 if (!client()->is_registered()) { 186 if (wait_for_policy_fetch_) { 187 FetchPolicyOAuthTokenUsingSigninProfile(); 188 } else if (!access_token_.empty()) { 189 OnOAuth2PolicyTokenFetched( 190 access_token_, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 191 } 192 } 193 194 if (!wait_for_policy_fetch_) { 195 // If this isn't blocking on a policy fetch then 196 // CloudPolicyManager::OnStoreLoaded() already published the cached policy. 197 // Start the refresh scheduler now, which will eventually refresh the 198 // cached policy or make the first fetch once the OAuth2 token is 199 // available. 200 StartRefreshSchedulerIfReady(); 201 } 202} 203 204void UserCloudPolicyManagerChromeOS::OnPolicyFetched( 205 CloudPolicyClient* client) { 206 // No action required. If we're blocked on a policy fetch, we'll learn about 207 // completion of it through OnInitialPolicyFetchComplete(). 208} 209 210void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged( 211 CloudPolicyClient* cloud_policy_client) { 212 DCHECK_EQ(client(), cloud_policy_client); 213 214 if (wait_for_policy_fetch_) { 215 time_client_registered_ = base::Time::Now(); 216 if (!time_token_available_.is_null()) { 217 UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayClientRegister, 218 time_client_registered_ - time_token_available_); 219 } 220 221 // If we're blocked on the policy fetch, now is a good time to issue it. 222 if (client()->is_registered()) { 223 service()->RefreshPolicy( 224 base::Bind( 225 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete, 226 base::Unretained(this))); 227 } else { 228 // If the client has switched to not registered, we bail out as this 229 // indicates the cloud policy setup flow has been aborted. 230 CancelWaitForPolicyFetch(); 231 } 232 } 233} 234 235void UserCloudPolicyManagerChromeOS::OnClientError( 236 CloudPolicyClient* cloud_policy_client) { 237 DCHECK_EQ(client(), cloud_policy_client); 238 if (wait_for_policy_fetch_) { 239 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError, 240 cloud_policy_client->status()); 241 } 242 CancelWaitForPolicyFetch(); 243} 244 245void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyRefreshNeeded() { 246 core()->RefreshSoon(); 247} 248 249void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() { 250 CheckAndPublishPolicy(); 251 StartRefreshSchedulerIfReady(); 252} 253 254void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() { 255 scoped_refptr<net::URLRequestContextGetter> signin_context; 256 Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile(); 257 if (signin_profile) 258 signin_context = signin_profile->GetRequestContext(); 259 if (!signin_context.get()) { 260 LOG(ERROR) << "No signin Profile for policy oauth token fetch!"; 261 OnOAuth2PolicyTokenFetched( 262 std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 263 return; 264 } 265 266 token_fetcher_.reset(new PolicyOAuth2TokenFetcher( 267 signin_context.get(), 268 g_browser_process->system_request_context(), 269 base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched, 270 base::Unretained(this)))); 271 token_fetcher_->Start(); 272} 273 274void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched( 275 const std::string& policy_token, 276 const GoogleServiceAuthError& error) { 277 DCHECK(!client()->is_registered()); 278 279 time_token_available_ = base::Time::Now(); 280 if (wait_for_policy_fetch_) { 281 UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayOAuth2Token, 282 time_token_available_ - time_init_completed_); 283 } 284 285 if (error.state() == GoogleServiceAuthError::NONE) { 286 // Start client registration. Either OnRegistrationStateChanged() or 287 // OnClientError() will be called back. 288 client()->Register(em::DeviceRegisterRequest::USER, 289 policy_token, std::string(), false, std::string()); 290 } else { 291 // Failed to get a token, stop waiting and use an empty policy. 292 CancelWaitForPolicyFetch(); 293 294 UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error, 295 error.state(), 296 GoogleServiceAuthError::NUM_STATES); 297 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { 298 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError, 299 error.network_error()); 300 } 301 } 302 303 token_fetcher_.reset(); 304} 305 306void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete( 307 bool success) { 308 const base::Time now = base::Time::Now(); 309 UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayPolicyFetch, 310 now - time_client_registered_); 311 UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayTotal, now - time_init_started_); 312 CancelWaitForPolicyFetch(); 313} 314 315void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() { 316 if (!wait_for_policy_fetch_) 317 return; 318 319 wait_for_policy_fetch_ = false; 320 CheckAndPublishPolicy(); 321 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler 322 // can be started. 323 StartRefreshSchedulerIfReady(); 324} 325 326void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() { 327 if (core()->refresh_scheduler()) 328 return; // Already started. 329 330 if (wait_for_policy_fetch_) 331 return; // Still waiting for the initial, blocking fetch. 332 333 if (!service() || !local_state_) 334 return; // Not connected. 335 336 if (component_policy_service_ && 337 !component_policy_service_->is_initialized()) { 338 // If the client doesn't have the list of components to fetch yet then don't 339 // start the scheduler. The |component_policy_service_| will call back into 340 // OnComponentCloudPolicyUpdated() once it's ready. 341 return; 342 } 343 344 core()->StartRefreshScheduler(); 345 core()->TrackRefreshDelayPref(local_state_, prefs::kUserPolicyRefreshRate); 346} 347 348} // namespace policy 349