// Copyright (c) 2012 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/chromeos/policy/device_local_account_policy_service.h"

#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/policy/affiliated_cloud_policy_invalidator.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_external_data_service.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/common/chrome_content_client.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/settings/cros_settings_names.h"
#include "chromeos/settings/cros_settings_provider.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/core/common/cloud/resource_cache.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/policy/policy_constants.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"

namespace em = enterprise_management;

namespace policy {

namespace {

// Device local accounts are always affiliated.
std::string GetDeviceDMToken(
    chromeos::DeviceSettingsService* device_settings_service,
    const std::vector<std::string>& user_affiliation_ids) {
  return device_settings_service->policy_data()->request_token();
}

// Creates and initializes a cloud policy client. Returns nullptr if the device
// doesn't have credentials in device settings (i.e. is not
// enterprise-enrolled).
std::unique_ptr<CloudPolicyClient> CreateClient(
    chromeos::DeviceSettingsService* device_settings_service,
    DeviceManagementService* device_management_service,
    scoped_refptr<net::URLRequestContextGetter> system_request_context) {
  const em::PolicyData* policy_data = device_settings_service->policy_data();
  if (!policy_data ||
      !policy_data->has_request_token() ||
      !policy_data->has_device_id() ||
      !device_management_service) {
    return std::unique_ptr<CloudPolicyClient>();
  }

  std::unique_ptr<CloudPolicyClient> client =
      std::make_unique<CloudPolicyClient>(
          std::string() /* machine_id */, std::string() /* machine_model */,
          std::string() /* brand_code */, device_management_service,
          system_request_context, nullptr /* signing_service */,
          base::BindRepeating(&GetDeviceDMToken, device_settings_service));
  std::vector<std::string> user_affiliation_ids(
      policy_data->user_affiliation_ids().begin(),
      policy_data->user_affiliation_ids().end());
  client->SetupRegistration(policy_data->request_token(),
                            policy_data->device_id(), user_affiliation_ids);
  return client;
}

// Get the subdirectory of the force-installed extension cache and the component
// policy cache used for |account_id|.
std::string GetCacheSubdirectoryForAccountID(const std::string& account_id) {
  return base::HexEncode(account_id.c_str(), account_id.size());
}

// Cleans up the cache directory by removing subdirectories that are not found
// in |subdirectories_to_keep|. Only caches whose cache directory is found in
// |subdirectories_to_keep| may be running while the clean-up is in progress.
void DeleteOrphanedCaches(
    const base::FilePath& cache_root_dir,
    const std::set<std::string>& subdirectories_to_keep) {
  base::FileEnumerator enumerator(cache_root_dir,
                                  false,
                                  base::FileEnumerator::DIRECTORIES);
  for (base::FilePath path = enumerator.Next(); !path.empty();
       path = enumerator.Next()) {
    const std::string subdirectory(path.BaseName().MaybeAsASCII());
    if (!base::ContainsKey(subdirectories_to_keep, subdirectory))
      base::DeleteFile(path, true);
  }
}

// Removes the subdirectory belonging to |account_id_to_delete| from the cache
// directory. No cache belonging to |account_id_to_delete| may be running while
// the removal is in progress.
void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) {
  base::FilePath cache_root_dir;
  CHECK(base::PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
                               &cache_root_dir));
  const base::FilePath path = cache_root_dir.Append(
      GetCacheSubdirectoryForAccountID(account_id_to_delete));
  if (base::DirectoryExists(path))
    base::DeleteFile(path, true);
}

}  // namespace

DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
    const DeviceLocalAccount& account,
    const base::FilePath& component_policy_cache_path,
    std::unique_ptr<DeviceLocalAccountPolicyStore> store,
    scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager,
    const base::Closure& policy_update_callback,
    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
    const scoped_refptr<base::SequencedTaskRunner>& resource_cache_task_runner,
    AffiliatedInvalidationServiceProvider* invalidation_service_provider)
    : invalidation_service_provider_(invalidation_service_provider),
      account_id_(account.account_id),
      user_id_(account.user_id),
      component_policy_cache_path_(component_policy_cache_path),
      store_(std::move(store)),
      external_data_manager_(external_data_manager),
      core_(dm_protocol::kChromePublicAccountPolicyType,
            store_->account_id(),
            store_.get(),
            task_runner),
      policy_update_callback_(policy_update_callback),
      resource_cache_task_runner_(resource_cache_task_runner) {
  if (account.type != DeviceLocalAccount::TYPE_ARC_KIOSK_APP) {
    extension_tracker_.reset(new DeviceLocalAccountExtensionTracker(
        account, store_.get(), &schema_registry_));
  }
  base::FilePath cache_root_dir;
  CHECK(base::PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
                               &cache_root_dir));
  extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader(
      store_.get(),
      cache_root_dir.Append(
          GetCacheSubdirectoryForAccountID(account.account_id)));
  store_->AddObserver(this);

  // Unblock the |schema_registry_| so that the |component_policy_service_|
  // starts using it.
  schema_registry_.RegisterComponent(
      PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()),
      g_browser_process->browser_policy_connector()->GetChromeSchema());
  schema_registry_.SetAllDomainsReady();
}

DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {
  store_->RemoveObserver(this);
  external_data_manager_->SetPolicyStore(nullptr);
  external_data_manager_->Disconnect();
}

void DeviceLocalAccountPolicyBroker::Initialize() {
  store_->Load();
}

void DeviceLocalAccountPolicyBroker::LoadImmediately() {
  store_->LoadImmediately();
}

bool DeviceLocalAccountPolicyBroker::HasInvalidatorForTest() const {
  return invalidator_ != nullptr;
}

void DeviceLocalAccountPolicyBroker::ConnectIfPossible(
    chromeos::DeviceSettingsService* device_settings_service,
    DeviceManagementService* device_management_service,
    scoped_refptr<net::URLRequestContextGetter> request_context) {
  if (core_.client())
    return;

  std::unique_ptr<CloudPolicyClient> client(CreateClient(
      device_settings_service, device_management_service, request_context));
  if (!client)
    return;

  CreateComponentCloudPolicyService(request_context, client.get());
  core_.Connect(std::move(client));
  external_data_manager_->Connect(request_context);
  core_.StartRefreshScheduler();
  UpdateRefreshDelay();
  invalidator_.reset(new AffiliatedCloudPolicyInvalidator(
      em::DeviceRegisterRequest::DEVICE,
      &core_,
      invalidation_service_provider_));
}

void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
  if (core_.refresh_scheduler()) {
    const base::Value* policy_value =
        store_->policy_map().GetValue(key::kPolicyRefreshRate);
    int delay = 0;
    if (policy_value && policy_value->GetAsInteger(&delay))
      core_.refresh_scheduler()->SetDesiredRefreshDelay(delay);
  }
}

std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
  std::string display_name;
  const base::Value* display_name_value =
      store_->policy_map().GetValue(policy::key::kUserDisplayName);
  if (display_name_value)
    display_name_value->GetAsString(&display_name);
  return display_name;
}

void DeviceLocalAccountPolicyBroker::OnStoreLoaded(CloudPolicyStore* store) {
  UpdateRefreshDelay();
  policy_update_callback_.Run();
}

void DeviceLocalAccountPolicyBroker::OnStoreError(CloudPolicyStore* store) {
  policy_update_callback_.Run();
}

void DeviceLocalAccountPolicyBroker::OnComponentCloudPolicyUpdated() {
  policy_update_callback_.Run();
}

