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 "base/values.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/policy/wildcard_login_checker.h"
18 #include "chrome/browser/chromeos/profiles/profile_helper.h"
19 #include "chrome/browser/lifetime/application_lifetime.h"
20 #include "chrome/common/chrome_content_client.h"
21 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
22 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
23 #include "components/policy/core/common/cloud/device_management_service.h"
24 #include "components/policy/core/common/cloud/system_policy_request_context.h"
25 #include "components/policy/core/common/policy_map.h"
26 #include "components/policy/core/common/policy_pref_names.h"
27 #include "components/policy/core/common/policy_types.h"
28 #include "components/user_manager/user_manager.h"
29 #include "net/url_request/url_request_context_getter.h"
30 #include "policy/policy_constants.h"
33 namespace em
= enterprise_management
;
39 // UMA histogram names.
40 const char kUMADelayInitialization
[] =
41 "Enterprise.UserPolicyChromeOS.DelayInitialization";
42 const char kUMAInitialFetchClientError
[] =
43 "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
44 const char kUMAInitialFetchDelayClientRegister
[] =
45 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
46 const char kUMAInitialFetchDelayOAuth2Token
[] =
47 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
48 const char kUMAInitialFetchDelayPolicyFetch
[] =
49 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
50 const char kUMAInitialFetchDelayTotal
[] =
51 "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
52 const char kUMAInitialFetchOAuth2Error
[] =
53 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
54 const char kUMAInitialFetchOAuth2NetworkError
[] =
55 "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
57 void OnWildcardCheckCompleted(const std::string
& username
,
58 WildcardLoginChecker::Result result
) {
59 if (result
== WildcardLoginChecker::RESULT_BLOCKED
) {
60 LOG(ERROR
) << "Online wildcard login check failed, terminating session.";
62 // TODO(mnissler): This only removes the user pod from the login screen, but
63 // the cryptohome remains. This is because deleting the cryptohome for a
64 // logged-in session is not possible. Fix this either by delaying the
65 // cryptohome deletion operation or by getting rid of the in-session
67 user_manager::UserManager::Get()->RemoveUserFromList(username
);
68 chrome::AttemptUserExit();
74 UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS(
75 scoped_ptr
<CloudPolicyStore
> store
,
76 scoped_ptr
<CloudExternalDataManager
> external_data_manager
,
77 const base::FilePath
& component_policy_cache_path
,
78 bool wait_for_policy_fetch
,
79 base::TimeDelta initial_policy_fetch_timeout
,
80 const scoped_refptr
<base::SequencedTaskRunner
>& task_runner
,
81 const scoped_refptr
<base::SequencedTaskRunner
>& file_task_runner
,
82 const scoped_refptr
<base::SequencedTaskRunner
>& io_task_runner
)
83 : CloudPolicyManager(dm_protocol::kChromeUserPolicyType
,
90 external_data_manager_(external_data_manager
.Pass()),
91 component_policy_cache_path_(component_policy_cache_path
),
92 wait_for_policy_fetch_(wait_for_policy_fetch
),
93 policy_fetch_timeout_(false, false) {
94 time_init_started_
= base::Time::Now();
95 if (wait_for_policy_fetch_
&& !initial_policy_fetch_timeout
.is_max()) {
96 policy_fetch_timeout_
.Start(
98 initial_policy_fetch_timeout
,
99 base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout
,
100 base::Unretained(this)));
104 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
106 void UserCloudPolicyManagerChromeOS::Connect(
107 PrefService
* local_state
,
108 DeviceManagementService
* device_management_service
,
109 scoped_refptr
<net::URLRequestContextGetter
> system_request_context
,
110 UserAffiliation user_affiliation
) {
111 DCHECK(device_management_service
);
113 local_state_
= local_state
;
114 scoped_refptr
<net::URLRequestContextGetter
> request_context
;
115 if (system_request_context
.get()) {
116 // |system_request_context| can be null for tests.
117 // Use the system request context here instead of a context derived
118 // from the Profile because Connect() is called before the profile is
119 // fully initialized (required so we can perform the initial policy load).
120 // TODO(atwilson): Change this to use a UserPolicyRequestContext once
121 // Connect() is called after profile initialization. http://crbug.com/323591
122 request_context
= new SystemPolicyRequestContext(
123 system_request_context
, GetUserAgent());
125 scoped_ptr
<CloudPolicyClient
> cloud_policy_client(
126 new CloudPolicyClient(std::string(), std::string(),
127 kPolicyVerificationKeyHash
, user_affiliation
,
128 device_management_service
, request_context
));
129 CreateComponentCloudPolicyService(component_policy_cache_path_
,
130 request_context
, cloud_policy_client
.get());
131 core()->Connect(cloud_policy_client
.Pass());
132 client()->AddObserver(this);
134 external_data_manager_
->Connect(request_context
);
136 // Determine the next step after the CloudPolicyService initializes.
137 if (service()->IsInitializationComplete()) {
138 OnInitializationCompleted(service());
140 service()->AddObserver(this);
144 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
145 const std::string
& access_token
) {
146 access_token_
= access_token
;
148 if (!wildcard_username_
.empty()) {
149 wildcard_login_checker_
.reset(new WildcardLoginChecker());
150 wildcard_login_checker_
->StartWithAccessToken(
152 base::Bind(&OnWildcardCheckCompleted
, wildcard_username_
));
155 if (service() && service()->IsInitializationComplete() &&
156 client() && !client()->is_registered()) {
157 OnOAuth2PolicyTokenFetched(
158 access_token
, GoogleServiceAuthError(GoogleServiceAuthError::NONE
));
162 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
163 return client() && client()->is_registered();
166 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
167 const std::string
& username
) {
168 DCHECK(access_token_
.empty());
169 wildcard_username_
= username
;
172 void UserCloudPolicyManagerChromeOS::Shutdown() {
174 client()->RemoveObserver(this);
176 service()->RemoveObserver(this);
177 token_fetcher_
.reset();
178 external_data_manager_
->Disconnect();
179 CloudPolicyManager::Shutdown();
182 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
183 PolicyDomain domain
) const {
184 if (!CloudPolicyManager::IsInitializationComplete(domain
))
186 if (domain
== POLICY_DOMAIN_CHROME
)
187 return !wait_for_policy_fetch_
;
191 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
192 CloudPolicyService
* cloud_policy_service
) {
193 DCHECK_EQ(service(), cloud_policy_service
);
194 cloud_policy_service
->RemoveObserver(this);
196 time_init_completed_
= base::Time::Now();
197 UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization
,
198 time_init_completed_
- time_init_started_
);
200 // If the CloudPolicyClient isn't registered at this stage then it needs an
201 // OAuth token for the initial registration.
203 // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
204 // on the initial policy fetch, so the token must be fetched immediately.
205 // In that case, the signin Profile is used to authenticate a Gaia request to
206 // fetch a refresh token, and then the policy token is fetched.
208 // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
209 // service will eventually call OnAccessTokenAvailable() once an access token
210 // is available. That call may have already happened while waiting for
211 // initialization of the CloudPolicyService, so in that case check if an
212 // access token is already available.
213 if (!client()->is_registered()) {
214 if (wait_for_policy_fetch_
) {
215 FetchPolicyOAuthTokenUsingSigninProfile();
216 } else if (!access_token_
.empty()) {
217 OnAccessTokenAvailable(access_token_
);
221 if (!wait_for_policy_fetch_
) {
222 // If this isn't blocking on a policy fetch then
223 // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
224 // Start the refresh scheduler now, which will eventually refresh the
225 // cached policy or make the first fetch once the OAuth2 token is
227 StartRefreshSchedulerIfReady();
231 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
232 CloudPolicyClient
* client
) {
233 // No action required. If we're blocked on a policy fetch, we'll learn about
234 // completion of it through OnInitialPolicyFetchComplete().
237 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
238 CloudPolicyClient
* cloud_policy_client
) {
239 DCHECK_EQ(client(), cloud_policy_client
);
241 if (wait_for_policy_fetch_
) {
242 time_client_registered_
= base::Time::Now();
243 if (!time_token_available_
.is_null()) {
244 UMA_HISTOGRAM_MEDIUM_TIMES(
245 kUMAInitialFetchDelayClientRegister
,
246 time_client_registered_
- time_token_available_
);
249 // If we're blocked on the policy fetch, now is a good time to issue it.
250 if (client()->is_registered()) {
251 service()->RefreshPolicy(
253 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete
,
254 base::Unretained(this)));
256 // If the client has switched to not registered, we bail out as this
257 // indicates the cloud policy setup flow has been aborted.
258 CancelWaitForPolicyFetch();
263 void UserCloudPolicyManagerChromeOS::OnClientError(
264 CloudPolicyClient
* cloud_policy_client
) {
265 DCHECK_EQ(client(), cloud_policy_client
);
266 if (wait_for_policy_fetch_
) {
267 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError
,
268 cloud_policy_client
->status());
270 CancelWaitForPolicyFetch();
273 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
274 CloudPolicyManager::OnComponentCloudPolicyUpdated();
275 StartRefreshSchedulerIfReady();
278 void UserCloudPolicyManagerChromeOS::GetChromePolicy(PolicyMap
* policy_map
) {
279 CloudPolicyManager::GetChromePolicy(policy_map
);
281 // If the store has a verified policy blob received from the server then apply
282 // the defaults for policies that haven't been configured by the administrator
283 // given that this is an enterprise user.
284 if (!store()->has_policy())
286 SetEnterpriseUsersDefaults(policy_map
);
289 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
290 scoped_refptr
<net::URLRequestContextGetter
> signin_context
;
291 Profile
* signin_profile
= chromeos::ProfileHelper::GetSigninProfile();
293 signin_context
= signin_profile
->GetRequestContext();
294 if (!signin_context
.get()) {
295 LOG(ERROR
) << "No signin Profile for policy oauth token fetch!";
296 OnOAuth2PolicyTokenFetched(
297 std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE
));
301 token_fetcher_
.reset(new PolicyOAuth2TokenFetcher(
302 signin_context
.get(),
303 g_browser_process
->system_request_context(),
304 base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched
,
305 base::Unretained(this))));
306 token_fetcher_
->Start();
309 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
310 const std::string
& policy_token
,
311 const GoogleServiceAuthError
& error
) {
312 DCHECK(!client()->is_registered());
313 time_token_available_
= base::Time::Now();
314 if (wait_for_policy_fetch_
) {
315 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token
,
316 time_token_available_
- time_init_completed_
);
319 if (error
.state() == GoogleServiceAuthError::NONE
) {
320 // Start client registration. Either OnRegistrationStateChanged() or
321 // OnClientError() will be called back.
322 client()->Register(em::DeviceRegisterRequest::USER
,
323 em::DeviceRegisterRequest::FLAVOR_USER_REGISTRATION
,
324 policy_token
, std::string(), std::string(),
327 // Failed to get a token, stop waiting and use an empty policy.
328 CancelWaitForPolicyFetch();
330 UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error
,
332 GoogleServiceAuthError::NUM_STATES
);
333 if (error
.state() == GoogleServiceAuthError::CONNECTION_FAILED
) {
334 // Network errors are negative in the code, but the histogram data type
335 // expects the corresponding positive value.
336 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError
,
337 -error
.network_error());
341 token_fetcher_
.reset();
344 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
346 const base::Time now
= base::Time::Now();
347 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayPolicyFetch
,
348 now
- time_client_registered_
);
349 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayTotal
,
350 now
- time_init_started_
);
351 CancelWaitForPolicyFetch();
354 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
355 if (!wait_for_policy_fetch_
)
357 LOG(WARNING
) << "Timed out while waiting for the initial policy fetch. "
358 << "The first session will start without policy.";
359 CancelWaitForPolicyFetch();
362 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
363 if (!wait_for_policy_fetch_
)
366 wait_for_policy_fetch_
= false;
367 policy_fetch_timeout_
.Stop();
368 CheckAndPublishPolicy();
369 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
371 StartRefreshSchedulerIfReady();
374 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
375 if (core()->refresh_scheduler())
376 return; // Already started.
378 if (wait_for_policy_fetch_
)
379 return; // Still waiting for the initial, blocking fetch.
381 if (!service() || !local_state_
)
382 return; // Not connected.
384 if (component_policy_service() &&
385 !component_policy_service()->is_initialized()) {
386 // If the client doesn't have the list of components to fetch yet then don't
387 // start the scheduler. The |component_policy_service_| will call back into
388 // OnComponentCloudPolicyUpdated() once it's ready.
392 core()->StartRefreshScheduler();
393 core()->TrackRefreshDelayPref(local_state_
,
394 policy_prefs::kUserPolicyRefreshRate
);
397 } // namespace policy