Home | History | Annotate | Download | only in dbus
      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