// 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/chromeos/policy/cloud_external_data_policy_observer.h"

#include <set>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/settings/cros_settings_names.h"
#include "chromeos/settings/cros_settings_provider.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"

namespace policy {

// Helper class that observes a policy for a logged-in user, notifying the
// |parent_| whenever the external data reference for this user changes.
class CloudExternalDataPolicyObserver::PolicyServiceObserver
    : public PolicyService::Observer {
 public:
  PolicyServiceObserver(CloudExternalDataPolicyObserver* parent,
                        const std::string& user_id,
                        PolicyService* policy_service);
  virtual ~PolicyServiceObserver();

  // PolicyService::Observer:
  virtual void OnPolicyUpdated(const PolicyNamespace& ns,
                               const PolicyMap& previous,
                               const PolicyMap& current) OVERRIDE;

 private:
  CloudExternalDataPolicyObserver* parent_;
  const std::string user_id_;
  PolicyService* policy_service_;

  DISALLOW_COPY_AND_ASSIGN(PolicyServiceObserver);
};

CloudExternalDataPolicyObserver::PolicyServiceObserver::PolicyServiceObserver(
    CloudExternalDataPolicyObserver* parent,
    const std::string& user_id,
    PolicyService* policy_service)
    : parent_(parent),
      user_id_(user_id),
      policy_service_(policy_service) {
  policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this);

  if (!IsDeviceLocalAccountUser(user_id, NULL)) {
    // Notify |parent_| if the external data reference for |user_id_| is set
    // during login. This is omitted for device-local accounts because their
    // policy is available before login and the external data reference will
    // have been seen by the |parent_| already.
    const PolicyMap::Entry* entry = policy_service_->GetPolicies(
        PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
            .Get(parent_->policy_);
    if (entry)
      parent_->HandleExternalDataPolicyUpdate(user_id_, entry);
  }
}

CloudExternalDataPolicyObserver::PolicyServiceObserver::
    ~PolicyServiceObserver() {
  policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this);
}

void CloudExternalDataPolicyObserver::PolicyServiceObserver::OnPolicyUpdated(
    const PolicyNamespace& ns,
    const PolicyMap& previous,
    const PolicyMap& current) {
  DCHECK(ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));

  const PolicyMap::Entry* previous_entry = previous.Get(parent_->policy_);
  const PolicyMap::Entry* current_entry = current.Get(parent_->policy_);
  if ((!previous_entry && current_entry) ||
      (previous_entry && !current_entry) ||
      (previous_entry && current_entry &&
           !previous_entry->Equals(*current_entry))) {
    // Notify |parent_| if the external data reference for |user_id_| has
    // changed.
    parent_->HandleExternalDataPolicyUpdate(user_id_, current_entry);
  }
}

void CloudExternalDataPolicyObserver::Delegate::OnExternalDataSet(
    const std::string& policy,
    const std::string& user_id) {
}

void CloudExternalDataPolicyObserver::Delegate::OnExternalDataCleared(
    const std::string& policy,
    const std::string& user_id) {
}

void CloudExternalDataPolicyObserver::Delegate::OnExternalDataFetched(
    const std::string& policy,
    const std::string& user_id,
    scoped_ptr<std::string> data) {
}

CloudExternalDataPolicyObserver::Delegate::~Delegate() {
}

CloudExternalDataPolicyObserver::CloudExternalDataPolicyObserver(
    chromeos::CrosSettings* cros_settings,
    DeviceLocalAccountPolicyService* device_local_account_policy_service,
    const std::string& policy,
    Delegate* delegate)
    : cros_settings_(cros_settings),
      device_local_account_policy_service_(device_local_account_policy_service),
      policy_(policy),
      delegate_(delegate),
      weak_factory_(this) {
  notification_registrar_.Add(
      this,
      chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
      content::NotificationService::AllSources());

  if (device_local_account_policy_service_)
    device_local_account_policy_service_->AddObserver(this);

  device_local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
      chromeos::kAccountsPrefDeviceLocalAccounts,
      base::Bind(&CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
                 base::Unretained(this)));
}

CloudExternalDataPolicyObserver::~CloudExternalDataPolicyObserver() {
  if (device_local_account_policy_service_)
    device_local_account_policy_service_->RemoveObserver(this);
  for (DeviceLocalAccountEntryMap::iterator it =
           device_local_account_entries_.begin();
       it != device_local_account_entries_.end(); ++it) {
    it->second.DeleteOwnedMembers();
  }
  device_local_account_entries_.clear();
}

void CloudExternalDataPolicyObserver::Init() {
  RetrieveDeviceLocalAccounts();
}

void CloudExternalDataPolicyObserver::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (type != chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
    NOTREACHED();
    return;
  }
  Profile* profile = content::Details<Profile>(details).ptr();

  const chromeos::User* user =
      chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
  if (!user) {
    NOTREACHED();
    return;
  }

  const std::string& user_id = user->email();
  if (ContainsKey(logged_in_user_observers_, user_id)) {
    NOTREACHED();
    return;
  }

  ProfilePolicyConnector* policy_connector =
      ProfilePolicyConnectorFactory::GetForProfile(profile);
  logged_in_user_observers_[user_id] = make_linked_ptr(
      new PolicyServiceObserver(this,
                                user_id,
                                policy_connector->policy_service()));
}

