- add sources.
[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/message_loop/message_loop_proxy.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/sequenced_task_runner.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/profiles/profile_helper.h"
18 #include "chrome/browser/policy/cloud/cloud_external_data_manager.h"
19 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
20 #include "chrome/browser/policy/cloud/resource_cache.h"
21 #include "chrome/browser/policy/policy_bundle.h"
22 #include "chrome/browser/policy/policy_domain_descriptor.h"
23 #include "components/policy/core/common/policy_pref_names.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "net/url_request/url_request_context_getter.h"
26
27 namespace em = enterprise_management;
28
29 namespace policy {
30
31 namespace {
32
33 // UMA histogram names.
34 const char kUMADelayInitialization[] =
35     "Enterprise.UserPolicyChromeOS.DelayInitialization";
36 const char kUMAInitialFetchClientError[] =
37     "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError";
38 const char kUMAInitialFetchDelayClientRegister[] =
39     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister";
40 const char kUMAInitialFetchDelayOAuth2Token[] =
41     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token";
42 const char kUMAInitialFetchDelayPolicyFetch[] =
43     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch";
44 const char kUMAInitialFetchDelayTotal[] =
45     "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal";
46 const char kUMAInitialFetchOAuth2Error[] =
47     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error";
48 const char kUMAInitialFetchOAuth2NetworkError[] =
49     "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError";
50
51 }  // namespace
52
53 UserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS(
54     scoped_ptr<CloudPolicyStore> store,
55     scoped_ptr<CloudExternalDataManager> external_data_manager,
56     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
57     scoped_ptr<ResourceCache> resource_cache,
58     bool wait_for_policy_fetch,
59     base::TimeDelta initial_policy_fetch_timeout)
60     : CloudPolicyManager(
61           PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
62           store.get(),
63           task_runner),
64       store_(store.Pass()),
65       external_data_manager_(external_data_manager.Pass()),
66       wait_for_policy_fetch_(wait_for_policy_fetch),
67       policy_fetch_timeout_(false, false) {
68   time_init_started_ = base::Time::Now();
69   if (wait_for_policy_fetch_) {
70     policy_fetch_timeout_.Start(
71         FROM_HERE,
72         initial_policy_fetch_timeout,
73         base::Bind(&UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch,
74                    base::Unretained(this)));
75   }
76   if (resource_cache) {
77     // TODO(joaodasilva): Move the backend from the FILE thread to the blocking
78     // pool.
79     component_policy_service_.reset(new ComponentCloudPolicyService(
80         this,
81         store_.get(),
82         resource_cache.Pass(),
83         content::BrowserThread::GetMessageLoopProxyForThread(
84             content::BrowserThread::FILE),
85         content::BrowserThread::GetMessageLoopProxyForThread(
86             content::BrowserThread::IO)));
87   }
88 }
89
90 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
91
92 void UserCloudPolicyManagerChromeOS::Connect(
93     PrefService* local_state,
94     DeviceManagementService* device_management_service,
95     scoped_refptr<net::URLRequestContextGetter> request_context,
96     UserAffiliation user_affiliation) {
97   DCHECK(device_management_service);
98   DCHECK(local_state);
99   local_state_ = local_state;
100   scoped_ptr<CloudPolicyClient> cloud_policy_client(
101       new CloudPolicyClient(std::string(), std::string(), user_affiliation,
102                             NULL, device_management_service));
103   core()->Connect(cloud_policy_client.Pass());
104   client()->AddObserver(this);
105
106   external_data_manager_->Connect(request_context);
107
108   if (component_policy_service_)
109     component_policy_service_->Connect(client(), request_context);
110
111   // Determine the next step after the CloudPolicyService initializes.
112   if (service()->IsInitializationComplete()) {
113     OnInitializationCompleted(service());
114   } else {
115     service()->AddObserver(this);
116   }
117 }
118
119 void UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable(
120     const std::string& access_token) {
121   access_token_ = access_token;
122   if (service() && service()->IsInitializationComplete() &&
123       client() && !client()->is_registered()) {
124     OnOAuth2PolicyTokenFetched(
125         access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
126   }
127 }
128
129 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
130   return client() && client()->is_registered();
131 }
132
133 void UserCloudPolicyManagerChromeOS::Shutdown() {
134   if (client())
135     client()->RemoveObserver(this);
136   if (service())
137     service()->RemoveObserver(this);
138   token_fetcher_.reset();
139   component_policy_service_.reset();
140   external_data_manager_->Disconnect();
141   CloudPolicyManager::Shutdown();
142 }
143
144 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
145     PolicyDomain domain) const {
146   if (!CloudPolicyManager::IsInitializationComplete(domain))
147     return false;
148   if (domain == POLICY_DOMAIN_CHROME)
149     return !wait_for_policy_fetch_;
150   if (ComponentCloudPolicyService::SupportsDomain(domain) &&
151       component_policy_service_) {
152     return component_policy_service_->is_initialized();
153   }
154   return true;
155 }
156
157 void UserCloudPolicyManagerChromeOS::RegisterPolicyDomain(
158     scoped_refptr<const PolicyDomainDescriptor> descriptor) {
159   if (ComponentCloudPolicyService::SupportsDomain(descriptor->domain()) &&
160       component_policy_service_) {
161     component_policy_service_->RegisterPolicyDomain(descriptor);
162   }
163 }
164
165 scoped_ptr<PolicyBundle> UserCloudPolicyManagerChromeOS::CreatePolicyBundle() {
166   scoped_ptr<PolicyBundle> bundle = CloudPolicyManager::CreatePolicyBundle();
167   if (component_policy_service_)
168     bundle->MergeFrom(component_policy_service_->policy());
169   return bundle.Pass();
170 }
171
172 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
173     CloudPolicyService* cloud_policy_service) {
174   DCHECK_EQ(service(), cloud_policy_service);
175   cloud_policy_service->RemoveObserver(this);
176
177   time_init_completed_ = base::Time::Now();
178   UMA_HISTOGRAM_TIMES(kUMADelayInitialization,
179                       time_init_completed_ - time_init_started_);
180
181   // If the CloudPolicyClient isn't registered at this stage then it needs an
182   // OAuth token for the initial registration.
183   //
184   // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
185   // on the initial policy fetch, so the token must be fetched immediately.
186   // In that case, the signin Profile is used to authenticate a Gaia request to
187   // fetch a refresh token, and then the policy token is fetched.
188   //
189   // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
190   // service will eventually call OnAccessTokenAvailable() once an access token
191   // is available. That call may have already happened while waiting for
192   // initialization of the CloudPolicyService, so in that case check if an
193   // access token is already available.
194   if (!client()->is_registered()) {
195     if (wait_for_policy_fetch_) {
196       FetchPolicyOAuthTokenUsingSigninProfile();
197     } else if (!access_token_.empty()) {
198       OnOAuth2PolicyTokenFetched(
199           access_token_, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
200     }
201   }
202
203   if (!wait_for_policy_fetch_) {
204     // If this isn't blocking on a policy fetch then
205     // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
206     // Start the refresh scheduler now, which will eventually refresh the
207     // cached policy or make the first fetch once the OAuth2 token is
208     // available.
209     StartRefreshSchedulerIfReady();
210   }
211 }
212
213 void UserCloudPolicyManagerChromeOS::OnPolicyFetched(
214     CloudPolicyClient* client) {
215   // No action required. If we're blocked on a policy fetch, we'll learn about
216   // completion of it through OnInitialPolicyFetchComplete().
217 }
218
219 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
220     CloudPolicyClient* cloud_policy_client) {
221   DCHECK_EQ(client(), cloud_policy_client);
222
223   if (wait_for_policy_fetch_) {
224     time_client_registered_ = base::Time::Now();
225     if (!time_token_available_.is_null()) {
226       UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayClientRegister,
227                           time_client_registered_ - time_token_available_);
228     }
229
230     // If we're blocked on the policy fetch, now is a good time to issue it.
231     if (client()->is_registered()) {
232       service()->RefreshPolicy(
233           base::Bind(
234               &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
235               base::Unretained(this)));
236     } else {
237       // If the client has switched to not registered, we bail out as this
238       // indicates the cloud policy setup flow has been aborted.
239       CancelWaitForPolicyFetch();
240     }
241   }
242 }
243
244 void UserCloudPolicyManagerChromeOS::OnClientError(
245     CloudPolicyClient* cloud_policy_client) {
246   DCHECK_EQ(client(), cloud_policy_client);
247   if (wait_for_policy_fetch_) {
248     UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
249                                 cloud_policy_client->status());
250   }
251   CancelWaitForPolicyFetch();
252 }
253
254 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyRefreshNeeded() {
255   core()->RefreshSoon();
256 }
257
258 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
259   CheckAndPublishPolicy();
260   StartRefreshSchedulerIfReady();
261 }
262
263 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
264   scoped_refptr<net::URLRequestContextGetter> signin_context;
265   Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
266   if (signin_profile)
267     signin_context = signin_profile->GetRequestContext();
268   if (!signin_context.get()) {
269     LOG(ERROR) << "No signin Profile for policy oauth token fetch!";
270     OnOAuth2PolicyTokenFetched(
271         std::string(), GoogleServiceAuthError(GoogleServiceAuthError::NONE));
272     return;
273   }
274
275   token_fetcher_.reset(new PolicyOAuth2TokenFetcher(
276       signin_context.get(),
277       g_browser_process->system_request_context(),
278       base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
279                  base::Unretained(this))));
280   token_fetcher_->Start();
281 }
282
283 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
284     const std::string& policy_token,
285     const GoogleServiceAuthError& error) {
286   DCHECK(!client()->is_registered());
287
288   time_token_available_ = base::Time::Now();
289   if (wait_for_policy_fetch_) {
290     UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayOAuth2Token,
291                         time_token_available_ - time_init_completed_);
292   }
293
294   if (error.state() == GoogleServiceAuthError::NONE) {
295     // Start client registration. Either OnRegistrationStateChanged() or
296     // OnClientError() will be called back.
297     client()->Register(em::DeviceRegisterRequest::USER,
298                        policy_token, std::string(), false, std::string());
299   } else {
300     // Failed to get a token, stop waiting and use an empty policy.
301     CancelWaitForPolicyFetch();
302
303     UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
304                               error.state(),
305                               GoogleServiceAuthError::NUM_STATES);
306     if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
307       UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
308                                   error.network_error());
309     }
310   }
311
312   token_fetcher_.reset();
313 }
314
315 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
316     bool success) {
317   const base::Time now = base::Time::Now();
318   UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayPolicyFetch,
319                       now - time_client_registered_);
320   UMA_HISTOGRAM_TIMES(kUMAInitialFetchDelayTotal, now - time_init_started_);
321   CancelWaitForPolicyFetch();
322 }
323
324 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
325   if (!wait_for_policy_fetch_)
326     return;
327
328   wait_for_policy_fetch_ = false;
329   CheckAndPublishPolicy();
330   // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
331   // can be started.
332   StartRefreshSchedulerIfReady();
333 }
334
335 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
336   if (core()->refresh_scheduler())
337     return;  // Already started.
338
339   if (wait_for_policy_fetch_)
340     return;  // Still waiting for the initial, blocking fetch.
341
342   if (!service() || !local_state_)
343     return;  // Not connected.
344
345   if (component_policy_service_ &&
346       !component_policy_service_->is_initialized()) {
347     // If the client doesn't have the list of components to fetch yet then don't
348     // start the scheduler. The |component_policy_service_| will call back into
349     // OnComponentCloudPolicyUpdated() once it's ready.
350     return;
351   }
352
353   core()->StartRefreshScheduler();
354   core()->TrackRefreshDelayPref(local_state_,
355                                 policy_prefs::kUserPolicyRefreshRate);
356 }
357
358 }  // namespace policy