// 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/managed_network_configuration_handler_impl.h"

#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/guid.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chromeos/dbus/shill/shill_manager_client.h"
#include "chromeos/dbus/shill/shill_profile_client.h"
#include "chromeos/dbus/shill/shill_service_client.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_device_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_policy_observer.h"
#include "chromeos/network/network_profile.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/onc/onc_merger.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/onc/onc_validator.h"
#include "chromeos/network/policy_util.h"
#include "chromeos/network/prohibited_technologies_handler.h"
#include "chromeos/network/shill_property_util.h"
#include "chromeos/network/tether_constants.h"
#include "components/onc/onc_constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

using GuidToPolicyMap = ManagedNetworkConfigurationHandler::GuidToPolicyMap;

// These are error strings used for error callbacks. None of these error
// messages are user-facing: they should only appear in logs.
const char kInvalidUserSettings[] = "InvalidUserSettings";
const char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured";
const char kPoliciesNotInitialized[] = "PoliciesNotInitialized";
const char kProfileNotInitialized[] = "ProfileNotInitialized";
const char kUnconfiguredNetwork[] = "UnconfiguredNetwork";
const char kUnknownNetwork[] = "UnknownNetwork";

std::string ToDebugString(::onc::ONCSource source,
                          const std::string& userhash) {
  return source == ::onc::ONC_SOURCE_USER_POLICY ?
      ("user policy of " + userhash) : "device policy";
}

void InvokeErrorCallback(const std::string& service_path,
                         const network_handler::ErrorCallback& error_callback,
                         const std::string& error_name) {
  std::string error_msg = "ManagedConfig Error: " + error_name;
  NET_LOG_ERROR(error_msg, service_path);
  network_handler::RunErrorCallback(
      error_callback, service_path, error_name, error_msg);
}

void LogErrorWithDictAndCallCallback(
    base::OnceClosure callback,
    const base::Location& from_where,
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  device_event_log::AddEntry(from_where.file_name(), from_where.line_number(),
                             device_event_log::LOG_TYPE_NETWORK,
                             device_event_log::LOG_LEVEL_ERROR, error_name);
  std::move(callback).Run();
}

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

std::string GetStringFromDictionary(const base::Value& dict, const char* key) {
  const base::Value* v = dict.FindKey(key);
  return v ? v->GetString() : std::string();
}

bool MatchesExistingNetworkState(const base::DictionaryValue& properties,
                                 const NetworkState* network_state) {
  std::string type =
      GetStringFromDictionary(properties, ::onc::network_config::kType);
  if (network_util::TranslateONCTypeToShill(type) != network_state->type()) {
    NET_LOG(ERROR) << "Network type mismatch for: " << network_state->guid()
                   << " type: " << type
                   << " does not match: " << network_state->type();
    return false;
  }
  if (type != ::onc::network_type::kWiFi)
    return true;

  const base::Value* wifi = properties.FindKey(::onc::network_config::kWiFi);
  if (!wifi) {
    NET_LOG(ERROR) << "WiFi network configuration missing is WiFi properties: "
                   << network_state->guid();
    return false;
  }
  // For WiFi networks ensure that Security and SSID match.
  std::string security = GetStringFromDictionary(*wifi, ::onc::wifi::kSecurity);
  if (network_util::TranslateONCSecurityToShill(security) !=
      network_state->security_class()) {
    NET_LOG(ERROR) << "Network security mismatch for: " << network_state->guid()
                   << " security: " << security
                   << " does not match: " << network_state->security_class();
    return false;
  }
  std::string hex_ssid = GetStringFromDictionary(*wifi, ::onc::wifi::kHexSSID);
  if (hex_ssid != network_state->GetHexSsid()) {
    NET_LOG(ERROR) << "Network HexSSID mismatch for: " << network_state->guid()
                   << " hex_ssid: " << hex_ssid
                   << " does not match: " << network_state->GetHexSsid();
    return false;
  }
  return true;
}

// Checks if |onc| is an unmanaged wifi network that has AutoConnect=true.
bool EnablesUnmanagedWifiAutoconnect(const base::DictionaryValue* onc) {
  const base::Value* type = onc->FindKeyOfType(::onc::network_config::kType,
                                               base::Value::Type::STRING);
  if (!type || type->GetString() != ::onc::network_type::kWiFi)
    return false;

  const base::Value* source = onc->FindKeyOfType(::onc::network_config::kSource,
                                                 base::Value::Type::STRING);
  if (!source ||
      source->GetString() == ::onc::network_config::kSourceDevicePolicy ||
      source->GetString() == ::onc::network_config::kSourceUserPolicy) {
    return false;
  }

  const base::Value* autoconnect = onc->FindPathOfType(
      {::onc::network_config::kWiFi, ::onc::wifi::kAutoConnect},
      base::Value::Type::BOOLEAN);
  return autoconnect && autoconnect->GetBool();
}

}  // namespace

