Upstream version 5.34.104.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 "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"
26 #include "url/gurl.h"
27
28 namespace em = enterprise_management;
29
30 namespace policy {
31
32 namespace {
33
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";
51
52 void OnWildcardCheckCompleted(const std::string& username, bool result) {
53   if (!result) {
54     LOG(ERROR) << "Online wildcard login check failed, terminating session.";
55
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
60     // wildcard check.
61     chromeos::UserManager::Get()->RemoveUserFromList(username);
62     chrome::AttemptUserExit();
63   }
64 }
65
66 }  // namespace
67
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)
77     : CloudPolicyManager(
78           PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
79           store.get(),
80           task_runner,
81           file_task_runner,
82           io_task_runner),
83       store_(store.Pass()),
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(
91         FROM_HERE,
92         initial_policy_fetch_timeout,
93         base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout,
94                    base::Unretained(this)));
95   }
96 }
97
98 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
99
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);
106   DCHECK(local_state);
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())));
120   }
121   scoped_ptr<CloudPolicyClient> cloud_policy_client(
122       new CloudPolicyClient(std::string(), std::string(),
123                             kPolicyVerificationKeyHash, user_affiliation,
124                             NULL, device_management_service,
125                             request_context));
126   core()->Connect(cloud_policy_client.Pass());
127   client()->AddObserver(this);
128
129   external_data_manager_->Connect(request_context);
130
131   CreateComponentCloudPolicyService(component_policy_cache_path_,
132                                     request_context);
133
134   // Determine the next step after the CloudPolicyService initializes.
135   if (service()->IsInitializationComplete()) {
136     OnInitializationCompleted(service());
137   } else {
138     service()->AddObserver(this);
139   }
140 }
141
142 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
143     const std::string& access_token) {
144   access_token_ = access_token;
145
146   if (!wildcard_username_.empty()) {
147     wildcard_login_checker_.reset(new WildcardLoginChecker());
148     wildcard_login_checker_->StartWithAccessToken(
149         access_token,
150         base::Bind(&OnWildcardCheckCompleted, wildcard_username_));
151   }
152
153   if (service() && service()->IsInitializationComplete() &&
154       client() && !client()->is_registered()) {
155     OnOAuth2PolicyTokenFetched(
156         access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
157   }
158 }
159
160 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
161   return client() && client()->is_registered();
162 }
163
164 void UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck(
165     const std::string& username) {
166   DCHECK(access_token_.empty());
167   wildcard_username_ = username;
168 }
169
170 void UserCloudPolicyManagerChromeOS::Shutdown() {
171   if (client())
172     client()->RemoveObserver(this);
173   if (service())
174     service()->RemoveObserver(this);
175   token_fetcher_.reset();
176   external_data_manager_->Disconnect();
177   CloudPolicyManager::Shutdown();
178 }
179
180 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
181     PolicyDomain domain) const {
182   if (!CloudPolicyManager::IsInitializationComplete(domain))
183     return false;
184   if (domain == POLICY_DOMAIN_CHROME)
185     return !wait_for_policy_fetch_;
186   return true;
187 }
188
189 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
190     CloudPolicyService* cloud_policy_service) {
191   DCHECK_EQ(service(), cloud_policy_service);
192   cloud_policy_service->RemoveObserver(this);
193
194   time_init_completed_ = base::Time::Now();
195   UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization,
196                              time_init_completed_ - time_init_started_);
197
198   // If the CloudPolicyClient isn't registered at this stage then it needs an
199   // OAuth token for the initial registration.
200   //
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.
205   //
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_);
216     }
217   }
218
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
224     // available.
225     StartRefreshSchedulerIfReady();
226   }
227 }
228
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().
233 }
234
235 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
236     CloudPolicyClient* cloud_policy_client) {
237   DCHECK_EQ(client(), cloud_policy_client);
238
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_);
245     }
246
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(
250           base::Bind(
251               &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
252               base::Unretained(this)));
253     } else {
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();
257     }
258   }
259 }
260
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());
267   }
268   CancelWaitForPolicyFetch();
269 }
270
271 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
272   CloudPolicyManager::OnComponentCloudPolicyUpdated();
273   StartRefreshSchedulerIfReady();
274 }
275
276 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
277   scoped_refptr<net::URLRequestContextGetter> signin_context;
278   Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
279   if (signin_profile)
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));
285     return;
286   }
287
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();
294 }
295
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_);
304   }
305
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());
311   } else {
312     // Failed to get a token, stop waiting and use an empty policy.
313     CancelWaitForPolicyFetch();
314
315     UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
316                               error.state(),
317                               GoogleServiceAuthError::NUM_STATES);
318     if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
319       UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
320                                   error.network_error());
321     }
322   }
323
324   token_fetcher_.reset();
325 }
326
327 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
328     bool success) {
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();
335 }
336
337 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
338   if (!wait_for_policy_fetch_)
339     return;
340   LOG(WARNING) << "Timed out while waiting for the initial policy fetch. "
341                << "The first session will start without policy.";
342   CancelWaitForPolicyFetch();
343 }
344
345 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
346   if (!wait_for_policy_fetch_)
347     return;
348
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
353   // can be started.
354   StartRefreshSchedulerIfReady();
355 }
356
357 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
358   if (core()->refresh_scheduler())
359     return;  // Already started.
360
361   if (wait_for_policy_fetch_)
362     return;  // Still waiting for the initial, blocking fetch.
363
364   if (!service() || !local_state_)
365     return;  // Not connected.
366
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.
372     return;
373   }
374
375   core()->StartRefreshScheduler();
376   core()->TrackRefreshDelayPref(local_state_,
377                                 policy_prefs::kUserPolicyRefreshRate);
378 }
379
380 }  // namespace policy