// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/network_change_manager_client.h"

#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/network_service_util.h"
#include "net/base/network_change_notifier_posix.h"
#include "services/network/public/mojom/network_service.mojom.h"

namespace chromeos {

NetworkChangeManagerClient::NetworkChangeManagerClient(
    net::NetworkChangeNotifierPosix* network_change_notifier)
    : connection_type_(net::NetworkChangeNotifier::CONNECTION_NONE),
      connection_subtype_(net::NetworkChangeNotifier::SUBTYPE_NONE),
      network_change_notifier_(network_change_notifier) {
  PowerManagerClient::Get()->AddObserver(this);
  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);

  if (content::IsOutOfProcessNetworkService())
    ConnectToNetworkChangeManager();

  // Update initial connection state.
  DefaultNetworkChanged(
      NetworkHandler::Get()->network_state_handler()->DefaultNetwork());
}

NetworkChangeManagerClient::~NetworkChangeManagerClient() {
  NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
                                                                 FROM_HERE);
  PowerManagerClient::Get()->RemoveObserver(this);
}

void NetworkChangeManagerClient::SuspendDone(
    const base::TimeDelta& sleep_duration) {
  // Force invalidation of network resources on resume.
  network_change_notifier_->OnIPAddressChanged();
  if (network_change_manager_) {
    network_change_manager_->OnNetworkChanged(
        /*dns_changed=*/false, /*ip_address_changed=*/true,
        /*connection_type_changed=*/false,
        network::mojom::ConnectionType::CONNECTION_UNKNOWN,
        /*connection_subtype_changed=*/false,
        network::mojom::ConnectionSubtype::SUBTYPE_NONE);
  }
}

void NetworkChangeManagerClient::DefaultNetworkChanged(
    const chromeos::NetworkState* default_network) {
  bool connection_type_changed = false;
  bool connection_subtype_changed = false;
  bool ip_address_changed = false;
  bool dns_changed = false;

  UpdateState(default_network, &dns_changed, &ip_address_changed,
              &connection_type_changed, &connection_subtype_changed);

  if (ip_address_changed)
    network_change_notifier_->OnIPAddressChanged();
  if (dns_changed)
    network_change_notifier_->OnDNSChanged();
  if (connection_type_changed)
    network_change_notifier_->OnConnectionChanged(connection_type_);
  if (connection_subtype_changed || connection_type_changed)
    network_change_notifier_->OnConnectionSubtypeChanged(connection_type_,
                                                         connection_subtype_);

  if (network_change_manager_) {
    network_change_manager_->OnNetworkChanged(
        dns_changed, ip_address_changed, connection_type_changed,
        network::mojom::ConnectionType(connection_type_),
        connection_subtype_changed,
        network::mojom::ConnectionSubtype(connection_subtype_));
  }
}

void NetworkChangeManagerClient::ConnectToNetworkChangeManager() {
  network::mojom::NetworkChangeManagerRequest request(
      mojo::MakeRequest(&network_change_manager_));
  content::GetNetworkService()->GetNetworkChangeManager(std::move(request));
  network_change_manager_.set_connection_error_handler(base::BindOnce(
      &NetworkChangeManagerClient::ReconnectToNetworkChangeManager,
      base::Unretained(this)));
}

void NetworkChangeManagerClient::ReconnectToNetworkChangeManager() {
  ConnectToNetworkChangeManager();

  // Tell the restarted network service what the current connection type is.
  network_change_manager_->OnNetworkChanged(
      /*dns_changed=*/false, /*ip_address_changed=*/false,
      /*connection_type_changed=*/true,
      network::mojom::ConnectionType(connection_type_),
      /*connection_subtype_changed=*/true,
      network::mojom::ConnectionSubtype(connection_subtype_));
}