struct ManagedNetworkConfigurationHandlerImpl::Policies {
  ~Policies();

  GuidToPolicyMap per_network_config;
  base::DictionaryValue global_network_config;
};

ManagedNetworkConfigurationHandlerImpl::Policies::~Policies() = default;

void ManagedNetworkConfigurationHandlerImpl::AddObserver(
    NetworkPolicyObserver* observer) {
  observers_.AddObserver(observer);
}

void ManagedNetworkConfigurationHandlerImpl::RemoveObserver(
    NetworkPolicyObserver* observer) {
  observers_.RemoveObserver(observer);
}

// GetManagedProperties

void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties(
    const std::string& userhash,
    const std::string& service_path,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback) {
  if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
    InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
    return;
  }
  NET_LOG_USER("GetManagedProperties", service_path);
  network_configuration_handler_->GetShillProperties(
      service_path,
      base::Bind(
          &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback,
          weak_ptr_factory_.GetWeakPtr(),
          base::Bind(
              &ManagedNetworkConfigurationHandlerImpl::SendManagedProperties,
              weak_ptr_factory_.GetWeakPtr(), userhash, callback,
              error_callback)),
      error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties(
    const std::string& userhash,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback,
    const std::string& service_path,
    std::unique_ptr<base::DictionaryValue> shill_properties) {
  std::string profile_path;
  shill_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
                                                  &profile_path);
  const NetworkState* network_state =
      network_state_handler_->GetNetworkState(service_path);
  const NetworkProfile* profile =
      network_profile_handler_
          ? network_profile_handler_->GetProfileForPath(profile_path)
          : nullptr;
  if (!profile && !(network_state && network_state->IsNonProfileType())) {
    // Visible but unsaved (not known) networks will not have a profile.
    NET_LOG_DEBUG("No profile for service: " + profile_path, service_path);
  }

  std::unique_ptr<NetworkUIData> ui_data =
      shill_property_util::GetUIDataFromProperties(*shill_properties);

  const base::DictionaryValue* user_settings = nullptr;

  if (ui_data && profile) {
    user_settings = ui_data->GetUserSettingsDictionary();
  } else if (profile) {
    NET_LOG_DEBUG("Service contains empty or invalid UIData", service_path);
    // TODO(pneubeck): add a conversion of user configured entries of old
    // ChromeOS versions. We will have to use a heuristic to determine which
    // properties _might_ be user configured.
  }

  std::string guid;
  shill_properties->GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);

  ::onc::ONCSource onc_source;
  FindPolicyByGUID(userhash, guid, &onc_source);
  std::unique_ptr<base::DictionaryValue> active_settings(
      onc::TranslateShillServiceToONCPart(*shill_properties, onc_source,
                                          &onc::kNetworkWithStateSignature,
                                          network_state));

  const base::DictionaryValue* network_policy = nullptr;
  const base::DictionaryValue* global_policy = nullptr;
  if (profile) {
    const Policies* policies = GetPoliciesForProfile(*profile);
    if (!policies) {
      InvokeErrorCallback(
          service_path, error_callback, kPoliciesNotInitialized);
      return;
    }
    if (!guid.empty())
      network_policy = GetByGUID(policies->per_network_config, guid);
    global_policy = &policies->global_network_config;
  }

  std::unique_ptr<base::DictionaryValue> augmented_properties(
      policy_util::CreateManagedONC(global_policy, network_policy,
                                    user_settings, active_settings.get(),
                                    profile));
  callback.Run(service_path, *augmented_properties);
}

// GetProperties

void ManagedNetworkConfigurationHandlerImpl::GetProperties(
    const std::string& userhash,
    const std::string& service_path,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback) {
  NET_LOG_USER("GetProperties", service_path);
  network_configuration_handler_->GetShillProperties(
      service_path,
      base::Bind(
          &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback,
          weak_ptr_factory_.GetWeakPtr(),
          base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties,
                     weak_ptr_factory_.GetWeakPtr(), userhash, callback,
                     error_callback)),
      error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::SendProperties(
    const std::string& userhash,
    const network_handler::DictionaryResultCallback& callback,
    const network_handler::ErrorCallback& error_callback,
    const std::string& service_path,
    std::unique_ptr<base::DictionaryValue> shill_properties) {
  const NetworkState* network_state =
      network_state_handler_->GetNetworkState(service_path);

  std::string guid;
  shill_properties->GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);

  ::onc::ONCSource onc_source;
  FindPolicyByGUID(userhash, guid, &onc_source);

  std::unique_ptr<base::DictionaryValue> onc_network(
      onc::TranslateShillServiceToONCPart(*shill_properties, onc_source,
                                          &onc::kNetworkWithStateSignature,
                                          network_state));
  callback.Run(service_path, *onc_network);
}

