普通文本  |  286行  |  10.84 KB

// 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 "base/strings/stringprintf.h"
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/shill_property_util.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 IsCaCertNssSet(const base::DictionaryValue& properties) {
  std::string ca_cert_nss;
  if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
                                               &ca_cert_nss) &&
      !ca_cert_nss.empty()) {
    return true;
  }

  const base::DictionaryValue* provider = NULL;
  properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
                                               &provider);
  if (!provider)
    return false;
  if (provider->GetStringWithoutPathExpansion(
          shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) &&
      !ca_cert_nss.empty()) {
    return true;
  }
  if (provider->GetStringWithoutPathExpansion(
          shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) &&
      !ca_cert_nss.empty()) {
    return true;
  }

  return false;
}

}  // namespace

namespace chromeos {

NetworkState::NetworkState(const std::string& path)
    : ManagedState(MANAGED_TYPE_NETWORK, path),
      connectable_(false),
      prefix_length_(0),
      signal_strength_(0),
      activate_over_non_cellular_networks_(false),
      cellular_out_of_credits_(false),
      has_ca_cert_nss_(false) {
}

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) {
    return GetStringValue(key, value, &connection_state_);
  } else if (key == shill::kConnectableProperty) {
    return GetBooleanValue(key, value, &connectable_);
  } else if (key == shill::kErrorProperty) {
    if (!GetStringValue(key, value, &error_))
      return false;
    // Shill uses "Unknown" to indicate an unset error state.
    if (error_ == kErrorUnknown)
      error_.clear();
    return true;
  } else if (key == IPConfigProperty(shill::kAddressProperty)) {
    return GetStringValue(key, value, &ip_address_);
  } else if (key == IPConfigProperty(shill::kGatewayProperty)) {
    return GetStringValue(key, value, &gateway_);
  } else if (key == IPConfigProperty(shill::kNameServersProperty)) {
    const base::ListValue* dns_servers;
    if (!value.GetAsList(&dns_servers))
      return false;
    dns_servers_.clear();
    ConvertListValueToStringVector(*dns_servers, &dns_servers_);
    return true;
  } else if (key == IPConfigProperty(shill::kPrefixlenProperty)) {
    return GetIntegerValue(key, value, &prefix_length_);
  } else if (key == IPConfigProperty(
      shill::kWebProxyAutoDiscoveryUrlProperty)) {
    std::string url_string;
    if (!GetStringValue(key, value, &url_string))
      return false;
    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: " + url_string,
                      path());
        web_proxy_auto_discovery_url_ = GURL();
      }
    }
    return true;
  } 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::kSecurityProperty) {
    return GetStringValue(key, value, &security_);
  } else if (key == shill::kEapMethodProperty) {
    return GetStringValue(key, value, &eap_method_);
  } else if (key == shill::kUIDataProperty) {
    scoped_ptr<NetworkUIData> new_ui_data =
        shill_property_util::GetUIDataFromValue(value);
    if (!new_ui_data) {
      NET_LOG_ERROR("Failed to parse " + key, path());
      return false;
    }
    ui_data_ = *new_ui_data;
    return true;
  } 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::kActivateOverNonCellularNetworkProperty) {
    return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
  } else if (key == shill::kOutOfCreditsProperty) {
    return GetBooleanValue(key, value, &cellular_out_of_credits_);
  }
  return false;
}

bool NetworkState::InitialPropertiesReceived(
    const base::DictionaryValue& properties) {
  NET_LOG_DEBUG("InitialPropertiesReceived", path());
  bool changed = UpdateName(properties);
  bool had_ca_cert_nss = has_ca_cert_nss_;
  has_ca_cert_nss_ = IsCaCertNssSet(properties);
  changed |= had_ca_cert_nss != has_ca_cert_nss_;
  return changed;
}

void NetworkState::GetProperties(base::DictionaryValue* dictionary) const {
  // Keep care that these properties are the same as in |PropertyChanged|.
  dictionary->SetStringWithoutPathExpansion(shill::kNameProperty, name());
  dictionary->SetStringWithoutPathExpansion(shill::kTypeProperty, type());
  dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
                                             signal_strength_);
  dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
                                            connection_state_);
  dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
                                             connectable_);

  dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error_);

  // IPConfig properties
  base::DictionaryValue* ipconfig_properties = new base::DictionaryValue;
  ipconfig_properties->SetStringWithoutPathExpansion(shill::kAddressProperty,
                                                     ip_address_);
  ipconfig_properties->SetStringWithoutPathExpansion(shill::kGatewayProperty,
                                                     gateway_);
  base::ListValue* name_servers = new base::ListValue;
  name_servers->AppendStrings(dns_servers_);
  ipconfig_properties->SetWithoutPathExpansion(shill::kNameServersProperty,
                                               name_servers);
  ipconfig_properties->SetStringWithoutPathExpansion(
      shill::kWebProxyAutoDiscoveryUrlProperty,
      web_proxy_auto_discovery_url_.spec());
  dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty,
                                      ipconfig_properties);

  dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
                                            activation_state_);
  dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
                                            roaming_);
  dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
                                            security_);
  dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
                                            eap_method_);
  // Proxy config and ONC source are intentionally omitted: These properties are
  // placed in NetworkState to transition ProxyConfigServiceImpl from
  // NetworkLibrary to the new network stack. The networking extension API
  // shouldn't depend on this member. Once ManagedNetworkConfigurationHandler
  // is used instead of NetworkLibrary, we can remove them again.
  dictionary->SetStringWithoutPathExpansion(
      shill::kNetworkTechnologyProperty,
      network_technology_);
  dictionary->SetStringWithoutPathExpansion(shill::kDeviceProperty,
                                            device_path_);
  dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid_);
  dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
                                            profile_path_);
  dictionary->SetBooleanWithoutPathExpansion(
      shill::kActivateOverNonCellularNetworkProperty,
      activate_over_non_cellular_networks_);
  dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
                                             cellular_out_of_credits_);
}

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

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

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

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

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_);
}

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;
}

// 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
std::string NetworkState::IPConfigProperty(const char* key) {
  return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key);
}

}  // namespace chromeos