root/chrome/browser/policy/cloud/user_policy_signin_service_base.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_factory_
  2. FetchPolicyForSignedInUser
  3. GoogleSignedOut
  4. Observe
  5. OnInitializationCompleted
  6. OnPolicyFetched
  7. OnRegistrationStateChanged
  8. OnClientError
  9. Shutdown
  10. PrepareForUserCloudPolicyManagerShutdown
  11. CreateClientForRegistrationOnly
  12. ShouldLoadPolicyForUser
  13. InitializeOnProfileReady
  14. InitializeForSignedInUser
  15. InitializeUserCloudPolicyManager
  16. ShutdownUserCloudPolicyManager
  17. CreateSystemRequestContext
  18. CreateUserRequestContext

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/cloud/user_policy_signin_service_base.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_switches.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/core/common/cloud/system_policy_request_context.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/policy/core/common/cloud/user_policy_request_context.h"
#include "components/signin/core/browser/signin_manager.h"
#include "content/public/browser/notification_source.h"
#include "net/url_request/url_request_context_getter.h"

namespace policy {

UserPolicySigninServiceBase::UserPolicySigninServiceBase(
    Profile* profile,
    PrefService* local_state,
    DeviceManagementService* device_management_service,
    UserCloudPolicyManager* policy_manager,
    SigninManager* signin_manager,
    scoped_refptr<net::URLRequestContextGetter> system_request_context)
    : policy_manager_(policy_manager),
      signin_manager_(signin_manager),
      local_state_(local_state),
      device_management_service_(device_management_service),
      system_request_context_(system_request_context),
      weak_factory_(this) {
  // Register a listener to be called back once the current profile has finished
  // initializing, so we can startup/shutdown the UserCloudPolicyManager.
  registrar_.Add(this,
                 chrome::NOTIFICATION_PROFILE_ADDED,
                 content::Source<Profile>(profile));
}

UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}

void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
    const std::string& username,
    const std::string& dm_token,
    const std::string& client_id,
    scoped_refptr<net::URLRequestContextGetter> profile_request_context,
    const PolicyFetchCallback& callback) {
  scoped_ptr<CloudPolicyClient> client(
      UserCloudPolicyManager::CreateCloudPolicyClient(
          device_management_service_,
          CreateUserRequestContext(profile_request_context)).Pass());
  client->SetupRegistration(dm_token, client_id);
  DCHECK(client->is_registered());
  // The user has just signed in, so the UserCloudPolicyManager should not yet
  // be initialized. This routine will initialize the UserCloudPolicyManager
  // with the passed client and will proactively ask the client to fetch
  // policy without waiting for the CloudPolicyService to finish initialization.
  UserCloudPolicyManager* manager = policy_manager();
  DCHECK(manager);
  DCHECK(!manager->core()->client());
  InitializeUserCloudPolicyManager(username, client.Pass());
  DCHECK(manager->IsClientRegistered());

  // Now initiate a policy fetch.
  manager->core()->service()->RefreshPolicy(callback);
}

void UserPolicySigninServiceBase::GoogleSignedOut(const std::string& username) {
  ShutdownUserCloudPolicyManager();
}

void UserPolicySigninServiceBase::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  switch (type) {
    case chrome::NOTIFICATION_PROFILE_ADDED:
      // A new profile has been loaded - if it's signed in, then initialize the
      // UCPM, otherwise shut down the UCPM (which deletes any cached policy
      // data). This must be done here instead of at constructor time because
      // the Profile is not fully initialized when this object is constructed
      // (DoFinalInit() has not yet been called, so ProfileIOData and
      // SSLConfigServiceManager have not been created yet).
      // TODO(atwilson): Switch to using a timer instead, to avoid contention
      // with other services at startup (http://crbug.com/165468).
      InitializeOnProfileReady(content::Source<Profile>(source).ptr());
      break;
    default:
      NOTREACHED();
  }
}

void UserPolicySigninServiceBase::OnInitializationCompleted(
    CloudPolicyService* service) {
  // This is meant to be overridden by subclasses. Starting and stopping to
  // observe the CloudPolicyService from this base class avoids the need for
  // more virtuals.
}

void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}

void UserPolicySigninServiceBase::OnRegistrationStateChanged(
    CloudPolicyClient* client) {}

void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
  if (client->is_registered()) {
    // If the client is already registered, it means this error must have
    // come from a policy fetch.
    if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
      // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
      // trigger to revert to "unmanaged" mode (we will check for management
      // being re-enabled on the next restart and/or login).
      DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";

      // Can't shutdown now because we're in the middle of a callback from
      // the CloudPolicyClient, so queue up a task to do the shutdown.
      base::MessageLoop::current()->PostTask(
          FROM_HERE,
          base::Bind(
              &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
              weak_factory_.GetWeakPtr()));
    } else {
      DVLOG(1) << "Error fetching policy: " << client->status();
    }
  }
}

