// Copyright (c) 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/network_connect.h"

#include <memory>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/values.h"
#include "chromeos/login/login_state.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_activation_handler.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.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/tether_constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

void IgnoreDisconnectError(const std::string& error_name,
                           std::unique_ptr<base::DictionaryValue> error_data) {}

// Returns true for carriers that can be activated through Shill instead of
// through a WebUI dialog.
bool IsDirectActivatedCarrier(const std::string& carrier) {
  if (carrier == shill::kCarrierSprint)
    return true;
  return false;
}

const NetworkState* GetNetworkStateFromId(const std::string& network_id) {
  // Note: network_id === NetworkState::guid.
  return NetworkHandler::Get()
      ->network_state_handler()
      ->GetNetworkStateFromGuid(network_id);
}

class NetworkConnectImpl : public NetworkConnect {
 public:
  explicit NetworkConnectImpl(Delegate* delegate);
  ~NetworkConnectImpl() override;

  // NetworkConnect
  void ConnectToNetworkId(const std::string& network_id) override;
  void DisconnectFromNetworkId(const std::string& network_id) override;
  void SetTechnologyEnabled(const NetworkTypePattern& technology,
                            bool enabled_state) override;
  void ShowMobileSetup(const std::string& network_id) override;
  void ConfigureNetworkIdAndConnect(
      const std::string& network_id,
      const base::DictionaryValue& shill_properties,
      bool shared) override;
  void CreateConfigurationAndConnect(base::DictionaryValue* shill_properties,
                                     bool shared) override;
  void CreateConfiguration(base::DictionaryValue* shill_properties,
                           bool shared) override;

 private:
  void ActivateCellular(const std::string& network_id);
  void HandleUnconfiguredNetwork(const std::string& network_id);
  void OnConnectFailed(const std::string& network_id,
                       const std::string& error_name,
                       std::unique_ptr<base::DictionaryValue> error_data);
  bool GetNetworkProfilePath(bool shared, std::string* profile_path);
  void OnConnectSucceeded(const std::string& network_id);
  void CallConnectToNetwork(const std::string& network_id,
                            bool check_error_state);
  void OnActivateFailed(const std::string& network_id,
                        const std::string& error_name,
                        std::unique_ptr<base::DictionaryValue> error_data);
  void OnActivateSucceeded(const std::string& network_id);
  void OnConfigureFailed(const std::string& error_name,
                         std::unique_ptr<base::DictionaryValue> error_data);
  void OnConfigureSucceeded(bool connect_on_configure,
                            const std::string& service_path,
                            const std::string& network_id);
  void CallCreateConfiguration(base::DictionaryValue* properties,
                               bool shared,
                               bool connect_on_configure);
  void SetPropertiesFailed(const std::string& desc,
                           const std::string& network_id,
                           const std::string& config_error_name,
                           std::unique_ptr<base::DictionaryValue> error_data);
  void SetPropertiesToClear(base::DictionaryValue* properties_to_set,
                            std::vector<std::string>* properties_to_clear);
  void ClearPropertiesAndConnect(
      const std::string& network_id,
      const std::vector<std::string>& properties_to_clear);
  void ConfigureSetProfileSucceeded(
      const std::string& network_id,
      std::unique_ptr<base::DictionaryValue> properties_to_set);

  Delegate* delegate_;
  base::WeakPtrFactory<NetworkConnectImpl> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(NetworkConnectImpl);
};

NetworkConnectImpl::NetworkConnectImpl(Delegate* delegate)
    : delegate_(delegate), weak_factory_(this) {}

NetworkConnectImpl::~NetworkConnectImpl() = default;

