| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/user_policy_signin_service.h" | |
| 6 | |
| 7 #include "base/values.h" | |
| 8 #include "chrome/browser/browser_process.h" | |
| 9 #include "chrome/browser/policy/browser_policy_connector.h" | |
| 10 #include "chrome/browser/policy/cloud_policy_service.h" | |
| 11 #include "chrome/browser/policy/user_cloud_policy_manager.h" | |
| 12 #include "chrome/browser/policy/user_cloud_policy_manager_factory.h" | |
| 13 #include "chrome/browser/prefs/pref_service.h" | |
| 14 #include "chrome/browser/profiles/profile.h" | |
| 15 #include "chrome/browser/signin/signin_manager.h" | |
| 16 #include "chrome/browser/signin/signin_manager_factory.h" | |
| 17 #include "chrome/browser/signin/token_service.h" | |
| 18 #include "chrome/browser/signin/token_service_factory.h" | |
| 19 #include "chrome/common/chrome_notification_types.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "content/public/browser/notification_details.h" | |
| 22 #include "content/public/browser/notification_source.h" | |
| 23 #include "google_apis/gaia/gaia_constants.h" | |
| 24 #include "google_apis/gaia/gaia_urls.h" | |
| 25 #include "google_apis/gaia/oauth2_access_token_fetcher.h" | |
| 26 | |
| 27 namespace { | |
| 28 // Various OAuth service scopes required to do CloudPolicyClient registration. | |
| 29 const char kServiceScopeChromeOSDeviceManagement[] = | |
| 30 "https://www.googleapis.com/auth/chromeosdevicemanagement"; | |
| 31 const char kServiceScopeGetUserInfo[] = | |
| 32 "https://www.googleapis.com/auth/userinfo.email"; | |
| 33 | |
| 34 // The key under which the hosted-domain value is stored in the UserInfo | |
| 35 // response. | |
| 36 const char kGetHostedDomainKey[] = "hd"; | |
| 37 } // namespace | |
| 38 | |
| 39 namespace policy { | |
| 40 | |
| 41 UserPolicySigninService::UserPolicySigninService( | |
| 42 Profile* profile) | |
| 43 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | |
| 44 profile_(profile), | |
| 45 pending_fetch_(false) { | |
| 46 | |
| 47 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin)) | |
| 48 return; | |
| 49 | |
| 50 // Initialize/shutdown the UserCloudPolicyManager when the user signs out. | |
| 51 registrar_.Add(this, | |
| 52 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, | |
| 53 content::Source<Profile>(profile)); | |
| 54 | |
| 55 // Listen for an OAuth token to become available so we can register a client | |
| 56 // if for some reason the client is not already registered (for example, if | |
| 57 // the policy load failed during initial signin). | |
| 58 registrar_.Add(this, | |
| 59 chrome::NOTIFICATION_TOKEN_AVAILABLE, | |
| 60 content::Source<TokenService>( | |
| 61 TokenServiceFactory::GetForProfile(profile))); | |
| 62 | |
| 63 // TokenService should not yet have loaded its tokens since this happens in | |
| 64 // the background after PKS initialization - so this service should always be | |
| 65 // created before the oauth token is available. | |
| 66 DCHECK(!TokenServiceFactory::GetForProfile(profile_)->HasOAuthLoginToken()); | |
| 67 | |
| 68 // Register a listener to be called back once the current profile has finished | |
| 69 // initializing, so we can startup the UserCloudPolicyManager. | |
| 70 registrar_.Add(this, | |
| 71 chrome::NOTIFICATION_PROFILE_ADDED, | |
| 72 content::Source<Profile>(profile)); | |
| 73 } | |
| 74 | |
| 75 UserPolicySigninService::~UserPolicySigninService() {} | |
| 76 | |
| 77 void UserPolicySigninService::FetchPolicyForSignedInUser( | |
| 78 const std::string& oauth2_access_token, | |
| 79 const PolicyFetchCallback& callback) { | |
| 80 if (!ShouldLoadPolicyForSignedInUser()) { | |
| 81 callback.Run(false); | |
| 82 return; | |
| 83 } | |
| 84 | |
| 85 // If the DeviceManagementService is not yet initialized, start it up now. | |
| 86 g_browser_process->browser_policy_connector()-> | |
| 87 ScheduleServiceInitialization(0); | |
| 88 | |
| 89 // The user has just signed in, so the UserCloudPolicyManager should not yet | |
| 90 // be initialized, and the client should not be registered because there | |
| 91 // should be no cached policy. This routine will proactively ask the client | |
| 92 // to register itself without waiting for the CloudPolicyService to finish | |
| 93 // initialization. | |
| 94 DCHECK(!GetManager()->core()->service()); | |
| 95 InitializeUserCloudPolicyManager(); | |
| 96 DCHECK(!GetManager()->IsClientRegistered()); | |
| 97 | |
| 98 DCHECK(!pending_fetch_); | |
| 99 pending_fetch_ = true; | |
| 100 pending_fetch_callback_ = callback; | |
| 101 | |
| 102 // Register the client using this access token. | |
| 103 RegisterCloudPolicyService(oauth2_access_token); | |
| 104 } | |
| 105 | |
| 106 void UserPolicySigninService::StopObserving() { | |
| 107 UserCloudPolicyManager* manager = GetManager(); | |
| 108 if (manager) { | |
| 109 if (manager->core()->service()) | |
| 110 manager->core()->service()->RemoveObserver(this); | |
| 111 if (manager->core()->client()) | |
| 112 manager->core()->client()->RemoveObserver(this); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 void UserPolicySigninService::StartObserving() { | |
| 117 UserCloudPolicyManager* manager = GetManager(); | |
| 118 // Manager should be fully initialized by now. | |
| 119 DCHECK(manager); | |
| 120 DCHECK(manager->core()->service()); | |
| 121 DCHECK(manager->core()->client()); | |
| 122 manager->core()->service()->AddObserver(this); | |
| 123 manager->core()->client()->AddObserver(this); | |
| 124 } | |
| 125 | |
| 126 void UserPolicySigninService::Observe( | |
| 127 int type, | |
| 128 const content::NotificationSource& source, | |
| 129 const content::NotificationDetails& details) { | |
| 130 // If using a TestingProfile with no SigninManager or UserCloudPolicyManager, | |
| 131 // skip initialization. | |
| 132 if (!GetManager() || !SigninManagerFactory::GetForProfile(profile_)) { | |
| 133 DVLOG(1) << "Skipping initialization for tests due to missing components."; | |
| 134 return; | |
| 135 } | |
| 136 | |
| 137 switch (type) { | |
| 138 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: | |
| 139 ShutdownUserCloudPolicyManager(); | |
| 140 break; | |
| 141 case chrome::NOTIFICATION_PROFILE_ADDED: { | |
| 142 // A new profile has been loaded - if it's signed in, then initialize the | |
| 143 // UCPM, otherwise shut down the UCPM (which deletes any cached policy | |
| 144 // data). This must be done here instead of at constructor time because | |
| 145 // the Profile is not fully initialized when this object is constructed | |
| 146 // (DoFinalInit() has not yet been called, so ProfileIOData and | |
| 147 // SSLConfigServiceManager have not been created yet). | |
| 148 // TODO(atwilson): Switch to using a timer instead, to avoid contention | |
| 149 // with other services at startup (http://crbug.com/165468). | |
| 150 SigninManager* signin_manager = | |
| 151 SigninManagerFactory::GetForProfile(profile_); | |
| 152 if (signin_manager->GetAuthenticatedUsername().empty()) | |
| 153 ShutdownUserCloudPolicyManager(); | |
| 154 else | |
| 155 InitializeUserCloudPolicyManager(); | |
| 156 break; | |
| 157 } | |
| 158 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | |
| 159 const TokenService::TokenAvailableDetails& token_details = | |
| 160 *(content::Details<const TokenService::TokenAvailableDetails>( | |
| 161 details).ptr()); | |
| 162 if (token_details.service() == | |
| 163 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { | |
| 164 // TokenService now has a refresh token (implying that the user is | |
| 165 // signed in) so initialize the UserCloudPolicyManager. | |
| 166 InitializeUserCloudPolicyManager(); | |
| 167 } | |
| 168 break; | |
| 169 } | |
| 170 default: | |
| 171 NOTREACHED(); | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 bool UserPolicySigninService::ShouldLoadPolicyForSignedInUser() { | |
| 176 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin)) | |
| 177 return false; // Cloud policy is disabled. | |
| 178 | |
| 179 const std::string& username = SigninManagerFactory::GetForProfile(profile_)-> | |
| 180 GetAuthenticatedUsername(); | |
| 181 | |
| 182 if (username.empty()) | |
| 183 return false; // Not signed in. | |
| 184 | |
| 185 return !BrowserPolicyConnector::IsNonEnterpriseUser(username); | |
| 186 } | |
| 187 | |
| 188 void UserPolicySigninService::InitializeUserCloudPolicyManager() { | |
| 189 if (!ShouldLoadPolicyForSignedInUser()) { | |
| 190 VLOG(1) << "Policy load not enabled for user: " << | |
| 191 SigninManagerFactory::GetForProfile(profile_)-> | |
| 192 GetAuthenticatedUsername(); | |
| 193 return; | |
| 194 } | |
| 195 | |
| 196 UserCloudPolicyManager* manager = GetManager(); | |
| 197 DCHECK(!SigninManagerFactory::GetForProfile(profile_)-> | |
| 198 GetAuthenticatedUsername().empty()); | |
| 199 if (!manager->core()->service()) { | |
| 200 // If there is no cached DMToken then we can detect this below (or when | |
| 201 // the OnInitializationCompleted() callback is invoked). | |
| 202 BrowserPolicyConnector* connector = | |
| 203 g_browser_process->browser_policy_connector(); | |
| 204 manager->Connect(g_browser_process->local_state(), | |
| 205 connector->device_management_service()); | |
| 206 DCHECK(manager->core()->service()); | |
| 207 StartObserving(); | |
| 208 } | |
| 209 | |
| 210 // If the CloudPolicyService is initialized, kick off registration. If the | |
| 211 // TokenService doesn't have an OAuth token yet (e.g. this is during initial | |
| 212 // signin, or when dynamically loading a signed-in policy) this does nothing | |
| 213 // until the OAuth token is loaded. | |
| 214 if (manager->core()->service()->IsInitializationComplete()) | |
| 215 OnInitializationCompleted(manager->core()->service()); | |
| 216 } | |
| 217 | |
| 218 void UserPolicySigninService::ShutdownUserCloudPolicyManager() { | |
| 219 // Stop any in-progress token fetch. | |
| 220 oauth2_access_token_fetcher_.reset(); | |
| 221 user_info_fetcher_.reset(); | |
| 222 oauth_access_token_.clear(); | |
| 223 | |
| 224 StopObserving(); | |
| 225 NotifyPendingFetchCallback(false); | |
| 226 | |
| 227 UserCloudPolicyManager* manager = GetManager(); | |
| 228 if (manager) // Can be null in unit tests. | |
| 229 manager->DisconnectAndRemovePolicy(); | |
| 230 } | |
| 231 | |
| 232 void UserPolicySigninService::OnInitializationCompleted( | |
| 233 CloudPolicyService* service) { | |
| 234 UserCloudPolicyManager* manager = GetManager(); | |
| 235 DCHECK_EQ(service, manager->core()->service()); | |
| 236 DCHECK(service->IsInitializationComplete()); | |
| 237 // The service is now initialized - if the client is not yet registered, then | |
| 238 // it means that there is no cached policy and so we need to initiate a new | |
| 239 // client registration. | |
| 240 DVLOG_IF(1, manager->IsClientRegistered()) | |
| 241 << "Client already registered - not fetching DMToken"; | |
| 242 if (!manager->IsClientRegistered()) { | |
| 243 std::string token = TokenServiceFactory::GetForProfile(profile_)-> | |
| 244 GetOAuth2LoginRefreshToken(); | |
| 245 if (token.empty()) { | |
| 246 // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE | |
| 247 // and will re-attempt registration once the token is available. | |
| 248 DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download"; | |
| 249 return; | |
| 250 } | |
| 251 RegisterCloudPolicyService(token); | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 void UserPolicySigninService::RegisterCloudPolicyService( | |
| 256 std::string login_token) { | |
| 257 DCHECK(!GetManager()->IsClientRegistered()); | |
| 258 DVLOG(1) << "Fetching new DM Token"; | |
| 259 // Do nothing if already starting the registration process. | |
| 260 if (oauth2_access_token_fetcher_.get() || | |
| 261 user_info_fetcher_.get() || | |
| 262 !oauth_access_token_.empty()) { | |
| 263 return; | |
| 264 } | |
| 265 | |
| 266 // Start fetching an OAuth2 access token for the device management and | |
| 267 // userinfo services. | |
| 268 oauth2_access_token_fetcher_.reset( | |
| 269 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); | |
| 270 std::vector<std::string> scopes; | |
| 271 scopes.push_back(kServiceScopeChromeOSDeviceManagement); | |
| 272 scopes.push_back(kServiceScopeGetUserInfo); | |
| 273 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); | |
| 274 oauth2_access_token_fetcher_->Start( | |
| 275 gaia_urls->oauth2_chrome_client_id(), | |
| 276 gaia_urls->oauth2_chrome_client_secret(), | |
| 277 login_token, | |
| 278 scopes); | |
| 279 } | |
| 280 | |
| 281 void UserPolicySigninService::OnGetTokenFailure( | |
| 282 const GoogleServiceAuthError& error) { | |
| 283 DLOG(WARNING) << "Could not fetch access token for " | |
| 284 << kServiceScopeChromeOSDeviceManagement; | |
| 285 oauth2_access_token_fetcher_.reset(); | |
| 286 // If there was a pending fetch request, let them know the fetch failed. | |
| 287 NotifyPendingFetchCallback(false); | |
| 288 } | |
| 289 | |
| 290 void UserPolicySigninService::OnGetTokenSuccess( | |
| 291 const std::string& access_token, | |
| 292 const base::Time& expiration_time) { | |
| 293 oauth_access_token_ = access_token; | |
| 294 DVLOG(1) << "Fetched new scoped OAuth token:" << oauth_access_token_; | |
| 295 oauth2_access_token_fetcher_.reset(); | |
| 296 // Now we've gotten our access token - contact GAIA to see if this is a | |
| 297 // hosted domain. | |
| 298 user_info_fetcher_.reset(new UserInfoFetcher(this, | |
| 299 profile_->GetRequestContext())); | |
| 300 user_info_fetcher_->Start(oauth_access_token_); | |
| 301 } | |
| 302 | |
| 303 void UserPolicySigninService::OnGetUserInfoFailure( | |
| 304 const GoogleServiceAuthError& error) { | |
| 305 user_info_fetcher_.reset(); | |
| 306 NotifyPendingFetchCallback(false); | |
| 307 } | |
| 308 | |
| 309 void UserPolicySigninService::OnGetUserInfoSuccess( | |
| 310 const DictionaryValue* data) { | |
| 311 user_info_fetcher_.reset(); | |
| 312 if (!data->HasKey(kGetHostedDomainKey)) { | |
| 313 VLOG(1) << "User not from a hosted domain - skipping registration"; | |
| 314 NotifyPendingFetchCallback(false); | |
| 315 return; | |
| 316 } | |
| 317 VLOG(1) << "Registering CloudPolicyClient for user from hosted domain"; | |
| 318 // The user is from a hosted domain, so it's OK to register the | |
| 319 // CloudPolicyClient and make requests from DMServer. | |
| 320 GetManager()->RegisterClient(oauth_access_token_); | |
| 321 } | |
| 322 | |
| 323 void UserPolicySigninService::OnRegistrationStateChanged( | |
| 324 CloudPolicyClient* client) { | |
| 325 DCHECK_EQ(GetManager()->core()->client(), client); | |
| 326 if (pending_fetch_) { | |
| 327 UserCloudPolicyManager* manager = GetManager(); | |
| 328 if (manager->IsClientRegistered()) { | |
| 329 // Request a policy fetch. | |
| 330 manager->core()->service()->RefreshPolicy( | |
| 331 base::Bind( | |
| 332 &UserPolicySigninService::NotifyPendingFetchCallback, | |
| 333 weak_factory_.GetWeakPtr())); | |
| 334 } else { | |
| 335 // Shouldn't be possible for the client to get unregistered. | |
| 336 NOTREACHED() << "Client unregistered while waiting for policy fetch"; | |
| 337 } | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 void UserPolicySigninService::NotifyPendingFetchCallback(bool success) { | |
| 342 if (pending_fetch_) { | |
| 343 pending_fetch_ = false; | |
| 344 pending_fetch_callback_.Run(success); | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 void UserPolicySigninService::OnPolicyFetched(CloudPolicyClient* client) { | |
| 349 // Do nothing when policy is fetched - if the policy fetch is successful, | |
| 350 // NotifyPendingFetchCallback will be invoked. | |
| 351 } | |
| 352 | |
| 353 void UserPolicySigninService::OnClientError(CloudPolicyClient* client) { | |
| 354 NotifyPendingFetchCallback(false); | |
| 355 } | |
| 356 | |
| 357 void UserPolicySigninService::Shutdown() { | |
| 358 StopObserving(); | |
| 359 } | |
| 360 | |
| 361 UserCloudPolicyManager* UserPolicySigninService::GetManager() { | |
| 362 return UserCloudPolicyManagerFactory::GetForProfile(profile_); | |
| 363 } | |
| 364 | |
| 365 } // namespace policy | |
| OLD | NEW |