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