// SetProperties

void ManagedNetworkConfigurationHandlerImpl::SetProperties(
    const std::string& service_path,
    const base::DictionaryValue& user_settings,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  const NetworkState* state =
      network_state_handler_->GetNetworkStateFromServicePath(
          service_path, true /* configured_only */);
  if (!state) {
    InvokeErrorCallback(service_path, error_callback, kUnknownNetwork);
    return;
  }

  std::string guid = state->guid();
  DCHECK(!guid.empty());

  const std::string& profile_path = state->profile_path();
  const NetworkProfile *profile =
      network_profile_handler_->GetProfileForPath(profile_path);
  if (!profile) {
    // TODO(pneubeck): create an initial configuration in this case. As for
    // CreateConfiguration, user settings from older ChromeOS versions have to
    // be determined here.
    InvokeErrorCallback(service_path, error_callback, kUnconfiguredNetwork);
    return;
  }

  NET_LOG(DEBUG) << "Set Managed Properties for GUID: " << guid
                 << ". Profile: " << profile->ToDebugString();

  const Policies* policies = GetPoliciesForProfile(*profile);
  if (!policies) {
    InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized);
    return;
  }

  // We need to ensure that required configuration properties (e.g. Type) are
  // included for ONC validation and translation to Shill properties.
  std::unique_ptr<base::DictionaryValue> user_settings_copy(
      user_settings.DeepCopy());
  user_settings_copy->SetKey(
      ::onc::network_config::kType,
      base::Value(network_util::TranslateShillTypeToONC(state->type())));
  user_settings_copy->MergeDictionary(&user_settings);

  // Validate the ONC dictionary. We are liberal and ignore unknown field
  // names. User settings are only partial ONC, thus we ignore missing fields.
  onc::Validator validator(false,  // Ignore unknown fields.
                           false,  // Ignore invalid recommended field names.
                           false,  // Ignore missing fields.
                           false,  // This ONC does not come from policy.
                           true);  // Log warnings.

  onc::Validator::Result validation_result;
  std::unique_ptr<base::DictionaryValue> validated_user_settings =
      validator.ValidateAndRepairObject(&onc::kNetworkConfigurationSignature,
                                        *user_settings_copy,
                                        &validation_result);
  if (validation_result == onc::Validator::INVALID) {
    InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings);
    return;
  }
  if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
    NET_LOG(USER) << "Validation of ONC user settings produced warnings.";

  // Don't allow AutoConnect=true for unmanaged wifi networks if
  // 'AllowOnlyPolicyNetworksToAutoconnect' policy is active.
  if (EnablesUnmanagedWifiAutoconnect(validated_user_settings.get()) &&
      AllowOnlyPolicyNetworksToAutoconnect()) {
    InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings);
    return;
  }

  // Fill in HexSSID field from contents of SSID field if not set already.
  onc::FillInHexSSIDFieldsInOncObject(onc::kNetworkConfigurationSignature,
                                      validated_user_settings.get());

  const base::DictionaryValue* network_policy =
      GetByGUID(policies->per_network_config, guid);
  if (network_policy)
    NET_LOG(DEBUG) << "Configuration is managed. GUID: " << guid;

  std::unique_ptr<base::DictionaryValue> shill_dictionary(
      policy_util::CreateShillConfiguration(
          *profile, guid, &policies->global_network_config, network_policy,
          validated_user_settings.get()));

  SetShillProperties(service_path, std::move(shill_dictionary), callback,
                     error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::SetManagerProperty(
    const std::string& property_name,
    const base::Value& value,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  network_configuration_handler_->SetManagerProperty(property_name, value,
                                                     callback, error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::SetShillProperties(
    const std::string& service_path,
    std::unique_ptr<base::DictionaryValue> shill_dictionary,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) {
  network_configuration_handler_->SetShillProperties(
      service_path, *shill_dictionary, callback, error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration(
    const std::string& userhash,
    const base::DictionaryValue& properties,
    const network_handler::ServiceResultCallback& callback,
    const network_handler::ErrorCallback& error_callback) const {
  std::string guid =
      GetStringFromDictionary(properties, ::onc::network_config::kGUID);
  NET_LOG(USER) << "CreateConfiguration: " << guid;

  // Validate the ONC dictionary. We are liberal and ignore unknown field
  // names. User settings are only partial ONC, thus we ignore missing fields.
  onc::Validator validator(false,   // Ignore unknown fields.
                           false,   // Ignore invalid recommended field names.
                           false,   // Ignore missing fields.
                           false,   // This ONC does not come from policy.
                           false);  // Don't log warnings.

  onc::Validator::Result validation_result;
  std::unique_ptr<base::DictionaryValue> validated_properties =
      validator.ValidateAndRepairObject(&onc::kNetworkConfigurationSignature,
                                        properties, &validation_result);

  if (validation_result == onc::Validator::INVALID) {
    InvokeErrorCallback("", error_callback, kInvalidUserSettings);
    return;
  }

  if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
    LOG(WARNING) << "Validation of ONC user settings produced warnings.";

  // Fill in HexSSID field from contents of SSID field if not set already - this
  // is required to properly match the configuration against existing policies.
  onc::FillInHexSSIDFieldsInOncObject(onc::kNetworkConfigurationSignature,
                                      validated_properties.get());

  // Make sure the network is not configured through a user policy.
  const Policies* policies = nullptr;
  if (!userhash.empty()) {
    policies = GetPoliciesForUser(userhash);
    if (!policies) {
      InvokeErrorCallback("", error_callback, kPoliciesNotInitialized);
      return;
    }

    if (policy_util::FindMatchingPolicy(policies->per_network_config,
                                        *validated_properties)) {
      InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured);
      return;
    }
  }

  // Make user the network is not configured through a device policy.
  policies = GetPoliciesForUser("");
  if (!policies) {
    InvokeErrorCallback("", error_callback, kPoliciesNotInitialized);
    return;
  }

  if (policy_util::FindMatchingPolicy(policies->per_network_config,
                                      *validated_properties)) {
    InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured);
    return;
  }

  const NetworkProfile* profile =
      network_profile_handler_->GetProfileForUserhash(userhash);
  if (!profile) {
    InvokeErrorCallback("", error_callback, kProfileNotInitialized);
    return;
  }

  // If a GUID was provided, verify that the new configuraiton matches an
  // existing NetworkState for an unconfigured (i.e. visible) network.
  // Requires HexSSID to be set first for comparing SSIDs.
  if (!guid.empty()) {
    const NetworkState* network_state =
        network_state_handler_->GetNetworkStateFromGuid(guid);
    // |network_state| can by null if a network went out of range or was
    // forgotten while the UI is open. Configuration should succeed and the GUID
    // can be reused.
    if (network_state) {
      if (!MatchesExistingNetworkState(*validated_properties, network_state)) {
        InvokeErrorCallback(network_state->path(), error_callback,
                            kNetworkAlreadyConfigured);
        return;
      } else if (!network_state->profile_path().empty()) {
        // Can occur after an invalid password or with multiple config UIs open.
        // Configuration should succeed, so just log an event.
        NET_LOG(EVENT) << "Reconfiguring network: " << guid
                       << " Profile: " << network_state->profile_path();
      }
    }
  } else {
    guid = base::GenerateGUID();
  }

  std::unique_ptr<base::DictionaryValue> shill_dictionary(
      policy_util::CreateShillConfiguration(*profile, guid,
                                            nullptr,  // no global policy
                                            nullptr,  // no network policy
                                            validated_properties.get()));

  network_configuration_handler_->CreateShillConfiguration(
      *shill_dictionary, callback, error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration(
    const std::string& service_path,
    const base::Closure& callback,
    const network_handler::ErrorCallback& error_callback) const {
  network_configuration_handler_->RemoveConfiguration(service_path, callback,
                                                      error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::
    RemoveConfigurationFromCurrentProfile(
        const std::string& service_path,
        const base::Closure& callback,
        const network_handler::ErrorCallback& error_callback) const {
  network_configuration_handler_->RemoveConfigurationFromCurrentProfile(
      service_path, callback, error_callback);
}

void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
    ::onc::ONCSource onc_source,
    const std::string& userhash,
    const base::ListValue& network_configs_onc,
    const base::DictionaryValue& global_network_config) {
  VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
          << ".";

  // |userhash| must be empty for device policies.
  DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY ||
         userhash.empty());
  Policies* policies = nullptr;
  if (base::Contains(policies_by_user_, userhash)) {
    policies = policies_by_user_[userhash].get();
  } else {
    policies = new Policies;
    policies_by_user_[userhash] = base::WrapUnique(policies);
  }

  policies->global_network_config.MergeDictionary(&global_network_config);

  // Update prohibited technologies.
  const base::ListValue* prohibited_list = nullptr;
  if (policies->global_network_config.GetListWithoutPathExpansion(
          ::onc::global_network_config::kDisableNetworkTypes,
          &prohibited_list) &&
      prohibited_technologies_handler_) {
    // Prohibited technologies are only allowed in user policy.
    DCHECK_EQ(::onc::ONC_SOURCE_DEVICE_POLICY, onc_source);

    prohibited_technologies_handler_->SetProhibitedTechnologies(
        prohibited_list);
  }

  GuidToPolicyMap old_per_network_config;
  policies->per_network_config.swap(old_per_network_config);

  // This stores all GUIDs of policies that have changed or are new.
  std::set<std::string> modified_policies;

  for (base::ListValue::const_iterator it = network_configs_onc.begin();
       it != network_configs_onc.end(); ++it) {
    const base::DictionaryValue* network = nullptr;
    it->GetAsDictionary(&network);
    DCHECK(network);

    std::string guid;
    network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid);
    DCHECK(!guid.empty());

    if (policies->per_network_config.count(guid) > 0) {
      NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) +
                    " contains several entries for the same GUID ", guid);
    }
    base::DictionaryValue* new_entry = network->DeepCopy();
    policies->per_network_config[guid] = base::WrapUnique(new_entry);

    base::DictionaryValue* old_entry = old_per_network_config[guid].get();
    if (!old_entry || !old_entry->Equals(new_entry))
      modified_policies.insert(guid);
  }

  old_per_network_config.clear();
  ApplyOrQueuePolicies(userhash, &modified_policies);
  for (auto& observer : observers_)
    observer.PoliciesChanged(userhash);
}

bool ManagedNetworkConfigurationHandlerImpl::IsAnyPolicyApplicationRunning()
    const {
  return !policy_applicators_.empty() || !queued_modified_policies_.empty();
}

bool ManagedNetworkConfigurationHandlerImpl::ApplyOrQueuePolicies(
    const std::string& userhash,
    std::set<std::string>* modified_policies) {
  DCHECK(modified_policies);

  const NetworkProfile* profile =
      network_profile_handler_->GetProfileForUserhash(userhash);
  if (!profile) {
    VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
            << "policy application.";
    // OnProfileAdded will apply all policies for this userhash.
    return false;
  }

  if (base::Contains(policy_applicators_, userhash)) {
    // A previous policy application is still running. Queue the modified
    // policies.
    // Note, even if |modified_policies| is empty, this means that a policy
    // application will be queued.
    queued_modified_policies_[userhash].insert(modified_policies->begin(),
                                               modified_policies->end());
    VLOG(1) << "Previous PolicyApplicator still running. Postponing policy "
               "application.";
    return false;
  }

  const Policies* policies = policies_by_user_[userhash].get();
  DCHECK(policies);

  PolicyApplicator* applicator =
      new PolicyApplicator(*profile,
                           policies->per_network_config,
                           policies->global_network_config,
                           this,
                           modified_policies);
  policy_applicators_[userhash] = base::WrapUnique(applicator);
  applicator->Run();
  return true;
}

void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
    const NetworkProfile& profile) {
  VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";

  const Policies* policies = GetPoliciesForProfile(profile);
  if (!policies) {
    VLOG(1) << "The relevant policy is not initialized, "
            << "postponing policy application.";
    // See SetPolicy.
    return;
  }

  std::set<std::string> policy_guids;
  for (auto it = policies->per_network_config.begin();
       it != policies->per_network_config.end(); ++it) {
    policy_guids.insert(it->first);
  }

  const bool started_policy_application =
      ApplyOrQueuePolicies(profile.userhash, &policy_guids);
  DCHECK(started_policy_application);
}

void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved(
    const NetworkProfile& profile) {
  // Nothing to do in this case.
}

void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy(
    const base::DictionaryValue& shill_properties,
    base::OnceClosure callback) {
  base::RepeatingClosure adapted_callback =
      base::AdaptCallbackForRepeating(std::move(callback));
  network_configuration_handler_->CreateShillConfiguration(
      shill_properties,
      base::BindRepeating(
          &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
          weak_ptr_factory_.GetWeakPtr(), adapted_callback),
      base::BindRepeating(&LogErrorWithDictAndCallCallback, adapted_callback,
                          FROM_HERE));
}

void ManagedNetworkConfigurationHandlerImpl::
    UpdateExistingConfigurationWithPropertiesFromPolicy(
        const base::DictionaryValue& existing_properties,
        const base::DictionaryValue& new_properties,
        base::OnceClosure callback) {
  base::RepeatingClosure adapted_callback =
      base::AdaptCallbackForRepeating(std::move(callback));
  base::DictionaryValue shill_properties;

  std::string profile;
  existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
                                                    &profile);
  if (profile.empty()) {
    NET_LOG_ERROR("Missing profile property",
                  shill_property_util::GetNetworkIdFromProperties(
                      existing_properties));
    return;
  }
  shill_properties.SetKey(shill::kProfileProperty, base::Value(profile));

  if (!shill_property_util::CopyIdentifyingProperties(
          existing_properties,
          true /* properties were read from Shill */,
          &shill_properties)) {
    NET_LOG_ERROR("Missing identifying properties",
                  shill_property_util::GetNetworkIdFromProperties(
                      existing_properties));
  }

  shill_properties.MergeDictionary(&new_properties);

  network_configuration_handler_->CreateShillConfiguration(
      shill_properties,
      base::BindRepeating(
          &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
          weak_ptr_factory_.GetWeakPtr(), adapted_callback),
      base::BindRepeating(&LogErrorWithDictAndCallCallback, adapted_callback,
                          FROM_HERE));
}

