blob: b8cf380e3e112ff59393cb9eda2122df953ffba9 [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 "chrome/browser/chromeos/cros/cros_network_functions.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_tokenizer.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/sms_watcher.h"
#include "chromeos/dbus/cashew_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_ipconfig_client.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_network_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/shill_service_client.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
// Class to watch network manager's properties without Libcros.
class NetworkManagerPropertiesWatcher : public CrosNetworkWatcher {
public:
NetworkManagerPropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback) {
DBusThreadManager::Get()->GetShillManagerClient()->
SetPropertyChangedHandler(base::Bind(callback,
flimflam::kFlimflamServicePath));
}
virtual ~NetworkManagerPropertiesWatcher() {
DBusThreadManager::Get()->GetShillManagerClient()->
ResetPropertyChangedHandler();
}
};
// Class to watch network service's properties without Libcros.
class NetworkServicePropertiesWatcher : public CrosNetworkWatcher {
public:
NetworkServicePropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback,
const std::string& service_path) : service_path_(service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->
SetPropertyChangedHandler(dbus::ObjectPath(service_path),
base::Bind(callback, service_path));
}
virtual ~NetworkServicePropertiesWatcher() {
DBusThreadManager::Get()->GetShillServiceClient()->
ResetPropertyChangedHandler(dbus::ObjectPath(service_path_));
}
private:
std::string service_path_;
};
// Class to watch network device's properties without Libcros.
class NetworkDevicePropertiesWatcher : public CrosNetworkWatcher {
public:
NetworkDevicePropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback,
const std::string& device_path) : device_path_(device_path) {
DBusThreadManager::Get()->GetShillDeviceClient()->
SetPropertyChangedHandler(dbus::ObjectPath(device_path),
base::Bind(callback, device_path));
}
virtual ~NetworkDevicePropertiesWatcher() {
DBusThreadManager::Get()->GetShillDeviceClient()->
ResetPropertyChangedHandler(dbus::ObjectPath(device_path_));
}
private:
std::string device_path_;
};
// Converts a string to a CellularDataPlanType.
CellularDataPlanType ParseCellularDataPlanType(const std::string& type) {
if (type == cashew::kCellularDataPlanUnlimited)
return CELLULAR_DATA_PLAN_UNLIMITED;
if (type == cashew::kCellularDataPlanMeteredPaid)
return CELLULAR_DATA_PLAN_METERED_PAID;
if (type == cashew::kCellularDataPlanMeteredBase)
return CELLULAR_DATA_PLAN_METERED_BASE;
return CELLULAR_DATA_PLAN_UNKNOWN;
}
// Gets a string property from dictionary.
bool GetStringProperty(const base::DictionaryValue& dictionary,
const std::string& key,
std::string* out) {
const bool result = dictionary.GetStringWithoutPathExpansion(key, out);
LOG_IF(WARNING, !result) << "Cannnot get property " << key;
return result;
}
// Gets an int64 property from dictionary.
bool GetInt64Property(const base::DictionaryValue& dictionary,
const std::string& key,
int64* out) {
// Int64 value is stored as a double because it cannot be fitted in int32.
double value_double = 0;
const bool result = dictionary.GetDoubleWithoutPathExpansion(key,
&value_double);
if (result)
*out = value_double;
else
LOG(WARNING) << "Cannnot get property " << key;
return result;
}
// Gets a base::Time property from dictionary.
bool GetTimeProperty(const base::DictionaryValue& dictionary,
const std::string& key,
base::Time* out) {
int64 value_int64 = 0;
if (!GetInt64Property(dictionary, key, &value_int64))
return false;
*out = base::Time::FromInternalValue(value_int64);
return true;
}
// Class to watch data plan update without Libcros.
class DataPlanUpdateWatcher : public CrosNetworkWatcher {
public:
explicit DataPlanUpdateWatcher(const DataPlanUpdateWatcherCallback& callback)
: callback_(callback) {
DBusThreadManager::Get()->GetCashewClient()->SetDataPlansUpdateHandler(
base::Bind(&DataPlanUpdateWatcher::OnDataPlansUpdate,
base::Unretained(this)));
}
virtual ~DataPlanUpdateWatcher() {
DBusThreadManager::Get()->GetCashewClient()->ResetDataPlansUpdateHandler();
}
private:
void OnDataPlansUpdate(const std::string& service,
const base::ListValue& data_plans) {
CellularDataPlanVector* data_plan_vector = new CellularDataPlanVector;
for (size_t i = 0; i != data_plans.GetSize(); ++i) {
const base::DictionaryValue* data_plan = NULL;
if (!data_plans.GetDictionary(i, &data_plan)) {
LOG(ERROR) << "data_plans[" << i << "] is not a dictionary.";
continue;
}
CellularDataPlan* plan = new CellularDataPlan;
// Plan name.
GetStringProperty(*data_plan, cashew::kCellularPlanNameProperty,
&plan->plan_name);
// Plan type.
std::string plan_type_string;
GetStringProperty(*data_plan, cashew::kCellularPlanTypeProperty,
&plan_type_string);
plan->plan_type = ParseCellularDataPlanType(plan_type_string);
// Update time.
GetTimeProperty(*data_plan, cashew::kCellularPlanUpdateTimeProperty,
&plan->update_time);
// Start time.
GetTimeProperty(*data_plan, cashew::kCellularPlanStartProperty,
&plan->plan_start_time);
// End time.
GetTimeProperty(*data_plan, cashew::kCellularPlanEndProperty,
&plan->plan_end_time);
// Data bytes.
GetInt64Property(*data_plan, cashew::kCellularPlanDataBytesProperty,
&plan->plan_data_bytes);
// Bytes used.
GetInt64Property(*data_plan, cashew::kCellularDataBytesUsedProperty,
&plan->data_bytes_used);
data_plan_vector->push_back(plan);
}
callback_.Run(service, data_plan_vector);
}
DataPlanUpdateWatcherCallback callback_;
};
// Does nothing. Used as a callback.
void DoNothing(DBusMethodCallStatus call_status) {}
// A callback used to implement CrosRequest*Properties functions.
void RunCallbackWithDictionaryValue(const NetworkPropertiesCallback& callback,
const std::string& path,
DBusMethodCallStatus call_status,
const base::DictionaryValue& value) {
callback.Run(path, call_status == DBUS_METHOD_CALL_SUCCESS ? &value : NULL);
}
// Used as a callback for ShillManagerClient::GetService
void OnGetService(const NetworkPropertiesCallback& callback,
DBusMethodCallStatus call_status,
const dbus::ObjectPath& service_path) {
if (call_status == DBUS_METHOD_CALL_SUCCESS) {
VLOG(1) << "OnGetServiceService: " << service_path.value();
DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
service_path, base::Bind(&RunCallbackWithDictionaryValue,
callback,
service_path.value()));
}
}
// A callback used to call a NetworkOperationCallback on error.
void OnNetworkActionError(const NetworkOperationCallback& callback,
const std::string& path,
const std::string& error_name,
const std::string& error_message) {
if (error_name.empty())
callback.Run(path, NETWORK_METHOD_ERROR_LOCAL, "");
else
callback.Run(path, NETWORK_METHOD_ERROR_REMOTE, error_message);
}
IPConfigType ParseIPConfigType(const std::string& type) {
if (type == flimflam::kTypeIPv4)
return IPCONFIG_TYPE_IPV4;
if (type == flimflam::kTypeIPv6)
return IPCONFIG_TYPE_IPV6;
if (type == flimflam::kTypeDHCP)
return IPCONFIG_TYPE_DHCP;
if (type == flimflam::kTypeBOOTP)
return IPCONFIG_TYPE_BOOTP;
if (type == flimflam::kTypeZeroConf)
return IPCONFIG_TYPE_ZEROCONF;
if (type == flimflam::kTypeDHCP6)
return IPCONFIG_TYPE_DHCP6;
if (type == flimflam::kTypePPP)
return IPCONFIG_TYPE_PPP;
return IPCONFIG_TYPE_UNKNOWN;
}
// Converts a list of name servers to a string.
std::string ConvertNameSerersListToString(const base::ListValue& name_servers) {
std::string result;
for (size_t i = 0; i != name_servers.GetSize(); ++i) {
std::string name_server;
if (!name_servers.GetString(i, &name_server)) {
LOG(ERROR) << "name_servers[" << i << "] is not a string.";
continue;
}
if (!result.empty())
result += ",";
result += name_server;
}
return result;
}
// Gets NetworkIPConfigVector populated with data from a
// given DBus object path.
//
// returns true on success.
bool ParseIPConfig(const std::string& device_path,
const std::string& ipconfig_path,
NetworkIPConfigVector* ipconfig_vector) {
ShillIPConfigClient* ipconfig_client =
DBusThreadManager::Get()->GetShillIPConfigClient();
// TODO(hashimoto): Remove this blocking D-Bus method call. crosbug.com/29902
scoped_ptr<base::DictionaryValue> properties(
ipconfig_client->CallGetPropertiesAndBlock(
dbus::ObjectPath(ipconfig_path)));
if (!properties.get())
return false;
std::string type_string;
properties->GetStringWithoutPathExpansion(flimflam::kMethodProperty,
&type_string);
std::string address;
properties->GetStringWithoutPathExpansion(flimflam::kAddressProperty,
&address);
int32 prefix_len = 0;
properties->GetIntegerWithoutPathExpansion(flimflam::kPrefixlenProperty,
&prefix_len);
std::string gateway;
properties->GetStringWithoutPathExpansion(flimflam::kGatewayProperty,
&gateway);
base::ListValue* name_servers = NULL;
std::string name_servers_string;
// store nameservers as a comma delimited list
if (properties->GetListWithoutPathExpansion(flimflam::kNameServersProperty,
&name_servers)) {
name_servers_string = ConvertNameSerersListToString(*name_servers);
} else {
LOG(ERROR) << "Cannot get name servers.";
}
ipconfig_vector->push_back(
NetworkIPConfig(device_path,
ParseIPConfigType(type_string),
address,
CrosPrefixLengthToNetmask(prefix_len),
gateway,
name_servers_string));
return true;
}
} // namespace
SMS::SMS()
: validity(0),
msgclass(0) {
}
SMS::~SMS() {}
bool CrosActivateCellularModem(const std::string& service_path,
const std::string& carrier) {
return DBusThreadManager::Get()->GetShillServiceClient()->
CallActivateCellularModemAndBlock(dbus::ObjectPath(service_path),
carrier);
}
void CrosSetNetworkServiceProperty(const std::string& service_path,
const std::string& property,
const base::Value& value) {
DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
dbus::ObjectPath(service_path), property, value,
base::Bind(&DoNothing));
}
void CrosClearNetworkServiceProperty(const std::string& service_path,
const std::string& property) {
DBusThreadManager::Get()->GetShillServiceClient()->ClearProperty(
dbus::ObjectPath(service_path), property, base::Bind(&DoNothing));
}
void CrosSetNetworkDeviceProperty(const std::string& device_path,
const std::string& property,
const base::Value& value) {
DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
dbus::ObjectPath(device_path), property, value, base::Bind(&DoNothing));
}
void CrosSetNetworkIPConfigProperty(const std::string& ipconfig_path,
const std::string& property,
const base::Value& value) {
DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
dbus::ObjectPath(ipconfig_path), property, value,
base::Bind(&DoNothing));
}
void CrosSetNetworkManagerProperty(const std::string& property,
const base::Value& value) {
DBusThreadManager::Get()->GetShillManagerClient()->SetProperty(
property, value, base::Bind(&DoNothing));
}
void CrosDeleteServiceFromProfile(const std::string& profile_path,
const std::string& service_path) {
DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
dbus::ObjectPath(profile_path), service_path, base::Bind(&DoNothing));
}
void CrosRequestCellularDataPlanUpdate(const std::string& modem_service_path) {
DBusThreadManager::Get()->GetCashewClient()->RequestDataPlansUpdate(
modem_service_path);
}
CrosNetworkWatcher* CrosMonitorNetworkManagerProperties(
const NetworkPropertiesWatcherCallback& callback) {
return new NetworkManagerPropertiesWatcher(callback);
}
CrosNetworkWatcher* CrosMonitorNetworkServiceProperties(
const NetworkPropertiesWatcherCallback& callback,
const std::string& service_path) {
return new NetworkServicePropertiesWatcher(callback, service_path);
}
CrosNetworkWatcher* CrosMonitorNetworkDeviceProperties(
const NetworkPropertiesWatcherCallback& callback,
const std::string& device_path) {
return new NetworkDevicePropertiesWatcher(callback, device_path);
}
CrosNetworkWatcher* CrosMonitorCellularDataPlan(
const DataPlanUpdateWatcherCallback& callback) {
return new DataPlanUpdateWatcher(callback);
}
CrosNetworkWatcher* CrosMonitorSMS(const std::string& modem_device_path,
MonitorSMSCallback callback) {
return new SMSWatcher(modem_device_path, callback);
}
void CrosRequestNetworkServiceConnect(
const std::string& service_path,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillServiceClient()->Connect(
dbus::ObjectPath(service_path),
base::Bind(callback, service_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, service_path));
}
void CrosRequestNetworkManagerProperties(
const NetworkPropertiesCallback& callback) {
DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
base::Bind(&RunCallbackWithDictionaryValue,
callback,
flimflam::kFlimflamServicePath));
}
void CrosRequestNetworkServiceProperties(
const std::string& service_path,
const NetworkPropertiesCallback& callback) {
DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
dbus::ObjectPath(service_path),
base::Bind(&RunCallbackWithDictionaryValue, callback, service_path));
}
void CrosRequestNetworkDeviceProperties(
const std::string& device_path,
const NetworkPropertiesCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
dbus::ObjectPath(device_path),
base::Bind(&RunCallbackWithDictionaryValue, callback, device_path));
}
void CrosRequestNetworkProfileProperties(
const std::string& profile_path,
const NetworkPropertiesCallback& callback) {
DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
dbus::ObjectPath(profile_path),
base::Bind(&RunCallbackWithDictionaryValue, callback, profile_path));
}
void CrosRequestNetworkProfileEntryProperties(
const std::string& profile_path,
const std::string& profile_entry_path,
const NetworkPropertiesCallback& callback) {
DBusThreadManager::Get()->GetShillProfileClient()->GetEntry(
dbus::ObjectPath(profile_path),
profile_entry_path,
base::Bind(&RunCallbackWithDictionaryValue,
callback,
profile_entry_path));
}
void CrosRequestHiddenWifiNetworkProperties(
const std::string& ssid,
const std::string& security,
const NetworkPropertiesCallback& callback) {
base::DictionaryValue properties;
properties.SetWithoutPathExpansion(
flimflam::kModeProperty,
base::Value::CreateStringValue(flimflam::kModeManaged));
properties.SetWithoutPathExpansion(
flimflam::kTypeProperty,
base::Value::CreateStringValue(flimflam::kTypeWifi));
properties.SetWithoutPathExpansion(
flimflam::kSSIDProperty,
base::Value::CreateStringValue(ssid));
properties.SetWithoutPathExpansion(
flimflam::kSecurityProperty,
base::Value::CreateStringValue(security));
// shill.Manger.GetService() will apply the property changes in
// |properties| and return a new or existing service to OnGetService().
// OnGetService will then call GetProperties which will then call callback.
DBusThreadManager::Get()->GetShillManagerClient()->GetService(
properties, base::Bind(&OnGetService, callback));
}
void CrosRequestVirtualNetworkProperties(
const std::string& service_name,
const std::string& server_hostname,
const std::string& provider_type,
const NetworkPropertiesCallback& callback) {
base::DictionaryValue properties;
properties.SetWithoutPathExpansion(
flimflam::kTypeProperty,
base::Value::CreateStringValue(flimflam::kTypeVPN));
properties.SetWithoutPathExpansion(
flimflam::kProviderNameProperty,
base::Value::CreateStringValue(service_name));
properties.SetWithoutPathExpansion(
flimflam::kProviderHostProperty,
base::Value::CreateStringValue(server_hostname));
properties.SetWithoutPathExpansion(
flimflam::kProviderTypeProperty,
base::Value::CreateStringValue(provider_type));
// The actual value of Domain does not matter, so just use service_name.
properties.SetWithoutPathExpansion(
flimflam::kVPNDomainProperty,
base::Value::CreateStringValue(service_name));
// shill.Manger.GetService() will apply the property changes in
// |properties| and pass a new or existing service to OnGetService().
// OnGetService will then call GetProperties which will then call callback.
DBusThreadManager::Get()->GetShillManagerClient()->GetService(
properties, base::Bind(&OnGetService, callback));
}
void CrosRequestNetworkServiceDisconnect(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
dbus::ObjectPath(service_path), base::Bind(&DoNothing));
}
void CrosRequestRemoveNetworkService(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Remove(
dbus::ObjectPath(service_path), base::Bind(&DoNothing));
}
void CrosRequestNetworkScan(const std::string& network_type) {
DBusThreadManager::Get()->GetShillManagerClient()->RequestScan(
network_type, base::Bind(&DoNothing));
}
void CrosRequestNetworkDeviceEnable(const std::string& network_type,
bool enable) {
if (enable) {
DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology(
network_type, base::Bind(&DoNothing));
} else {
DBusThreadManager::Get()->GetShillManagerClient()->DisableTechnology(
network_type, base::Bind(&DoNothing));
}
}
void CrosRequestRequirePin(const std::string& device_path,
const std::string& pin,
bool enable,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
dbus::ObjectPath(device_path), pin, enable,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
void CrosRequestEnterPin(const std::string& device_path,
const std::string& pin,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
dbus::ObjectPath(device_path), pin,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
void CrosRequestUnblockPin(const std::string& device_path,
const std::string& unblock_code,
const std::string& pin,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
dbus::ObjectPath(device_path), unblock_code, pin,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
void CrosRequestChangePin(const std::string& device_path,
const std::string& old_pin,
const std::string& new_pin,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
dbus::ObjectPath(device_path), old_pin, new_pin,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
void CrosProposeScan(const std::string& device_path) {
DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
dbus::ObjectPath(device_path), base::Bind(&DoNothing));
}
void CrosRequestCellularRegister(const std::string& device_path,
const std::string& network_id,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->Register(
dbus::ObjectPath(device_path), network_id,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
bool CrosSetOfflineMode(bool offline) {
base::FundamentalValue value(offline);
DBusThreadManager::Get()->GetShillManagerClient()->SetProperty(
flimflam::kOfflineModeProperty, value, base::Bind(&DoNothing));
return true;
}
bool CrosListIPConfigs(const std::string& device_path,
NetworkIPConfigVector* ipconfig_vector,
std::vector<std::string>* ipconfig_paths,
std::string* hardware_address) {
if (hardware_address)
hardware_address->clear();
const dbus::ObjectPath device_object_path(device_path);
ShillDeviceClient* device_client =
DBusThreadManager::Get()->GetShillDeviceClient();
// TODO(hashimoto): Remove this blocking D-Bus method call.
// crosbug.com/29902
scoped_ptr<base::DictionaryValue> properties(
device_client->CallGetPropertiesAndBlock(device_object_path));
if (!properties.get())
return false;
ListValue* ips = NULL;
if (!properties->GetListWithoutPathExpansion(
flimflam::kIPConfigsProperty, &ips))
return false;
for (size_t i = 0; i < ips->GetSize(); i++) {
std::string ipconfig_path;
if (!ips->GetString(i, &ipconfig_path)) {
LOG(WARNING) << "Found NULL ip for device " << device_path;
continue;
}
ParseIPConfig(device_path, ipconfig_path, ipconfig_vector);
if (ipconfig_paths)
ipconfig_paths->push_back(ipconfig_path);
}
// Store the hardware address as well.
if (hardware_address)
properties->GetStringWithoutPathExpansion(flimflam::kAddressProperty,
hardware_address);
return true;
}
bool CrosAddIPConfig(const std::string& device_path, IPConfigType type) {
std::string type_str;
switch (type) {
case IPCONFIG_TYPE_IPV4:
type_str = flimflam::kTypeIPv4;
break;
case IPCONFIG_TYPE_IPV6:
type_str = flimflam::kTypeIPv6;
break;
case IPCONFIG_TYPE_DHCP:
type_str = flimflam::kTypeDHCP;
break;
case IPCONFIG_TYPE_BOOTP:
type_str = flimflam::kTypeBOOTP;
break;
case IPCONFIG_TYPE_ZEROCONF:
type_str = flimflam::kTypeZeroConf;
break;
case IPCONFIG_TYPE_DHCP6:
type_str = flimflam::kTypeDHCP6;
break;
case IPCONFIG_TYPE_PPP:
type_str = flimflam::kTypePPP;
break;
default:
return false;
};
const dbus::ObjectPath result =
DBusThreadManager::Get()->GetShillDeviceClient()->
CallAddIPConfigAndBlock(dbus::ObjectPath(device_path), type_str);
if (result.value().empty()) {
LOG(ERROR) << "Add IPConfig failed for device path " << device_path
<< " and type " << type_str;
return false;
}
return true;
}
bool CrosRemoveIPConfig(const std::string& ipconfig_path) {
return DBusThreadManager::Get()->GetShillIPConfigClient()->
CallRemoveAndBlock(dbus::ObjectPath(ipconfig_path));
}
void CrosRequestIPConfigRefresh(const std::string& ipconfig_path) {
DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
dbus::ObjectPath(ipconfig_path),
base::Bind(&DoNothing));
}
bool CrosGetWifiAccessPoints(WifiAccessPointVector* result) {
scoped_ptr<base::DictionaryValue> manager_properties(
DBusThreadManager::Get()->GetShillManagerClient()->
CallGetPropertiesAndBlock());
if (!manager_properties.get()) {
LOG(WARNING) << "Couldn't read managers's properties";
return false;
}
base::ListValue* devices = NULL;
if (!manager_properties->GetListWithoutPathExpansion(
flimflam::kDevicesProperty, &devices)) {
LOG(WARNING) << flimflam::kDevicesProperty << " property not found";
return false;
}
const base::Time now = base::Time::Now();
bool found_at_least_one_device = false;
result->clear();
for (size_t i = 0; i < devices->GetSize(); i++) {
std::string device_path;
if (!devices->GetString(i, &device_path)) {
LOG(WARNING) << "Couldn't get devices[" << i << "]";
continue;
}
scoped_ptr<base::DictionaryValue> device_properties(
DBusThreadManager::Get()->GetShillDeviceClient()->
CallGetPropertiesAndBlock(dbus::ObjectPath(device_path)));
if (!device_properties.get()) {
LOG(WARNING) << "Couldn't read device's properties " << device_path;
continue;
}
base::ListValue* networks = NULL;
if (!device_properties->GetListWithoutPathExpansion(
flimflam::kNetworksProperty, &networks))
continue; // Some devices do not list networks, e.g. ethernet.
base::Value* device_powered_value = NULL;
bool device_powered = false;
if (device_properties->GetWithoutPathExpansion(
flimflam::kPoweredProperty, &device_powered_value) &&
device_powered_value->GetAsBoolean(&device_powered) &&
!device_powered)
continue; // Skip devices that are not powered up.
int scan_interval = 0;
device_properties->GetIntegerWithoutPathExpansion(
flimflam::kScanIntervalProperty, &scan_interval);
found_at_least_one_device = true;
for (size_t j = 0; j < networks->GetSize(); j++) {
std::string network_path;
if (!networks->GetString(j, &network_path)) {
LOG(WARNING) << "Couldn't get networks[" << j << "]";
continue;
}
scoped_ptr<base::DictionaryValue> network_properties(
DBusThreadManager::Get()->GetShillNetworkClient()->
CallGetPropertiesAndBlock(dbus::ObjectPath(network_path)));
if (!network_properties.get()) {
LOG(WARNING) << "Couldn't read network's properties " << network_path;
continue;
}
// Using the scan interval as a proxy for approximate age.
// TODO(joth): Replace with actual age, when available from dbus.
const int age_seconds = scan_interval;
WifiAccessPoint ap;
network_properties->GetStringWithoutPathExpansion(
flimflam::kAddressProperty, &ap.mac_address);
network_properties->GetStringWithoutPathExpansion(
flimflam::kNameProperty, &ap.name);
ap.timestamp = now - base::TimeDelta::FromSeconds(age_seconds);
network_properties->GetIntegerWithoutPathExpansion(
flimflam::kSignalStrengthProperty, &ap.signal_strength);
network_properties->GetIntegerWithoutPathExpansion(
flimflam::kWifiChannelProperty, &ap.channel);
result->push_back(ap);
}
}
if (!found_at_least_one_device)
return false; // No powered device found that has a 'Networks' array.
return true;
}
void CrosConfigureService(const base::DictionaryValue& properties) {
DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
properties, base::Bind(&DoNothing));
}
std::string CrosPrefixLengthToNetmask(int32 prefix_length) {
std::string netmask;
// Return the empty string for invalid inputs.
if (prefix_length < 0 || prefix_length > 32)
return netmask;
for (int i = 0; i < 4; i++) {
int remainder = 8;
if (prefix_length >= 8) {
prefix_length -= 8;
} else {
remainder = prefix_length;
prefix_length = 0;
}
if (i > 0)
netmask += ".";
int value = remainder == 0 ? 0 :
((2L << (remainder - 1)) - 1) << (8 - remainder);
netmask += StringPrintf("%d", value);
}
return netmask;
}
int32 CrosNetmaskToPrefixLength(const std::string& netmask) {
int count = 0;
int prefix_length = 0;
StringTokenizer t(netmask, ".");
while (t.GetNext()) {
// If there are more than 4 numbers, then it's invalid.
if (count == 4)
return -1;
std::string token = t.token();
// If we already found the last mask and the current one is not
// "0" then the netmask is invalid. For example, 255.224.255.0
if (prefix_length / 8 != count) {
if (token != "0")
return -1;
} else if (token == "255") {
prefix_length += 8;
} else if (token == "254") {
prefix_length += 7;
} else if (token == "252") {
prefix_length += 6;
} else if (token == "248") {
prefix_length += 5;
} else if (token == "240") {
prefix_length += 4;
} else if (token == "224") {
prefix_length += 3;
} else if (token == "192") {
prefix_length += 2;
} else if (token == "128") {
prefix_length += 1;
} else if (token == "0") {
prefix_length += 0;
} else {
// mask is not a valid number.
return -1;
}
count++;
}
if (count < 4)
return -1;
return prefix_length;
}
// Changes the active cellular carrier.
void CrosSetCarrier(const std::string& device_path,
const std::string& carrier,
const NetworkOperationCallback& callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
dbus::ObjectPath(device_path), carrier,
base::Bind(callback, device_path, NETWORK_METHOD_ERROR_NONE,
std::string()),
base::Bind(&OnNetworkActionError, callback, device_path));
}
} // namespace chromeos