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