void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied(
    const NetworkProfile& profile) {
  const std::string& userhash = profile.userhash;
  VLOG(1) << "Policy application for user '" << userhash << "' finished.";

  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
      FROM_HERE, policy_applicators_[userhash].release());
  policy_applicators_.erase(userhash);

  if (base::Contains(queued_modified_policies_, userhash)) {
    std::set<std::string> modified_policies;
    queued_modified_policies_[userhash].swap(modified_policies);
    // Remove |userhash| from the queue.
    queued_modified_policies_.erase(userhash);
    ApplyOrQueuePolicies(userhash, &modified_policies);
  } else {
    if (userhash.empty())
      device_policy_applied_ = true;
    else
      user_policy_applied_ = true;

    if (device_policy_applied_ && user_policy_applied_) {
      network_state_handler_->UpdateBlockedWifiNetworks(
          AllowOnlyPolicyNetworksToConnect(),
          AllowOnlyPolicyNetworksToConnectIfAvailable(),
          GetBlacklistedHexSSIDs());
    }

    for (auto& observer : observers_)
      observer.PoliciesApplied(userhash);
  }
}

const base::DictionaryValue*
ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID(
    const std::string userhash,
    const std::string& guid,
    ::onc::ONCSource* onc_source) const {
  *onc_source = ::onc::ONC_SOURCE_NONE;

  if (!userhash.empty()) {
    const Policies* user_policies = GetPoliciesForUser(userhash);
    if (user_policies) {
      const base::DictionaryValue* policy =
          GetByGUID(user_policies->per_network_config, guid);
      if (policy) {
        *onc_source = ::onc::ONC_SOURCE_USER_POLICY;
        return policy;
      }
    }
  }

  const Policies* device_policies = GetPoliciesForUser(std::string());
  if (device_policies) {
    const base::DictionaryValue* policy =
        GetByGUID(device_policies->per_network_config, guid);
    if (policy) {
      *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
      return policy;
    }
  }

  return nullptr;
}

