user_policy_signin_service.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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/cloud/user_policy_signin_service.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/prefs/pref_service.h"
11#include "chrome/browser/browser_process.h"
12#include "chrome/browser/policy/cloud/cloud_policy_client_registration_helper.h"
13#include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/profiles/profile_manager.h"
16#include "chrome/browser/signin/signin_manager.h"
17#include "chrome/browser/signin/signin_manager_factory.h"
18#include "chrome/browser/signin/token_service.h"
19#include "chrome/browser/signin/token_service_factory.h"
20#include "chrome/common/chrome_notification_types.h"
21#include "chrome/common/pref_names.h"
22#include "content/public/browser/notification_details.h"
23#include "google_apis/gaia/gaia_constants.h"
24
25#if defined(ENABLE_MANAGED_USERS)
26#include "chrome/browser/managed_mode/managed_user_service.h"
27#endif
28
29namespace policy {
30
31UserPolicySigninService::UserPolicySigninService(
32    Profile* profile) : UserPolicySigninServiceBase(profile) {
33  if (profile->GetPrefs()->GetBoolean(prefs::kDisableCloudPolicyOnSignin))
34    return;
35
36  // Listen for an OAuth token to become available so we can register a client
37  // if for some reason the client is not already registered (for example, if
38  // the policy load failed during initial signin).
39  registrar()->Add(this,
40                   chrome::NOTIFICATION_TOKEN_AVAILABLE,
41                   content::Source<TokenService>(
42                       TokenServiceFactory::GetForProfile(profile)));
43
44  // TokenService should not yet have loaded its tokens since this happens in
45  // the background after PKS initialization - so this service should always be
46  // created before the oauth token is available.
47  DCHECK(!TokenServiceFactory::GetForProfile(profile)->HasOAuthLoginToken());
48
49  // Register a listener for the import finished notification in a first run
50  // scenario, which indicates the profile is ready to be further initialized.
51  registrar()->Add(this,
52                   chrome::NOTIFICATION_IMPORT_FINISHED,
53                   content::Source<Profile>(profile));
54}
55
56UserPolicySigninService::~UserPolicySigninService() {}
57
58void UserPolicySigninService::Shutdown() {
59  // Stop any pending registration helper activity. We do this here instead of
60  // in the destructor because we want to shutdown the registration helper
61  // before UserCloudPolicyManager shuts down the CloudPolicyClient.
62  registration_helper_.reset();
63  UserPolicySigninServiceBase::Shutdown();
64}
65
66void UserPolicySigninService::RegisterPolicyClient(
67    const std::string& username,
68    const std::string& oauth2_refresh_token,
69    const PolicyRegistrationCallback& callback) {
70  DCHECK(!oauth2_refresh_token.empty());
71
72  // Create a new CloudPolicyClient for fetching the DMToken.
73  scoped_ptr<CloudPolicyClient> policy_client = PrepareToRegister(username);
74  if (!policy_client) {
75    callback.Run(policy_client.Pass());
76    return;
77  }
78
79  // Fire off the registration process. Callback keeps the CloudPolicyClient
80  // alive for the length of the registration process.
81  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
82      profile()->GetRequestContext(),
83      policy_client.get(),
84      ShouldForceLoadPolicy(),
85      enterprise_management::DeviceRegisterRequest::BROWSER));
86  registration_helper_->StartRegistrationWithLoginToken(
87      oauth2_refresh_token,
88      base::Bind(&UserPolicySigninService::CallPolicyRegistrationCallback,
89                 base::Unretained(this),
90                 base::Passed(&policy_client),
91                 callback));
92}
93
94void UserPolicySigninService::CallPolicyRegistrationCallback(
95    scoped_ptr<CloudPolicyClient> client,
96    PolicyRegistrationCallback callback) {
97  registration_helper_.reset();
98  if (!client->is_registered()) {
99    // Registration failed, so free the client and pass NULL to the callback.
100    client.reset();
101  }
102  callback.Run(client.Pass());
103}
104
105void UserPolicySigninService::Observe(
106    int type,
107    const content::NotificationSource& source,
108    const content::NotificationDetails& details) {
109  // If an import process is running, wait for NOTIFICATION_IMPORT_FINISHED
110  // before potentially creating the SigninManager. Its dependencies can access
111  // databases that the import process is also accessing, causing conflicts.
112  // Note that the profile manager is NULL in unit tests.
113  if (g_browser_process->profile_manager() &&
114      g_browser_process->profile_manager()->will_import()) {
115    return;
116  }
117
118#if defined(ENABLE_MANAGED_USERS)
119  if (ManagedUserService::ProfileIsManaged(profile())) {
120    registrar()->RemoveAll();
121    return;
122  }
123#endif
124
125  // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
126  // skip initialization.
127  if (!GetManager() || !SigninManagerFactory::GetForProfile(profile())) {
128    DVLOG(1) << "Skipping initialization for tests due to missing components.";
129    return;
130  }
131
132  switch (type) {
133    case chrome::NOTIFICATION_IMPORT_FINISHED:
134      InitializeOnProfileReady();
135      break;
136    case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
137      const TokenService::TokenAvailableDetails& token_details =
138          *(content::Details<const TokenService::TokenAvailableDetails>(
139              details).ptr());
140      if (token_details.service() ==
141              GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
142        SigninManager* signin_manager =
143            SigninManagerFactory::GetForProfile(profile());
144        std::string username = signin_manager->GetAuthenticatedUsername();
145        // Should not have GAIA tokens if the user isn't signed in.
146        DCHECK(!username.empty());
147        // TokenService now has a refresh token (implying that the user is
148        // signed in) so initialize the UserCloudPolicyManager.
149        InitializeForSignedInUser(username);
150      }
151      break;
152    }
153    default:
154      UserPolicySigninServiceBase::Observe(type, source, details);
155  }
156}
157
158void UserPolicySigninService::InitializeUserCloudPolicyManager(
159    scoped_ptr<CloudPolicyClient> client) {
160  UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(client.Pass());
161  ProhibitSignoutIfNeeded();
162}
163
164void UserPolicySigninService::ShutdownUserCloudPolicyManager() {
165  UserCloudPolicyManager* manager = GetManager();
166  if (manager) {
167    // Allow the user to signout again.
168    SigninManagerFactory::GetForProfile(profile())->ProhibitSignout(false);
169  }
170  UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager();
171}
172
173void UserPolicySigninService::OnInitializationCompleted(
174    CloudPolicyService* service) {
175  UserCloudPolicyManager* manager = GetManager();
176  DCHECK_EQ(service, manager->core()->service());
177  DCHECK(service->IsInitializationComplete());
178  // The service is now initialized - if the client is not yet registered, then
179  // it means that there is no cached policy and so we need to initiate a new
180  // client registration.
181  DVLOG_IF(1, manager->IsClientRegistered())
182      << "Client already registered - not fetching DMToken";
183  if (!manager->IsClientRegistered()) {
184    std::string token = TokenServiceFactory::GetForProfile(profile())->
185        GetOAuth2LoginRefreshToken();
186    if (token.empty()) {
187      // No token yet - this class listens for NOTIFICATION_TOKEN_AVAILABLE
188      // and will re-attempt registration once the token is available.
189      DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download";
190      return;
191    }
192    RegisterCloudPolicyService(token);
193  }
194  // If client is registered now, prohibit signout.
195  ProhibitSignoutIfNeeded();
196}
197
198void UserPolicySigninService::RegisterCloudPolicyService(
199    const std::string& login_token) {
200  DCHECK(!GetManager()->IsClientRegistered());
201  DVLOG(1) << "Fetching new DM Token";
202  // Do nothing if already starting the registration process.
203  if (registration_helper_)
204    return;
205
206  // Start the process of registering the CloudPolicyClient. Once it completes,
207  // policy fetch will automatically happen.
208  registration_helper_.reset(new CloudPolicyClientRegistrationHelper(
209      profile()->GetRequestContext(),
210      GetManager()->core()->client(),
211      ShouldForceLoadPolicy(),
212      enterprise_management::DeviceRegisterRequest::BROWSER));
213  registration_helper_->StartRegistrationWithLoginToken(
214      login_token,
215      base::Bind(&UserPolicySigninService::OnRegistrationComplete,
216                 base::Unretained(this)));
217}
218
219void UserPolicySigninService::OnRegistrationComplete() {
220  ProhibitSignoutIfNeeded();
221  registration_helper_.reset();
222}
223
224void UserPolicySigninService::ProhibitSignoutIfNeeded() {
225  if (GetManager()->IsClientRegistered()) {
226    DVLOG(1) << "User is registered for policy - prohibiting signout";
227    SigninManager* signin_manager =
228        SigninManagerFactory::GetForProfile(profile());
229    signin_manager->ProhibitSignout(true);
230  }
231}
232
233}  // namespace policy
234