void NetworkChangeManagerClient::UpdateState(
    const chromeos::NetworkState* default_network,
    bool* dns_changed,
    bool* ip_address_changed,
    bool* connection_type_changed,
    bool* connection_subtype_changed) {
  *connection_type_changed = false;
  *connection_subtype_changed = false;
  *ip_address_changed = false;
  *dns_changed = false;

  if (!default_network || !default_network->IsConnectedState()) {
    // If we lost a default network, we must update our state and notify
    // observers, otherwise we have nothing to do.
    if (connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE) {
      NET_LOG_EVENT("NCNDefaultNetworkLost", service_path_);
      *ip_address_changed = true;
      *dns_changed = true;
      *connection_type_changed = true;
      *connection_subtype_changed = true;
      connection_type_ = net::NetworkChangeNotifier::CONNECTION_NONE;
      connection_subtype_ = net::NetworkChangeNotifier::SUBTYPE_NONE;
      service_path_.clear();
      ip_address_.clear();
      dns_servers_.clear();
    }
    return;
  }

  // We do have a default network and it is connected.
  net::NetworkChangeNotifier::ConnectionType new_connection_type =
      ConnectionTypeFromShill(default_network->type(),
                              default_network->network_technology());
  if (new_connection_type != connection_type_) {
    NET_LOG_EVENT(
        "NCNDefaultConnectionTypeChanged",
        base::StringPrintf("%s -> %s",
                           net::NetworkChangeNotifier::ConnectionTypeToString(
                               connection_type_),
                           net::NetworkChangeNotifier::ConnectionTypeToString(
                               new_connection_type)));
    *connection_type_changed = true;
  }
  if (default_network->path() != service_path_) {
    NET_LOG_EVENT("NCNDefaultNetworkServicePathChanged",
                  base::StringPrintf("%s -> %s", service_path_.c_str(),
                                     default_network->path().c_str()));

    // If we had a default network service change, network resources
    // must always be invalidated.
    *ip_address_changed = true;
    *dns_changed = true;
  }

  std::string new_ip_address = default_network->GetIpAddress();
  if (new_ip_address != ip_address_) {
    // Is this a state update with an online->online transition?
    bool stayed_online =
        (!*connection_type_changed &&
         connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE);

    bool is_suppressed = true;
    // Suppress IP address change signalling on online->online transitions
    // when getting an IP address update for the first time.
    if (!(stayed_online && ip_address_.empty())) {
      is_suppressed = false;
      *ip_address_changed = true;
    }
    NET_LOG_EVENT(base::StringPrintf("%s%s", "NCNDefaultIPAddressChanged",
                                     is_suppressed ? " (Suppressed)" : ""),
                  base::StringPrintf("%s -> %s", ip_address_.c_str(),
                                     new_ip_address.c_str()));
  }
  std::string new_dns_servers = default_network->GetDnsServersAsString();
  if (new_dns_servers != dns_servers_) {
    NET_LOG_EVENT("NCNDefaultDNSServerChanged",
                  base::StringPrintf("%s -> %s", dns_servers_.c_str(),
                                     new_dns_servers.c_str()));
    *dns_changed = true;
  }

  connection_type_ = new_connection_type;
  service_path_ = default_network->path();
  ip_address_ = new_ip_address;
  dns_servers_ = new_dns_servers;
  net::NetworkChangeNotifier::ConnectionSubtype new_subtype =
      GetConnectionSubtype(default_network->type(),
                           default_network->network_technology());
  if (new_subtype != connection_subtype_) {
    connection_subtype_ = new_subtype;
    *connection_subtype_changed = true;
  }
}

// static
net::NetworkChangeNotifier::ConnectionType
NetworkChangeManagerClient::ConnectionTypeFromShill(
    const std::string& type,
    const std::string& technology) {
  if (NetworkTypePattern::Ethernet().MatchesType(type))
    return net::NetworkChangeNotifier::CONNECTION_ETHERNET;
  if (type == shill::kTypeWifi)
    return net::NetworkChangeNotifier::CONNECTION_WIFI;
  if (type == shill::kTypeWimax)
    return net::NetworkChangeNotifier::CONNECTION_4G;
  if (type == shill::kTypeBluetooth)
    return net::NetworkChangeNotifier::CONNECTION_BLUETOOTH;

  if (type != shill::kTypeCellular)
    return net::NetworkChangeNotifier::CONNECTION_UNKNOWN;

  // For cellular types, mapping depends on the technology.
  if (technology == shill::kNetworkTechnologyEvdo ||
      technology == shill::kNetworkTechnologyGsm ||
      technology == shill::kNetworkTechnologyUmts ||
      technology == shill::kNetworkTechnologyHspa) {
    return net::NetworkChangeNotifier::CONNECTION_3G;
  }
  if (technology == shill::kNetworkTechnologyHspaPlus ||
      technology == shill::kNetworkTechnologyLte ||
      technology == shill::kNetworkTechnologyLteAdvanced) {
    return net::NetworkChangeNotifier::CONNECTION_4G;
  }

  // Default cellular type is 2G.
  return net::NetworkChangeNotifier::CONNECTION_2G;
}

// static
net::NetworkChangeNotifier::ConnectionSubtype
NetworkChangeManagerClient::GetConnectionSubtype(
    const std::string& type,
    const std::string& technology) {
  if (type != shill::kTypeCellular)
    return net::NetworkChangeNotifier::SUBTYPE_UNKNOWN;

  if (technology == shill::kNetworkTechnology1Xrtt)
    return net::NetworkChangeNotifier::SUBTYPE_1XRTT;
  if (technology == shill::kNetworkTechnologyEvdo)
    return net::NetworkChangeNotifier::SUBTYPE_EVDO_REV_0;
  if (technology == shill::kNetworkTechnologyGsm)
    return net::NetworkChangeNotifier::SUBTYPE_GSM;
  if (technology == shill::kNetworkTechnologyGprs)
    return net::NetworkChangeNotifier::SUBTYPE_GPRS;
  if (technology == shill::kNetworkTechnologyEdge)
    return net::NetworkChangeNotifier::SUBTYPE_EDGE;
  if (technology == shill::kNetworkTechnologyUmts)
    return net::NetworkChangeNotifier::SUBTYPE_UMTS;
  if (technology == shill::kNetworkTechnologyHspa)
    return net::NetworkChangeNotifier::SUBTYPE_HSPA;
  if (technology == shill::kNetworkTechnologyHspaPlus)
    return net::NetworkChangeNotifier::SUBTYPE_HSPAP;
  if (technology == shill::kNetworkTechnologyLte)
    return net::NetworkChangeNotifier::SUBTYPE_LTE;
  if (technology == shill::kNetworkTechnologyLteAdvanced)
    return net::NetworkChangeNotifier::SUBTYPE_LTE_ADVANCED;

  return net::NetworkChangeNotifier::SUBTYPE_UNKNOWN;
}

}  // namespace chromeos
