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

#include <stddef.h>

#include <memory>

#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_type_pattern.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/shill_property_util.h"
#include "components/device_event_log/device_event_log.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace {

const char kErrorUnknown[] = "Unknown";

bool ConvertListValueToStringVector(const base::ListValue& string_list,
                                    std::vector<std::string>* result) {
  for (size_t i = 0; i < string_list.GetSize(); ++i) {
    std::string str;
    if (!string_list.GetString(i, &str))
      return false;
    result->push_back(str);
  }
  return true;
}

bool IsCaptivePortalState(const base::DictionaryValue& properties, bool log) {
  std::string state;
  properties.GetStringWithoutPathExpansion(shill::kStateProperty, &state);
  if (state != shill::kStatePortal)
    return false;
  std::string portal_detection_phase, portal_detection_status;
  if (!properties.GetStringWithoutPathExpansion(
          shill::kPortalDetectionFailedPhaseProperty,
          &portal_detection_phase) ||
      !properties.GetStringWithoutPathExpansion(
          shill::kPortalDetectionFailedStatusProperty,
          &portal_detection_status)) {
    // If Shill (or a stub) has not set PortalDetectionFailedStatus
    // or PortalDetectionFailedPhase, assume we are in captive portal state.
    return true;
  }

  // Shill reports the phase in which it determined that the device is behind a
  // captive portal. We only want to rely only on incorrect content being
  // returned and ignore other reasons.
  bool is_captive_portal =
      portal_detection_phase == shill::kPortalDetectionPhaseContent &&
      portal_detection_status == shill::kPortalDetectionStatusFailure;

  if (log) {
    std::string name;
    properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
    if (name.empty())
      properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &name);
    if (!is_captive_portal) {
      NET_LOG(EVENT) << "State is 'portal' but not in captive portal state:"
                     << " name=" << name << " phase=" << portal_detection_phase
                     << " status=" << portal_detection_status;
    } else {
      NET_LOG(EVENT) << "Network is in captive portal state: " << name;
    }
  }

  return is_captive_portal;
}

}  // namespace

namespace chromeos {

NetworkState::NetworkState(const std::string& path)
    : ManagedState(MANAGED_TYPE_NETWORK, path) {}

NetworkState::~NetworkState() {}

bool NetworkState::PropertyChanged(const std::string& key,
                                   const base::Value& value) {
  // Keep care that these properties are the same as in |GetProperties|.
  if (ManagedStatePropertyChanged(key, value))
    return true;
  if (key == shill::kSignalStrengthProperty) {
    return GetIntegerValue(key, value, &signal_strength_);
  } else if (key == shill::kStateProperty) {
    std::string saved_state = connection_state_;
    if (GetStringValue(key, value, &connection_state_)) {
      if (connection_state_ != saved_state)
        last_connection_state_ = saved_state;
      return true;
    } else {
      return false;
    }
  } else if (key == shill::kVisibleProperty) {
    return GetBooleanValue(key, value, &visible_);
  } else if (key == shill::kConnectableProperty) {
    return GetBooleanValue(key, value, &connectable_);
  } else if (key == shill::kErrorProperty) {
    if (!GetStringValue(key, value, &error_))
      return false;
    if (ErrorIsValid(error_))
      last_error_ = error_;
    else
      error_.clear();
    return true;
  } else if (key == shill::kWifiFrequency) {
    return GetIntegerValue(key, value, &frequency_);
  } else if (key == shill::kActivationTypeProperty) {
    return GetStringValue(key, value, &activation_type_);
  } else if (key == shill::kActivationStateProperty) {
    return GetStringValue(key, value, &activation_state_);
  } else if (key == shill::kRoamingStateProperty) {
    return GetStringValue(key, value, &roaming_);
  } else if (key == shill::kPaymentPortalProperty) {
    const base::DictionaryValue* olp;
    if (!value.GetAsDictionary(&olp))
      return false;
    return olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL,
                                              &payment_url_);
  } else if (key == shill::kSecurityClassProperty) {
    return GetStringValue(key, value, &security_class_);
  } else if (key == shill::kEapMethodProperty) {
    return GetStringValue(key, value, &eap_method_);
  } else if (key == shill::kEapKeyMgmtProperty) {
    return GetStringValue(key, value, &eap_key_mgmt_);
  } else if (key == shill::kNetworkTechnologyProperty) {
    return GetStringValue(key, value, &network_technology_);
  } else if (key == shill::kDeviceProperty) {
    return GetStringValue(key, value, &device_path_);
  } else if (key == shill::kGuidProperty) {
    return GetStringValue(key, value, &guid_);
  } else if (key == shill::kProfileProperty) {
    return GetStringValue(key, value, &profile_path_);
  } else if (key == shill::kWifiHexSsid) {
    std::string ssid_hex;
    if (!GetStringValue(key, value, &ssid_hex))
      return false;
    raw_ssid_.clear();
    return base::HexStringToBytes(ssid_hex, &raw_ssid_);
  } else if (key == shill::kWifiBSsid) {
    return GetStringValue(key, value, &bssid_);
  } else if (key == shill::kPriorityProperty) {
    return GetIntegerValue(key, value, &priority_);
  } else if (key == shill::kOutOfCreditsProperty) {
    return GetBooleanValue(key, value, &cellular_out_of_credits_);
  } else if (key == shill::kProxyConfigProperty) {
    std::string proxy_config_str;
    if (!value.GetAsString(&proxy_config_str)) {
      NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
      return false;
    }

    proxy_config_.Clear();
    if (proxy_config_str.empty())
      return true;

    std::unique_ptr<base::DictionaryValue> proxy_config_dict(
        onc::ReadDictionaryFromJson(proxy_config_str));
    if (proxy_config_dict) {
      // Warning: The DictionaryValue returned from
      // ReadDictionaryFromJson/JSONParser is an optimized derived class that
      // doesn't allow releasing ownership of nested values. A Swap in the wrong
      // order leads to memory access errors.
      proxy_config_.MergeDictionary(proxy_config_dict.get());
    } else {
      NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
    }
    return true;
  } else if (key == shill::kProviderProperty) {
    std::string vpn_provider_type;
    const base::DictionaryValue* dict;
    if (!value.GetAsDictionary(&dict) ||
        !dict->GetStringWithoutPathExpansion(shill::kTypeProperty,
                                             &vpn_provider_type)) {
      NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
      return false;
    }

    if (vpn_provider_type == shill::kProviderThirdPartyVpn) {
      // If the network uses a third-party VPN provider, copy over the
      // provider's extension ID, which is held in |shill::kHostProperty|.
      if (!dict->GetStringWithoutPathExpansion(
              shill::kHostProperty, &third_party_vpn_provider_extension_id_)) {
        NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
        return false;
      }
    } else {
      third_party_vpn_provider_extension_id_.clear();
    }

    vpn_provider_type_ = vpn_provider_type;
    return true;
  }
  return false;
}

