Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: chrome/browser/policy/user_policy_signin_service.cc

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, add chrome/browser/chromeos/policy/OWNERS Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 <vector>
8
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/values.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/policy/browser_policy_connector.h"
14 #include "chrome/browser/policy/cloud_policy_client.h"
15 #include "chrome/browser/policy/cloud_policy_service.h"
16 #include "chrome/browser/policy/user_cloud_policy_manager.h"
17 #include "chrome/browser/policy/user_cloud_policy_manager_factory.h"
18 #include "chrome/browser/policy/user_info_fetcher.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/signin/signin_manager.h"
22 #include "chrome/browser/signin/signin_manager_factory.h"
23 #include "chrome/browser/signin/token_service.h"
24 #include "chrome/browser/signin/token_service_factory.h"
25 #include "chrome/common/chrome_notification_types.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/pref_names.h"
28 #include "content/public/browser/notification_details.h"
29 #include "content/public/browser/notification_source.h"
30 #include "google_apis/gaia/gaia_constants.h"
31 #include "google_apis/gaia/gaia_urls.h"
32 #include "google_apis/gaia/oauth2_access_token_consumer.h"
33 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
34
35 namespace em = enterprise_management;
36
37 namespace {
38
39 // Various OAuth service scopes required to do CloudPolicyClient registration.
40 const char kServiceScopeChromeOSDeviceManagement[] =
41 "https://www.googleapis.com/auth/chromeosdevicemanagement";
42 const char kServiceScopeGetUserInfo[] =
43 "https://www.googleapis.com/auth/userinfo.email";
44
45 // The key under which the hosted-domain value is stored in the UserInfo
46 // response.
47 const char kGetHostedDomainKey[] = "hd";
48
49 bool ShouldForceLoadPolicy() {
50 return CommandLine::ForCurrentProcess()->HasSwitch(
51 switches::kForceLoadCloudPolicy);
52 }
53
54 } // namespace
55
56 namespace policy {
57
58 // Helper class that registers a CloudPolicyClient and returns the associated
59 // DMToken to the caller.
60 class CloudPolicyClientRegistrationHelper
61 : public policy::CloudPolicyClient::Observer,
62 public OAuth2AccessTokenConsumer,
63 public policy::UserInfoFetcher::Delegate {
64 public:
65 explicit CloudPolicyClientRegistrationHelper(
66 net::URLRequestContextGetter* context);
67
68 virtual ~CloudPolicyClientRegistrationHelper();
69
70 // Starts the client registration process. Callback is invoked when the
71 // registration is complete.
72 void StartRegistration(policy::CloudPolicyClient* client,
73 const std::string& oauth2_login_token,
74 base::Closure callback);
75
76 // OAuth2AccessTokenConsumer implementation.
77 virtual void OnGetTokenSuccess(const std::string& access_token,
78 const base::Time& expiration_time) OVERRIDE;
79 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
80
81 // UserInfoFetcher::Delegate implementation:
82 virtual void OnGetUserInfoSuccess(const DictionaryValue* response) OVERRIDE;
83 virtual void OnGetUserInfoFailure(
84 const GoogleServiceAuthError& error) OVERRIDE;
85
86 // CloudPolicyClient::Observer implementation.
87 virtual void OnPolicyFetched(policy::CloudPolicyClient* client) OVERRIDE {}
88 virtual void OnRegistrationStateChanged(
89 policy::CloudPolicyClient* client) OVERRIDE;
90 virtual void OnClientError(policy::CloudPolicyClient* client) OVERRIDE;
91
92 private:
93 // Invoked when the registration request has been completed.
94 void RequestCompleted();
95
96 // Fetcher used while obtaining an OAuth token for client registration.
97 scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
98
99 // Helper class for fetching information from GAIA about the currently
100 // signed-in user.
101 scoped_ptr<policy::UserInfoFetcher> user_info_fetcher_;
102
103 // Access token used to register the CloudPolicyClient and also access
104 // GAIA to get information about the signed in user.
105 std::string oauth_access_token_;
106
107 net::URLRequestContextGetter* context_;
108 policy::CloudPolicyClient* client_;
109 base::Closure callback_;
110 };
111
112 CloudPolicyClientRegistrationHelper::CloudPolicyClientRegistrationHelper(
113 net::URLRequestContextGetter* context) : context_(context) {
114 DCHECK(context_);
115 }
116
117 CloudPolicyClientRegistrationHelper::~CloudPolicyClientRegistrationHelper() {
118 // Clean up any pending observers in case the browser is shutdown while
119 // trying to register for policy.
120 if (client_)
121 client_->RemoveObserver(this);
122 }
123
124 void CloudPolicyClientRegistrationHelper::RequestCompleted() {
125 if (client_) {
126 client_->RemoveObserver(this);
127 // |client_| may be freed by the callback so clear it now.
128 client_ = NULL;
129 callback_.Run();
130 }
131 }
132
133 void CloudPolicyClientRegistrationHelper::StartRegistration(
134 policy::CloudPolicyClient* client,
135 const std::string& login_token,
136 base::Closure callback) {
137 DVLOG(1) << "Starting registration process";
138 DCHECK(client);
139 DCHECK(!client->is_registered());
140 client_ = client;
141 callback_ = callback;
142 client_->AddObserver(this);
143
144 // Start fetching an OAuth2 access token for the device management and
145 // userinfo services.
146 oauth2_access_token_fetcher_.reset(
147 new OAuth2AccessTokenFetcher(this, context_));
148 std::vector<std::string> scopes;
149 scopes.push_back(kServiceScopeChromeOSDeviceManagement);
150 scopes.push_back(kServiceScopeGetUserInfo);
151 GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
152 oauth2_access_token_fetcher_->Start(
153 gaia_urls->oauth2_chrome_client_id(),
154 gaia_urls->oauth2_chrome_client_secret(),
155 login_token,
156 scopes);
157 }
158
159 void CloudPolicyClientRegistrationHelper::OnGetTokenFailure(
160 const GoogleServiceAuthError& error) {
161 DLOG(WARNING) << "Could not fetch access token for "
162 << kServiceScopeChromeOSDeviceManagement;
163 oauth2_access_token_fetcher_.reset();
164
165 // Invoke the callback to let them know the fetch failed.
166 RequestCompleted();
167 }
168
169 void CloudPolicyClientRegistrationHelper::OnGetTokenSuccess(
170 const std::string& access_token,
171 const base::Time& expiration_time) {
172 // Cache the access token to be used after the GetUserInfo call.
173 oauth_access_token_ = access_token;
174 DVLOG(1) << "Fetched new scoped OAuth token:" << oauth_access_token_;
175 oauth2_access_token_fetcher_.reset();
176 // Now we've gotten our access token - contact GAIA to see if this is a
177 // hosted domain.
178 user_info_fetcher_.reset(new policy::UserInfoFetcher(this, context_));
179 user_info_fetcher_->Start(oauth_access_token_);
180 }
181
182 void CloudPolicyClientRegistrationHelper::OnGetUserInfoFailure(
183 const GoogleServiceAuthError& error) {
184 DVLOG(1) << "Failed to fetch user info from GAIA: " << error.state();
185 user_info_fetcher_.reset();
186 RequestCompleted();
187 }
188
189 void CloudPolicyClientRegistrationHelper::OnGetUserInfoSuccess(
190 const DictionaryValue* data) {
191 user_info_fetcher_.reset();
192 if (!data->HasKey(kGetHostedDomainKey) && !ShouldForceLoadPolicy()) {
193 DVLOG(1) << "User not from a hosted domain - skipping registration";
194 RequestCompleted();
195 return;
196 }
197 DVLOG(1) << "Registering CloudPolicyClient for user from hosted domain";
198 // The user is from a hosted domain, so it's OK to register the
199 // CloudPolicyClient and make requests to DMServer.
200 if (client_->is_registered()) {
201 // Client should not be registered yet.
202 NOTREACHED();
203 RequestCompleted();
204 return;
205 }
206
207 // Kick off registration of the CloudPolicyClient with our newly minted
208 // oauth_access_token_.
209 client_->Register(em::DeviceRegisterRequest::BROWSER, oauth_access_token_,
210 std::string(), false);
211 }
212
213 void CloudPolicyClientRegistrationHelper::OnRegistrationStateChanged(
214 policy::CloudPolicyClient* client) {
215 DVLOG(1) << "Client registration succeeded";
216 DCHECK_EQ(client, client_);
217 DCHECK(client->is_registered());
218 RequestCompleted();
219 }
220
221 void CloudPolicyClientRegistrationHelper::OnClientError(
222 policy::CloudPolicyClient* client) {
223 DVLOG(1) << "Client registration failed";
224 DCHECK_EQ(client, client_);
225 RequestCompleted();
226 }
227
228 UserPolicySigninService::UserPolicySigninService(
229 Profile* profile)
230 : profile_(profile) {
231 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
232 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin) ||
233 ProfileManager::IsImportProcess(*cmd_line)) {
234 return;
235 }
236
237 // Initialize/shutdown the UserCloudPolicyManager when the user signs out.
238 registrar_.Add(this,
239 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
240 content::Source<Profile>(profile));
241
242 // Listen for an OAuth token to become available so we can register a client
243 // if for some reason the client is not already registered (for example, if
244 // the policy load failed during initial signin).
245 registrar_.Add(this,
246 chrome::NOTIFICATION_TOKEN_AVAILABLE,
247 content::Source<TokenService>(
248 TokenServiceFactory::GetForProfile(profile)));
249
250 // TokenService should not yet have loaded its tokens since this happens in
251 // the background after PKS initialization - so this service should always be
252 // created before the oauth token is available.
253 DCHECK(!TokenServiceFactory::GetForProfile(profile_)->HasOAuthLoginToken());
254
255 // Register a listener to be called back once the current profile has finished
256 // initializing, so we can startup the UserCloudPolicyManager.
257 registrar_.Add(this,
258 chrome::NOTIFICATION_PROFILE_ADDED,
259 content::Source<Profile>(profile));
260
261 // Register a listener for the import finished notification in a first run
262 // scenario, which indicates the profile is ready to be further initialized.
263 registrar_.Add(this,
264 chrome::NOTIFICATION_IMPORT_FINISHED,
265 content::Source<Profile>(profile));
266 }
267
268 UserPolicySigninService::~UserPolicySigninService() {}
269
270 void UserPolicySigninService::RegisterPolicyClient(
271 const std::string& username,
272 const std::string& oauth2_refresh_token,
273 const PolicyRegistrationCallback& callback) {
274 DCHECK(!username.empty());
275 DCHECK(!oauth2_refresh_token.empty());
276 // We should not be called with a client already initialized.
277 DCHECK(!GetManager() || !GetManager()->core()->client());
278
279 // If the user should not get policy, just bail out.
280 if (!GetManager() || !ShouldLoadPolicyForUser(username)) {
281 DVLOG(1) << "Signed in user is not in the whitelist";
282 callback.Run(scoped_ptr<CloudPolicyClient>().Pass());
283 return;
284 }
285
286 // If the DeviceManagementService is not yet initialized, start it up now.
287 g_browser_process->browser_policy_connector()->
288 ScheduleServiceInitialization(0);
289
290 // Create a new CloudPolicyClient for fetching the DMToken.
291 scoped_ptr<CloudPolicyClient> policy_client(
292 UserCloudPolicyManager::CreateCloudPolicyClient(
293 g_browser_process->browser_policy_connector()->
294 device_management_service()));
295
296 registration_helper_.reset(
297 new CloudPolicyClientRegistrationHelper(profile_->GetRequestContext()));
298
299 // Fire off the registration process. Callback keeps the CloudPolicyClient
300 // alive for the length of the registration process.
301 // Grab a pointer to the client before base::Bind() clears the reference in
302 // |policy_client|.
303 CloudPolicyClient* client = policy_client.get();
304 base::Closure registration_callback =
305 base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
306 base::Unretained(this), base::Passed(&policy_client),
307 callback);
308 registration_helper_->StartRegistration(
309 client, oauth2_refresh_token, registration_callback);
310 }
311
312 void UserPolicySigninService::CallPolicyRegistrationCallback(
313 scoped_ptr<CloudPolicyClient> client,
314 PolicyRegistrationCallback callback) {
315 registration_helper_.reset();
316 if (!client->is_registered()) {
317 // Registration failed, so free the client and pass NULL to the callback.
318 client.reset();
319 }
320 callback.Run(client.Pass());
321 }
322
323 void UserPolicySigninService::FetchPolicyForSignedInUser(
324 scoped_ptr<CloudPolicyClient> client,
325 const PolicyFetchCallback& callback) {
326 DCHECK(client);
327 DCHECK(client->is_registered());
328 // The user has just signed in, so the UserCloudPolicyManager should not yet
329 // be initialized. This routine will initialize the UserCloudPolicyManager
330 // with the passed client and will proactively ask the client to fetch
331 // policy without waiting for the CloudPolicyService to finish initialization.
332 UserCloudPolicyManager* manager = GetManager();
333 DCHECK(manager);
334 DCHECK(!manager->core()->client());
335 InitializeUserCloudPolicyManager(client.Pass());
336 DCHECK(manager->IsClientRegistered());
337
338 // Now initiate a policy fetch.
339 manager->core()->service()->RefreshPolicy(callback);
340 }
341
342 void UserPolicySigninService::StopObserving() {
343 UserCloudPolicyManager* manager = GetManager();
344 if (manager && manager->core()->service())
345 manager->core()->service()->RemoveObserver(this);
346 }
347
348 void UserPolicySigninService::StartObserving() {
349 UserCloudPolicyManager* manager = GetManager();
350 // Manager should be fully initialized by now.
351 DCHECK(manager);
352 DCHECK(manager->core()->service());
353 manager->core()->service()->AddObserver(this);
354 }
355
356 void UserPolicySigninService::Observe(
357 int type,
358 const content::NotificationSource& source,
359 const content::NotificationDetails& details) {
360 // If an import process is running, wait for NOTIFICATION_IMPORT_FINISHED
361 // before potentially creating the SigninManager. Its dependencies can access
362 // databases that the import process is also accessing, causing conflicts.
363 // Note that the profile manager is NULL in unit tests.
364 if (g_browser_process->profile_manager() &&
365 g_browser_process->profile_manager()->will_import()) {
366 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_ADDED, type);
367 return;
368 }
369
370 // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
371 // skip initialization.
372 if (!GetManager() || !SigninManagerFactory::GetForProfile(profile_)) {
373 DVLOG(1) << "Skipping initialization for tests due to missing components.";
374 return;
375 }
376
377 switch (type) {
378 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
379 ShutdownUserCloudPolicyManager();
380 break;
381 case chrome::NOTIFICATION_IMPORT_FINISHED:
382 case chrome::NOTIFICATION_PROFILE_ADDED: {
383 // A new profile has been loaded - if it's signed in, then initialize the
384 // UCPM, otherwise shut down the UCPM (which deletes any cached policy
385 // data). This must be done here instead of at constructor time because
386 // the Profile is not fully initialized when this object is constructed
387 // (DoFinalInit() has not yet been called, so ProfileIOData and
388 // SSLConfigServiceManager have not been created yet).
389 // TODO(atwilson): Switch to using a timer instead, to avoid contention
390 // with other services at startup (http://crbug.com/165468).
391 SigninManager* signin_manager =
392 SigninManagerFactory::GetForProfile(profile_);
393 std::string username = signin_manager->GetAuthenticatedUsername();
394 if (username.empty())
395 ShutdownUserCloudPolicyManager();
396 else
397 InitializeForSignedInUser();
398 break;
399 }
400 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
401 const TokenService::TokenAvailableDetails& token_details =
402 *(content::Details<const TokenService::TokenAvailableDetails>(
403 details).ptr());
404 if (token_details.service() ==
405 GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
406 SigninManager* signin_manager =
407 SigninManagerFactory::GetForProfile(profile_);
408 std::string username = signin_manager->GetAuthenticatedUsername();
409 // Should not have GAIA tokens if the user isn't signed in.
410 DCHECK(!username.empty());
411 // TokenService now has a refresh token (implying that the user is
412 // signed in) so initialize the UserCloudPolicyManager.
413 InitializeForSignedInUser();
414 }
415 break;
416 }
417 default:
418 NOTREACHED();
419 }
420 }
421
422 bool UserPolicySigninService::ShouldLoadPolicyForUser(
423 const std::string& username) {
424 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
425 return false; // Cloud policy is disabled.
426
427 if (username.empty())
428 return false; // Not signed in.
429
430 if (ShouldForceLoadPolicy())
431 return true;
432
433 return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
434 }
435
436 void UserPolicySigninService::InitializeUserCloudPolicyManager(
437 scoped_ptr<CloudPolicyClient> client) {
438 UserCloudPolicyManager* manager = GetManager();
439 DCHECK(!manager->core()->client());
440 // If there is no cached DMToken then we can detect this below (or when
441 // the OnInitializationCompleted() callback is invoked).
442 manager->Connect(g_browser_process->local_state(), client.Pass());
443 DCHECK(manager->core()->service());
444 StartObserving();
445 ProhibitSignoutIfNeeded();
446 }
447
448 void UserPolicySigninService::InitializeForSignedInUser() {
449 SigninManager* signin_manager =
450 SigninManagerFactory::GetForProfile(profile_);
451 std::string username = signin_manager->GetAuthenticatedUsername();
452
453 if (!ShouldLoadPolicyForUser(username)) {
454 DVLOG(1) << "Policy load not enabled for user: " << username;
455 return;
456 }
457 DCHECK(!username.empty());
458
459 UserCloudPolicyManager* manager = GetManager();
460 // Initialize the UCPM if it is not already initialized.
461 if (!manager->core()->service()) {
462 // If there is no cached DMToken then we can detect this when the
463 // OnInitializationCompleted() callback is invoked and this will
464 // initiate a policy fetch.
465 BrowserPolicyConnector* connector =
466 g_browser_process->browser_policy_connector();
467 InitializeUserCloudPolicyManager(
468 UserCloudPolicyManager::CreateCloudPolicyClient(
469 connector->device_management_service()).Pass());
470 }
471
472 // If the CloudPolicyService is initialized, kick off registration. If the
473 // TokenService doesn't have an OAuth token yet (e.g. this is during initial
474 // signin, or when dynamically loading a signed-in policy) this does nothing
475 // until the OAuth token is loaded.
476 if (manager->core()->service()->IsInitializationComplete())
477 OnInitializationCompleted(manager->core()->service());
478 }
479
480 void UserPolicySigninService::ShutdownUserCloudPolicyManager() {
481 // Stop any in-progress token fetch.
482 registration_helper_.reset();
483
484 StopObserving();
485
486 UserCloudPolicyManager* manager = GetManager();
487 if (manager) // Can be null in unit tests.
488 manager->DisconnectAndRemovePolicy();
489 }
490
491 void UserPolicySigninService::OnInitializationCompleted(
492 CloudPolicyService* service) {
493 UserCloudPolicyManager* manager = GetManager();
494 DCHECK_EQ(service, manager->core()->service());
495 DCHECK(service->IsInitializationComplete());
496 // The service is now initialized - if the client is not yet registered, then
497 // it means that there is no cached policy and so we need to initiate a new
498 // client registration.
499 DVLOG_IF(1, manager->IsClientRegistered())
500 << "Client already registered - not fetching DMToken";
501 if (!manager->IsClientRegistered()) {
502 std::string token = TokenServiceFactory::GetForProfile(profile_)->
503 GetOAuth2LoginRefreshToken();
504 if (token.empty()) {
505 // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE
506 // and will re-attempt registration once the token is available.
507 DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download";
508 return;
509 }
510 RegisterCloudPolicyService(token);
511 }
512 // If client is registered now, prohibit signout.
513 ProhibitSignoutIfNeeded();
514 }
515
516 void UserPolicySigninService::RegisterCloudPolicyService(
517 std::string login_token) {
518 DCHECK(!GetManager()->IsClientRegistered());
519 DVLOG(1) << "Fetching new DM Token";
520 // Do nothing if already starting the registration process.
521 if (registration_helper_)
522 return;
523
524 // Start the process of registering the CloudPolicyClient. Once it completes,
525 // policy fetch will automatically happen.
526 registration_helper_.reset(
527 new CloudPolicyClientRegistrationHelper(profile_->GetRequestContext()));
528 registration_helper_->StartRegistration(
529 GetManager()->core()->client(),
530 login_token,
531 base::Bind(&UserPolicySigninService::OnRegistrationComplete,
532 base::Unretained(this)));
533 }
534
535 void UserPolicySigninService::OnRegistrationComplete() {
536 ProhibitSignoutIfNeeded();
537 registration_helper_.reset();
538 }
539
540 void UserPolicySigninService::ProhibitSignoutIfNeeded() {
541 if (GetManager()->IsClientRegistered()) {
542 DVLOG(1) << "User is registered for policy - prohibiting signout";
543 SigninManager* signin_manager =
544 SigninManagerFactory::GetForProfile(profile_);
545 signin_manager->ProhibitSignout();
546 }
547 }
548
549 void UserPolicySigninService::Shutdown() {
550 // Stop any pending registration helper activity. We do this here instead of
551 // in the destructor because we want to shutdown the registration helper
552 // before UserCloudPolicyManager shuts down the CloudPolicyClient.
553 registration_helper_.reset();
554 StopObserving();
555 }
556
557 UserCloudPolicyManager* UserPolicySigninService::GetManager() {
558 return UserCloudPolicyManagerFactory::GetForProfile(profile_);
559 }
560
561 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/user_policy_signin_service.h ('k') | chrome/browser/policy/user_policy_signin_service_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698