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