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.
5 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.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/policy/wildcard_login_checker.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/lifetime/application_lifetime.h"
19 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
20 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
21 #include "components/policy/core/common/cloud/device_management_service.h"
22 #include "components/policy/core/common/cloud/system_policy_request_context.h"
23 #include "components/policy/core/common/policy_pref_names.h"
24 #include "content/public/common/content_client.h"
25 #include "net/url_request/url_request_context_getter.h"
28 namespace em = enterprise_management;
34 // UMA histogram names.
35 const char kUMADelayInitialization[] =
36 "Enterprise.UserPolicyChromeOS.DelayInitialization";
37 const char kUMAInitialFetchClientError[] =
38 "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
39 const char kUMAInitialFetchDelayClientRegister[] =
40 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
41 const char kUMAInitialFetchDelayOAuth2Token[] =
42 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
43 const char kUMAInitialFetchDelayPolicyFetch[] =
44 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
45 const char kUMAInitialFetchDelayTotal[] =
46 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
47 const char kUMAInitialFetchOAuth2Error[] =
48 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
49 const char kUMAInitialFetchOAuth2NetworkError[] =
50 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
52 void OnWildcardCheckCompleted(const std::string& username, bool result) {
54 LOG(ERROR) << "Online wildcard login check failed, terminating session.";
56 // TODO(mnissler): This only removes the user pod from the login screen, but
57 // the cryptohome remains. This is because deleting the cryptohome for a
58 // logged-in session is not possible. Fix this either by delaying the
59 // cryptohome deletion operation or by getting rid of the in-session
61 chromeos::UserManager::Get()->RemoveUserFromList(username);
62 chrome::AttemptUserExit();
68 UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS(
69 scoped_ptr<CloudPolicyStore> store,
70 scoped_ptr<CloudExternalDataManager> external_data_manager,
71 const base::FilePath& component_policy_cache_path,
72 bool wait_for_policy_fetch,
73 base::TimeDelta initial_policy_fetch_timeout,
74 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
75 const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
76 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
78 PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
84 external_data_manager_(external_data_manager.Pass()),
85 component_policy_cache_path_(component_policy_cache_path),
86 wait_for_policy_fetch_(wait_for_policy_fetch),
87 policy_fetch_timeout_(false, false) {
88 time_init_started_ = base::Time::Now();
89 if (wait_for_policy_fetch_) {
90 policy_fetch_timeout_.Start(
92 initial_policy_fetch_timeout,
93 base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout,
94 base::Unretained(this)));
98 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
100 void UserCloudPolicyManagerChromeOS::Connect(
101 PrefService* local_state,
102 DeviceManagementService* device_management_service,
103 scoped_refptr<net::URLRequestContextGetter> system_request_context,
104 UserAffiliation user_affiliation) {
105 DCHECK(device_management_service);
107 local_state_ = local_state;
108 scoped_refptr<net::URLRequestContextGetter> request_context;
109 if (system_request_context) {
110 // |system_request_context| can be null for tests.
111 // Use the system request context here instead of a context derived
112 // from the Profile because Connect() is called before the profile is
113 // fully initialized (required so we can perform the initial policy load).
114 // TODO(atwilson): Change this to use a UserPolicyRequestContext once
115 // Connect() is called after profile initialization. http://crbug.com/323591
116 request_context = new SystemPolicyRequestContext(
117 system_request_context,
118 content::GetUserAgent(GURL(
119 device_management_service->GetServerUrl())));
121 scoped_ptr<CloudPolicyClient> cloud_policy_client(
122 new CloudPolicyClient(std::string(), std::string(),
123 kPolicyVerificationKeyHash, user_affiliation,
124 NULL, device_management_service,
126 core()->Connect(cloud_policy_client.Pass());
127 client()->AddObserver(this);
129 external_data_manager_->Connect(request_context);
131 CreateComponentCloudPolicyService(component_policy_cache_path_,
134 // Determine the next step after the CloudPolicyService initializes.
135 if (service()->IsInitializationComplete()) {
136 OnInitializationCompleted(service());
138 service()->AddObserver(this);
142 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
143 const std::string& access_token) {
144 access_token_ = access_token;
146 if (!wildcard_username_.empty()) {
147 wildcard_login_checker_.reset(new WildcardLoginChecker());
148 wildcard_login_checker_->StartWithAccessToken(
150 base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
153 if (service() && service()->IsInitializationComplete() &&
154 client() && !client()->is_registered()) {
155 OnOAuth2PolicyTokenFetched(
156 access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
160 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
161 return client() && client()->is_registered();
164 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
165 const std::string& username) {
166 DCHECK(access_token_.empty());
167 wildcard_username_ = username;
170 void UserCloudPolicyManagerChromeOS::Shutdown() {
172 client()->RemoveObserver(this);
174 service()->RemoveObserver(this);
175 token_fetcher_.reset();
176 external_data_manager_->Disconnect();
177 CloudPolicyManager::Shutdown();
180 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
181 PolicyDomain domain) const {
182 if (!CloudPolicyManager::IsInitializationComplete(domain))
184 if (domain == POLICY_DOMAIN_CHROME)
185 return !wait_for_policy_fetch_;
189 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
190 CloudPolicyService* cloud_policy_service) {
191 DCHECK_EQ(service(), cloud_policy_service);
192 cloud_policy_service->RemoveObserver(this);
194 time_init_completed_ = base::Time::Now();
195 UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization,
196 time_init_completed_ - time_init_started_);
198 // If the CloudPolicyClient isn't registered at this stage then it needs an
199 // OAuth token for the initial registration.
201 // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
202 // on the initial policy fetch, so the token must be fetched immediately.
203 // In that case, the signin Profile is used to authenticate a Gaia request to
204 // fetch a refresh token, and then the policy token is fetched.
206 // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
207 // service will eventually call OnAccessTokenAvailable() once an access token
208 // is available. That call may have already happened while waiting for
209 // initialization of the CloudPolicyService, so in that case check if an
210 // access token is already available.
211 if (!client()->is_registered()) {
212 if (wait_for_policy_fetch_) {
213 FetchPolicyOAuthTokenUsingSigninProfile();
214 } else if (!access_token_.empty()) {
215 OnAccessTokenAvailable(access_token_);
219 if (!wait_for_policy_fetch_) {
220 // If this isn't blocking on a policy fetch then
221 // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
222 // Start the refresh scheduler now, which will eventually refresh the
223 // cached policy or make the first fetch once the OAuth2 token is
225 StartRefreshSchedulerIfReady();
229 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
230 CloudPolicyClient* client) {
231 // No action required. If we're blocked on a policy fetch, we'll learn about
232 // completion of it through OnInitialPolicyFetchComplete().
235 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
236 CloudPolicyClient* cloud_policy_client) {
237 DCHECK_EQ(client(), cloud_policy_client);
239 if (wait_for_policy_fetch_) {
240 time_client_registered_ = base::Time::Now();
241 if (!time_token_available_.is_null()) {
242 UMA_HISTOGRAM_MEDIUM_TIMES(
243 kUMAInitialFetchDelayClientRegister,
244 time_client_registered_ - time_token_available_);
247 // If we're blocked on the policy fetch, now is a good time to issue it.
248 if (client()->is_registered()) {
249 service()->RefreshPolicy(
251 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
252 base::Unretained(this)));
254 // If the client has switched to not registered, we bail out as this
255 // indicates the cloud policy setup flow has been aborted.
256 CancelWaitForPolicyFetch();
261 void UserCloudPolicyManagerChromeOS::OnClientError(
262 CloudPolicyClient* cloud_policy_client) {
263 DCHECK_EQ(client(), cloud_policy_client);
264 if (wait_for_policy_fetch_) {
265 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
266 cloud_policy_client->status());
268 CancelWaitForPolicyFetch();
271 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
272 CloudPolicyManager::OnComponentCloudPolicyUpdated();
273 StartRefreshSchedulerIfReady();
276 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
277 scoped_refptr<net::URLRequestContextGetter> signin_context;
278 Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
280 signin_context = signin_profile->GetRequestContext();
281 if (!signin_context.get()) {
282 LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
283 OnOAuth2PolicyTokenFetched(
284 std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
288 token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
289 signin_context.get(),
290 g_browser_process->system_request_context(),
291 base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
292 base::Unretained(this))));
293 token_fetcher_->Start();
296 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
297 const std::string& policy_token,
298 const GoogleServiceAuthError& error) {
299 DCHECK(!client()->is_registered());
300 time_token_available_ = base::Time::Now();
301 if (wait_for_policy_fetch_) {
302 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token,
303 time_token_available_ - time_init_completed_);
306 if (error.state() == GoogleServiceAuthError::NONE) {
307 // Start client registration. Either OnRegistrationStateChanged() or
308 // OnClientError() will be called back.
309 client()->Register(em::DeviceRegisterRequest::USER,
310 policy_token, std::string(), false, std::string());
312 // Failed to get a token, stop waiting and use an empty policy.
313 CancelWaitForPolicyFetch();
315 UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
317 GoogleServiceAuthError::NUM_STATES);
318 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
319 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
320 error.network_error());
324 token_fetcher_.reset();
327 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
329 const base::Time now = base::Time::Now();
330 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayPolicyFetch,
331 now - time_client_registered_);
332 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayTotal,
333 now - time_init_started_);
334 CancelWaitForPolicyFetch();
337 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
338 if (!wait_for_policy_fetch_)
340 LOG(WARNING) << "Timed out while waiting for the initial policy fetch. "
341 << "The first session will start without policy.";
342 CancelWaitForPolicyFetch();
345 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
346 if (!wait_for_policy_fetch_)
349 wait_for_policy_fetch_ = false;
350 policy_fetch_timeout_.Stop();
351 CheckAndPublishPolicy();
352 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
354 StartRefreshSchedulerIfReady();
357 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
358 if (core()->refresh_scheduler())
359 return; // Already started.
361 if (wait_for_policy_fetch_)
362 return; // Still waiting for the initial, blocking fetch.
364 if (!service() || !local_state_)
365 return; // Not connected.
367 if (component_policy_service() &&
368 !component_policy_service()->is_initialized()) {
369 // If the client doesn't have the list of components to fetch yet then don't
370 // start the scheduler. The |component_policy_service_| will call back into
371 // OnComponentCloudPolicyUpdated() once it's ready.
375 core()->StartRefreshScheduler();
376 core()->TrackRefreshDelayPref(local_state_,
377 policy_prefs::kUserPolicyRefreshRate);
380 } // namespace policy