blob: ea3ba013d7893180a729a8a46b487622b68426a8 [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/cros_network_functions.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.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_profile_client.h"
#include "chromeos/dbus/shill_property_changed_observer.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/sms_watcher.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using base::DoNothing;
namespace chromeos {
namespace {
// Class to watch network manager's properties without Libcros.
class NetworkManagerPropertiesWatcher
: public CrosNetworkWatcher,
public ShillPropertyChangedObserver {
public:
NetworkManagerPropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback)
: callback_(callback) {
DBusThreadManager::Get()->GetShillManagerClient()->
AddPropertyChangedObserver(this);
}
virtual ~NetworkManagerPropertiesWatcher() {
DBusThreadManager::Get()->GetShillManagerClient()->
RemovePropertyChangedObserver(this);
}
virtual void OnPropertyChanged(const std::string& name,
const base::Value& value) OVERRIDE {
callback_.Run(flimflam::kFlimflamServicePath, name, value);
}
private:
NetworkPropertiesWatcherCallback callback_;
};
// Class to watch network service's properties without Libcros.
class NetworkServicePropertiesWatcher
: public CrosNetworkWatcher,
public ShillPropertyChangedObserver {
public:
NetworkServicePropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback,
const std::string& service_path) : service_path_(service_path),
callback_(callback) {
DBusThreadManager::Get()->GetShillServiceClient()->
AddPropertyChangedObserver(dbus::ObjectPath(service_path), this);
}
virtual ~NetworkServicePropertiesWatcher() {
DBusThreadManager::Get()->GetShillServiceClient()->
RemovePropertyChangedObserver(dbus::ObjectPath(service_path_), this);
}
virtual void OnPropertyChanged(const std::string& name,
const base::Value& value) OVERRIDE {
callback_.Run(service_path_, name, value);
}
private:
std::string service_path_;
NetworkPropertiesWatcherCallback callback_;
};
// Class to watch network device's properties without Libcros.
class NetworkDevicePropertiesWatcher
: public CrosNetworkWatcher,
public ShillPropertyChangedObserver {
public:
NetworkDevicePropertiesWatcher(
const NetworkPropertiesWatcherCallback& callback,
const std::string& device_path) : device_path_(device_path),
callback_(callback) {
DBusThreadManager::Get()->GetShillDeviceClient()->
AddPropertyChangedObserver(dbus::ObjectPath(device_path), this);
}
virtual ~NetworkDevicePropertiesWatcher() {
DBusThreadManager::Get()->GetShillDeviceClient()->
RemovePropertyChangedObserver(dbus::ObjectPath(device_path_), this);
}
virtual void OnPropertyChanged(const std::string& name,
const base::Value& value) OVERRIDE {
callback_.Run(device_path_, name, value);
}
private:
std::string device_path_;
NetworkPropertiesWatcherCallback callback_;
};
// 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;
}
// Does nothing. Used as a callback.
void DoNothingWithCallStatus(DBusMethodCallStatus call_status) {}
// Does nothing. Used as a callback.
void DoNothingWithObjectPath(const dbus::ObjectPath& object_path) {}
// Ignores errors.
void IgnoreErrors(const std::string& error_name,
const std::string& error_message) {}
// 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);
}
// A callback used to implement CrosRequest*Properties functions.
void RunCallbackWithDictionaryValueNoStatus(
const NetworkPropertiesCallback& callback,
const std::string& path,
const base::DictionaryValue& value) {
callback.Run(path, &value);
}
// A callback used to implement the error callback for CrosRequest*Properties
// functions.
void RunCallbackWithDictionaryValueError(
const NetworkPropertiesCallback& callback,
const std::string& path,
const std::string& error_name,
const std::string& error_message) {
callback.Run(path, NULL);
}
// Used as a callback for ShillManagerClient::GetService
void OnGetService(const NetworkPropertiesCallback& callback,
const dbus::ObjectPath& service_path) {
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,
network_util::PrefixLengthToNetmask(prefix_len),
gateway,
name_servers_string));
return true;
}
void ListIPConfigsCallback(const NetworkGetIPConfigsCallback& callback,
const std::string& device_path,
DBusMethodCallStatus call_status,
const base::DictionaryValue& properties) {
NetworkIPConfigVector ipconfig_vector;
std::string hardware_address;
const base::ListValue* ips = NULL;
if (call_status != DBUS_METHOD_CALL_SUCCESS ||
!properties.GetListWithoutPathExpansion(flimflam::kIPConfigsProperty,
&ips)) {
callback.Run(ipconfig_vector, hardware_address);
return;
}
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);
}
// Get the hardware address as well.
properties.GetStringWithoutPathExpansion(flimflam::kAddressProperty,
&hardware_address);
callback.Run(ipconfig_vector, hardware_address);
}
} // namespace
bool CrosActivateCellularModem(const std::string& service_path,
const std::string& carrier) {
return DBusThreadManager::Get()->GetShillServiceClient()->
CallActivateCellularModemAndBlock(dbus::ObjectPath(service_path),
carrier);
}
void CrosCompleteCellularActivation(const std::string& service_path) {
return DBusThreadManager::Get()->GetShillServiceClient()->
CompleteCellularActivation(dbus::ObjectPath(service_path),
base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
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),
base::Bind(&IgnoreErrors));
}
void CrosClearNetworkServiceProperty(const std::string& service_path,
const std::string& property) {
DBusThreadManager::Get()->GetShillServiceClient()->ClearProperty(
dbus::ObjectPath(service_path), property, base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
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),
base::Bind(&IgnoreErrors));
}
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(&DoNothingWithCallStatus));
}
void CrosSetNetworkManagerProperty(const std::string& property,
const base::Value& value) {
DBusThreadManager::Get()->GetShillManagerClient()->SetProperty(
property, value, base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
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),
base::Bind(&IgnoreErrors));
}
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* 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(&RunCallbackWithDictionaryValueNoStatus,
callback, profile_path),
base::Bind(&RunCallbackWithDictionaryValueError, 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(&RunCallbackWithDictionaryValueNoStatus,
callback,
profile_entry_path),
base::Bind(&RunCallbackWithDictionaryValueError,
callback,
profile_entry_path));
}
void CrosRequestHiddenWifiNetworkProperties(
const std::string& ssid,
const std::string& security,
const NetworkPropertiesCallback& callback) {
base::DictionaryValue properties;
properties.SetWithoutPathExpansion(
flimflam::kModeProperty,
new base::StringValue(flimflam::kModeManaged));
properties.SetWithoutPathExpansion(
flimflam::kTypeProperty,
new base::StringValue(flimflam::kTypeWifi));
properties.SetWithoutPathExpansion(
flimflam::kSSIDProperty,
new base::StringValue(ssid));
properties.SetWithoutPathExpansion(
flimflam::kSecurityProperty,
new base::StringValue(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),
base::Bind(&IgnoreErrors));
}
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,
new base::StringValue(flimflam::kTypeVPN));
properties.SetWithoutPathExpansion(
flimflam::kNameProperty,
new base::StringValue(service_name));
properties.SetWithoutPathExpansion(
flimflam::kProviderHostProperty,
new base::StringValue(server_hostname));
properties.SetWithoutPathExpansion(
flimflam::kProviderTypeProperty,
new base::StringValue(provider_type));
// shill.Manger.ConfigureService() 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()->ConfigureService(
properties, base::Bind(&OnGetService, callback),
base::Bind(&IgnoreErrors));
}
void CrosRequestNetworkServiceDisconnect(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
dbus::ObjectPath(service_path), base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
void CrosRequestRemoveNetworkService(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Remove(
dbus::ObjectPath(service_path), base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
void CrosRequestNetworkScan(const std::string& network_type) {
DBusThreadManager::Get()->GetShillManagerClient()->RequestScan(
network_type, base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
void CrosRequestNetworkDeviceEnable(const std::string& network_type,
bool enable) {
if (enable) {
DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology(
network_type, base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
} else {
DBusThreadManager::Get()->GetShillManagerClient()->DisableTechnology(
network_type, base::Bind(&DoNothing),
base::Bind(&IgnoreErrors));
}
}
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(&DoNothingWithCallStatus));
}
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));
}
void CrosListIPConfigs(const std::string& device_path,
const NetworkGetIPConfigsCallback& callback) {
const dbus::ObjectPath device_object_path(device_path);
DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
device_object_path,
base::Bind(&ListIPConfigsCallback, callback, device_path));
}
void CrosRequestIPConfigRefresh(const std::string& ipconfig_path) {
DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
dbus::ObjectPath(ipconfig_path),
base::Bind(&DoNothingWithCallStatus));
}
void CrosConfigureService(const base::DictionaryValue& properties) {
DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
properties, base::Bind(&DoNothingWithObjectPath),
base::Bind(&IgnoreErrors));
}
// 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