1 // Copyright 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/fake_shill_device_client.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& device_path, 26 const std::string& error_name, 27 const std::string& error_message) { 28 LOG(ERROR) << "Shill Error for: " << device_path 29 << ": " << error_name << " : " << error_message; 30 } 31 32 void PostDeviceNotFoundError( 33 const ShillDeviceClient::ErrorCallback& error_callback) { 34 std::string error_name("org.chromium.flimflam.Error.Failure"); 35 std::string error_message("Failed"); 36 base::MessageLoop::current()->PostTask( 37 FROM_HERE, base::Bind(error_callback, error_name, error_message)); 38 } 39 40 } // namespace 41 42 FakeShillDeviceClient::FakeShillDeviceClient() : weak_ptr_factory_(this) { 43 } 44 45 FakeShillDeviceClient::~FakeShillDeviceClient() { 46 STLDeleteContainerPairSecondPointers( 47 observer_list_.begin(), observer_list_.end()); 48 } 49 50 // ShillDeviceClient overrides. 51 52 void FakeShillDeviceClient::Init(dbus::Bus* bus) {} 53 54 void FakeShillDeviceClient::AddPropertyChangedObserver( 55 const dbus::ObjectPath& device_path, 56 ShillPropertyChangedObserver* observer) { 57 GetObserverList(device_path).AddObserver(observer); 58 } 59 60 void FakeShillDeviceClient::RemovePropertyChangedObserver( 61 const dbus::ObjectPath& device_path, 62 ShillPropertyChangedObserver* observer) { 63 GetObserverList(device_path).RemoveObserver(observer); 64 } 65 66 void FakeShillDeviceClient::GetProperties( 67 const dbus::ObjectPath& device_path, 68 const DictionaryValueCallback& callback) { 69 base::MessageLoop::current()->PostTask( 70 FROM_HERE, 71 base::Bind(&FakeShillDeviceClient::PassStubDeviceProperties, 72 weak_ptr_factory_.GetWeakPtr(), 73 device_path, callback)); 74 } 75 76 void FakeShillDeviceClient::ProposeScan( 77 const dbus::ObjectPath& device_path, 78 const VoidDBusMethodCallback& callback) { 79 PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS); 80 } 81 82 void FakeShillDeviceClient::SetProperty(const dbus::ObjectPath& device_path, 83 const std::string& name, 84 const base::Value& value, 85 const base::Closure& callback, 86 const ErrorCallback& error_callback) { 87 base::DictionaryValue* device_properties = NULL; 88 if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(), 89 &device_properties)) { 90 PostDeviceNotFoundError(error_callback); 91 return; 92 } 93 device_properties->SetWithoutPathExpansion(name, value.DeepCopy()); 94 base::MessageLoop::current()->PostTask( 95 FROM_HERE, 96 base::Bind(&FakeShillDeviceClient::NotifyObserversPropertyChanged, 97 weak_ptr_factory_.GetWeakPtr(), device_path, name)); 98 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 99 } 100 101 void FakeShillDeviceClient::ClearProperty( 102 const dbus::ObjectPath& device_path, 103 const std::string& name, 104 const VoidDBusMethodCallback& callback) { 105 base::DictionaryValue* device_properties = NULL; 106 if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(), 107 &device_properties)) { 108 PostVoidCallback(callback, DBUS_METHOD_CALL_FAILURE); 109 return; 110 } 111 device_properties->RemoveWithoutPathExpansion(name, NULL); 112 PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS); 113 } 114 115 void FakeShillDeviceClient::AddIPConfig( 116 const dbus::ObjectPath& device_path, 117 const std::string& method, 118 const ObjectPathDBusMethodCallback& callback) { 119 base::MessageLoop::current()->PostTask(FROM_HERE, 120 base::Bind(callback, 121 DBUS_METHOD_CALL_SUCCESS, 122 dbus::ObjectPath())); 123 } 124 125 void FakeShillDeviceClient::RequirePin(const dbus::ObjectPath& device_path, 126 const std::string& pin, 127 bool require, 128 const base::Closure& callback, 129 const ErrorCallback& error_callback) { 130 if (!stub_devices_.HasKey(device_path.value())) { 131 PostDeviceNotFoundError(error_callback); 132 return; 133 } 134 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 135 } 136 137 void FakeShillDeviceClient::EnterPin(const dbus::ObjectPath& device_path, 138 const std::string& pin, 139 const base::Closure& callback, 140 const ErrorCallback& error_callback) { 141 if (!stub_devices_.HasKey(device_path.value())) { 142 PostDeviceNotFoundError(error_callback); 143 return; 144 } 145 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 146 } 147 148 void FakeShillDeviceClient::UnblockPin(const dbus::ObjectPath& device_path, 149 const std::string& puk, 150 const std::string& pin, 151 const base::Closure& callback, 152 const ErrorCallback& error_callback) { 153 if (!stub_devices_.HasKey(device_path.value())) { 154 PostDeviceNotFoundError(error_callback); 155 return; 156 } 157 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 158 } 159 160 void FakeShillDeviceClient::ChangePin(const dbus::ObjectPath& device_path, 161 const std::string& old_pin, 162 const std::string& new_pin, 163 const base::Closure& callback, 164 const ErrorCallback& error_callback) { 165 if (!stub_devices_.HasKey(device_path.value())) { 166 PostDeviceNotFoundError(error_callback); 167 return; 168 } 169 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 170 } 171 172 void FakeShillDeviceClient::Register(const dbus::ObjectPath& device_path, 173 const std::string& network_id, 174 const base::Closure& callback, 175 const ErrorCallback& error_callback) { 176 if (!stub_devices_.HasKey(device_path.value())) { 177 PostDeviceNotFoundError(error_callback); 178 return; 179 } 180 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 181 } 182 183 void FakeShillDeviceClient::SetCarrier(const dbus::ObjectPath& device_path, 184 const std::string& carrier, 185 const base::Closure& callback, 186 const ErrorCallback& error_callback) { 187 if (!stub_devices_.HasKey(device_path.value())) { 188 PostDeviceNotFoundError(error_callback); 189 return; 190 } 191 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 192 } 193 194 void FakeShillDeviceClient::Reset(const dbus::ObjectPath& device_path, 195 const base::Closure& callback, 196 const ErrorCallback& error_callback) { 197 if (!stub_devices_.HasKey(device_path.value())) { 198 PostDeviceNotFoundError(error_callback); 199 return; 200 } 201 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 202 } 203 204 ShillDeviceClient::TestInterface* FakeShillDeviceClient::GetTestInterface() { 205 return this; 206 } 207 208 // ShillDeviceClient::TestInterface overrides. 209 210 void FakeShillDeviceClient::AddDevice(const std::string& device_path, 211 const std::string& type, 212 const std::string& object_path) { 213 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()-> 214 AddDevice(device_path); 215 216 base::DictionaryValue* properties = GetDeviceProperties(device_path); 217 properties->SetWithoutPathExpansion( 218 shill::kTypeProperty, 219 base::Value::CreateStringValue(type)); 220 properties->SetWithoutPathExpansion( 221 shill::kDBusObjectProperty, 222 base::Value::CreateStringValue(object_path)); 223 properties->SetWithoutPathExpansion( 224 shill::kDBusConnectionProperty, 225 base::Value::CreateStringValue("/stub")); 226 } 227 228 void FakeShillDeviceClient::RemoveDevice(const std::string& device_path) { 229 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()-> 230 RemoveDevice(device_path); 231 232 stub_devices_.RemoveWithoutPathExpansion(device_path, NULL); 233 } 234 235 void FakeShillDeviceClient::ClearDevices() { 236 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()-> 237 ClearDevices(); 238 239 stub_devices_.Clear(); 240 } 241 242 void FakeShillDeviceClient::SetDeviceProperty(const std::string& device_path, 243 const std::string& name, 244 const base::Value& value) { 245 VLOG(1) << "SetDeviceProperty: " << device_path 246 << ": " << name << " = " << value; 247 SetProperty(dbus::ObjectPath(device_path), name, value, 248 base::Bind(&base::DoNothing), 249 base::Bind(&ErrorFunction, device_path)); 250 } 251 252 std::string FakeShillDeviceClient::GetDevicePathForType( 253 const std::string& type) { 254 for (base::DictionaryValue::Iterator iter(stub_devices_); 255 !iter.IsAtEnd(); iter.Advance()) { 256 const base::DictionaryValue* properties = NULL; 257 if (!iter.value().GetAsDictionary(&properties)) 258 continue; 259 std::string prop_type; 260 if (!properties->GetStringWithoutPathExpansion( 261 shill::kTypeProperty, &prop_type) || 262 prop_type != type) 263 continue; 264 return iter.key(); 265 } 266 return std::string(); 267 } 268 269 void FakeShillDeviceClient::PassStubDeviceProperties( 270 const dbus::ObjectPath& device_path, 271 const DictionaryValueCallback& callback) const { 272 const base::DictionaryValue* device_properties = NULL; 273 if (!stub_devices_.GetDictionaryWithoutPathExpansion( 274 device_path.value(), &device_properties)) { 275 base::DictionaryValue empty_dictionary; 276 callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary); 277 return; 278 } 279 callback.Run(DBUS_METHOD_CALL_SUCCESS, *device_properties); 280 } 281 282 // Posts a task to run a void callback with status code |status|. 283 void FakeShillDeviceClient::PostVoidCallback( 284 const VoidDBusMethodCallback& callback, 285 DBusMethodCallStatus status) { 286 base::MessageLoop::current()->PostTask(FROM_HERE, 287 base::Bind(callback, status)); 288 } 289 290 void FakeShillDeviceClient::NotifyObserversPropertyChanged( 291 const dbus::ObjectPath& device_path, 292 const std::string& property) { 293 base::DictionaryValue* dict = NULL; 294 std::string path = device_path.value(); 295 if (!stub_devices_.GetDictionaryWithoutPathExpansion(path, &dict)) { 296 LOG(ERROR) << "Notify for unknown service: " << path; 297 return; 298 } 299 base::Value* value = NULL; 300 if (!dict->GetWithoutPathExpansion(property, &value)) { 301 LOG(ERROR) << "Notify for unknown property: " 302 << path << " : " << property; 303 return; 304 } 305 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, 306 GetObserverList(device_path), 307 OnPropertyChanged(property, *value)); 308 } 309 310 base::DictionaryValue* FakeShillDeviceClient::GetDeviceProperties( 311 const std::string& device_path) { 312 base::DictionaryValue* properties = NULL; 313 if (!stub_devices_.GetDictionaryWithoutPathExpansion( 314 device_path, &properties)) { 315 properties = new base::DictionaryValue; 316 stub_devices_.SetWithoutPathExpansion(device_path, properties); 317 } 318 return properties; 319 } 320 321 FakeShillDeviceClient::PropertyObserverList& 322 FakeShillDeviceClient::GetObserverList(const dbus::ObjectPath& device_path) { 323 std::map<dbus::ObjectPath, PropertyObserverList*>::iterator iter = 324 observer_list_.find(device_path); 325 if (iter != observer_list_.end()) 326 return *(iter->second); 327 PropertyObserverList* observer_list = new PropertyObserverList(); 328 observer_list_[device_path] = observer_list; 329 return *observer_list; 330 } 331 332 } // namespace chromeos 333