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