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/fake_bluetooth_device_client.h" 6 7 #include <fcntl.h> 8 #include <unistd.h> 9 #include <sys/types.h> 10 #include <sys/socket.h> 11 12 #include <algorithm> 13 #include <map> 14 #include <string> 15 #include <utility> 16 #include <vector> 17 18 #include "base/bind.h" 19 #include "base/logging.h" 20 #include "base/memory/scoped_ptr.h" 21 #include "base/message_loop/message_loop.h" 22 #include "base/stl_util.h" 23 #include "base/threading/worker_pool.h" 24 #include "base/time/time.h" 25 #include "chromeos/dbus/dbus_thread_manager.h" 26 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" 27 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" 28 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" 29 #include "chromeos/dbus/fake_bluetooth_input_client.h" 30 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" 31 #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" 32 #include "dbus/file_descriptor.h" 33 #include "dbus/object_path.h" 34 #include "third_party/cros_system_api/dbus/service_constants.h" 35 36 namespace { 37 38 // Default interval between simulated events. 39 const int kSimulationIntervalMs = 750; 40 41 42 void SimulatedProfileSocket(int fd) { 43 // Simulate a server-side socket of a profile; read data from the socket, 44 // write it back, and then close. 45 char buf[1024]; 46 ssize_t len; 47 ssize_t count; 48 49 len = read(fd, buf, sizeof buf); 50 if (len < 0) { 51 close(fd); 52 return; 53 } 54 55 count = len; 56 len = write(fd, buf, count); 57 if (len < 0) { 58 close(fd); 59 return; 60 } 61 62 close(fd); 63 } 64 65 } 66 67 namespace chromeos { 68 69 const char FakeBluetoothDeviceClient::kPairedDevicePath[] = 70 "/fake/hci0/dev0"; 71 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = 72 "00:11:22:33:44:55"; 73 const char FakeBluetoothDeviceClient::kPairedDeviceName[] = 74 "Fake Device"; 75 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104; 76 77 const char FakeBluetoothDeviceClient::kAppleMousePath[] = 78 "/fake/hci0/dev1"; 79 const char FakeBluetoothDeviceClient::kAppleMouseAddress[] = 80 "28:CF:DA:00:00:00"; 81 const char FakeBluetoothDeviceClient::kAppleMouseName[] = 82 "Apple Magic Mouse"; 83 const uint32 FakeBluetoothDeviceClient::kAppleMouseClass = 0x002580; 84 85 const char FakeBluetoothDeviceClient::kAppleKeyboardPath[] = 86 "/fake/hci0/dev2"; 87 const char FakeBluetoothDeviceClient::kAppleKeyboardAddress[] = 88 "28:37:37:00:00:00"; 89 const char FakeBluetoothDeviceClient::kAppleKeyboardName[] = 90 "Apple Wireless Keyboard"; 91 const uint32 FakeBluetoothDeviceClient::kAppleKeyboardClass = 0x002540; 92 93 const char FakeBluetoothDeviceClient::kVanishingDevicePath[] = 94 "/fake/hci0/dev3"; 95 const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] = 96 "01:02:03:04:05:06"; 97 const char FakeBluetoothDeviceClient::kVanishingDeviceName[] = 98 "Vanishing Device"; 99 const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104; 100 101 const char FakeBluetoothDeviceClient::kMicrosoftMousePath[] = 102 "/fake/hci0/dev4"; 103 const char FakeBluetoothDeviceClient::kMicrosoftMouseAddress[] = 104 "7C:ED:8D:00:00:00"; 105 const char FakeBluetoothDeviceClient::kMicrosoftMouseName[] = 106 "Microsoft Mouse"; 107 const uint32 FakeBluetoothDeviceClient::kMicrosoftMouseClass = 0x002580; 108 109 const char FakeBluetoothDeviceClient::kMotorolaKeyboardPath[] = 110 "/fake/hci0/dev5"; 111 const char FakeBluetoothDeviceClient::kMotorolaKeyboardAddress[] = 112 "00:0F:F6:00:00:00"; 113 const char FakeBluetoothDeviceClient::kMotorolaKeyboardName[] = 114 "Motorola Keyboard"; 115 const uint32 FakeBluetoothDeviceClient::kMotorolaKeyboardClass = 0x002540; 116 117 const char FakeBluetoothDeviceClient::kSonyHeadphonesPath[] = 118 "/fake/hci0/dev6"; 119 const char FakeBluetoothDeviceClient::kSonyHeadphonesAddress[] = 120 "00:24:BE:00:00:00"; 121 const char FakeBluetoothDeviceClient::kSonyHeadphonesName[] = 122 "Sony BT-00"; 123 const uint32 FakeBluetoothDeviceClient::kSonyHeadphonesClass = 0x240408; 124 125 const char FakeBluetoothDeviceClient::kPhonePath[] = 126 "/fake/hci0/dev7"; 127 const char FakeBluetoothDeviceClient::kPhoneAddress[] = 128 "20:7D:74:00:00:00"; 129 const char FakeBluetoothDeviceClient::kPhoneName[] = 130 "Phone"; 131 const uint32 FakeBluetoothDeviceClient::kPhoneClass = 0x7a020c; 132 133 const char FakeBluetoothDeviceClient::kWeirdDevicePath[] = 134 "/fake/hci0/dev8"; 135 const char FakeBluetoothDeviceClient::kWeirdDeviceAddress[] = 136 "20:7D:74:00:00:01"; 137 const char FakeBluetoothDeviceClient::kWeirdDeviceName[] = 138 "Weird Device"; 139 const uint32 FakeBluetoothDeviceClient::kWeirdDeviceClass = 0x7a020c; 140 141 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] = 142 "/fake/hci0/dev9"; 143 const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] = 144 "20:7D:74:00:00:02"; 145 const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] = 146 "Unconnectable Device"; 147 const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c; 148 149 const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] = 150 "/fake/hci0/devA"; 151 const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] = 152 "20:7D:74:00:00:03"; 153 const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] = 154 "Unpairable Device"; 155 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540; 156 157 FakeBluetoothDeviceClient::Properties::Properties( 158 const PropertyChangedCallback& callback) 159 : BluetoothDeviceClient::Properties( 160 NULL, 161 bluetooth_device::kBluetoothDeviceInterface, 162 callback) { 163 } 164 165 FakeBluetoothDeviceClient::Properties::~Properties() { 166 } 167 168 void FakeBluetoothDeviceClient::Properties::Get( 169 dbus::PropertyBase* property, 170 dbus::PropertySet::GetCallback callback) { 171 VLOG(1) << "Get " << property->name(); 172 callback.Run(false); 173 } 174 175 void FakeBluetoothDeviceClient::Properties::GetAll() { 176 VLOG(1) << "GetAll"; 177 } 178 179 void FakeBluetoothDeviceClient::Properties::Set( 180 dbus::PropertyBase *property, 181 dbus::PropertySet::SetCallback callback) { 182 VLOG(1) << "Set " << property->name(); 183 if (property->name() == trusted.name()) { 184 callback.Run(true); 185 property->ReplaceValueWithSetValue(); 186 } else { 187 callback.Run(false); 188 } 189 } 190 191 192 FakeBluetoothDeviceClient::FakeBluetoothDeviceClient() 193 : simulation_interval_ms_(kSimulationIntervalMs), 194 discovery_simulation_step_(0), 195 pairing_cancelled_(false) { 196 Properties* properties = new Properties(base::Bind( 197 &FakeBluetoothDeviceClient::OnPropertyChanged, 198 base::Unretained(this), 199 dbus::ObjectPath(kPairedDevicePath))); 200 properties->address.ReplaceValue(kPairedDeviceAddress); 201 properties->bluetooth_class.ReplaceValue(kPairedDeviceClass); 202 properties->name.ReplaceValue("Fake Device (Name)"); 203 properties->alias.ReplaceValue(kPairedDeviceName); 204 properties->paired.ReplaceValue(true); 205 properties->trusted.ReplaceValue(true); 206 properties->adapter.ReplaceValue( 207 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 208 209 std::vector<std::string> uuids; 210 uuids.push_back("00001800-0000-1000-8000-00805f9b34fb"); 211 uuids.push_back("00001801-0000-1000-8000-00805f9b34fb"); 212 properties->uuids.ReplaceValue(uuids); 213 214 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); 215 216 properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties; 217 device_list_.push_back(dbus::ObjectPath(kPairedDevicePath)); 218 } 219 220 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() { 221 // Clean up Properties structures 222 STLDeleteValues(&properties_map_); 223 } 224 225 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) { 226 observers_.AddObserver(observer); 227 } 228 229 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) { 230 observers_.RemoveObserver(observer); 231 } 232 233 std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter( 234 const dbus::ObjectPath& adapter_path) { 235 if (adapter_path == 236 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) 237 return device_list_; 238 else 239 return std::vector<dbus::ObjectPath>(); 240 } 241 242 FakeBluetoothDeviceClient::Properties* 243 FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) { 244 PropertiesMap::iterator iter = properties_map_.find(object_path); 245 if (iter != properties_map_.end()) 246 return iter->second; 247 return NULL; 248 } 249 250 void FakeBluetoothDeviceClient::Connect( 251 const dbus::ObjectPath& object_path, 252 const base::Closure& callback, 253 const ErrorCallback& error_callback) { 254 VLOG(1) << "Connect: " << object_path.value(); 255 Properties* properties = GetProperties(object_path); 256 257 if (properties->connected.value() == true) { 258 // Already connected. 259 callback.Run(); 260 return; 261 } 262 263 if (properties->paired.value() != true && 264 object_path != dbus::ObjectPath(kMicrosoftMousePath)) { 265 // Must be paired. 266 error_callback.Run(bluetooth_device::kErrorFailed, "Not paired"); 267 return; 268 } else if (properties->paired.value() == true && 269 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) { 270 // Must not be paired 271 error_callback.Run(bluetooth_device::kErrorFailed, 272 "Connection fails while paired"); 273 return; 274 } 275 276 // The device can be connected. 277 properties->connected.ReplaceValue(true); 278 callback.Run(); 279 280 AddInputDeviceIfNeeded(object_path, properties); 281 } 282 283 void FakeBluetoothDeviceClient::Disconnect( 284 const dbus::ObjectPath& object_path, 285 const base::Closure& callback, 286 const ErrorCallback& error_callback) { 287 VLOG(1) << "Disconnect: " << object_path.value(); 288 Properties* properties = GetProperties(object_path); 289 290 if (properties->connected.value() == true) { 291 callback.Run(); 292 properties->connected.ReplaceValue(false); 293 } else { 294 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); 295 } 296 } 297 298 void FakeBluetoothDeviceClient::ConnectProfile( 299 const dbus::ObjectPath& object_path, 300 const std::string& uuid, 301 const base::Closure& callback, 302 const ErrorCallback& error_callback) { 303 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; 304 305 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = 306 static_cast<FakeBluetoothProfileManagerClient*>( 307 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); 308 FakeBluetoothProfileServiceProvider* profile_service_provider = 309 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); 310 if (profile_service_provider == NULL) { 311 error_callback.Run(kNoResponseError, "Missing profile"); 312 return; 313 } 314 315 // Make a socket pair of a compatible type with the type used by Bluetooth; 316 // spin up a thread to simulate the server side and wrap the client side in 317 // a D-Bus file descriptor object. 318 int socket_type = SOCK_STREAM; 319 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) 320 socket_type = SOCK_SEQPACKET; 321 322 int fds[2]; 323 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { 324 error_callback.Run(kNoResponseError, "socketpair call failed"); 325 return; 326 } 327 328 int args; 329 args = fcntl(fds[1], F_GETFL, NULL); 330 if (args < 0) { 331 error_callback.Run(kNoResponseError, "failed to get socket flags"); 332 return; 333 } 334 335 args |= O_NONBLOCK; 336 if (fcntl(fds[1], F_SETFL, args) < 0) { 337 error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); 338 return; 339 } 340 341 base::WorkerPool::GetTaskRunner(false)->PostTask( 342 FROM_HERE, 343 base::Bind(&SimulatedProfileSocket, 344 fds[0])); 345 346 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); 347 348 // Post the new connection to the service provider. 349 BluetoothProfileServiceProvider::Delegate::Options options; 350 351 profile_service_provider->NewConnection( 352 object_path, 353 fd.Pass(), 354 options, 355 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, 356 base::Unretained(this), 357 object_path, 358 callback, 359 error_callback)); 360 } 361 362 void FakeBluetoothDeviceClient::DisconnectProfile( 363 const dbus::ObjectPath& object_path, 364 const std::string& uuid, 365 const base::Closure& callback, 366 const ErrorCallback& error_callback) { 367 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; 368 369 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = 370 static_cast<FakeBluetoothProfileManagerClient*>( 371 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); 372 FakeBluetoothProfileServiceProvider* profile_service_provider = 373 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); 374 if (profile_service_provider == NULL) { 375 error_callback.Run(kNoResponseError, "Missing profile"); 376 return; 377 } 378 379 profile_service_provider->RequestDisconnection( 380 object_path, 381 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, 382 base::Unretained(this), 383 object_path, 384 callback, 385 error_callback)); 386 } 387 388 void FakeBluetoothDeviceClient::Pair( 389 const dbus::ObjectPath& object_path, 390 const base::Closure& callback, 391 const ErrorCallback& error_callback) { 392 VLOG(1) << "Pair: " << object_path.value(); 393 Properties* properties = GetProperties(object_path); 394 395 if (properties->paired.value() == true) { 396 // Already paired. 397 callback.Run(); 398 return; 399 } 400 401 pairing_cancelled_ = false; 402 403 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = 404 static_cast<FakeBluetoothAgentManagerClient*>( 405 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); 406 FakeBluetoothAgentServiceProvider* agent_service_provider = 407 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); 408 if (agent_service_provider == NULL) { 409 error_callback.Run(kNoResponseError, "Missing agent"); 410 return; 411 } 412 413 if (object_path == dbus::ObjectPath(kAppleMousePath) || 414 object_path == dbus::ObjectPath(kMicrosoftMousePath) || 415 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) { 416 // No need to call anything on the pairing delegate, just wait 3 times 417 // the interval before acting as if the other end accepted it. 418 base::MessageLoop::current()->PostDelayedTask( 419 FROM_HERE, 420 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 421 base::Unretained(this), 422 object_path, callback, error_callback), 423 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 424 425 } else if (object_path == dbus::ObjectPath(kAppleKeyboardPath)) { 426 // Display a Pincode, and wait 7 times the interval before acting as 427 // if the other end accepted it. 428 agent_service_provider->DisplayPinCode(object_path, "123456"); 429 430 base::MessageLoop::current()->PostDelayedTask( 431 FROM_HERE, 432 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 433 base::Unretained(this), 434 object_path, callback, error_callback), 435 base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_)); 436 437 } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) { 438 // The vanishing device simulates being too far away, and thus times out. 439 base::MessageLoop::current()->PostDelayedTask( 440 FROM_HERE, 441 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing, 442 base::Unretained(this), 443 object_path, error_callback), 444 base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_)); 445 446 } else if (object_path == dbus::ObjectPath(kMotorolaKeyboardPath)) { 447 // Display a passkey, and each interval act as if another key was entered 448 // for it. 449 agent_service_provider->DisplayPasskey(object_path, 123456, 0); 450 451 base::MessageLoop::current()->PostDelayedTask( 452 FROM_HERE, 453 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, 454 base::Unretained(this), 455 1, object_path, callback, error_callback), 456 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 457 458 } else if (object_path == dbus::ObjectPath(kSonyHeadphonesPath)) { 459 // Request a Pincode. 460 agent_service_provider->RequestPinCode( 461 object_path, 462 base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, 463 base::Unretained(this), 464 object_path, 465 callback, 466 error_callback)); 467 468 } else if (object_path == dbus::ObjectPath(kPhonePath)) { 469 // Request confirmation of a Passkey. 470 agent_service_provider->RequestConfirmation( 471 object_path, 123456, 472 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, 473 base::Unretained(this), 474 object_path, 475 callback, 476 error_callback)); 477 478 } else if (object_path == dbus::ObjectPath(kWeirdDevicePath)) { 479 // Request a Passkey from the user. 480 agent_service_provider->RequestPasskey( 481 object_path, 482 base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, 483 base::Unretained(this), 484 object_path, 485 callback, 486 error_callback)); 487 488 } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) { 489 // Fails the pairing with an org.bluez.Error.Failed error. 490 base::MessageLoop::current()->PostDelayedTask( 491 FROM_HERE, 492 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, 493 base::Unretained(this), 494 object_path, error_callback), 495 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 496 497 } else { 498 error_callback.Run(kNoResponseError, "No pairing fake"); 499 } 500 } 501 502 void FakeBluetoothDeviceClient::CancelPairing( 503 const dbus::ObjectPath& object_path, 504 const base::Closure& callback, 505 const ErrorCallback& error_callback) { 506 VLOG(1) << "CancelPairing: " << object_path.value(); 507 pairing_cancelled_ = true; 508 callback.Run(); 509 } 510 511 512 void FakeBluetoothDeviceClient::BeginDiscoverySimulation( 513 const dbus::ObjectPath& adapter_path) { 514 VLOG(1) << "starting discovery simulation"; 515 516 discovery_simulation_step_ = 1; 517 518 base::MessageLoop::current()->PostDelayedTask( 519 FROM_HERE, 520 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, 521 base::Unretained(this)), 522 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 523 } 524 525 void FakeBluetoothDeviceClient::EndDiscoverySimulation( 526 const dbus::ObjectPath& adapter_path) { 527 VLOG(1) << "stopping discovery simulation"; 528 discovery_simulation_step_ = 0; 529 } 530 531 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) { 532 simulation_interval_ms_ = interval_ms; 533 } 534 535 void FakeBluetoothDeviceClient::RemoveDevice( 536 const dbus::ObjectPath& adapter_path, 537 const dbus::ObjectPath& device_path) { 538 std::vector<dbus::ObjectPath>::iterator listiter = 539 std::find(device_list_.begin(), device_list_.end(), device_path); 540 if (listiter == device_list_.end()) 541 return; 542 543 PropertiesMap::iterator iter = properties_map_.find(device_path); 544 Properties* properties = iter->second; 545 546 VLOG(1) << "removing device: " << properties->alias.value(); 547 device_list_.erase(listiter); 548 549 // Remove the Input interface if it exists. This should be called before the 550 // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the 551 // BluetoothDeviceChromeOS object, including the device_path referenced here. 552 FakeBluetoothInputClient* fake_bluetooth_input_client = 553 static_cast<FakeBluetoothInputClient*>( 554 DBusThreadManager::Get()->GetBluetoothInputClient()); 555 fake_bluetooth_input_client->RemoveInputDevice(device_path); 556 557 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 558 DeviceRemoved(device_path)); 559 560 delete properties; 561 properties_map_.erase(iter); 562 } 563 564 void FakeBluetoothDeviceClient::OnPropertyChanged( 565 const dbus::ObjectPath& object_path, 566 const std::string& property_name) { 567 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 568 DevicePropertyChanged(object_path, property_name)); 569 } 570 571 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { 572 if (!discovery_simulation_step_) 573 return; 574 575 // Timer fires every .75s, the numbers below are arbitrary to give a feel 576 // for a discovery process. 577 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; 578 if (discovery_simulation_step_ == 2) { 579 if (std::find(device_list_.begin(), device_list_.end(), 580 dbus::ObjectPath(kAppleMousePath)) == device_list_.end()) { 581 Properties* properties = new Properties(base::Bind( 582 &FakeBluetoothDeviceClient::OnPropertyChanged, 583 base::Unretained(this), 584 dbus::ObjectPath(kAppleMousePath))); 585 properties->address.ReplaceValue(kAppleMouseAddress); 586 properties->bluetooth_class.ReplaceValue(kAppleMouseClass); 587 properties->name.ReplaceValue("Fake Apple Magic Mouse"); 588 properties->alias.ReplaceValue(kAppleMouseName); 589 properties->adapter.ReplaceValue( 590 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 591 592 std::vector<std::string> uuids; 593 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 594 properties->uuids.ReplaceValue(uuids); 595 596 properties_map_[dbus::ObjectPath(kAppleMousePath)] = properties; 597 device_list_.push_back(dbus::ObjectPath(kAppleMousePath)); 598 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 599 DeviceAdded(dbus::ObjectPath(kAppleMousePath))); 600 } 601 602 } else if (discovery_simulation_step_ == 4) { 603 if (std::find(device_list_.begin(), device_list_.end(), 604 dbus::ObjectPath(kAppleKeyboardPath)) == device_list_.end()) { 605 Properties *properties = new Properties(base::Bind( 606 &FakeBluetoothDeviceClient::OnPropertyChanged, 607 base::Unretained(this), 608 dbus::ObjectPath(kAppleKeyboardPath))); 609 properties->address.ReplaceValue(kAppleKeyboardAddress); 610 properties->bluetooth_class.ReplaceValue(kAppleKeyboardClass); 611 properties->name.ReplaceValue("Fake Apple Wireless Keyboard"); 612 properties->alias.ReplaceValue(kAppleKeyboardName); 613 properties->adapter.ReplaceValue( 614 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 615 616 std::vector<std::string> uuids; 617 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 618 properties->uuids.ReplaceValue(uuids); 619 620 properties_map_[dbus::ObjectPath(kAppleKeyboardPath)] = properties; 621 device_list_.push_back(dbus::ObjectPath(kAppleKeyboardPath)); 622 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 623 DeviceAdded(dbus::ObjectPath(kAppleKeyboardPath))); 624 } 625 626 if (std::find(device_list_.begin(), device_list_.end(), 627 dbus::ObjectPath(kVanishingDevicePath)) == 628 device_list_.end()) { 629 Properties* properties = new Properties(base::Bind( 630 &FakeBluetoothDeviceClient::OnPropertyChanged, 631 base::Unretained(this), 632 dbus::ObjectPath(kVanishingDevicePath))); 633 properties->address.ReplaceValue(kVanishingDeviceAddress); 634 properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass); 635 properties->name.ReplaceValue("Fake Vanishing Device"); 636 properties->alias.ReplaceValue(kVanishingDeviceName); 637 properties->adapter.ReplaceValue( 638 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 639 640 properties_map_[dbus::ObjectPath(kVanishingDevicePath)] = properties; 641 device_list_.push_back(dbus::ObjectPath(kVanishingDevicePath)); 642 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 643 DeviceAdded(dbus::ObjectPath(kVanishingDevicePath))); 644 } 645 646 } else if (discovery_simulation_step_ == 7) { 647 if (std::find(device_list_.begin(), device_list_.end(), 648 dbus::ObjectPath(kMicrosoftMousePath)) == 649 device_list_.end()) { 650 Properties* properties = new Properties(base::Bind( 651 &FakeBluetoothDeviceClient::OnPropertyChanged, 652 base::Unretained(this), 653 dbus::ObjectPath(kMicrosoftMousePath))); 654 properties->address.ReplaceValue(kMicrosoftMouseAddress); 655 properties->bluetooth_class.ReplaceValue(kMicrosoftMouseClass); 656 properties->name.ReplaceValue("Fake Microsoft Mouse"); 657 properties->alias.ReplaceValue(kMicrosoftMouseName); 658 properties->adapter.ReplaceValue( 659 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 660 661 std::vector<std::string> uuids; 662 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 663 properties->uuids.ReplaceValue(uuids); 664 665 properties_map_[dbus::ObjectPath(kMicrosoftMousePath)] = properties; 666 device_list_.push_back(dbus::ObjectPath(kMicrosoftMousePath)); 667 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 668 DeviceAdded(dbus::ObjectPath(kMicrosoftMousePath))); 669 } 670 671 } else if (discovery_simulation_step_ == 8) { 672 if (std::find(device_list_.begin(), device_list_.end(), 673 dbus::ObjectPath(kMotorolaKeyboardPath)) == 674 device_list_.end()) { 675 Properties* properties = new Properties(base::Bind( 676 &FakeBluetoothDeviceClient::OnPropertyChanged, 677 base::Unretained(this), 678 dbus::ObjectPath(kMotorolaKeyboardPath))); 679 properties->address.ReplaceValue(kMotorolaKeyboardAddress); 680 properties->bluetooth_class.ReplaceValue(kMotorolaKeyboardClass); 681 properties->name.ReplaceValue("Fake Motorola Keyboard"); 682 properties->alias.ReplaceValue(kMotorolaKeyboardName); 683 properties->adapter.ReplaceValue( 684 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 685 686 std::vector<std::string> uuids; 687 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 688 properties->uuids.ReplaceValue(uuids); 689 690 properties_map_[dbus::ObjectPath(kMotorolaKeyboardPath)] = properties; 691 device_list_.push_back(dbus::ObjectPath(kMotorolaKeyboardPath)); 692 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 693 DeviceAdded(dbus::ObjectPath(kMotorolaKeyboardPath))); 694 } 695 696 if (std::find(device_list_.begin(), device_list_.end(), 697 dbus::ObjectPath(kSonyHeadphonesPath)) == 698 device_list_.end()) { 699 Properties* properties = new Properties(base::Bind( 700 &FakeBluetoothDeviceClient::OnPropertyChanged, 701 base::Unretained(this), 702 dbus::ObjectPath(kSonyHeadphonesPath))); 703 properties->address.ReplaceValue(kSonyHeadphonesAddress); 704 properties->bluetooth_class.ReplaceValue(kSonyHeadphonesClass); 705 properties->name.ReplaceValue("Fake Sony Headphones"); 706 properties->alias.ReplaceValue(kSonyHeadphonesName); 707 properties->adapter.ReplaceValue( 708 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 709 710 properties_map_[dbus::ObjectPath(kSonyHeadphonesPath)] = properties; 711 device_list_.push_back(dbus::ObjectPath(kSonyHeadphonesPath)); 712 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 713 DeviceAdded(dbus::ObjectPath(kSonyHeadphonesPath))); 714 } 715 716 } else if (discovery_simulation_step_ == 10) { 717 if (std::find(device_list_.begin(), device_list_.end(), 718 dbus::ObjectPath(kPhonePath)) == device_list_.end()) { 719 Properties* properties = new Properties(base::Bind( 720 &FakeBluetoothDeviceClient::OnPropertyChanged, 721 base::Unretained(this), 722 dbus::ObjectPath(kPhonePath))); 723 properties->address.ReplaceValue(kPhoneAddress); 724 properties->bluetooth_class.ReplaceValue(kPhoneClass); 725 properties->name.ReplaceValue("Fake Phone"); 726 properties->alias.ReplaceValue(kPhoneName); 727 properties->adapter.ReplaceValue( 728 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 729 730 properties_map_[dbus::ObjectPath(kPhonePath)] = properties; 731 device_list_.push_back(dbus::ObjectPath(kPhonePath)); 732 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 733 DeviceAdded(dbus::ObjectPath(kPhonePath))); 734 } 735 736 if (std::find(device_list_.begin(), device_list_.end(), 737 dbus::ObjectPath(kWeirdDevicePath)) == device_list_.end()) { 738 Properties* properties = new Properties(base::Bind( 739 &FakeBluetoothDeviceClient::OnPropertyChanged, 740 base::Unretained(this), 741 dbus::ObjectPath(kWeirdDevicePath))); 742 properties->address.ReplaceValue(kWeirdDeviceAddress); 743 properties->bluetooth_class.ReplaceValue(kWeirdDeviceClass); 744 properties->name.ReplaceValue("Fake Weird Device"); 745 properties->alias.ReplaceValue(kWeirdDeviceName); 746 properties->adapter.ReplaceValue( 747 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 748 749 properties_map_[dbus::ObjectPath(kWeirdDevicePath)] = properties; 750 device_list_.push_back(dbus::ObjectPath(kWeirdDevicePath)); 751 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 752 DeviceAdded(dbus::ObjectPath(kWeirdDevicePath))); 753 } 754 755 if (std::find(device_list_.begin(), device_list_.end(), 756 dbus::ObjectPath(kUnconnectableDevicePath)) == 757 device_list_.end()) { 758 Properties* properties = new Properties(base::Bind( 759 &FakeBluetoothDeviceClient::OnPropertyChanged, 760 base::Unretained(this), 761 dbus::ObjectPath(kUnconnectableDevicePath))); 762 properties->address.ReplaceValue(kUnconnectableDeviceAddress); 763 properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass); 764 properties->name.ReplaceValue("Fake Unconnectable Device"); 765 properties->alias.ReplaceValue(kUnconnectableDeviceName); 766 properties->adapter.ReplaceValue( 767 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 768 769 properties_map_[dbus::ObjectPath(kUnconnectableDevicePath)] = properties; 770 device_list_.push_back(dbus::ObjectPath(kUnconnectableDevicePath)); 771 FOR_EACH_OBSERVER( 772 BluetoothDeviceClient::Observer, observers_, 773 DeviceAdded(dbus::ObjectPath(kUnconnectableDevicePath))); 774 } 775 776 if (std::find(device_list_.begin(), device_list_.end(), 777 dbus::ObjectPath(kUnpairableDevicePath)) == 778 device_list_.end()) { 779 Properties* properties = new Properties(base::Bind( 780 &FakeBluetoothDeviceClient::OnPropertyChanged, 781 base::Unretained(this), 782 dbus::ObjectPath(kUnpairableDevicePath))); 783 properties->address.ReplaceValue(kUnpairableDeviceAddress); 784 properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass); 785 properties->name.ReplaceValue("Fake Unpairable Device"); 786 properties->alias.ReplaceValue(kUnpairableDeviceName); 787 properties->adapter.ReplaceValue( 788 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 789 790 properties_map_[dbus::ObjectPath(kUnpairableDevicePath)] = properties; 791 device_list_.push_back(dbus::ObjectPath(kUnpairableDevicePath)); 792 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 793 DeviceAdded(dbus::ObjectPath(kUnpairableDevicePath))); 794 } 795 796 } else if (discovery_simulation_step_ == 13) { 797 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 798 dbus::ObjectPath(kVanishingDevicePath)); 799 800 } else if (discovery_simulation_step_ == 14) { 801 return; 802 803 } 804 805 ++discovery_simulation_step_; 806 base::MessageLoop::current()->PostDelayedTask( 807 FROM_HERE, 808 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, 809 base::Unretained(this)), 810 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 811 } 812 813 814 void FakeBluetoothDeviceClient::CompleteSimulatedPairing( 815 const dbus::ObjectPath& object_path, 816 const base::Closure& callback, 817 const ErrorCallback& error_callback) { 818 VLOG(1) << "CompleteSimulatedPairing: " << object_path.value(); 819 if (pairing_cancelled_) { 820 pairing_cancelled_ = false; 821 822 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, 823 "Cancaled"); 824 } else { 825 Properties* properties = GetProperties(object_path); 826 827 properties->paired.ReplaceValue(true); 828 callback.Run(); 829 830 AddInputDeviceIfNeeded(object_path, properties); 831 } 832 } 833 834 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing( 835 const dbus::ObjectPath& object_path, 836 const ErrorCallback& error_callback) { 837 VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value(); 838 839 error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout, 840 "Timed out"); 841 } 842 843 void FakeBluetoothDeviceClient::CancelSimulatedPairing( 844 const dbus::ObjectPath& object_path, 845 const ErrorCallback& error_callback) { 846 VLOG(1) << "CancelSimulatedPairing: " << object_path.value(); 847 848 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, 849 "Canceled"); 850 } 851 852 void FakeBluetoothDeviceClient::RejectSimulatedPairing( 853 const dbus::ObjectPath& object_path, 854 const ErrorCallback& error_callback) { 855 VLOG(1) << "RejectSimulatedPairing: " << object_path.value(); 856 857 error_callback.Run(bluetooth_device::kErrorAuthenticationRejected, 858 "Rejected"); 859 } 860 861 void FakeBluetoothDeviceClient::FailSimulatedPairing( 862 const dbus::ObjectPath& object_path, 863 const ErrorCallback& error_callback) { 864 VLOG(1) << "FailSimulatedPairing: " << object_path.value(); 865 866 error_callback.Run(bluetooth_device::kErrorFailed, "Failed"); 867 } 868 869 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( 870 const dbus::ObjectPath& object_path, 871 Properties* properties) { 872 // If the paired device is a HID device based on it's bluetooth class, 873 // simulate the Input interface. 874 FakeBluetoothInputClient* fake_bluetooth_input_client = 875 static_cast<FakeBluetoothInputClient*>( 876 DBusThreadManager::Get()->GetBluetoothInputClient()); 877 878 if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) 879 fake_bluetooth_input_client->AddInputDevice(object_path); 880 } 881 882 void FakeBluetoothDeviceClient::PinCodeCallback( 883 const dbus::ObjectPath& object_path, 884 const base::Closure& callback, 885 const ErrorCallback& error_callback, 886 BluetoothAgentServiceProvider::Delegate::Status status, 887 const std::string& pincode) { 888 VLOG(1) << "PinCodeCallback: " << object_path.value(); 889 890 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 891 base::MessageLoop::current()->PostDelayedTask( 892 FROM_HERE, 893 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 894 base::Unretained(this), 895 object_path, callback, error_callback), 896 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 897 898 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 899 base::MessageLoop::current()->PostDelayedTask( 900 FROM_HERE, 901 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 902 base::Unretained(this), 903 object_path, error_callback), 904 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 905 906 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 907 base::MessageLoop::current()->PostDelayedTask( 908 FROM_HERE, 909 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 910 base::Unretained(this), 911 object_path, error_callback), 912 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 913 914 } 915 } 916 917 void FakeBluetoothDeviceClient::PasskeyCallback( 918 const dbus::ObjectPath& object_path, 919 const base::Closure& callback, 920 const ErrorCallback& error_callback, 921 BluetoothAgentServiceProvider::Delegate::Status status, 922 uint32 passkey) { 923 VLOG(1) << "PasskeyCallback: " << object_path.value(); 924 925 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 926 base::MessageLoop::current()->PostDelayedTask( 927 FROM_HERE, 928 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 929 base::Unretained(this), 930 object_path, callback, error_callback), 931 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 932 933 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 934 base::MessageLoop::current()->PostDelayedTask( 935 FROM_HERE, 936 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 937 base::Unretained(this), 938 object_path, error_callback), 939 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 940 941 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 942 base::MessageLoop::current()->PostDelayedTask( 943 FROM_HERE, 944 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 945 base::Unretained(this), 946 object_path, error_callback), 947 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 948 949 } 950 } 951 952 void FakeBluetoothDeviceClient::ConfirmationCallback( 953 const dbus::ObjectPath& object_path, 954 const base::Closure& callback, 955 const ErrorCallback& error_callback, 956 BluetoothAgentServiceProvider::Delegate::Status status) { 957 VLOG(1) << "ConfirmationCallback: " << object_path.value(); 958 959 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 960 base::MessageLoop::current()->PostDelayedTask( 961 FROM_HERE, 962 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 963 base::Unretained(this), 964 object_path, callback, error_callback), 965 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 966 967 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 968 base::MessageLoop::current()->PostDelayedTask( 969 FROM_HERE, 970 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 971 base::Unretained(this), 972 object_path, error_callback), 973 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 974 975 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 976 base::MessageLoop::current()->PostDelayedTask( 977 FROM_HERE, 978 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 979 base::Unretained(this), 980 object_path, error_callback), 981 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 982 983 } 984 } 985 986 void FakeBluetoothDeviceClient::SimulateKeypress( 987 uint16 entered, 988 const dbus::ObjectPath& object_path, 989 const base::Closure& callback, 990 const ErrorCallback& error_callback) { 991 VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value(); 992 993 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = 994 static_cast<FakeBluetoothAgentManagerClient*>( 995 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); 996 FakeBluetoothAgentServiceProvider* agent_service_provider = 997 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); 998 999 // The agent service provider object could have been destroyed after the 1000 // pairing is canceled. 1001 if (!agent_service_provider) 1002 return; 1003 1004 agent_service_provider->DisplayPasskey(object_path, 123456, entered); 1005 1006 if (entered < 7) { 1007 base::MessageLoop::current()->PostDelayedTask( 1008 FROM_HERE, 1009 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, 1010 base::Unretained(this), 1011 entered + 1, object_path, callback, error_callback), 1012 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1013 1014 } else { 1015 base::MessageLoop::current()->PostDelayedTask( 1016 FROM_HERE, 1017 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 1018 base::Unretained(this), 1019 object_path, callback, error_callback), 1020 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1021 1022 } 1023 } 1024 1025 void FakeBluetoothDeviceClient::ConnectionCallback( 1026 const dbus::ObjectPath& object_path, 1027 const base::Closure& callback, 1028 const ErrorCallback& error_callback, 1029 BluetoothProfileServiceProvider::Delegate::Status status) { 1030 VLOG(1) << "ConnectionCallback: " << object_path.value(); 1031 1032 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { 1033 callback.Run(); 1034 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { 1035 // TODO(keybuk): tear down this side of the connection 1036 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); 1037 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { 1038 // TODO(keybuk): tear down this side of the connection 1039 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); 1040 } 1041 } 1042 1043 void FakeBluetoothDeviceClient::DisconnectionCallback( 1044 const dbus::ObjectPath& object_path, 1045 const base::Closure& callback, 1046 const ErrorCallback& error_callback, 1047 BluetoothProfileServiceProvider::Delegate::Status status) { 1048 VLOG(1) << "DisconnectionCallback: " << object_path.value(); 1049 1050 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { 1051 // TODO(keybuk): tear down this side of the connection 1052 callback.Run(); 1053 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { 1054 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); 1055 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { 1056 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); 1057 } 1058 } 1059 1060 } // namespace chromeos 1061