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.
5 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.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"
27 namespace em = enterprise_management;
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";
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)
61 PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
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(
72 initial_policy_fetch_timeout,
73 base::Bind(&UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch,
74 base::Unretained(this)));
77 // TODO(joaodasilva): Move the backend from the FILE thread to the blocking
79 component_policy_service_.reset(new ComponentCloudPolicyService(
82 resource_cache.Pass(),
83 content::BrowserThread::GetMessageLoopProxyForThread(
84 content::BrowserThread::FILE),
85 content::BrowserThread::GetMessageLoopProxyForThread(
86 content::BrowserThread::IO)));
90 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
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);
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);
106 external_data_manager_->Connect(request_context);
108 if (component_policy_service_)
109 component_policy_service_->Connect(client(), request_context);
111 // Determine the next step after the CloudPolicyService initializes.
112 if (service()->IsInitializationComplete()) {
113 OnInitializationCompleted(service());
115 service()->AddObserver(this);
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));
129 bool UserCloudPolicyManagerChromeOS::IsClientRegistered() const {
130 return client() && client()->is_registered();
133 void UserCloudPolicyManagerChromeOS::Shutdown() {
135 client()->RemoveObserver(this);
137 service()->RemoveObserver(this);
138 token_fetcher_.reset();
139 component_policy_service_.reset();
140 external_data_manager_->Disconnect();
141 CloudPolicyManager::Shutdown();
144 bool UserCloudPolicyManagerChromeOS::IsInitializationComplete(
145 PolicyDomain domain) const {
146 if (!CloudPolicyManager::IsInitializationComplete(domain))
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();
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);
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();
172 void UserCloudPolicyManagerChromeOS::OnInitializationCompleted(
173 CloudPolicyService* cloud_policy_service) {
174 DCHECK_EQ(service(), cloud_policy_service);
175 cloud_policy_service->RemoveObserver(this);
177 time_init_completed_ = base::Time::Now();
178 UMA_HISTOGRAM_TIMES(kUMADelayInitialization,
179 time_init_completed_ - time_init_started_);
181 // If the CloudPolicyClient isn't registered at this stage then it needs an
182 // OAuth token for the initial registration.
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.
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));
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
209 StartRefreshSchedulerIfReady();
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().
219 void UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged(
220 CloudPolicyClient* cloud_policy_client) {
221 DCHECK_EQ(client(), cloud_policy_client);
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_);
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(
234 &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete,
235 base::Unretained(this)));
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();
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());
251 CancelWaitForPolicyFetch();
254 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyRefreshNeeded() {
255 core()->RefreshSoon();
258 void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() {
259 CheckAndPublishPolicy();
260 StartRefreshSchedulerIfReady();
263 void UserCloudPolicyManagerChromeOS::FetchPolicyOAuthTokenUsingSigninProfile() {
264 scoped_refptr<net::URLRequestContextGetter> signin_context;
265 Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
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));
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();
283 void UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched(
284 const std::string& policy_token,
285 const GoogleServiceAuthError& error) {
286 DCHECK(!client()->is_registered());
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_);
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());
300 // Failed to get a token, stop waiting and use an empty policy.
301 CancelWaitForPolicyFetch();
303 UMA_HISTOGRAM_ENUMERATION(kUMAInitialFetchOAuth2Error,
305 GoogleServiceAuthError::NUM_STATES);
306 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
307 UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchOAuth2NetworkError,
308 error.network_error());
312 token_fetcher_.reset();
315 void UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete(
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();
324 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch() {
325 if (!wait_for_policy_fetch_)
328 wait_for_policy_fetch_ = false;
329 CheckAndPublishPolicy();
330 // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
332 StartRefreshSchedulerIfReady();
335 void UserCloudPolicyManagerChromeOS::StartRefreshSchedulerIfReady() {
336 if (core()->refresh_scheduler())
337 return; // Already started.
339 if (wait_for_policy_fetch_)
340 return; // Still waiting for the initial, blocking fetch.
342 if (!service() || !local_state_)
343 return; // Not connected.
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.
353 core()->StartRefreshScheduler();
354 core()->TrackRefreshDelayPref(local_state_,
355 policy_prefs::kUserPolicyRefreshRate);
358 } // namespace policy