Fix a type mismatch on Windows caused by r201738.
[chromium-blink-merge.git] / chromeos / dbus / fake_bluetooth_device_client.cc
blobb1ed840a9786a878500bf5e4cdd7999a661d8c9f
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.
5 #include "chromeos/dbus/fake_bluetooth_device_client.h"
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
12 #include <algorithm>
13 #include <map>
14 #include <string>
15 #include <utility>
16 #include <vector>
18 #include "base/bind.h"
19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop.h"
22 #include "base/stl_util.h"
23 #include "base/threading/worker_pool.h"
24 #include "base/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"
36 namespace {
38 // Default interval between simulated events.
39 const int kSimulationIntervalMs = 750;
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;
49 len = read(fd, buf, sizeof buf);
50 if (len < 0) {
51 close(fd);
52 return;
55 count = len;
56 len = write(fd, buf, count);
57 if (len < 0) {
58 close(fd);
59 return;
62 close(fd);
67 namespace chromeos {
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
157 FakeBluetoothDeviceClient::Properties::Properties(
158 const PropertyChangedCallback& callback)
159 : ExperimentalBluetoothDeviceClient::Properties(
160 NULL,
161 bluetooth_device::kExperimentalBluetoothDeviceInterface,
162 callback) {
165 FakeBluetoothDeviceClient::Properties::~Properties() {
168 void FakeBluetoothDeviceClient::Properties::Get(
169 dbus::PropertyBase* property,
170 dbus::PropertySet::GetCallback callback) {
171 VLOG(1) << "Get " << property->name();
172 callback.Run(false);
175 void FakeBluetoothDeviceClient::Properties::GetAll() {
176 VLOG(1) << "GetAll";
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);
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));
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);
214 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306");
216 properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties;
217 device_list_.push_back(dbus::ObjectPath(kPairedDevicePath));
220 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
221 // Clean up Properties structures
222 STLDeleteValues(&properties_map_);
225 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
226 observers_.AddObserver(observer);
229 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) {
230 observers_.RemoveObserver(observer);
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>();
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;
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);
257 if (properties->connected.value() == true) {
258 // Already connected.
259 callback.Run();
260 return;
263 if (properties->paired.value() != true &&
264 object_path != dbus::ObjectPath(kMicrosoftMousePath)) {
265 // Must be paired.
266 error_callback.Run(bluetooth_adapter::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_adapter::kErrorFailed,
272 "Connection fails while paired");
273 return;
276 // The device can be connected.
277 properties->connected.ReplaceValue(true);
278 callback.Run();
280 AddInputDeviceIfNeeded(object_path, properties);
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);
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");
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;
305 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
306 static_cast<FakeBluetoothProfileManagerClient*>(
307 DBusThreadManager::Get()->
308 GetExperimentalBluetoothProfileManagerClient());
309 FakeBluetoothProfileServiceProvider* profile_service_provider =
310 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
311 if (profile_service_provider == NULL) {
312 error_callback.Run(kNoResponseError, "Missing profile");
313 return;
316 // Make a socket pair of a compatible type with the type used by Bluetooth;
317 // spin up a thread to simulate the server side and wrap the client side in
318 // a D-Bus file descriptor object.
319 int socket_type = SOCK_STREAM;
320 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid)
321 socket_type = SOCK_SEQPACKET;
323 int fds[2];
324 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) {
325 error_callback.Run(kNoResponseError, "socketpair call failed");
326 return;
329 int args;
330 args = fcntl(fds[1], F_GETFL, NULL);
331 if (args < 0) {
332 error_callback.Run(kNoResponseError, "failed to get socket flags");
333 return;
336 args |= O_NONBLOCK;
337 if (fcntl(fds[1], F_SETFL, args) < 0) {
338 error_callback.Run(kNoResponseError, "failed to set socket non-blocking");
339 return;
342 base::WorkerPool::GetTaskRunner(false)->PostTask(
343 FROM_HERE,
344 base::Bind(&SimulatedProfileSocket,
345 fds[0]));
347 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));
349 // Post the new connection to the service provider.
350 ExperimentalBluetoothProfileServiceProvider::Delegate::Options options;
352 profile_service_provider->NewConnection(
353 object_path,
354 fd.Pass(),
355 options,
356 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
357 base::Unretained(this),
358 object_path,
359 callback,
360 error_callback));
363 void FakeBluetoothDeviceClient::DisconnectProfile(
364 const dbus::ObjectPath& object_path,
365 const std::string& uuid,
366 const base::Closure& callback,
367 const ErrorCallback& error_callback) {
368 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid;
370 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
371 static_cast<FakeBluetoothProfileManagerClient*>(
372 DBusThreadManager::Get()->
373 GetExperimentalBluetoothProfileManagerClient());
374 FakeBluetoothProfileServiceProvider* profile_service_provider =
375 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
376 if (profile_service_provider == NULL) {
377 error_callback.Run(kNoResponseError, "Missing profile");
378 return;
381 profile_service_provider->RequestDisconnection(
382 object_path,
383 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
384 base::Unretained(this),
385 object_path,
386 callback,
387 error_callback));
390 void FakeBluetoothDeviceClient::Pair(
391 const dbus::ObjectPath& object_path,
392 const base::Closure& callback,
393 const ErrorCallback& error_callback) {
394 VLOG(1) << "Pair: " << object_path.value();
395 Properties* properties = GetProperties(object_path);
397 if (properties->paired.value() == true) {
398 // Already paired.
399 callback.Run();
400 return;
403 pairing_cancelled_ = false;
405 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
406 static_cast<FakeBluetoothAgentManagerClient*>(
407 DBusThreadManager::Get()->
408 GetExperimentalBluetoothAgentManagerClient());
409 FakeBluetoothAgentServiceProvider* agent_service_provider =
410 fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
411 if (agent_service_provider == NULL) {
412 error_callback.Run(kNoResponseError, "Missing agent");
413 return;
416 if (object_path == dbus::ObjectPath(kAppleMousePath) ||
417 object_path == dbus::ObjectPath(kMicrosoftMousePath) ||
418 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
419 // No need to call anything on the pairing delegate, just wait 3 times
420 // the interval before acting as if the other end accepted it.
421 MessageLoop::current()->PostDelayedTask(
422 FROM_HERE,
423 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
424 base::Unretained(this),
425 object_path, callback, error_callback),
426 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
428 } else if (object_path == dbus::ObjectPath(kAppleKeyboardPath)) {
429 // Display a Pincode, and wait 7 times the interval before acting as
430 // if the other end accepted it.
431 agent_service_provider->DisplayPinCode(object_path, "123456");
433 MessageLoop::current()->PostDelayedTask(
434 FROM_HERE,
435 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
436 base::Unretained(this),
437 object_path, callback, error_callback),
438 base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_));
440 } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) {
441 // The vanishing device simulates being too far away, and thus times out.
442 MessageLoop::current()->PostDelayedTask(
443 FROM_HERE,
444 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing,
445 base::Unretained(this),
446 object_path, error_callback),
447 base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_));
449 } else if (object_path == dbus::ObjectPath(kMotorolaKeyboardPath)) {
450 // Display a passkey, and each interval act as if another key was entered
451 // for it.
452 agent_service_provider->DisplayPasskey(object_path, 123456, 0);
454 MessageLoop::current()->PostDelayedTask(
455 FROM_HERE,
456 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
457 base::Unretained(this),
458 1, object_path, callback, error_callback),
459 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
461 } else if (object_path == dbus::ObjectPath(kSonyHeadphonesPath)) {
462 // Request a Pincode.
463 agent_service_provider->RequestPinCode(
464 object_path,
465 base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback,
466 base::Unretained(this),
467 object_path,
468 callback,
469 error_callback));
471 } else if (object_path == dbus::ObjectPath(kPhonePath)) {
472 // Request confirmation of a Passkey.
473 agent_service_provider->RequestConfirmation(
474 object_path, 123456,
475 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback,
476 base::Unretained(this),
477 object_path,
478 callback,
479 error_callback));
481 } else if (object_path == dbus::ObjectPath(kWeirdDevicePath)) {
482 // Request a Passkey from the user.
483 agent_service_provider->RequestPasskey(
484 object_path,
485 base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback,
486 base::Unretained(this),
487 object_path,
488 callback,
489 error_callback));
491 } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) {
492 // Fails the pairing with an org.bluez.Error.Failed error.
493 MessageLoop::current()->PostDelayedTask(
494 FROM_HERE,
495 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing,
496 base::Unretained(this),
497 object_path, error_callback),
498 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
500 } else {
501 error_callback.Run(kNoResponseError, "No pairing fake");
505 void FakeBluetoothDeviceClient::CancelPairing(
506 const dbus::ObjectPath& object_path,
507 const base::Closure& callback,
508 const ErrorCallback& error_callback) {
509 VLOG(1) << "CancelPairing: " << object_path.value();
510 pairing_cancelled_ = true;
511 callback.Run();
515 void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
516 const dbus::ObjectPath& adapter_path) {
517 VLOG(1) << "starting discovery simulation";
519 discovery_simulation_step_ = 1;
521 MessageLoop::current()->PostDelayedTask(
522 FROM_HERE,
523 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
524 base::Unretained(this)),
525 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
528 void FakeBluetoothDeviceClient::EndDiscoverySimulation(
529 const dbus::ObjectPath& adapter_path) {
530 VLOG(1) << "stopping discovery simulation";
531 discovery_simulation_step_ = 0;
534 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
535 simulation_interval_ms_ = interval_ms;
538 void FakeBluetoothDeviceClient::RemoveDevice(
539 const dbus::ObjectPath& adapter_path,
540 const dbus::ObjectPath& device_path) {
541 std::vector<dbus::ObjectPath>::iterator listiter =
542 std::find(device_list_.begin(), device_list_.end(), device_path);
543 if (listiter == device_list_.end())
544 return;
546 PropertiesMap::iterator iter = properties_map_.find(device_path);
547 Properties* properties = iter->second;
549 VLOG(1) << "removing device: " << properties->alias.value();
550 device_list_.erase(listiter);
552 // Remove the Input interface if it exists. This should be called before the
553 // ExperimentalBluetoothDeviceClient::Observer::DeviceRemoved because it
554 // deletes the BluetoothDeviceExperimentalChromeOS object, including the
555 // device_path referenced here.
556 FakeBluetoothInputClient* fake_bluetooth_input_client =
557 static_cast<FakeBluetoothInputClient*>(
558 DBusThreadManager::Get()->GetExperimentalBluetoothInputClient());
559 fake_bluetooth_input_client->RemoveInputDevice(device_path);
561 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
562 DeviceRemoved(device_path));
564 delete properties;
565 properties_map_.erase(iter);
568 void FakeBluetoothDeviceClient::OnPropertyChanged(
569 const dbus::ObjectPath& object_path,
570 const std::string& property_name) {
571 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
572 DevicePropertyChanged(object_path, property_name));
575 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
576 if (!discovery_simulation_step_)
577 return;
579 // Timer fires every .75s, the numbers below are arbitrary to give a feel
580 // for a discovery process.
581 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_;
582 if (discovery_simulation_step_ == 2) {
583 if (std::find(device_list_.begin(), device_list_.end(),
584 dbus::ObjectPath(kAppleMousePath)) == device_list_.end()) {
585 Properties* properties = new Properties(base::Bind(
586 &FakeBluetoothDeviceClient::OnPropertyChanged,
587 base::Unretained(this),
588 dbus::ObjectPath(kAppleMousePath)));
589 properties->address.ReplaceValue(kAppleMouseAddress);
590 properties->bluetooth_class.ReplaceValue(kAppleMouseClass);
591 properties->name.ReplaceValue("Fake Apple Magic Mouse");
592 properties->alias.ReplaceValue(kAppleMouseName);
593 properties->adapter.ReplaceValue(
594 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
596 std::vector<std::string> uuids;
597 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
598 properties->uuids.ReplaceValue(uuids);
600 properties_map_[dbus::ObjectPath(kAppleMousePath)] = properties;
601 device_list_.push_back(dbus::ObjectPath(kAppleMousePath));
602 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
603 DeviceAdded(dbus::ObjectPath(kAppleMousePath)));
606 } else if (discovery_simulation_step_ == 4) {
607 if (std::find(device_list_.begin(), device_list_.end(),
608 dbus::ObjectPath(kAppleKeyboardPath)) == device_list_.end()) {
609 Properties *properties = new Properties(base::Bind(
610 &FakeBluetoothDeviceClient::OnPropertyChanged,
611 base::Unretained(this),
612 dbus::ObjectPath(kAppleKeyboardPath)));
613 properties->address.ReplaceValue(kAppleKeyboardAddress);
614 properties->bluetooth_class.ReplaceValue(kAppleKeyboardClass);
615 properties->name.ReplaceValue("Fake Apple Wireless Keyboard");
616 properties->alias.ReplaceValue(kAppleKeyboardName);
617 properties->adapter.ReplaceValue(
618 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
620 std::vector<std::string> uuids;
621 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
622 properties->uuids.ReplaceValue(uuids);
624 properties_map_[dbus::ObjectPath(kAppleKeyboardPath)] = properties;
625 device_list_.push_back(dbus::ObjectPath(kAppleKeyboardPath));
626 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
627 DeviceAdded(dbus::ObjectPath(kAppleKeyboardPath)));
630 if (std::find(device_list_.begin(), device_list_.end(),
631 dbus::ObjectPath(kVanishingDevicePath)) ==
632 device_list_.end()) {
633 Properties* properties = new Properties(base::Bind(
634 &FakeBluetoothDeviceClient::OnPropertyChanged,
635 base::Unretained(this),
636 dbus::ObjectPath(kVanishingDevicePath)));
637 properties->address.ReplaceValue(kVanishingDeviceAddress);
638 properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass);
639 properties->name.ReplaceValue("Fake Vanishing Device");
640 properties->alias.ReplaceValue(kVanishingDeviceName);
641 properties->adapter.ReplaceValue(
642 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
644 properties_map_[dbus::ObjectPath(kVanishingDevicePath)] = properties;
645 device_list_.push_back(dbus::ObjectPath(kVanishingDevicePath));
646 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
647 DeviceAdded(dbus::ObjectPath(kVanishingDevicePath)));
650 } else if (discovery_simulation_step_ == 7) {
651 if (std::find(device_list_.begin(), device_list_.end(),
652 dbus::ObjectPath(kMicrosoftMousePath)) ==
653 device_list_.end()) {
654 Properties* properties = new Properties(base::Bind(
655 &FakeBluetoothDeviceClient::OnPropertyChanged,
656 base::Unretained(this),
657 dbus::ObjectPath(kMicrosoftMousePath)));
658 properties->address.ReplaceValue(kMicrosoftMouseAddress);
659 properties->bluetooth_class.ReplaceValue(kMicrosoftMouseClass);
660 properties->name.ReplaceValue("Fake Microsoft Mouse");
661 properties->alias.ReplaceValue(kMicrosoftMouseName);
662 properties->adapter.ReplaceValue(
663 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
665 std::vector<std::string> uuids;
666 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
667 properties->uuids.ReplaceValue(uuids);
669 properties_map_[dbus::ObjectPath(kMicrosoftMousePath)] = properties;
670 device_list_.push_back(dbus::ObjectPath(kMicrosoftMousePath));
671 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
672 DeviceAdded(dbus::ObjectPath(kMicrosoftMousePath)));
675 } else if (discovery_simulation_step_ == 8) {
676 if (std::find(device_list_.begin(), device_list_.end(),
677 dbus::ObjectPath(kMotorolaKeyboardPath)) ==
678 device_list_.end()) {
679 Properties* properties = new Properties(base::Bind(
680 &FakeBluetoothDeviceClient::OnPropertyChanged,
681 base::Unretained(this),
682 dbus::ObjectPath(kMotorolaKeyboardPath)));
683 properties->address.ReplaceValue(kMotorolaKeyboardAddress);
684 properties->bluetooth_class.ReplaceValue(kMotorolaKeyboardClass);
685 properties->name.ReplaceValue("Fake Motorola Keyboard");
686 properties->alias.ReplaceValue(kMotorolaKeyboardName);
687 properties->adapter.ReplaceValue(
688 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
690 std::vector<std::string> uuids;
691 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
692 properties->uuids.ReplaceValue(uuids);
694 properties_map_[dbus::ObjectPath(kMotorolaKeyboardPath)] = properties;
695 device_list_.push_back(dbus::ObjectPath(kMotorolaKeyboardPath));
696 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
697 DeviceAdded(dbus::ObjectPath(kMotorolaKeyboardPath)));
700 if (std::find(device_list_.begin(), device_list_.end(),
701 dbus::ObjectPath(kSonyHeadphonesPath)) ==
702 device_list_.end()) {
703 Properties* properties = new Properties(base::Bind(
704 &FakeBluetoothDeviceClient::OnPropertyChanged,
705 base::Unretained(this),
706 dbus::ObjectPath(kSonyHeadphonesPath)));
707 properties->address.ReplaceValue(kSonyHeadphonesAddress);
708 properties->bluetooth_class.ReplaceValue(kSonyHeadphonesClass);
709 properties->name.ReplaceValue("Fake Sony Headphones");
710 properties->alias.ReplaceValue(kSonyHeadphonesName);
711 properties->adapter.ReplaceValue(
712 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
714 properties_map_[dbus::ObjectPath(kSonyHeadphonesPath)] = properties;
715 device_list_.push_back(dbus::ObjectPath(kSonyHeadphonesPath));
716 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
717 DeviceAdded(dbus::ObjectPath(kSonyHeadphonesPath)));
720 } else if (discovery_simulation_step_ == 10) {
721 if (std::find(device_list_.begin(), device_list_.end(),
722 dbus::ObjectPath(kPhonePath)) == device_list_.end()) {
723 Properties* properties = new Properties(base::Bind(
724 &FakeBluetoothDeviceClient::OnPropertyChanged,
725 base::Unretained(this),
726 dbus::ObjectPath(kPhonePath)));
727 properties->address.ReplaceValue(kPhoneAddress);
728 properties->bluetooth_class.ReplaceValue(kPhoneClass);
729 properties->name.ReplaceValue("Fake Phone");
730 properties->alias.ReplaceValue(kPhoneName);
731 properties->adapter.ReplaceValue(
732 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
734 properties_map_[dbus::ObjectPath(kPhonePath)] = properties;
735 device_list_.push_back(dbus::ObjectPath(kPhonePath));
736 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
737 DeviceAdded(dbus::ObjectPath(kPhonePath)));
740 if (std::find(device_list_.begin(), device_list_.end(),
741 dbus::ObjectPath(kWeirdDevicePath)) == device_list_.end()) {
742 Properties* properties = new Properties(base::Bind(
743 &FakeBluetoothDeviceClient::OnPropertyChanged,
744 base::Unretained(this),
745 dbus::ObjectPath(kWeirdDevicePath)));
746 properties->address.ReplaceValue(kWeirdDeviceAddress);
747 properties->bluetooth_class.ReplaceValue(kWeirdDeviceClass);
748 properties->name.ReplaceValue("Fake Weird Device");
749 properties->alias.ReplaceValue(kWeirdDeviceName);
750 properties->adapter.ReplaceValue(
751 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
753 properties_map_[dbus::ObjectPath(kWeirdDevicePath)] = properties;
754 device_list_.push_back(dbus::ObjectPath(kWeirdDevicePath));
755 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer, observers_,
756 DeviceAdded(dbus::ObjectPath(kWeirdDevicePath)));
759 if (std::find(device_list_.begin(), device_list_.end(),
760 dbus::ObjectPath(kUnconnectableDevicePath)) ==
761 device_list_.end()) {
762 Properties* properties = new Properties(base::Bind(
763 &FakeBluetoothDeviceClient::OnPropertyChanged,
764 base::Unretained(this),
765 dbus::ObjectPath(kUnconnectableDevicePath)));
766 properties->address.ReplaceValue(kUnconnectableDeviceAddress);
767 properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass);
768 properties->name.ReplaceValue("Fake Unconnectable Device");
769 properties->alias.ReplaceValue(kUnconnectableDeviceName);
770 properties->adapter.ReplaceValue(
771 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
773 properties_map_[dbus::ObjectPath(kUnconnectableDevicePath)] = properties;
774 device_list_.push_back(dbus::ObjectPath(kUnconnectableDevicePath));
775 FOR_EACH_OBSERVER(
776 ExperimentalBluetoothDeviceClient::Observer, observers_,
777 DeviceAdded(dbus::ObjectPath(kUnconnectableDevicePath)));
780 if (std::find(device_list_.begin(), device_list_.end(),
781 dbus::ObjectPath(kUnpairableDevicePath)) ==
782 device_list_.end()) {
783 Properties* properties = new Properties(base::Bind(
784 &FakeBluetoothDeviceClient::OnPropertyChanged,
785 base::Unretained(this),
786 dbus::ObjectPath(kUnpairableDevicePath)));
787 properties->address.ReplaceValue(kUnpairableDeviceAddress);
788 properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass);
789 properties->name.ReplaceValue("Fake Unpairable Device");
790 properties->alias.ReplaceValue(kUnpairableDeviceName);
791 properties->adapter.ReplaceValue(
792 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
794 properties_map_[dbus::ObjectPath(kUnpairableDevicePath)] = properties;
795 device_list_.push_back(dbus::ObjectPath(kUnpairableDevicePath));
796 FOR_EACH_OBSERVER(
797 ExperimentalBluetoothDeviceClient::Observer, observers_,
798 DeviceAdded(dbus::ObjectPath(kUnpairableDevicePath)));
801 } else if (discovery_simulation_step_ == 13) {
802 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
803 dbus::ObjectPath(kVanishingDevicePath));
805 } else if (discovery_simulation_step_ == 14) {
806 return;
810 ++discovery_simulation_step_;
811 MessageLoop::current()->PostDelayedTask(
812 FROM_HERE,
813 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
814 base::Unretained(this)),
815 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
819 void FakeBluetoothDeviceClient::CompleteSimulatedPairing(
820 const dbus::ObjectPath& object_path,
821 const base::Closure& callback,
822 const ErrorCallback& error_callback) {
823 VLOG(1) << "CompleteSimulatedPairing: " << object_path.value();
824 if (pairing_cancelled_) {
825 pairing_cancelled_ = false;
827 error_callback.Run(bluetooth_adapter::kErrorAuthenticationCanceled,
828 "Cancaled");
829 } else {
830 Properties* properties = GetProperties(object_path);
832 properties->paired.ReplaceValue(true);
833 callback.Run();
835 AddInputDeviceIfNeeded(object_path, properties);
839 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing(
840 const dbus::ObjectPath& object_path,
841 const ErrorCallback& error_callback) {
842 VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value();
844 error_callback.Run(bluetooth_adapter::kErrorAuthenticationTimeout,
845 "Timed out");
848 void FakeBluetoothDeviceClient::CancelSimulatedPairing(
849 const dbus::ObjectPath& object_path,
850 const ErrorCallback& error_callback) {
851 VLOG(1) << "CancelSimulatedPairing: " << object_path.value();
853 error_callback.Run(bluetooth_adapter::kErrorAuthenticationCanceled,
854 "Canceled");
857 void FakeBluetoothDeviceClient::RejectSimulatedPairing(
858 const dbus::ObjectPath& object_path,
859 const ErrorCallback& error_callback) {
860 VLOG(1) << "RejectSimulatedPairing: " << object_path.value();
862 error_callback.Run(bluetooth_adapter::kErrorAuthenticationRejected,
863 "Rejected");
866 void FakeBluetoothDeviceClient::FailSimulatedPairing(
867 const dbus::ObjectPath& object_path,
868 const ErrorCallback& error_callback) {
869 VLOG(1) << "FailSimulatedPairing: " << object_path.value();
871 error_callback.Run(bluetooth_adapter::kErrorFailed, "Failed");
874 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded(
875 const dbus::ObjectPath& object_path,
876 Properties* properties) {
877 // If the paired device is a HID device based on it's bluetooth class,
878 // simulate the Input interface.
879 FakeBluetoothInputClient* fake_bluetooth_input_client =
880 static_cast<FakeBluetoothInputClient*>(
881 DBusThreadManager::Get()->GetExperimentalBluetoothInputClient());
883 if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500)
884 fake_bluetooth_input_client->AddInputDevice(object_path);
887 void FakeBluetoothDeviceClient::PinCodeCallback(
888 const dbus::ObjectPath& object_path,
889 const base::Closure& callback,
890 const ErrorCallback& error_callback,
891 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status,
892 const std::string& pincode) {
893 VLOG(1) << "PinCodeCallback: " << object_path.value();
895 if (status == ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS) {
896 MessageLoop::current()->PostDelayedTask(
897 FROM_HERE,
898 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
899 base::Unretained(this),
900 object_path, callback, error_callback),
901 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
903 } else if (status ==
904 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED) {
905 MessageLoop::current()->PostDelayedTask(
906 FROM_HERE,
907 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
908 base::Unretained(this),
909 object_path, error_callback),
910 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
912 } else if (status ==
913 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED) {
914 MessageLoop::current()->PostDelayedTask(
915 FROM_HERE,
916 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
917 base::Unretained(this),
918 object_path, error_callback),
919 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
924 void FakeBluetoothDeviceClient::PasskeyCallback(
925 const dbus::ObjectPath& object_path,
926 const base::Closure& callback,
927 const ErrorCallback& error_callback,
928 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status,
929 uint32 passkey) {
930 VLOG(1) << "PasskeyCallback: " << object_path.value();
932 if (status == ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS) {
933 MessageLoop::current()->PostDelayedTask(
934 FROM_HERE,
935 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
936 base::Unretained(this),
937 object_path, callback, error_callback),
938 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
940 } else if (status ==
941 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED) {
942 MessageLoop::current()->PostDelayedTask(
943 FROM_HERE,
944 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
945 base::Unretained(this),
946 object_path, error_callback),
947 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
949 } else if (status ==
950 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED) {
951 MessageLoop::current()->PostDelayedTask(
952 FROM_HERE,
953 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
954 base::Unretained(this),
955 object_path, error_callback),
956 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
961 void FakeBluetoothDeviceClient::ConfirmationCallback(
962 const dbus::ObjectPath& object_path,
963 const base::Closure& callback,
964 const ErrorCallback& error_callback,
965 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status) {
966 VLOG(1) << "ConfirmationCallback: " << object_path.value();
968 if (status == ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS) {
969 MessageLoop::current()->PostDelayedTask(
970 FROM_HERE,
971 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
972 base::Unretained(this),
973 object_path, callback, error_callback),
974 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
976 } else if (status ==
977 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED) {
978 MessageLoop::current()->PostDelayedTask(
979 FROM_HERE,
980 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
981 base::Unretained(this),
982 object_path, error_callback),
983 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
985 } else if (status ==
986 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED) {
987 MessageLoop::current()->PostDelayedTask(
988 FROM_HERE,
989 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
990 base::Unretained(this),
991 object_path, error_callback),
992 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
997 void FakeBluetoothDeviceClient::SimulateKeypress(
998 uint16 entered,
999 const dbus::ObjectPath& object_path,
1000 const base::Closure& callback,
1001 const ErrorCallback& error_callback) {
1002 VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value();
1004 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
1005 static_cast<FakeBluetoothAgentManagerClient*>(
1006 DBusThreadManager::Get()->
1007 GetExperimentalBluetoothAgentManagerClient());
1008 FakeBluetoothAgentServiceProvider* agent_service_provider =
1009 fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
1010 agent_service_provider->DisplayPasskey(object_path, 123456, entered);
1012 if (entered < 7) {
1013 MessageLoop::current()->PostDelayedTask(
1014 FROM_HERE,
1015 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
1016 base::Unretained(this),
1017 entered + 1, object_path, callback, error_callback),
1018 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
1020 } else {
1021 MessageLoop::current()->PostDelayedTask(
1022 FROM_HERE,
1023 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
1024 base::Unretained(this),
1025 object_path, callback, error_callback),
1026 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
1031 void FakeBluetoothDeviceClient::ConnectionCallback(
1032 const dbus::ObjectPath& object_path,
1033 const base::Closure& callback,
1034 const ErrorCallback& error_callback,
1035 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) {
1036 VLOG(1) << "ConnectionCallback: " << object_path.value();
1038 if (status ==
1039 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) {
1040 callback.Run();
1041 } else if (status ==
1042 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) {
1043 // TODO(keybuk): tear down this side of the connection
1044 error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled");
1045 } else if (status ==
1046 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) {
1047 // TODO(keybuk): tear down this side of the connection
1048 error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected");
1052 void FakeBluetoothDeviceClient::DisconnectionCallback(
1053 const dbus::ObjectPath& object_path,
1054 const base::Closure& callback,
1055 const ErrorCallback& error_callback,
1056 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) {
1057 VLOG(1) << "DisconnectionCallback: " << object_path.value();
1059 if (status ==
1060 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) {
1061 // TODO(keybuk): tear down this side of the connection
1062 callback.Run();
1063 } else if (status ==
1064 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) {
1065 error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled");
1066 } else if (status ==
1067 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) {
1068 error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected");
1072 } // namespace chromeos