|  | // 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 |