const GuidToPolicyMap*
ManagedNetworkConfigurationHandlerImpl::GetNetworkConfigsFromPolicy(
    const std::string& userhash) const {
  const Policies* policies = GetPoliciesForUser(userhash);
  if (!policies)
    return nullptr;

  return &policies->per_network_config;
}

const base::DictionaryValue*
ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy(
    const std::string& userhash) const {
  const Policies* policies = GetPoliciesForUser(userhash);
  if (!policies)
    return nullptr;

  return &policies->global_network_config;
}

const base::DictionaryValue*
ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile(
    const std::string& guid,
    const std::string& profile_path,
    ::onc::ONCSource* onc_source) const {
  if (profile_path.empty())
    return nullptr;

  const NetworkProfile* profile =
      network_profile_handler_->GetProfileForPath(profile_path);
  if (!profile) {
    NET_LOG_ERROR("Profile path unknown:" + profile_path, guid);
    return nullptr;
  }

  const Policies* policies = GetPoliciesForProfile(*profile);
  if (!policies)
    return nullptr;

  const base::DictionaryValue* policy =
      GetByGUID(policies->per_network_config, guid);
  if (policy && onc_source) {
    *onc_source = (profile->userhash.empty() ? ::onc::ONC_SOURCE_DEVICE_POLICY
                                             : ::onc::ONC_SOURCE_USER_POLICY);
  }
  return policy;
}