void DeviceLocalAccountPolicyBroker::CreateComponentCloudPolicyService(
    const scoped_refptr<net::URLRequestContextGetter>& request_context,
    CloudPolicyClient* client) {
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableComponentCloudPolicy)) {
    // Disabled via the command line.
    return;
  }

  std::unique_ptr<ResourceCache> resource_cache(new ResourceCache(
      component_policy_cache_path_, resource_cache_task_runner_));

  component_policy_service_.reset(new ComponentCloudPolicyService(
      dm_protocol::kChromeExtensionPolicyType, this, &schema_registry_, core(),
      client, std::move(resource_cache), request_context,
      resource_cache_task_runner_,
      content::BrowserThread::GetTaskRunnerForThread(
          content::BrowserThread::IO)));
}

DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
    chromeos::SessionManagerClient* session_manager_client,
    chromeos::DeviceSettingsService* device_settings_service,
    chromeos::CrosSettings* cros_settings,
    AffiliatedInvalidationServiceProvider* invalidation_service_provider,
    scoped_refptr<base::SequencedTaskRunner> store_background_task_runner,
    scoped_refptr<base::SequencedTaskRunner> extension_cache_task_runner,
    scoped_refptr<base::SequencedTaskRunner>
        external_data_service_backend_task_runner,
    scoped_refptr<base::SequencedTaskRunner> io_task_runner,
    scoped_refptr<net::URLRequestContextGetter> request_context)
    : session_manager_client_(session_manager_client),
      device_settings_service_(device_settings_service),
      cros_settings_(cros_settings),
      invalidation_service_provider_(invalidation_service_provider),
      device_management_service_(nullptr),
      waiting_for_cros_settings_(false),
      orphan_extension_cache_deletion_state_(NOT_STARTED),
      store_background_task_runner_(store_background_task_runner),
      extension_cache_task_runner_(extension_cache_task_runner),
      resource_cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
          {base::MayBlock(), base::TaskPriority::BACKGROUND})),
      request_context_(request_context),
      local_accounts_subscription_(cros_settings_->AddSettingsObserver(
          chromeos::kAccountsPrefDeviceLocalAccounts,
          base::Bind(
              &DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending,
              base::Unretained(this)))),
      weak_factory_(this) {
  CHECK(base::PathService::Get(
      chromeos::DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY,
      &component_policy_cache_root_));
  external_data_service_.reset(new DeviceLocalAccountExternalDataService(
      this,
      external_data_service_backend_task_runner,
      io_task_runner));
  UpdateAccountList();
}

DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
  DCHECK(!request_context_.get());
  DCHECK(policy_brokers_.empty());
}

void DeviceLocalAccountPolicyService::Shutdown() {
  device_management_service_ = nullptr;
  request_context_ = nullptr;
  DeleteBrokers(&policy_brokers_);
}

void DeviceLocalAccountPolicyService::Connect(
    DeviceManagementService* device_management_service) {
  DCHECK(!device_management_service_);
  device_management_service_ = device_management_service;

  // Connect the brokers.
  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
       it != policy_brokers_.end(); ++it) {
    it->second->ConnectIfPossible(device_settings_service_,
                                  device_management_service_,
                                  request_context_);
  }
}

DeviceLocalAccountPolicyBroker*
    DeviceLocalAccountPolicyService::GetBrokerForUser(
        const std::string& user_id) {
  PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
  if (entry == policy_brokers_.end())
    return nullptr;

  return entry->second;
}

bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
    const std::string& user_id) {
  DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
  return broker && broker->core()->store()->is_managed();
}

void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool DeviceLocalAccountPolicyService::IsExtensionCacheDirectoryBusy(
    const std::string& account_id) {
  return busy_extension_cache_directories_.find(account_id) !=
            busy_extension_cache_directories_.end();
}

void DeviceLocalAccountPolicyService::StartExtensionCachesIfPossible() {
  for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
       it != policy_brokers_.end(); ++it) {
    if (!it->second->extension_loader()->IsCacheRunning() &&
        !IsExtensionCacheDirectoryBusy(it->second->account_id())) {
      it->second->extension_loader()->StartCache(extension_cache_task_runner_);
    }
  }
}

