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