bool ManagedNetworkConfigurationHandlerImpl::AllowOnlyPolicyNetworksToConnect()
    const {
  const base::DictionaryValue* global_network_config =
      GetGlobalConfigFromPolicy(
          std::string() /* no username hash, device policy */);
  if (!global_network_config)
    return false;

  const base::Value* managed_only_value = global_network_config->FindKeyOfType(
      ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
      base::Value::Type::BOOLEAN);
  return managed_only_value && managed_only_value->GetBool();
}

bool ManagedNetworkConfigurationHandlerImpl::
    AllowOnlyPolicyNetworksToConnectIfAvailable() const {
  const base::DictionaryValue* global_network_config =
      GetGlobalConfigFromPolicy(
          std::string() /* no username hash, device policy */);
  if (!global_network_config)
    return false;

  // Check if policy is enabled.
  const base::Value* available_only_value =
      global_network_config->FindKeyOfType(
          ::onc::global_network_config::
              kAllowOnlyPolicyNetworksToConnectIfAvailable,
          base::Value::Type::BOOLEAN);
  return available_only_value && available_only_value->GetBool();
}

bool ManagedNetworkConfigurationHandlerImpl::
    AllowOnlyPolicyNetworksToAutoconnect() const {
  const base::DictionaryValue* global_network_config =
      GetGlobalConfigFromPolicy(
          std::string() /* no username hash, device policy */);
  if (!global_network_config)
    return false;

  const base::Value* autoconnect_value = global_network_config->FindKeyOfType(
      ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
      base::Value::Type::BOOLEAN);
  return autoconnect_value && autoconnect_value->GetBool();
}

