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& username) {
     74   ShutdownUserCloudPolicyManager();
     75 }
     76 
     77 void UserPolicySigninServiceBase::Observe(
     78     int type,
     79     const content::NotificationSource& source,
     80     const content::NotificationDetails& details) {
     81   switch (type) {
     82     case chrome::NOTIFICATION_PROFILE_ADDED:
     83       // A new profile has been loaded - if it's signed in, then initialize the
     84       // UCPM, otherwise shut down the UCPM (which deletes any cached policy
     85       // data). This must be done here instead of at constructor time because
     86       // the Profile is not fully initialized when this object is constructed
     87       // (DoFinalInit() has not yet been called, so ProfileIOData and
     88       // SSLConfigServiceManager have not been created yet).
     89       // TODO(atwilson): Switch to using a timer instead, to avoid contention
     90       // with other services at startup (http://crbug.com/165468).
     91       InitializeOnProfileReady(content::Source<Profile>(source).ptr());
     92       break;
     93     default:
     94       NOTREACHED();
     95   }
     96 }
     97 
     98 void UserPolicySigninServiceBase::OnInitializationCompleted(
     99     CloudPolicyService* service) {
    100   // This is meant to be overridden by subclasses. Starting and stopping to
    101   // observe the CloudPolicyService from this base class avoids the need for
    102   // more virtuals.
    103 }
    104 
    105 void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
    106 
    107 void UserPolicySigninServiceBase::OnRegistrationStateChanged(
    108     CloudPolicyClient* client) {}
    109 
    110 void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
    111   if (client->is_registered()) {
    112     // If the client is already registered, it means this error must have
    113     // come from a policy fetch.
    114     if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
    115       // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
    116       // trigger to revert to "unmanaged" mode (we will check for management
    117       // being re-enabled on the next restart and/or login).
    118       DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
    119 
    120       // Can't shutdown now because we're in the middle of a callback from
    121       // the CloudPolicyClient, so queue up a task to do the shutdown.
    122       base::MessageLoop::current()->PostTask(
    123           FROM_HERE,
    124           base::Bind(
    125               &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
    126               weak_factory_.GetWeakPtr()));
    127     } else {
    128       DVLOG(1) << "Error fetching policy: " << client->status();
    129     }
    130   }
    131 }
    132 
    133 void UserPolicySigninServiceBase::Shutdown() {
    134   if (signin_manager())
    135     signin_manager()->RemoveObserver(this);
    136   PrepareForUserCloudPolicyManagerShutdown();
    137 }
    138 
    139 void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
    140   UserCloudPolicyManager* manager = policy_manager();
    141   if (manager && manager->core()->client())
    142     manager->core()->client()->RemoveObserver(this);
    143   if (manager && manager->core()->service())
    144     manager->core()->service()->RemoveObserver(this);
    145 }
    146 
    147 scoped_ptr<CloudPolicyClient>
    148 UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
    149     const std::string& username) {
    150   DCHECK(!username.empty());
    151   // We should not be called with a client already initialized.
    152 #if !defined(OS_IOS)
    153   // On iOS we check if an account has policy while the profile is signed in
    154   // to another account.
    155   DCHECK(!policy_manager() || !policy_manager()->core()->client());
    156 #endif
    157 
    158   // If the user should not get policy, just bail out.
    159   if (!policy_manager() || !ShouldLoadPolicyForUser(username)) {
    160     DVLOG(1) << "Signed in user is not in the whitelist";
    161     return scoped_ptr<CloudPolicyClient>();
    162   }
    163 
    164   // If the DeviceManagementService is not yet initialized, start it up now.
    165   device_management_service_->ScheduleInitialization(0);
    166 
    167   // Create a new CloudPolicyClient for fetching the DMToken.
    168   return UserCloudPolicyManager::CreateCloudPolicyClient(
    169       device_management_service_, CreateSystemRequestContext());
    170 }
    171 
    172 bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
    173     const std::string& username) {
    174   if (username.empty())
    175     return false;  // Not signed in.
    176 
    177   return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
    178 }
    179 
    180 void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile* profile) {
    181   // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
    182   // skip initialization.
    183   if (!policy_manager() || !signin_manager()) {
    184     DVLOG(1) << "Skipping initialization for tests due to missing components.";
    185     return;
    186   }
    187 
    188   // Shutdown the UserCloudPolicyManager when the user signs out. We start
    189   // observing the SigninManager here because we don't want to get signout
    190   // notifications until after the profile has started initializing
    191   // (http://crbug.com/316229).
    192   signin_manager()->AddObserver(this);
    193 
    194   std::string username = signin_manager()->GetAuthenticatedUsername();
    195   if (username.empty())
    196     ShutdownUserCloudPolicyManager();
    197   else
    198     InitializeForSignedInUser(username, profile->GetRequestContext());
    199 }
    200 
    201 void UserPolicySigninServiceBase::InitializeForSignedInUser(
    202     const std::string& username,
    203     scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
    204   DCHECK(!username.empty());
    205   if (!ShouldLoadPolicyForUser(username)) {
    206     DVLOG(1) << "Policy load not enabled for user: " << username;
    207     return;
    208   }
    209 
    210   UserCloudPolicyManager* manager = policy_manager();
    211   // Initialize the UCPM if it is not already initialized.
    212   if (!manager->core()->service()) {
    213     // If there is no cached DMToken then we can detect this when the
    214     // OnInitializationCompleted() callback is invoked and this will
    215     // initiate a policy fetch.
    216     InitializeUserCloudPolicyManager(
    217         username,
    218         UserCloudPolicyManager::CreateCloudPolicyClient(
    219             device_management_service_,
    220             CreateUserRequestContext(profile_request_context)).Pass());
    221   } else {
    222     manager->SetSigninUsername(username);
    223   }
    224 
    225   // If the CloudPolicyService is initialized, kick off registration.
    226   // Otherwise OnInitializationCompleted is invoked as soon as the service
    227   // finishes its initialization.
    228   if (manager->core()->service()->IsInitializationComplete())
    229     OnInitializationCompleted(manager->core()->service());
    230 }
    231 
    232 void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
    233     const std::string& username,
    234     scoped_ptr<CloudPolicyClient> client) {
    235   DCHECK(client);
    236   UserCloudPolicyManager* manager = policy_manager();
    237   manager->SetSigninUsername(username);
    238   DCHECK(!manager->core()->client());
    239   scoped_refptr<net::URLRequestContextGetter> context =
    240       client->GetRequestContext();
    241   manager->Connect(local_state_, context, client.Pass());
    242   DCHECK(manager->core()->service());
    243 
    244   // Observe the client to detect errors fetching policy.
    245   manager->core()->client()->AddObserver(this);
    246   // Observe the service to determine when it's initialized.
    247   manager->core()->service()->AddObserver(this);
    248 }
    249 
    250 void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
    251   PrepareForUserCloudPolicyManagerShutdown();
    252   UserCloudPolicyManager* manager = policy_manager();
    253   if (manager)
    254     manager->DisconnectAndRemovePolicy();
    255 }
    256 
    257 scoped_refptr<net::URLRequestContextGetter>
    258 UserPolicySigninServiceBase::CreateSystemRequestContext() {
    259   return new SystemPolicyRequestContext(
    260       system_request_context(), GetUserAgent());
    261 }
    262 
    263 scoped_refptr<net::URLRequestContextGetter>
    264 UserPolicySigninServiceBase::CreateUserRequestContext(
    265     scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
    266   return new UserPolicyRequestContext(
    267       profile_request_context, system_request_context(), GetUserAgent());
    268 }
    269 
    270 }  // namespace policy
    271