void NetworkConnectImpl::HandleUnconfiguredNetwork(
    const std::string& network_id) {
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network) {
    NET_LOG_ERROR("Configuring unknown network", network_id);
    return;
  }

  if (network->type() == shill::kTypeWifi) {
    // If the network does not require a password, do not show the dialog since
    // there is nothing to configure. Likewise, if the network is the underlying
    // Wi-Fi hotspot for a Tether network, do not show the dialog since the
    // Tether component handles this case itself.
    if (network->security_class() != shill::kSecurityNone &&
        network->tether_guid().empty()) {
      delegate_->ShowNetworkConfigure(network_id);
    }
    return;
  }

  if (network->type() == shill::kTypeWimax) {
    delegate_->ShowNetworkConfigure(network_id);
    return;
  }

  if (network->type() == shill::kTypeVPN) {
    // Third-party VPNs handle configuration UI themselves.
    if (network->vpn_provider_type() != shill::kProviderThirdPartyVpn)
      delegate_->ShowNetworkConfigure(network_id);
    return;
  }

  if (network->type() == shill::kTypeCellular) {
    if (network->RequiresActivation()) {
      ActivateCellular(network_id);
      return;
    }
    if (network->cellular_out_of_credits()) {
      ShowMobileSetup(network_id);
      return;
    }
    // No special configure or setup for |network|, show the settings UI.
    if (LoginState::Get()->IsUserLoggedIn())
      delegate_->ShowNetworkSettings(network_id);
    return;
  }
  NOTREACHED();
}

// If |shared| is true, sets |profile_path| to the shared profile path.
// Otherwise sets |profile_path| to the user profile path if authenticated and
// available. Returns 'false' if unable to set |profile_path|.
bool NetworkConnectImpl::GetNetworkProfilePath(bool shared,
                                               std::string* profile_path) {
  if (shared) {
    *profile_path = NetworkProfileHandler::GetSharedProfilePath();
    return true;
  }

  if (!LoginState::Get()->UserHasNetworkProfile()) {
    NET_LOG_ERROR("User profile specified before login", "");
    return false;
  }

  const NetworkProfile* profile =
      NetworkHandler::Get()->network_profile_handler()->GetDefaultUserProfile();
  if (!profile) {
    NET_LOG_ERROR("No user profile for unshared network configuration", "");
    return false;
  }

  *profile_path = profile->path;
  return true;
}

void NetworkConnectImpl::OnConnectFailed(
    const std::string& network_id,
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG(ERROR) << "Connect Failed: " << error_name << " For: " << network_id;

  if (error_name == NetworkConnectionHandler::kErrorConnectFailed ||
      error_name == NetworkConnectionHandler::kErrorBadPassphrase ||
      error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
      error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
      error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
    HandleUnconfiguredNetwork(network_id);
  } else if (error_name ==
             NetworkConnectionHandler::kErrorCertificateRequired) {
    // If ShowEnrollNetwork does fails, treat as an unconfigured network.
    if (!delegate_->ShowEnrollNetwork(network_id))
      HandleUnconfiguredNetwork(network_id);
  }
  // Notifications for other connect failures are handled by
  // NetworkStateNotifier, so no need to do anything else here.
}

void NetworkConnectImpl::OnConnectSucceeded(const std::string& network_id) {
  NET_LOG_USER("Connect Succeeded", network_id);
}

// If |check_error_state| is true, error state for the network is checked,
// otherwise any current error state is ignored (e.g. for recently configured
// networks or repeat connect attempts).
void NetworkConnectImpl::CallConnectToNetwork(const std::string& network_id,
                                              bool check_error_state) {
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network) {
    OnConnectFailed(network_id, NetworkConnectionHandler::kErrorNotFound,
                    nullptr);
    return;
  }

  NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
      network->path(),
      base::Bind(&NetworkConnectImpl::OnConnectSucceeded,
                 weak_factory_.GetWeakPtr(), network_id),
      base::Bind(&NetworkConnectImpl::OnConnectFailed,
                 weak_factory_.GetWeakPtr(), network_id),
      check_error_state, ConnectCallbackMode::ON_COMPLETED);
}

void NetworkConnectImpl::OnActivateFailed(
    const std::string& network_id,
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG_ERROR("Unable to activate network", network_id);
  delegate_->ShowNetworkConnectError(
      NetworkConnectionHandler::kErrorActivateFailed, network_id);
}

