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_nfc_adapter_client.h" 6 7 #include "base/logging.h" 8 #include "chromeos/dbus/dbus_thread_manager.h" 9 #include "chromeos/dbus/fake_nfc_device_client.h" 10 #include "chromeos/dbus/fake_nfc_tag_client.h" 11 #include "chromeos/dbus/nfc_client_helpers.h" 12 #include "dbus/message.h" 13 #include "dbus/object_path.h" 14 #include "third_party/cros_system_api/dbus/service_constants.h" 15 16 namespace chromeos { 17 18 using nfc_client_helpers::ObjectPathVector; 19 20 const char FakeNfcAdapterClient::kAdapterPath0[] = "/fake/nfc0"; 21 const char FakeNfcAdapterClient::kAdapterPath1[] = "/fake/nfc1"; 22 23 FakeNfcAdapterClient::Properties::Properties( 24 const PropertyChangedCallback& callback) 25 : NfcAdapterClient::Properties(NULL, callback) { 26 } 27 28 FakeNfcAdapterClient::Properties::~Properties() { 29 } 30 31 void FakeNfcAdapterClient::Properties::Get( 32 dbus::PropertyBase* property, 33 dbus::PropertySet::GetCallback callback) { 34 VLOG(1) << "Get " << property->name(); 35 callback.Run(false); 36 } 37 38 void FakeNfcAdapterClient::Properties::GetAll() { 39 VLOG(1) << "GetAll"; 40 } 41 42 void FakeNfcAdapterClient::Properties::Set( 43 dbus::PropertyBase* property, 44 dbus::PropertySet::SetCallback callback) { 45 VLOG(1) << "Set " << property->name(); 46 if (property->name() != powered.name()) { 47 callback.Run(false); 48 return; 49 } 50 51 // Cannot set the power if currently polling. 52 if (polling.value()) { 53 LOG(ERROR) << "Cannot set power while polling."; 54 callback.Run(false); 55 return; 56 } 57 58 // Cannot set power if there is a device or a tag that is currently 59 // "paired". 60 if (!devices.value().empty() || !tags.value().empty()) { 61 LOG(ERROR) << "Cannot set power while the device is paired."; 62 callback.Run(false); 63 return; 64 } 65 66 // Obtain the cached "set value" and send a property changed signal only if 67 // its value is different from the current value of the property. 68 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); 69 dbus::MessageWriter writer(response.get()); 70 property->AppendSetValueToWriter(&writer); 71 dbus::MessageReader reader(response.get()); 72 bool set_value = false; 73 if (!reader.PopVariantOfBool(&set_value) || set_value == powered.value()) { 74 LOG(WARNING) << "Property has not changed."; 75 callback.Run(false); 76 return; 77 } 78 property->ReplaceValueWithSetValue(); 79 callback.Run(true); 80 } 81 82 FakeNfcAdapterClient::FakeNfcAdapterClient() 83 : present_(true), 84 second_present_(false), 85 start_pairing_on_poll_(true), 86 device_pairing_(false) { 87 VLOG(1) << "Creating FakeNfcAdapterClient"; 88 89 std::vector<std::string> protocols; 90 protocols.push_back(nfc_common::kProtocolFelica); 91 protocols.push_back(nfc_common::kProtocolMifare); 92 protocols.push_back(nfc_common::kProtocolJewel); 93 protocols.push_back(nfc_common::kProtocolIsoDep); 94 protocols.push_back(nfc_common::kProtocolNfcDep); 95 96 properties_.reset(new Properties(base::Bind( 97 &FakeNfcAdapterClient::OnPropertyChanged, 98 base::Unretained(this), 99 dbus::ObjectPath(kAdapterPath0)))); 100 properties_->protocols.ReplaceValue(protocols); 101 102 second_properties_.reset(new Properties(base::Bind( 103 &FakeNfcAdapterClient::OnPropertyChanged, 104 base::Unretained(this), 105 dbus::ObjectPath(kAdapterPath1)))); 106 second_properties_->protocols.ReplaceValue(protocols); 107 } 108 109 FakeNfcAdapterClient::~FakeNfcAdapterClient() { 110 } 111 112 void FakeNfcAdapterClient::Init(dbus::Bus* bus) { 113 } 114 115 void FakeNfcAdapterClient::AddObserver(Observer* observer) { 116 observers_.AddObserver(observer); 117 } 118 119 void FakeNfcAdapterClient::RemoveObserver(Observer* observer) { 120 observers_.RemoveObserver(observer); 121 } 122 123 std::vector<dbus::ObjectPath> FakeNfcAdapterClient::GetAdapters() { 124 std::vector<dbus::ObjectPath> object_paths; 125 if (present_) 126 object_paths.push_back(dbus::ObjectPath(kAdapterPath0)); 127 if (second_present_) 128 object_paths.push_back(dbus::ObjectPath(kAdapterPath1)); 129 return object_paths; 130 } 131 132 FakeNfcAdapterClient::Properties* 133 FakeNfcAdapterClient::GetProperties(const dbus::ObjectPath& object_path) { 134 if (object_path == dbus::ObjectPath(kAdapterPath0)) 135 return properties_.get(); 136 if (object_path == dbus::ObjectPath(kAdapterPath1)) 137 return second_properties_.get(); 138 return NULL; 139 } 140 141 void FakeNfcAdapterClient::StartPollLoop( 142 const dbus::ObjectPath& object_path, 143 const std::string& mode, 144 const base::Closure& callback, 145 const nfc_client_helpers::ErrorCallback& error_callback) { 146 VLOG(1) << "FakeNfcAdapterClient::StartPollLoop"; 147 if (object_path != dbus::ObjectPath(kAdapterPath0)) { 148 error_callback.Run(nfc_client_helpers::kNoResponseError, ""); 149 return; 150 } 151 if (!properties_->powered.value()) { 152 error_callback.Run(nfc_error::kFailed, "Adapter not powered."); 153 return; 154 } 155 if (properties_->polling.value()) { 156 error_callback.Run(nfc_error::kFailed, "Already polling."); 157 return; 158 } 159 if (!properties_->devices.value().empty() || 160 !properties_->tags.value().empty()) { 161 error_callback.Run(nfc_error::kFailed, "Adapter busy."); 162 return; 163 } 164 properties_->polling.ReplaceValue(true); 165 properties_->mode.ReplaceValue(mode); 166 callback.Run(); 167 168 if (!start_pairing_on_poll_) 169 return; 170 171 if (device_pairing_) { 172 FakeNfcDeviceClient* device_client = 173 static_cast<FakeNfcDeviceClient*>( 174 DBusThreadManager::Get()->GetNfcDeviceClient()); 175 device_client->BeginPairingSimulation(3000, 2000); 176 } else { 177 FakeNfcTagClient* tag_client = 178 static_cast<FakeNfcTagClient*>( 179 DBusThreadManager::Get()->GetNfcTagClient()); 180 tag_client->BeginPairingSimulation(2000); 181 } 182 device_pairing_ = !device_pairing_; 183 } 184 185 void FakeNfcAdapterClient::StopPollLoop( 186 const dbus::ObjectPath& object_path, 187 const base::Closure& callback, 188 const nfc_client_helpers::ErrorCallback& error_callback) { 189 VLOG(1) << "FakeNfcAdapterClient::StopPollLoop."; 190 if (object_path != dbus::ObjectPath(kAdapterPath0)) { 191 error_callback.Run(nfc_client_helpers::kNoResponseError, ""); 192 return; 193 } 194 if (!properties_->polling.value()) { 195 error_callback.Run("org.neard.Error.Failed", "Not polling."); 196 return; 197 } 198 FakeNfcDeviceClient* device_client = 199 static_cast<FakeNfcDeviceClient*>( 200 DBusThreadManager::Get()->GetNfcDeviceClient()); 201 device_client->EndPairingSimulation(); 202 FakeNfcTagClient* tag_client = 203 static_cast<FakeNfcTagClient*>( 204 DBusThreadManager::Get()->GetNfcTagClient()); 205 tag_client->EndPairingSimulation(); 206 properties_->polling.ReplaceValue(false); 207 callback.Run(); 208 } 209 210 void FakeNfcAdapterClient::SetAdapterPresent(bool present) { 211 if (present == present_) 212 return; 213 present_ = present; 214 if (present_) { 215 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 216 AdapterAdded(dbus::ObjectPath(kAdapterPath0))); 217 } else { 218 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 219 AdapterRemoved(dbus::ObjectPath(kAdapterPath0))); 220 } 221 } 222 223 void FakeNfcAdapterClient::SetSecondAdapterPresent(bool present) { 224 if (present == second_present_) 225 return; 226 second_present_ = present; 227 if (present_) { 228 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 229 AdapterAdded(dbus::ObjectPath(kAdapterPath1))); 230 } else { 231 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 232 AdapterRemoved(dbus::ObjectPath(kAdapterPath1))); 233 } 234 } 235 236 void FakeNfcAdapterClient::SetDevice(const dbus::ObjectPath& device_path) { 237 LOG(INFO) << "Add device path to the fake adapter: " << device_path.value(); 238 if (!properties_->polling.value()) { 239 LOG(ERROR) << "Adapter not polling, cannot set device."; 240 return; 241 } 242 const ObjectPathVector& devices(properties_->devices.value()); 243 for (ObjectPathVector::const_iterator iter = devices.begin(); 244 iter != devices.end(); ++iter) { 245 if (*iter == device_path) { 246 LOG(WARNING) << "Device path already in list of devices."; 247 return; 248 } 249 } 250 // Mark as not polling. 251 properties_->polling.ReplaceValue(false); 252 253 ObjectPathVector new_devices = devices; 254 new_devices.push_back(device_path); 255 properties_->devices.ReplaceValue(new_devices); 256 } 257 258 void FakeNfcAdapterClient::SetTag(const dbus::ObjectPath& tag_path) { 259 LOG(INFO) << "Add tag path to the fake adapter: " << tag_path.value(); 260 if (!properties_->polling.value()) { 261 LOG(ERROR) << "Adapter not polling, cannot set tag."; 262 return; 263 } 264 const ObjectPathVector& tags(properties_->tags.value()); 265 for (ObjectPathVector::const_iterator iter = tags.begin(); 266 iter != tags.end(); ++iter) { 267 if (*iter == tag_path) { 268 LOG(WARNING) << "Tag path already in list of tags."; 269 return; 270 } 271 } 272 // Mark as not polling. 273 properties_->polling.ReplaceValue(false); 274 275 ObjectPathVector new_tags = tags; 276 new_tags.push_back(tag_path); 277 properties_->tags.ReplaceValue(new_tags); 278 } 279 280 void FakeNfcAdapterClient::UnsetDevice(const dbus::ObjectPath& device_path) { 281 LOG(INFO) << "Remove device path from the fake adapter: " 282 << device_path.value(); 283 ObjectPathVector new_devices = properties_->devices.value(); 284 for (ObjectPathVector::iterator iter = new_devices.begin(); 285 iter != new_devices.end(); ++iter) { 286 if (*iter == device_path) { 287 new_devices.erase(iter); 288 properties_->devices.ReplaceValue(new_devices); 289 290 // Mark as polling. 291 DCHECK(!properties_->polling.value()); 292 properties_->polling.ReplaceValue(true); 293 return; 294 } 295 } 296 LOG(WARNING) << "Device path not in list of devices."; 297 } 298 299 void FakeNfcAdapterClient::UnsetTag(const dbus::ObjectPath& tag_path) { 300 LOG(INFO) << "Remove tag path from the fake adapter: " << tag_path.value(); 301 ObjectPathVector new_tags = properties_->tags.value(); 302 for (ObjectPathVector::iterator iter = new_tags.begin(); 303 iter != new_tags.end(); ++iter) { 304 if (*iter == tag_path) { 305 new_tags.erase(iter); 306 properties_->tags.ReplaceValue(new_tags); 307 308 // Mark as polling. 309 DCHECK(!properties_->polling.value()); 310 properties_->polling.ReplaceValue(true); 311 return; 312 } 313 } 314 LOG(WARNING) << "Tag path not in list of tags."; 315 } 316 317 void FakeNfcAdapterClient::EnablePairingOnPoll(bool enabled) { 318 start_pairing_on_poll_ = enabled; 319 } 320 321 void FakeNfcAdapterClient::OnPropertyChanged( 322 const dbus::ObjectPath& object_path, 323 const std::string& property_name) { 324 FOR_EACH_OBSERVER(NfcAdapterClient::Observer, observers_, 325 AdapterPropertyChanged(object_path, property_name)); 326 } 327 328 } // namespace chromeos 329