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