void NetworkConnectImpl::OnActivateSucceeded(const std::string& network_id) {
  NET_LOG_USER("Activation Succeeded", network_id);
}

void NetworkConnectImpl::OnConfigureFailed(
    const std::string& error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG_ERROR("Unable to configure network", "");
  delegate_->ShowNetworkConnectError(
      NetworkConnectionHandler::kErrorConfigureFailed, "");
}

void NetworkConnectImpl::OnConfigureSucceeded(bool connect_on_configure,
                                              const std::string& service_path,
                                              const std::string& network_id) {
  NET_LOG_USER("Configure Succeeded", network_id);
  if (!connect_on_configure)
    return;
  // After configuring a network, ignore any (possibly stale) error state.
  const bool check_error_state = false;
  CallConnectToNetwork(network_id, check_error_state);
}

void NetworkConnectImpl::CallCreateConfiguration(
    base::DictionaryValue* shill_properties,
    bool shared,
    bool connect_on_configure) {
  std::string profile_path;
  if (!GetNetworkProfilePath(shared, &profile_path)) {
    delegate_->ShowNetworkConnectError(
        NetworkConnectionHandler::kErrorConfigureFailed, "");
    return;
  }
  shill_properties->SetKey(shill::kProfileProperty, base::Value(profile_path));
  NetworkHandler::Get()
      ->network_configuration_handler()
      ->CreateShillConfiguration(
          *shill_properties,
          base::Bind(&NetworkConnectImpl::OnConfigureSucceeded,
                     weak_factory_.GetWeakPtr(), connect_on_configure),
          base::Bind(&NetworkConnectImpl::OnConfigureFailed,
                     weak_factory_.GetWeakPtr()));
}

void NetworkConnectImpl::SetPropertiesFailed(
    const std::string& desc,
    const std::string& network_id,
    const std::string& config_error_name,
    std::unique_ptr<base::DictionaryValue> error_data) {
  NET_LOG_ERROR(desc + ": Failed: " + config_error_name, network_id);
  delegate_->ShowNetworkConnectError(
      NetworkConnectionHandler::kErrorConfigureFailed, network_id);
}

void NetworkConnectImpl::SetPropertiesToClear(
    base::DictionaryValue* properties_to_set,
    std::vector<std::string>* properties_to_clear) {
  // Move empty string properties to properties_to_clear.
  for (base::DictionaryValue::Iterator iter(*properties_to_set);
       !iter.IsAtEnd(); iter.Advance()) {
    std::string value_str;
    if (iter.value().GetAsString(&value_str) && value_str.empty())
      properties_to_clear->push_back(iter.key());
  }
  // Remove cleared properties from properties_to_set.
  for (std::vector<std::string>::iterator iter = properties_to_clear->begin();
       iter != properties_to_clear->end(); ++iter) {
    properties_to_set->RemoveWithoutPathExpansion(*iter, NULL);
  }
}

void NetworkConnectImpl::ClearPropertiesAndConnect(
    const std::string& network_id,
    const std::vector<std::string>& properties_to_clear) {
  NET_LOG_USER("ClearPropertiesAndConnect", network_id);
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network) {
    SetPropertiesFailed("ClearProperties", network_id,
                        NetworkConnectionHandler::kErrorNotFound, nullptr);
    return;
  }
  // After configuring a network, ignore any (possibly stale) error state.
  const bool check_error_state = false;
  NetworkHandler::Get()->network_configuration_handler()->ClearShillProperties(
      network->path(), properties_to_clear,
      base::Bind(&NetworkConnectImpl::CallConnectToNetwork,
                 weak_factory_.GetWeakPtr(), network_id, check_error_state),
      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
                 weak_factory_.GetWeakPtr(), "ClearProperties", network_id));
}

