// 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/policy/cloud/cloud_policy_manager.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/policy/cloud/cloud_policy_service.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_switches.h"
#include "net/url_request/url_request_context_getter.h"

#if !defined(OS_ANDROID) && !defined(OS_IOS)
#include "chrome/browser/policy/cloud/resource_cache.h"
#endif

namespace policy {

CloudPolicyManager::CloudPolicyManager(
    const PolicyNamespaceKey& policy_ns_key,
    CloudPolicyStore* cloud_policy_store,
    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
    const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
    : core_(policy_ns_key, cloud_policy_store, task_runner),
      waiting_for_policy_refresh_(false),
      file_task_runner_(file_task_runner),
      io_task_runner_(io_task_runner) {
  store()->AddObserver(this);

  // If the underlying store is already initialized, publish the loaded
  // policy. Otherwise, request a load now.
  if (store()->is_initialized())
    CheckAndPublishPolicy();
  else
    store()->Load();
}

CloudPolicyManager::~CloudPolicyManager() {}

void CloudPolicyManager::Shutdown() {
  component_policy_service_.reset();
  core_.Disconnect();
  store()->RemoveObserver(this);
  ConfigurationPolicyProvider::Shutdown();
}

bool CloudPolicyManager::IsInitializationComplete(PolicyDomain domain) const {
  if (domain == POLICY_DOMAIN_CHROME)
    return store()->is_initialized();
  if (ComponentCloudPolicyService::SupportsDomain(domain) &&
      component_policy_service_) {
    return component_policy_service_->is_initialized();
  }
  return true;
}

void CloudPolicyManager::RefreshPolicies() {
  if (service()) {
    waiting_for_policy_refresh_ = true;
    service()->RefreshPolicy(
        base::Bind(&CloudPolicyManager::OnRefreshComplete,
                   base::Unretained(this)));
  } else {
    OnRefreshComplete(false);
  }
}

void CloudPolicyManager::OnStoreLoaded(CloudPolicyStore* cloud_policy_store) {
  DCHECK_EQ(store(), cloud_policy_store);
  CheckAndPublishPolicy();
}

void CloudPolicyManager::OnStoreError(CloudPolicyStore* cloud_policy_store) {
  DCHECK_EQ(store(), cloud_policy_store);
  // Publish policy (even though it hasn't changed) in order to signal load
  // complete on the ConfigurationPolicyProvider interface. Technically, this
  // is only required on the first load, but doesn't hurt in any case.
  CheckAndPublishPolicy();
}

void CloudPolicyManager::OnComponentCloudPolicyUpdated() {
  CheckAndPublishPolicy();
}

void CloudPolicyManager::CheckAndPublishPolicy() {
  if (IsInitializationComplete(POLICY_DOMAIN_CHROME) &&
      !waiting_for_policy_refresh_) {
    scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
    bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
        .CopyFrom(store()->policy_map());
    if (component_policy_service_)
      bundle->MergeFrom(component_policy_service_->policy());
    UpdatePolicy(bundle.Pass());
  }
}

void CloudPolicyManager::CreateComponentCloudPolicyService(
    const base::FilePath& policy_cache_path,
    const scoped_refptr<net::URLRequestContextGetter>& request_context) {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
  // Init() must have been called.
  DCHECK(schema_registry());
  // Called at most once.
  DCHECK(!component_policy_service_);

  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableComponentCloudPolicy) ||
      policy_cache_path.empty()) {
    return;
  }

  // TODO(joaodasilva): Move the |file_task_runner_| to the blocking pool.
  // Currently it's not possible because the ComponentCloudPolicyStore is
  // NonThreadSafe and doesn't support getting calls from different threads.
  scoped_ptr<ResourceCache> resource_cache(
      new ResourceCache(policy_cache_path, file_task_runner_));
  component_policy_service_.reset(new ComponentCloudPolicyService(
      this,
      schema_registry(),
      core(),
      resource_cache.Pass(),
      request_context,
      file_task_runner_,
      io_task_runner_));
#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
}

void CloudPolicyManager::OnRefreshComplete(bool success) {
  waiting_for_policy_refresh_ = false;
  CheckAndPublishPolicy();
}

}  // namespace policy