bool DeviceLocalAccountPolicyService::StartExtensionCacheForAccountIfPresent(
    const std::string& account_id) {
  for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
       it != policy_brokers_.end(); ++it) {
    if (it->second->account_id() == account_id) {
      DCHECK(!it->second->extension_loader()->IsCacheRunning());
      it->second->extension_loader()->StartCache(extension_cache_task_runner_);
      return true;
    }
  }
  return false;
}

void DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted() {
  DCHECK_EQ(IN_PROGRESS, orphan_extension_cache_deletion_state_);

  orphan_extension_cache_deletion_state_ = DONE;
  StartExtensionCachesIfPossible();
}

void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown(
    const std::string& account_id) {
  DCHECK_NE(NOT_STARTED, orphan_extension_cache_deletion_state_);
  DCHECK(IsExtensionCacheDirectoryBusy(account_id));

  // The account with |account_id| was deleted and the broker for it has shut
  // down completely.

  if (StartExtensionCacheForAccountIfPresent(account_id)) {
    // If another account with the same ID was created in the meantime, its
    // extension cache is started, reusing the cache directory. The directory no
    // longer needs to be marked as busy in this case.
    busy_extension_cache_directories_.erase(account_id);
    return;
  }

  // If no account with |account_id| exists anymore, the cache directory should
  // be removed. The directory must stay marked as busy while the removal is in
  // progress.
  extension_cache_task_runner_->PostTaskAndReply(
      FROM_HERE, base::BindOnce(&DeleteObsoleteExtensionCache, account_id),
      base::BindOnce(
          &DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheDeleted,
          weak_factory_.GetWeakPtr(), account_id));
}

void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheDeleted(
    const std::string& account_id) {
  DCHECK_EQ(DONE, orphan_extension_cache_deletion_state_);
  DCHECK(IsExtensionCacheDirectoryBusy(account_id));

  // The cache directory for |account_id| has been deleted. The directory no
  // longer needs to be marked as busy.
  busy_extension_cache_directories_.erase(account_id);

  // If another account with the same ID was created in the meantime, start its
  // extension cache, creating a new cache directory.
  StartExtensionCacheForAccountIfPresent(account_id);
}

void DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending() {
  // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
  // pending (because the |cros_settings_| are not trusted yet), the updated
  // account list will be processed by that call when it eventually runs.
  if (!waiting_for_cros_settings_)
    UpdateAccountList();
}