void UserPolicySigninServiceBase::Shutdown() {
  if (signin_manager())
    signin_manager()->RemoveObserver(this);
  PrepareForUserCloudPolicyManagerShutdown();
}

void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
  UserCloudPolicyManager* manager = policy_manager();
  if (manager && manager->core()->client())
    manager->core()->client()->RemoveObserver(this);
  if (manager && manager->core()->service())
    manager->core()->service()->RemoveObserver(this);
}

scoped_ptr<CloudPolicyClient>
UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
    const std::string& username) {
  DCHECK(!username.empty());
  // We should not be called with a client already initialized.
  DCHECK(!policy_manager() || !policy_manager()->core()->client());

  // If the user should not get policy, just bail out.
  if (!policy_manager() || !ShouldLoadPolicyForUser(username)) {
    DVLOG(1) << "Signed in user is not in the whitelist";
    return scoped_ptr<CloudPolicyClient>();
  }

  // If the DeviceManagementService is not yet initialized, start it up now.
  device_management_service_->ScheduleInitialization(0);

  // Create a new CloudPolicyClient for fetching the DMToken.
  return UserCloudPolicyManager::CreateCloudPolicyClient(
      device_management_service_, CreateSystemRequestContext());
}

bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
    const std::string& username) {
  if (username.empty())
    return false;  // Not signed in.

  return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
}

void UserPolicySigninServiceBase::InitializeOnProfileReady(Profile* profile) {
  // If using a TestingProfile with no SigninManager or UserCloudPolicyManager,
  // skip initialization.
  if (!policy_manager() || !signin_manager()) {
    DVLOG(1) << "Skipping initialization for tests due to missing components.";
    return;
  }

  // Shutdown the UserCloudPolicyManager when the user signs out. We start
  // observing the SigninManager here because we don't want to get signout
  // notifications until after the profile has started initializing
  // (http://crbug.com/316229).
  signin_manager()->AddObserver(this);

  std::string username = signin_manager()->GetAuthenticatedUsername();
  if (username.empty())
    ShutdownUserCloudPolicyManager();
  else
    InitializeForSignedInUser(username, profile->GetRequestContext());
}

void UserPolicySigninServiceBase::InitializeForSignedInUser(
    const std::string& username,
    scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
  DCHECK(!username.empty());
  if (!ShouldLoadPolicyForUser(username)) {
    DVLOG(1) << "Policy load not enabled for user: " << username;
    return;
  }

  UserCloudPolicyManager* manager = policy_manager();
  // Initialize the UCPM if it is not already initialized.
  if (!manager->core()->service()) {
    // If there is no cached DMToken then we can detect this when the
    // OnInitializationCompleted() callback is invoked and this will
    // initiate a policy fetch.
    InitializeUserCloudPolicyManager(
        username,
        UserCloudPolicyManager::CreateCloudPolicyClient(
            device_management_service_,
            CreateUserRequestContext(profile_request_context)).Pass());
  } else {
    manager->SetSigninUsername(username);
  }

  // If the CloudPolicyService is initialized, kick off registration.
  // Otherwise OnInitializationCompleted is invoked as soon as the service
  // finishes its initialization.
  if (manager->core()->service()->IsInitializationComplete())
    OnInitializationCompleted(manager->core()->service());
}

void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
    const std::string& username,
    scoped_ptr<CloudPolicyClient> client) {
  DCHECK(client);
  UserCloudPolicyManager* manager = policy_manager();
  manager->SetSigninUsername(username);
  DCHECK(!manager->core()->client());
  scoped_refptr<net::URLRequestContextGetter> context =
      client->GetRequestContext();
  manager->Connect(local_state_, context, client.Pass());
  DCHECK(manager->core()->service());

  // Observe the client to detect errors fetching policy.
  manager->core()->client()->AddObserver(this);
  // Observe the service to determine when it's initialized.
  manager->core()->service()->AddObserver(this);
}

void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
  PrepareForUserCloudPolicyManagerShutdown();
  UserCloudPolicyManager* manager = policy_manager();
  if (manager)
    manager->DisconnectAndRemovePolicy();
}

scoped_refptr<net::URLRequestContextGetter>
UserPolicySigninServiceBase::CreateSystemRequestContext() {
  return new SystemPolicyRequestContext(
      system_request_context(), GetUserAgent());
}

scoped_refptr<net::URLRequestContextGetter>
UserPolicySigninServiceBase::CreateUserRequestContext(
    scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
  return new UserPolicyRequestContext(
      profile_request_context, system_request_context(), GetUserAgent());
}

}  // namespace policy

/* [<][>][^][v][top][bottom][index][help] */