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