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