// 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 "chromeos/network/policy_applicator.h"

#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/policy_util.h"
#include "chromeos/network/shill_property_util.h"
#include "components/onc/onc_constants.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

void LogErrorMessage(const tracked_objects::Location& from_where,
                     const std::string& error_name,
                     const std::string& error_message) {
  LOG(ERROR) << from_where.ToString() << ": " << error_message;
}

const base::DictionaryValue* GetByGUID(
    const PolicyApplicator::GuidToPolicyMap& policies,
    const std::string& guid) {
  PolicyApplicator::GuidToPolicyMap::const_iterator it = policies.find(guid);
  if (it == policies.end())
    return NULL;
  return it->second;
}

}  // namespace

PolicyApplicator::PolicyApplicator(
    base::WeakPtr<ConfigurationHandler> handler,
    const NetworkProfile& profile,
    const GuidToPolicyMap& all_policies,
    const base::DictionaryValue& global_network_config,
    std::set<std::string>* modified_policies)
    : handler_(handler), profile_(profile) {
  global_network_config_.MergeDictionary(&global_network_config);
  remaining_policies_.swap(*modified_policies);
  for (GuidToPolicyMap::const_iterator it = all_policies.begin();
       it != all_policies.end(); ++it) {
    all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy()));
  }
}

void PolicyApplicator::Run() {
  DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
      dbus::ObjectPath(profile_.path),
      base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this),
      base::Bind(&LogErrorMessage, FROM_HERE));
}

void PolicyApplicator::GetProfilePropertiesCallback(
    const base::DictionaryValue& profile_properties) {
  if (!handler_) {
    LOG(WARNING) << "Handler destructed during policy application to profile "
                 << profile_.ToDebugString();
    return;
  }

  VLOG(2) << "Received properties for profile " << profile_.ToDebugString();
  const base::ListValue* entries = NULL;
  if (!profile_properties.GetListWithoutPathExpansion(
           shill::kEntriesProperty, &entries)) {
    LOG(ERROR) << "Profile " << profile_.ToDebugString()
               << " doesn't contain the property "
               << shill::kEntriesProperty;
    return;
  }

  for (base::ListValue::const_iterator it = entries->begin();
       it != entries->end(); ++it) {
    std::string entry;
    (*it)->GetAsString(&entry);

    DBusThreadManager::Get()->GetShillProfileClient()->GetEntry(
        dbus::ObjectPath(profile_.path),
        entry,
        base::Bind(&PolicyApplicator::GetEntryCallback, this, entry),
        base::Bind(&LogErrorMessage, FROM_HERE));
  }
}

void PolicyApplicator::GetEntryCallback(
    const std::string& entry,
    const base::DictionaryValue& entry_properties) {
  if (!handler_) {
    LOG(WARNING) << "Handler destructed during policy application to profile "
                 << profile_.ToDebugString();
    return;
  }

  VLOG(2) << "Received properties for entry " << entry << " of profile "
          << profile_.ToDebugString();

  scoped_ptr<base::DictionaryValue> onc_part(
      onc::TranslateShillServiceToONCPart(entry_properties,
                                          &onc::kNetworkWithStateSignature));

  std::string old_guid;
  if (!onc_part->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
                                               &old_guid)) {
    VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
            << " doesn't contain a GUID.";
    // This might be an entry of an older ChromeOS version. Assume it to be
    // unmanaged.
  }

  scoped_ptr<NetworkUIData> ui_data =
      shill_property_util::GetUIDataFromProperties(entry_properties);
  if (!ui_data) {
    VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
            << " contains no or no valid UIData.";
    // This might be an entry of an older ChromeOS version. Assume it to be
    // unmanaged. It's an inconsistency if there is a GUID but no UIData, thus
    // clear the GUID just in case.
    old_guid.clear();
  }

  bool was_managed = !old_guid.empty() && ui_data &&
                     (ui_data->onc_source() ==
                          ::onc::ONC_SOURCE_DEVICE_POLICY ||
                      ui_data->onc_source() == ::onc::ONC_SOURCE_USER_POLICY);

  const base::DictionaryValue* new_policy = NULL;
  if (was_managed) {
    // If we have a GUID that might match a current policy, do a lookup using
    // that GUID at first. In particular this is necessary, as some networks
    // can't be matched to policies by properties (e.g. VPN).
    new_policy = GetByGUID(all_policies_, old_guid);
  }

  if (!new_policy) {
    // If we didn't find a policy by GUID, still a new policy might match.
    new_policy = policy_util::FindMatchingPolicy(all_policies_, *onc_part);
  }

  if (new_policy) {
    std::string new_guid;
    new_policy->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
                                              &new_guid);

    VLOG_IF(1, was_managed && old_guid != new_guid)
        << "Updating configuration previously managed by policy " << old_guid
        << " with new policy " << new_guid << ".";
    VLOG_IF(1, !was_managed) << "Applying policy " << new_guid
                             << " to previously unmanaged "
                             << "configuration.";

    if (old_guid == new_guid &&
        remaining_policies_.find(new_guid) == remaining_policies_.end()) {
      VLOG(1) << "Not updating existing managed configuration with guid "
              << new_guid << " because the policy didn't change.";
    } else {
      const base::DictionaryValue* user_settings =
          ui_data ? ui_data->user_settings() : NULL;
      scoped_ptr<base::DictionaryValue> new_shill_properties =
          policy_util::CreateShillConfiguration(
              profile_, new_guid, new_policy, user_settings);
      // A new policy has to be applied to this profile entry. In order to keep
      // implicit state of Shill like "connected successfully before", keep the
      // entry if a policy is reapplied (e.g. after reboot) or is updated.
      // However, some Shill properties are used to identify the network and
      // cannot be modified after initial configuration, so we have to delete
      // the profile entry in these cases. Also, keeping Shill's state if the
      // SSID changed might not be a good idea anyways. If the policy GUID
      // changed, or there was no policy before, we delete the entry at first to
      // ensure that no old configuration remains.
      if (old_guid == new_guid &&
          shill_property_util::DoIdentifyingPropertiesMatch(
              *new_shill_properties, entry_properties)) {
        VLOG(1) << "Updating previously managed configuration with the "
                << "updated policy " << new_guid << ".";
      } else {
        VLOG(1) << "Deleting profile entry before writing new policy "
                << new_guid << " because of identifying properties changed.";
        DeleteEntry(entry);
      }

      WriteNewShillConfiguration(*new_shill_properties, *new_policy);
      remaining_policies_.erase(new_guid);
    }
  } else if (was_managed) {
    VLOG(1) << "Removing configuration previously managed by policy "
            << old_guid << ", because the policy was removed.";

    // Remove the entry, because the network was managed but isn't anymore.
    // Note: An alternative might be to preserve the user settings, but it's
    // unclear which values originating the policy should be removed.
    DeleteEntry(entry);
  } else {
    // The entry wasn't managed and doesn't match any current policy. Global
    // network settings have to be applied.
    base::DictionaryValue shill_properties_to_update;
    GetPropertiesForUnmanagedEntry(entry_properties,
                                   &shill_properties_to_update);
    if (shill_properties_to_update.empty()) {
      VLOG(2) << "Ignore unmanaged entry.";
      // Calling a SetProperties of Shill with an empty dictionary is a no op.
    } else {
      VLOG(2) << "Apply global network config to unmanaged entry.";
      handler_->UpdateExistingConfigurationWithPropertiesFromPolicy(
          entry_properties, shill_properties_to_update);
    }
  }
}

