Upstream version 7.36.149.0
[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 "net/url_request/url_request_context_getter.h"
29 #include "policy/policy_constants.h"
30 #include "url/gurl.h"
31
32 namespace em = enterprise_management;
33
34 namespace policy {
35
36 namespace {
37
38 // UMA histogram names.
39 const char kUMADelayInitialization[] =
40     "Enterprise.UserPolicyChromeOS.DelayInitialization";
41 const char kUMAInitialFetchClientError[] =
42     "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
43 const char kUMAInitialFetchDelayClientRegister[] =
44     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
45 const char kUMAInitialFetchDelayOAuth2Token[] =
46     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
47 const char kUMAInitialFetchDelayPolicyFetch[] =
48     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
49 const char kUMAInitialFetchDelayTotal[] =
50     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
51 const char kUMAInitialFetchOAuth2Error[] =
52     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
53 const char kUMAInitialFetchOAuth2NetworkError[] =
54     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
55
56 void OnWildcardCheckCompleted(const std::string& username,
57                               WildcardLoginChecker::Result result) {
58   if (result == WildcardLoginChecker::RESULT_BLOCKED) {
59     LOG(ERROR) << "Online wildcard login check failed, terminating session.";
60
61     // TODO(mnissler): This only removes the user pod from the login screen, but
62     // the cryptohome remains. This is because deleting the cryptohome for a
63     // logged-in session is not possible. Fix this either by delaying the
64     // cryptohome deletion operation or by getting rid of the in-session
65     // wildcard check.
66     chromeos::UserManager::Get()->RemoveUserFromList(username);
67     chrome::AttemptUserExit();
68   }
69 }
70
71 }  // namespace
72
73 UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS(
74     scoped_ptr<CloudPolicyStore> store,
75     scoped_ptr<CloudExternalDataManager> external_data_manager,
76     const base::FilePath& component_policy_cache_path,
77     bool wait_for_policy_fetch,
78     base::TimeDelta initial_policy_fetch_timeout,
79     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
80     const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
81     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
82     : CloudPolicyManager(
83           PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
84           store.get(),
85           task_runner,
86           file_task_runner,
87           io_task_runner),
88       store_(store.Pass()),
89       external_data_manager_(external_data_manager.Pass()),
90       component_policy_cache_path_(component_policy_cache_path),
91       wait_for_policy_fetch_(wait_for_policy_fetch),
92       policy_fetch_timeout_(false, false) {
93   time_init_started_ = base::Time::Now();
94   if (wait_for_policy_fetch_) {
95     policy_fetch_timeout_.Start(
96         FROM_HERE,
97         initial_policy_fetch_timeout,
98         base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout,
99                    base::Unretained(this)));
100   }
101 }
102
103 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
104
105 void UserCloudPolicyManagerChromeOS::Connect(
106     PrefService* local_state,
107     DeviceManagementService* device_management_service,
108     scoped_refptr<net::URLRequestContextGetter> system_request_context,
109     UserAffiliation user_affiliation) {
110   DCHECK(device_management_service);
111   DCHECK(local_state);
112   local_state_ = local_state;
113   scoped_refptr<net::URLRequestContextGetter> request_context;
114   if (system_request_context) {
115     // |system_request_context| can be null for tests.
116     // Use the system request context here instead of a context derived
117     // from the Profile because Connect() is called before the profile is
118     // fully initialized (required so we can perform the initial policy load).
119     // TODO(atwilson): Change this to use a UserPolicyRequestContext once
120     // Connect() is called after profile initialization. http://crbug.com/323591
121     request_context = new SystemPolicyRequestContext(
122         system_request_context, GetUserAgent());
123   }
124   scoped_ptr<CloudPolicyClient> cloud_policy_client(
125       new CloudPolicyClient(std::string(), std::string(),
126                             kPolicyVerificationKeyHash, user_affiliation,
127                             NULL, device_management_service,
128                             request_context));
129   core()->Connect(cloud_policy_client.Pass());
130   client()->AddObserver(this);
131
132   external_data_manager_->Connect(request_context);
133
134   CreateComponentCloudPolicyService(component_policy_cache_path_,
135                                     request_context);
136
137   // Determine the next step after the CloudPolicyService initializes.
138   if (service()->IsInitializationComplete()) {
139     OnInitializationCompleted(service());
140   } else {
141     service()->AddObserver(this);
142   }
143 }
144
145 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
146     const std::string& access_token) {
147   access_token_ = access_token;
148
149   if (!wildcard_username_.empty()) {
150     wildcard_login_checker_.reset(new WildcardLoginChecker());
151     wildcard_login_checker_->StartWithAccessToken(
152         access_token,
153         base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
154   }
155
156   if (service() && service()->IsInitializationComplete() &&
157       client() && !client()->is_registered()) {
158     OnOAuth2PolicyTokenFetched(
159         access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
160   }
161 }
162
163 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
164   return client() && client()->is_registered();
165 }
166
167 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
168     const std::string& username) {
169   DCHECK(access_token_.empty());
170   wildcard_username_ = username;
171 }
172
173 void UserCloudPolicyManagerChromeOS::Shutdown() {
174   if (client())
175     client()->RemoveObserver(this);
176   if (service())
177     service()->RemoveObserver(this);
178   token_fetcher_.reset();
179   external_data_manager_->Disconnect();
180   CloudPolicyManager::Shutdown();
181 }
182
183 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
184     PolicyDomain domain) const {
185   if (!CloudPolicyManager::IsInitializationComplete(domain))
186     return false;
187   if (domain == POLICY_DOMAIN_CHROME)
188     return !wait_for_policy_fetch_;
189   return true;
190 }
191
192 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
193     CloudPolicyService* cloud_policy_service) {
194   DCHECK_EQ(service(), cloud_policy_service);
195   cloud_policy_service->RemoveObserver(this);
196
197   time_init_completed_ = base::Time::Now();
198   UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization,
199                              time_init_completed_ - time_init_started_);
200
201   // If the CloudPolicyClient isn't registered at this stage then it needs an
202   // OAuth token for the initial registration.
203   //
204   // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
205   // on the initial policy fetch, so the token must be fetched immediately.
206   // In that case, the signin Profile is used to authenticate a Gaia request to
207   // fetch a refresh token, and then the policy token is fetched.
208   //
209   // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
210   // service will eventually call OnAccessTokenAvailable() once an access token
211   // is available. That call may have already happened while waiting for
212   // initialization of the CloudPolicyService, so in that case check if an
213   // access token is already available.
214   if (!client()->is_registered()) {
215     if (wait_for_policy_fetch_) {
216       FetchPolicyOAuthTokenUsingSigninProfile();
217     } else if (!access_token_.empty()) {
218       OnAccessTokenAvailable(access_token_);
219     }
220   }
221
222   if (!wait_for_policy_fetch_) {
223     // If this isn't blocking on a policy fetch then
224     // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
225     // Start the refresh scheduler now, which will eventually refresh the
226     // cached policy or make the first fetch once the OAuth2 token is
227     // available.
228     StartRefreshSchedulerIfReady();
229   }
230 }
231
232 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
233     CloudPolicyClient* client) {
234   // No action required. If we're blocked on a policy fetch, we'll learn about
235   // completion of it through OnInitialPolicyFetchComplete().
236 }
237
238 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
239     CloudPolicyClient* cloud_policy_client) {
240   DCHECK_EQ(client(), cloud_policy_client);
241
242   if (wait_for_policy_fetch_) {
243     time_client_registered_ = base::Time::Now();
244     if (!time_token_available_.is_null()) {
245       UMA_HISTOGRAM_MEDIUM_TIMES(
246           kUMAInitialFetchDelayClientRegister,
247           time_client_registered_ - time_token_available_);
248     }
249
250     // If we're blocked on the policy fetch, now is a good time to issue it.
251     if (client()->is_registered()) {
252       service()->RefreshPolicy(
253           base::Bind(
254               &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
255               base::Unretained(this)));
256     } else {
257       // If the client has switched to not registered, we bail out as this
258       // indicates the cloud policy setup flow has been aborted.
259       CancelWaitForPolicyFetch();
260     }
261   }
262 }
263
264 void UserCloudPolicyManagerChromeOS::OnClientError(
265     CloudPolicyClient* cloud_policy_client) {
266   DCHECK_EQ(client(), cloud_policy_client);
267   if (wait_for_policy_fetch_) {
268     UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
269                                 cloud_policy_client->status());
270   }
271   CancelWaitForPolicyFetch();
272 }
273
274 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
275   CloudPolicyManager::OnComponentCloudPolicyUpdated();
276   StartRefreshSchedulerIfReady();
277 }
278
279 void UserCloudPolicyManagerChromeOS::GetChromePolicy(PolicyMap* policy_map) {
280   CloudPolicyManager::GetChromePolicy(policy_map);
281
282   // Default multi-profile behavior for managed accounts to primary-only.
283   if (store()->has_policy() &&
284       !policy_map->Get(key::kChromeOsMultiProfileUserBehavior)) {
285     policy_map->Set(key::kChromeOsMultiProfileUserBehavior,
286                     POLICY_LEVEL_MANDATORY,
287                     POLICY_SCOPE_USER,
288                     new base::StringValue("primary-only"),
289                     NULL);
290   }
291 }
292
293 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
294   scoped_refptr<net::URLRequestContextGetter> signin_context;
295   Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
296   if (signin_profile)
297     signin_context = signin_profile->GetRequestContext();
298   if (!signin_context.get()) {
299     LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
300     OnOAuth2PolicyTokenFetched(
301         std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
302     return;
303   }
304
305   token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
306       signin_context.get(),
307       g_browser_process->system_request_context(),
308       base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
309                  base::Unretained(this))));
310   token_fetcher_->Start();
311 }
312
313 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
314     const std::string& policy_token,
315     const GoogleServiceAuthError& error) {
316   DCHECK(!client()->is_registered());
317   time_token_available_ = base::Time::Now();
318   if (wait_for_policy_fetch_) {
319     UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token,
320                                time_token_available_ - time_init_completed_);
321   }
322
323   if (error.state() == GoogleServiceAuthError::NONE) {
324     // Start client registration. Either OnRegistrationStateChanged() or
325     // OnClientError() will be called back.
326     client()->Register(em::DeviceRegisterRequest::USER, policy_token,
327                        std::string(), false, std::string(), std::string());
328   } else {
329     // Failed to get a token, stop waiting and use an empty policy.
330     CancelWaitForPolicyFetch();
331
332     UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
333                               error.state(),
334                               GoogleServiceAuthError::NUM_STATES);
335     if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
336       UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
337                                   error.network_error());
338     }
339   }
340
341   token_fetcher_.reset();
342 }
343
344 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
345     bool success) {
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();
352 }
353
354 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
355   if (!wait_for_policy_fetch_)
356     return;
357   LOG(WARNING) << "Timed out while waiting for the initial policy fetch. "
358                << "The first session will start without policy.";
359   CancelWaitForPolicyFetch();
360 }
361
362 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
363   if (!wait_for_policy_fetch_)
364     return;
365
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
370   // can be started.
371   StartRefreshSchedulerIfReady();
372 }
373
374 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
375   if (core()->refresh_scheduler())
376     return;  // Already started.
377
378   if (wait_for_policy_fetch_)
379     return;  // Still waiting for the initial, blocking fetch.
380
381   if (!service() || !local_state_)
382     return;  // Not connected.
383
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.
389     return;
390   }
391
392   core()->StartRefreshScheduler();
393   core()->TrackRefreshDelayPref(local_state_,
394                                 policy_prefs::kUserPolicyRefreshRate);
395 }
396
397 }  // namespace policy