std::vector<std::string>
ManagedNetworkConfigurationHandlerImpl::GetBlacklistedHexSSIDs() const {
  const base::DictionaryValue* global_network_config =
      GetGlobalConfigFromPolicy(
          std::string() /* no username hash, device policy */);
  if (!global_network_config)
    return std::vector<std::string>();

  const base::Value* blacklist_value = global_network_config->FindKeyOfType(
      ::onc::global_network_config::kBlacklistedHexSSIDs,
      base::Value::Type::LIST);
  if (!blacklist_value)
    return std::vector<std::string>();

  std::vector<std::string> blacklisted_hex_ssids;
  for (const base::Value& entry : blacklist_value->GetList())
    blacklisted_hex_ssids.push_back(entry.GetString());
  return blacklisted_hex_ssids;
}

const ManagedNetworkConfigurationHandlerImpl::Policies*
ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser(
    const std::string& userhash) const {
  UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
  if (it == policies_by_user_.end())
    return nullptr;
  return it->second.get();
}

const ManagedNetworkConfigurationHandlerImpl::Policies*
ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile(
    const NetworkProfile& profile) const {
  DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
         profile.userhash.empty());
  return GetPoliciesForUser(profile.userhash);
}

ManagedNetworkConfigurationHandlerImpl::
    ManagedNetworkConfigurationHandlerImpl() {
  CHECK(base::ThreadTaskRunnerHandle::IsSet());
}

ManagedNetworkConfigurationHandlerImpl::
    ~ManagedNetworkConfigurationHandlerImpl() {
  if (network_profile_handler_)
    network_profile_handler_->RemoveObserver(this);
}

void ManagedNetworkConfigurationHandlerImpl::Init(
    NetworkStateHandler* network_state_handler,
    NetworkProfileHandler* network_profile_handler,
    NetworkConfigurationHandler* network_configuration_handler,
    NetworkDeviceHandler* network_device_handler,
    ProhibitedTechnologiesHandler* prohibited_technologies_handler) {
  network_state_handler_ = network_state_handler;
  network_profile_handler_ = network_profile_handler;
  network_configuration_handler_ = network_configuration_handler;
  network_device_handler_ = network_device_handler;
  if (network_profile_handler_)
    network_profile_handler_->AddObserver(this);
  prohibited_technologies_handler_ = prohibited_technologies_handler;
}

void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork(
    base::OnceClosure callback,
    const std::string& service_path,
    const std::string& guid) {
  DCHECK(!service_path.empty());

  // When this is called, the policy has been fully applied and is reflected in
  // NetworkStateHandler, so it is safe to notify obserers.
  // Notifying observers is the last step of policy application to
  // |service_path|.
  for (auto& observer : observers_)
    observer.PolicyAppliedToNetwork(service_path);

  // Inform the caller that has requested policy application that it has
  // finished.
  std::move(callback).Run();
}

// Get{Managed}Properties helpers

