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