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& account_id, 74 const std::string& username) { 75 ShutdownUserCloudPolicyManager(); 76 } 77 78 void 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 99 void 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 106 void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {} 107 108 void UserPolicySigninServiceBase::OnRegistrationStateChanged( 109 CloudPolicyClient* client) {} 110 111 void 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 134 void UserPolicySigninServiceBase::Shutdown() { 135 if (signin_manager()) 136 signin_manager()->RemoveObserver(this); 137 PrepareForUserCloudPolicyManagerShutdown(); 138 } 139 140 void 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 148 scoped_ptr<CloudPolicyClient> 149 UserPolicySigninServiceBase::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 173 bool 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 181 void 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 202 void 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 233 void 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 251 void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() { 252 PrepareForUserCloudPolicyManagerShutdown(); 253 UserCloudPolicyManager* manager = policy_manager(); 254 if (manager) 255 manager->DisconnectAndRemovePolicy(); 256 } 257 258 scoped_refptr<net::URLRequestContextGetter> 259 UserPolicySigninServiceBase::CreateSystemRequestContext() { 260 return new SystemPolicyRequestContext( 261 system_request_context(), GetUserAgent()); 262 } 263 264 scoped_refptr<net::URLRequestContextGetter> 265 UserPolicySigninServiceBase::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