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)
84 PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
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 NULL, device_management_service,
130 core()->Connect(cloud_policy_client.Pass());
131 client()->AddObserver(this);
133 external_data_manager_->Connect(request_context);
135 CreateComponentCloudPolicyService(component_policy_cache_path_,
138 // Determine the next step after the CloudPolicyService initializes.
139 if (service()->IsInitializationComplete()) {
140 OnInitializationCompleted(service());
142 service()->AddObserver(this);
146 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
147 const std::string& access_token) {
148 access_token_ = access_token;
150 if (!wildcard_username_.empty()) {
151 wildcard_login_checker_.reset(new WildcardLoginChecker());
152 wildcard_login_checker_->StartWithAccessToken(
154 base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
157 if (service() && service()->IsInitializationComplete() &&
158 client() && !client()->is_registered()) {
159 OnOAuth2PolicyTokenFetched(
160 access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
164 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
165 return client() && client()->is_registered();
168 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
169 const std::string& username) {
170 DCHECK(access_token_.empty());
171 wildcard_username_ = username;
174 void UserCloudPolicyManagerChromeOS::Shutdown() {
176 client()->RemoveObserver(this);
178 service()->RemoveObserver(this);
179 token_fetcher_.reset();
180 external_data_manager_->Disconnect();
181 CloudPolicyManager::Shutdown();
184 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
185 PolicyDomain domain) const {
186 if (!CloudPolicyManager::IsInitializationComplete(domain))
188 if (domain == POLICY_DOMAIN_CHROME)
189 return !wait_for_policy_fetch_;
193 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
194 CloudPolicyService* cloud_policy_service) {
195 DCHECK_EQ(service(), cloud_policy_service);
196 cloud_policy_service->RemoveObserver(this);
198 time_init_completed_ = base::Time::Now();
199 UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization,
200 time_init_completed_ - time_init_started_);
202 // If the CloudPolicyClient isn't registered at this stage then it needs an
203 // OAuth token for the initial registration.
205 // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
206 // on the initial policy fetch, so the token must be fetched immediately.
207 // In that case, the signin Profile is used to authenticate a Gaia request to
208 // fetch a refresh token, and then the policy token is fetched.
210 // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
211 // service will eventually call OnAccessTokenAvailable() once an access token
212 // is available. That call may have already happened while waiting for
213 // initialization of the CloudPolicyService, so in that case check if an
214 // access token is already available.
215 if (!client()->is_registered()) {
216 if (wait_for_policy_fetch_) {
217 FetchPolicyOAuthTokenUsingSigninProfile();
218 } else if (!access_token_.empty()) {
219 OnAccessTokenAvailable(access_token_);
223 if (!wait_for_policy_fetch_) {
224 // If this isn't blocking on a policy fetch then
225 // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
226 // Start the refresh scheduler now, which will eventually refresh the
227 // cached policy or make the first fetch once the OAuth2 token is
229 StartRefreshSchedulerIfReady();
233 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
234 CloudPolicyClient* client) {
235 // No action required. If we're blocked on a policy fetch, we'll learn about
236 // completion of it through OnInitialPolicyFetchComplete().
239 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
240 CloudPolicyClient* cloud_policy_client) {
241 DCHECK_EQ(client(), cloud_policy_client);
243 if (wait_for_policy_fetch_) {
244 time_client_registered_ = base::Time::Now();
245 if (!time_token_available_.is_null()) {
246 UMA_HISTOGRAM_MEDIUM_TIMES(
247 kUMAInitialFetchDelayClientRegister,
248 time_client_registered_ - time_token_available_);
251 // If we're blocked on the policy fetch, now is a good time to issue it.
252 if (client()->is_registered()) {
253 service()->RefreshPolicy(
255 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
256 base::Unretained(this)));
258 // If the client has switched to not registered, we bail out as this
259 // indicates the cloud policy setup flow has been aborted.
260 CancelWaitForPolicyFetch();
265 void UserCloudPolicyManagerChromeOS::OnClientError(
266 CloudPolicyClient* cloud_policy_client) {
267 DCHECK_EQ(client(), cloud_policy_client);
268 if (wait_for_policy_fetch_) {
269 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
270 cloud_policy_client->status());
272 CancelWaitForPolicyFetch();
275 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
276 CloudPolicyManager::OnComponentCloudPolicyUpdated();
277 StartRefreshSchedulerIfReady();
280 void UserCloudPolicyManagerChromeOS::GetChromePolicy(PolicyMap* policy_map) {
281 CloudPolicyManager::GetChromePolicy(policy_map);
283 // If the store has a verified policy blob received from the server then apply
284 // the defaults for policies that haven't been configured by the administrator
285 // given that this is an enterprise user.
286 if (!store()->has_policy())
288 SetEnterpriseUsersDefaults(policy_map);
291 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
292 scoped_refptr<net::URLRequestContextGetter> signin_context;
293 Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
295 signin_context = signin_profile->GetRequestContext();
296 if (!signin_context.get()) {
297 LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
298 OnOAuth2PolicyTokenFetched(
299 std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
303 token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
304 signin_context.get(),
305 g_browser_process->system_request_context(),
306 base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
307 base::Unretained(this))));
308 token_fetcher_->Start();
311 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
312 const std::string& policy_token,
313 const GoogleServiceAuthError& error) {
314 DCHECK(!client()->is_registered());
315 time_token_available_ = base::Time::Now();
316 if (wait_for_policy_fetch_) {
317 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token,
318 time_token_available_ - time_init_completed_);
321 if (error.state() == GoogleServiceAuthError::NONE) {
322 // Start client registration. Either OnRegistrationStateChanged() or
323 // OnClientError() will be called back.
324 client()->Register(em::DeviceRegisterRequest::USER, policy_token,
325 std::string(), false, 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 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
335 error.network_error());
339 token_fetcher_.reset();
342 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
344 const base::Time now = base::Time::Now();
345 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayPolicyFetch,
346 now - time_client_registered_);
347 UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayTotal,
348 now - time_init_started_);
349 CancelWaitForPolicyFetch();
352 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
353 if (!wait_for_policy_fetch_)
355 LOG(WARNING) << "Timed out while waiting for the initial policy fetch. "
356 << "The first session will start without policy.";
357 CancelWaitForPolicyFetch();
360 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
361 if (!wait_for_policy_fetch_)
364 wait_for_policy_fetch_ = false;
365 policy_fetch_timeout_.Stop();
366 CheckAndPublishPolicy();
367 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
369 StartRefreshSchedulerIfReady();
372 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
373 if (core()->refresh_scheduler())
374 return; // Already started.
376 if (wait_for_policy_fetch_)
377 return; // Still waiting for the initial, blocking fetch.
379 if (!service() || !local_state_)
380 return; // Not connected.
382 if (component_policy_service() &&
383 !component_policy_service()->is_initialized()) {
384 // If the client doesn't have the list of components to fetch yet then don't
385 // start the scheduler. The |component_policy_service_| will call back into
386 // OnComponentCloudPolicyUpdated() once it's ready.
390 core()->StartRefreshScheduler();
391 core()->TrackRefreshDelayPref(local_state_,
392 policy_prefs::kUserPolicyRefreshRate);
395 } // namespace policy