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