void NetworkConnectImpl::ConfigureSetProfileSucceeded(
    const std::string& network_id,
    std::unique_ptr<base::DictionaryValue> properties_to_set) {
  std::vector<std::string> properties_to_clear;
  SetPropertiesToClear(properties_to_set.get(), &properties_to_clear);
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network) {
    SetPropertiesFailed("SetProperties", network_id,
                        NetworkConnectionHandler::kErrorNotFound, nullptr);
    return;
  }
  NetworkHandler::Get()->network_configuration_handler()->SetShillProperties(
      network->path(), *properties_to_set,
      base::Bind(&NetworkConnectImpl::ClearPropertiesAndConnect,
                 weak_factory_.GetWeakPtr(), network_id, properties_to_clear),
      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
                 weak_factory_.GetWeakPtr(), "SetProperties", network_id));
}

// Public methods

void NetworkConnectImpl::ConnectToNetworkId(const std::string& network_id) {
  NET_LOG_USER("ConnectToNetwork", network_id);
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (network) {
    if (!network->error().empty() && !network->security_class().empty()) {
      NET_LOG_USER("Configure: " + network->error(), network_id);
      // If the network is in an error state, show the configuration UI
      // directly to avoid a spurious notification.
      HandleUnconfiguredNetwork(network_id);
      return;
    } else if (network->RequiresActivation()) {
      ActivateCellular(network_id);
      return;
    } else if (network->type() == kTypeTether &&
               !network->tether_has_connected_to_host()) {
      delegate_->ShowNetworkConfigure(network_id);
      return;
    }
  }
  const bool check_error_state = true;
  CallConnectToNetwork(network_id, check_error_state);
}

void NetworkConnectImpl::DisconnectFromNetworkId(
    const std::string& network_id) {
  NET_LOG_USER("DisconnectFromNetwork", network_id);
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network)
    return;
  NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
      network->path(), base::DoNothing(), base::Bind(&IgnoreDisconnectError));
}

void NetworkConnectImpl::SetTechnologyEnabled(
    const NetworkTypePattern& technology,
    bool enabled_state) {
  std::string log_string = base::StringPrintf(
      "technology %s, target state: %s", technology.ToDebugString().c_str(),
      (enabled_state ? "ENABLED" : "DISABLED"));
  NET_LOG_USER("SetTechnologyEnabled", log_string);
  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
  bool enabled = handler->IsTechnologyEnabled(technology);
  if (enabled_state == enabled) {
    NET_LOG_USER("Technology already in target state.", log_string);
    return;
  }
  if (enabled) {
    // User requested to disable the technology.
    handler->SetTechnologyEnabled(technology, false,
                                  network_handler::ErrorCallback());
    return;
  }
  // If we're dealing with a cellular network, then handle SIM lock here.
  // SIM locking only applies to cellular.
  if (technology.MatchesPattern(NetworkTypePattern::Cellular())) {
    const DeviceState* mobile = handler->GetDeviceStateByType(technology);
    if (!mobile) {
      NET_LOG_ERROR("SetTechnologyEnabled with no device", log_string);
      return;
    }
    if (mobile->IsSimAbsent()) {
      // If this is true, then we have a cellular device with no SIM
      // inserted. TODO(armansito): Chrome should display a notification here,
      // prompting the user to insert a SIM card and restart the device to
      // enable cellular. See crbug.com/125171.
      NET_LOG_USER("Cannot enable cellular device without SIM.", log_string);
      return;
    }
    if (!mobile->IsSimLocked()) {
      // A SIM has been inserted, but it is locked. Let the user unlock it
      // via Settings or the details dialog.
      const NetworkState* network = handler->FirstNetworkByType(technology);
      delegate_->ShowNetworkSettings(network ? network->guid() : "");
      return;
    }
  }
  handler->SetTechnologyEnabled(technology, true,
                                network_handler::ErrorCallback());
}