void PolicyApplicator::DeleteEntry(const std::string& entry) {
  DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
      dbus::ObjectPath(profile_.path),
      entry,
      base::Bind(&base::DoNothing),
      base::Bind(&LogErrorMessage, FROM_HERE));
}

void PolicyApplicator::WriteNewShillConfiguration(
    const base::DictionaryValue& shill_dictionary,
    const base::DictionaryValue& policy) {
  // Ethernet (non EAP) settings, like GUID or UIData, cannot be stored per
  // user. Abort in that case.
  std::string type;
  policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type);
  if (type == ::onc::network_type::kEthernet &&
      profile_.type() == NetworkProfile::TYPE_USER) {
    const base::DictionaryValue* ethernet = NULL;
    policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet,
                                             &ethernet);
    std::string auth;
    ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
                                            &auth);
    if (auth == ::onc::ethernet::kNone)
      return;
  }

  handler_->CreateConfigurationFromPolicy(shill_dictionary);
}

void PolicyApplicator::GetPropertiesForUnmanagedEntry(
    const base::DictionaryValue& entry_properties,
    base::DictionaryValue* properties_to_update) const {
  // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config.

  std::string type;
  entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
  if (NetworkTypePattern::Ethernet().MatchesType(type))
    return;  // Autoconnect for Ethernet cannot be configured.

  // By default all networks are allowed to autoconnect.
  bool only_policy_autoconnect = false;
  global_network_config_.GetBooleanWithoutPathExpansion(
      ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
      &only_policy_autoconnect);
  if (!only_policy_autoconnect)
    return;

  bool old_autoconnect = false;
  if (entry_properties.GetBooleanWithoutPathExpansion(
          shill::kAutoConnectProperty, &old_autoconnect) &&
      !old_autoconnect) {
    // Autoconnect is already explictly disabled. No need to set it again.
    return;
  }
  // If autconnect is not explicitly set yet, it might automatically be enabled
  // by Shill. To prevent that, disable it explicitly.
  properties_to_update->SetBooleanWithoutPathExpansion(
      shill::kAutoConnectProperty, false);
}

PolicyApplicator::~PolicyApplicator() {
  ApplyRemainingPolicies();
  STLDeleteValues(&all_policies_);
}

void PolicyApplicator::ApplyRemainingPolicies() {
  if (!handler_) {
    LOG(WARNING) << "Handler destructed during policy application to profile "
                 << profile_.ToDebugString();
    return;
  }

  if (remaining_policies_.empty())
    return;

  VLOG(2) << "Create new managed network configurations in profile"
          << profile_.ToDebugString() << ".";
  // All profile entries were compared to policies. |remaining_policies_|
  // contains all modified policies that didn't match any entry. For these
  // remaining policies, new configurations have to be created.
  for (std::set<std::string>::iterator it = remaining_policies_.begin();
       it != remaining_policies_.end(); ++it) {
    const base::DictionaryValue* policy = GetByGUID(all_policies_, *it);
    DCHECK(policy);

    VLOG(1) << "Creating new configuration managed by policy " << *it
            << " in profile " << profile_.ToDebugString() << ".";

    scoped_ptr<base::DictionaryValue> shill_dictionary =
        policy_util::CreateShillConfiguration(profile_, *it, policy, NULL);
    WriteNewShillConfiguration(*shill_dictionary, *policy);
  }
}

}  // namespace chromeos
