// 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/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_manager_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/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 LogErrorWithDict(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);
}

const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies,
                                       const std::string& guid) {
  auto it = policies.find(guid);
  if (it == policies.end())
    return NULL;
  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_->GetProfileForPath(profile_path);
  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.
                           false);  // Don't 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(ERROR) << "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()));

  // 'Carrier' needs to be handled specially if set.
  base::DictionaryValue* cellular = nullptr;
  if (validated_user_settings->GetDictionaryWithoutPathExpansion(
          ::onc::network_config::kCellular, &cellular)) {
    std::string carrier;
    if (cellular->GetStringWithoutPathExpansion(::onc::cellular::kCarrier,
                                                &carrier)) {
      network_device_handler_->SetCarrier(
          state->device_path(), carrier,
          base::Bind(
              &ManagedNetworkConfigurationHandlerImpl::SetShillProperties,
              weak_ptr_factory_.GetWeakPtr(), service_path,
              base::Passed(&shill_dictionary), callback, error_callback),
          error_callback);
      return;
    }
  }

  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 = NULL;
  if (base::ContainsKey(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 = NULL;
    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::ContainsKey(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) {
  network_configuration_handler_->CreateShillConfiguration(
      shill_properties,
      base::Bind(
          &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
          weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&LogErrorWithDict, FROM_HERE));
}

void ManagedNetworkConfigurationHandlerImpl::
    UpdateExistingConfigurationWithPropertiesFromPolicy(
        const base::DictionaryValue& existing_properties,
        const base::DictionaryValue& new_properties) {
  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::Bind(
          &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
          weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&LogErrorWithDict, 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::ContainsKey(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 NULL;
}

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

  return &policies->per_network_config;
}

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

  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 NULL;
  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()
    : network_state_handler_(NULL),
      network_profile_handler_(NULL),
      network_configuration_handler_(NULL),
      network_device_handler_(NULL),
      user_policy_applied_(false),
      device_policy_applied_(false),
      weak_ptr_factory_(this) {
  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;
  network_profile_handler_->AddObserver(this);
  prohibited_technologies_handler_ = prohibited_technologies_handler;
}

void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork(
    const std::string& service_path,
    const std::string& guid) {
  if (service_path.empty())
    return;
  for (auto& observer : observers_)
    observer.PolicyAppliedToNetwork(service_path);
}

// 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->GetList().push_back(network->ipv4_config()->Clone());
  } else {
    // Convert the DeviceState IPConfigs dictionary to a ListValue.
    for (const auto iter : device_state->ip_configs().DictItems())
      ip_configs->GetList().push_back(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