void NetworkConnectImpl::ActivateCellular(const std::string& network_id) {
  NET_LOG_USER("ActivateCellular", network_id);
  const NetworkState* cellular = GetNetworkStateFromId(network_id);
  if (!cellular || cellular->type() != shill::kTypeCellular) {
    NET_LOG_ERROR("ActivateCellular with no Service", network_id);
    return;
  }
  const DeviceState* cellular_device =
      NetworkHandler::Get()->network_state_handler()->GetDeviceState(
          cellular->device_path());
  if (!cellular_device) {
    NET_LOG_ERROR("ActivateCellular with no Device", network_id);
    return;
  }
  if (!IsDirectActivatedCarrier(cellular_device->carrier())) {
    // For non direct activation, show the mobile setup dialog which can be
    // used to activate the network.
    ShowMobileSetup(network_id);
    return;
  }
  if (cellular->activation_state() == shill::kActivationStateActivated) {
    NET_LOG_ERROR("ActivateCellular for activated service", network_id);
    return;
  }

  NetworkHandler::Get()->network_activation_handler()->Activate(
      cellular->path(),
      "",  // carrier
      base::Bind(&NetworkConnectImpl::OnActivateSucceeded,
                 weak_factory_.GetWeakPtr(), network_id),
      base::Bind(&NetworkConnectImpl::OnActivateFailed,
                 weak_factory_.GetWeakPtr(), network_id));
}

void NetworkConnectImpl::ShowMobileSetup(const std::string& network_id) {
  const NetworkState* cellular = GetNetworkStateFromId(network_id);
  if (!cellular || cellular->type() != shill::kTypeCellular) {
    NET_LOG_ERROR("ShowMobileSetup without Cellular network", network_id);
    return;
  }
  if (cellular->activation_state() != shill::kActivationStateActivated &&
      cellular->activation_type() == shill::kActivationTypeNonCellular &&
      !NetworkHandler::Get()->network_state_handler()->DefaultNetwork()) {
    delegate_->ShowMobileActivationError(network_id);
    return;
  }
  delegate_->ShowMobileSetupDialog(network_id);
}

void NetworkConnectImpl::ConfigureNetworkIdAndConnect(
    const std::string& network_id,
    const base::DictionaryValue& properties,
    bool shared) {
  NET_LOG_USER("ConfigureNetworkIdAndConnect", network_id);

  std::unique_ptr<base::DictionaryValue> properties_to_set(
      properties.DeepCopy());

  std::string profile_path;
  if (!GetNetworkProfilePath(shared, &profile_path)) {
    delegate_->ShowNetworkConnectError(
        NetworkConnectionHandler::kErrorConfigureFailed, network_id);
    return;
  }
  const NetworkState* network = GetNetworkStateFromId(network_id);
  if (!network) {
    delegate_->ShowNetworkConnectError(NetworkConnectionHandler::kErrorNotFound,
                                       network_id);
    return;
  }
  NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
      network->path(), profile_path,
      base::Bind(&NetworkConnectImpl::ConfigureSetProfileSucceeded,
                 weak_factory_.GetWeakPtr(), network_id,
                 base::Passed(&properties_to_set)),
      base::Bind(&NetworkConnectImpl::SetPropertiesFailed,
                 weak_factory_.GetWeakPtr(), "SetProfile: " + profile_path,
                 network_id));
}

void NetworkConnectImpl::CreateConfigurationAndConnect(
    base::DictionaryValue* properties,
    bool shared) {
  NET_LOG_USER("CreateConfigurationAndConnect", "");
  CallCreateConfiguration(properties, shared, true /* connect_on_configure */);
}

void NetworkConnectImpl::CreateConfiguration(base::DictionaryValue* properties,
                                             bool shared) {
  NET_LOG_USER("CreateConfiguration", "");
  CallCreateConfiguration(properties, shared, false /* connect_on_configure */);
}

}  // namespace

static NetworkConnect* g_network_connect = NULL;

// static
void NetworkConnect::Initialize(Delegate* delegate) {
  CHECK(g_network_connect == NULL);
  g_network_connect = new NetworkConnectImpl(delegate);
}

// static
void NetworkConnect::Shutdown() {
  CHECK(g_network_connect);
  delete g_network_connect;
  g_network_connect = NULL;
}

// static
NetworkConnect* NetworkConnect::Get() {
  CHECK(g_network_connect);
  return g_network_connect;
}

NetworkConnect::NetworkConnect() = default;

NetworkConnect::~NetworkConnect() = default;

}  // namespace chromeos