void CloudExternalDataPolicyObserver::OnPolicyUpdated(
    const std::string& user_id) {
  if (ContainsKey(logged_in_user_observers_, user_id)) {
    // When a device-local account is logged in, a policy change triggers both
    // OnPolicyUpdated() and PolicyServiceObserver::OnPolicyUpdated(). Ignore
    // the former so that the policy change is handled only once.
    return;
  }

  if (!device_local_account_policy_service_) {
    NOTREACHED();
    return;
  }
  DeviceLocalAccountPolicyBroker* broker =
      device_local_account_policy_service_->GetBrokerForUser(user_id);
  if (!broker) {
    // The order in which |this| and the |device_local_account_policy_service_|
    // find out that a new device-local account has been added is undefined. If
    // no |broker| exists yet, the |device_local_account_policy_service_| must
    // not have seen the new |user_id| yet. OnPolicyUpdated() will be invoked
    // again by the |device_local_account_policy_service_| in this case when it
    // finds out about |user_id| and creates a |broker| for it.
    return;
  }

  const PolicyMap::Entry* entry =
      broker->core()->store()->policy_map().Get(policy_);
  if (!entry) {
    DeviceLocalAccountEntryMap::iterator it =
        device_local_account_entries_.find(user_id);
    if (it != device_local_account_entries_.end()) {
      it->second.DeleteOwnedMembers();
      device_local_account_entries_.erase(it);
      HandleExternalDataPolicyUpdate(user_id, NULL);
    }
    return;
  }

  PolicyMap::Entry& map_entry = device_local_account_entries_[user_id];
  if (map_entry.Equals(*entry))
    return;

  map_entry.DeleteOwnedMembers();
  map_entry = *entry->DeepCopy();
  HandleExternalDataPolicyUpdate(user_id, entry);
}

void CloudExternalDataPolicyObserver::OnDeviceLocalAccountsChanged() {
  // No action needed here, changes to the list of device-local accounts get
  // handled via the kAccountsPrefDeviceLocalAccounts device setting observer.
}

void CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts() {
  // Schedule a callback if device policy has not yet been verified.
  if (chromeos::CrosSettingsProvider::TRUSTED !=
      cros_settings_->PrepareTrustedValues(base::Bind(
          &CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
          weak_factory_.GetWeakPtr()))) {
    return;
  }

  std::vector<DeviceLocalAccount> device_local_account_list =
      policy::GetDeviceLocalAccounts(cros_settings_);
  std::set<std::string> device_local_accounts;
  for (std::vector<DeviceLocalAccount>::const_iterator it =
           device_local_account_list.begin();
       it != device_local_account_list.end(); ++it) {
    device_local_accounts.insert(it->user_id);
  }

  for (DeviceLocalAccountEntryMap::iterator it =
           device_local_account_entries_.begin();
       it != device_local_account_entries_.end(); ) {
    if (!ContainsKey(device_local_accounts, it->first)) {
      const std::string user_id = it->first;
      it->second.DeleteOwnedMembers();
      device_local_account_entries_.erase(it++);
      // When a device-local account whose external data reference was set is
      // removed, emit a notification that the external data reference has been
      // cleared.
      HandleExternalDataPolicyUpdate(user_id, NULL);
    } else {
      ++it;
    }
  }

  for (std::set<std::string>::const_iterator it = device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    OnPolicyUpdated(*it);
  }
}

void CloudExternalDataPolicyObserver::HandleExternalDataPolicyUpdate(
    const std::string& user_id,
    const PolicyMap::Entry* entry) {
  if (!entry) {
    delegate_->OnExternalDataCleared(policy_, user_id);
    fetch_weak_ptrs_.erase(user_id);
    return;
  }

  delegate_->OnExternalDataSet(policy_, user_id);

  linked_ptr<WeakPtrFactory>& weak_ptr_factory = fetch_weak_ptrs_[user_id];
  weak_ptr_factory.reset(new WeakPtrFactory(this));
  if (entry->external_data_fetcher) {
    entry->external_data_fetcher->Fetch(base::Bind(
        &CloudExternalDataPolicyObserver::OnExternalDataFetched,
        weak_ptr_factory->GetWeakPtr(),
        user_id));
  } else {
    NOTREACHED();
  }
}

void CloudExternalDataPolicyObserver::OnExternalDataFetched(
    const std::string& user_id,
    scoped_ptr<std::string> data) {
  FetchWeakPtrMap::iterator it = fetch_weak_ptrs_.find(user_id);
  DCHECK(it != fetch_weak_ptrs_.end());
  fetch_weak_ptrs_.erase(it);
  delegate_->OnExternalDataFetched(policy_, user_id, data.Pass());
}

}  // namespace policy
