Home | History | Annotate | Download | only in dbus
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/dbus/shill_device_client_stub.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/stl_util.h"
     10 #include "base/values.h"
     11 #include "chromeos/dbus/dbus_thread_manager.h"
     12 #include "chromeos/dbus/shill_manager_client.h"
     13 #include "chromeos/dbus/shill_property_changed_observer.h"
     14 #include "dbus/bus.h"
     15 #include "dbus/message.h"
     16 #include "dbus/object_path.h"
     17 #include "dbus/object_proxy.h"
     18 #include "dbus/values_util.h"
     19 #include "third_party/cros_system_api/dbus/service_constants.h"
     20 
     21 namespace chromeos {
     22 
     23 namespace {
     24 
     25 void ErrorFunction(const std::string& error_name,
     26                    const std::string& error_message) {
     27   LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
     28 }
     29 
     30 }  // namespace
     31 
     32 ShillDeviceClientStub::ShillDeviceClientStub() : weak_ptr_factory_(this) {
     33   SetDefaultProperties();
     34 }
     35 
     36 ShillDeviceClientStub::~ShillDeviceClientStub() {
     37   STLDeleteContainerPairSecondPointers(
     38       observer_list_.begin(), observer_list_.end());
     39 }
     40 
     41 // ShillDeviceClient overrides.
     42 
     43 void ShillDeviceClientStub::AddPropertyChangedObserver(
     44     const dbus::ObjectPath& device_path,
     45     ShillPropertyChangedObserver* observer){
     46   GetObserverList(device_path).AddObserver(observer);
     47 }
     48 
     49 void ShillDeviceClientStub::RemovePropertyChangedObserver(
     50     const dbus::ObjectPath& device_path,
     51     ShillPropertyChangedObserver* observer){
     52   GetObserverList(device_path).RemoveObserver(observer);
     53 }
     54 
     55 void ShillDeviceClientStub::GetProperties(
     56     const dbus::ObjectPath& device_path,
     57     const DictionaryValueCallback& callback){
     58   base::MessageLoop::current()->PostTask(
     59       FROM_HERE,
     60       base::Bind(&ShillDeviceClientStub::PassStubDeviceProperties,
     61                  weak_ptr_factory_.GetWeakPtr(),
     62                  device_path, callback));
     63 }
     64 
     65 void ShillDeviceClientStub::ProposeScan(const dbus::ObjectPath& device_path,
     66                                         const VoidDBusMethodCallback& callback){
     67   PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS);
     68 }
     69 
     70 void ShillDeviceClientStub::SetProperty(const dbus::ObjectPath& device_path,
     71                                         const std::string& name,
     72                                         const base::Value& value,
     73                                         const base::Closure& callback,
     74                                         const ErrorCallback& error_callback){
     75   base::DictionaryValue* device_properties = NULL;
     76   if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(),
     77                                                        &device_properties)) {
     78     std::string error_name("org.chromium.flimflam.Error.Failure");
     79     std::string error_message("Failed");
     80     base::MessageLoop::current()->PostTask(FROM_HERE,
     81                                            base::Bind(error_callback,
     82                                                       error_name,
     83                                                       error_message));
     84     return;
     85   }
     86   device_properties->SetWithoutPathExpansion(name, value.DeepCopy());
     87   base::MessageLoop::current()->PostTask(
     88       FROM_HERE,
     89       base::Bind(&ShillDeviceClientStub::NotifyObserversPropertyChanged,
     90                  weak_ptr_factory_.GetWeakPtr(), device_path, name));
     91   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
     92 }
     93 
     94 void ShillDeviceClientStub::ClearProperty(
     95     const dbus::ObjectPath& device_path,
     96     const std::string& name,
     97     const VoidDBusMethodCallback& callback){
     98   base::DictionaryValue* device_properties = NULL;
     99   if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(),
    100                                                        &device_properties)) {
    101     PostVoidCallback(callback, DBUS_METHOD_CALL_FAILURE);
    102     return;
    103   }
    104   device_properties->RemoveWithoutPathExpansion(name, NULL);
    105   PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS);
    106 }
    107 
    108 void ShillDeviceClientStub::AddIPConfig(
    109     const dbus::ObjectPath& device_path,
    110     const std::string& method,
    111     const ObjectPathDBusMethodCallback& callback){
    112   base::MessageLoop::current()->PostTask(FROM_HERE,
    113                                          base::Bind(callback,
    114                                                     DBUS_METHOD_CALL_SUCCESS,
    115                                                     dbus::ObjectPath()));
    116 }
    117 
    118 void ShillDeviceClientStub::RequirePin(const dbus::ObjectPath& device_path,
    119                                        const std::string& pin,
    120                                        bool require,
    121                                        const base::Closure& callback,
    122                                        const ErrorCallback& error_callback){
    123   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    124 }
    125 
    126 void ShillDeviceClientStub::EnterPin(const dbus::ObjectPath& device_path,
    127                                      const std::string& pin,
    128                                      const base::Closure& callback,
    129                                      const ErrorCallback& error_callback){
    130   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    131 }
    132 
    133 void ShillDeviceClientStub::UnblockPin(const dbus::ObjectPath& device_path,
    134                                        const std::string& puk,
    135                                        const std::string& pin,
    136                                        const base::Closure& callback,
    137                                        const ErrorCallback& error_callback){
    138   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    139 }
    140 
    141 void ShillDeviceClientStub::ChangePin(const dbus::ObjectPath& device_path,
    142                                       const std::string& old_pin,
    143                                       const std::string& new_pin,
    144                                       const base::Closure& callback,
    145                                       const ErrorCallback& error_callback){
    146   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    147 }
    148 
    149 void ShillDeviceClientStub::Register(const dbus::ObjectPath& device_path,
    150                                      const std::string& network_id,
    151                                      const base::Closure& callback,
    152                                      const ErrorCallback& error_callback){
    153   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    154 }
    155 
    156 void ShillDeviceClientStub::SetCarrier(const dbus::ObjectPath& device_path,
    157                                        const std::string& carrier,
    158                                        const base::Closure& callback,
    159                                        const ErrorCallback& error_callback){
    160   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    161 }
    162 
    163 void ShillDeviceClientStub::Reset(const dbus::ObjectPath& device_path,
    164                                   const base::Closure& callback,
    165                                   const ErrorCallback& error_callback){
    166   base::MessageLoop::current()->PostTask(FROM_HERE, callback);
    167 }
    168 
    169 ShillDeviceClient::TestInterface* ShillDeviceClientStub::GetTestInterface(){
    170   return this;
    171 }
    172 
    173 // ShillDeviceClient::TestInterface overrides.
    174 
    175 void ShillDeviceClientStub::AddDevice(const std::string& device_path,
    176                                       const std::string& type,
    177                                       const std::string& object_path){
    178   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
    179       AddDevice(device_path);
    180 
    181   base::DictionaryValue* properties = GetDeviceProperties(device_path);
    182   properties->SetWithoutPathExpansion(
    183       flimflam::kTypeProperty,
    184       base::Value::CreateStringValue(type));
    185   properties->SetWithoutPathExpansion(
    186       flimflam::kDBusObjectProperty,
    187       base::Value::CreateStringValue(object_path));
    188   properties->SetWithoutPathExpansion(
    189       flimflam::kDBusConnectionProperty,
    190       base::Value::CreateStringValue("/stub"));
    191 }
    192 
    193 void ShillDeviceClientStub::RemoveDevice(const std::string& device_path){
    194   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
    195       RemoveDevice(device_path);
    196 
    197   stub_devices_.RemoveWithoutPathExpansion(device_path, NULL);
    198 }
    199 
    200 void ShillDeviceClientStub::ClearDevices(){
    201   DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
    202       ClearDevices();
    203 
    204   stub_devices_.Clear();
    205 }
    206 
    207 void ShillDeviceClientStub::SetDeviceProperty(const std::string& device_path,
    208                                               const std::string& name,
    209                                               const base::Value& value){
    210   VLOG(1) << "SetDeviceProperty: " << device_path
    211           << ": " << name << " = " << value;
    212   SetProperty(dbus::ObjectPath(device_path), name, value,
    213               base::Bind(&base::DoNothing),
    214               base::Bind(&ErrorFunction));
    215 }
    216 
    217 std::string ShillDeviceClientStub::GetDevicePathForType(
    218     const std::string& type) {
    219   for (base::DictionaryValue::Iterator iter(stub_devices_);
    220        !iter.IsAtEnd(); iter.Advance()) {
    221     const base::DictionaryValue* properties = NULL;
    222     if (!iter.value().GetAsDictionary(&properties))
    223       continue;
    224     std::string prop_type;
    225     if (!properties->GetStringWithoutPathExpansion(
    226             flimflam::kTypeProperty, &prop_type) ||
    227         prop_type != type)
    228       continue;
    229     return iter.key();
    230   }
    231   return std::string();
    232 }
    233 
    234 void ShillDeviceClientStub::SetDefaultProperties() {
    235   // Add a wifi device.
    236   AddDevice("stub_wifi_device1", flimflam::kTypeWifi, "/device/wifi1");
    237 
    238   // Add a cellular device. Used in SMS stub.
    239   AddDevice("stub_cellular_device1", flimflam::kTypeCellular,
    240             "/device/cellular1");
    241 
    242   // Add a wimax device.
    243   AddDevice("stub_wimax_device1", flimflam::kTypeWimax,
    244             "/device/wimax1");
    245 }
    246 
    247 void ShillDeviceClientStub::PassStubDeviceProperties(
    248     const dbus::ObjectPath& device_path,
    249     const DictionaryValueCallback& callback) const {
    250   const base::DictionaryValue* device_properties = NULL;
    251   if (!stub_devices_.GetDictionaryWithoutPathExpansion(
    252       device_path.value(), &device_properties)) {
    253     base::DictionaryValue empty_dictionary;
    254     callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary);
    255     return;
    256   }
    257   callback.Run(DBUS_METHOD_CALL_SUCCESS, *device_properties);
    258 }
    259 
    260 // Posts a task to run a void callback with status code |status|.
    261 void ShillDeviceClientStub::PostVoidCallback(
    262     const VoidDBusMethodCallback& callback,
    263     DBusMethodCallStatus status) {
    264   base::MessageLoop::current()->PostTask(FROM_HERE,
    265                                    base::Bind(callback, status));
    266 }
    267 
    268 void ShillDeviceClientStub::NotifyObserversPropertyChanged(
    269     const dbus::ObjectPath& device_path,
    270     const std::string& property) {
    271   base::DictionaryValue* dict = NULL;
    272   std::string path = device_path.value();
    273   if (!stub_devices_.GetDictionaryWithoutPathExpansion(path, &dict)) {
    274     LOG(ERROR) << "Notify for unknown service: " << path;
    275     return;
    276   }
    277   base::Value* value = NULL;
    278   if (!dict->GetWithoutPathExpansion(property, &value)) {
    279     LOG(ERROR) << "Notify for unknown property: "
    280         << path << " : " << property;
    281     return;
    282   }
    283   FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
    284                     GetObserverList(device_path),
    285                     OnPropertyChanged(property, *value));
    286 }
    287 
    288 base::DictionaryValue* ShillDeviceClientStub::GetDeviceProperties(
    289     const std::string& device_path) {
    290   base::DictionaryValue* properties = NULL;
    291   if (!stub_devices_.GetDictionaryWithoutPathExpansion(
    292       device_path, &properties)) {
    293     properties = new base::DictionaryValue;
    294     stub_devices_.SetWithoutPathExpansion(device_path, properties);
    295   }
    296   return properties;
    297 }
    298 
    299 ShillDeviceClientStub::PropertyObserverList&
    300 ShillDeviceClientStub::GetObserverList(const dbus::ObjectPath& device_path) {
    301   std::map<dbus::ObjectPath, PropertyObserverList*>::iterator iter =
    302       observer_list_.find(device_path);
    303   if (iter != observer_list_.end())
    304     return *(iter->second);
    305   PropertyObserverList* observer_list = new PropertyObserverList();
    306   observer_list_[device_path] = observer_list;
    307   return *observer_list;
    308 }
    309 
    310 }  // namespace chromeos
    311