bool NetworkState::InitialPropertiesReceived(
    const base::DictionaryValue& properties) {
  NET_LOG(EVENT) << "InitialPropertiesReceived: " << path() << ": " << name()
                 << " State: " << connection_state_ << " Visible: " << visible_;
  if (!properties.HasKey(shill::kTypeProperty)) {
    NET_LOG(ERROR) << "NetworkState has no type: "
                   << shill_property_util::GetNetworkIdFromProperties(
                          properties);
    return false;
  }

  // By convention, all visible WiFi and WiMAX networks have a
  // SignalStrength > 0.
  if ((type() == shill::kTypeWifi || type() == shill::kTypeWimax) &&
      visible() && signal_strength_ <= 0) {
    signal_strength_ = 1;
  }

  // Any change to connection state will trigger a complete property update,
  // so we update is_captive_portal_ here.
  is_captive_portal_ = IsCaptivePortalState(properties, true /* log */);

  // Ensure that the network has a valid name.
  return UpdateName(properties);
}

void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
  ManagedState::GetStateProperties(dictionary);

  // Properties shared by all types.
  dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
  dictionary->SetStringWithoutPathExpansion(shill::kSecurityClassProperty,
                                            security_class());
  dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
                                            profile_path());
  dictionary->SetIntegerWithoutPathExpansion(shill::kPriorityProperty,
                                             priority_);

  if (visible()) {
    dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
                                              connection_state());
  }

  // VPN properties.
  if (NetworkTypePattern::VPN().MatchesType(type())) {
    // Shill sends VPN provider properties in a nested dictionary. |dictionary|
    // must replicate that nested structure.
    std::unique_ptr<base::DictionaryValue> provider_property(
        new base::DictionaryValue);
    provider_property->SetStringWithoutPathExpansion(shill::kTypeProperty,
                                                     vpn_provider_type_);
    if (vpn_provider_type_ == shill::kProviderThirdPartyVpn) {
      provider_property->SetStringWithoutPathExpansion(
          shill::kHostProperty, third_party_vpn_provider_extension_id_);
    }
    dictionary->SetWithoutPathExpansion(shill::kProviderProperty,
                                        provider_property.release());
  }

  // Wireless properties
  if (!NetworkTypePattern::Wireless().MatchesType(type()))
    return;

  if (visible()) {
    dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
                                               connectable());
    dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
                                               signal_strength());
  }

  // Wifi properties
  if (NetworkTypePattern::WiFi().MatchesType(type())) {
    dictionary->SetStringWithoutPathExpansion(shill::kWifiBSsid, bssid_);
    dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
                                              eap_method());
    dictionary->SetIntegerWithoutPathExpansion(shill::kWifiFrequency,
                                               frequency_);
  }

  // Mobile properties
  if (NetworkTypePattern::Mobile().MatchesType(type())) {
    dictionary->SetStringWithoutPathExpansion(shill::kNetworkTechnologyProperty,
                                              network_technology());
    dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
                                              activation_state());
    dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
                                              roaming());
    dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
                                               cellular_out_of_credits());
  }
}

