| 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 // (DoFinalInit() has not yet been called, so ProfileIOData and |
| 133 // SSLConfigServiceManager have not been created yet). |
| 134 SigninManager* signin_manager = |
| 135 SigninManagerFactory::GetForProfile(profile_); |
| 136 if (signin_manager->GetAuthenticatedUsername().empty()) |
| 137 ShutdownUserCloudPolicyManager(); |
| 138 else |
| 139 InitializeUserCloudPolicyManager(); |
| 83 break; | 140 break; |
| 141 } |
| 84 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 142 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
| 85 const TokenService::TokenAvailableDetails& token_details = | 143 const TokenService::TokenAvailableDetails& token_details = |
| 86 *(content::Details<const TokenService::TokenAvailableDetails>( | 144 *(content::Details<const TokenService::TokenAvailableDetails>( |
| 87 details).ptr()); | 145 details).ptr()); |
| 88 if (token_details.service() == | 146 if (token_details.service() == |
| 89 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { | 147 GaiaConstants::kGaiaOAuth2LoginRefreshToken) { |
| 90 // TokenService now has a refresh token, so initialize the | 148 // TokenService now has a refresh token (implying that the user is |
| 91 // UserCloudPolicyManager. | 149 // signed in) so initialize the UserCloudPolicyManager. |
| 92 ConfigureUserCloudPolicyManager(); | 150 InitializeUserCloudPolicyManager(); |
| 93 } | 151 } |
| 94 break; | 152 break; |
| 95 } | 153 } |
| 96 default: | 154 default: |
| 97 NOTREACHED(); | 155 NOTREACHED(); |
| 98 } | 156 } |
| 99 } | 157 } |
| 100 | 158 |
| 159 void UserPolicySigninService::InitializeUserCloudPolicyManager() { |
| 160 UserCloudPolicyManager* manager = GetManager(); |
| 161 DCHECK(!SigninManagerFactory::GetForProfile(profile_)-> |
| 162 GetAuthenticatedUsername().empty()); |
| 163 if (!manager->core()->service()) { |
| 164 // Make sure we've initialized the DeviceManagementService. It's OK to |
| 165 // call this multiple times so we do it every time we initialize the |
| 166 // UserCloudPolicyManager. |
| 167 g_browser_process->browser_policy_connector()-> |
| 168 ScheduleServiceInitialization( |
| 169 kPolicyServiceInitializationDelayMilliseconds); |
| 170 // If there is no cached DMToken then we can detect this below (or when |
| 171 // the OnInitializationCompleted() callback is invoked). |
| 172 BrowserPolicyConnector* connector = |
| 173 g_browser_process->browser_policy_connector(); |
| 174 manager->Connect(g_browser_process->local_state(), |
| 175 connector->device_management_service()); |
| 176 DCHECK(manager->core()->service()); |
| 177 StartObserving(); |
| 178 } |
| 101 | 179 |
| 102 void UserPolicySigninService::ConfigureUserCloudPolicyManager() { | 180 // If the CloudPolicyService is initialized, kick off registration. If the |
| 103 // Don't do anything unless cloud policy is enabled. | 181 // TokenService doesn't have an OAuth token yet (e.g. this is during initial |
| 104 if (!profile_->GetPrefs()->GetBoolean(prefs::kLoadCloudPolicyOnSignin)) | 182 // signin, or when dynamically loading a signed-in policy) this does nothing |
| 105 return; | 183 // until the OAuth token is loaded. |
| 184 if (manager->core()->service()->IsInitializationComplete()) |
| 185 OnInitializationCompleted(manager->core()->service()); |
| 186 } |
| 106 | 187 |
| 107 // Either startup or shutdown the UserCloudPolicyManager depending on whether | 188 void UserPolicySigninService::ShutdownUserCloudPolicyManager() { |
| 108 // the user is signed in or not. | 189 StopObserving(); |
| 190 NotifyPendingFetchCallback(false); |
| 191 |
| 109 UserCloudPolicyManager* manager = GetManager(); | 192 UserCloudPolicyManager* manager = GetManager(); |
| 110 if (!manager) | 193 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(); | 194 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 } | 195 } |
| 144 | 196 |
| 145 void UserPolicySigninService::OnInitializationCompleted( | 197 void UserPolicySigninService::OnInitializationCompleted( |
| 146 CloudPolicyService* service) { | 198 CloudPolicyService* service) { |
| 147 UserCloudPolicyManager* manager = GetManager(); | 199 UserCloudPolicyManager* manager = GetManager(); |
| 148 DCHECK_EQ(service, manager->core()->service()); | 200 DCHECK_EQ(service, manager->core()->service()); |
| 149 DCHECK(service->IsInitializationComplete()); | 201 DCHECK(service->IsInitializationComplete()); |
| 150 // The service is now initialized - if the client is not yet registered, then | 202 // 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 | 203 // it means that there is no cached policy and so we need to initiate a new |
| 152 // client registration. | 204 // client registration. |
| 153 DVLOG_IF(1, manager->IsClientRegistered()) | 205 DVLOG_IF(1, manager->IsClientRegistered()) |
| 154 << "Client already registered - not fetching DMToken"; | 206 << "Client already registered - not fetching DMToken"; |
| 155 if (!manager->IsClientRegistered()) | 207 if (!manager->IsClientRegistered()) { |
| 156 RegisterCloudPolicyService(); | 208 std::string token = TokenServiceFactory::GetForProfile(profile_)-> |
| 209 GetOAuth2LoginRefreshToken(); |
| 210 if (token.empty()) { |
| 211 // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE |
| 212 // and will re-attempt registration once the token is available. |
| 213 DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download"; |
| 214 return; |
| 215 } |
| 216 RegisterCloudPolicyService(token); |
| 217 } |
| 157 } | 218 } |
| 158 | 219 |
| 159 void UserPolicySigninService::RegisterCloudPolicyService() { | 220 void UserPolicySigninService::RegisterCloudPolicyService( |
| 221 std::string login_token) { |
| 222 DCHECK(!GetManager()->IsClientRegistered()); |
| 160 DVLOG(1) << "Fetching new DM Token"; | 223 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. | 224 // Do nothing if already fetching an access token. |
| 171 if (oauth2_access_token_fetcher_.get()) | 225 if (oauth2_access_token_fetcher_.get()) |
| 172 return; | 226 return; |
| 173 | 227 |
| 174 // Start fetching an OAuth2 access token for the device management service and | 228 // Start fetching an OAuth2 access token for the device management service and |
| 175 // hand it off to the CloudPolicyClient when done. | 229 // hand it off to the CloudPolicyClient when done. |
| 176 oauth2_access_token_fetcher_.reset( | 230 oauth2_access_token_fetcher_.reset( |
| 177 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); | 231 new OAuth2AccessTokenFetcher(this, profile_->GetRequestContext())); |
| 178 std::vector<std::string> scopes(1, kServiceScopeChromeOSDeviceManagement); | 232 std::vector<std::string> scopes(1, kServiceScopeChromeOSDeviceManagement); |
| 179 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); | 233 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); |
| 180 oauth2_access_token_fetcher_->Start( | 234 oauth2_access_token_fetcher_->Start( |
| 181 gaia_urls->oauth2_chrome_client_id(), | 235 gaia_urls->oauth2_chrome_client_id(), |
| 182 gaia_urls->oauth2_chrome_client_secret(), | 236 gaia_urls->oauth2_chrome_client_secret(), |
| 183 token, | 237 login_token, |
| 184 scopes); | 238 scopes); |
| 185 } | 239 } |
| 186 | 240 |
| 187 void UserPolicySigninService::OnGetTokenFailure( | 241 void UserPolicySigninService::OnGetTokenFailure( |
| 188 const GoogleServiceAuthError& error) { | 242 const GoogleServiceAuthError& error) { |
| 189 DLOG(WARNING) << "Could not fetch access token for " | 243 DLOG(WARNING) << "Could not fetch access token for " |
| 190 << kServiceScopeChromeOSDeviceManagement; | 244 << kServiceScopeChromeOSDeviceManagement; |
| 191 oauth2_access_token_fetcher_.reset(); | 245 oauth2_access_token_fetcher_.reset(); |
| 246 // If there was a pending fetch request, let them know the fetch failed. |
| 247 NotifyPendingFetchCallback(false); |
| 192 } | 248 } |
| 193 | 249 |
| 194 void UserPolicySigninService::OnGetTokenSuccess( | 250 void UserPolicySigninService::OnGetTokenSuccess( |
| 195 const std::string& access_token, | 251 const std::string& access_token, |
| 196 const base::Time& expiration_time) { | 252 const base::Time& expiration_time) { |
| 197 UserCloudPolicyManager* manager = GetManager(); | 253 UserCloudPolicyManager* manager = GetManager(); |
| 198 // Pass along the new access token to the CloudPolicyClient. | 254 // Pass along the new access token to the CloudPolicyClient. |
| 199 DVLOG(1) << "Fetched new scoped OAuth token:" << access_token; | 255 DVLOG(1) << "Fetched new scoped OAuth token:" << access_token; |
| 200 manager->RegisterClient(access_token); | 256 manager->RegisterClient(access_token); |
| 201 oauth2_access_token_fetcher_.reset(); | 257 oauth2_access_token_fetcher_.reset(); |
| 202 } | 258 } |
| 203 | 259 |
| 260 void UserPolicySigninService::OnRegistrationStateChanged( |
| 261 CloudPolicyClient* client) { |
| 262 DCHECK_EQ(GetManager()->core()->client(), client); |
| 263 if (pending_fetch_) { |
| 264 UserCloudPolicyManager* manager = GetManager(); |
| 265 if (manager->IsClientRegistered()) { |
| 266 // Request a policy fetch. |
| 267 manager->core()->service()->RefreshPolicy( |
| 268 base::Bind( |
| 269 &UserPolicySigninService::NotifyPendingFetchCallback, |
| 270 weak_factory_.GetWeakPtr())); |
| 271 } else { |
| 272 // Shouldn't be possible for the client to get unregistered. |
| 273 NOTREACHED() << "Client unregistered while waiting for policy fetch"; |
| 274 } |
| 275 } |
| 276 } |
| 277 |
| 278 void UserPolicySigninService::NotifyPendingFetchCallback(bool success) { |
| 279 if (pending_fetch_) { |
| 280 pending_fetch_ = false; |
| 281 pending_fetch_callback_.Run(success); |
| 282 } |
| 283 } |
| 284 |
| 285 void UserPolicySigninService::OnPolicyFetched(CloudPolicyClient* client) { |
| 286 // Do nothing when policy is fetched - if the policy fetch is successful, |
| 287 // NotifyPendingFetchCallback will be invoked. |
| 288 } |
| 289 |
| 290 void UserPolicySigninService::OnClientError(CloudPolicyClient* client) { |
| 291 NotifyPendingFetchCallback(false); |
| 292 } |
| 293 |
| 204 void UserPolicySigninService::Shutdown() { | 294 void UserPolicySigninService::Shutdown() { |
| 205 StopObserving(); | 295 StopObserving(); |
| 206 } | 296 } |
| 207 | 297 |
| 208 UserCloudPolicyManager* UserPolicySigninService::GetManager() { | 298 UserCloudPolicyManager* UserPolicySigninService::GetManager() { |
| 209 return UserCloudPolicyManagerFactory::GetForProfile(profile_); | 299 return UserCloudPolicyManagerFactory::GetForProfile(profile_); |
| 210 } | 300 } |
| 211 | 301 |
| 212 } // namespace policy | 302 } // namespace policy |
| OLD | NEW |