void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties(
    const std::string& service_path,
    base::DictionaryValue* properties) {
  const NetworkState* network =
      network_state_handler_->GetNetworkState(service_path);
  if (!network) {
    NET_LOG(ERROR) << "GetDeviceStateProperties: no network for: "
                   << service_path;
    return;
  }
  if (!network->IsConnectedState())
    return;  // No (non saved) IP Configs for non connected networks.

  const DeviceState* device_state =
      network->device_path().empty()
          ? nullptr
          : network_state_handler_->GetDeviceState(network->device_path());

  // Get the hardware MAC address from the DeviceState.
  if (device_state && !device_state->mac_address().empty()) {
    properties->SetKey(shill::kAddressProperty,
                       base::Value(device_state->mac_address()));
  }

  // Get the IPConfig properties from the device and store them in "IPConfigs"
  // (plural) in the properties dictionary. (Note: Shill only provides a single
  // "IPConfig" property for a network service, but a consumer of this API may
  // want information about all ipv4 and ipv6 IPConfig properties.
  auto ip_configs = std::make_unique<base::ListValue>();

  if (!device_state || device_state->ip_configs().empty()) {
    // Shill may not provide IPConfigs for external Cellular devices/dongles
    // (https://crbug.com/739314) or VPNs, so build a dictionary of ipv4
    // properties from cached NetworkState properties .
    NET_LOG(DEBUG)
        << "GetDeviceStateProperties: Setting IPv4 properties from network: "
        << service_path;
    if (network->ipv4_config())
      ip_configs->Append(network->ipv4_config()->Clone());
  } else {
    // Convert the DeviceState IPConfigs dictionary to a ListValue.
    for (const auto iter : device_state->ip_configs().DictItems())
      ip_configs->Append(iter.second.Clone());
  }
  if (!ip_configs->GetList().empty()) {
    properties->SetWithoutPathExpansion(shill::kIPConfigsProperty,
                                        std::move(ip_configs));
  }
}

void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback(
    GetDevicePropertiesCallback send_callback,
    const std::string& service_path,
    const base::DictionaryValue& shill_properties) {
  std::unique_ptr<base::DictionaryValue> shill_properties_copy(
      shill_properties.DeepCopy());

  std::string guid;
  shill_properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);
  if (guid.empty()) {
    // Unmanaged networks are assigned a GUID in NetworkState. Provide this
    // value in the ONC dictionary.
    const NetworkState* state =
        network_state_handler_->GetNetworkState(service_path);
    if (state && !state->guid().empty()) {
      guid = state->guid();
      shill_properties_copy->SetKey(shill::kGuidProperty, base::Value(guid));
    } else {
      LOG(ERROR) << "Network has no GUID specified: " << service_path;
    }
  }

  std::string type;
  shill_properties_copy->GetStringWithoutPathExpansion(shill::kTypeProperty,
                                                       &type);
  // Add any associated DeviceState properties.
  GetDeviceStateProperties(service_path, shill_properties_copy.get());

  // Only request additional Device properties for Cellular networks with a
  // valid device.
  std::string device_path;
  if (!network_device_handler_ ||
      type != shill::kTypeCellular ||
      !shill_properties_copy->GetStringWithoutPathExpansion(
          shill::kDeviceProperty, &device_path) ||
      device_path.empty()) {
    send_callback.Run(service_path, std::move(shill_properties_copy));
    return;
  }

  // Request the device properties. On success or failure pass (a possibly
  // modified) |shill_properties| to |send_callback|.
  std::unique_ptr<base::DictionaryValue> shill_properties_copy_error_copy(
      shill_properties_copy->DeepCopy());
  network_device_handler_->GetDeviceProperties(
      device_path,
      base::Bind(&ManagedNetworkConfigurationHandlerImpl::
                     GetDevicePropertiesSuccess,
                 weak_ptr_factory_.GetWeakPtr(),
                 service_path,
                 base::Passed(&shill_properties_copy),
                 send_callback),
      base::Bind(&ManagedNetworkConfigurationHandlerImpl::
                     GetDevicePropertiesFailure,
                 weak_ptr_factory_.GetWeakPtr(),
                 service_path,
                 base::Passed(&shill_properties_copy_error_copy),
                 send_callback));
}

void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess(
    const std::string& service_path,
    std::unique_ptr<base::DictionaryValue> network_properties,
    GetDevicePropertiesCallback send_callback,
    const std::string& device_path,
    const base::DictionaryValue& device_properties) {
  // Create a "Device" dictionary in |network_properties|.
  network_properties->SetKey(shill::kDeviceProperty, device_properties.Clone());
  send_callback.Run(service_path, std::move(network_properties));
}

void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure(
    const std::string& service_path,
    std::unique_ptr<base::DictionaryValue> network_properties,
    GetDevicePropertiesCallback send_callback,
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG_ERROR("Error getting device properties", service_path);
  send_callback.Run(service_path, std::move(network_properties));
}


}  // namespace chromeos
