1dc5111a831da02dbb6aa0803d86b10b3bb914a5
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / user_cloud_policy_manager_chromeos.cc
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 "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"
31 #include "url/gurl.h"
32
33 namespace em = enterprise_management;
34
35 namespace policy {
36
37 namespace {
38
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";
56
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.";
61
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
66     // wildcard check.
67     user_manager::UserManager::Get()->RemoveUserFromList(username);
68     chrome::AttemptUserExit();
69   }
70 }
71
72 }  // namespace
73
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(
84           PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
85           store.get(),
86           task_runner,
87           file_task_runner,
88           io_task_runner),
89       store_(store.Pass()),
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(
97         FROM_HERE,
98         initial_policy_fetch_timeout,
99         base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout,
100                    base::Unretained(this)));
101   }
102 }
103
104 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
105
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);
112   DCHECK(local_state);
113   local_state_ = local_state;
114   scoped_refptr<net::URLRequestContextGetter> request_context;
115   if (system_request_context) {
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());
124   }
125   scoped_ptr<CloudPolicyClient> cloud_policy_client(
126       new CloudPolicyClient(std::string(), std::string(),
127                             kPolicyVerificationKeyHash, user_affiliation,
128                             NULL, device_management_service,
129                             request_context));
130   core()->Connect(cloud_policy_client.Pass());
131   client()->AddObserver(this);
132
133   external_data_manager_->Connect(request_context);
134
135   CreateComponentCloudPolicyService(component_policy_cache_path_,
136                                     request_context);
137
138   // Determine the next step after the CloudPolicyService initializes.
139   if (service()->IsInitializationComplete()) {
140     OnInitializationCompleted(service());
141   } else {
142     service()->AddObserver(this);
143   }
144 }
145
146 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
147     const std::string& access_token) {
148   access_token_ = access_token;
149
150   if (!wildcard_username_.empty()) {
151     wildcard_login_checker_.reset(new WildcardLoginChecker());
152     wildcard_login_checker_->StartWithAccessToken(
153         access_token,
154         base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
155   }
156
157   if (service() && service()->IsInitializationComplete() &&
158       client() && !client()->is_registered()) {
159     OnOAuth2PolicyTokenFetched(
160         access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
161   }
162 }
163
164 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
165   return client() && client()->is_registered();
166 }
167
168 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
169     const std::string& username) {
170   DCHECK(access_token_.empty());
171   wildcard_username_ = username;
172 }
173
174 void UserCloudPolicyManagerChromeOS::Shutdown() {
175   if (client())
176     client()->RemoveObserver(this);
177   if (service())
178     service()->RemoveObserver(this);
179   token_fetcher_.reset();
180   external_data_manager_->Disconnect();
181   CloudPolicyManager::Shutdown();
182 }
183
184 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
185     PolicyDomain domain) const {
186   if (!CloudPolicyManager::IsInitializationComplete(domain))
187     return false;
188   if (domain == POLICY_DOMAIN_CHROME)
189     return !wait_for_policy_fetch_;
190   return true;
191 }
192
193 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
194     CloudPolicyService* cloud_policy_service) {
195   DCHECK_EQ(service(), cloud_policy_service);
196   cloud_policy_service->RemoveObserver(this);
197
198   time_init_completed_ = base::Time::Now();
199   UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization,
200                              time_init_completed_ - time_init_started_);
201
202   // If the CloudPolicyClient isn't registered at this stage then it needs an
203   // OAuth token for the initial registration.
204   //
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.
209   //
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_);
220     }
221   }
222
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
228     // available.
229     StartRefreshSchedulerIfReady();
230   }
231 }
232
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().
237 }
238
239 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
240     CloudPolicyClient* cloud_policy_client) {
241   DCHECK_EQ(client(), cloud_policy_client);
242
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_);
249     }
250
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(
254           base::Bind(
255               &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
256               base::Unretained(this)));
257     } else {
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();
261     }
262   }
263 }
264
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());
271   }
272   CancelWaitForPolicyFetch();
273 }
274
275 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
276   CloudPolicyManager::OnComponentCloudPolicyUpdated();
277   StartRefreshSchedulerIfReady();
278 }
279
280 void UserCloudPolicyManagerChromeOS::GetChromePolicy(PolicyMap* policy_map) {
281   CloudPolicyManager::GetChromePolicy(policy_map);
282
283   // Default multi-profile behavior for managed accounts to primary-only.
284   if (store()->has_policy() &&
285       !policy_map->Get(key::kChromeOsMultiProfileUserBehavior)) {
286     policy_map->Set(key::kChromeOsMultiProfileUserBehavior,
287                     POLICY_LEVEL_MANDATORY,
288                     POLICY_SCOPE_USER,
289                     new base::StringValue("primary-only"),
290                     NULL);
291   }
292 }
293
294 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
295   scoped_refptr<net::URLRequestContextGetter> signin_context;
296   Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
297   if (signin_profile)
298     signin_context = signin_profile->GetRequestContext();
299   if (!signin_context.get()) {
300     LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
301     OnOAuth2PolicyTokenFetched(
302         std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
303     return;
304   }
305
306   token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
307       signin_context.get(),
308       g_browser_process->system_request_context(),
309       base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
310                  base::Unretained(this))));
311   token_fetcher_->Start();
312 }
313
314 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
315     const std::string& policy_token,
316     const GoogleServiceAuthError& error) {
317   DCHECK(!client()->is_registered());
318   time_token_available_ = base::Time::Now();
319   if (wait_for_policy_fetch_) {
320     UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token,
321                                time_token_available_ - time_init_completed_);
322   }
323
324   if (error.state() == GoogleServiceAuthError::NONE) {
325     // Start client registration. Either OnRegistrationStateChanged() or
326     // OnClientError() will be called back.
327     client()->Register(em::DeviceRegisterRequest::USER, policy_token,
328                        std::string(), false, std::string(), std::string());
329   } else {
330     // Failed to get a token, stop waiting and use an empty policy.
331     CancelWaitForPolicyFetch();
332
333     UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
334                               error.state(),
335                               GoogleServiceAuthError::NUM_STATES);
336     if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
337       UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
338                                   error.network_error());
339     }
340   }
341
342   token_fetcher_.reset();
343 }
344
345 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
346     bool success) {
347   const base::Time now = base::Time::Now();
348   UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayPolicyFetch,
349                              now - time_client_registered_);
350   UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayTotal,
351                              now - time_init_started_);
352   CancelWaitForPolicyFetch();
353 }
354
355 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
356   if (!wait_for_policy_fetch_)
357     return;
358   LOG(WARNING) << "Timed out while waiting for the initial policy fetch. "
359                << "The first session will start without policy.";
360   CancelWaitForPolicyFetch();
361 }
362
363 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
364   if (!wait_for_policy_fetch_)
365     return;
366
367   wait_for_policy_fetch_ = false;
368   policy_fetch_timeout_.Stop();
369   CheckAndPublishPolicy();
370   // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
371   // can be started.
372   StartRefreshSchedulerIfReady();
373 }
374
375 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
376   if (core()->refresh_scheduler())
377     return;  // Already started.
378
379   if (wait_for_policy_fetch_)
380     return;  // Still waiting for the initial, blocking fetch.
381
382   if (!service() || !local_state_)
383     return;  // Not connected.
384
385   if (component_policy_service() &&
386       !component_policy_service()->is_initialized()) {
387     // If the client doesn't have the list of components to fetch yet then don't
388     // start the scheduler. The |component_policy_service_| will call back into
389     // OnComponentCloudPolicyUpdated() once it's ready.
390     return;
391   }
392
393   core()->StartRefreshScheduler();
394   core()->TrackRefreshDelayPref(local_state_,
395                                 policy_prefs::kUserPolicyRefreshRate);
396 }
397
398 }  // namespace policy