user_cloud_policy_manager_chromeos.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König// Use of this source code is governed by a BSD-style license that can be 3303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König// found in the LICENSE file. 4303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 5303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" 6303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 7303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/bind.h" 8303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/bind_helpers.h" 9303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/logging.h" 10303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/metrics/histogram.h" 11303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/metrics/sparse_histogram.h" 12303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/sequenced_task_runner.h" 13303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "base/values.h" 14303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/browser_process.h" 15303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" 16303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h" 17303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/chromeos/policy/wildcard_login_checker.h" 18303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/chromeos/profiles/profile_helper.h" 19303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/browser/lifetime/application_lifetime.h" 20303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "chrome/common/chrome_content_client.h" 21303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/cloud/cloud_external_data_manager.h" 22303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h" 23303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/cloud/device_management_service.h" 24303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/cloud/system_policy_request_context.h" 25303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/policy_map.h" 26303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/policy_pref_names.h" 27303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "components/policy/core/common/policy_types.h" 28303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "net/url_request/url_request_context_getter.h" 29303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "policy/policy_constants.h" 30303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König#include "url/gurl.h" 31303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 32303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Könignamespace em = enterprise_management; 33303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 34303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Könignamespace policy { 35303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 36303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Könignamespace { 37303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 38303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König// UMA histogram names. 39303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMADelayInitialization[] = 40303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.DelayInitialization"; 41303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchClientError[] = 42303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.ClientError"; 43303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchDelayClientRegister[] = 44303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.DelayClientRegister"; 45303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchDelayOAuth2Token[] = 46303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.DelayOAuth2Token"; 47303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchDelayPolicyFetch[] = 48303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.DelayPolicyFetch"; 49303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchDelayTotal[] = 50303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.DelayTotal"; 51303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchOAuth2Error[] = 52303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error"; 53303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königconst char kUMAInitialFetchOAuth2NetworkError[] = 54303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König "Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2NetworkError"; 55303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 56303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid OnWildcardCheckCompleted(const std::string& username, 57303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König WildcardLoginChecker::Result result) { 58303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (result == WildcardLoginChecker::RESULT_BLOCKED) { 59303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König LOG(ERROR) << "Online wildcard login check failed, terminating session."; 60303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 61303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // TODO(mnissler): This only removes the user pod from the login screen, but 62303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // the cryptohome remains. This is because deleting the cryptohome for a 63303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // logged-in session is not possible. Fix this either by delaying the 64303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // cryptohome deletion operation or by getting rid of the in-session 65303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // wildcard check. 66303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König chromeos::UserManager::Get()->RemoveUserFromList(username); 67303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König chrome::AttemptUserExit(); 68303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 69303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 70303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 71303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} // namespace 72303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 73303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian KönigUserCloudPolicyManagerChromeOS::UserCloudPolicyManagerChromeOS( 74303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König scoped_ptr<CloudPolicyStore> store, 75303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König scoped_ptr<CloudExternalDataManager> external_data_manager, 76303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const base::FilePath& component_policy_cache_path, 77303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König bool wait_for_policy_fetch, 78303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::TimeDelta initial_policy_fetch_timeout, 79303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const scoped_refptr<base::SequencedTaskRunner>& task_runner, 80303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const scoped_refptr<base::SequencedTaskRunner>& file_task_runner, 81303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) 82303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König : CloudPolicyManager( 83303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()), 84303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König store.get(), 85303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König task_runner, 86303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König file_task_runner, 87303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König io_task_runner), 88303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König store_(store.Pass()), 89303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König external_data_manager_(external_data_manager.Pass()), 90303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König component_policy_cache_path_(component_policy_cache_path), 91303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König wait_for_policy_fetch_(wait_for_policy_fetch), 92303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König policy_fetch_timeout_(false, false) { 93303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König time_init_started_ = base::Time::Now(); 94303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (wait_for_policy_fetch_) { 95303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König policy_fetch_timeout_.Start( 96303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König FROM_HERE, 97303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König initial_policy_fetch_timeout, 98303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::Bind(&UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout, 99303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::Unretained(this))); 100303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 101303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 102303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 103303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian KönigUserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {} 104303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 105303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::Connect( 106303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König PrefService* local_state, 107303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DeviceManagementService* device_management_service, 108303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König scoped_refptr<net::URLRequestContextGetter> system_request_context, 109303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König UserAffiliation user_affiliation) { 110303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK(device_management_service); 111303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK(local_state); 112303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König local_state_ = local_state; 113303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König scoped_refptr<net::URLRequestContextGetter> request_context; 114303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (system_request_context) { 115303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // |system_request_context| can be null for tests. 116303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // Use the system request context here instead of a context derived 117303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // from the Profile because Connect() is called before the profile is 118303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // fully initialized (required so we can perform the initial policy load). 119303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // TODO(atwilson): Change this to use a UserPolicyRequestContext once 120303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // Connect() is called after profile initialization. http://crbug.com/323591 121303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König request_context = new SystemPolicyRequestContext( 122303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König system_request_context, GetUserAgent()); 123303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 124303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König scoped_ptr<CloudPolicyClient> cloud_policy_client( 125303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König new CloudPolicyClient(std::string(), std::string(), 126303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König kPolicyVerificationKeyHash, user_affiliation, 127303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König NULL, device_management_service, 128303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König request_context)); 129303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König core()->Connect(cloud_policy_client.Pass()); 130303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König client()->AddObserver(this); 131303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 132303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König external_data_manager_->Connect(request_context); 133303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 134303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CreateComponentCloudPolicyService(component_policy_cache_path_, 135303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König request_context); 136303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 137303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // Determine the next step after the CloudPolicyService initializes. 138303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (service()->IsInitializationComplete()) { 139303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König OnInitializationCompleted(service()); 140303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } else { 141303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König service()->AddObserver(this); 142303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 143303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 144303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 145303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::OnAccessTokenAvailable( 146303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const std::string& access_token) { 147303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König access_token_ = access_token; 148303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 149303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (!wildcard_username_.empty()) { 150303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König wildcard_login_checker_.reset(new WildcardLoginChecker()); 151303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König wildcard_login_checker_->StartWithAccessToken( 152303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König access_token, 153303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::Bind(&OnWildcardCheckCompleted, wildcard_username_)); 154303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 155303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 156303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (service() && service()->IsInitializationComplete() && 157303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König client() && !client()->is_registered()) { 158303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König OnOAuth2PolicyTokenFetched( 159303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König access_token, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 160303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 161303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 162303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 163303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königbool UserCloudPolicyManagerChromeOS::IsClientRegistered() const { 164303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König return client() && client()->is_registered(); 165303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 166303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 167303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::EnableWildcardLoginCheck( 168303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König const std::string& username) { 169303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK(access_token_.empty()); 170303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König wildcard_username_ = username; 171303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 172303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 173303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::Shutdown() { 174303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (client()) 175303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König client()->RemoveObserver(this); 176303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (service()) 177303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König service()->RemoveObserver(this); 178303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König token_fetcher_.reset(); 179303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König external_data_manager_->Disconnect(); 180303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CloudPolicyManager::Shutdown(); 181303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 182303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 183303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königbool UserCloudPolicyManagerChromeOS::IsInitializationComplete( 184303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König PolicyDomain domain) const { 185303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (!CloudPolicyManager::IsInitializationComplete(domain)) 186303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König return false; 187303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (domain == POLICY_DOMAIN_CHROME) 188303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König return !wait_for_policy_fetch_; 189303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König return true; 190303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 191303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 192303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::OnInitializationCompleted( 193303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CloudPolicyService* cloud_policy_service) { 194303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK_EQ(service(), cloud_policy_service); 195303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König cloud_policy_service->RemoveObserver(this); 196303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 197303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König time_init_completed_ = base::Time::Now(); 198303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König UMA_HISTOGRAM_MEDIUM_TIMES(kUMADelayInitialization, 199303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König time_init_completed_ - time_init_started_); 200303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 201303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If the CloudPolicyClient isn't registered at this stage then it needs an 202303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // OAuth token for the initial registration. 203303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // 204303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If |wait_for_policy_fetch_| is true then Profile initialization is blocking 205303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // on the initial policy fetch, so the token must be fetched immediately. 206303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // In that case, the signin Profile is used to authenticate a Gaia request to 207303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // fetch a refresh token, and then the policy token is fetched. 208303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // 209303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder 210303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // service will eventually call OnAccessTokenAvailable() once an access token 211303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // is available. That call may have already happened while waiting for 212303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // initialization of the CloudPolicyService, so in that case check if an 213303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // access token is already available. 214303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (!client()->is_registered()) { 215303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (wait_for_policy_fetch_) { 216303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König FetchPolicyOAuthTokenUsingSigninProfile(); 217303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } else if (!access_token_.empty()) { 218303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König OnAccessTokenAvailable(access_token_); 219303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 220303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 221303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 222303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (!wait_for_policy_fetch_) { 223303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If this isn't blocking on a policy fetch then 224303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // CloudPolicyManager::OnStoreLoaded() already published the cached policy. 225303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // Start the refresh scheduler now, which will eventually refresh the 226303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // cached policy or make the first fetch once the OAuth2 token is 227303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // available. 228303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König StartRefreshSchedulerIfReady(); 229303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 230303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 231303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 232303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::OnPolicyFetched( 233303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CloudPolicyClient* client) { 234303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // No action required. If we're blocked on a policy fetch, we'll learn about 235303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // completion of it through OnInitialPolicyFetchComplete(). 236303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 237303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 238303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::OnRegistrationStateChanged( 239303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CloudPolicyClient* cloud_policy_client) { 240303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK_EQ(client(), cloud_policy_client); 241303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 242303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (wait_for_policy_fetch_) { 243303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König time_client_registered_ = base::Time::Now(); 244303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (!time_token_available_.is_null()) { 245303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König UMA_HISTOGRAM_MEDIUM_TIMES( 246303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König kUMAInitialFetchDelayClientRegister, 247303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König time_client_registered_ - time_token_available_); 248303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 249303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 250303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If we're blocked on the policy fetch, now is a good time to issue it. 251303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (client()->is_registered()) { 252303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König service()->RefreshPolicy( 253303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::Bind( 254303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König &UserCloudPolicyManagerChromeOS::OnInitialPolicyFetchComplete, 255303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König base::Unretained(this))); 256303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } else { 257303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // If the client has switched to not registered, we bail out as this 258303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König // indicates the cloud policy setup flow has been aborted. 259303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CancelWaitForPolicyFetch(); 260303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 261303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 262303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König} 263303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König 264303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian Königvoid UserCloudPolicyManagerChromeOS::OnClientError( 265303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CloudPolicyClient* cloud_policy_client) { 266303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König DCHECK_EQ(client(), cloud_policy_client); 267303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König if (wait_for_policy_fetch_) { 268303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError, 269303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König cloud_policy_client->status()); 270303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König } 271303f4b7dcddee384d6f1dc1027cbdee840a38d7dChristian König CancelWaitForPolicyFetch(); 272} 273 274void UserCloudPolicyManagerChromeOS::OnComponentCloudPolicyUpdated() { 275 CloudPolicyManager::OnComponentCloudPolicyUpdated(); 276 StartRefreshSchedulerIfReady(); 277} 278 279void 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 293void 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 313void 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 344void 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 354void 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 362void 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 374void 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 398