Home | History | Annotate | Download | only in cloud
      1 // Copyright 2013 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_base.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/browser/signin/signin_manager_factory.h"
     13 #include "chrome/common/chrome_content_client.h"
     14 #include "components/policy/core/browser/browser_policy_connector.h"
     15 #include "components/policy/core/common/cloud/device_management_service.h"
     16 #include "components/policy/core/common/cloud/system_policy_request_context.h"
     17 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
     18 #include "components/policy/core/common/cloud/user_policy_request_context.h"
     19 #include "components/signin/core/browser/signin_manager.h"
     20 #include "content/public/browser/notification_source.h"
     21 #include "net/url_request/url_request_context_getter.h"
     22 
     23 namespace policy {
     24 
     25 UserPolicySigninServiceBase::UserPolicySigninServiceBase(
     26     Profile* profile,
     27     PrefService* local_state,
     28     DeviceManagementService* device_management_service,
     29     UserCloudPolicyManager* policy_manager,
     30     SigninManager* signin_manager,
     31     scoped_refptr<net::URLRequestContextGetter> system_request_context)
     32     : policy_manager_(policy_manager),
     33       signin_manager_(signin_manager),
     34       local_state_(local_state),
     35       device_management_service_(device_management_service),
     36       system_request_context_(system_request_context),
     37       weak_factory_(this) {
     38   // Register a listener to be called back once the current profile has finished
     39   // initializing, so we can startup/shutdown the UserCloudPolicyManager.
     40   registrar_.Add(this,
     41                  chrome::NOTIFICATION_PROFILE_ADDED,
     42                  content::Source<Profile>(profile));
     43 }
     44 
     45 UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
     46 
     47 void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
     48     const std::string& username,
     49     const std::string& dm_token,
     50     const std::string& client_id,
     51     scoped_refptr<net::URLRequestContextGetter> profile_request_context,
     52     const PolicyFetchCallback& callback) {
     53   scoped_ptr<CloudPolicyClient> client(
     54       UserCloudPolicyManager::CreateCloudPolicyClient(
     55           device_management_service_,
     56           CreateUserRequestContext(profile_request_context)).Pass());
     57   client->SetupRegistration(dm_token, client_id);
     58   DCHECK(client->is_registered());
     59   // The user has just signed in, so the UserCloudPolicyManager should not yet
     60   // be initialized. This routine will initialize the UserCloudPolicyManager
     61   // with the passed client and will proactively ask the client to fetch
     62   // policy without waiting for the CloudPolicyService to finish initialization.
     63   UserCloudPolicyManager* manager = policy_manager();
     64   DCHECK(manager);
     65   DCHECK(!manager->core()->client());
     66   InitializeUserCloudPolicyManager(username, client.Pass());
     67   DCHECK(manager->IsClientRegistered());
     68 
     69   // Now initiate a policy fetch.
     70   manager->core()->service()->RefreshPolicy(callback);
     71 }
     72 
     73 void UserPolicySigninServiceBase::GoogleSignedOut(const std::string& account_id,
     74                                                   const std::string& username) {
     75   ShutdownUserCloudPolicyManager();
     76 }
     77 
     78 void UserPolicySigninServiceBase::Observe(
     79     int type,
     80     const content::NotificationSource& source,
     81     const content::NotificationDetails& details) {
     82   switch (type) {
     83     case chrome::NOTIFICATION_PROFILE_ADDED:
     84       // A new profile has been loaded - if it's signed in, then initialize the
     85       // UCPM, otherwise shut down the UCPM (which deletes any cached policy
     86       // data). This must be done here instead of at constructor time because
     87       // the Profile is not fully initialized when this object is constructed
     88       // (DoFinalInit() has not yet been called, so ProfileIOData and
     89       // SSLConfigServiceManager have not been created yet).
     90       // TODO(atwilson): Switch to using a timer instead, to avoid contention
     91       // with other services at startup (http://crbug.com/165468).
     92       InitializeOnProfileReady(content::Source<Profile>(source).ptr());
     93       break;
     94     default:
     95       NOTREACHED();
     96   }
     97 }
     98 
     99 void UserPolicySigninServiceBase::OnInitializationCompleted(
    100     CloudPolicyService* service) {
    101   // This is meant to be overridden by subclasses. Starting and stopping to
    102   // observe the CloudPolicyService from this base class avoids the need for
    103   // more virtuals.
    104 }
    105 
    106 void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
    107 
    108 void UserPolicySigninServiceBase::OnRegistrationStateChanged(
    109     CloudPolicyClient* client) {}
    110 
    111 void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
    112   if (client->is_registered()) {
    113     // If the client is already registered, it means this error must have
    114     // come from a policy fetch.
    115     if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
    116       // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
    117       // trigger to revert to "unmanaged" mode (we will check for management
    118       // being re-enabled on the next restart and/or login).
    119       DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
    120 
    121       // Can't shutdown now because we're in the middle of a callback from
    122       // the CloudPolicyClient, so queue up a task to do the shutdown.
    123       base::MessageLoop::current()->PostTask(
    124           FROM_HERE,
    125           base::Bind(
    126               &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
    127               weak_factory_.GetWeakPtr()));
    128     } else {
    129       DVLOG(1) << "Error fetching policy: " << client->status();
    130     }
    131   }
    132 }
    133 
    134 void UserPolicySigninServiceBase::Shutdown() {
    135   if (signin_manager())
    136     signin_manager()->RemoveObserver(this);
    137   PrepareForUserCloudPolicyManagerShutdown();
    138 }
    139 
    140 void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
    141   UserCloudPolicyManager* manager = policy_manager();
    142   if (manager && manager->core()->client())
    143     manager->core()->client()->RemoveObserver(this);
    144   if (manager && manager->core()->service())
    145     manager->core()->service()->RemoveObserver(this);
    146 }
    147 
    148 scoped_ptr<CloudPolicyClient>
    149 UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
    150     const std::string& username) {
    151   DCHECK(!username.empty());
    152   // We should not be called with a client already initialized.
    153 #if !defined(OS_IOS)
    154   // On iOS we check if an account has policy while the profile is signed in
    155   // to another account.
    156   DCHECK(!policy_manager() || !policy_manager()->core()->client());
    157 #endif
    158 
    159   // If the user should not get policy, just bail out.
    160   if (!policy_manager() || !ShouldLoadPolicyForUser(username)) {
    161     DVLOG(1) << "Signed in user is not in the whitelist";
    162     return scoped_ptr<CloudPolicyClient>();
    163   }
    164 
    165   // If the DeviceManagementService is not yet initialized, start it up now.
    166   device_management_service_->ScheduleInitialization(0);
    167 
    168   // Create a new CloudPolicyClient for fetching the DMToken.
    169   return UserCloudPolicyManager::CreateCloudPolicyClient(
    170       device_management_service_, CreateSystemRequestContext());
    171 }
    172 
    173 bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
    174     const std::string& username) {
    175   if (username.empty())
    176     return false;  // Not signed in.
    177 
    178   return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
    179 }
    180 
    181 void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile* profile) {
    182   // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
    183   // skip initialization.
    184   if (!policy_manager() || !signin_manager()) {
    185     DVLOG(1) << "Skipping initialization for tests due to missing components.";
    186     return;
    187   }
    188 
    189   // Shutdown the UserCloudPolicyManager when the user signs out. We start
    190   // observing the SigninManager here because we don't want to get signout
    191   // notifications until after the profile has started initializing
    192   // (http://crbug.com/316229).
    193   signin_manager()->AddObserver(this);
    194 
    195   std::string username = signin_manager()->GetAuthenticatedUsername();
    196   if (username.empty())
    197     ShutdownUserCloudPolicyManager();
    198   else
    199     InitializeForSignedInUser(username, profile->GetRequestContext());
    200 }
    201 
    202 void UserPolicySigninServiceBase::InitializeForSignedInUser(
    203     const std::string& username,
    204     scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
    205   DCHECK(!username.empty());
    206   if (!ShouldLoadPolicyForUser(username)) {
    207     DVLOG(1) << "Policy load not enabled for user: " << username;
    208     return;
    209   }
    210 
    211   UserCloudPolicyManager* manager = policy_manager();
    212   // Initialize the UCPM if it is not already initialized.
    213   if (!manager->core()->service()) {
    214     // If there is no cached DMToken then we can detect this when the
    215     // OnInitializationCompleted() callback is invoked and this will
    216     // initiate a policy fetch.
    217     InitializeUserCloudPolicyManager(
    218         username,
    219         UserCloudPolicyManager::CreateCloudPolicyClient(
    220             device_management_service_,
    221             CreateUserRequestContext(profile_request_context)).Pass());
    222   } else {
    223     manager->SetSigninUsername(username);
    224   }
    225 
    226   // If the CloudPolicyService is initialized, kick off registration.
    227   // Otherwise OnInitializationCompleted is invoked as soon as the service
    228   // finishes its initialization.
    229   if (manager->core()->service()->IsInitializationComplete())
    230     OnInitializationCompleted(manager->core()->service());
    231 }
    232 
    233 void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
    234     const std::string& username,
    235     scoped_ptr<CloudPolicyClient> client) {
    236   DCHECK(client);
    237   UserCloudPolicyManager* manager = policy_manager();
    238   manager->SetSigninUsername(username);
    239   DCHECK(!manager->core()->client());
    240   scoped_refptr<net::URLRequestContextGetter> context =
    241       client->GetRequestContext();
    242   manager->Connect(local_state_, context, client.Pass());
    243   DCHECK(manager->core()->service());
    244 
    245   // Observe the client to detect errors fetching policy.
    246   manager->core()->client()->AddObserver(this);
    247   // Observe the service to determine when it's initialized.
    248   manager->core()->service()->AddObserver(this);
    249 }
    250 
    251 void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
    252   PrepareForUserCloudPolicyManagerShutdown();
    253   UserCloudPolicyManager* manager = policy_manager();
    254   if (manager)
    255     manager->DisconnectAndRemovePolicy();
    256 }
    257 
    258 scoped_refptr<net::URLRequestContextGetter>
    259 UserPolicySigninServiceBase::CreateSystemRequestContext() {
    260   return new SystemPolicyRequestContext(
    261       system_request_context(), GetUserAgent());
    262 }
    263 
    264 scoped_refptr<net::URLRequestContextGetter>
    265 UserPolicySigninServiceBase::CreateUserRequestContext(
    266     scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
    267   return new UserPolicyRequestContext(
    268       profile_request_context, system_request_context(), GetUserAgent());
    269 }
    270 
    271 }  // namespace policy
    272