blob: 264698cbbd0b9a4502d5932f804d643a35f13853 [file] [log] [blame]
// 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/device_state.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/shill_property_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
DeviceState::DeviceState(const std::string& path)
: ManagedState(MANAGED_TYPE_DEVICE, path),
allow_roaming_(false),
provider_requires_roaming_(false),
support_network_scan_(false),
scanning_(false),
sim_retries_left_(0),
sim_present_(true),
eap_authentication_completed_(false) {
}
DeviceState::~DeviceState() {
}
bool DeviceState::PropertyChanged(const std::string& key,
const base::Value& value) {
// All property values get stored in |properties_|.
properties_.SetWithoutPathExpansion(key, value.DeepCopy());
if (ManagedStatePropertyChanged(key, value))
return true;
if (key == shill::kAddressProperty) {
return GetStringValue(key, value, &mac_address_);
} else if (key == shill::kScanningProperty) {
return GetBooleanValue(key, value, &scanning_);
} else if (key == shill::kSupportNetworkScanProperty) {
return GetBooleanValue(key, value, &support_network_scan_);
} else if (key == shill::kCellularAllowRoamingProperty) {
return GetBooleanValue(key, value, &allow_roaming_);
} else if (key == shill::kProviderRequiresRoamingProperty) {
return GetBooleanValue(key, value, &provider_requires_roaming_);
} else if (key == shill::kHomeProviderProperty) {
return shill_property_util::GetHomeProviderFromProperty(
value, &home_provider_id_);
} else if (key == shill::kTechnologyFamilyProperty) {
return GetStringValue(key, value, &technology_family_);
} else if (key == shill::kCarrierProperty) {
return GetStringValue(key, value, &carrier_);
} else if (key == shill::kFoundNetworksProperty) {
const base::ListValue* list = nullptr;
if (!value.GetAsList(&list))
return false;
CellularScanResults parsed_results;
if (!network_util::ParseCellularScanResults(*list, &parsed_results))
return false;
scan_results_.swap(parsed_results);
return true;
} else if (key == shill::kSIMLockStatusProperty) {
const base::DictionaryValue* dict = nullptr;
if (!value.GetAsDictionary(&dict))
return false;
// Set default values for SIM properties.
sim_lock_type_.erase();
sim_retries_left_ = 0;
const base::Value* out_value = nullptr;
if (dict->GetWithoutPathExpansion(shill::kSIMLockTypeProperty,
&out_value)) {
GetStringValue(shill::kSIMLockTypeProperty, *out_value, &sim_lock_type_);
}
if (dict->GetWithoutPathExpansion(shill::kSIMLockRetriesLeftProperty,
&out_value)) {
GetUInt32Value(shill::kSIMLockRetriesLeftProperty, *out_value,
&sim_retries_left_);
}
return true;
} else if (key == shill::kMeidProperty) {
return GetStringValue(key, value, &meid_);
} else if (key == shill::kImeiProperty) {
return GetStringValue(key, value, &imei_);
} else if (key == shill::kIccidProperty) {
return GetStringValue(key, value, &iccid_);
} else if (key == shill::kMdnProperty) {
return GetStringValue(key, value, &mdn_);
} else if (key == shill::kSIMPresentProperty) {
return GetBooleanValue(key, value, &sim_present_);
} else if (key == shill::kEapAuthenticationCompletedProperty) {
return GetBooleanValue(key, value, &eap_authentication_completed_);
} else if (key == shill::kIPConfigsProperty) {
// If kIPConfigsProperty changes, clear any previous ip_configs_.
// ShillPropertyhandler will request the IPConfig objects which will trigger
// calls to IPConfigPropertiesChanged.
ip_configs_.Clear();
return false; // No actual state change.
}
return false;
}
bool DeviceState::InitialPropertiesReceived(
const base::DictionaryValue& properties) {
// Update UMA stats.
if (sim_present_) {
bool locked = !sim_lock_type_.empty();
UMA_HISTOGRAM_BOOLEAN("Cellular.SIMLocked", locked);
}
return false;
}
void DeviceState::IPConfigPropertiesChanged(
const std::string& ip_config_path,
const base::DictionaryValue& properties) {
base::DictionaryValue* ip_config = nullptr;
if (ip_configs_.GetDictionaryWithoutPathExpansion(
ip_config_path, &ip_config)) {
NET_LOG_EVENT("IPConfig Updated: " + ip_config_path, path());
ip_config->Clear();
} else {
NET_LOG_EVENT("IPConfig Added: " + ip_config_path, path());
ip_config = new base::DictionaryValue;
ip_configs_.SetWithoutPathExpansion(ip_config_path, ip_config);
}
ip_config->MergeDictionary(&properties);
}
std::string DeviceState::GetIpAddressByType(const std::string& type) const {
for (base::DictionaryValue::Iterator iter(ip_configs_); !iter.IsAtEnd();
iter.Advance()) {
const base::DictionaryValue* ip_config;
if (!iter.value().GetAsDictionary(&ip_config))
continue;
std::string ip_config_method;
if (!ip_config->GetString(shill::kMethodProperty, &ip_config_method))
continue;
if (type == ip_config_method ||
(type == shill::kTypeIPv4 && ip_config_method == shill::kTypeDHCP) ||
(type == shill::kTypeIPv6 && ip_config_method == shill::kTypeDHCP6)) {
std::string address;
if (!ip_config->GetString(shill::kAddressProperty, &address))
continue;
return address;
}
}
return std::string();
}
bool DeviceState::IsSimAbsent() const {
return technology_family_ == shill::kTechnologyFamilyGsm && !sim_present_;
}
} // namespace chromeos