1// Copyright 2013 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/policy/cloud/user_policy_signin_service_base.h" 6 7#include "base/bind.h" 8#include "base/message_loop/message_loop.h" 9#include "chrome/browser/chrome_notification_types.h" 10#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h" 11#include "chrome/browser/profiles/profile.h" 12#include "chrome/browser/signin/signin_manager_factory.h" 13#include "chrome/common/chrome_content_client.h" 14#include "components/policy/core/browser/browser_policy_connector.h" 15#include "components/policy/core/common/cloud/device_management_service.h" 16#include "components/policy/core/common/cloud/system_policy_request_context.h" 17#include "components/policy/core/common/cloud/user_cloud_policy_manager.h" 18#include "components/policy/core/common/cloud/user_policy_request_context.h" 19#include "components/signin/core/browser/signin_manager.h" 20#include "content/public/browser/notification_source.h" 21#include "net/url_request/url_request_context_getter.h" 22 23namespace policy { 24 25UserPolicySigninServiceBase::UserPolicySigninServiceBase( 26 Profile* profile, 27 PrefService* local_state, 28 DeviceManagementService* device_management_service, 29 UserCloudPolicyManager* policy_manager, 30 SigninManager* signin_manager, 31 scoped_refptr<net::URLRequestContextGetter> system_request_context) 32 : policy_manager_(policy_manager), 33 signin_manager_(signin_manager), 34 local_state_(local_state), 35 device_management_service_(device_management_service), 36 system_request_context_(system_request_context), 37 weak_factory_(this) { 38 // Register a listener to be called back once the current profile has finished 39 // initializing, so we can startup/shutdown the UserCloudPolicyManager. 40 registrar_.Add(this, 41 chrome::NOTIFICATION_PROFILE_ADDED, 42 content::Source<Profile>(profile)); 43} 44 45UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {} 46 47void UserPolicySigninServiceBase::FetchPolicyForSignedInUser( 48 const std::string& username, 49 const std::string& dm_token, 50 const std::string& client_id, 51 scoped_refptr<net::URLRequestContextGetter> profile_request_context, 52 const PolicyFetchCallback& callback) { 53 scoped_ptr<CloudPolicyClient> client( 54 UserCloudPolicyManager::CreateCloudPolicyClient( 55 device_management_service_, 56 CreateUserRequestContext(profile_request_context)).Pass()); 57 client->SetupRegistration(dm_token, client_id); 58 DCHECK(client->is_registered()); 59 // The user has just signed in, so the UserCloudPolicyManager should not yet 60 // be initialized. This routine will initialize the UserCloudPolicyManager 61 // with the passed client and will proactively ask the client to fetch 62 // policy without waiting for the CloudPolicyService to finish initialization. 63 UserCloudPolicyManager* manager = policy_manager(); 64 DCHECK(manager); 65 DCHECK(!manager->core()->client()); 66 InitializeUserCloudPolicyManager(username, client.Pass()); 67 DCHECK(manager->IsClientRegistered()); 68 69 // Now initiate a policy fetch. 70 manager->core()->service()->RefreshPolicy(callback); 71} 72 73void UserPolicySigninServiceBase::GoogleSignedOut(const std::string& account_id, 74 const std::string& username) { 75 ShutdownUserCloudPolicyManager(); 76} 77 78void UserPolicySigninServiceBase::Observe( 79 int type, 80 const content::NotificationSource& source, 81 const content::NotificationDetails& details) { 82 switch (type) { 83 case chrome::NOTIFICATION_PROFILE_ADDED: 84 // A new profile has been loaded - if it's signed in, then initialize the 85 // UCPM, otherwise shut down the UCPM (which deletes any cached policy 86 // data). This must be done here instead of at constructor time because 87 // the Profile is not fully initialized when this object is constructed 88 // (DoFinalInit() has not yet been called, so ProfileIOData and 89 // SSLConfigServiceManager have not been created yet). 90 // TODO(atwilson): Switch to using a timer instead, to avoid contention 91 // with other services at startup (http://crbug.com/165468). 92 InitializeOnProfileReady(content::Source<Profile>(source).ptr()); 93 break; 94 default: 95 NOTREACHED(); 96 } 97} 98 99void UserPolicySigninServiceBase::OnInitializationCompleted( 100 CloudPolicyService* service) { 101 // This is meant to be overridden by subclasses. Starting and stopping to 102 // observe the CloudPolicyService from this base class avoids the need for 103 // more virtuals. 104} 105 106void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {} 107 108void UserPolicySigninServiceBase::OnRegistrationStateChanged( 109 CloudPolicyClient* client) {} 110 111void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) { 112 if (client->is_registered()) { 113 // If the client is already registered, it means this error must have 114 // come from a policy fetch. 115 if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) { 116 // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our 117 // trigger to revert to "unmanaged" mode (we will check for management 118 // being re-enabled on the next restart and/or login). 119 DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy"; 120 121 // Can't shutdown now because we're in the middle of a callback from 122 // the CloudPolicyClient, so queue up a task to do the shutdown. 123 base::MessageLoop::current()->PostTask( 124 FROM_HERE, 125 base::Bind( 126 &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager, 127 weak_factory_.GetWeakPtr())); 128 } else { 129 DVLOG(1) << "Error fetching policy: " << client->status(); 130 } 131 } 132} 133 134void UserPolicySigninServiceBase::Shutdown() { 135 if (signin_manager()) 136 signin_manager()->RemoveObserver(this); 137 PrepareForUserCloudPolicyManagerShutdown(); 138} 139 140void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() { 141 UserCloudPolicyManager* manager = policy_manager(); 142 if (manager && manager->core()->client()) 143 manager->core()->client()->RemoveObserver(this); 144 if (manager && manager->core()->service()) 145 manager->core()->service()->RemoveObserver(this); 146} 147 148scoped_ptr<CloudPolicyClient> 149UserPolicySigninServiceBase::CreateClientForRegistrationOnly( 150 const std::string& username) { 151 DCHECK(!username.empty()); 152 // We should not be called with a client already initialized. 153#if !defined(OS_IOS) 154 // On iOS we check if an account has policy while the profile is signed in 155 // to another account. 156 DCHECK(!policy_manager() || !policy_manager()->core()->client()); 157#endif 158 159 // If the user should not get policy, just bail out. 160 if (!policy_manager() || !ShouldLoadPolicyForUser(username)) { 161 DVLOG(1) << "Signed in user is not in the whitelist"; 162 return scoped_ptr<CloudPolicyClient>(); 163 } 164 165 // If the DeviceManagementService is not yet initialized, start it up now. 166 device_management_service_->ScheduleInitialization(0); 167 168 // Create a new CloudPolicyClient for fetching the DMToken. 169 return UserCloudPolicyManager::CreateCloudPolicyClient( 170 device_management_service_, CreateSystemRequestContext()); 171} 172 173bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser( 174 const std::string& username) { 175 if (username.empty()) 176 return false; // Not signed in. 177 178 return !BrowserPolicyConnector::IsNonEnterpriseUser(username); 179} 180 181void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile* profile) { 182 // If using a TestingProfile with no SigninManager or UserCloudPolicyManager, 183 // skip initialization. 184 if (!policy_manager() || !signin_manager()) { 185 DVLOG(1) << "Skipping initialization for tests due to missing components."; 186 return; 187 } 188 189 // Shutdown the UserCloudPolicyManager when the user signs out. We start 190 // observing the SigninManager here because we don't want to get signout 191 // notifications until after the profile has started initializing 192 // (http://crbug.com/316229). 193 signin_manager()->AddObserver(this); 194 195 std::string username = signin_manager()->GetAuthenticatedUsername(); 196 if (username.empty()) 197 ShutdownUserCloudPolicyManager(); 198 else 199 InitializeForSignedInUser(username, profile->GetRequestContext()); 200} 201 202void UserPolicySigninServiceBase::InitializeForSignedInUser( 203 const std::string& username, 204 scoped_refptr<net::URLRequestContextGetter> profile_request_context) { 205 DCHECK(!username.empty()); 206 if (!ShouldLoadPolicyForUser(username)) { 207 DVLOG(1) << "Policy load not enabled for user: " << username; 208 return; 209 } 210 211 UserCloudPolicyManager* manager = policy_manager(); 212 // Initialize the UCPM if it is not already initialized. 213 if (!manager->core()->service()) { 214 // If there is no cached DMToken then we can detect this when the 215 // OnInitializationCompleted() callback is invoked and this will 216 // initiate a policy fetch. 217 InitializeUserCloudPolicyManager( 218 username, 219 UserCloudPolicyManager::CreateCloudPolicyClient( 220 device_management_service_, 221 CreateUserRequestContext(profile_request_context)).Pass()); 222 } else { 223 manager->SetSigninUsername(username); 224 } 225 226 // If the CloudPolicyService is initialized, kick off registration. 227 // Otherwise OnInitializationCompleted is invoked as soon as the service 228 // finishes its initialization. 229 if (manager->core()->service()->IsInitializationComplete()) 230 OnInitializationCompleted(manager->core()->service()); 231} 232 233void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager( 234 const std::string& username, 235 scoped_ptr<CloudPolicyClient> client) { 236 DCHECK(client); 237 UserCloudPolicyManager* manager = policy_manager(); 238 manager->SetSigninUsername(username); 239 DCHECK(!manager->core()->client()); 240 scoped_refptr<net::URLRequestContextGetter> context = 241 client->GetRequestContext(); 242 manager->Connect(local_state_, context, client.Pass()); 243 DCHECK(manager->core()->service()); 244 245 // Observe the client to detect errors fetching policy. 246 manager->core()->client()->AddObserver(this); 247 // Observe the service to determine when it's initialized. 248 manager->core()->service()->AddObserver(this); 249} 250 251void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() { 252 PrepareForUserCloudPolicyManagerShutdown(); 253 UserCloudPolicyManager* manager = policy_manager(); 254 if (manager) 255 manager->DisconnectAndRemovePolicy(); 256} 257 258scoped_refptr<net::URLRequestContextGetter> 259UserPolicySigninServiceBase::CreateSystemRequestContext() { 260 return new SystemPolicyRequestContext( 261 system_request_context(), GetUserAgent()); 262} 263 264scoped_refptr<net::URLRequestContextGetter> 265UserPolicySigninServiceBase::CreateUserRequestContext( 266 scoped_refptr<net::URLRequestContextGetter> profile_request_context) { 267 return new UserPolicyRequestContext( 268 profile_request_context, system_request_context(), GetUserAgent()); 269} 270 271} // namespace policy 272