void DeviceLocalAccountPolicyService::UpdateAccountList() {
  chromeos::CrosSettingsProvider::TrustedStatus status =
      cros_settings_->PrepareTrustedValues(
          base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
                     weak_factory_.GetWeakPtr()));
  switch (status) {
    case chromeos::CrosSettingsProvider::TRUSTED:
      waiting_for_cros_settings_ = false;
      break;
    case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
      waiting_for_cros_settings_ = true;
      // Purposely break to allow initialization with temporarily untrusted
      // settings so that a crash-n-restart public session have its loader
      // properly registered as ExtensionService's external provider.
      break;
    case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
      waiting_for_cros_settings_ = false;
      return;
  }

  // Update |policy_brokers_|, keeping existing entries.
  PolicyBrokerMap old_policy_brokers;
  policy_brokers_.swap(old_policy_brokers);
  std::set<std::string> subdirectories_to_keep;
  const std::vector<DeviceLocalAccount> device_local_accounts =
      GetDeviceLocalAccounts(cros_settings_);
  for (std::vector<DeviceLocalAccount>::const_iterator it =
           device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    PolicyBrokerMap::iterator broker_it = old_policy_brokers.find(it->user_id);

    std::unique_ptr<DeviceLocalAccountPolicyBroker> broker;
    bool broker_initialized = false;
    if (broker_it != old_policy_brokers.end()) {
      // Reuse the existing broker if present.
      broker.reset(broker_it->second);
      old_policy_brokers.erase(broker_it);
      broker_initialized = true;
    } else {
      std::unique_ptr<DeviceLocalAccountPolicyStore> store(
          new DeviceLocalAccountPolicyStore(
              it->account_id, session_manager_client_, device_settings_service_,
              store_background_task_runner_));
      scoped_refptr<DeviceLocalAccountExternalDataManager>
          external_data_manager =
              external_data_service_->GetExternalDataManager(it->account_id,
                                                             store.get());
      broker.reset(new DeviceLocalAccountPolicyBroker(
          *it,
          component_policy_cache_root_.Append(
              GetCacheSubdirectoryForAccountID(it->account_id)),
          std::move(store), external_data_manager,
          base::Bind(&DeviceLocalAccountPolicyService::NotifyPolicyUpdated,
                     base::Unretained(this), it->user_id),
          base::ThreadTaskRunnerHandle::Get(), resource_cache_task_runner_,
          invalidation_service_provider_));
    }

    // Fire up the cloud connection for fetching policy for the account from
    // the cloud if this is an enterprise-managed device.
    broker->ConnectIfPossible(device_settings_service_,
                              device_management_service_,
                              request_context_);

    policy_brokers_[it->user_id] = broker.release();
    if (!broker_initialized) {
      // The broker must be initialized after it has been added to
      // |policy_brokers_|.
      policy_brokers_[it->user_id]->Initialize();
    }

    subdirectories_to_keep.insert(
        GetCacheSubdirectoryForAccountID(it->account_id));
  }

  if (orphan_extension_cache_deletion_state_ == NOT_STARTED) {
    DCHECK(old_policy_brokers.empty());
    DCHECK(busy_extension_cache_directories_.empty());

    // If this method is running for the first time, no extension caches have
    // been started yet. Take this opportunity to do a clean-up by removing
    // orphaned cache directories not found in |subdirectories_to_keep| from the
    // cache directory.
    orphan_extension_cache_deletion_state_ = IN_PROGRESS;

    base::FilePath cache_root_dir;
    CHECK(base::PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
                                 &cache_root_dir));
    extension_cache_task_runner_->PostTaskAndReply(
        FROM_HERE,
        base::BindOnce(&DeleteOrphanedCaches, cache_root_dir,
                       subdirectories_to_keep),
        base::BindOnce(
            &DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted,
            weak_factory_.GetWeakPtr()));

    // Start the extension caches for all brokers. These belong to accounts in
    // |account_ids| and are not affected by the clean-up.
    StartExtensionCachesIfPossible();
  } else {
    // If this method has run before, obsolete brokers may exist. Shut down
    // their extension caches and delete the brokers.
    DeleteBrokers(&old_policy_brokers);

    if (orphan_extension_cache_deletion_state_ == DONE) {
      // If the initial clean-up of orphaned cache directories has been
      // complete, start any extension caches that are not running yet but can
      // be started now because their cache directories are not busy.
      StartExtensionCachesIfPossible();
    }
  }

  // Purge the component policy caches of any accounts that have been removed.
  // Do this only after any obsolete brokers have been destroyed. This races
  // with ComponentCloudPolicyStore so make sure they both run on the same task
  // runner.
  resource_cache_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DeleteOrphanedCaches, component_policy_cache_root_,
                     subdirectories_to_keep));

  for (auto& observer : observers_)
    observer.OnDeviceLocalAccountsChanged();
}

void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
  for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it) {
    scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader>
        extension_loader = it->second->extension_loader();
    if (extension_loader->IsCacheRunning()) {
      DCHECK(!IsExtensionCacheDirectoryBusy(it->second->account_id()));
      busy_extension_cache_directories_.insert(it->second->account_id());
      extension_loader->StopCache(base::Bind(
          &DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown,
          weak_factory_.GetWeakPtr(),
          it->second->account_id()));
    }

    delete it->second;
  }
  map->clear();
}

void DeviceLocalAccountPolicyService::NotifyPolicyUpdated(
    const std::string& user_id) {
  for (auto& observer : observers_)
    observer.OnPolicyUpdated(user_id);
}

}  // namespace policy