void NetworkState::IPConfigPropertiesChanged(
    const base::DictionaryValue& properties) {
  for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
       iter.Advance()) {
    std::string key = iter.key();
    const base::Value& value = iter.value();

    if (key == shill::kAddressProperty) {
      GetStringValue(key, value, &ip_address_);
    } else if (key == shill::kGatewayProperty) {
      GetStringValue(key, value, &gateway_);
    } else if (key == shill::kNameServersProperty) {
      const base::ListValue* dns_servers;
      if (value.GetAsList(&dns_servers)) {
        dns_servers_.clear();
        ConvertListValueToStringVector(*dns_servers, &dns_servers_);
      }
    } else if (key == shill::kPrefixlenProperty) {
      GetIntegerValue(key, value, &prefix_length_);
    } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
      std::string url_string;
      if (GetStringValue(key, value, &url_string)) {
        if (url_string.empty()) {
          web_proxy_auto_discovery_url_ = GURL();
        } else {
          GURL gurl(url_string);
          if (gurl.is_valid()) {
            web_proxy_auto_discovery_url_ = gurl;
          } else {
            NET_LOG(ERROR) << "Invalid WebProxyAutoDiscoveryUrl: " << path()
                           << ": " << url_string;
            web_proxy_auto_discovery_url_ = GURL();
          }
        }
      }
    }
  }
}

bool NetworkState::RequiresActivation() const {
  return (type() == shill::kTypeCellular &&
          activation_state() != shill::kActivationStateActivated &&
          activation_state() != shill::kActivationStateUnknown);
}

std::string NetworkState::connection_state() const {
  if (!visible())
    return shill::kStateDisconnect;
  return connection_state_;
}

bool NetworkState::IsDynamicWep() const {
  return security_class_ == shill::kSecurityWep &&
         eap_key_mgmt_ == shill::kKeyManagementIEEE8021X;
}

bool NetworkState::IsConnectedState() const {
  return visible() && StateIsConnected(connection_state_);
}

bool NetworkState::IsConnectingState() const {
  return visible() && StateIsConnecting(connection_state_);
}

bool NetworkState::IsReconnecting() const {
  return visible() && StateIsConnecting(connection_state_) &&
         StateIsConnected(last_connection_state_);
}

bool NetworkState::IsInProfile() const {
  // kTypeEthernetEap is always saved. We need this check because it does
  // not show up in the visible list, but its properties may not be available
  // when it first shows up in ServiceCompleteList. See crbug.com/355117.
  return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
}

bool NetworkState::IsPrivate() const {
  return !profile_path_.empty() &&
         profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
}

std::string NetworkState::GetHexSsid() const {
  return base::HexEncode(raw_ssid().data(), raw_ssid().size());
}

std::string NetworkState::GetDnsServersAsString() const {
  std::string result;
  for (size_t i = 0; i < dns_servers_.size(); ++i) {
    if (i != 0)
      result += ",";
    result += dns_servers_[i];
  }
  return result;
}

std::string NetworkState::GetNetmask() const {
  return network_util::PrefixLengthToNetmask(prefix_length_);
}

std::string NetworkState::GetSpecifier() const {
  if (!update_received()) {
    NET_LOG(ERROR) << "GetSpecifier called before update: " << path();
    return std::string();
  }
  if (type() == shill::kTypeWifi)
    return name() + "_" + security_class_;
  if (!name().empty())
    return name();
  return type();  // For unnamed networks such as ethernet.
}

void NetworkState::SetGuid(const std::string& guid) {
  guid_ = guid;
}

bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
  std::string updated_name =
      shill_property_util::GetNameFromProperties(path(), properties);
  if (updated_name != name()) {
    set_name(updated_name);
    return true;
  }
  return false;
}

std::string NetworkState::GetErrorState() const {
  if (ErrorIsValid(error()))
    return error();
  return last_error();
}

// static
bool NetworkState::StateIsConnected(const std::string& connection_state) {
  return (connection_state == shill::kStateReady ||
          connection_state == shill::kStateOnline ||
          connection_state == shill::kStatePortal);
}

// static
bool NetworkState::StateIsConnecting(const std::string& connection_state) {
  return (connection_state == shill::kStateAssociation ||
          connection_state == shill::kStateConfiguration ||
          connection_state == shill::kStateCarrier);
}

// static
bool NetworkState::NetworkStateIsCaptivePortal(
    const base::DictionaryValue& shill_properties) {
  return IsCaptivePortalState(shill_properties, false /* log */);
}

// static
bool NetworkState::ErrorIsValid(const std::string& error) {
  // Shill uses "Unknown" to indicate an unset or cleared error state.
  return !error.empty() && error != kErrorUnknown;
}

}  // namespace chromeos
