Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/policy/user_policy_signin_service.h" | 5 #include "chrome/browser/policy/user_policy_signin_service.h" |
| 6 | 6 |
| 7 #include "chrome/browser/browser_process.h" | 7 #include "chrome/browser/browser_process.h" |
| 8 #include "chrome/browser/policy/browser_policy_connector.h" | 8 #include "chrome/browser/policy/browser_policy_connector.h" |
| 9 #include "chrome/browser/policy/cloud_policy_service.h" | 9 #include "chrome/browser/policy/cloud_policy_service.h" |
| 10 #include "chrome/browser/policy/user_cloud_policy_manager.h" | 10 #include "chrome/browser/policy/user_cloud_policy_manager.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 | 30 |
| 31 // How long to delay before starting device policy network requests. Set to a | 31 // How long to delay before starting device policy network requests. Set to a |
| 32 // few seconds to alleviate contention during initial startup. | 32 // few seconds to alleviate contention during initial startup. |
| 33 const int64 kPolicyServiceInitializationDelayMilliseconds = 2000; | 33 const int64 kPolicyServiceInitializationDelayMilliseconds = 2000; |
| 34 } // namespace | 34 } // namespace |
| 35 | 35 |
| 36 namespace policy { | 36 namespace policy { |
| 37 | 37 |
| 38 UserPolicySigninService::UserPolicySigninService( | 38 UserPolicySigninService::UserPolicySigninService( |
| 39 Profile* profile) | 39 Profile* profile) |
| 40 : profile_(profile) { | 40 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 41 profile_(profile), | |
| 42 pending_fetch_(false) { | |
| 41 | 43 |
| 42 // Initialize/shutdown the UserCloudPolicyManager when the user signs in or | 44 if (!profile_->GetPrefs()->GetBoolean(prefs::kLoadCloudPolicyOnSignin)) |
| 43 // out. | 45 return; |
| 46 | |
| 47 // Initialize/shutdown the UserCloudPolicyManager when the user signs out. | |
| 44 registrar_.Add(this, | 48 registrar_.Add(this, |
| 45 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, | 49 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, |
| 46 content::Source<Profile>(profile)); | 50 content::Source<Profile>(profile)); |
| 51 | |
| 52 // Listen for an OAuth token to become available so we can register a client | |
| 53 // if for some reason the client is not already registered (for example, if | |
| 54 // the policy load failed during initial signin). | |
| 47 registrar_.Add(this, | 55 registrar_.Add(this, |
| 48 chrome::NOTIFICATION_TOKEN_AVAILABLE, | 56 chrome::NOTIFICATION_TOKEN_AVAILABLE, |
| 49 content::Source<TokenService>( | 57 content::Source<TokenService>( |
| 50 TokenServiceFactory::GetForProfile(profile))); | 58 TokenServiceFactory::GetForProfile(profile))); |
| 51 | 59 |
| 52 // The Profile is not yet fully initialized when this object is created, | 60 // TokenService should not yet have loaded its tokens since this happens in |
| 53 // so wait until the initialization has finished to initialize the | 61 // the background after PKS initialization - so this service should always be |
| 54 // UserCloudPolicyManager as otherwise various crashes ensue from services | 62 // created before the oauth token is available. |
| 55 // trying to access the partially-initialized Profile. | 63 DCHECK(!TokenServiceFactory::GetForProfile(profile_)->HasOAuthLoginToken()); |
| 56 // TODO(atwilson): Remove this once ProfileImpl::DoFinalInit() goes away and | 64 |
| 57 // the profile is fully initialized before ProfileKeyedServices are created. | 65 // Register a listener to be called back once the current profile has finished |
| 66 // initializing, so we can startup the UserCloudPolicyManager. | |
| 58 registrar_.Add(this, | 67 registrar_.Add(this, |
| 59 chrome::NOTIFICATION_PROFILE_ADDED, | 68 chrome::NOTIFICATION_PROFILE_ADDED, |
| 60 content::Source<Profile>(profile)); | 69 content::Source<Profile>(profile)); |
| 61 } | 70 } |
| 62 | 71 |
| 63 UserPolicySigninService::~UserPolicySigninService() {} | 72 UserPolicySigninService::~UserPolicySigninService() {} |
| 64 | 73 |
| 74 void UserPolicySigninService::FetchPolicyForSignedInUser( | |
| 75 const std::string& oauth2_access_token, | |
| 76 const PolicyFetchCallback& callback) { | |
| 77 if (!profile_->GetPrefs()->GetBoolean(prefs::kLoadCloudPolicyOnSignin)) { | |
| 78 callback.Run(false); | |
| 79 return; | |
| 80 } | |
| 81 | |
| 82 // The user has just signed in, so the UserCloudPolicyManager should not yet | |
| 83 // be initialized, and the client should not be registered because there | |
| 84 // should be no cached policy. This routine will proactively ask the client | |
| 85 // to register itself without waiting for the CloudPolicyService to finish | |
| 86 // initialization. | |
| 87 DCHECK(!GetManager()->core()->service()); | |
| 88 InitializeUserCloudPolicyManager(); | |
| 89 DCHECK(!GetManager()->IsClientRegistered()); | |
| 90 | |
| 91 DCHECK(!pending_fetch_); | |
| 92 pending_fetch_ = true; | |
| 93 pending_fetch_callback_ = callback; | |
| 94 | |
| 95 // Register the client using this access token. | |
| 96 RegisterCloudPolicyService(oauth2_access_token); | |
| 97 } | |
| 98 | |
| 65 void UserPolicySigninService::StopObserving() { | 99 void UserPolicySigninService::StopObserving() { |
| 66 UserCloudPolicyManager* manager = GetManager(); | 100 UserCloudPolicyManager* manager = GetManager(); |
| 67 if (manager && manager->core()->service()) | 101 if (manager) { |
| 68 manager->core()->service()->RemoveObserver(this); | 102 if (manager->core()->service()) |
| 103 manager->core()->service()->RemoveObserver(this); | |
| 104 if (manager->core()->client()) | |
| 105 manager->core()->client()->RemoveObserver(this); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 void UserPolicySigninService::StartObserving() { | |
| 110 UserCloudPolicyManager* manager = GetManager(); | |
| 111 // Manager should be fully initialized by now. | |
| 112 DCHECK(manager); | |
| 113 DCHECK(manager->core()->service()); | |
| 114 DCHECK(manager->core()->client()); | |
| 115 manager->core()->service()->AddObserver(this); | |
| 116 manager->core()->client()->AddObserver(this); | |
| 69 } | 117 } |
| 70 | 118 |
| 71 void UserPolicySigninService::Observe( | 119 void UserPolicySigninService::Observe( |
| 72 int type, | 120 int type, |
| 73 const content::NotificationSource& source, | 121 const content::NotificationSource& source, |
| 74 const content::NotificationDetails& details) { | 122 const content::NotificationDetails& details) { |
| 75 switch (type) { | 123 switch (type) { |
| 76 case chrome::NOTIFICATION_PROFILE_ADDED: | 124 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: |
| 77 // Profile is initialized so it's safe to initialize the | 125 ShutdownUserCloudPolicyManager(); |
| 78 // UserCloudPolicyManager now. | |
| 79 ConfigureUserCloudPolicyManager(); | |
| 80 break; | 126 break; |
| 81 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: | 127 case chrome::NOTIFICATION_PROFILE_ADDED: { |
| 82 ConfigureUserCloudPolicyManager(); | 128 // A new profile has been loaded - if it's signed in, then initialize the |
| 129 // UCPM, otherwise shut down the UCPM (which deletes any cached policy | |
| 130 // data). This must be done here instead of at constructor time because | |
| 131 // the Profile is not fully initialized when this object is constructed | |
| 132 // (accessing things like URLFetchers will crash). | |
|
Mattias Nissler (ping if slow)
2012/12/10 09:01:09
nit: Can you elaborate why it crashes and what the
Andrew T Wilson (Slow)
2012/12/10 10:12:40
Done.
| |
| 133 SigninManager* signin_manager = | |
| 134 SigninManagerFactory::GetForProfile(profile_); | |
| 135 if (signin_manager->GetAuthenticatedUsername().empty()) | |
| 136 ShutdownUserCloudPolicyManager(); | |
| 137 else | |
| 138 InitializeUserCloudPolicyManager(); | |
| 83 break; | 139 break; |
| 140 } | |
| 84 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 141 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
| 85 const TokenService::TokenAvailableDetails& token_details = | 142 const TokenService::TokenAvailableDetails& token_details = |
| 86 *(content::Details<const TokenService::TokenAvailableDetails>( | 143 *(content::Details<const TokenService::TokenAvailableDetails>( |
| 87 details).ptr()); | 144 details).ptr()); |
| 88 if (token_details.service() == | 145 if (token_details.service() == |
| 89 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { | 146 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { |
| 90 // TokenService now has a refresh token, so initialize the | 147 // TokenService now has a refresh token (implying that the user is |
| 91 // UserCloudPolicyManager. | 148 // signed in) so initialize the UserCloudPolicyManager. |
| 92 ConfigureUserCloudPolicyManager(); | 149 InitializeUserCloudPolicyManager(); |
| 93 } | 150 } |
| 94 break; | 151 break; |
| 95 } | 152 } |
| 96 default: | 153 default: |
| 97 NOTREACHED(); | 154 NOTREACHED(); |
| 98 } | 155 } |
| 99 } | 156 } |
| 100 | 157 |
| 158 void UserPolicySigninService::InitializeUserCloudPolicyManager() { | |
| 159 UserCloudPolicyManager* manager = GetManager(); | |
| 160 DCHECK(!SigninManagerFactory::GetForProfile(profile_)-> | |
| 161 GetAuthenticatedUsername().empty()); | |
| 162 if (!manager->core()->service()) { | |
| 163 // Make sure we've initialized the DeviceManagementService. It's OK to | |
| 164 // call this multiple times so we do it every time we initialize the | |
| 165 // UserCloudPolicyManager. | |
| 166 g_browser_process->browser_policy_connector()-> | |
| 167 ScheduleServiceInitialization( | |
| 168 kPolicyServiceInitializationDelayMilliseconds); | |
| 169 // If there is no cached DMToken then we can detect this below (or when | |
| 170 // the OnInitializationCompleted() callback is invoked). | |
| 171 policy::DeviceManagementService* service = g_browser_process-> | |
| 172 browser_policy_connector()->device_management_service(); | |
|
Mattias Nissler (ping if slow)
2012/12/10 09:01:09
nit: declaring a |connector| local might improve r
Andrew T Wilson (Slow)
2012/12/10 10:12:40
Done.
| |
| 173 manager->Connect(g_browser_process->local_state(), service); | |
| 174 DCHECK(manager->core()->service()); | |
| 175 StartObserving(); | |
| 176 } | |
| 101 | 177 |
| 102 void UserPolicySigninService::ConfigureUserCloudPolicyManager() { | 178 // If the CloudPolicyService is initialized, kick off registration. If the |
| 103 // Don't do anything unless cloud policy is enabled. | 179 // TokenService doesn't have an OAuth token yet (e.g. this is during initial |
| 104 if (!profile_->GetPrefs()->GetBoolean(prefs::kLoadCloudPolicyOnSignin)) | 180 // signin, or when dynamically loading a signed-in policy) this does nothing |
| 105 return; | 181 // until the OAuth token is loaded. |
| 182 if (manager->core()->service()->IsInitializationComplete()) | |
| 183 OnInitializationCompleted(manager->core()->service()); | |
| 184 } | |
| 106 | 185 |
| 107 // Either startup or shutdown the UserCloudPolicyManager depending on whether | 186 void UserPolicySigninService::ShutdownUserCloudPolicyManager() { |
| 108 // the user is signed in or not. | 187 StopObserving(); |
| 188 NotifyPendingFetchCallback(false); | |
| 189 | |
| 109 UserCloudPolicyManager* manager = GetManager(); | 190 UserCloudPolicyManager* manager = GetManager(); |
| 110 if (!manager) | 191 if (manager) // Can be null in unit tests. |
| 111 return; // Can be null in unit tests. | |
| 112 | |
| 113 SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_); | |
| 114 if (signin_manager->GetAuthenticatedUsername().empty()) { | |
| 115 // User has signed out - remove existing policy. | |
| 116 StopObserving(); | |
| 117 manager->DisconnectAndRemovePolicy(); | 192 manager->DisconnectAndRemovePolicy(); |
| 118 } else { | |
| 119 // Initialize the UserCloudPolicyManager if it isn't already initialized. | |
| 120 if (!manager->core()->service()) { | |
| 121 // Make sure we've initialized the DeviceManagementService. It's OK to | |
| 122 // call this multiple times so we do it every time we initialize the | |
| 123 // UserCloudPolicyManager. | |
| 124 g_browser_process->browser_policy_connector()-> | |
| 125 ScheduleServiceInitialization( | |
| 126 kPolicyServiceInitializationDelayMilliseconds); | |
| 127 // If there is no cached DMToken then we can detect this below (or when | |
| 128 // the OnInitializationCompleted() callback is invoked. | |
| 129 policy::DeviceManagementService* service = g_browser_process-> | |
| 130 browser_policy_connector()->device_management_service(); | |
| 131 manager->Connect(g_browser_process->local_state(), service); | |
| 132 DCHECK(manager->core()->service()); | |
| 133 manager->core()->service()->AddObserver(this); | |
| 134 } | |
| 135 | |
| 136 // If the CloudPolicyService is initialized, but the CloudPolicyClient still | |
| 137 // needs to be registered, kick off registration. | |
| 138 if (manager->core()->service()->IsInitializationComplete() && | |
| 139 !manager->IsClientRegistered()) { | |
| 140 RegisterCloudPolicyService(); | |
| 141 } | |
| 142 } | |
| 143 } | 193 } |
| 144 | 194 |
| 145 void UserPolicySigninService::OnInitializationCompleted( | 195 void UserPolicySigninService::OnInitializationCompleted( |
| 146 CloudPolicyService* service) { | 196 CloudPolicyService* service) { |
| 147 UserCloudPolicyManager* manager = GetManager(); | 197 UserCloudPolicyManager* manager = GetManager(); |
| 148 DCHECK_EQ(service, manager->core()->service()); | 198 DCHECK_EQ(service, manager->core()->service()); |
| 149 DCHECK(service->IsInitializationComplete()); | 199 DCHECK(service->IsInitializationComplete()); |
| 150 // The service is now initialized - if the client is not yet registered, then | 200 // The service is now initialized - if the client is not yet registered, then |
| 151 // it means that there is no cached policy and so we need to initiate a new | 201 // it means that there is no cached policy and so we need to initiate a new |
| 152 // client registration. | 202 // client registration. |
| 153 DVLOG_IF(1, manager->IsClientRegistered()) | 203 DVLOG_IF(1, manager->IsClientRegistered()) |
| 154 << "Client already registered - not fetching DMToken"; | 204 << "Client already registered - not fetching DMToken"; |
| 155 if (!manager->IsClientRegistered()) | 205 if (!manager->IsClientRegistered()) { |
| 156 RegisterCloudPolicyService(); | 206 std::string token = TokenServiceFactory::GetForProfile(profile_)-> |
| 207 GetOAuth2LoginRefreshToken(); | |
| 208 if (token.empty()) { | |
| 209 // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE | |
| 210 // and will re-attempt registration once the token is available. | |
| 211 DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download"; | |
| 212 return; | |
| 213 } | |
| 214 RegisterCloudPolicyService(token); | |
| 215 } | |
| 157 } | 216 } |
| 158 | 217 |
| 159 void UserPolicySigninService::RegisterCloudPolicyService() { | 218 void UserPolicySigninService::RegisterCloudPolicyService( |
| 219 std::string login_token) { | |
| 220 DCHECK(!GetManager()->IsClientRegistered()); | |
| 160 DVLOG(1) << "Fetching new DM Token"; | 221 DVLOG(1) << "Fetching new DM Token"; |
| 161 // TODO(atwilson): Move the code to mint the devicemanagement token into | |
| 162 // TokenService. | |
| 163 std::string token = TokenServiceFactory::GetForProfile(profile_)-> | |
| 164 GetOAuth2LoginRefreshToken(); | |
| 165 if (token.empty()) { | |
| 166 DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download"; | |
| 167 return; | |
| 168 } | |
| 169 | |
| 170 // Do nothing if already fetching an access token. | 222 // Do nothing if already fetching an access token. |
| 171 if (oauth2_access_token_fetcher_.get()) | 223 if (oauth2_access_token_fetcher_.get()) |
| 172 return; | 224 return; |
| 173 | 225 |
| 174 // Start fetching an OAuth2 access token for the device management service and | 226 // Start fetching an OAuth2 access token for the device management service and |
| 175 // hand it off to the CloudPolicyClient when done. | 227 // hand it off to the CloudPolicyClient when done. |
| 176 oauth2_access_token_fetcher_.reset( | 228 oauth2_access_token_fetcher_.reset( |
| 177 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); | 229 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); |
| 178 std::vector<std::string> scopes(1, kServiceScopeChromeOSDeviceManagement); | 230 std::vector<std::string> scopes(1, kServiceScopeChromeOSDeviceManagement); |
| 179 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); | 231 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); |
| 180 oauth2_access_token_fetcher_->Start( | 232 oauth2_access_token_fetcher_->Start( |
| 181 gaia_urls->oauth2_chrome_client_id(), | 233 gaia_urls->oauth2_chrome_client_id(), |
| 182 gaia_urls->oauth2_chrome_client_secret(), | 234 gaia_urls->oauth2_chrome_client_secret(), |
| 183 token, | 235 login_token, |
| 184 scopes); | 236 scopes); |
| 185 } | 237 } |
| 186 | 238 |
| 187 void UserPolicySigninService::OnGetTokenFailure( | 239 void UserPolicySigninService::OnGetTokenFailure( |
| 188 const GoogleServiceAuthError& error) { | 240 const GoogleServiceAuthError& error) { |
| 189 DLOG(WARNING) << "Could not fetch access token for " | 241 DLOG(WARNING) << "Could not fetch access token for " |
| 190 << kServiceScopeChromeOSDeviceManagement; | 242 << kServiceScopeChromeOSDeviceManagement; |
| 191 oauth2_access_token_fetcher_.reset(); | 243 oauth2_access_token_fetcher_.reset(); |
| 244 // If there was a pending fetch request, let them know the fetch failed. | |
| 245 NotifyPendingFetchCallback(false); | |
| 192 } | 246 } |
| 193 | 247 |
| 194 void UserPolicySigninService::OnGetTokenSuccess( | 248 void UserPolicySigninService::OnGetTokenSuccess( |
| 195 const std::string& access_token, | 249 const std::string& access_token, |
| 196 const base::Time& expiration_time) { | 250 const base::Time& expiration_time) { |
| 197 UserCloudPolicyManager* manager = GetManager(); | 251 UserCloudPolicyManager* manager = GetManager(); |
| 198 // Pass along the new access token to the CloudPolicyClient. | 252 // Pass along the new access token to the CloudPolicyClient. |
| 199 DVLOG(1) << "Fetched new scoped OAuth token:" << access_token; | 253 DVLOG(1) << "Fetched new scoped OAuth token:" << access_token; |
| 200 manager->RegisterClient(access_token); | 254 manager->RegisterClient(access_token); |
| 201 oauth2_access_token_fetcher_.reset(); | 255 oauth2_access_token_fetcher_.reset(); |
| 202 } | 256 } |
| 203 | 257 |
| 258 void UserPolicySigninService::OnRegistrationStateChanged( | |
| 259 CloudPolicyClient* client) { | |
| 260 DCHECK_EQ(GetManager()->core()->client(), client); | |
| 261 if (pending_fetch_) { | |
| 262 UserCloudPolicyManager* manager = GetManager(); | |
| 263 if (manager->IsClientRegistered()) { | |
| 264 // Request a policy fetch. | |
| 265 manager->core()->service()->RefreshPolicy( | |
| 266 base::Bind( | |
| 267 &UserPolicySigninService::NotifyPendingFetchCallback, | |
| 268 weak_factory_.GetWeakPtr())); | |
| 269 } else { | |
| 270 // Shouldn't be possible for the client to get unregistered. | |
| 271 NOTREACHED() << "Client unregistered while waiting for policy fetch"; | |
| 272 } | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 void UserPolicySigninService::NotifyPendingFetchCallback(bool success) { | |
| 277 if (pending_fetch_) { | |
| 278 pending_fetch_ = false; | |
| 279 pending_fetch_callback_.Run(success); | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 void UserPolicySigninService::OnPolicyFetched(CloudPolicyClient* client) { | |
| 284 // Do nothing when policy is fetched - if the policy fetch is successful, | |
| 285 // NotifyPendingFetchCallback will be invoked. | |
| 286 } | |
| 287 | |
| 288 void UserPolicySigninService::OnClientError(CloudPolicyClient* client) { | |
| 289 NotifyPendingFetchCallback(false); | |
| 290 } | |
| 291 | |
| 204 void UserPolicySigninService::Shutdown() { | 292 void UserPolicySigninService::Shutdown() { |
| 205 StopObserving(); | 293 StopObserving(); |
| 206 } | 294 } |
| 207 | 295 |
| 208 UserCloudPolicyManager* UserPolicySigninService::GetManager() { | 296 UserCloudPolicyManager* UserPolicySigninService::GetManager() { |
| 209 return UserCloudPolicyManagerFactory::GetForProfile(profile_); | 297 return UserCloudPolicyManagerFactory::GetForProfile(profile_); |
| 210 } | 298 } |
| 211 | 299 |
| 212 } // namespace policy | 300 } // namespace policy |
| OLD | NEW |