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