Merge from Chromium at DEPS revision r190564

This commit was generated by merge_to_master.py.

Change-Id: Icadecbce29854b8fa25fd335b2c1949b5ca5d170
diff --git a/device/bluetooth/DEPS b/device/bluetooth/DEPS
index 730c30e..7f93e42 100644
--- a/device/bluetooth/DEPS
+++ b/device/bluetooth/DEPS
@@ -1,10 +1,8 @@
 include_rules = [
-  "+chrome/common",
-  "+chrome/test/base",
-  "+content/public/test",
   "+chromeos/dbus",
   "+dbus",
   "+grit",
+  "+net/base",
   "+ui/base/l10n",
   "+third_party/cros_system_api/dbus",
   "+third_party/libxml/chromium",
diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc
index b36cd0b..b64c143 100644
--- a/device/bluetooth/bluetooth_adapter.cc
+++ b/device/bluetooth/bluetooth_adapter.cc
@@ -4,11 +4,16 @@
 
 #include "device/bluetooth/bluetooth_adapter.h"
 
+#include "base/stl_util.h"
 #include "device/bluetooth/bluetooth_device.h"
 
 namespace device {
 
+BluetoothAdapter::BluetoothAdapter() {
+}
+
 BluetoothAdapter::~BluetoothAdapter() {
+  STLDeleteValues(&devices_);
 }
 
 const std::string& BluetoothAdapter::address() const {
@@ -31,4 +36,28 @@
   return devices;
 }
 
+BluetoothAdapter::ConstDeviceList BluetoothAdapter::GetDevices() const {
+  ConstDeviceList devices;
+  for (DevicesMap::const_iterator iter = devices_.begin();
+       iter != devices_.end();
+       ++iter)
+    devices.push_back(iter->second);
+
+  return devices;
+}
+
+BluetoothDevice* BluetoothAdapter::GetDevice(const std::string& address) {
+  return const_cast<BluetoothDevice *>(
+      const_cast<const BluetoothAdapter *>(this)->GetDevice(address));
+}
+
+const BluetoothDevice* BluetoothAdapter::GetDevice(
+    const std::string& address) const {
+  DevicesMap::const_iterator iter = devices_.find(address);
+  if (iter != devices_.end())
+    return iter->second;
+
+  return NULL;
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index 86de361..75c0606 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -5,6 +5,7 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_H_
 
+#include <map>
 #include <string>
 #include <vector>
 
@@ -44,12 +45,18 @@
 
     // Called when the discovering state of the adapter |adapter| changes,
     // when |discovering| is true the adapter is seeking new devices, false
-    // means it is not. Note that device discovery involves both states when
-    // the adapter is seeking new devices and states when it is not because
-    // it is interrogating the devices it found.
+    // means it is not.
     virtual void AdapterDiscoveringChanged(BluetoothAdapter* adapter,
                                            bool discovering) {}
 
+    // Called when the scanning discovery state of the adapter |adapter|
+    // changes during discovery. When |scanning| is true the adapter is
+    // actively scanning for new devices and when false it is contacting
+    // the devices found to update information; the adapter will repeatedly
+    // cycle between both states during discovery.
+    virtual void AdapterScanningChanged(BluetoothAdapter* adapter,
+                                        bool scanning) {}
+
     // Called when a new device |device| is added to the adapter |adapter|,
     // either because it has been discovered or a connection made. |device|
     // should not be cached, instead copy its address.
@@ -92,6 +99,9 @@
   // The name of the adapter.
   virtual const std::string& name() const;
 
+  // Indicates whether the adapter is initialized and ready to use.
+  virtual bool IsInitialized() const = 0;
+
   // Indicates whether the adapter is actually present on the system, for
   // the default adapter this indicates whether any adapter is present. An
   // adapter is only considered present if the address has been obtained.
@@ -107,18 +117,34 @@
                           const base::Closure& callback,
                           const ErrorCallback& error_callback) = 0;
 
-  // Indicates whether the adapter is currently discovering new devices,
-  // note that a typical discovery process has phases of this being true
-  // followed by phases of being false when the adapter interrogates the
-  // devices found.
+  // Indicates whether the adapter is currently discovering new devices.
   virtual bool IsDiscovering() const = 0;
 
-  // Requests that the adapter either begin discovering new devices when
-  // |discovering| is true, or cease any discovery when false.  On success,
-  // callback will be called.  On failure, |error_callback| will be called.
-  virtual void SetDiscovering(bool discovering,
-                              const base::Closure& callback,
-                              const ErrorCallback& error_callback) = 0;
+  // Indicates whether the adapter is currently scanning for new devices
+  // during discovery; when false the adapter is contacting the devices found
+  // to obtain information.
+  virtual bool IsScanning() const = 0;
+
+  // Requests that the adapter begin discovering new devices, code must
+  // always call this method if they require the adapter be in discovery
+  // and should not make it conditional on the value of IsDiscovering()
+  // as other adapter users may be making the same request. Code must also
+  // call StopDiscovering() when done. On success |callback| will be called,
+  // on failure |error_callback| will be called instead.
+  //
+  // Since discovery may already be in progress when this method is called,
+  // callers should retrieve the current set of discovered devices by calling
+  // GetDevices() and checking for those with IsVisible() as true.
+  virtual void StartDiscovering(const base::Closure& callback,
+                                const ErrorCallback& error_callback) = 0;
+
+  // Requests that an earlier call to StartDiscovering() be cancelled; the
+  // adapter may not actually cease discovering devices if other callers
+  // have called StartDiscovering() and not yet called this method. On
+  // success |callback| will be called, on failure |error_callback| will be
+  // called instead.
+  virtual void StopDiscovering(const base::Closure& callback,
+                               const ErrorCallback& error_callback) = 0;
 
   // Requests the list of devices from the adapter, all are returned
   // including those currently connected and those paired. Use the
@@ -126,13 +152,13 @@
   typedef std::vector<BluetoothDevice*> DeviceList;
   virtual DeviceList GetDevices();
   typedef std::vector<const BluetoothDevice*> ConstDeviceList;
-  virtual ConstDeviceList GetDevices() const = 0;
+  virtual ConstDeviceList GetDevices() const;
 
   // Returns a pointer to the device with the given address |address| or
   // NULL if no such device is known.
-  virtual BluetoothDevice* GetDevice(const std::string& address) = 0;
+  virtual BluetoothDevice* GetDevice(const std::string& address);
   virtual const BluetoothDevice* GetDevice(
-      const std::string& address) const = 0;
+      const std::string& address) const;
 
   // Requests the local Out Of Band pairing data.
   virtual void ReadLocalOutOfBandPairingData(
@@ -141,6 +167,7 @@
 
  protected:
   friend class base::RefCounted<BluetoothAdapter>;
+  BluetoothAdapter();
   virtual ~BluetoothAdapter();
 
   // Address of the adapter.
@@ -148,6 +175,13 @@
 
   // Name of the adapter.
   std::string name_;
+
+  // Devices paired with, connected to, discovered by, or visible to the
+  // adapter. The key is the Bluetooth address of the device and the value
+  // is the BluetoothDevice object whose lifetime is managed by the
+  // adapter instance.
+  typedef std::map<const std::string, BluetoothDevice*> DevicesMap;
+  DevicesMap devices_;
 };
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.cc b/device/bluetooth/bluetooth_adapter_chromeos.cc
index 36699e5..d92a021 100644
--- a/device/bluetooth/bluetooth_adapter_chromeos.cc
+++ b/device/bluetooth/bluetooth_adapter_chromeos.cc
@@ -25,9 +25,11 @@
 
 namespace chromeos {
 
-BluetoothAdapterChromeOs::BluetoothAdapterChromeOs() : track_default_(false),
+BluetoothAdapterChromeOS::BluetoothAdapterChromeOS() : BluetoothAdapter(),
+                                                       track_default_(false),
                                                        powered_(false),
-                                                       discovering_(false),
+                                                       scanning_(false),
+                                                       discovering_count_(0),
                                                        weak_ptr_factory_(this) {
   DBusThreadManager::Get()->GetBluetoothManagerClient()->
       AddObserver(this);
@@ -37,128 +39,107 @@
       AddObserver(this);
 }
 
-BluetoothAdapterChromeOs::~BluetoothAdapterChromeOs() {
+BluetoothAdapterChromeOS::~BluetoothAdapterChromeOS() {
   DBusThreadManager::Get()->GetBluetoothDeviceClient()->
       RemoveObserver(this);
   DBusThreadManager::Get()->GetBluetoothAdapterClient()->
       RemoveObserver(this);
   DBusThreadManager::Get()->GetBluetoothManagerClient()->
       RemoveObserver(this);
-
-  STLDeleteValues(&devices_);
 }
 
-void BluetoothAdapterChromeOs::AddObserver(
+void BluetoothAdapterChromeOS::AddObserver(
     BluetoothAdapter::Observer* observer) {
   DCHECK(observer);
   observers_.AddObserver(observer);
 }
 
-void BluetoothAdapterChromeOs::RemoveObserver(
+void BluetoothAdapterChromeOS::RemoveObserver(
     BluetoothAdapter::Observer* observer) {
   DCHECK(observer);
   observers_.RemoveObserver(observer);
 }
 
-bool BluetoothAdapterChromeOs::IsPresent() const {
+// TODO(youngki) Return true when object path and properties of the adapter are
+// initialized.
+bool BluetoothAdapterChromeOS::IsInitialized() const {
+  return true;
+}
+
+bool BluetoothAdapterChromeOS::IsPresent() const {
   return !object_path_.value().empty() && !address_.empty();
 }
 
-bool BluetoothAdapterChromeOs::IsPowered() const {
+bool BluetoothAdapterChromeOS::IsPowered() const {
   return powered_;
 }
 
-void BluetoothAdapterChromeOs::SetPowered(bool powered,
+void BluetoothAdapterChromeOS::SetPowered(bool powered,
                                           const base::Closure& callback,
                                           const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothAdapterClient()->
       GetProperties(object_path_)->powered.Set(
           powered,
-          base::Bind(&BluetoothAdapterChromeOs::OnSetPowered,
+          base::Bind(&BluetoothAdapterChromeOS::OnSetPowered,
                      weak_ptr_factory_.GetWeakPtr(),
                      callback,
                      error_callback));
 }
 
-bool BluetoothAdapterChromeOs::IsDiscovering() const {
-  return discovering_;
+bool BluetoothAdapterChromeOS::IsDiscovering() const {
+  return discovering_count_ > 0;
 }
 
-void BluetoothAdapterChromeOs::SetDiscovering(
-    bool discovering,
+bool BluetoothAdapterChromeOS::IsScanning() const {
+  return scanning_;
+}
+
+void BluetoothAdapterChromeOS::StartDiscovering(
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  if (discovering) {
-    DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-        StartDiscovery(object_path_,
-                       base::Bind(&BluetoothAdapterChromeOs::OnStartDiscovery,
-                                  weak_ptr_factory_.GetWeakPtr(),
-                                  callback,
-                                  error_callback));
-  } else {
-    DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-        StopDiscovery(object_path_,
-                      base::Bind(&BluetoothAdapterChromeOs::OnStopDiscovery,
-                                 weak_ptr_factory_.GetWeakPtr(),
-                                 callback,
-                                 error_callback));
-  }
+  // BlueZ counts discovery sessions, and permits multiple sessions for a
+  // single connection, so issue a StartDiscovery() call for every use
+  // within Chromium for the right behavior.
+  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
+      StartDiscovery(object_path_,
+                     base::Bind(
+                         &BluetoothAdapterChromeOS::OnStartDiscovery,
+                         weak_ptr_factory_.GetWeakPtr(),
+                         callback, error_callback));
 }
 
-BluetoothAdapter::ConstDeviceList BluetoothAdapterChromeOs::GetDevices() const {
-  ConstDeviceList devices;
-  for (DevicesMap::const_iterator iter = devices_.begin();
-       iter != devices_.end();
-       ++iter)
-    devices.push_back(iter->second);
-
-  return devices;
+void BluetoothAdapterChromeOS::StopDiscovering(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  // Inform BlueZ to stop one of our open discovery sessions.
+  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
+      StopDiscovery(object_path_,
+                    base::Bind(
+                        &BluetoothAdapterChromeOS::OnStopDiscovery,
+                        weak_ptr_factory_.GetWeakPtr(),
+                        callback, error_callback));
 }
 
-BluetoothDevice* BluetoothAdapterChromeOs::GetDevice(
-    const std::string& address) {
-  return const_cast<BluetoothDevice *>(
-      const_cast<const BluetoothAdapterChromeOs *>(this)->GetDevice(address));
-}
-
-const BluetoothDevice* BluetoothAdapterChromeOs::GetDevice(
-    const std::string& address) const {
-  DevicesMap::const_iterator iter = devices_.find(address);
-  if (iter != devices_.end())
-    return iter->second;
-
-  return NULL;
-}
-
-void BluetoothAdapterChromeOs::ReadLocalOutOfBandPairingData(
+void BluetoothAdapterChromeOS::ReadLocalOutOfBandPairingData(
     const BluetoothAdapter::BluetoothOutOfBandPairingDataCallback& callback,
     const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
       ReadLocalData(object_path_,
-          base::Bind(&BluetoothAdapterChromeOs::OnReadLocalData,
+          base::Bind(&BluetoothAdapterChromeOS::OnReadLocalData,
               weak_ptr_factory_.GetWeakPtr(),
               callback,
               error_callback));
 }
 
-void BluetoothAdapterChromeOs::TrackDefaultAdapter() {
-  DVLOG(1) << "Tracking default adapter";
+void BluetoothAdapterChromeOS::TrackDefaultAdapter() {
+  VLOG(1) << "Tracking default adapter";
   track_default_ = true;
   DBusThreadManager::Get()->GetBluetoothManagerClient()->
-      DefaultAdapter(base::Bind(&BluetoothAdapterChromeOs::AdapterCallback,
+      DefaultAdapter(base::Bind(&BluetoothAdapterChromeOS::AdapterCallback,
                                 weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BluetoothAdapterChromeOs::FindAdapter(const std::string& address) {
-  DVLOG(1) << "Using adapter " << address;
-  track_default_ = false;
-  DBusThreadManager::Get()->GetBluetoothManagerClient()->
-      FindAdapter(address,
-                  base::Bind(&BluetoothAdapterChromeOs::AdapterCallback,
-                             weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BluetoothAdapterChromeOs::AdapterCallback(
+void BluetoothAdapterChromeOS::AdapterCallback(
     const dbus::ObjectPath& adapter_path,
     bool success) {
   if (success) {
@@ -168,29 +149,29 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DefaultAdapterChanged(
+void BluetoothAdapterChromeOS::DefaultAdapterChanged(
     const dbus::ObjectPath& adapter_path) {
   if (track_default_)
     ChangeAdapter(adapter_path);
 }
 
-void BluetoothAdapterChromeOs::AdapterRemoved(
+void BluetoothAdapterChromeOS::AdapterRemoved(
     const dbus::ObjectPath& adapter_path) {
   if (adapter_path == object_path_)
     RemoveAdapter();
 }
 
-void BluetoothAdapterChromeOs::ChangeAdapter(
+void BluetoothAdapterChromeOS::ChangeAdapter(
     const dbus::ObjectPath& adapter_path) {
   if (object_path_.value().empty()) {
-    DVLOG(1) << "Adapter path initialized to " << adapter_path.value();
+    VLOG(1) << "Adapter path initialized to " << adapter_path.value();
   } else if (object_path_.value() != adapter_path.value()) {
-    DVLOG(1) << "Adapter path changed from " << object_path_.value()
-             << " to " << adapter_path.value();
+    VLOG(1) << "Adapter path changed from " << object_path_.value()
+            << " to " << adapter_path.value();
 
     RemoveAdapter();
   } else {
-    DVLOG(1) << "Adapter address updated";
+    VLOG(1) << "Adapter address updated";
   }
 
   object_path_ = adapter_path;
@@ -205,7 +186,7 @@
 
   // Delay announcing a new adapter until we have an address.
   if (address_.empty()) {
-    DVLOG(1) << "Adapter address not yet known";
+    VLOG(1) << "Adapter address not yet known";
     return;
   }
 
@@ -217,10 +198,10 @@
                     AdapterPresentChanged(this, true));
 }
 
-void BluetoothAdapterChromeOs::RemoveAdapter() {
+void BluetoothAdapterChromeOS::RemoveAdapter() {
   const bool adapter_was_present = IsPresent();
 
-  DVLOG(1) << "Adapter lost.";
+  VLOG(1) << "Adapter lost.";
   PoweredChanged(false);
   DiscoveringChanged(false);
   ClearDevices();
@@ -234,7 +215,7 @@
                       AdapterPresentChanged(this, false));
 }
 
-void BluetoothAdapterChromeOs::OnSetPowered(const base::Closure& callback,
+void BluetoothAdapterChromeOS::OnSetPowered(const base::Closure& callback,
                                             const ErrorCallback& error_callback,
                                             bool success) {
   if (success)
@@ -243,7 +224,7 @@
     error_callback.Run();
 }
 
-void BluetoothAdapterChromeOs::PoweredChanged(bool powered) {
+void BluetoothAdapterChromeOS::PoweredChanged(bool powered) {
   if (powered == powered_)
     return;
 
@@ -253,51 +234,67 @@
                     AdapterPoweredChanged(this, powered_));
 }
 
-void BluetoothAdapterChromeOs::OnStartDiscovery(
+void BluetoothAdapterChromeOS::OnStartDiscovery(
     const base::Closure& callback,
     const ErrorCallback& error_callback,
     const dbus::ObjectPath& adapter_path,
     bool success) {
   if (success) {
-    DVLOG(1) << object_path_.value() << ": started discovery.";
+    if (discovering_count_++ == 0) {
+      VLOG(1) << object_path_.value() << ": started discovery.";
 
-    // Clear devices found in previous discovery attempts
-    ClearDiscoveredDevices();
+      // Clear devices found in previous discovery attempts
+      ClearDiscoveredDevices();
+
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        AdapterDiscoveringChanged(this, true));
+    }
+
     callback.Run();
   } else {
-    // TODO(keybuk): in future, don't run the callback if the error was just
-    // that we were already discovering.
     error_callback.Run();
   }
 }
 
-void BluetoothAdapterChromeOs::OnStopDiscovery(
+void BluetoothAdapterChromeOS::OnStopDiscovery(
     const base::Closure& callback,
     const ErrorCallback& error_callback,
     const dbus::ObjectPath& adapter_path,
     bool success) {
   if (success) {
-    DVLOG(1) << object_path_.value() << ": stopped discovery.";
+    if (--discovering_count_ == 0) {
+      VLOG(1) << object_path_.value() << ": stopped discovery.";
+
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        AdapterDiscoveringChanged(this, false));
+    } else if (discovering_count_ < 0) {
+      LOG(WARNING) << adapter_path.value() << ": call to StopDiscovering "
+                   << "without matching StartDiscovering.";
+      error_callback.Run();
+      return;
+    }
+
     callback.Run();
+
     // Leave found devices available for perusing.
   } else {
-    // TODO(keybuk): in future, don't run the callback if the error was just
-    // that we weren't discovering.
     error_callback.Run();
   }
 }
 
-void BluetoothAdapterChromeOs::DiscoveringChanged(bool discovering) {
-  if (discovering == discovering_)
+void BluetoothAdapterChromeOS::DiscoveringChanged(bool discovering) {
+  // The BlueZ discovering property actually just indicates whether the
+  // device is in an inquiry scan, so update our scanning property.
+  if (discovering == scanning_)
     return;
 
-  discovering_ = discovering;
+  scanning_ = discovering;
 
   FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
-                    AdapterDiscoveringChanged(this, discovering_));
+                    AdapterScanningChanged(this, scanning_));
 }
 
-void BluetoothAdapterChromeOs::OnReadLocalData(
+void BluetoothAdapterChromeOS::OnReadLocalData(
     const BluetoothAdapter::BluetoothOutOfBandPairingDataCallback& callback,
     const ErrorCallback& error_callback,
     const BluetoothOutOfBandPairingData& data,
@@ -308,7 +305,7 @@
     error_callback.Run();
 }
 
-void BluetoothAdapterChromeOs::AdapterPropertyChanged(
+void BluetoothAdapterChromeOS::AdapterPropertyChanged(
     const dbus::ObjectPath& adapter_path,
     const std::string& property_name) {
   if (adapter_path != object_path_)
@@ -338,13 +335,13 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DevicePropertyChanged(
+void BluetoothAdapterChromeOS::DevicePropertyChanged(
     const dbus::ObjectPath& device_path,
     const std::string& property_name) {
   UpdateDevice(device_path);
 }
 
-void BluetoothAdapterChromeOs::UpdateDevice(
+void BluetoothAdapterChromeOS::UpdateDevice(
     const dbus::ObjectPath& device_path) {
   BluetoothDeviceClient::Properties* properties =
       DBusThreadManager::Get()->GetBluetoothDeviceClient()->
@@ -361,19 +358,19 @@
   // pairing gaining an object path in the process. In any case, we want
   // to update the existing object, not create a new one.
   DevicesMap::iterator iter = devices_.find(address);
-  BluetoothDeviceChromeOs* device;
+  BluetoothDeviceChromeOS* device;
   const bool update_device = (iter != devices_.end());
   if (update_device) {
-    device = iter->second;
+    device = static_cast<BluetoothDeviceChromeOS*>(iter->second);
   } else {
-    device = BluetoothDeviceChromeOs::Create(this);
+    device = BluetoothDeviceChromeOS::Create(this);
     devices_[address] = device;
   }
 
   const bool was_paired = device->IsPaired();
   if (!was_paired) {
-    DVLOG(1) << "Assigned object path " << device_path.value() << " to device "
-             << address;
+    VLOG(1) << "Assigned object path " << device_path.value() << " to device "
+            << address;
     device->SetObjectPath(device_path);
   }
   device->Update(properties, true);
@@ -387,12 +384,12 @@
   }
 }
 
-void BluetoothAdapterChromeOs::ClearDevices() {
+void BluetoothAdapterChromeOS::ClearDevices() {
   DevicesMap replace;
   devices_.swap(replace);
   for (DevicesMap::iterator iter = replace.begin();
        iter != replace.end(); ++iter) {
-    BluetoothDeviceChromeOs* device = iter->second;
+    BluetoothDevice* device = iter->second;
     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                       DeviceRemoved(this, device));
 
@@ -400,7 +397,7 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DeviceCreated(
+void BluetoothAdapterChromeOS::DeviceCreated(
     const dbus::ObjectPath& adapter_path,
     const dbus::ObjectPath& device_path) {
   if (adapter_path != object_path_)
@@ -409,7 +406,7 @@
   UpdateDevice(device_path);
 }
 
-void BluetoothAdapterChromeOs::DeviceRemoved(
+void BluetoothAdapterChromeOS::DeviceRemoved(
     const dbus::ObjectPath& adapter_path,
     const dbus::ObjectPath& device_path) {
   if (adapter_path != object_path_)
@@ -417,7 +414,8 @@
 
   DevicesMap::iterator iter = devices_.begin();
   while (iter != devices_.end()) {
-    BluetoothDeviceChromeOs* device = iter->second;
+    BluetoothDeviceChromeOS* device =
+        static_cast<BluetoothDeviceChromeOS*>(iter->second);
     DevicesMap::iterator temp = iter;
     ++iter;
 
@@ -431,12 +429,12 @@
       FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                         DeviceRemoved(this, device));
 
-      DVLOG(1) << "Removed device " << device->address();
+      VLOG(1) << "Removed device " << device->address();
 
       delete device;
       devices_.erase(temp);
     } else {
-      DVLOG(1) << "Removed object path from device " << device->address();
+      VLOG(1) << "Removed object path from device " << device->address();
       device->RemoveObjectPath();
 
       FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
@@ -445,17 +443,17 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DevicesChanged(
+void BluetoothAdapterChromeOS::DevicesChanged(
     const std::vector<dbus::ObjectPath>& devices) {
   for (std::vector<dbus::ObjectPath>::const_iterator iter =
            devices.begin(); iter != devices.end(); ++iter)
     UpdateDevice(*iter);
 }
 
-void BluetoothAdapterChromeOs::ClearDiscoveredDevices() {
+void BluetoothAdapterChromeOS::ClearDiscoveredDevices() {
   DevicesMap::iterator iter = devices_.begin();
   while (iter != devices_.end()) {
-    BluetoothDeviceChromeOs* device = iter->second;
+    BluetoothDevice* device = iter->second;
     DevicesMap::iterator temp = iter;
     ++iter;
 
@@ -469,7 +467,7 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DeviceFound(
+void BluetoothAdapterChromeOS::DeviceFound(
     const dbus::ObjectPath& adapter_path,
     const std::string& address,
     const BluetoothDeviceClient::Properties& properties) {
@@ -479,17 +477,17 @@
   // DeviceFound can also be called to indicate that a device we've
   // paired with is now visible to the adapter during discovery, in which
   // case we want to update the existing object, not create a new one.
-  BluetoothDeviceChromeOs* device;
+  BluetoothDeviceChromeOS* device;
   DevicesMap::iterator iter = devices_.find(address);
   const bool update_device = (iter != devices_.end());
   if (update_device) {
-    device = iter->second;
+    device = static_cast<BluetoothDeviceChromeOS*>(iter->second);
   } else {
-    device = BluetoothDeviceChromeOs::Create(this);
+    device = BluetoothDeviceChromeOS::Create(this);
     devices_[address] = device;
   }
 
-  DVLOG(1) << "Device " << address << " is visible to the adapter";
+  VLOG(1) << "Device " << address << " is visible to the adapter";
   device->SetVisible(true);
   device->Update(&properties, false);
 
@@ -502,7 +500,7 @@
   }
 }
 
-void BluetoothAdapterChromeOs::DeviceDisappeared(
+void BluetoothAdapterChromeOS::DeviceDisappeared(
     const dbus::ObjectPath& adapter_path,
     const std::string& address) {
   if (adapter_path != object_path_)
@@ -512,7 +510,8 @@
   if (iter == devices_.end())
     return;
 
-  BluetoothDeviceChromeOs* device = iter->second;
+  BluetoothDeviceChromeOS* device =
+      static_cast<BluetoothDeviceChromeOS*>(iter->second);
 
   // DeviceDisappeared can also be called to indicate that a device we've
   // paired with is no longer visible to the adapter, so don't remove
@@ -521,14 +520,14 @@
     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                       DeviceRemoved(this, device));
 
-    DVLOG(1) << "Discovered device " << device->address()
+    VLOG(1) << "Discovered device " << device->address()
              << " is no longer visible to the adapter";
 
     delete device;
     devices_.erase(iter);
   } else {
-    DVLOG(1) << "Paired device " << device->address()
-             << " is no longer visible to the adapter";
+    VLOG(1) << "Paired device " << device->address()
+            << " is no longer visible to the adapter";
     device->SetVisible(false);
 
     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.h b/device/bluetooth/bluetooth_adapter_chromeos.h
index 18cb7aa..093cdd0 100644
--- a/device/bluetooth/bluetooth_adapter_chromeos.h
+++ b/device/bluetooth/bluetooth_adapter_chromeos.h
@@ -5,7 +5,6 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_CHROMEOS_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_CHROMEOS_H_
 
-#include <map>
 #include <string>
 #include <vector>
 
@@ -28,11 +27,11 @@
 
 namespace chromeos {
 
-class BluetoothDeviceChromeOs;
+class BluetoothDeviceChromeOS;
 
-// The BluetoothAdapterChromeOs class is an implementation of BluetoothAdapter
+// The BluetoothAdapterChromeOS class is an implementation of BluetoothAdapter
 // for Chrome OS platform.
-class BluetoothAdapterChromeOs
+class BluetoothAdapterChromeOS
     : public device::BluetoothAdapter,
       public BluetoothManagerClient::Observer,
       public BluetoothAdapterClient::Observer,
@@ -43,6 +42,7 @@
       device::BluetoothAdapter::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(
       device::BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual bool IsInitialized() const OVERRIDE;
   virtual bool IsPresent() const OVERRIDE;
   virtual bool IsPowered() const OVERRIDE;
   virtual void SetPowered(
@@ -50,39 +50,33 @@
       const base::Closure& callback,
       const ErrorCallback& error_callback) OVERRIDE;
   virtual bool IsDiscovering() const OVERRIDE;
-  virtual void SetDiscovering(
-      bool discovering,
+  virtual bool IsScanning() const OVERRIDE;
+  virtual void StartDiscovering(
       const base::Closure& callback,
       const ErrorCallback& error_callback) OVERRIDE;
-  virtual ConstDeviceList GetDevices() const OVERRIDE;
-  virtual device::BluetoothDevice* GetDevice(
-      const std::string& address) OVERRIDE;
-  virtual const device::BluetoothDevice* GetDevice(
-      const std::string& address) const OVERRIDE;
+  virtual void StopDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
   virtual void ReadLocalOutOfBandPairingData(
       const device::BluetoothAdapter::BluetoothOutOfBandPairingDataCallback&
           callback,
       const ErrorCallback& error_callback) OVERRIDE;
 
  private:
-  friend class BluetoothDeviceChromeOs;
+  friend class BluetoothDeviceChromeOS;
   friend class device::BluetoothAdapterFactory;
   friend class device::MockBluetoothAdapter;
 
-  BluetoothAdapterChromeOs();
-  virtual ~BluetoothAdapterChromeOs();
+  BluetoothAdapterChromeOS();
+  virtual ~BluetoothAdapterChromeOS();
 
   // Obtains the default adapter object path from the Bluetooth Daemon
   // and tracks future changes to it.
   void TrackDefaultAdapter();
 
-  // Obtains the object paht for the adapter named by |address| from the
-  // Bluetooth Daemon.
-  void FindAdapter(const std::string& address);
-
-  // Called by dbus:: in response to the method call sent by both
-  // DefaultAdapter() and FindAdapter(), |object_path| will contain the
-  // dbus object path of the requested adapter when |success| is true.
+  // Called by dbus:: in response to the method call sent by DefaultAdapter().
+  // |object_path| will contain the dbus object path of the requested adapter
+  // when |success| is true.
   void AdapterCallback(const dbus::ObjectPath& adapter_path, bool success);
 
   // BluetoothManagerClient::Observer override.
@@ -118,19 +112,23 @@
   // and directly using values obtained from properties.
   void PoweredChanged(bool powered);
 
-  // Called by dbus:: in response to the method calls send by SetDiscovering().
-  // |callback| and |error_callback| are the callbacks passed to
-  // SetDiscovering().
+  // Called by BluetoothAdapterClient in response to the method call sent
+  // by StartDiscovering(), |callback| and |error_callback| are the callbacks
+  // provided to that method.
   void OnStartDiscovery(const base::Closure& callback,
                         const ErrorCallback& error_callback,
                         const dbus::ObjectPath& adapter_path,
                         bool success);
+
+  // Called by BluetoothAdapterClient in response to the method call sent
+  // by StopDiscovering(), |callback| and |error_callback| are the callbacks
+  // provided to that method.
   void OnStopDiscovery(const base::Closure& callback,
                        const ErrorCallback& error_callback,
                        const dbus::ObjectPath& adapter_path,
                        bool success);
 
-  // Updates the tracked state of the adapter's discovering state to
+  // Updates the tracked state of the adapter's scanning state to
   // |discovering| and notifies observers. Called on receipt of a property
   // changed signal, and directly using values obtained from properties.
   void DiscoveringChanged(bool discovering);
@@ -224,20 +222,17 @@
   // Tracked adapter state, cached locally so we only send change notifications
   // to observers on a genuine change.
   bool powered_;
-  bool discovering_;
+  bool scanning_;
 
-  // Devices paired with, connected to, discovered by, or visible to the
-  // adapter. The key is the Bluetooth address of the device and the value
-  // is the BluetoothDeviceChromeOs object whose lifetime is managed by the
-  // adapter instance.
-  typedef std::map<const std::string, BluetoothDeviceChromeOs*> DevicesMap;
-  DevicesMap devices_;
+  // Count of callers to StartDiscovering() and StopDiscovering(), used to
+  // provide the IsDiscovering() status.
+  int discovering_count_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<BluetoothAdapterChromeOs> weak_ptr_factory_;
+  base::WeakPtrFactory<BluetoothAdapterChromeOS> weak_ptr_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterChromeOs);
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterChromeOS);
 };
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_adapter_chromeos_experimental.cc b/device/bluetooth/bluetooth_adapter_chromeos_experimental.cc
new file mode 100644
index 0000000..c382f08
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_chromeos_experimental.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_adapter_chromeos_experimental.h"
+
+#include <string>
+
+using device::BluetoothAdapter;
+
+namespace chromeos {
+
+BluetoothAdapterChromeOSExperimental::BluetoothAdapterChromeOSExperimental()
+    : BluetoothAdapter(),
+      weak_ptr_factory_(this) {
+}
+
+BluetoothAdapterChromeOSExperimental::~BluetoothAdapterChromeOSExperimental() {
+}
+
+void BluetoothAdapterChromeOSExperimental::AddObserver(
+    BluetoothAdapter::Observer* observer) {
+}
+
+void BluetoothAdapterChromeOSExperimental::RemoveObserver(
+    BluetoothAdapter::Observer* observer) {
+}
+
+bool BluetoothAdapterChromeOSExperimental::IsInitialized() const {
+  return true;
+}
+
+bool BluetoothAdapterChromeOSExperimental::IsPresent() const {
+  return false;
+}
+
+bool BluetoothAdapterChromeOSExperimental::IsPowered() const {
+  return false;
+}
+
+void BluetoothAdapterChromeOSExperimental::SetPowered(bool powered,
+                                          const base::Closure& callback,
+                                          const ErrorCallback& error_callback) {
+  error_callback.Run();
+}
+
+bool BluetoothAdapterChromeOSExperimental::IsDiscovering() const {
+  return false;
+}
+
+bool BluetoothAdapterChromeOSExperimental::IsScanning() const {
+  return false;
+}
+
+void BluetoothAdapterChromeOSExperimental::StartDiscovering(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  error_callback.Run();
+}
+
+void BluetoothAdapterChromeOSExperimental::StopDiscovering(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  error_callback.Run();
+}
+
+void BluetoothAdapterChromeOSExperimental::ReadLocalOutOfBandPairingData(
+    const BluetoothAdapter::BluetoothOutOfBandPairingDataCallback& callback,
+    const ErrorCallback& error_callback) {
+  error_callback.Run();
+}
+
+void BluetoothAdapterChromeOSExperimental::TrackDefaultAdapter() {
+}
+
+}  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_adapter_chromeos_experimental.h b/device/bluetooth/bluetooth_adapter_chromeos_experimental.h
new file mode 100644
index 0000000..fdb0ca5
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_chromeos_experimental.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_CHROMEOS_EXPERIMENTAL_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_CHROMEOS_EXPERIMENTAL_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+
+namespace device {
+
+class BluetoothAdapterFactory;
+
+}  // namespace device
+
+namespace chromeos {
+
+// The BluetoothAdapterChromeOSExperimental class is an alternate implementation
+// of BluetoothAdapter for the Chrome OS platform using the Bluetooth Smart
+// capable backend. It will become the sole implementation for Chrome OS, and
+// be renamed to BluetoothAdapterChromeOS, once the backend is switched,
+class BluetoothAdapterChromeOSExperimental
+    : public device::BluetoothAdapter {
+ public:
+  // BluetoothAdapter override
+  virtual void AddObserver(
+      device::BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(
+      device::BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual bool IsInitialized() const OVERRIDE;
+  virtual bool IsPresent() const OVERRIDE;
+  virtual bool IsPowered() const OVERRIDE;
+  virtual void SetPowered(
+      bool powered,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual bool IsDiscovering() const OVERRIDE;
+  virtual bool IsScanning() const OVERRIDE;
+  virtual void StartDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void StopDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void ReadLocalOutOfBandPairingData(
+      const device::BluetoothAdapter::BluetoothOutOfBandPairingDataCallback&
+          callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+
+ private:
+  friend class device::BluetoothAdapterFactory;
+
+  BluetoothAdapterChromeOSExperimental();
+  virtual ~BluetoothAdapterChromeOSExperimental();
+
+  // Obtains the default adapter object path from the Bluetooth Daemon
+  // and tracks future changes to it.
+  void TrackDefaultAdapter();
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate its weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<BluetoothAdapterChromeOSExperimental> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterChromeOSExperimental);
+};
+
+}  // namespace chromeos
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_CHROMEOS_EXPERIMENTAL_H_
diff --git a/device/bluetooth/bluetooth_adapter_chromeos_unittest.cc b/device/bluetooth/bluetooth_adapter_chromeos_unittest.cc
index 890d241..517a27e 100644
--- a/device/bluetooth/bluetooth_adapter_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_chromeos_unittest.cc
@@ -22,7 +22,7 @@
 
 namespace chromeos {
 
-class BluetoothAdapterChromeOsTest : public testing::Test {
+class BluetoothAdapterChromeOSTest : public testing::Test {
  public:
   virtual void SetUp() {
     MockDBusThreadManager* mock_dbus_thread_manager = new MockDBusThreadManager;
@@ -36,31 +36,38 @@
     mock_adapter_client_ =
         mock_dbus_thread_manager->mock_bluetooth_adapter_client();
 
-    set_callback_called_ = false;
+    callback_called_ = false;
     error_callback_called_ = false;
   }
 
   virtual void TearDown() {
+    adapter_ = NULL;
     DBusThreadManager::Shutdown();
   }
 
-  void SetCallback() {
-    set_callback_called_ = true;
+  void Callback() {
+    callback_called_ = true;
   }
 
   void ErrorCallback() {
     error_callback_called_ = true;
   }
 
+  void SetAdapter(scoped_refptr<device::BluetoothAdapter> adapter) {
+    adapter_ = adapter;
+  }
+
  protected:
   MockBluetoothManagerClient* mock_manager_client_;
   MockBluetoothAdapterClient* mock_adapter_client_;
 
-  bool set_callback_called_;
+  bool callback_called_;
   bool error_callback_called_;
+
+  scoped_refptr<BluetoothAdapter> adapter_;
 };
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterNotPresent) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterNotPresent) {
   // Create the default adapter instance;
   // BluetoothManagerClient::DefaultAdapter will be called once, passing
   // a callback to obtain the adapter path.
@@ -68,25 +75,26 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
-  ASSERT_TRUE(adapter.get() != NULL);
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+  ASSERT_TRUE(adapter_ != NULL);
 
   // Call the adapter callback; make out it failed.
   // BluetoothAdapter::Observer::AdapterPresentChanged must not be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(dbus::ObjectPath(""), false);
 
   // Adapter should not be present.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterWithAddress) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterWithAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -97,8 +105,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -112,19 +121,19 @@
   // BluetoothAdapter::Observer::AdapterPresentChanged will be called to
   // indicate the adapter is now present.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should be present with the given address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterWithoutAddress) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -135,8 +144,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -149,36 +159,36 @@
   // BluetoothAdapter::Observer::AdapterPresentChanged must not be called
   // yet.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should not be present yet.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 
   // Tell the adapter the address now;
   // BluetoothAdapter::Observer::AdapterPresentChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.address.name());
 
   // Adapter should be present with the given address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterBecomesPresentWithAddress) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterBecomesPresentWithAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -189,8 +199,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback; make out it failed.
   adapter_callback.Run(dbus::ObjectPath(""), false);
@@ -206,23 +217,23 @@
 
   // BluetoothAdapter::Observer::AdapterPresentChanged must be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(adapter_path);
 
   // Adapter should be present with the new address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterReplacedWithAddress) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterReplacedWithAddress) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
   const std::string initial_adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -235,8 +246,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -262,25 +274,25 @@
   // with false to indicate the old adapter being removed and once with true
   // to announce the new adapter.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
       .Times(1);
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should be present with the new address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(new_adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(new_adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterBecomesPresentWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -292,8 +304,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback; make out it failed.
   adapter_callback.Run(dbus::ObjectPath(""), false);
@@ -308,25 +321,25 @@
 
   // BluetoothAdapter::Observer::AdapterPresentChanged must not be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(adapter_path);
 
   // Adapter should not be present yet.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 
   // Tell the adapter the address now;
   // BluetoothAdapter::Observer::AdapterPresentChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
@@ -334,11 +347,11 @@
                                adapter_properties.address.name());
 
   // Adapter should be present with the new address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterReplacedWithoutAddress) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterReplacedWithoutAddress) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
   const std::string initial_adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -351,8 +364,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -376,25 +390,25 @@
   // BluetoothAdapter::Observer::AdapterPresentChanged must be called to
   // indicate the adapter has gone away.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should be now marked not present.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 
   // Tell the adapter the address now;
   // BluetoothAdapter::Observer::AdapterPresentChanged now must be called.
   new_adapter_properties.address.ReplaceValue(new_adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
@@ -402,11 +416,11 @@
                                new_adapter_properties.address.name());
 
   // Adapter should be present with the new address.
-  EXPECT_TRUE(adapter->IsPresent());
-  EXPECT_EQ(new_adapter_address, adapter->address());
+  EXPECT_TRUE(adapter_->IsPresent());
+  EXPECT_EQ(new_adapter_address, adapter_->address());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterRemoved) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterRemoved) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -417,8 +431,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -435,22 +450,22 @@
   // BluetoothAdapter::Observer::AdapterPresentChanged will be called to
   // indicate the adapter is no longer present.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->AdapterRemoved(adapter_path);
 
   // Adapter should be no longer present.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterWithoutAddressRemoved) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterWithoutAddressRemoved) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
 
   // Create the default adapter instance;
@@ -460,8 +475,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -477,22 +493,22 @@
   // BluetoothAdapter::Observer::AdapterPresentChanged must not be called
   // since we never should have announced it in the first place.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->AdapterRemoved(adapter_path);
 
   // Adapter should be still no longer present.
-  EXPECT_FALSE(adapter->IsPresent());
+  EXPECT_FALSE(adapter_->IsPresent());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyInitiallyFalse) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -504,8 +520,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -520,10 +537,10 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyInitiallyTrue) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -535,8 +552,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -550,21 +568,21 @@
 
   // BluetoothAdapter::Observer::AdapterPoweredChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), true))
       .Times(1);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyInitiallyTrueWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -576,8 +594,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -587,42 +606,42 @@
   adapter_properties.powered.ReplaceValue(true);
 
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
       .WillRepeatedly(Return(&adapter_properties));
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should not yet have the property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 
   // Tell the adapter the address now,
   // BluetoothAdapter::Observer::AdapterPresentChanged and
   // BluetoothAdapter::Observer::AdapterPoweredChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), true))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.address.name());
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterPoweredPropertyChanged) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterPoweredPropertyChanged) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -633,8 +652,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -649,30 +669,30 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 
   // Report that the property has been changed;
   // BluetoothAdapter::Observer::AdapterPoweredChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), true))
       .Times(1);
 
   adapter_properties.powered.ReplaceValue(true);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.powered.name());
 
   // Adapter should have the new property values.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterPoweredPropertyUnchanged) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterPoweredPropertyUnchanged) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -683,8 +703,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -699,28 +720,28 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 
   // Report that the property has been changed, but don't change the value;
   // BluetoothAdapter::Observer::AdapterPoweredChanged should not be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.powered.name());
 
   // Adapter should still have the same property values.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyChangedWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -732,8 +753,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -742,12 +764,12 @@
   MockBluetoothAdapterClient::Properties adapter_properties;
 
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
       .WillRepeatedly(Return(&adapter_properties));
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(adapter_path, true);
@@ -757,28 +779,28 @@
   // the adapter so it is not present.
   adapter_properties.powered.ReplaceValue(true);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.powered.name());
 
   // Adapter should not yet have the property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 
   // Tell the adapter the address now,
   // BluetoothAdapter::Observer::AdapterPresentChanged and
   // BluetoothAdapter::Observer::AdapterPoweredChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), true))
       .Times(1);
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
@@ -786,10 +808,10 @@
                                adapter_properties.address.name());
 
   // Adapter should now have the correct property value.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyResetOnReplace) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
@@ -803,8 +825,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -829,31 +852,31 @@
 
   // BluetoothAdapter::Observer::AdapterPoweredChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
         .Times(1);
   }
 
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyResetOnReplaceWhenTrue) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
@@ -867,8 +890,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -896,37 +920,37 @@
   // to set the value to false for the previous adapter and once to set the
   // value to true for the new adapter.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
         .Times(1);
   }
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), false))
+    EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), true))
+    EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), true))
         .Times(1);
   }
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_TRUE(adapter->IsPowered());
+  EXPECT_TRUE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterPoweredPropertyResetOnRemove) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -938,8 +962,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -956,24 +981,24 @@
   // Report that the adapter has been removed;
   // BluetoothAdapter::Observer::AdapterPoweredChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
       .Times(1);
-  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPoweredChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->AdapterRemoved(adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_FALSE(adapter->IsPowered());
+  EXPECT_FALSE(adapter_->IsPowered());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterSetPowered) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterSetPowered) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -984,8 +1009,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1004,10 +1030,10 @@
   EXPECT_CALL(adapter_properties, Set(&adapter_properties.powered, _))
       .WillOnce(SaveArg<1>(&set_callback));
 
-  adapter->SetPowered(true,
-                      base::Bind(&BluetoothAdapterChromeOsTest::SetCallback,
+  adapter_->SetPowered(true,
+                      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
                                  base::Unretained(this)),
-                      base::Bind(&BluetoothAdapterChromeOsTest::ErrorCallback,
+                      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
                                  base::Unretained(this)));
 
   // Reply to the callback to indicate success, the set callback we provided
@@ -1017,11 +1043,11 @@
 
   set_callback.Run(true);
 
-  EXPECT_TRUE(set_callback_called_);
+  EXPECT_TRUE(callback_called_);
   EXPECT_FALSE(error_callback_called_);
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterSetPoweredError) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterSetPoweredError) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -1032,8 +1058,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1052,11 +1079,11 @@
   EXPECT_CALL(adapter_properties, Set(&adapter_properties.powered, _))
       .WillOnce(SaveArg<1>(&set_callback));
 
-  adapter->SetPowered(true,
-                      base::Bind(&BluetoothAdapterChromeOsTest::SetCallback,
-                                 base::Unretained(this)),
-                      base::Bind(&BluetoothAdapterChromeOsTest::ErrorCallback,
-                                 base::Unretained(this)));
+  adapter_->SetPowered(true,
+                       base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                                  base::Unretained(this)),
+                       base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                                  base::Unretained(this)));
 
   // Reply to the callback to indicate failure, the error callback we provided
   // should be called but the properties should not be refetched.
@@ -1065,11 +1092,11 @@
 
   set_callback.Run(false);
 
-  EXPECT_FALSE(set_callback_called_);
+  EXPECT_FALSE(callback_called_);
   EXPECT_TRUE(error_callback_called_);
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyInitiallyFalse) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1081,8 +1108,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1097,10 +1125,10 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyInitiallyTrue) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1112,8 +1140,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1125,23 +1154,23 @@
   EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
       .WillRepeatedly(Return(&adapter_properties));
 
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), true))
       .Times(1);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyInitiallyTrueWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1153,53 +1182,54 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
-  // the property set but BluetoothAdapter::Observer::AdapterDiscoveringChanged
+  // the property set but BluetoothAdapter::Observer::AdapterScanningChanged
   // should not yet be called.
   MockBluetoothAdapterClient::Properties adapter_properties;
   adapter_properties.discovering.ReplaceValue(true);
 
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
       .WillRepeatedly(Return(&adapter_properties));
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should not yet have the property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
 
   // Tell the adapter the address now,
   // BluetoothAdapter::Observer::AdapterPresentChanged and
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged now must be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), true))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.address.name());
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest, DefaultAdapterDiscoveringPropertyChanged) {
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterDiscoveringPropertyChanged) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
 
@@ -1210,8 +1240,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1226,30 +1257,30 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
 
   // Report that the property has been changed;
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), true))
       .Times(1);
 
   adapter_properties.discovering.ReplaceValue(true);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.discovering.name());
 
   // Adapter should have the new property values.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyUnchanged) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1261,8 +1292,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1277,29 +1309,29 @@
   adapter_callback.Run(adapter_path, true);
 
   // Adapter should have the correct property value.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 
   // Report that the property has been changed, but don't change the value;
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged should not be
+  // BluetoothAdapter::Observer::AdapterScanningChanged should not be
   // called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.discovering.name());
 
   // Adapter should still have the same property values.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyChangedWithoutAddress) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1311,22 +1343,23 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
-  // the property set but BluetoothAdapter::Observer::AdapterDiscoveringChanged
+  // the property set but BluetoothAdapter::Observer::AdapterScanningChanged
   // should not yet be called.
   MockBluetoothAdapterClient::Properties adapter_properties;
 
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
       .WillRepeatedly(Return(&adapter_properties));
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), _))
       .Times(0);
 
   adapter_callback.Run(adapter_path, true);
@@ -1336,28 +1369,28 @@
   // the adapter so it is not present.
   adapter_properties.discovering.ReplaceValue(true);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), _))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), _))
       .Times(0);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->AdapterPropertyChanged(adapter_path,
                                adapter_properties.discovering.name());
 
   // Adapter should not yet have the property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
 
   // Tell the adapter the address now,
   // BluetoothAdapter::Observer::AdapterPresentChanged and
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged now must be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged now must be called.
   adapter_properties.address.ReplaceValue(adapter_address);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
       .Times(1);
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), true))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), true))
       .Times(1);
 
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
@@ -1365,10 +1398,10 @@
                                adapter_properties.address.name());
 
   // Adapter should now have the correct property value.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyResetOnReplace) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
@@ -1382,8 +1415,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1406,33 +1440,33 @@
   EXPECT_CALL(*mock_adapter_client_, GetProperties(new_adapter_path))
       .WillRepeatedly(Return(&new_adapter_properties));
 
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
         .Times(1);
   }
 
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyResetOnReplaceWhenTrue) {
   const dbus::ObjectPath initial_adapter_path("/fake/hci0");
   const dbus::ObjectPath new_adapter_path("/fake/hci1");
@@ -1446,8 +1480,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1471,43 +1506,43 @@
   EXPECT_CALL(*mock_adapter_client_, GetProperties(new_adapter_path))
       .WillRepeatedly(Return(&new_adapter_properties));
 
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called once
+  // BluetoothAdapter::Observer::AdapterScanningChanged will be called once
   // to set the value to false for the previous adapter and once to set the
   // value to true for the new adapter.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), true))
+    EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), true))
         .Times(1);
   }
 
   {
     InSequence s;
 
-    EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(),
-                                                            false))
+    EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(),
+                                                         false))
         .Times(1);
-    EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(),
-                                                            true))
+    EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(),
+                                                         true))
         .Times(1);
   }
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->DefaultAdapterChanged(new_adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_TRUE(adapter->IsDiscovering());
+  EXPECT_TRUE(adapter_->IsScanning());
 }
 
-TEST_F(BluetoothAdapterChromeOsTest,
+TEST_F(BluetoothAdapterChromeOSTest,
        DefaultAdapterDiscoveringPropertyResetOnRemove) {
   const dbus::ObjectPath adapter_path("/fake/hci0");
   const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
@@ -1519,8 +1554,9 @@
   EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
       .WillOnce(SaveArg<0>(&adapter_callback));
 
-  scoped_refptr<BluetoothAdapter> adapter =
-      BluetoothAdapterFactory::DefaultAdapter();
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
 
   // Call the adapter callback;
   // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -1535,23 +1571,815 @@
   adapter_callback.Run(adapter_path, true);
 
   // Report that the adapter has been removed;
-  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  // BluetoothAdapter::Observer::AdapterScanningChanged will be called.
   MockBluetoothAdapter::Observer adapter_observer;
-  adapter->AddObserver(&adapter_observer);
+  adapter_->AddObserver(&adapter_observer);
 
-  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterPresentChanged(adapter_.get(), false))
       .Times(1);
-  EXPECT_CALL(adapter_observer, AdapterDiscoveringChanged(adapter.get(), false))
+  EXPECT_CALL(adapter_observer, AdapterScanningChanged(adapter_.get(), false))
       .Times(1);
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
   static_cast<BluetoothManagerClient::Observer*>(adapter_chromeos)
       ->AdapterRemoved(adapter_path);
 
   // Adapter should have the new property value.
-  EXPECT_FALSE(adapter->IsDiscovering());
+  EXPECT_FALSE(adapter_->IsScanning());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterNotInitiallyDiscovering) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Adapter should have the correct property value.
+  EXPECT_FALSE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterStartDiscovering) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterStartDiscoveringError) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate failure,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will not be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, false);
+
+  EXPECT_FALSE(callback_called_);
+  EXPECT_TRUE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_FALSE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterSecondStartDiscovering) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices again;
+  // BluetoothAdapterClient::StartDiscovery will be called again.
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since it has not changed.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest,
+       DefaultAdapterSecondStartDiscoveringError) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices again;
+  // BluetoothAdapterClient::StartDiscovery will be called again.
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate failure, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since it has not really changed.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, false);
+
+  EXPECT_FALSE(callback_called_);
+  EXPECT_TRUE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterStopDiscovering) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to stop discovering devices;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback stop_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged should be called.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), false))
+      .Times(1);
+
+  stop_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_FALSE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest, DefaultAdapterStopDiscoveringError) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to stop discovering devices;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback stop_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate failure,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will not be called.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  stop_discovery_callback.Run(adapter_path, false);
+
+  EXPECT_FALSE(callback_called_);
+  EXPECT_TRUE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest,
+       DefaultAdapterStopDiscoveringAfterSecondStart) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices again;
+  // BluetoothAdapterClient::StartDiscovery will be called again.
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since it has not changed.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to stop discovering devices;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback stop_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since there is still an open session.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  stop_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest,
+       DefaultAdapterStopDiscoveringAfterSecondStartError) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices again;
+  // BluetoothAdapterClient::StartDiscovery will be called again.
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate failure, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since it has not changed.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, false);
+
+  // Ask the adapter to stop discovering devices;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback stop_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged should be called.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), false))
+      .Times(1);
+
+  stop_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_FALSE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterChromeOSTest,
+       DefaultAdapterSecondStopDiscoveringAfterSecondStart) {
+  const dbus::ObjectPath adapter_path("/fake/hci0");
+  const std::string adapter_address = "CA:FE:4A:C0:FE:FE";
+
+  // Create the default adapter instance;
+  // BluetoothManagerClient::DefaultAdapter will be called once, passing
+  // a callback to obtain the adapter path.
+  BluetoothManagerClient::AdapterCallback adapter_callback;
+  EXPECT_CALL(*mock_manager_client_, DefaultAdapter(_))
+      .WillOnce(SaveArg<0>(&adapter_callback));
+
+  BluetoothAdapterFactory::GetAdapter(
+      base::Bind(&BluetoothAdapterChromeOSTest::SetAdapter,
+                 base::Unretained(this)));
+
+  // Call the adapter callback;
+  // BluetoothAdapterClient::GetProperties will be called once to obtain
+  // the property set.
+  MockBluetoothAdapterClient::Properties adapter_properties;
+  adapter_properties.address.ReplaceValue(adapter_address);
+
+  EXPECT_CALL(*mock_adapter_client_, GetProperties(adapter_path))
+      .WillRepeatedly(Return(&adapter_properties));
+
+  adapter_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices;
+  // BluetoothAdapterClient::StartDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback start_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged will be called.
+  MockBluetoothAdapter::Observer adapter_observer;
+  adapter_->AddObserver(&adapter_observer);
+
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), true))
+      .Times(1);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to start discovering devices again;
+  // BluetoothAdapterClient::StartDiscovery will be called again.
+  EXPECT_CALL(*mock_adapter_client_, StartDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&start_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StartDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since it has not changed.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  start_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to stop discovering devices;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  BluetoothAdapterClient::AdapterCallback stop_discovery_callback;
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success, we do not expect
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged to be called
+  // since there is still an open session.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), _))
+      .Times(0);
+
+  stop_discovery_callback.Run(adapter_path, true);
+
+  // Ask the adapter to stop discovering devices again;
+  // BluetoothAdapterClient::StopDiscovery will be called.
+  EXPECT_CALL(*mock_adapter_client_, StopDiscovery(adapter_path, _))
+      .WillOnce(SaveArg<1>(&stop_discovery_callback));
+
+  callback_called_ = false;
+  error_callback_called_ = false;
+
+  adapter_->StopDiscovering(
+      base::Bind(&BluetoothAdapterChromeOSTest::Callback,
+                 base::Unretained(this)),
+      base::Bind(&BluetoothAdapterChromeOSTest::ErrorCallback,
+                 base::Unretained(this)));
+
+  // After returning to indicate success,
+  // BluetoothAdapter::Observer::AdapterDiscoveringChanged should be called.
+  EXPECT_CALL(adapter_observer,
+              AdapterDiscoveringChanged(adapter_.get(), false))
+      .Times(1);
+
+  stop_discovery_callback.Run(adapter_path, true);
+
+  EXPECT_TRUE(callback_called_);
+  EXPECT_FALSE(error_callback_called_);
+
+  // Adapter should have the correct property value.
+  EXPECT_FALSE(adapter_->IsDiscovering());
 }
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_adapter_devices_chromeos_unittest.cc b/device/bluetooth/bluetooth_adapter_devices_chromeos_unittest.cc
index ac7677b..a4e01de 100644
--- a/device/bluetooth/bluetooth_adapter_devices_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_devices_chromeos_unittest.cc
@@ -24,7 +24,7 @@
 
 namespace chromeos {
 
-class BluetoothAdapterDevicesChromeOsTest : public testing::Test {
+class BluetoothAdapterDevicesChromeOSTest : public testing::Test {
  public:
   virtual void SetUp() {
     MockDBusThreadManager* mock_dbus_thread_manager = new MockDBusThreadManager;
@@ -52,8 +52,10 @@
     EXPECT_CALL(*mock_adapter_client_, AddObserver(_))
         .Times(1);
 
-    adapter_ = BluetoothAdapterFactory::DefaultAdapter();
-    ASSERT_TRUE(adapter_.get() != NULL);
+    BluetoothAdapterFactory::GetAdapter(
+        base::Bind(&BluetoothAdapterDevicesChromeOSTest::SetAdapter,
+                   base::Unretained(this)));
+    ASSERT_TRUE(adapter_ != NULL);
 
     // Call the adapter callback;
     // BluetoothAdapterClient::GetProperties will be called once to obtain
@@ -83,8 +85,8 @@
   }
 
   virtual void TearDown() {
-    BluetoothAdapterChromeOs* adapter_chromeos =
-        static_cast<BluetoothAdapterChromeOs*>(adapter_.get());
+    BluetoothAdapterChromeOS* adapter_chromeos =
+        static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
     EXPECT_CALL(*mock_device_client_, RemoveObserver(adapter_chromeos))
         .Times(1);
     EXPECT_CALL(*mock_adapter_client_, RemoveObserver(adapter_chromeos))
@@ -96,6 +98,10 @@
     DBusThreadManager::Shutdown();
   }
 
+  void SetAdapter(scoped_refptr<device::BluetoothAdapter> adapter) {
+    adapter_ = adapter;
+  }
+
  protected:
   MockBluetoothManagerClient* mock_manager_client_;
   MockBluetoothAdapterClient* mock_adapter_client_;
@@ -108,12 +114,12 @@
   MockBluetoothAdapter::Observer adapter_observer_;
 };
 
-const dbus::ObjectPath BluetoothAdapterDevicesChromeOsTest::adapter_path_(
+const dbus::ObjectPath BluetoothAdapterDevicesChromeOSTest::adapter_path_(
     "/fake/hci0");
-const std::string BluetoothAdapterDevicesChromeOsTest::adapter_address_ =
+const std::string BluetoothAdapterDevicesChromeOSTest::adapter_address_ =
     "CA:FE:4A:C0:FE:FE";
 
-TEST_F(BluetoothAdapterDevicesChromeOsTest, DeviceRemovedAfterFound) {
+TEST_F(BluetoothAdapterDevicesChromeOSTest, DeviceRemovedAfterFound) {
   const dbus::ObjectPath device_path("/fake/hci0/dev_ba_c0_11_00_00_01");
   const std::string device_address = "BA:C0:11:00:00:01";
 
@@ -130,8 +136,8 @@
       .Times(1)
       .WillOnce(SaveArg<1>(&device));
 
-  BluetoothAdapterChromeOs* adapter_chromeos =
-      static_cast<BluetoothAdapterChromeOs*>(adapter_.get());
+  BluetoothAdapterChromeOS* adapter_chromeos =
+      static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
   static_cast<BluetoothAdapterClient::Observer*>(adapter_chromeos)
       ->DeviceFound(adapter_path_, device_address, device_properties);
 
diff --git a/device/bluetooth/bluetooth_adapter_factory.cc b/device/bluetooth/bluetooth_adapter_factory.cc
index 03d633f..f772431 100644
--- a/device/bluetooth/bluetooth_adapter_factory.cc
+++ b/device/bluetooth/bluetooth_adapter_factory.cc
@@ -4,17 +4,28 @@
 
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 
+#include <vector>
+
+#include "base/bind.h"
+#include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/chromeos_switches.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
 #if defined(OS_CHROMEOS)
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
+#include "device/bluetooth/bluetooth_adapter_chromeos_experimental.h"
+#elif defined(OS_WIN)
+#include "device/bluetooth/bluetooth_adapter_win.h"
 #endif
 
 namespace {
 
+using device::BluetoothAdapter;
+using device::BluetoothAdapterFactory;
+
 // Shared default adapter instance, we don't want to keep this class around
 // if nobody is using it so use a WeakPtr and create the object when needed;
 // since Google C++ Style (and clang's static analyzer) forbids us having
@@ -22,34 +33,75 @@
 base::LazyInstance<base::WeakPtr<device::BluetoothAdapter> >::Leaky
     default_adapter = LAZY_INSTANCE_INITIALIZER;
 
+typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
+    AdapterCallbackList;
+
+// List of adapter callbacks to be called once the adapter is initialized.
+// Since Google C++ Style (and clang's static analyzer) forbids us having
+// exit-time destructors we use a lazy instance for it.
+base::LazyInstance<AdapterCallbackList> adapter_callbacks =
+    LAZY_INSTANCE_INITIALIZER;
+
+void RunAdapterCallbacks() {
+  CHECK(default_adapter.Get().get());
+  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get());
+  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
+           iter = adapter_callbacks.Get().begin();
+       iter != adapter_callbacks.Get().end();
+       ++iter) {
+    iter->Run(adapter);
+  }
+  adapter_callbacks.Get().clear();
+}
+
 }  // namespace
 
 namespace device {
 
 // static
-scoped_refptr<BluetoothAdapter> BluetoothAdapterFactory::DefaultAdapter() {
+bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
+#if defined(OS_CHROMEOS)
+  return true;
+#elif defined(OS_WIN)
+  return true;
+#endif
+  return false;
+}
+
+// static
+void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
   if (!default_adapter.Get().get()) {
 #if defined(OS_CHROMEOS)
-    chromeos::BluetoothAdapterChromeOs* new_adapter =
-        new chromeos::BluetoothAdapterChromeOs;
+    if (CommandLine::ForCurrentProcess()->HasSwitch(
+        chromeos::switches::kEnableExperimentalBluetooth)) {
+      chromeos::BluetoothAdapterChromeOSExperimental* new_adapter =
+          new chromeos::BluetoothAdapterChromeOSExperimental;
+      new_adapter->TrackDefaultAdapter();
+      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
+    } else {
+      chromeos::BluetoothAdapterChromeOS* new_adapter =
+          new chromeos::BluetoothAdapterChromeOS;
+      new_adapter->TrackDefaultAdapter();
+      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
+    }
+#elif defined(OS_WIN)
+    BluetoothAdapterWin* new_adapter = new BluetoothAdapterWin(
+        base::Bind(&RunAdapterCallbacks));
     new_adapter->TrackDefaultAdapter();
     default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
 #endif
   }
 
-  return scoped_refptr<BluetoothAdapter>(default_adapter.Get());
+  if (default_adapter.Get()->IsInitialized()) {
+    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get()));
+  } else {
+    adapter_callbacks.Get().push_back(callback);
+  }
 }
 
 // static
-BluetoothAdapter* BluetoothAdapterFactory::Create(const std::string& address) {
-  BluetoothAdapter* adapter = NULL;
-#if defined(OS_CHROMEOS)
-  chromeos::BluetoothAdapterChromeOs* adapter_chromeos =
-      new chromeos::BluetoothAdapterChromeOs;
-  adapter_chromeos->FindAdapter(address);
-  adapter = adapter_chromeos;
-#endif
-  return adapter;
+scoped_refptr<BluetoothAdapter> BluetoothAdapterFactory::MaybeGetAdapter() {
+  return scoped_refptr<BluetoothAdapter>(default_adapter.Get());
 }
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_factory.h b/device/bluetooth/bluetooth_adapter_factory.h
index 82e1e6f..3b6a2c2 100644
--- a/device/bluetooth/bluetooth_adapter_factory.h
+++ b/device/bluetooth/bluetooth_adapter_factory.h
@@ -7,25 +7,34 @@
 
 #include <string>
 
+#include "base/callback.h"
 #include "base/memory/ref_counted.h"
+#include "device/bluetooth/bluetooth_adapter.h"
 
 namespace device {
 
-class BluetoothAdapter;
-
 // BluetoothAdapterFactory is a class that contains static methods, which
-// instantiate either a specific bluetooth adapter, or the generic "default
+// instantiate either a specific Bluetooth adapter, or the generic "default
 // adapter" which may change depending on availability.
 class BluetoothAdapterFactory {
  public:
-  // Returns the shared instance for the default adapter, whichever that may
-  // be at the time. Check the returned scoped_refptr does not point to NULL and
-  // use IsPresent() and the AdapterPresentChanged() observer method to
-  // determine whether an adapter is actually available or not.
-  static scoped_refptr<BluetoothAdapter> DefaultAdapter();
+  typedef base::Callback<void(scoped_refptr<BluetoothAdapter> adapter)>
+      AdapterCallback;
 
-  // Creates an instance for a specific adapter at address |address|.
-  static BluetoothAdapter* Create(const std::string& address);
+  // Returns true if the Bluetooth adapter is available for the current
+  // platform.
+  static bool IsBluetoothAdapterAvailable();
+
+  // Returns the shared instance of the default adapter, creating and
+  // initializing it if necessary. |callback| is called with the adapter
+  // instance passed only once the adapter is fully initialized and ready to
+  // use.
+  static void GetAdapter(const AdapterCallback& callback);
+
+  // Returns the shared instance of the adapter that has already been created,
+  // but may or may not have been initialized.
+  // It returns NULL if no adapter has been created at the time.
+  static scoped_refptr<BluetoothAdapter> MaybeGetAdapter();
 };
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
new file mode 100644
index 0000000..8d646a3
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -0,0 +1,92 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_MAC_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_MAC_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+
+#ifdef __OBJC__
+@class NSArray;
+#else
+class NSArray;
+#endif
+
+namespace base {
+
+class SequencedTaskRunner;
+
+}  // namespace base
+
+namespace device {
+
+class BluetoothAdapterMacTest;
+
+class BluetoothAdapterMac : public BluetoothAdapter {
+ public:
+  // BluetoothAdapter override
+  virtual void AddObserver(BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual bool IsInitialized() const OVERRIDE;
+  virtual bool IsPresent() const OVERRIDE;
+  virtual bool IsPowered() const OVERRIDE;
+  virtual void SetPowered(
+      bool powered,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual bool IsDiscovering() const OVERRIDE;
+  virtual bool IsScanning() const OVERRIDE;
+
+  virtual void StartDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void StopDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void ReadLocalOutOfBandPairingData(
+      const BluetoothOutOfBandPairingDataCallback& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+
+ private:
+  friend class BluetoothAdapterFactory;
+  friend class BluetoothAdapterMacTest;
+
+  BluetoothAdapterMac();
+  virtual ~BluetoothAdapterMac();
+
+  void TrackDefaultAdapter();
+  void TrackTestAdapter(
+      scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
+  void PollAdapter();
+
+  // Adds |devices| into |devices_| and notifies observers of the changes.
+  // |devices| is an array of pointers to discovered or paired
+  // |IOBluetoothDevice| objects.
+  void AddDevices(NSArray* devices);
+
+  // Removes devices that used to be paired but are unpaired by the system from
+  // |devices_|.
+  // |devices| is an array of pointers to paired |IOBluetoothDevice| objects.
+  void RemoveUnpairedDevices(NSArray* paired_devices);
+
+  bool powered_;
+
+  scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
+
+  // List of observers interested in event notifications from us.
+  ObserverList<BluetoothAdapter::Observer> observers_;
+
+  base::WeakPtrFactory<BluetoothAdapterMac> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterMac);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_MAC_H_
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
new file mode 100644
index 0000000..c7d0eb5
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -0,0 +1,203 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_adapter_mac.h"
+
+#import <IOBluetooth/objc/IOBluetoothDevice.h>
+#import <IOBluetooth/objc/IOBluetoothHostController.h>
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/hash_tables.h"
+#include "base/location.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time.h"
+#include "base/strings/sys_string_conversions.h"
+#include "device/bluetooth/bluetooth_device_mac.h"
+
+// Replicate specific 10.7 SDK declarations for building with prior SDKs.
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
+@interface IOBluetoothHostController (LionSDKDeclarations)
+- (NSString*)nameAsString;
+- (BluetoothHCIPowerState)powerState;
+@end
+
+@interface IOBluetoothDevice (LionSDKDeclarations)
+- (NSString*)addressString;
+@end
+
+#endif  // MAC_OS_X_VERSION_10_7
+
+namespace {
+
+const int kPollIntervalMs = 500;
+
+}  // namespace
+
+namespace device {
+
+BluetoothAdapterMac::BluetoothAdapterMac()
+    : BluetoothAdapter(),
+      powered_(false),
+      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+}
+
+BluetoothAdapterMac::~BluetoothAdapterMac() {
+}
+
+void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) {
+  DCHECK(observer);
+  observers_.AddObserver(observer);
+}
+
+void BluetoothAdapterMac::RemoveObserver(BluetoothAdapter::Observer* observer) {
+  DCHECK(observer);
+  observers_.RemoveObserver(observer);
+}
+
+bool BluetoothAdapterMac::IsInitialized() const {
+  return true;
+}
+
+bool BluetoothAdapterMac::IsPresent() const {
+  return !address_.empty();
+}
+
+bool BluetoothAdapterMac::IsPowered() const {
+  return powered_;
+}
+
+void BluetoothAdapterMac::SetPowered(bool powered,
+                                     const base::Closure& callback,
+                                     const ErrorCallback& error_callback) {
+}
+
+bool BluetoothAdapterMac::IsDiscovering() const {
+  return false;
+}
+
+bool BluetoothAdapterMac::IsScanning() const {
+  return false;
+}
+
+void BluetoothAdapterMac::StartDiscovering(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+}
+
+void BluetoothAdapterMac::StopDiscovering(const base::Closure& callback,
+                                          const ErrorCallback& error_callback) {
+}
+
+void BluetoothAdapterMac::ReadLocalOutOfBandPairingData(
+    const BluetoothOutOfBandPairingDataCallback& callback,
+    const ErrorCallback& error_callback) {
+}
+
+void BluetoothAdapterMac::TrackDefaultAdapter() {
+  ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+  PollAdapter();
+}
+
+void BluetoothAdapterMac::TrackTestAdapter(
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner) {
+  ui_task_runner_ = ui_task_runner;
+  PollAdapter();
+}
+
+void BluetoothAdapterMac::PollAdapter() {
+  bool was_present = IsPresent();
+  std::string name = "";
+  std::string address = "";
+  bool powered = false;
+  IOBluetoothHostController* controller =
+      [IOBluetoothHostController defaultController];
+
+  if (controller != nil) {
+    name = base::SysNSStringToUTF8([controller nameAsString]);
+    address = base::SysNSStringToUTF8([controller addressAsString]);
+    powered = ([controller powerState] == kBluetoothHCIPowerStateON);
+  }
+
+  bool is_present = !address.empty();
+  name_ = name;
+  address_ = address;
+
+  if (was_present != is_present) {
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterPresentChanged(this, is_present));
+  }
+  if (powered_ != powered) {
+    powered_ = powered;
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterPoweredChanged(this, powered_));
+  }
+
+  NSArray* paired_devices = [IOBluetoothDevice pairedDevices];
+  AddDevices(paired_devices);
+  RemoveUnpairedDevices(paired_devices);
+
+  ui_task_runner_->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&BluetoothAdapterMac::PollAdapter,
+                 weak_ptr_factory_.GetWeakPtr()),
+      base::TimeDelta::FromMilliseconds(kPollIntervalMs));
+}
+
+void BluetoothAdapterMac::AddDevices(NSArray* devices) {
+  for (IOBluetoothDevice* device in devices) {
+    std::string device_address =
+        base::SysNSStringToUTF8([device addressString]);
+    DevicesMap::iterator found_device_iter = devices_.find(device_address);
+
+    if (found_device_iter == devices_.end()) {
+      devices_[device_address] = new BluetoothDeviceMac(device);
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceAdded(this, devices_[device_address]));
+      continue;
+    }
+    BluetoothDeviceMac* device_mac =
+        static_cast<BluetoothDeviceMac*>(found_device_iter->second);
+    if (device_mac->device_fingerprint() !=
+        BluetoothDeviceMac::ComputeDeviceFingerprint(device)) {
+      devices_[device_address] = new BluetoothDeviceMac(device);
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceChanged(this, devices_[device_address]));
+      delete device_mac;
+    }
+  }
+}
+
+void BluetoothAdapterMac::RemoveUnpairedDevices(NSArray* paired_devices) {
+  base::hash_set<std::string> paired_device_address_list;
+  for (IOBluetoothDevice* device in paired_devices) {
+    paired_device_address_list.insert(
+        base::SysNSStringToUTF8([device addressString]));
+  }
+
+  DevicesMap::iterator iter = devices_.begin();
+  while (iter != devices_.end()) {
+    DevicesMap::iterator device_iter = iter;
+    ++iter;
+
+    if (paired_device_address_list.find(device_iter->first) !=
+        paired_device_address_list.end())
+      continue;
+
+    if (device_iter->second->IsPaired()) {
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceRemoved(this, device_iter->second));
+      delete device_iter->second;
+      devices_.erase(device_iter);
+    }
+  }
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_mac_unittest.mm b/device/bluetooth/bluetooth_adapter_mac_unittest.mm
new file mode 100644
index 0000000..19e2a8a
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_mac_unittest.mm
@@ -0,0 +1,215 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <IOBluetooth/IOBluetoothUtilities.h>
+#import <IOBluetooth/objc/IOBluetoothDevice.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/test/test_simple_task_runner.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_adapter_mac.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+@interface TestIOBluetoothDevice : IOBluetoothDevice {
+ @private
+  NSString* device_name_;
+  NSString* device_address_;
+  BOOL paired_;
+}
+
++ (TestIOBluetoothDevice*)deviceWithName:(NSString*)device_name
+                                 address:(NSString*)device_address
+                                  paired:(BOOL)paired;
+- (id)initWithName:(NSString*)device_name
+           address:(NSString*)device_address
+            paired:(BOOL)paired;
+
+@property (nonatomic, copy, getter=name) NSString* deviceName;
+@property (nonatomic, copy, getter=addressString) NSString* deviceAddress;
+@property (nonatomic, assign, getter=isPaired) BOOL paired;
+
+@end
+
+@implementation TestIOBluetoothDevice
+
+@synthesize deviceName = device_name_;
+@synthesize deviceAddress = device_address_;
+@synthesize paired = paired_;
+
++ (TestIOBluetoothDevice*)deviceWithName:(NSString*)device_name
+                                 address:(NSString*)device_address
+                                  paired:(BOOL)paired {
+  return [[[TestIOBluetoothDevice alloc] initWithName:device_name
+                                              address:device_address
+                                               paired:paired] autorelease];
+}
+
+- (id)initWithName:(NSString*)device_name
+           address:(NSString*)device_address
+            paired:(BOOL)paired {
+  if (self = [super init]) {
+    [self setDeviceName:device_name];
+    [self setDeviceAddress:device_address];
+    [self setPaired:paired];
+  }
+
+  return self;
+}
+
+- (void)dealloc {
+  [self setDeviceName:nil];
+  [self setDeviceAddress:nil];
+  [super dealloc];
+}
+
+@end
+
+namespace {
+
+class AdapterObserver : public device::BluetoothAdapter::Observer {
+ public:
+  AdapterObserver() {
+    Clear();
+  }
+
+  void Clear() {
+    num_device_added_ = 0;
+    num_device_changed_ = 0;
+    num_device_removed_ = 0;
+  }
+
+  virtual void DeviceAdded(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_added_++;
+  }
+
+  virtual void DeviceChanged(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_changed_++;
+  }
+
+  virtual void DeviceRemoved(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_removed_++;
+  }
+
+  int num_device_added() const {
+    return num_device_added_;
+  }
+
+  int num_device_changed() const {
+    return num_device_changed_;
+  }
+
+  int num_device_removed() const {
+    return num_device_removed_;
+  }
+
+ private:
+  int num_device_added_;
+  int num_device_changed_;
+  int num_device_removed_;
+};
+
+}  // namespace
+
+namespace device {
+
+class BluetoothAdapterMacTest : public testing::Test {
+ public:
+  BluetoothAdapterMacTest()
+      : ui_task_runner_(new base::TestSimpleTaskRunner()),
+        adapter_(new BluetoothAdapterMac()),
+        adapter_mac_(static_cast<BluetoothAdapterMac*>(adapter_.get())) {
+    adapter_mac_->TrackTestAdapter(ui_task_runner_);
+    adapter_mac_->RemoveUnpairedDevices([NSArray array]);
+    adapter_observer_.Clear();
+  }
+
+  virtual void SetUp() OVERRIDE {
+    adapter_mac_->AddObserver(&adapter_observer_);
+  }
+
+  virtual void TearDown() OVERRIDE {
+    adapter_mac_->RemoveObserver(&adapter_observer_);
+  }
+
+  void AddDevices(NSArray* devices) {
+    adapter_mac_->AddDevices(devices);
+  }
+
+  void RemoveUnpairedDevices(NSArray* devices) {
+    adapter_mac_->RemoveUnpairedDevices(devices);
+  }
+
+ protected:
+  scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;
+  scoped_refptr<BluetoothAdapter> adapter_;
+  BluetoothAdapterMac* adapter_mac_;
+  AdapterObserver adapter_observer_;
+};
+
+TEST_F(BluetoothAdapterMacTest, Poll) {
+  EXPECT_FALSE(ui_task_runner_->GetPendingTasks().empty());
+}
+
+TEST_F(BluetoothAdapterMacTest, AddDevices) {
+  TestIOBluetoothDevice* android_device =
+      [TestIOBluetoothDevice deviceWithName:@"android"
+                                    address:@"11:22:33:44:55:66"
+                                     paired:false];
+  TestIOBluetoothDevice* laptop_device =
+      [TestIOBluetoothDevice deviceWithName:@"laptop"
+                                    address:@"77:88:99:aa:bb:cc"
+                                     paired:false];
+  TestIOBluetoothDevice* iphone_device =
+      [TestIOBluetoothDevice deviceWithName:@"iphone"
+                                    address:@"dd:ee:ff:11:22:33"
+                                     paired:false];
+  NSMutableArray* devices = [NSMutableArray arrayWithCapacity:3];
+  [devices addObject:android_device];
+  [devices addObject:laptop_device];
+  [devices addObject:iphone_device];
+  AddDevices(devices);
+  EXPECT_EQ(3, adapter_observer_.num_device_added());
+  adapter_observer_.Clear();
+
+  AddDevices(devices);
+  EXPECT_EQ(0, adapter_observer_.num_device_added());
+  EXPECT_EQ(0, adapter_observer_.num_device_changed());
+
+  [iphone_device setDeviceName:@"apple phone"];
+  AddDevices(devices);
+  EXPECT_EQ(0, adapter_observer_.num_device_added());
+  EXPECT_EQ(1, adapter_observer_.num_device_changed());
+  adapter_observer_.Clear();
+}
+
+TEST_F(BluetoothAdapterMacTest, RemoveUnpairedDevices) {
+  TestIOBluetoothDevice* android_device =
+      [TestIOBluetoothDevice deviceWithName:@"android"
+                                    address:@"11:22:33:44:55:66"
+                                     paired:true];
+  TestIOBluetoothDevice* laptop_device =
+      [TestIOBluetoothDevice deviceWithName:@"laptop"
+                                    address:@"77:88:99:aa:bb:cc"
+                                     paired:false];
+  NSMutableArray* devices = [NSMutableArray arrayWithCapacity:2];
+  [devices addObject:android_device];
+  [devices addObject:laptop_device];
+  AddDevices(devices);
+  adapter_observer_.Clear();
+
+  RemoveUnpairedDevices([NSArray arrayWithObject:android_device]);
+  EXPECT_EQ(0, adapter_observer_.num_device_removed());
+
+  RemoveUnpairedDevices([NSArray array]);
+  EXPECT_EQ(1, adapter_observer_.num_device_removed());
+
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc
index 97eca65..374620b 100644
--- a/device/bluetooth/bluetooth_adapter_win.cc
+++ b/device/bluetooth/bluetooth_adapter_win.cc
@@ -1,75 +1,152 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// TODO(youngki): Implement this file.
 
 #include "device/bluetooth/bluetooth_adapter_win.h"
 
+#include <hash_set>
 #include <string>
+#include <utility>
+
 #include "base/logging.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/thread_task_runner_handle.h"
+#include "device/bluetooth/bluetooth_device_win.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
 
 namespace device {
 
-BluetoothAdapterWin::BluetoothAdapterWin()
+BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback)
     : BluetoothAdapter(),
+      init_callback_(init_callback),
+      initialized_(false),
+      powered_(false),
+      discovery_status_(NOT_DISCOVERING),
+      scanning_(false),
+      num_discovery_listeners_(0),
       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
 }
 
 BluetoothAdapterWin::~BluetoothAdapterWin() {
+  if (task_manager_) {
+    task_manager_->RemoveObserver(this);
+    task_manager_->Shutdown();
+  }
 }
 
 void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) {
-  NOTIMPLEMENTED();
+  DCHECK(observer);
+  observers_.AddObserver(observer);
 }
 
 void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) {
-  NOTIMPLEMENTED();
+  DCHECK(observer);
+  observers_.RemoveObserver(observer);
+}
+
+// TODO(youngki): Return true when |task_manager_| initializes the adapter
+// state.
+bool BluetoothAdapterWin::IsInitialized() const {
+  return initialized_;
 }
 
 bool BluetoothAdapterWin::IsPresent() const {
-  NOTIMPLEMENTED();
-  return false;
+  return !address_.empty();
 }
 
 bool BluetoothAdapterWin::IsPowered() const {
-  NOTIMPLEMENTED();
-  return false;
+  return powered_;
 }
 
 void BluetoothAdapterWin::SetPowered(
     bool powered,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  NOTIMPLEMENTED();
+  task_manager_->PostSetPoweredBluetoothTask(powered, callback, error_callback);
 }
 
 bool BluetoothAdapterWin::IsDiscovering() const {
-  NOTIMPLEMENTED();
-  return false;
+  return discovery_status_ == DISCOVERING ||
+      discovery_status_ == DISCOVERY_STOPPING;
 }
 
-void BluetoothAdapterWin::SetDiscovering(
-    bool discovering,
+bool BluetoothAdapterWin::IsScanning() const {
+  return scanning_;
+}
+
+// If the method is called when |discovery_status_| is DISCOVERY_STOPPING,
+// starting again is handled by BluetoothAdapterWin::DiscoveryStopped().
+void BluetoothAdapterWin::StartDiscovering(
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  NOTIMPLEMENTED();
+  if (discovery_status_ == DISCOVERING) {
+    num_discovery_listeners_++;
+    callback.Run();
+    return;
+  }
+  on_start_discovery_callbacks_.push_back(
+      std::make_pair(callback, error_callback));
+  MaybePostStartDiscoveryTask();
 }
 
-BluetoothAdapter::ConstDeviceList BluetoothAdapterWin::GetDevices() const {
-  NOTIMPLEMENTED();
-  return BluetoothAdapter::ConstDeviceList();
+void BluetoothAdapterWin::StopDiscovering(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  if (discovery_status_ == NOT_DISCOVERING) {
+    error_callback.Run();
+    return;
+  }
+  on_stop_discovery_callbacks_.push_back(callback);
+  MaybePostStopDiscoveryTask();
 }
 
-BluetoothDevice* BluetoothAdapterWin::GetDevice(const std::string& address) {
-  NOTIMPLEMENTED();
-  return NULL;
+void BluetoothAdapterWin::DiscoveryStarted(bool success) {
+  discovery_status_ = success ? DISCOVERING : NOT_DISCOVERING;
+  for (std::vector<std::pair<base::Closure, ErrorCallback> >::const_iterator
+       iter = on_start_discovery_callbacks_.begin();
+       iter != on_start_discovery_callbacks_.end();
+       ++iter) {
+    if (success)
+      ui_task_runner_->PostTask(FROM_HERE, iter->first);
+    else
+      ui_task_runner_->PostTask(FROM_HERE, iter->second);
+  }
+  num_discovery_listeners_ = on_start_discovery_callbacks_.size();
+  on_start_discovery_callbacks_.clear();
+
+  if (success) {
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterDiscoveringChanged(this, true));
+
+    // If there are stop discovery requests, post the stop discovery again.
+    MaybePostStopDiscoveryTask();
+  } else if (!on_stop_discovery_callbacks_.empty()) {
+    // If there are stop discovery requests but start discovery has failed,
+    // notify that stop discovery has been complete.
+    DiscoveryStopped();
+  }
 }
 
-const BluetoothDevice* BluetoothAdapterWin::GetDevice(
-    const std::string& address) const {
-  NOTIMPLEMENTED();
-  return NULL;
+void BluetoothAdapterWin::DiscoveryStopped() {
+  bool was_discovering = IsDiscovering();
+  discovery_status_ = NOT_DISCOVERING;
+  for (std::vector<base::Closure>::const_iterator iter =
+           on_stop_discovery_callbacks_.begin();
+       iter != on_stop_discovery_callbacks_.end();
+       ++iter) {
+    ui_task_runner_->PostTask(FROM_HERE, *iter);
+  }
+  num_discovery_listeners_ = 0;
+  on_stop_discovery_callbacks_.clear();
+  ScanningChanged(false);
+  if (was_discovering)
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterDiscoveringChanged(this, false));
+
+  // If there are start discovery requests, post the start discovery again.
+  MaybePostStartDiscoveryTask();
 }
 
 void BluetoothAdapterWin::ReadLocalOutOfBandPairingData(
@@ -78,4 +155,130 @@
   NOTIMPLEMENTED();
 }
 
+void BluetoothAdapterWin::AdapterStateChanged(
+    const BluetoothTaskManagerWin::AdapterState& state) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  name_ = state.name;
+  bool was_present = IsPresent();
+  bool is_present = !state.address.empty();
+  address_ = state.address;
+  if (was_present != is_present) {
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterPresentChanged(this, is_present));
+  }
+  if (powered_ != state.powered) {
+    powered_ = state.powered;
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterPoweredChanged(this, powered_));
+  }
+  if (!initialized_) {
+    initialized_ = true;
+    init_callback_.Run();
+  }
+}
+
+void BluetoothAdapterWin::ScanningChanged(bool scanning) {
+  if (scanning_ != scanning) {
+    scanning_ = scanning;
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      AdapterScanningChanged(this, scanning_));
+  }
+}
+
+void BluetoothAdapterWin::DevicesDiscovered(
+    const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) {
+  std::hash_set<std::string> device_address_list;
+  for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter =
+           devices.begin();
+       iter != devices.end();
+       ++iter) {
+    device_address_list.insert((*iter)->address);
+    DevicesMap::iterator found_device_iter = devices_.find((*iter)->address);
+
+    if (found_device_iter == devices_.end()) {
+      devices_[(*iter)->address] = new BluetoothDeviceWin(**iter);
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceAdded(this, devices_[(*iter)->address]));
+      continue;
+    }
+    BluetoothDeviceWin* device_win =
+        static_cast<BluetoothDeviceWin*>(found_device_iter->second);
+    if (device_win->device_fingerprint() !=
+        BluetoothDeviceWin::ComputeDeviceFingerprint(**iter)) {
+      devices_[(*iter)->address] = new BluetoothDeviceWin(**iter);
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceChanged(this, devices_[(*iter)->address]));
+      delete device_win;
+    }
+  }
+
+  DevicesMap::iterator device_iter = devices_.begin();
+  while (device_iter != devices_.end()) {
+    if (device_address_list.find(device_iter->first) !=
+        device_address_list.end()) {
+      ++device_iter;
+      continue;
+    }
+    if (device_iter->second->IsConnected() || device_iter->second->IsPaired()) {
+      BluetoothDeviceWin* device_win =
+          static_cast<BluetoothDeviceWin*>(device_iter->second);
+      device_win->SetVisible(false);
+      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                        DeviceChanged(this, device_win));
+      ++device_iter;
+      continue;
+    }
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      DeviceRemoved(this, device_iter->second));
+    delete device_iter->second;
+    device_iter = devices_.erase(device_iter);
+  }
+}
+
+void BluetoothAdapterWin::TrackDefaultAdapter() {
+  ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+  task_manager_ =
+      new BluetoothTaskManagerWin(ui_task_runner_);
+  task_manager_->AddObserver(this);
+  task_manager_->Initialize();
+}
+
+void BluetoothAdapterWin::TrackTestAdapter(
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+    scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) {
+  ui_task_runner_ = ui_task_runner;
+  task_manager_ =
+      new BluetoothTaskManagerWin(ui_task_runner_);
+  task_manager_->AddObserver(this);
+  task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner);
+}
+
+void BluetoothAdapterWin::MaybePostStartDiscoveryTask() {
+  if (discovery_status_ == NOT_DISCOVERING &&
+      !on_start_discovery_callbacks_.empty()) {
+    discovery_status_ = DISCOVERY_STARTING;
+    task_manager_->PostStartDiscoveryTask();
+  }
+}
+
+void BluetoothAdapterWin::MaybePostStopDiscoveryTask() {
+  if (discovery_status_ != DISCOVERING)
+    return;
+
+  if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) {
+    for (std::vector<base::Closure>::const_iterator iter =
+             on_stop_discovery_callbacks_.begin();
+         iter != on_stop_discovery_callbacks_.end();
+         ++iter) {
+      ui_task_runner_->PostTask(FROM_HERE, *iter);
+    }
+    num_discovery_listeners_ -= on_stop_discovery_callbacks_.size();
+    on_stop_discovery_callbacks_.clear();
+    return;
+  }
+
+  discovery_status_ = DISCOVERY_STOPPING;
+  task_manager_->PostStopDiscoveryTask();
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h
index de76b18..76581d9 100644
--- a/device/bluetooth/bluetooth_adapter_win.h
+++ b/device/bluetooth/bluetooth_adapter_win.h
@@ -6,19 +6,37 @@
 #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_WIN_H_
 
 #include <string>
+#include <utility>
+#include <vector>
 
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+
+namespace base {
+
+class SequencedTaskRunner;
+
+}  // namespace base
 
 namespace device {
 
 class BluetoothAdapterFactory;
+class BluetoothAdapterWinTest;
 class BluetoothDevice;
 
-class BluetoothAdapterWin : public BluetoothAdapter {
+class BluetoothAdapterWin : public BluetoothAdapter,
+                            public BluetoothTaskManagerWin::Observer {
+ public:
+  typedef base::Callback<void()> InitCallback;
+
   // BluetoothAdapter override
   virtual void AddObserver(BluetoothAdapter::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(BluetoothAdapter::Observer* observer) OVERRIDE;
+  virtual bool IsInitialized() const OVERRIDE;
   virtual bool IsPresent() const OVERRIDE;
   virtual bool IsPowered() const OVERRIDE;
   virtual void SetPowered(
@@ -26,24 +44,69 @@
       const base::Closure& callback,
       const ErrorCallback& error_callback) OVERRIDE;
   virtual bool IsDiscovering() const OVERRIDE;
-  virtual void SetDiscovering(
-      bool discovering,
+  virtual bool IsScanning() const OVERRIDE;
+
+  virtual void StartDiscovering(
       const base::Closure& callback,
       const ErrorCallback& error_callback) OVERRIDE;
-  virtual ConstDeviceList GetDevices() const OVERRIDE;
-  virtual BluetoothDevice* GetDevice(const std::string& address) OVERRIDE;
-  virtual const BluetoothDevice* GetDevice(
-      const std::string& address) const OVERRIDE;
+  virtual void StopDiscovering(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
   virtual void ReadLocalOutOfBandPairingData(
       const BluetoothOutOfBandPairingDataCallback& callback,
       const ErrorCallback& error_callback) OVERRIDE;
 
- private:
-  friend class device::BluetoothAdapterFactory;
+  // BluetoothTaskManagerWin::Observer override
+  virtual void AdapterStateChanged(
+      const BluetoothTaskManagerWin::AdapterState& state) OVERRIDE;
+  virtual void DiscoveryStarted(bool success) OVERRIDE;
+  virtual void DiscoveryStopped() OVERRIDE;
+  virtual void ScanningChanged(bool scanning) OVERRIDE;
+  virtual void DevicesDiscovered(
+      const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices)
+          OVERRIDE;
 
-  BluetoothAdapterWin();
+ private:
+  friend class BluetoothAdapterFactory;
+  friend class BluetoothAdapterWinTest;
+
+  enum DiscoveryStatus {
+    NOT_DISCOVERING,
+    DISCOVERY_STARTING,
+    DISCOVERING,
+    DISCOVERY_STOPPING
+  };
+
+  explicit BluetoothAdapterWin(const InitCallback& init_callback);
   virtual ~BluetoothAdapterWin();
 
+  void TrackDefaultAdapter();
+  void TrackTestAdapter(
+      scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+      scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner);
+
+  void MaybePostStartDiscoveryTask();
+  void MaybePostStopDiscoveryTask();
+
+  InitCallback init_callback_;
+  bool initialized_;
+  bool powered_;
+  DiscoveryStatus discovery_status_;
+  bool scanning_;
+
+  std::vector<std::pair<base::Closure, ErrorCallback> >
+      on_start_discovery_callbacks_;
+  std::vector<base::Closure> on_stop_discovery_callbacks_;
+  size_t num_discovery_listeners_;
+
+  scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
+  scoped_refptr<BluetoothTaskManagerWin> task_manager_;
+
+  base::ThreadChecker thread_checker_;
+
+  // List of observers interested in event notifications from us.
+  ObserverList<BluetoothAdapter::Observer> observers_;
+
   // NOTE: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<BluetoothAdapterWin> weak_ptr_factory_;
diff --git a/device/bluetooth/bluetooth_adapter_win_unittest.cc b/device/bluetooth/bluetooth_adapter_win_unittest.cc
new file mode 100644
index 0000000..91887c4
--- /dev/null
+++ b/device/bluetooth/bluetooth_adapter_win_unittest.cc
@@ -0,0 +1,576 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/test_simple_task_runner.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_adapter_win.h"
+#include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kAdapterAddress[] = "Bluetooth Adapter Address";
+const char kAdapterName[] = "Bluetooth Adapter Name";
+
+
+void MakeDeviceState(const std::string& name,
+                     const std::string& address,
+                     device::BluetoothTaskManagerWin::DeviceState* state) {
+  state->name = name;
+  state->address = address;
+  state->bluetooth_class = 0;
+  state->authenticated = false;
+  state->connected = false;
+}
+
+class AdapterObserver : public device::BluetoothAdapter::Observer {
+ public:
+  AdapterObserver() {
+    Clear();
+  }
+
+  void Clear() {
+    num_present_changed_ = 0;
+    num_powered_changed_ = 0;
+    num_discovering_changed_ = 0;
+    num_scanning_changed_ = 0;
+    num_device_added_ = 0;
+    num_device_changed_ = 0;
+    num_device_removed_ = 0;
+  }
+
+  virtual void AdapterPresentChanged(
+      device::BluetoothAdapter* adapter, bool present) OVERRIDE {
+    num_present_changed_++;
+  }
+
+  virtual void AdapterPoweredChanged(
+      device::BluetoothAdapter* adapter, bool powered) OVERRIDE {
+    num_powered_changed_++;
+  }
+
+  virtual void AdapterDiscoveringChanged(
+      device::BluetoothAdapter* adapter, bool discovering) OVERRIDE {
+    num_discovering_changed_++;
+  }
+
+  virtual void AdapterScanningChanged(
+      device::BluetoothAdapter* adapter, bool scanning) OVERRIDE {
+    num_scanning_changed_++;
+  }
+
+  virtual void DeviceAdded(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_added_++;
+  }
+
+  virtual void DeviceChanged(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_changed_++;
+  }
+
+  virtual void DeviceRemoved(
+      device::BluetoothAdapter* adapter,
+      device::BluetoothDevice* device) OVERRIDE {
+    num_device_removed_++;
+  }
+
+  int num_present_changed() const {
+    return num_present_changed_;
+  }
+
+  int num_powered_changed() const {
+    return num_powered_changed_;
+  }
+
+  int num_discovering_changed() const {
+    return num_discovering_changed_;
+  }
+
+  int num_scanning_changed() const {
+    return num_scanning_changed_;
+  }
+
+  int num_device_added() const {
+    return num_device_added_;
+  }
+
+  int num_device_changed() const {
+    return num_device_changed_;
+  }
+
+  int num_device_removed() const {
+    return num_device_removed_;
+  }
+
+ private:
+  int num_present_changed_;
+  int num_powered_changed_;
+  int num_discovering_changed_;
+  int num_scanning_changed_;
+  int num_device_added_;
+  int num_device_changed_;
+  int num_device_removed_;
+};
+
+}  // namespace
+
+namespace device {
+
+class BluetoothAdapterWinTest : public testing::Test {
+ public:
+  BluetoothAdapterWinTest()
+      : ui_task_runner_(new base::TestSimpleTaskRunner()),
+        bluetooth_task_runner_(new base::TestSimpleTaskRunner()),
+        adapter_(new BluetoothAdapterWin(
+          base::Bind(&BluetoothAdapterWinTest::RunInitCallback,
+                     base::Unretained(this)))),
+        adapter_win_(static_cast<BluetoothAdapterWin*>(adapter_.get())),
+        init_callback_called_(false) {
+    adapter_win_->TrackTestAdapter(ui_task_runner_,
+                                   bluetooth_task_runner_);
+  }
+
+  virtual void SetUp() OVERRIDE {
+    adapter_win_->AddObserver(&adapter_observer_);
+    num_start_discovery_callbacks_ = 0;
+    num_start_discovery_error_callbacks_ = 0;
+    num_stop_discovery_callbacks_ = 0;
+    num_stop_discovery_error_callbacks_ = 0;
+  }
+
+  virtual void TearDown() OVERRIDE {
+    adapter_win_->RemoveObserver(&adapter_observer_);
+  }
+
+  void RunInitCallback() {
+    init_callback_called_ = true;
+  }
+
+  void IncrementNumStartDiscoveryCallbacks() {
+    num_start_discovery_callbacks_++;
+  }
+
+  void IncrementNumStartDiscoveryErrorCallbacks() {
+    num_start_discovery_error_callbacks_++;
+  }
+
+  void IncrementNumStopDiscoveryCallbacks() {
+    num_stop_discovery_callbacks_++;
+  }
+
+  void IncrementNumStopDiscoveryErrorCallbacks() {
+    num_stop_discovery_error_callbacks_++;
+  }
+
+ protected:
+  scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;
+  scoped_refptr<base::TestSimpleTaskRunner> bluetooth_task_runner_;
+  scoped_refptr<BluetoothAdapter> adapter_;
+  BluetoothAdapterWin* adapter_win_;
+  AdapterObserver adapter_observer_;
+  bool init_callback_called_;
+  int num_start_discovery_callbacks_;
+  int num_start_discovery_error_callbacks_;
+  int num_stop_discovery_callbacks_;
+  int num_stop_discovery_error_callbacks_;
+};
+
+TEST_F(BluetoothAdapterWinTest, AdapterNotPresent) {
+  BluetoothTaskManagerWin::AdapterState state;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_FALSE(adapter_win_->IsPresent());
+}
+
+TEST_F(BluetoothAdapterWinTest, AdapterPresent) {
+  BluetoothTaskManagerWin::AdapterState state;
+  state.address = kAdapterAddress;
+  state.name = kAdapterName;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_TRUE(adapter_win_->IsPresent());
+}
+
+TEST_F(BluetoothAdapterWinTest, AdapterPresentChanged) {
+  BluetoothTaskManagerWin::AdapterState state;
+  state.address = kAdapterAddress;
+  state.name = kAdapterName;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_EQ(1, adapter_observer_.num_present_changed());
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_EQ(1, adapter_observer_.num_present_changed());
+  BluetoothTaskManagerWin::AdapterState empty_state;
+  adapter_win_->AdapterStateChanged(empty_state);
+  EXPECT_EQ(2, adapter_observer_.num_present_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, AdapterPoweredChanged) {
+  BluetoothTaskManagerWin::AdapterState state;
+  state.powered = true;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_EQ(1, adapter_observer_.num_powered_changed());
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_EQ(1, adapter_observer_.num_powered_changed());
+  state.powered = false;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_EQ(2, adapter_observer_.num_powered_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, AdapterInitialized) {
+  EXPECT_FALSE(adapter_win_->IsInitialized());
+  EXPECT_FALSE(init_callback_called_);
+  BluetoothTaskManagerWin::AdapterState state;
+  adapter_win_->AdapterStateChanged(state);
+  EXPECT_TRUE(adapter_win_->IsInitialized());
+  EXPECT_TRUE(init_callback_called_);
+}
+
+TEST_F(BluetoothAdapterWinTest, SingleStartDiscovery) {
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->StartDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  EXPECT_TRUE(ui_task_runner_->GetPendingTasks().empty());
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(0, num_start_discovery_callbacks_);
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_start_discovery_callbacks_);
+  EXPECT_EQ(1, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, SingleStartDiscoveryFailure) {
+  adapter_win_->StartDiscovering(
+      base::Closure(),
+      base::Bind(
+          &BluetoothAdapterWinTest::IncrementNumStartDiscoveryErrorCallbacks,
+          base::Unretained(this)));
+  adapter_win_->DiscoveryStarted(false);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_start_discovery_error_callbacks_);
+  EXPECT_EQ(0, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, MultipleStartDiscoveries) {
+  bluetooth_task_runner_->ClearPendingTasks();
+  int num_discoveries = 5;
+  for (int i = 0; i < num_discoveries; i++) {
+    adapter_win_->StartDiscovering(
+        base::Bind(
+            &BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+            base::Unretained(this)),
+        BluetoothAdapter::ErrorCallback());
+    EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+  }
+  EXPECT_TRUE(ui_task_runner_->GetPendingTasks().empty());
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(0, num_start_discovery_callbacks_);
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  EXPECT_EQ(num_discoveries, num_start_discovery_callbacks_);
+  EXPECT_EQ(1, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, MultipleStartDiscoveriesFailure) {
+  int num_discoveries = 5;
+  for (int i = 0; i < num_discoveries; i++) {
+    adapter_win_->StartDiscovering(
+        base::Closure(),
+        base::Bind(
+            &BluetoothAdapterWinTest::IncrementNumStartDiscoveryErrorCallbacks,
+            base::Unretained(this)));
+  }
+  adapter_win_->DiscoveryStarted(false);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(num_discoveries, num_start_discovery_error_callbacks_);
+  EXPECT_EQ(0, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, MultipleStartDiscoveriesAfterDiscovering) {
+  adapter_win_->StartDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_start_discovery_callbacks_);
+
+  bluetooth_task_runner_->ClearPendingTasks();
+  for (int i = 0; i < 5; i++) {
+    int num_start_discovery_callbacks = num_start_discovery_callbacks_;
+    adapter_win_->StartDiscovering(
+        base::Bind(
+           &BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+           base::Unretained(this)),
+        BluetoothAdapter::ErrorCallback());
+    EXPECT_TRUE(adapter_->IsDiscovering());
+    EXPECT_TRUE(bluetooth_task_runner_->GetPendingTasks().empty());
+    EXPECT_TRUE(ui_task_runner_->GetPendingTasks().empty());
+    EXPECT_EQ(num_start_discovery_callbacks + 1,
+              num_start_discovery_callbacks_);
+  }
+  EXPECT_EQ(1, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, StartDiscoveryAfterDiscoveringFailure) {
+  adapter_win_->StartDiscovering(
+      base::Closure(),
+      base::Bind(
+          &BluetoothAdapterWinTest::IncrementNumStartDiscoveryErrorCallbacks,
+          base::Unretained(this)));
+  adapter_win_->DiscoveryStarted(false);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_start_discovery_error_callbacks_);
+
+  adapter_win_->StartDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_start_discovery_callbacks_);
+}
+
+TEST_F(BluetoothAdapterWinTest, SingleStopDiscovery) {
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->ClearPendingTasks();
+  adapter_win_->StopDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  EXPECT_EQ(0, num_stop_discovery_callbacks_);
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->DiscoveryStopped();
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(1, num_stop_discovery_callbacks_);
+  EXPECT_TRUE(bluetooth_task_runner_->GetPendingTasks().empty());
+  EXPECT_EQ(2, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, MultipleStopDiscoveries) {
+  int num_discoveries = 5;
+  for (int i = 0; i < num_discoveries; i++) {
+    adapter_win_->StartDiscovering(
+        base::Closure(), BluetoothAdapter::ErrorCallback());
+  }
+  adapter_win_->DiscoveryStarted(true);
+  ui_task_runner_->ClearPendingTasks();
+  bluetooth_task_runner_->ClearPendingTasks();
+  for (int i = 0; i < num_discoveries - 1; i++) {
+    adapter_win_->StopDiscovering(
+        base::Bind(&BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+                   base::Unretained(this)),
+        BluetoothAdapter::ErrorCallback());
+    EXPECT_TRUE(bluetooth_task_runner_->GetPendingTasks().empty());
+    ui_task_runner_->RunPendingTasks();
+    EXPECT_EQ(i + 1, num_stop_discovery_callbacks_);
+  }
+  adapter_win_->StopDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  adapter_win_->DiscoveryStopped();
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  EXPECT_EQ(num_discoveries, num_stop_discovery_callbacks_);
+  EXPECT_EQ(2, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest,
+       StartDiscoveryAndStartDiscoveryAndStopDiscoveries) {
+  adapter_win_->StartDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  adapter_win_->StartDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  ui_task_runner_->ClearPendingTasks();
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->StopDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  EXPECT_TRUE(bluetooth_task_runner_->GetPendingTasks().empty());
+  adapter_win_->StopDiscovering(
+      base::Bind(&BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+                 base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+}
+
+TEST_F(BluetoothAdapterWinTest,
+       StartDiscoveryAndStopDiscoveryAndStartDiscovery) {
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  EXPECT_TRUE(adapter_->IsDiscovering());
+  adapter_win_->StopDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStopped();
+  EXPECT_FALSE(adapter_->IsDiscovering());
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  EXPECT_TRUE(adapter_->IsDiscovering());
+}
+
+TEST_F(BluetoothAdapterWinTest, StartDiscoveryBeforeDiscoveryStopped) {
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->DiscoveryStarted(true);
+  adapter_win_->StopDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->DiscoveryStopped();
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+}
+
+TEST_F(BluetoothAdapterWinTest, StopDiscoveryWithoutStartDiscovery) {
+  adapter_win_->StopDiscovering(
+      base::Closure(),
+      base::Bind(
+          &BluetoothAdapterWinTest::IncrementNumStopDiscoveryErrorCallbacks,
+          base::Unretained(this)));
+  EXPECT_EQ(1, num_stop_discovery_error_callbacks_);
+}
+
+TEST_F(BluetoothAdapterWinTest, StopDiscoveryBeforeDiscoveryStarted) {
+  adapter_win_->StartDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  adapter_win_->StopDiscovering(
+      base::Closure(), BluetoothAdapter::ErrorCallback());
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->DiscoveryStarted(true);
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+}
+
+TEST_F(BluetoothAdapterWinTest, StartAndStopBeforeDiscoveryStarted) {
+  int num_expected_start_discoveries = 3;
+  int num_expected_stop_discoveries = 2;
+  for (int i = 0; i < num_expected_start_discoveries; i++) {
+    adapter_win_->StartDiscovering(
+        base::Bind(
+            &BluetoothAdapterWinTest::IncrementNumStartDiscoveryCallbacks,
+            base::Unretained(this)),
+        BluetoothAdapter::ErrorCallback());
+  }
+  for (int i = 0; i < num_expected_stop_discoveries; i++) {
+    adapter_win_->StopDiscovering(
+        base::Bind(
+            &BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+            base::Unretained(this)),
+        BluetoothAdapter::ErrorCallback());
+  }
+  bluetooth_task_runner_->ClearPendingTasks();
+  adapter_win_->DiscoveryStarted(true);
+  EXPECT_TRUE(bluetooth_task_runner_->GetPendingTasks().empty());
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_EQ(num_expected_start_discoveries, num_start_discovery_callbacks_);
+  EXPECT_EQ(num_expected_stop_discoveries, num_stop_discovery_callbacks_);
+}
+
+TEST_F(BluetoothAdapterWinTest, StopDiscoveryBeforeDiscoveryStartedAndFailed) {
+  adapter_win_->StartDiscovering(
+      base::Closure(),
+      base::Bind(
+          &BluetoothAdapterWinTest::IncrementNumStartDiscoveryErrorCallbacks,
+          base::Unretained(this)));
+  adapter_win_->StopDiscovering(
+      base::Bind(
+          &BluetoothAdapterWinTest::IncrementNumStopDiscoveryCallbacks,
+          base::Unretained(this)),
+      BluetoothAdapter::ErrorCallback());
+  ui_task_runner_->ClearPendingTasks();
+  adapter_win_->DiscoveryStarted(false);
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_EQ(1, num_start_discovery_error_callbacks_);
+  EXPECT_EQ(1, num_stop_discovery_callbacks_);
+  EXPECT_EQ(0, adapter_observer_.num_discovering_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, ScanningChanged) {
+  adapter_win_->ScanningChanged(false);
+  EXPECT_EQ(0, adapter_observer_.num_scanning_changed());
+  adapter_win_->ScanningChanged(true);
+  EXPECT_EQ(1, adapter_observer_.num_scanning_changed());
+  adapter_win_->ScanningChanged(true);
+  EXPECT_EQ(1, adapter_observer_.num_scanning_changed());
+  adapter_win_->ScanningChanged(false);
+  EXPECT_EQ(2, adapter_observer_.num_scanning_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, ScanningFalseOnDiscoveryStopped) {
+  adapter_win_->ScanningChanged(true);
+  adapter_win_->DiscoveryStopped();
+  EXPECT_EQ(2, adapter_observer_.num_scanning_changed());
+}
+
+TEST_F(BluetoothAdapterWinTest, DevicesDiscovered) {
+  BluetoothTaskManagerWin::DeviceState* android_phone_state =
+      new BluetoothTaskManagerWin::DeviceState();
+  MakeDeviceState("phone", "android phone address", android_phone_state);
+  BluetoothTaskManagerWin::DeviceState* laptop_state =
+      new BluetoothTaskManagerWin::DeviceState();
+  MakeDeviceState("laptop", "laptop address", laptop_state);
+  BluetoothTaskManagerWin::DeviceState* iphone_state =
+      new BluetoothTaskManagerWin::DeviceState();
+  MakeDeviceState("phone", "iphone address", iphone_state);
+  ScopedVector<BluetoothTaskManagerWin::DeviceState> devices;
+  devices.push_back(android_phone_state);
+  devices.push_back(laptop_state);
+  devices.push_back(iphone_state);
+
+  adapter_win_->DevicesDiscovered(devices);
+  EXPECT_EQ(3, adapter_observer_.num_device_added());
+  adapter_observer_.Clear();
+
+  iphone_state->name = "apple phone";
+  adapter_win_->DevicesDiscovered(devices);
+  EXPECT_EQ(0, adapter_observer_.num_device_added());
+  EXPECT_EQ(1, adapter_observer_.num_device_changed());
+  EXPECT_EQ(0, adapter_observer_.num_device_removed());
+  adapter_observer_.Clear();
+
+  laptop_state->address = "notebook address";
+  laptop_state->connected = true;
+  adapter_win_->DevicesDiscovered(devices);
+  EXPECT_EQ(1, adapter_observer_.num_device_added());
+  EXPECT_EQ(0, adapter_observer_.num_device_changed());
+  EXPECT_EQ(1, adapter_observer_.num_device_removed());
+  adapter_observer_.Clear();
+
+  devices.clear();
+  adapter_win_->DevicesDiscovered(devices);
+
+  EXPECT_EQ(2, adapter_observer_.num_device_removed());
+  EXPECT_EQ(1, adapter_observer_.num_device_changed());
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_device.cc b/device/bluetooth/bluetooth_device.cc
index 378c6ce..a2249c5 100644
--- a/device/bluetooth/bluetooth_device.cc
+++ b/device/bluetooth/bluetooth_device.cc
@@ -4,17 +4,27 @@
 
 #include "device/bluetooth/bluetooth_device.h"
 
+#include <string>
+
 #include "base/utf_string_conversions.h"
-#include "grit/generated_resources.h"
+#include "device/bluetooth/bluetooth_utils.h"
+#include "grit/device_bluetooth_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace device {
 
+// static
+bool BluetoothDevice::IsUUIDValid(const std::string& uuid) {
+  return !bluetooth_utils::CanonicalUuid(uuid).empty();
+}
+
 BluetoothDevice::BluetoothDevice()
     : bluetooth_class_(0),
       visible_(false),
       bonded_(false),
-      connected_(false) {
+      connected_(false),
+      connectable_(true),
+      connecting_(false) {
 }
 
 BluetoothDevice::~BluetoothDevice() {
@@ -167,4 +177,25 @@
   return connected_;
 }
 
+bool BluetoothDevice::IsConnectable() const {
+  return connectable_;
+}
+
+bool BluetoothDevice::IsConnecting() const {
+  return connecting_;
+}
+
+bool BluetoothDevice::ProvidesServiceWithUUID(
+    const std::string& uuid) const {
+  std::string canonical_uuid = bluetooth_utils::CanonicalUuid(uuid);
+  const BluetoothDevice::ServiceList& services = GetServices();
+  for (BluetoothDevice::ServiceList::const_iterator iter = services.begin();
+       iter != services.end();
+       ++iter) {
+    if (bluetooth_utils::CanonicalUuid(*iter) == canonical_uuid)
+      return true;
+  }
+  return false;
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 90e420b..b7dc9e2 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -9,8 +9,9 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "base/string16.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_vector.h"
+#include "base/string16.h"
 
 namespace device {
 
@@ -52,6 +53,19 @@
     DEVICE_KEYBOARD_MOUSE_COMBO
   };
 
+  // Possible errors passed back to an error callback function in case of a
+  // failed call to Connect().
+  enum ConnectErrorCode {
+    ERROR_UNKNOWN,
+    ERROR_INPROGRESS,
+    ERROR_FAILED,
+    ERROR_AUTH_FAILED,
+    ERROR_AUTH_CANCELED,
+    ERROR_AUTH_REJECTED,
+    ERROR_AUTH_TIMEOUT,
+    ERROR_UNSUPPORTED_DEVICE
+  };
+
   // Interface for observing changes from bluetooth devices.
   class Observer {
    public:
@@ -131,6 +145,10 @@
     virtual void DismissDisplayOrConfirm() = 0;
   };
 
+  // Returns true if uuid is in a a valid canonical format
+  // (see utils::CanonicalUuid).
+  static bool IsUUIDValid(const std::string& uuid);
+
   virtual ~BluetoothDevice();
 
   // Returns the Bluetooth of address the device. This should be used as
@@ -165,6 +183,15 @@
   // and at least one service available for use.
   virtual bool IsConnected() const;
 
+  // Indicates whether the bonded device accepts connections initiated from the
+  // adapter. This value is undefined for unbonded devices.
+  virtual bool IsConnectable() const;
+
+  // Indicates whether there is a call to Connect() ongoing. For this attribute,
+  // we consider a call is ongoing if none of the callbacks passed to Connect()
+  // were called after the corresponding call to Connect().
+  virtual bool IsConnecting() const;
+
   // Returns the services (as UUID strings) that this device provides.
   typedef std::vector<std::string> ServiceList;
   virtual const ServiceList& GetServices() const = 0;
@@ -173,6 +200,11 @@
   // is called, in the success case the callback is simply not called.
   typedef base::Callback<void()> ErrorCallback;
 
+  // The ConnectErrorCallback is used for methods that can fail with an error,
+  // passed back as an error code argument to this callback.
+  // In the success case this callback is not called.
+  typedef base::Callback<void(enum ConnectErrorCode)> ConnectErrorCallback;
+
   // Returns the services (as BluetoothServiceRecord objects) that this device
   // provides.
   typedef ScopedVector<BluetoothServiceRecord> ServiceRecordList;
@@ -180,9 +212,8 @@
   virtual void GetServiceRecords(const ServiceRecordsCallback& callback,
                                  const ErrorCallback& error_callback) = 0;
 
-  // Indicates whether this device provides the given service.  |uuid| should
-  // be in canonical form (see utils::CanonicalUuid).
-  virtual bool ProvidesServiceWithUUID(const std::string& uuid) const = 0;
+  // Indicates whether this device provides the given service.
+  virtual bool ProvidesServiceWithUUID(const std::string& uuid) const;
 
   // The ProvidesServiceCallback is used by ProvidesServiceWithName to indicate
   // whether or not a matching service was found.
@@ -222,9 +253,12 @@
   //
   // If the request fails, |error_callback| will be called; otherwise,
   // |callback| is called when the request is complete.
+  // After calling Connect, CancelPairing should be called to cancel the pairing
+  // process and release |pairing_delegate_| if user cancels the pairing and
+  // closes the pairing UI.
   virtual void Connect(PairingDelegate* pairing_delegate,
                        const base::Closure& callback,
-                       const ErrorCallback& error_callback) = 0;
+                       const ConnectErrorCallback& error_callback) = 0;
 
   // Sends the PIN code |pincode| to the remote device during pairing.
   //
@@ -246,7 +280,8 @@
   // Rejects a pairing or connection request from a remote device.
   virtual void RejectPairing() = 0;
 
-  // Cancels a pairing or connection attempt to a remote device.
+  // Cancels a pairing or connection attempt to a remote device or release
+  // |pairing_deleage_| and |agent_|.
   virtual void CancelPairing() = 0;
 
   // Disconnects the device, terminating the low-level ACL connection
@@ -307,6 +342,16 @@
   bool bonded_;
   bool connected_;
 
+  // Indicates whether the device normally accepts connections initiated from
+  // the adapter once paired.
+  bool connectable_;
+
+  // Indicated whether the device is in a connecting status.
+  bool connecting_;
+
+  // The services (identified by UUIDs) that this device provides.
+  ServiceList service_uuids_;
+
  private:
   // Returns a localized string containing the device's bluetooth address and
   // a device type for display when |name_| is empty.
diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc
index 2a09cac..32f4d9f 100644
--- a/device/bluetooth/bluetooth_device_chromeos.cc
+++ b/device/bluetooth/bluetooth_device_chromeos.cc
@@ -28,6 +28,7 @@
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
 #include "device/bluetooth/bluetooth_service_record.h"
+#include "device/bluetooth/bluetooth_service_record_chromeos.h"
 #include "device/bluetooth/bluetooth_socket_chromeos.h"
 #include "device/bluetooth/bluetooth_utils.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -37,98 +38,113 @@
 using device::BluetoothServiceRecord;
 using device::BluetoothSocket;
 
+namespace {
+
+void DoNothingServiceRecordList(const BluetoothDevice::ServiceRecordList&) {}
+
+} // namespace
+
 namespace chromeos {
 
-BluetoothDeviceChromeOs::BluetoothDeviceChromeOs(
-    BluetoothAdapterChromeOs* adapter)
-  : BluetoothDevice(),
-    adapter_(adapter),
-    pairing_delegate_(NULL),
-    connecting_applications_counter_(0),
-    weak_ptr_factory_(this) {
+BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
+    BluetoothAdapterChromeOS* adapter)
+    : BluetoothDevice(),
+      adapter_(adapter),
+      pairing_delegate_(NULL),
+      connecting_applications_counter_(0),
+      connecting_calls_(0),
+      service_records_loaded_(false),
+      weak_ptr_factory_(this) {
 }
 
-BluetoothDeviceChromeOs::~BluetoothDeviceChromeOs() {
+BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
 }
 
-bool BluetoothDeviceChromeOs::IsPaired() const {
+bool BluetoothDeviceChromeOS::IsPaired() const {
   return !object_path_.value().empty();
 }
 
 const BluetoothDevice::ServiceList&
-BluetoothDeviceChromeOs::GetServices() const {
+BluetoothDeviceChromeOS::GetServices() const {
   return service_uuids_;
 }
 
-void BluetoothDeviceChromeOs::GetServiceRecords(
+void BluetoothDeviceChromeOS::GetServiceRecords(
     const ServiceRecordsCallback& callback,
     const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothDeviceClient()->
       DiscoverServices(
           object_path_,
           "",  // empty pattern to browse all services
-          base::Bind(&BluetoothDeviceChromeOs::CollectServiceRecordsCallback,
+          base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback,
                      weak_ptr_factory_.GetWeakPtr(),
                      callback,
-                     error_callback));
+                     base::Bind(
+                         &BluetoothDeviceChromeOS::OnGetServiceRecordsError,
+                         weak_ptr_factory_.GetWeakPtr(),
+                         callback,
+                         error_callback)));
 }
 
-bool BluetoothDeviceChromeOs::ProvidesServiceWithUUID(
-    const std::string& uuid) const {
-  const BluetoothDevice::ServiceList& services = GetServices();
-  for (BluetoothDevice::ServiceList::const_iterator iter = services.begin();
-       iter != services.end();
-       ++iter) {
-    if (device::bluetooth_utils::CanonicalUuid(*iter) == uuid)
-      return true;
-  }
-  return false;
-}
-
-void BluetoothDeviceChromeOs::ProvidesServiceWithName(
+void BluetoothDeviceChromeOS::ProvidesServiceWithName(
     const std::string& name,
     const ProvidesServiceCallback& callback) {
   GetServiceRecords(
-      base::Bind(&BluetoothDeviceChromeOs::SearchServicesForNameCallback,
+      base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameCallback,
                  weak_ptr_factory_.GetWeakPtr(),
                  name,
                  callback),
-      base::Bind(&BluetoothDeviceChromeOs::SearchServicesForNameErrorCallback,
+      base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback,
                  weak_ptr_factory_.GetWeakPtr(),
                  callback));
 }
 
-bool BluetoothDeviceChromeOs::ExpectingPinCode() const {
+bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
   return !pincode_callback_.is_null();
 }
 
-bool BluetoothDeviceChromeOs::ExpectingPasskey() const {
+bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
   return !passkey_callback_.is_null();
 }
 
-bool BluetoothDeviceChromeOs::ExpectingConfirmation() const {
+bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
   return !confirmation_callback_.is_null();
 }
 
-void BluetoothDeviceChromeOs::Connect(PairingDelegate* pairing_delegate,
-                                      const base::Closure& callback,
-                                      const ErrorCallback& error_callback) {
+void BluetoothDeviceChromeOS::Connect(
+    PairingDelegate* pairing_delegate,
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback) {
+  // This is safe because Connect() and its callbacks are called in the same
+  // thread.
+  connecting_calls_++;
+  connecting_ = !!connecting_calls_;
+  // Set the decrement to be issued when either callback is called.
+  base::Closure wrapped_callback = base::Bind(
+      &BluetoothDeviceChromeOS::OnConnectCallbackCalled,
+      weak_ptr_factory_.GetWeakPtr(),
+      callback);
+  ConnectErrorCallback wrapped_error_callback = base::Bind(
+      &BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled,
+      weak_ptr_factory_.GetWeakPtr(),
+      error_callback);
+
   if (IsPaired() || IsBonded() || IsConnected()) {
     // Connection to already paired or connected device.
-    ConnectApplications(callback, error_callback);
+    ConnectApplications(wrapped_callback, wrapped_error_callback);
 
   } else if (!pairing_delegate) {
     // No pairing delegate supplied, initiate low-security connection only.
     DBusThreadManager::Get()->GetBluetoothAdapterClient()->
         CreateDevice(adapter_->object_path_,
                      address_,
-                     base::Bind(&BluetoothDeviceChromeOs::ConnectCallback,
+                     base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
                                 weak_ptr_factory_.GetWeakPtr(),
-                                callback,
-                                error_callback),
-                     base::Bind(&BluetoothDeviceChromeOs::ConnectErrorCallback,
+                                wrapped_callback,
+                                wrapped_error_callback),
+                     base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
                                 weak_ptr_factory_.GetWeakPtr(),
-                                error_callback));
+                                wrapped_error_callback));
   } else {
     // Initiate high-security connection with pairing.
     DCHECK(!pairing_delegate_);
@@ -153,24 +169,24 @@
       agent_.reset(NULL);
     }
 
-    DVLOG(1) << "Pairing: " << address_;
+    VLOG(1) << "Pairing: " << address_;
     DBusThreadManager::Get()->GetBluetoothAdapterClient()->
         CreatePairedDevice(
             adapter_->object_path_,
             address_,
             agent_path,
             bluetooth_agent::kDisplayYesNoCapability,
-            base::Bind(&BluetoothDeviceChromeOs::ConnectCallback,
+            base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
                        weak_ptr_factory_.GetWeakPtr(),
-                       callback,
-                       error_callback),
-            base::Bind(&BluetoothDeviceChromeOs::ConnectErrorCallback,
+                       wrapped_callback,
+                       wrapped_error_callback),
+            base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
                        weak_ptr_factory_.GetWeakPtr(),
-                       error_callback));
+                       wrapped_error_callback));
   }
 }
 
-void BluetoothDeviceChromeOs::SetPinCode(const std::string& pincode) {
+void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
   if (!agent_.get() || pincode_callback_.is_null())
     return;
 
@@ -178,7 +194,7 @@
   pincode_callback_.Reset();
 }
 
-void BluetoothDeviceChromeOs::SetPasskey(uint32 passkey) {
+void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
   if (!agent_.get() || passkey_callback_.is_null())
     return;
 
@@ -186,7 +202,7 @@
   passkey_callback_.Reset();
 }
 
-void BluetoothDeviceChromeOs::ConfirmPairing() {
+void BluetoothDeviceChromeOS::ConfirmPairing() {
   if (!agent_.get() || confirmation_callback_.is_null())
     return;
 
@@ -194,7 +210,7 @@
   confirmation_callback_.Reset();
 }
 
-void BluetoothDeviceChromeOs::RejectPairing() {
+void BluetoothDeviceChromeOS::RejectPairing() {
   if (!agent_.get())
     return;
 
@@ -212,58 +228,73 @@
   }
 }
 
-void BluetoothDeviceChromeOs::CancelPairing() {
-  if (!agent_.get())
-    return;
+void BluetoothDeviceChromeOS::CancelPairing() {
+  bool have_callback = false;
+  if (agent_.get()) {
+    if (!pincode_callback_.is_null()) {
+      pincode_callback_.Run(CANCELLED, "");
+      pincode_callback_.Reset();
+      have_callback = true;
+    }
+    if (!passkey_callback_.is_null()) {
+      passkey_callback_.Run(CANCELLED, 0);
+      passkey_callback_.Reset();
+      have_callback = true;
+    }
+    if (!confirmation_callback_.is_null()) {
+      confirmation_callback_.Run(CANCELLED);
+      confirmation_callback_.Reset();
+      have_callback = true;
+    }
+  }
 
-  if (!pincode_callback_.is_null()) {
-    pincode_callback_.Run(CANCELLED, "");
-    pincode_callback_.Reset();
-  }
-  if (!passkey_callback_.is_null()) {
-    passkey_callback_.Run(CANCELLED, 0);
-    passkey_callback_.Reset();
-  }
-  if (!confirmation_callback_.is_null()) {
-    confirmation_callback_.Run(CANCELLED);
-    confirmation_callback_.Reset();
+  if (!have_callback) {
+    // User cancels the pairing process.
+    DBusThreadManager::Get()->GetBluetoothAdapterClient()->CancelDeviceCreation(
+        adapter_->object_path_,
+        address_,
+        base::Bind(&BluetoothDeviceChromeOS::OnCancelDeviceCreation,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    pairing_delegate_ = NULL;
+    agent_.reset();
   }
 }
 
-void BluetoothDeviceChromeOs::Disconnect(const base::Closure& callback,
+void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
                                          const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothDeviceClient()->
       Disconnect(object_path_,
-                 base::Bind(&BluetoothDeviceChromeOs::DisconnectCallback,
+                 base::Bind(&BluetoothDeviceChromeOS::DisconnectCallback,
                             weak_ptr_factory_.GetWeakPtr(),
                             callback,
                             error_callback));
 
 }
 
-void BluetoothDeviceChromeOs::Forget(const ErrorCallback& error_callback) {
+void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothAdapterClient()->
       RemoveDevice(adapter_->object_path_,
                    object_path_,
-                   base::Bind(&BluetoothDeviceChromeOs::ForgetCallback,
+                   base::Bind(&BluetoothDeviceChromeOS::ForgetCallback,
                               weak_ptr_factory_.GetWeakPtr(),
                               error_callback));
 }
 
-void BluetoothDeviceChromeOs::ConnectToService(const std::string& service_uuid,
+void BluetoothDeviceChromeOS::ConnectToService(const std::string& service_uuid,
                                                const SocketCallback& callback) {
   GetServiceRecords(
-      base::Bind(&BluetoothDeviceChromeOs::GetServiceRecordsForConnectCallback,
+      base::Bind(&BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback,
                  weak_ptr_factory_.GetWeakPtr(),
                  service_uuid,
                  callback),
       base::Bind(
-          &BluetoothDeviceChromeOs::GetServiceRecordsForConnectErrorCallback,
+          &BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback,
           weak_ptr_factory_.GetWeakPtr(),
           callback));
 }
 
-void BluetoothDeviceChromeOs::SetOutOfBandPairingData(
+void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
     const BluetoothOutOfBandPairingData& data,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
@@ -272,37 +303,37 @@
           object_path_,
           address(),
           data,
-          base::Bind(&BluetoothDeviceChromeOs::OnRemoteDataCallback,
+          base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
                      weak_ptr_factory_.GetWeakPtr(),
                      callback,
                      error_callback));
 }
 
-void BluetoothDeviceChromeOs::ClearOutOfBandPairingData(
+void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
   DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
       RemoveRemoteData(
           object_path_,
           address(),
-          base::Bind(&BluetoothDeviceChromeOs::OnRemoteDataCallback,
+          base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
                      weak_ptr_factory_.GetWeakPtr(),
                      callback,
                      error_callback));
 }
 
-void BluetoothDeviceChromeOs::SetObjectPath(
+void BluetoothDeviceChromeOS::SetObjectPath(
     const dbus::ObjectPath& object_path) {
   DCHECK(object_path_ == dbus::ObjectPath(""));
   object_path_ = object_path;
 }
 
-void BluetoothDeviceChromeOs::RemoveObjectPath() {
+void BluetoothDeviceChromeOS::RemoveObjectPath() {
   DCHECK(object_path_ != dbus::ObjectPath(""));
   object_path_ = dbus::ObjectPath("");
 }
 
-void BluetoothDeviceChromeOs::Update(
+void BluetoothDeviceChromeOS::Update(
     const BluetoothDeviceClient::Properties* properties,
     bool update_state) {
   std::string address = properties->address.value();
@@ -322,6 +353,13 @@
   }
 
   if (update_state) {
+    // When the device reconnects and we don't have any service records for it,
+    // try to update the cache or fail silently.
+    if (!service_records_loaded_ && !connected_ &&
+        properties->connected.value())
+      GetServiceRecords(base::Bind(&DoNothingServiceRecordList),
+                        base::Bind(&base::DoNothing));
+
     // BlueZ uses paired to mean link keys exchanged, whereas the Bluetooth
     // spec refers to this as bonded. Use the spec name for our interface.
     bonded_ = properties->paired.value();
@@ -329,11 +367,11 @@
   }
 }
 
-void BluetoothDeviceChromeOs::ConnectCallback(
+void BluetoothDeviceChromeOS::OnCreateDevice(
     const base::Closure& callback,
-    const ErrorCallback& error_callback,
+    const ConnectErrorCallback& error_callback,
     const dbus::ObjectPath& device_path) {
-  DVLOG(1) << "Connection successful: " << device_path.value();
+  VLOG(1) << "Connection successful: " << device_path.value();
   if (object_path_.value().empty()) {
     object_path_ = device_path;
   } else {
@@ -351,25 +389,50 @@
   DBusThreadManager::Get()->GetBluetoothDeviceClient()->
       GetProperties(object_path_)->trusted.Set(
           true,
-          base::Bind(&BluetoothDeviceChromeOs::OnSetTrusted,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback,
-                     error_callback));
+          base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
+                     weak_ptr_factory_.GetWeakPtr()));
 
-  // Connect application-layer protocols.
-  ConnectApplications(callback, error_callback);
+  // In parallel with the |trusted| property change, call GetServiceRecords to
+  // retrieve the SDP from the device and then, either on success or failure,
+  // call ConnectApplications.
+  GetServiceRecords(
+      base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback,
+                 error_callback),
+      base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 callback,
+                 error_callback));
 }
 
-void BluetoothDeviceChromeOs::ConnectErrorCallback(
-    const ErrorCallback& error_callback,
+void BluetoothDeviceChromeOS::OnCreateDeviceError(
+    const ConnectErrorCallback& error_callback,
     const std::string& error_name,
     const std::string& error_message) {
-  LOG(WARNING) << "Connection failed: " << address_
-               << ": " << error_name << ": " << error_message;
-  error_callback.Run();
+  // The default |error_code| is an unknown error.
+  ConnectErrorCode error_code = ERROR_UNKNOWN;
+
+  // Report any error in the log, even if we know the possible source of it.
+  LOG(WARNING) << "Connection failed (on CreatePairedDevice): "
+               << "\"" << name_ << "\" (" << address_ << "): "
+               << error_name << ": \"" << error_message << "\"";
+
+  // Determines the right error code from error_name, assuming the error name
+  // comes from CreatePairedDevice bluez function.
+  if (error_name == bluetooth_adapter::kErrorConnectionAttemptFailed) {
+    error_code = ERROR_FAILED;
+  } else if (error_name == bluetooth_adapter::kErrorAuthenticationFailed) {
+    error_code = ERROR_AUTH_FAILED;
+  } else if (error_name == bluetooth_adapter::kErrorAuthenticationRejected) {
+    error_code = ERROR_AUTH_REJECTED;
+  } else if (error_name == bluetooth_adapter::kErrorAuthenticationTimeout) {
+    error_code = ERROR_AUTH_TIMEOUT;
+  }
+  error_callback.Run(error_code);
 }
 
-void BluetoothDeviceChromeOs::CollectServiceRecordsCallback(
+void BluetoothDeviceChromeOS::CollectServiceRecordsCallback(
     const ServiceRecordsCallback& callback,
     const ErrorCallback& error_callback,
     const dbus::ObjectPath& device_path,
@@ -380,48 +443,95 @@
     return;
   }
 
-  ScopedVector<BluetoothServiceRecord> records;
+  // Update the cache. No other thread is executing a GetServiceRecords
+  // callback, so it is safe to delete the previous objects here.
+  service_records_.clear();
+  // TODO(deymo): Perhaps don't update the cache if the new SDP information is
+  // empty and we had something before. Some devices only answer this
+  // information while paired, and this callback could be called in any order if
+  // several calls to GetServiceRecords are made while initial pairing with the
+  // device. This requires more investigation.
   for (BluetoothDeviceClient::ServiceMap::const_iterator i =
       service_map.begin(); i != service_map.end(); ++i) {
-    records.push_back(
-        new BluetoothServiceRecord(address(), i->second));
+    service_records_.push_back(
+        new BluetoothServiceRecordChromeOS(address(), i->second));
   }
-  callback.Run(records);
+  service_records_loaded_ = true;
+
+  callback.Run(service_records_);
 }
 
-void BluetoothDeviceChromeOs::OnSetTrusted(const base::Closure& callback,
-                                           const ErrorCallback& error_callback,
-                                           bool success) {
-  if (success) {
-    callback.Run();
+void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
+  LOG_IF(WARNING, !success) << "Failed to set device as trusted: " << address_;
+}
+
+void BluetoothDeviceChromeOS::OnInitialGetServiceRecords(
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback,
+    const ServiceRecordList& list) {
+  // Connect application-layer protocols.
+  ConnectApplications(callback, error_callback);
+}
+
+void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError(
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback) {
+  // Ignore the error retrieving the service records and continue.
+  LOG(WARNING) << "Error retrieving SDP for " << address_ << " after pairing.";
+  // Connect application-layer protocols.
+  ConnectApplications(callback, error_callback);
+}
+
+void BluetoothDeviceChromeOS::OnGetServiceRecordsError(
+    const ServiceRecordsCallback& callback,
+    const ErrorCallback& error_callback) {
+  if (service_records_loaded_) {
+    callback.Run(service_records_);
   } else {
-    LOG(WARNING) << "Failed to set device as trusted: " << address_;
     error_callback.Run();
   }
 }
 
-void BluetoothDeviceChromeOs::ConnectApplications(
+void BluetoothDeviceChromeOS::OnConnectCallbackCalled(
+    const base::Closure& callback) {
+  // Update the connecting status.
+  connecting_calls_--;
+  connecting_ = !!connecting_calls_;
+  callback.Run();
+}
+
+void BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled(
+    const ConnectErrorCallback& error_callback,
+    enum ConnectErrorCode error_code) {
+  // Update the connecting status.
+  connecting_calls_--;
+  connecting_ = !!connecting_calls_;
+  error_callback.Run(error_code);
+}
+
+void BluetoothDeviceChromeOS::ConnectApplications(
     const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+    const ConnectErrorCallback& error_callback) {
   // Introspect the device object to determine supported applications.
   DBusThreadManager::Get()->GetIntrospectableClient()->
       Introspect(bluetooth_device::kBluetoothDeviceServiceName,
                  object_path_,
-                 base::Bind(&BluetoothDeviceChromeOs::OnIntrospect,
+                 base::Bind(&BluetoothDeviceChromeOS::OnIntrospect,
                             weak_ptr_factory_.GetWeakPtr(),
                             callback,
                             error_callback));
 }
 
-void BluetoothDeviceChromeOs::OnIntrospect(const base::Closure& callback,
-                                           const ErrorCallback& error_callback,
-                                           const std::string& service_name,
-                                           const dbus::ObjectPath& device_path,
-                                           const std::string& xml_data,
-                                           bool success) {
+void BluetoothDeviceChromeOS::OnIntrospect(
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback,
+    const std::string& service_name,
+    const dbus::ObjectPath& device_path,
+    const std::string& xml_data,
+    bool success) {
   if (!success) {
     LOG(WARNING) << "Failed to determine supported applications: " << address_;
-    error_callback.Run();
+    error_callback.Run(ERROR_UNKNOWN);
     return;
   }
 
@@ -441,11 +551,11 @@
       // Supports Input interface.
       DBusThreadManager::Get()->GetBluetoothInputClient()->
           Connect(object_path_,
-                  base::Bind(&BluetoothDeviceChromeOs::OnConnect,
+                  base::Bind(&BluetoothDeviceChromeOS::OnConnect,
                              weak_ptr_factory_.GetWeakPtr(),
                              callback,
                              *iter),
-                  base::Bind(&BluetoothDeviceChromeOs::OnConnectError,
+                  base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
                              weak_ptr_factory_.GetWeakPtr(),
                              error_callback, *iter));
     }
@@ -460,11 +570,11 @@
     callback.Run();
 }
 
-void BluetoothDeviceChromeOs::OnConnect(const base::Closure& callback,
+void BluetoothDeviceChromeOS::OnConnect(const base::Closure& callback,
                                         const std::string& interface_name,
                                         const dbus::ObjectPath& device_path) {
-  DVLOG(1) << "Application connection successful: " << device_path.value()
-           << ": " << interface_name;
+  VLOG(1) << "Application connection successful: " << device_path.value()
+          << ": " << interface_name;
 
   connecting_applications_counter_--;
   // |callback| should only be called once, meaning it cannot be called before
@@ -478,33 +588,56 @@
   }
 }
 
-void BluetoothDeviceChromeOs::OnConnectError(
-    const ErrorCallback& error_callback,
+void BluetoothDeviceChromeOS::OnConnectError(
+    const ConnectErrorCallback& error_callback,
     const std::string& interface_name,
     const dbus::ObjectPath& device_path,
     const std::string& error_name,
     const std::string& error_message) {
-  LOG(WARNING) << "Connection failed: " << address_ << ": " << interface_name
-               << ": " << error_name << ": " << error_message;
-  error_callback.Run();
+  // The default |error_code| is an unknown error.
+  ConnectErrorCode error_code = ERROR_UNKNOWN;
+
+  // Report any error in the log, even if we know the possible source of it.
+  LOG(WARNING) << "Connection failed (on Connect): "
+               << interface_name << ": "
+               << "\"" << name_ << "\" (" << address_ << "): "
+               << error_name << ": \"" << error_message << "\"";
+
+  // Determines the right error code from error_name, assuming the error name
+  // comes from Connect bluez function.
+  if (error_name == bluetooth_adapter::kErrorFailed) {
+    error_code = ERROR_FAILED;
+  } else if (error_name == bluetooth_adapter::kErrorInProgress) {
+    error_code = ERROR_INPROGRESS;
+  } else if (error_name == bluetooth_adapter::kErrorNotSupported) {
+    error_code = ERROR_UNSUPPORTED_DEVICE;
+  }
+
+  error_callback.Run(error_code);
 }
 
-void BluetoothDeviceChromeOs::DisconnectCallback(
+void BluetoothDeviceChromeOS::DisconnectCallback(
     const base::Closure& callback,
     const ErrorCallback& error_callback,
     const dbus::ObjectPath& device_path,
     bool success) {
   DCHECK(device_path == object_path_);
   if (success) {
-    DVLOG(1) << "Disconnection successful: " << address_;
+    VLOG(1) << "Disconnection successful: " << address_;
     callback.Run();
   } else {
-    LOG(WARNING) << "Disconnection failed: " << address_;
-    error_callback.Run();
+    if (connected_)  {
+      LOG(WARNING) << "Disconnection failed: " << address_;
+      error_callback.Run();
+    } else {
+      VLOG(1) << "Disconnection failed on a already disconnected device: "
+              << address_;
+      callback.Run();
+    }
   }
 }
 
-void BluetoothDeviceChromeOs::ForgetCallback(
+void BluetoothDeviceChromeOS::ForgetCallback(
     const ErrorCallback& error_callback,
     const dbus::ObjectPath& adapter_path,
     bool success) {
@@ -519,12 +652,19 @@
   }
 }
 
-void BluetoothDeviceChromeOs::SearchServicesForNameErrorCallback(
+void BluetoothDeviceChromeOS::OnCancelDeviceCreation(
+    const dbus::ObjectPath& adapter_path,
+    bool success) {
+  if (!success)
+    LOG(WARNING) << "CancelDeviceCreation failed: " << address_;
+}
+
+void BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback(
     const ProvidesServiceCallback& callback) {
   callback.Run(false);
 }
 
-void BluetoothDeviceChromeOs::SearchServicesForNameCallback(
+void BluetoothDeviceChromeOS::SearchServicesForNameCallback(
     const std::string& name,
     const ProvidesServiceCallback& callback,
     const ServiceRecordList& list) {
@@ -538,12 +678,12 @@
   callback.Run(false);
 }
 
-void BluetoothDeviceChromeOs::GetServiceRecordsForConnectErrorCallback(
+void BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback(
     const SocketCallback& callback) {
   callback.Run(NULL);
 }
 
-void BluetoothDeviceChromeOs::GetServiceRecordsForConnectCallback(
+void BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback(
     const std::string& service_uuid,
     const SocketCallback& callback,
     const ServiceRecordList& list) {
@@ -552,7 +692,7 @@
     if ((*i)->uuid() == service_uuid) {
       // If multiple service records are found, use the first one that works.
       scoped_refptr<BluetoothSocket> socket(
-          BluetoothSocketChromeOs::CreateBluetoothSocket(**i));
+          BluetoothSocketChromeOS::CreateBluetoothSocket(**i));
       if (socket.get() != NULL) {
         callback.Run(socket);
         return;
@@ -562,7 +702,7 @@
   callback.Run(NULL);
 }
 
-void BluetoothDeviceChromeOs::OnRemoteDataCallback(
+void BluetoothDeviceChromeOS::OnRemoteDataCallback(
     const base::Closure& callback,
     const ErrorCallback& error_callback,
     bool success) {
@@ -572,14 +712,14 @@
     error_callback.Run();
 }
 
-void BluetoothDeviceChromeOs::DisconnectRequested(
+void BluetoothDeviceChromeOS::DisconnectRequested(
     const dbus::ObjectPath& object_path) {
   DCHECK(object_path == object_path_);
 }
 
-void BluetoothDeviceChromeOs::Release() {
+void BluetoothDeviceChromeOS::Release() {
   DCHECK(agent_.get());
-  DVLOG(1) << "Release: " << address_;
+  VLOG(1) << "Release: " << address_;
 
   DCHECK(pairing_delegate_);
   pairing_delegate_->DismissDisplayOrConfirm();
@@ -592,11 +732,11 @@
   agent_.reset();
 }
 
-void BluetoothDeviceChromeOs::RequestPinCode(
+void BluetoothDeviceChromeOS::RequestPinCode(
     const dbus::ObjectPath& device_path,
     const PinCodeCallback& callback) {
   DCHECK(agent_.get());
-  DVLOG(1) << "RequestPinCode: " << device_path.value();
+  VLOG(1) << "RequestPinCode: " << device_path.value();
 
   DCHECK(pairing_delegate_);
   DCHECK(pincode_callback_.is_null());
@@ -604,12 +744,12 @@
   pairing_delegate_->RequestPinCode(this);
 }
 
-void BluetoothDeviceChromeOs::RequestPasskey(
+void BluetoothDeviceChromeOS::RequestPasskey(
     const dbus::ObjectPath& device_path,
     const PasskeyCallback& callback) {
   DCHECK(agent_.get());
   DCHECK(device_path == object_path_);
-  DVLOG(1) << "RequestPasskey: " << device_path.value();
+  VLOG(1) << "RequestPasskey: " << device_path.value();
 
   DCHECK(pairing_delegate_);
   DCHECK(passkey_callback_.is_null());
@@ -617,35 +757,35 @@
   pairing_delegate_->RequestPasskey(this);
 }
 
-void BluetoothDeviceChromeOs::DisplayPinCode(
+void BluetoothDeviceChromeOS::DisplayPinCode(
     const dbus::ObjectPath& device_path,
     const std::string& pincode) {
   DCHECK(agent_.get());
   DCHECK(device_path == object_path_);
-  DVLOG(1) << "DisplayPinCode: " << device_path.value() << " " << pincode;
+  VLOG(1) << "DisplayPinCode: " << device_path.value() << " " << pincode;
 
   DCHECK(pairing_delegate_);
   pairing_delegate_->DisplayPinCode(this, pincode);
 }
 
-void BluetoothDeviceChromeOs::DisplayPasskey(
+void BluetoothDeviceChromeOS::DisplayPasskey(
     const dbus::ObjectPath& device_path,
     uint32 passkey) {
   DCHECK(agent_.get());
   DCHECK(device_path == object_path_);
-  DVLOG(1) << "DisplayPasskey: " << device_path.value() << " " << passkey;
+  VLOG(1) << "DisplayPasskey: " << device_path.value() << " " << passkey;
 
   DCHECK(pairing_delegate_);
   pairing_delegate_->DisplayPasskey(this, passkey);
 }
 
-void BluetoothDeviceChromeOs::RequestConfirmation(
+void BluetoothDeviceChromeOS::RequestConfirmation(
     const dbus::ObjectPath& device_path,
     uint32 passkey,
     const ConfirmationCallback& callback) {
   DCHECK(agent_.get());
   DCHECK(device_path == object_path_);
-  DVLOG(1) << "RequestConfirmation: " << device_path.value() << " " << passkey;
+  VLOG(1) << "RequestConfirmation: " << device_path.value() << " " << passkey;
 
   DCHECK(pairing_delegate_);
   DCHECK(confirmation_callback_.is_null());
@@ -653,7 +793,7 @@
   pairing_delegate_->ConfirmPasskey(this, passkey);
 }
 
-void BluetoothDeviceChromeOs::Authorize(const dbus::ObjectPath& device_path,
+void BluetoothDeviceChromeOS::Authorize(const dbus::ObjectPath& device_path,
                                         const std::string& uuid,
                                         const ConfirmationCallback& callback) {
   DCHECK(agent_.get());
@@ -663,7 +803,7 @@
   callback.Run(REJECTED);
 }
 
-void BluetoothDeviceChromeOs::ConfirmModeChange(
+void BluetoothDeviceChromeOS::ConfirmModeChange(
     Mode mode,
     const ConfirmationCallback& callback) {
   DCHECK(agent_.get());
@@ -672,9 +812,9 @@
   callback.Run(REJECTED);
 }
 
-void BluetoothDeviceChromeOs::Cancel() {
+void BluetoothDeviceChromeOS::Cancel() {
   DCHECK(agent_.get());
-  DVLOG(1) << "Cancel: " << address_;
+  VLOG(1) << "Cancel: " << address_;
 
   DCHECK(pairing_delegate_);
   pairing_delegate_->DismissDisplayOrConfirm();
@@ -682,9 +822,9 @@
 
 
 // static
-BluetoothDeviceChromeOs* BluetoothDeviceChromeOs::Create(
-    BluetoothAdapterChromeOs* adapter) {
-  return new BluetoothDeviceChromeOs(adapter);
+BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create(
+    BluetoothAdapterChromeOS* adapter) {
+  return new BluetoothDeviceChromeOS(adapter);
 }
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_device_chromeos.h b/device/bluetooth/bluetooth_device_chromeos.h
index 4b2d3b5..32e8984 100644
--- a/device/bluetooth/bluetooth_device_chromeos.h
+++ b/device/bluetooth/bluetooth_device_chromeos.h
@@ -28,16 +28,16 @@
 
 namespace chromeos {
 
-class BluetoothAdapterChromeOs;
+class BluetoothAdapterChromeOS;
 
-// The BluetoothDeviceChromeOs class is an implementation of BluetoothDevice
+// The BluetoothDeviceChromeOS class is an implementation of BluetoothDevice
 // for Chrome OS platform.
-class BluetoothDeviceChromeOs
+class BluetoothDeviceChromeOS
     : public device::BluetoothDevice,
       public BluetoothDeviceClient::Observer,
       public BluetoothAgentServiceProvider::Delegate {
  public:
-  virtual ~BluetoothDeviceChromeOs();
+  virtual ~BluetoothDeviceChromeOS();
 
   // BluetoothDevice override
   virtual bool IsPaired() const OVERRIDE;
@@ -45,7 +45,6 @@
   virtual void GetServiceRecords(
       const ServiceRecordsCallback& callback,
       const ErrorCallback& error_callback) OVERRIDE;
-  virtual bool ProvidesServiceWithUUID(const std::string& uuid) const OVERRIDE;
   virtual void ProvidesServiceWithName(
       const std::string& name,
       const ProvidesServiceCallback& callback) OVERRIDE;
@@ -55,7 +54,7 @@
   virtual void Connect(
       device::BluetoothDevice::PairingDelegate* pairing_delegate,
       const base::Closure& callback,
-      const ErrorCallback& error_callback) OVERRIDE;
+      const ConnectErrorCallback& error_callback) OVERRIDE;
   virtual void SetPinCode(const std::string& pincode) OVERRIDE;
   virtual void SetPasskey(uint32 passkey) OVERRIDE;
   virtual void ConfirmPairing() OVERRIDE;
@@ -77,10 +76,10 @@
       const ErrorCallback& error_callback) OVERRIDE;
 
  private:
-  friend class BluetoothAdapterChromeOs;
+  friend class BluetoothAdapterChromeOS;
   friend class device::MockBluetoothDevice;
 
-  explicit BluetoothDeviceChromeOs(BluetoothAdapterChromeOs* adapter);
+  explicit BluetoothDeviceChromeOS(BluetoothAdapterChromeOS* adapter);
 
   // Sets the dbus object path for the device to |object_path|, indicating
   // that the device has gone from being discovered to paired or bonded.
@@ -103,19 +102,19 @@
   // CreatePairedDevice() succeeds, provides the new object path for the remote
   // device in |device_path|. |callback| and |error_callback| are the callbacks
   // provided to Connect().
-  void ConnectCallback(const base::Closure& callback,
-                       const ErrorCallback& error_callback,
-                       const dbus::ObjectPath& device_path);
+  void OnCreateDevice(const base::Closure& callback,
+                      const ConnectErrorCallback& error_callback,
+                      const dbus::ObjectPath& device_path);
 
   // Called by BluetoothAdapterClient when a call to CreateDevice() or
   // CreatePairedDevice() fails with the error named |error_name| and
   // optional message |error_message|, |error_callback| is the callback
   // provided to Connect().
-  void ConnectErrorCallback(const ErrorCallback& error_callback,
-                            const std::string& error_name,
-                            const std::string& error_message);
+  void OnCreateDeviceError(const ConnectErrorCallback& error_callback,
+                           const std::string& error_name,
+                           const std::string& error_message);
 
-  // Called by BluetoothAdapterClient when a call to DiscoverServices()
+  // Called by BluetoothAdapterClient when a call to GetServiceRecords()
   // completes.  |callback| and |error_callback| are the callbacks provided to
   // GetServiceRecords.
   void CollectServiceRecordsCallback(
@@ -127,18 +126,44 @@
 
   // Called by BluetoothProperty when the call to Set() for the Trusted
   // property completes. |success| indicates whether or not the request
-  // succeeded, |callback| and |error_callback| are the callbacks provided to
-  // Connect().
-  void OnSetTrusted(const base::Closure& callback,
-                    const ErrorCallback& error_callback,
-                    bool success);
+  // succeeded.
+  void OnSetTrusted(bool success);
+
+  // Called by BluetoothAdapterClient when a call to GetServiceRecords()
+  // fails.  |callback| and |error_callback| are the callbacks provided to
+  // GetServiceRecords().
+  void OnGetServiceRecordsError(const ServiceRecordsCallback& callback,
+                                const ErrorCallback& error_callback);
+
+  // Called by BluetoothAdapterClient when the initial call to
+  // GetServiceRecords() after pairing completes. |callback| and
+  // |error_callback| are the callbacks provided to Connect().
+  void OnInitialGetServiceRecords(const base::Closure& callback,
+                                  const ConnectErrorCallback& error_callback,
+                                  const ServiceRecordList& list);
+
+  // Called by BluetoothAdapterClient when the initial call to
+  // GetServiceRecords() after pairing fails. |callback| and |error_callback|
+  // are the callbacks provided to Connect().
+  void OnInitialGetServiceRecordsError(
+      const base::Closure& callback,
+      const ConnectErrorCallback& error_callback);
+
+  // Called by Connect() when it succeeds. The |callback| is the value passed to
+  // the Connect() call.
+  void OnConnectCallbackCalled(const base::Closure& callback);
+
+  // Called by Connect() when it fails. The |error_callback| is the value passed
+  // to the Connect() call.
+  void OnConnectErrorCallbackCalled(const ConnectErrorCallback& error_callback,
+                                    enum ConnectErrorCode error_code);
 
   // Connect application-level protocols of the device to the system, called
   // on a successful connection or to reconnect to a device that is already
   // paired or previously connected. |error_callback| is called on failure.
   // Otherwise, |callback| is called when the request is complete.
   void ConnectApplications(const base::Closure& callback,
-                           const ErrorCallback& error_callback);
+                           const ConnectErrorCallback& error_callback);
 
   // Called by IntrospectableClient when a call to Introspect() completes.
   // |success| indicates whether or not the request succeeded, |callback| and
@@ -146,7 +171,7 @@
   // |service_name| and |device_path| specify the remote object being
   // introspected and |xml_data| contains the XML-formatted protocol data.
   void OnIntrospect(const base::Closure& callback,
-                    const ErrorCallback& error_callback,
+                    const ConnectErrorCallback& error_callback,
                     const std::string& service_name,
                     const dbus::ObjectPath& device_path,
                     const std::string& xml_data, bool success);
@@ -164,7 +189,7 @@
   // |interface_name| specifies the interface being connected,
   // |device_path| the remote object path,
   // |error_name| the error name and |error_message| the optional message.
-  void OnConnectError(const ErrorCallback& error_callback,
+  void OnConnectError(const ConnectErrorCallback& error_callback,
                       const std::string& interface_name,
                       const dbus::ObjectPath& device_path,
                       const std::string& error_name,
@@ -185,6 +210,11 @@
   void ForgetCallback(const ErrorCallback& error_callback,
                       const dbus::ObjectPath& adapter_path, bool success);
 
+  // Called by BluetoothAdapterClient when a call to CancelDeviceCreation()
+  // completes, |success| indicates whether or not the request succeeded.
+  void OnCancelDeviceCreation(const dbus::ObjectPath& adapter_path,
+                              bool success);
+
   // Called if the call to GetServiceRecords from ProvidesServiceWithName fails.
   void SearchServicesForNameErrorCallback(
       const ProvidesServiceCallback& callback);
@@ -330,12 +360,12 @@
   // the request failed before a reply was returned from the device.
   virtual void Cancel() OVERRIDE;
 
-  // Creates a new BluetoothDeviceChromeOs object bound to the adapter
+  // Creates a new BluetoothDeviceChromeOS object bound to the adapter
   // |adapter|.
-  static BluetoothDeviceChromeOs* Create(BluetoothAdapterChromeOs* adapter);
+  static BluetoothDeviceChromeOS* Create(BluetoothAdapterChromeOS* adapter);
 
   // The adapter that owns this device instance.
-  BluetoothAdapterChromeOs* adapter_;
+  BluetoothAdapterChromeOS* adapter_;
 
   // The dbus object path of the device, will be empty if the device has only
   // been discovered and not yet paired with.
@@ -363,11 +393,21 @@
   // Used to keep track of pending application connection requests.
   int connecting_applications_counter_;
 
+  // Used to keep track of ongoing calls to Connect().
+  int connecting_calls_;
+
+  // A service records cache.
+  ServiceRecordList service_records_;
+
+  // This says whether the |service_records_| cache is initialized. Note that an
+  // empty |service_records_| list can be a valid list.
+  bool service_records_loaded_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<BluetoothDeviceChromeOs> weak_ptr_factory_;
+  base::WeakPtrFactory<BluetoothDeviceChromeOS> weak_ptr_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceChromeOs);
+  DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceChromeOS);
 };
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_device_mac.h b/device/bluetooth/bluetooth_device_mac.h
new file mode 100644
index 0000000..d1f4b24
--- /dev/null
+++ b/device/bluetooth/bluetooth_device_mac.h
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_MAC_H_
+#define DEVICE_BLUETOOTH_BlUETOOTH_DEVICE_MAC_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "device/bluetooth/bluetooth_device.h"
+
+#ifdef __OBJC__
+@class IOBluetoothDevice;
+#else
+class IOBluetoothDevice;
+#endif
+
+namespace device {
+
+class BluetoothDeviceMac : public BluetoothDevice {
+ public:
+  explicit BluetoothDeviceMac(const IOBluetoothDevice* device);
+  virtual ~BluetoothDeviceMac();
+
+  // BluetoothDevice override
+  virtual bool IsPaired() const OVERRIDE;
+  virtual const ServiceList& GetServices() const OVERRIDE;
+  virtual void GetServiceRecords(
+      const ServiceRecordsCallback& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void ProvidesServiceWithName(
+      const std::string& name,
+      const ProvidesServiceCallback& callback) OVERRIDE;
+  virtual bool ExpectingPinCode() const OVERRIDE;
+  virtual bool ExpectingPasskey() const OVERRIDE;
+  virtual bool ExpectingConfirmation() const OVERRIDE;
+  virtual void Connect(
+      PairingDelegate* pairing_delegate,
+      const base::Closure& callback,
+      const ConnectErrorCallback& error_callback) OVERRIDE;
+  virtual void SetPinCode(const std::string& pincode) OVERRIDE;
+  virtual void SetPasskey(uint32 passkey) OVERRIDE;
+  virtual void ConfirmPairing() OVERRIDE;
+  virtual void RejectPairing() OVERRIDE;
+  virtual void CancelPairing() OVERRIDE;
+  virtual void Disconnect(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void Forget(const ErrorCallback& error_callback) OVERRIDE;
+  virtual void ConnectToService(
+      const std::string& service_uuid,
+      const SocketCallback& callback) OVERRIDE;
+  virtual void SetOutOfBandPairingData(
+      const BluetoothOutOfBandPairingData& data,
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+  virtual void ClearOutOfBandPairingData(
+      const base::Closure& callback,
+      const ErrorCallback& error_callback) OVERRIDE;
+
+ private:
+  friend class BluetoothAdapterMac;
+
+  // Computes the fingerprint that can be used to compare the devices.
+  static uint32 ComputeDeviceFingerprint(const IOBluetoothDevice* device);
+
+  uint32 device_fingerprint() const {
+    return device_fingerprint_;
+  }
+
+  // Used to compare the devices.
+  const uint32 device_fingerprint_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceMac);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_MAC_H_
diff --git a/device/bluetooth/bluetooth_device_mac.mm b/device/bluetooth/bluetooth_device_mac.mm
new file mode 100644
index 0000000..d7ddb54
--- /dev/null
+++ b/device/bluetooth/bluetooth_device_mac.mm
@@ -0,0 +1,158 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_device_mac.h"
+
+#include <IOBluetooth/Bluetooth.h>
+#import <IOBluetooth/objc/IOBluetoothDevice.h>
+#import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/hash.h"
+#include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
+#include "device/bluetooth/bluetooth_service_record_mac.h"
+
+// Replicate specific 10.7 SDK declarations for building with prior SDKs.
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
+@interface IOBluetoothDevice (LionSDKDeclarations)
+- (NSString*)addressString;
+- (NSString*)name;
+- (unsigned int)classOfDevice;
+- (NSArray*)services;
+@end
+
+#endif  // MAC_OS_X_VERSION_10_7
+
+namespace device {
+
+BluetoothDeviceMac::BluetoothDeviceMac(const IOBluetoothDevice* device)
+    : BluetoothDevice(),
+      device_fingerprint_(ComputeDeviceFingerprint(device)) {
+  name_ = base::SysNSStringToUTF8([device name]);
+  address_ = base::SysNSStringToUTF8([device addressString]);
+  bluetooth_class_ = [device classOfDevice];
+  connected_ = [device isConnected];
+  bonded_ = [device isPaired];
+  visible_ = true;
+}
+
+BluetoothDeviceMac::~BluetoothDeviceMac() {
+}
+
+bool BluetoothDeviceMac::IsPaired() const {
+  return bonded_;
+}
+
+const BluetoothDevice::ServiceList& BluetoothDeviceMac::GetServices() const {
+  return service_uuids_;
+}
+
+void BluetoothDeviceMac::GetServiceRecords(
+    const ServiceRecordsCallback& callback,
+    const ErrorCallback& error_callback) {
+}
+
+void BluetoothDeviceMac::ProvidesServiceWithName(
+    const std::string& name,
+    const ProvidesServiceCallback& callback) {
+}
+
+bool BluetoothDeviceMac::ExpectingPinCode() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool BluetoothDeviceMac::ExpectingPasskey() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool BluetoothDeviceMac::ExpectingConfirmation() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void BluetoothDeviceMac::Connect(
+    PairingDelegate* pairing_delegate,
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::SetPinCode(const std::string& pincode) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::SetPasskey(uint32 passkey) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::ConfirmPairing() {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::RejectPairing() {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::CancelPairing() {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::Disconnect(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::Forget(const ErrorCallback& error_callback) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::ConnectToService(
+    const std::string& service_uuid,
+    const SocketCallback& callback) {
+}
+
+void BluetoothDeviceMac::SetOutOfBandPairingData(
+    const BluetoothOutOfBandPairingData& data,
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  NOTIMPLEMENTED();
+}
+
+void BluetoothDeviceMac::ClearOutOfBandPairingData(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback) {
+  NOTIMPLEMENTED();
+}
+
+// static
+uint32 BluetoothDeviceMac::ComputeDeviceFingerprint(
+    const IOBluetoothDevice* device) {
+  std::string device_string = base::StringPrintf("%s|%s|%u|%d|%d",
+      base::SysNSStringToUTF8([device name]).c_str(),
+      base::SysNSStringToUTF8([device addressString]).c_str(),
+      [device classOfDevice],
+      [device isConnected],
+      [device isPaired]);
+
+  for (IOBluetoothSDPServiceRecord* record in [device services]) {
+    base::StringAppendF(
+        &device_string,
+        "|%s|%u",
+        base::SysNSStringToUTF8([record getServiceName]).c_str(),
+        [[record attributes] count]);
+  }
+
+  return base::Hash(device_string);
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_device_win.cc b/device/bluetooth/bluetooth_device_win.cc
index 5b6cd9c..c06693f 100644
--- a/device/bluetooth/bluetooth_device_win.cc
+++ b/device/bluetooth/bluetooth_device_win.cc
@@ -1,50 +1,89 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// TODO(youngki): Implement this file.
 
 #include "device/bluetooth/bluetooth_device_win.h"
 
 #include <string>
+
 #include "base/basictypes.h"
+#include "base/hash.h"
 #include "base/logging.h"
+#include "base/memory/scoped_vector.h"
+#include "base/stringprintf.h"
 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
+#include "device/bluetooth/bluetooth_service_record_win.h"
+#include "device/bluetooth/bluetooth_socket_win.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+
+namespace {
+
+const int kSdpBytesBufferSize = 1024;
+
+}  // namespace
 
 namespace device {
 
-BluetoothDeviceWin::BluetoothDeviceWin() : BluetoothDevice() {
+BluetoothDeviceWin::BluetoothDeviceWin(
+    const BluetoothTaskManagerWin::DeviceState& state)
+    : BluetoothDevice(), device_fingerprint_(ComputeDeviceFingerprint(state)) {
+  name_ = state.name;
+  address_ = state.address;
+  bluetooth_class_ = state.bluetooth_class;
+  connected_ = state.connected;
+  bonded_ = state.authenticated;
+
+  for (ScopedVector<BluetoothTaskManagerWin::ServiceRecordState>::const_iterator
+       iter = state.service_record_states.begin();
+       iter != state.service_record_states.end();
+       ++iter) {
+    uint8 sdp_bytes_buffer[kSdpBytesBufferSize];
+    std::copy((*iter)->sdp_bytes.begin(),
+              (*iter)->sdp_bytes.end(),
+              sdp_bytes_buffer);
+    BluetoothServiceRecord* service_record = new BluetoothServiceRecordWin(
+        (*iter)->name,
+        (*iter)->address,
+        (*iter)->sdp_bytes.size(),
+        sdp_bytes_buffer);
+    service_record_list_.push_back(service_record);
+    service_uuids_.push_back(service_record->uuid());
+  }
 }
 
 BluetoothDeviceWin::~BluetoothDeviceWin() {
 }
 
+void BluetoothDeviceWin::SetVisible(bool visible) {
+  visible_ = visible;
+}
+
 bool BluetoothDeviceWin::IsPaired() const {
-  NOTIMPLEMENTED();
   return false;
 }
 
 const BluetoothDevice::ServiceList& BluetoothDeviceWin::GetServices() const {
-  NOTIMPLEMENTED();
   return service_uuids_;
 }
 
 void BluetoothDeviceWin::GetServiceRecords(
     const ServiceRecordsCallback& callback,
     const ErrorCallback& error_callback) {
-  NOTIMPLEMENTED();
-}
-
-bool BluetoothDeviceWin::ProvidesServiceWithUUID(
-    const std::string& uuid) const {
-  NOTIMPLEMENTED();
-  return false;
+  callback.Run(service_record_list_);
 }
 
 void BluetoothDeviceWin::ProvidesServiceWithName(
     const std::string& name,
     const ProvidesServiceCallback& callback) {
-  NOTIMPLEMENTED();
+  for (ServiceRecordList::const_iterator iter = service_record_list_.begin();
+       iter != service_record_list_.end();
+       ++iter) {
+    if ((*iter)->name() == name) {
+      callback.Run(true);
+      return;
+    }
+  }
+  callback.Run(false);
 }
 
 bool BluetoothDeviceWin::ExpectingPinCode() const {
@@ -65,7 +104,7 @@
 void BluetoothDeviceWin::Connect(
     PairingDelegate* pairing_delegate,
     const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+    const ConnectErrorCallback& error_callback) {
   NOTIMPLEMENTED();
 }
 
@@ -102,7 +141,19 @@
 void BluetoothDeviceWin::ConnectToService(
     const std::string& service_uuid,
     const SocketCallback& callback) {
-  NOTIMPLEMENTED();
+  for (ServiceRecordList::const_iterator iter = service_record_list_.begin();
+       iter != service_record_list_.end();
+       ++iter) {
+    if ((*iter)->uuid() == service_uuid) {
+      // If multiple service records are found, use the first one that works.
+      scoped_refptr<BluetoothSocket> socket(
+          BluetoothSocketWin::CreateBluetoothSocket(**iter));
+      if (socket.get() != NULL) {
+        callback.Run(socket);
+        return;
+      }
+    }
+  }
 }
 
 void BluetoothDeviceWin::SetOutOfBandPairingData(
@@ -118,4 +169,27 @@
   NOTIMPLEMENTED();
 }
 
+// static
+uint32 BluetoothDeviceWin::ComputeDeviceFingerprint(
+    const BluetoothTaskManagerWin::DeviceState& state) {
+  std::string device_string = base::StringPrintf("%s%s%u%s%s%s",
+      state.name.c_str(),
+      state.address.c_str(),
+      state.bluetooth_class,
+      state.visible ? "true" : "false",
+      state.connected ? "true" : "false",
+      state.authenticated ? "true" : "false");
+  for (ScopedVector<BluetoothTaskManagerWin::ServiceRecordState>::const_iterator
+      iter = state.service_record_states.begin();
+      iter != state.service_record_states.end();
+      ++iter) {
+    base::StringAppendF(&device_string,
+                        "%s%s%d",
+                        (*iter)->name.c_str(),
+                        (*iter)->address.c_str(),
+                        (*iter)->sdp_bytes.size());
+  }
+  return base::Hash(device_string);
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h
index ee2048b..b1e9d80 100644
--- a/device/bluetooth/bluetooth_device_win.h
+++ b/device/bluetooth/bluetooth_device_win.h
@@ -6,23 +6,30 @@
 #define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WIN_H_
 
 #include <string>
+#include <vector>
 
 #include "base/basictypes.h"
 #include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
 
 namespace device {
 
+class BluetoothAdapterWin;
+
 class BluetoothDeviceWin : public BluetoothDevice {
  public:
-  BluetoothDeviceWin();
+  explicit BluetoothDeviceWin(
+      const BluetoothTaskManagerWin::DeviceState& state);
   virtual ~BluetoothDeviceWin();
 
+  void SetVisible(bool visible);
+
+  // BluetoothDevice override
   virtual bool IsPaired() const OVERRIDE;
   virtual const ServiceList& GetServices() const OVERRIDE;
   virtual void GetServiceRecords(
       const ServiceRecordsCallback& callback,
       const ErrorCallback& error_callback) OVERRIDE;
-  virtual bool ProvidesServiceWithUUID(const std::string& uuid) const OVERRIDE;
   virtual void ProvidesServiceWithName(
       const std::string& name,
       const ProvidesServiceCallback& callback) OVERRIDE;
@@ -32,7 +39,7 @@
   virtual void Connect(
       PairingDelegate* pairing_delegate,
       const base::Closure& callback,
-      const ErrorCallback& error_callback) OVERRIDE;
+      const ConnectErrorCallback& error_callback) OVERRIDE;
   virtual void SetPinCode(const std::string& pincode) OVERRIDE;
   virtual void SetPasskey(uint32 passkey) OVERRIDE;
   virtual void ConfirmPairing() OVERRIDE;
@@ -54,8 +61,21 @@
       const ErrorCallback& error_callback) OVERRIDE;
 
  private:
-  // The services (identified by UUIDs) that this device provides.
-  std::vector<std::string> service_uuids_;
+  friend class BluetoothAdapterWin;
+
+  // Computes the fingerprint that can be used to compare the devices.
+  static uint32 ComputeDeviceFingerprint(
+      const BluetoothTaskManagerWin::DeviceState& state);
+
+  uint32 device_fingerprint() const {
+    return device_fingerprint_;
+  }
+
+  // Used to compare the devices.
+  uint32 device_fingerprint_;
+  ServiceRecordList service_record_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceWin);
 };
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_device_win_unittest.cc b/device/bluetooth/bluetooth_device_win_unittest.cc
new file mode 100644
index 0000000..892f022
--- /dev/null
+++ b/device/bluetooth/bluetooth_device_win_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/string_number_conversions.h"
+#include "device/bluetooth/bluetooth_device_win.h"
+#include "device/bluetooth/bluetooth_service_record.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kDeviceName[] = "Device";
+const char kDeviceAddress[] = "device address";
+
+const char kTestAudioSdpName[] = "Audio";
+const char kTestAudioSdpAddress[] = "01:02:03:0A:10:A0";
+const char kTestAudioSdpBytes[] =
+    "35510900000a00010001090001350319110a09000435103506190100090019350619001909"
+    "010209000535031910020900093508350619110d090102090100250c417564696f20536f75"
+    "726365090311090001";
+const char kTestAudioSdpUuid[] = "0000110a-0000-1000-8000-00805f9b34fb";
+
+const char kTestVideoSdpName[] = "Video";
+const char kTestVideoSdpAddress[] = "A0:10:0A:03:02:01";
+const char kTestVideoSdpBytes[] =
+    "354b0900000a000100030900013506191112191203090004350c3503190100350519000308"
+    "0b090005350319100209000935083506191108090100090100250d566f6963652047617465"
+    "776179";
+const char kTestVideoSdpUuid[] = "00001112-0000-1000-8000-00805f9b34fb";
+
+}  // namespace
+
+namespace device {
+
+class BluetoothDeviceWinTest : public testing::Test {
+ public:
+  BluetoothDeviceWinTest()
+      : error_called_(false),
+        provides_service_with_name_(false) {
+    BluetoothTaskManagerWin::DeviceState device_state;
+    device_state.name = kDeviceName;
+    device_state.address = kDeviceAddress;
+
+    BluetoothTaskManagerWin::ServiceRecordState* audio_state =
+        new BluetoothTaskManagerWin::ServiceRecordState();
+    audio_state->name = kTestAudioSdpName;
+    audio_state->address = kTestAudioSdpAddress;
+    base::HexStringToBytes(kTestAudioSdpBytes, &audio_state->sdp_bytes);
+    device_state.service_record_states.push_back(audio_state);
+
+    BluetoothTaskManagerWin::ServiceRecordState* video_state =
+        new BluetoothTaskManagerWin::ServiceRecordState();
+    video_state->name = kTestVideoSdpName;
+    video_state->address = kTestVideoSdpAddress;
+    base::HexStringToBytes(kTestVideoSdpBytes, &video_state->sdp_bytes);
+    device_state.service_record_states.push_back(video_state);
+
+    device_.reset(new BluetoothDeviceWin(device_state));
+  }
+
+  void GetServiceRecords(
+      const BluetoothDevice::ServiceRecordList& service_record_list) {
+    service_records_ = &service_record_list;
+  }
+
+  void OnError() {
+    error_called_ = true;
+  }
+
+  void SetProvidesServiceWithName(bool provides_service_with_name) {
+    provides_service_with_name_ = provides_service_with_name;
+  }
+
+ protected:
+  scoped_ptr<BluetoothDevice> device_;
+  scoped_ptr<BluetoothDevice> empty_device_;
+  const BluetoothDevice::ServiceRecordList* service_records_;
+  bool error_called_;
+  bool provides_service_with_name_;
+};
+
+TEST_F(BluetoothDeviceWinTest, GetServices) {
+  const BluetoothDevice::ServiceList& service_list = device_->GetServices();
+
+  EXPECT_EQ(2, service_list.size());
+  EXPECT_STREQ(kTestAudioSdpUuid, service_list[0].c_str());
+  EXPECT_STREQ(kTestVideoSdpUuid, service_list[1].c_str());
+}
+
+TEST_F(BluetoothDeviceWinTest, GetServiceRecords) {
+  device_->GetServiceRecords(
+      base::Bind(&BluetoothDeviceWinTest::GetServiceRecords,
+                 base::Unretained(this)),
+      BluetoothDevice::ErrorCallback());
+  ASSERT_TRUE(service_records_ != NULL);
+  EXPECT_EQ(2, service_records_->size());
+  EXPECT_STREQ(kTestAudioSdpUuid, (*service_records_)[0]->uuid().c_str());
+  EXPECT_STREQ(kTestVideoSdpUuid, (*service_records_)[1]->uuid().c_str());
+}
+
+TEST_F(BluetoothDeviceWinTest, ProvidesServiceWithName) {
+  device_->ProvidesServiceWithName(
+      kTestAudioSdpName,
+      base::Bind(&BluetoothDeviceWinTest::SetProvidesServiceWithName,
+                 base::Unretained(this)));
+  EXPECT_TRUE(provides_service_with_name_);
+
+  device_->ProvidesServiceWithName(
+      kTestVideoSdpName,
+      base::Bind(&BluetoothDeviceWinTest::SetProvidesServiceWithName,
+                 base::Unretained(this)));
+  EXPECT_TRUE(provides_service_with_name_);
+
+  device_->ProvidesServiceWithName(
+      "name that does not exist",
+      base::Bind(&BluetoothDeviceWinTest::SetProvidesServiceWithName,
+                 base::Unretained(this)));
+  EXPECT_FALSE(provides_service_with_name_);
+}
+
+}  // namespace device
\ No newline at end of file
diff --git a/device/bluetooth/bluetooth_init_win.cc b/device/bluetooth/bluetooth_init_win.cc
new file mode 100644
index 0000000..54d0b20
--- /dev/null
+++ b/device/bluetooth/bluetooth_init_win.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_init_win.h"
+
+#include "base/threading/thread_restrictions.h"
+
+namespace {
+
+// A frame-based exception handler filter function for a handler for exceptions
+// generated by the Visual C++ delay loader helper function.
+int FilterVisualCPPExceptions(DWORD exception_code) {
+  return HRESULT_FACILITY(exception_code) == FACILITY_VISUALCPP ?
+      EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+
+}  // namespace
+
+namespace device {
+namespace bluetooth_init_win {
+
+bool HasBluetoothStack() {
+  static enum {
+    HBS_UNKNOWN,
+    HBS_YES,
+    HBS_NO,
+  } has_bluetooth_stack = HBS_UNKNOWN;
+
+  if (has_bluetooth_stack == HBS_UNKNOWN) {
+    base::ThreadRestrictions::AssertIOAllowed();
+    HRESULT hr = E_FAIL;
+    __try {
+      hr = __HrLoadAllImportsForDll("bthprops.cpl");
+    } __except(FilterVisualCPPExceptions(::GetExceptionCode())) {
+      hr = E_FAIL;
+    }
+    has_bluetooth_stack = SUCCEEDED(hr) ? HBS_YES : HBS_NO;
+  }
+
+  return has_bluetooth_stack == HBS_YES;
+}
+
+}  // namespace bluetooth_init_win
+}  // namespace device
\ No newline at end of file
diff --git a/device/bluetooth/bluetooth_init_win.h b/device/bluetooth/bluetooth_init_win.h
new file mode 100644
index 0000000..00fd186
--- /dev/null
+++ b/device/bluetooth/bluetooth_init_win.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_INIT_WIN_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_INIT_WIN_H_
+
+// windows.h needs to be included before BluetoothAPIs.h.
+#include <windows.h>
+
+#include <BluetoothAPIs.h>
+#if defined(_WIN32_WINNT_WIN8) && _MSC_VER < 1700
+// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h.
+#undef FACILITY_VISUALCPP
+#endif
+#include <delayimp.h>
+#include <ws2def.h>
+#include <ws2bth.h>
+
+#pragma comment(lib, "Bthprops.lib")
+
+namespace device {
+namespace bluetooth_init_win {
+
+// Returns true if the machine has a bluetooth stack available. The first call
+// to this function will involve file IO, so it should be done on an appropriate
+// thread. This function is not threadsafe.
+bool HasBluetoothStack();
+
+}  // namespace bluetooth_init_win
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_INIT_WIN_H_
diff --git a/device/bluetooth/bluetooth_service_record.cc b/device/bluetooth/bluetooth_service_record.cc
index 0ea18d7..aa97373 100644
--- a/device/bluetooth/bluetooth_service_record.cc
+++ b/device/bluetooth/bluetooth_service_record.cc
@@ -4,119 +4,12 @@
 
 #include "device/bluetooth/bluetooth_service_record.h"
 
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/string_number_conversions.h"
-#include "device/bluetooth/bluetooth_utils.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-namespace {
-
-static const char* kAttributeNode = "attribute";
-static const char* kIdAttribute = "id";
-static const char* kProtocolDescriptorListId = "0x0004";
-static const char* kRfcommUuid = "0x0003";
-static const char* kSdpNameId = "0x0100";
-static const char* kSequenceNode = "sequence";
-static const char* kTextNode = "text";
-static const char* kUint8Node = "uint8";
-static const char* kUuidId = "0x0001";
-static const char* kUuidNode = "uuid";
-static const char* kValueAttribute = "value";
-
-bool AdvanceToTag(XmlReader* reader, const char* node_type) {
-  do {
-    if (!reader->Read())
-      return false;
-  } while (reader->NodeName() != node_type);
-  return true;
-}
-
-bool ExtractTextValue(XmlReader* reader, std::string* value_out) {
-  if (AdvanceToTag(reader, kTextNode)) {
-    reader->NodeAttribute(kValueAttribute, value_out);
-    return true;
-  }
-  return false;
-}
-
-}  // namespace
-
 namespace device {
 
-BluetoothServiceRecord::BluetoothServiceRecord(
-    const std::string& address,
-    const std::string& xml_data)
-  : address_(address),
-    supports_rfcomm_(false) {
-
-  XmlReader reader;
-  if (!reader.Load(xml_data))
-    return;
-
-  while (AdvanceToTag(&reader, kAttributeNode)) {
-    std::string id;
-    if (reader.NodeAttribute(kIdAttribute, &id)) {
-      if (id == kSdpNameId) {
-        ExtractTextValue(&reader, &name_);
-      } else if (id == kProtocolDescriptorListId) {
-        if (AdvanceToTag(&reader, kSequenceNode)) {
-          ExtractChannels(&reader);
-        }
-      } else if (id == kUuidId) {
-        if (AdvanceToTag(&reader, kSequenceNode)) {
-          ExtractUuid(&reader);
-        }
-      }
-    }
-    // We don't care about anything else here, so find the closing tag
-    AdvanceToTag(&reader, kAttributeNode);
-  }
+BluetoothServiceRecord::BluetoothServiceRecord() {
 }
 
-void BluetoothServiceRecord::ExtractChannels(XmlReader* reader) {
-  const int start_depth = reader->Depth();
-  do {
-    if (reader->NodeName() == kSequenceNode) {
-      if (AdvanceToTag(reader, kUuidNode)) {
-        std::string type;
-        if (reader->NodeAttribute(kValueAttribute, &type) &&
-            type == kRfcommUuid) {
-          if (AdvanceToTag(reader, kUint8Node)) {
-            std::string channel_string;
-            if (reader->NodeAttribute(kValueAttribute, &channel_string)) {
-              std::vector<uint8> channel_bytes;
-              if (base::HexStringToBytes(channel_string.substr(2),
-                    &channel_bytes)) {
-                if (channel_bytes.size() == 1) {
-                  rfcomm_channel_ = channel_bytes[0];
-                  supports_rfcomm_ = true;
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  } while (AdvanceToTag(reader, kSequenceNode) &&
-           reader->Depth() != start_depth);
-}
-
-void BluetoothServiceRecord::ExtractUuid(XmlReader* reader) {
-  const int start_depth = reader->Depth();
-  do {
-    if (reader->NodeName() == kSequenceNode) {
-      if (AdvanceToTag(reader, kUuidNode)) {
-        if (!reader->NodeAttribute(kValueAttribute, &uuid_))
-          uuid_.clear();
-      }
-    }
-  } while (AdvanceToTag(reader, kSequenceNode) &&
-           reader->Depth() != start_depth);
-
-  uuid_ = device::bluetooth_utils::CanonicalUuid(uuid_);
+BluetoothServiceRecord::~BluetoothServiceRecord() {
 }
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_service_record.h b/device/bluetooth/bluetooth_service_record.h
index e04d73a..eebdb6a 100644
--- a/device/bluetooth/bluetooth_service_record.h
+++ b/device/bluetooth/bluetooth_service_record.h
@@ -9,8 +9,6 @@
 
 #include "base/basictypes.h"
 
-class XmlReader;
-
 namespace device {
 
 // BluetoothServiceRecord represents an SDP service record.
@@ -19,38 +17,51 @@
 // that have been necessary so far.
 class BluetoothServiceRecord {
  public:
-   BluetoothServiceRecord(
-       const std::string& address,
-       const std::string& xml_data);
+  virtual ~BluetoothServiceRecord();
 
-   // The human-readable name of this service.
-   const std::string& name() const { return name_; }
+  // The human-readable name of this service.
+  const std::string& name() const { return name_; }
 
-   // The address of the BluetoothDevice providing this service.
-   const std::string& address() const { return address_; }
+  // The address of the BluetoothDevice providing this service.
+  const std::string& address() const { return address_; }
 
-   // The UUID of the service.  This field may be empty if no UUID was
-   // specified in the service record.
-   const std::string& uuid() const { return uuid_; }
+  // The UUID of the service.  This field may be empty if no UUID was
+  // specified in the service record.
+  const std::string& uuid() const { return uuid_; }
 
-   // Indicates if this service supports RFCOMM communication.
-   bool SupportsRfcomm() const { return supports_rfcomm_; }
+  // Indicates if this service supports HID.
+  bool SupportsHid() const { return supports_hid_; }
 
-   // The RFCOMM channel to use, if this service supports RFCOMM communication.
-   // The return value is undefined if SupportsRfcomm() returns false.
-   uint8 rfcomm_channel() const { return rfcomm_channel_; }
+  // For HID services, returns the HIDReconnectInitiate attribute. For non-HID
+  // or unknown services defaults to true.
+  bool hid_reconnect_initiate() const { return hid_reconnect_initiate_; }
 
- private:
-  void ExtractChannels(XmlReader* reader);
-  void ExtractUuid(XmlReader* reader);
+  // For HID services, returns the HIDNormallyConnectable attribute. For non-HID
+  // or unknown services defaults to true.
+  bool hid_normally_connectable() const { return hid_normally_connectable_; }
+
+  // Indicates if this service supports RFCOMM communication.
+  bool SupportsRfcomm() const { return supports_rfcomm_; }
+
+  // The RFCOMM channel to use, if this service supports RFCOMM communication.
+  // The return value is undefined if SupportsRfcomm() returns false.
+  uint8 rfcomm_channel() const { return rfcomm_channel_; }
+
+ protected:
+  BluetoothServiceRecord();
 
   std::string address_;
   std::string name_;
   std::string uuid_;
 
+  bool supports_hid_;
+  bool hid_reconnect_initiate_;
+  bool hid_normally_connectable_;
+
   bool supports_rfcomm_;
   uint8 rfcomm_channel_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(BluetoothServiceRecord);
 };
 
diff --git a/device/bluetooth/bluetooth_service_record_chromeos.cc b/device/bluetooth/bluetooth_service_record_chromeos.cc
new file mode 100644
index 0000000..b7ab878
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_chromeos.cc
@@ -0,0 +1,178 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_service_record_chromeos.h"
+
+#include <bluetooth/bluetooth.h>
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "device/bluetooth/bluetooth_utils.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+
+namespace {
+
+static const char* kAttributeNode = "attribute";
+static const char* kBooleanNode = "boolean";
+static const char* kSequenceNode = "sequence";
+static const char* kTextNode = "text";
+static const char* kUint8Node = "uint8";
+static const char* kUuidNode = "uuid";
+
+static const char* kIdAttribute = "id";
+static const char* kValueAttribute = "value";
+static const char* kValueTrue = "true";
+
+static const char* kHidNormallyConnectableId = "0x020d";
+static const char* kHidReconnectInitiateId = "0x0205";
+static const char* kProtocolDescriptorListId = "0x0004";
+static const char* kSdpNameId = "0x0100";
+static const char* kServiceClassUuidId = "0x0001";
+
+static const char* kProtocolRfcommUuid = "0x0003";
+static const char* kProtocolHidpUuid = "0x0011";
+
+bool AdvanceToTag(XmlReader* reader, const char* node_type) {
+  do {
+    if (!reader->Read())
+      return false;
+  } while (reader->NodeName() != node_type);
+  return true;
+}
+
+bool ExtractTextValue(XmlReader* reader, std::string* value_out) {
+  if (AdvanceToTag(reader, kTextNode)) {
+    reader->NodeAttribute(kValueAttribute, value_out);
+    return true;
+  }
+  return false;
+}
+
+bool ExtractBooleanValue(XmlReader* reader, bool* value_out) {
+  if (AdvanceToTag(reader, kBooleanNode)) {
+    std::string str_value;
+    if (!reader->NodeAttribute(kValueAttribute, &str_value))
+      return false;
+    *value_out = str_value == kValueTrue;
+    return true;
+  }
+  return false;
+}
+
+}  // namespace
+
+namespace chromeos {
+
+BluetoothServiceRecordChromeOS::BluetoothServiceRecordChromeOS(
+    const std::string& address,
+    const std::string& xml_data) {
+  address_ = address;
+  supports_rfcomm_ = false;
+  supports_hid_ = false;
+
+  // For HID services the default is false when the attribute is not present.
+  hid_reconnect_initiate_ = false;
+  hid_normally_connectable_ = false;
+
+  XmlReader reader;
+  if (!reader.Load(xml_data))
+    return;
+
+  while (AdvanceToTag(&reader, kAttributeNode)) {
+    std::string id;
+    if (reader.NodeAttribute(kIdAttribute, &id)) {
+      if (id == kSdpNameId) {
+        ExtractTextValue(&reader, &name_);
+      } else if (id == kProtocolDescriptorListId) {
+        if (AdvanceToTag(&reader, kSequenceNode)) {
+          ExtractProtocolDescriptors(&reader);
+        }
+      } else if (id == kServiceClassUuidId) {
+        if (AdvanceToTag(&reader, kSequenceNode)) {
+          ExtractServiceClassUuid(&reader);
+        }
+      } else if (id == kHidNormallyConnectableId) {
+        ExtractBooleanValue(&reader, &hid_normally_connectable_);
+      } else if (id == kHidReconnectInitiateId) {
+        ExtractBooleanValue(&reader, &hid_reconnect_initiate_);
+      }
+    }
+    // We don't care about anything else here, so find the closing tag
+    AdvanceToTag(&reader, kAttributeNode);
+  }
+  if (!supports_hid_) {
+    // For non-HID services the default is true.
+    hid_normally_connectable_ = true;
+    hid_reconnect_initiate_ = true;
+  }
+}
+
+void BluetoothServiceRecordChromeOS::GetBluetoothAddress(
+    bdaddr_t* out_address) const {
+  std::string numbers_only;
+  for (int i = 0; i < 6; ++i)
+    numbers_only += address_.substr(i * 3, 2);
+
+  std::vector<uint8> address_bytes;
+  base::HexStringToBytes(numbers_only, &address_bytes);
+  for (int i = 0; i < 6; ++i)
+    out_address->b[5 - i] = address_bytes[i];
+}
+
+void BluetoothServiceRecordChromeOS::ExtractProtocolDescriptors(
+    XmlReader* reader) {
+  const int start_depth = reader->Depth();
+  // The ProtocolDescriptorList can have one or more sequence of sequence of
+  // stack, where each stack starts with an UUID and the remaining tags (if
+  // present) are protocol-specific.
+  do {
+    if (reader->NodeName() == kSequenceNode) {
+      if (AdvanceToTag(reader, kUuidNode)) {
+        std::string protocolUuid;
+        if (reader->NodeAttribute(kValueAttribute, &protocolUuid)) {
+          // Per protocol parameters parsing.
+          if (protocolUuid == kProtocolRfcommUuid) {
+            if (AdvanceToTag(reader, kUint8Node)) {
+              std::string channel_string;
+              if (reader->NodeAttribute(kValueAttribute, &channel_string)) {
+                std::vector<uint8> channel_bytes;
+                if (base::HexStringToBytes(channel_string.substr(2),
+                      &channel_bytes)) {
+                  if (channel_bytes.size() == 1) {
+                    rfcomm_channel_ = channel_bytes[0];
+                    supports_rfcomm_ = true;
+                  }
+                }
+              }
+            }
+          } else if (protocolUuid == kProtocolHidpUuid) {
+            supports_hid_ = true;
+          }
+        }
+      }
+    }
+  } while (AdvanceToTag(reader, kSequenceNode) &&
+           reader->Depth() != start_depth);
+}
+
+void BluetoothServiceRecordChromeOS::ExtractServiceClassUuid(
+    XmlReader* reader) {
+  const int start_depth = reader->Depth();
+  do {
+    if (reader->NodeName() == kSequenceNode) {
+      if (AdvanceToTag(reader, kUuidNode)) {
+        if (!reader->NodeAttribute(kValueAttribute, &uuid_))
+          uuid_.clear();
+      }
+    }
+  } while (AdvanceToTag(reader, kSequenceNode) &&
+           reader->Depth() != start_depth);
+
+  uuid_ = device::bluetooth_utils::CanonicalUuid(uuid_);
+}
+
+}  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_service_record_chromeos.h b/device/bluetooth/bluetooth_service_record_chromeos.h
new file mode 100644
index 0000000..5d0ce9b
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_chromeos.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_CHROMEOS_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_CHROMEOS_H_
+
+#include <bluetooth/bluetooth.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "device/bluetooth/bluetooth_service_record.h"
+
+class XmlReader;
+
+namespace chromeos {
+
+// BluetoothServiceRecordChromeOS is an implementation of BluetoothServiceRecord
+// for the ChromeOS platform.
+class BluetoothServiceRecordChromeOS : public device::BluetoothServiceRecord {
+ public:
+  BluetoothServiceRecordChromeOS(const std::string& address,
+                                 const std::string& xml_data);
+
+  void GetBluetoothAddress(bdaddr_t* out_address) const;
+
+ private:
+  void ExtractProtocolDescriptors(XmlReader* reader);
+  void ExtractServiceClassUuid(XmlReader* reader);
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothServiceRecordChromeOS);
+};
+
+}  // namespace chromeos
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_CHROMEOS_H_
diff --git a/device/bluetooth/bluetooth_service_record_chromeos_unittest.cc b/device/bluetooth/bluetooth_service_record_chromeos_unittest.cc
new file mode 100644
index 0000000..df4bab7
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_chromeos_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <bluetooth/bluetooth.h>
+
+#include <string>
+
+#include "base/base_paths.h"
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "device/bluetooth/bluetooth_service_record_chromeos.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+static const char* kAddress = "01:02:03:0A:10:A0";
+static const char* kCustomUuid = "01234567-89ab-cdef-0123-456789abcdef";
+static const char* kSerialUuid = "00001101-0000-1000-8000-00805f9b34fb";
+
+}  // namespace
+
+namespace chromeos {
+
+class BluetoothServiceRecordChromeOSTest : public testing::Test {
+ public:
+  base::FilePath GetTestDataFilePath(const char* file) {
+    base::FilePath path;
+    PathService::Get(base::DIR_SOURCE_ROOT, &path);
+    path = path.AppendASCII("device");
+    path = path.AppendASCII("test");
+    path = path.AppendASCII("data");
+    path = path.AppendASCII("bluetooth");
+    path = path.AppendASCII(file);
+    return path;
+  }
+};
+
+TEST_F(BluetoothServiceRecordChromeOSTest, RfcommService) {
+  std::string xml_data;
+  file_util::ReadFileToString(GetTestDataFilePath("rfcomm.xml"), &xml_data);
+
+  BluetoothServiceRecordChromeOS service_record(kAddress, xml_data);
+  EXPECT_EQ(kAddress, service_record.address());
+  EXPECT_EQ("Headset Audio Gateway", service_record.name());
+  EXPECT_TRUE(service_record.SupportsRfcomm());
+  EXPECT_EQ((uint8)12, service_record.rfcomm_channel());
+  EXPECT_EQ(kCustomUuid, service_record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordChromeOSTest, ShortUuid) {
+  std::string xml_data;
+  file_util::ReadFileToString(GetTestDataFilePath("short_uuid.xml"), &xml_data);
+  BluetoothServiceRecordChromeOS short_uuid_service_record(kAddress, xml_data);
+  EXPECT_EQ(kSerialUuid, short_uuid_service_record.uuid());
+
+  xml_data.clear();
+  file_util::ReadFileToString(
+      GetTestDataFilePath("medium_uuid.xml"), &xml_data);
+  BluetoothServiceRecordChromeOS medium_uuid_service_record(kAddress, xml_data);
+  EXPECT_EQ(kSerialUuid, medium_uuid_service_record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordChromeOSTest, CleanUuid) {
+  std::string xml_data;
+  file_util::ReadFileToString(GetTestDataFilePath("uppercase_uuid.xml"),
+      &xml_data);
+  BluetoothServiceRecordChromeOS service_record(kAddress, xml_data);
+  EXPECT_EQ(kCustomUuid, service_record.uuid());
+
+  xml_data.clear();
+  file_util::ReadFileToString(GetTestDataFilePath("invalid_uuid.xml"),
+      &xml_data);
+  BluetoothServiceRecordChromeOS invalid_service_record(kAddress, xml_data);
+  EXPECT_EQ("", invalid_service_record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordChromeOSTest, BluetoothAddress) {
+  BluetoothServiceRecordChromeOS service_record(kAddress, "");
+  bdaddr_t bluetooth_address;
+  service_record.GetBluetoothAddress(&bluetooth_address);
+  EXPECT_EQ(1, bluetooth_address.b[5]);
+  EXPECT_EQ(2, bluetooth_address.b[4]);
+  EXPECT_EQ(3, bluetooth_address.b[3]);
+  EXPECT_EQ(10, bluetooth_address.b[2]);
+  EXPECT_EQ(16, bluetooth_address.b[1]);
+  EXPECT_EQ(160, bluetooth_address.b[0]);
+}
+
+}  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_service_record_mac.h b/device/bluetooth/bluetooth_service_record_mac.h
new file mode 100644
index 0000000..13eb56b
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_mac.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_MAC_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_MAC_H_
+
+#include "device/bluetooth/bluetooth_service_record.h"
+
+#ifdef __OBJC__
+@class IOBluetoothDevice;
+@class IOBluetoothSDPServiceRecord;
+#else
+class IOBluetoothDevice;
+class IOBluetoothSDPServiceRecord;
+#endif
+
+namespace device {
+
+class BluetoothServiceRecordMac : public BluetoothServiceRecord {
+ public:
+  explicit BluetoothServiceRecordMac(IOBluetoothSDPServiceRecord* record);
+  virtual ~BluetoothServiceRecordMac();
+
+  IOBluetoothDevice* GetIOBluetoothDevice() const {
+    return device_;
+  }
+
+ private:
+  IOBluetoothDevice* device_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothServiceRecordMac);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_MAC_H_
diff --git a/device/bluetooth/bluetooth_service_record_mac.mm b/device/bluetooth/bluetooth_service_record_mac.mm
new file mode 100644
index 0000000..3410351
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_mac.mm
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_service_record_mac.h"
+
+#include <IOBluetooth/Bluetooth.h>
+#import <IOBluetooth/IOBluetoothUtilities.h>
+#import <IOBluetooth/objc/IOBluetoothDevice.h>
+#import <IOBluetooth/objc/IOBluetoothSDPDataElement.h>
+#import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h>
+#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+
+namespace {
+
+void ExtractUuid(IOBluetoothSDPDataElement* service_class_data,
+                 std::string* uuid) {
+  NSArray* inner_elements = [service_class_data getArrayValue];
+  IOBluetoothSDPUUID* sdp_uuid = nil;
+  for (IOBluetoothSDPDataElement* inner_element in inner_elements) {
+    if ([inner_element getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID) {
+      sdp_uuid = [[inner_element getUUIDValue] getUUIDWithLength:16];
+      break;
+    }
+  }
+  if (sdp_uuid != nil) {
+    const uint8* uuid_bytes = reinterpret_cast<const uint8*>([sdp_uuid bytes]);
+    *uuid = base::StringPrintf(
+        "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+        uuid_bytes[0], uuid_bytes[1], uuid_bytes[2], uuid_bytes[3],
+        uuid_bytes[4], uuid_bytes[5], uuid_bytes[6], uuid_bytes[7],
+        uuid_bytes[8], uuid_bytes[9], uuid_bytes[10], uuid_bytes[11],
+        uuid_bytes[12], uuid_bytes[13], uuid_bytes[14], uuid_bytes[15]);
+  }
+}
+
+}  // namespace
+
+namespace device {
+
+BluetoothServiceRecordMac::BluetoothServiceRecordMac(
+    IOBluetoothSDPServiceRecord* record)
+    : BluetoothServiceRecord() {
+  name_ = base::SysNSStringToUTF8([record getServiceName]);
+  device_ = [[record device] retain];
+  address_ = base::SysNSStringToUTF8(IOBluetoothNSStringFromDeviceAddress(
+      [device_ getAddress]));
+
+  // TODO(youngki): Extract these values from |record|.
+  supports_hid_ = false;
+  hid_reconnect_initiate_ = false;
+  hid_normally_connectable_ = false;
+
+  supports_rfcomm_ =
+      [record getRFCOMMChannelID:&rfcomm_channel_] == kIOReturnSuccess;
+
+  const BluetoothSDPServiceAttributeID service_class_id = 1;
+
+  IOBluetoothSDPDataElement* service_class_data =
+      [record getAttributeDataElement:service_class_id];
+  if ([service_class_data getTypeDescriptor] ==
+          kBluetoothSDPDataElementTypeDataElementSequence) {
+    ExtractUuid(service_class_data, &uuid_);
+  }
+}
+
+BluetoothServiceRecordMac::~BluetoothServiceRecordMac() {
+  [device_ release];
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_service_record_mac_unittest.mm b/device/bluetooth/bluetooth_service_record_mac_unittest.mm
new file mode 100644
index 0000000..8cfb46f
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_mac_unittest.mm
@@ -0,0 +1,152 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_service_record_mac.h"
+
+#import <IOBluetooth/objc/IOBluetoothSDPDataElement.h>
+#import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h>
+#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/string_number_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const BluetoothSDPServiceAttributeID kServiceClassIDAttributeId = 0x0001;
+const BluetoothSDPServiceAttributeID kProtocolDescriptorListAttributeId =
+    0x0004;
+const BluetoothSDPServiceAttributeID kServiceNameAttributeId = 0x0100;
+
+const uint8 kRfcommChannel = 0x0c;
+const char kServiceName[] = "Headset Audio Gateway";
+
+const char kExpectedRfcommUuid[] = "01234567-89ab-cdef-0123-456789abcdef";
+const char kExpectedSerialUuid[] = "00001101-0000-1000-8000-00805f9b34fb";
+
+const int kMaxUuidSize = 16;
+
+}  // namespace
+
+namespace device {
+
+class BluetoothServiceRecordMacTest : public testing::Test {
+ public:
+
+  IOBluetoothSDPUUID* ConvertUuid(const char* uuid_hex_char, size_t uuid_size) {
+    std::vector<uint8> uuid_bytes_vector;
+    uint8 uuid_buffer[kMaxUuidSize];
+    base::HexStringToBytes(uuid_hex_char, &uuid_bytes_vector);
+    std::copy(uuid_bytes_vector.begin(),
+              uuid_bytes_vector.end(),
+              uuid_buffer);
+    return [IOBluetoothSDPUUID uuidWithBytes:uuid_buffer length:uuid_size];
+  }
+
+  IOBluetoothSDPDataElement* GetServiceClassId(IOBluetoothSDPUUID* uuid) {
+    IOBluetoothSDPDataElement* uuid_element =
+        [IOBluetoothSDPDataElement withElementValue:uuid];
+    return [IOBluetoothSDPDataElement
+        withElementValue:[NSArray arrayWithObject:uuid_element]];
+  }
+
+  IOBluetoothSDPDataElement* GetProtocolDescriptorList(bool supports_rfcomm) {
+    NSMutableArray* protocol_descriptor_list_sequence = [NSMutableArray array];
+
+    const uint8 l2cap_uuid_bytes[] = { 0x01, 0x00 };
+
+    IOBluetoothSDPUUID* l2cap_uuid =
+        [IOBluetoothSDPUUID uuidWithBytes:l2cap_uuid_bytes length:2];
+    [protocol_descriptor_list_sequence
+        addObject:[NSArray arrayWithObject:l2cap_uuid]];
+
+    if (supports_rfcomm) {
+      const uint8 rfcomm_uuid_bytes[] = { 0x00, 0x03 };
+      IOBluetoothSDPUUID* rfcomm_uuid =
+          [IOBluetoothSDPUUID uuidWithBytes:rfcomm_uuid_bytes length:2];
+      NSNumber* rfcomm_channel =
+          [NSNumber numberWithUnsignedChar:kRfcommChannel];
+      [protocol_descriptor_list_sequence
+          addObject:[NSArray
+              arrayWithObjects:rfcomm_uuid, rfcomm_channel, nil]];
+    }
+
+    return [IOBluetoothSDPDataElement
+        withElementValue:protocol_descriptor_list_sequence];
+  }
+
+  IOBluetoothSDPDataElement* GetServiceName(const std::string& service_name) {
+    return [IOBluetoothSDPDataElement
+        withElementValue:base::SysUTF8ToNSString(service_name)];
+  }
+
+  IOBluetoothSDPServiceRecord* GetServiceRecord(
+      IOBluetoothSDPUUID* uuid, bool supports_rfcomm) {
+    NSMutableDictionary* service_attrs = [NSMutableDictionary dictionary];
+
+    if (uuid != nil) {
+      [service_attrs
+          setObject:GetServiceClassId(uuid)
+             forKey:[NSNumber numberWithInt:kServiceClassIDAttributeId]];
+    }
+    [service_attrs
+        setObject:GetProtocolDescriptorList(supports_rfcomm)
+           forKey:[NSNumber numberWithInt:kProtocolDescriptorListAttributeId]];
+    [service_attrs
+        setObject:GetServiceName(kServiceName)
+           forKey:[NSNumber numberWithInt:kServiceNameAttributeId]];
+
+    return [IOBluetoothSDPServiceRecord withServiceDictionary:service_attrs
+                                                       device:nil];
+  }
+};
+
+TEST_F(BluetoothServiceRecordMacTest, RfcommService) {
+  const char rfcomm_uuid_bytes[] = "0123456789abcdef0123456789abcdef";
+  IOBluetoothSDPUUID* rfcomm_uuid =
+      ConvertUuid(rfcomm_uuid_bytes, sizeof(rfcomm_uuid_bytes) / 2);
+
+  BluetoothServiceRecordMac record(GetServiceRecord(rfcomm_uuid, true));
+  EXPECT_EQ(kServiceName, record.name());
+  EXPECT_TRUE(record.SupportsRfcomm());
+  EXPECT_EQ(kRfcommChannel, record.rfcomm_channel());
+  EXPECT_EQ(kExpectedRfcommUuid, record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordMacTest, ShortUuid) {
+  const char short_uuid_bytes[] = "1101";
+  IOBluetoothSDPUUID* short_uuid =
+      ConvertUuid(short_uuid_bytes, sizeof(short_uuid_bytes) / 2);
+
+  BluetoothServiceRecordMac record(GetServiceRecord(short_uuid, false));
+  EXPECT_EQ(kExpectedSerialUuid, record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordMacTest, MediumUuid) {
+  const char medium_uuid_bytes[] = "00001101";
+  IOBluetoothSDPUUID* medium_uuid =
+      ConvertUuid(medium_uuid_bytes, sizeof(medium_uuid_bytes) / 2);
+
+  BluetoothServiceRecordMac record(GetServiceRecord(medium_uuid, false));
+  EXPECT_EQ(kExpectedSerialUuid, record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordMacTest, UpperCaseUuid) {
+  const char upper_case_uuid_bytes[] = "0123456789ABCDEF0123456789ABCDEF";
+  IOBluetoothSDPUUID* upper_case_uuid =
+      ConvertUuid(upper_case_uuid_bytes, sizeof(upper_case_uuid_bytes) / 2);
+
+  BluetoothServiceRecordMac record(GetServiceRecord(upper_case_uuid, false));
+  EXPECT_EQ(kExpectedRfcommUuid, record.uuid());
+}
+
+TEST_F(BluetoothServiceRecordMacTest, InvalidUuid) {
+  BluetoothServiceRecordMac record(GetServiceRecord(nil, false));
+  EXPECT_EQ("", record.uuid());
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_service_record_unittest.cc b/device/bluetooth/bluetooth_service_record_unittest.cc
deleted file mode 100644
index b59474f..0000000
--- a/device/bluetooth/bluetooth_service_record_unittest.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/base_paths.h"
-#include "base/basictypes.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "device/bluetooth/bluetooth_service_record.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-static const char* kAddress = "01:02:03:04:05:06";
-static const char* kCustomUuid = "01234567-89ab-cdef-0123-456789abcdef";
-static const char* kSerialUuid = "00001101-0000-1000-8000-00805f9b34fb";
-
-}  // namespace
-
-namespace device {
-
-class BluetoothServiceRecordTest : public testing::Test {
- public:
-  FilePath GetTestDataFilePath(const char* file) {
-    FilePath path;
-    PathService::Get(base::DIR_SOURCE_ROOT, &path);
-    path = path.AppendASCII("device");
-    path = path.AppendASCII("test");
-    path = path.AppendASCII("data");
-    path = path.AppendASCII("bluetooth");
-    path = path.AppendASCII(file);
-    return path;
-  }
-};
-
-TEST_F(BluetoothServiceRecordTest, RfcommService) {
-  std::string xml_data;
-  file_util::ReadFileToString(GetTestDataFilePath("rfcomm.xml"), &xml_data);
-
-  BluetoothServiceRecord service_record(kAddress, xml_data);
-  EXPECT_EQ(kAddress, service_record.address());
-  EXPECT_EQ("Headset Audio Gateway", service_record.name());
-  EXPECT_TRUE(service_record.SupportsRfcomm());
-  EXPECT_EQ((uint8)12, service_record.rfcomm_channel());
-  EXPECT_EQ(kCustomUuid, service_record.uuid());
-}
-
-TEST_F(BluetoothServiceRecordTest, ShortUuid) {
-  std::string xml_data;
-  file_util::ReadFileToString(GetTestDataFilePath("short_uuid.xml"), &xml_data);
-  BluetoothServiceRecord short_uuid_service_record(kAddress, xml_data);
-  EXPECT_EQ(kSerialUuid, short_uuid_service_record.uuid());
-
-  xml_data.clear();
-  file_util::ReadFileToString(
-      GetTestDataFilePath("medium_uuid.xml"), &xml_data);
-  BluetoothServiceRecord medium_uuid_service_record(kAddress, xml_data);
-  EXPECT_EQ(kSerialUuid, medium_uuid_service_record.uuid());
-}
-
-TEST_F(BluetoothServiceRecordTest, CleanUuid) {
-  std::string xml_data;
-  file_util::ReadFileToString(GetTestDataFilePath("uppercase_uuid.xml"),
-      &xml_data);
-  BluetoothServiceRecord service_record(kAddress, xml_data);
-  EXPECT_EQ(kCustomUuid, service_record.uuid());
-
-  xml_data.clear();
-  file_util::ReadFileToString(GetTestDataFilePath("invalid_uuid.xml"),
-      &xml_data);
-  BluetoothServiceRecord invalid_service_record(kAddress, xml_data);
-  EXPECT_EQ("", invalid_service_record.uuid());
-}
-
-}  // namespace device
diff --git a/device/bluetooth/bluetooth_service_record_win.cc b/device/bluetooth/bluetooth_service_record_win.cc
new file mode 100644
index 0000000..a09b335
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_win.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_service_record_win.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "device/bluetooth/bluetooth_init_win.h"
+#include "device/bluetooth/bluetooth_utils.h"
+
+namespace {
+
+const uint16 kProtocolDescriptorListId = 4;
+const uint16 kRfcommUuid = 3;
+const uint16 kUuidId = 1;
+
+bool AdvanceToSdpType(const SDP_ELEMENT_DATA& sequence_data,
+                      SDP_TYPE type,
+                      HBLUETOOTH_CONTAINER_ELEMENT* element,
+                      SDP_ELEMENT_DATA* sdp_data) {
+  while (ERROR_SUCCESS == BluetoothSdpGetContainerElementData(
+      sequence_data.data.sequence.value,
+      sequence_data.data.sequence.length,
+      element,
+      sdp_data)) {
+    if (sdp_data->type == type) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void ExtractChannels(const SDP_ELEMENT_DATA& protocol_descriptor_list_data,
+                     bool* supports_rfcomm,
+                     uint8* rfcomm_channel) {
+  HBLUETOOTH_CONTAINER_ELEMENT sequence_element = NULL;
+  SDP_ELEMENT_DATA sequence_data;
+  while (AdvanceToSdpType(protocol_descriptor_list_data,
+                          SDP_TYPE_SEQUENCE,
+                          &sequence_element,
+                          &sequence_data)) {
+    HBLUETOOTH_CONTAINER_ELEMENT inner_sequence_element = NULL;
+    SDP_ELEMENT_DATA inner_sequence_data;
+    if (AdvanceToSdpType(sequence_data,
+                         SDP_TYPE_UUID,
+                         &inner_sequence_element,
+                         &inner_sequence_data) &&
+        inner_sequence_data.data.uuid32 == kRfcommUuid &&
+        AdvanceToSdpType(sequence_data,
+                         SDP_TYPE_UINT,
+                         &inner_sequence_element,
+                         &inner_sequence_data) &&
+        inner_sequence_data.specificType == SDP_ST_UINT8) {
+      *rfcomm_channel = inner_sequence_data.data.uint8;
+      *supports_rfcomm = true;
+    }
+  }
+}
+
+void ExtractUuid(const SDP_ELEMENT_DATA& uuid_data, std::string* uuid) {
+  HBLUETOOTH_CONTAINER_ELEMENT inner_uuid_element = NULL;
+  SDP_ELEMENT_DATA inner_uuid_data;
+  if (AdvanceToSdpType(uuid_data,
+                       SDP_TYPE_UUID,
+                       &inner_uuid_element,
+                       &inner_uuid_data)) {
+    if (inner_uuid_data.specificType == SDP_ST_UUID16) {
+      std::string uuid_hex =
+          base::StringPrintf("%04x", inner_uuid_data.data.uuid16);
+      *uuid = device::bluetooth_utils::CanonicalUuid(uuid_hex);
+    } else if (inner_uuid_data.specificType == SDP_ST_UUID32) {
+      std::string uuid_hex =
+          base::StringPrintf("%08x", inner_uuid_data.data.uuid32);
+      *uuid = device::bluetooth_utils::CanonicalUuid(uuid_hex);
+    } else if (inner_uuid_data.specificType == SDP_ST_UUID128) {
+      *uuid = base::StringPrintf(
+          "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+          inner_uuid_data.data.uuid128.Data1,
+          inner_uuid_data.data.uuid128.Data2,
+          inner_uuid_data.data.uuid128.Data3,
+          inner_uuid_data.data.uuid128.Data4[0],
+          inner_uuid_data.data.uuid128.Data4[1],
+          inner_uuid_data.data.uuid128.Data4[2],
+          inner_uuid_data.data.uuid128.Data4[3],
+          inner_uuid_data.data.uuid128.Data4[4],
+          inner_uuid_data.data.uuid128.Data4[5],
+          inner_uuid_data.data.uuid128.Data4[6],
+          inner_uuid_data.data.uuid128.Data4[7]);
+    } else {
+      uuid->clear();
+    }
+  }
+}
+
+BTH_ADDR ConvertToBthAddr(const std::string& address) {
+  BTH_ADDR bth_addr = 0;
+  std::string numbers_only;
+  for (int i = 0; i < 6; ++i) {
+    numbers_only += address.substr(i * 3, 2);
+  }
+
+  std::vector<uint8> address_bytes;
+  base::HexStringToBytes(numbers_only, &address_bytes);
+  int byte_position = 0;
+  for (std::vector<uint8>::reverse_iterator iter = address_bytes.rbegin();
+      iter != address_bytes.rend();
+      ++iter) {
+    bth_addr += *iter * pow(256.0, byte_position);
+    byte_position++;
+  }
+  return bth_addr;
+}
+
+}  // namespace
+
+namespace device {
+
+BluetoothServiceRecordWin::BluetoothServiceRecordWin(
+    const std::string& name,
+    const std::string& address,
+    uint64 blob_size,
+    uint8* blob_data) : bth_addr_(ConvertToBthAddr(address)) {
+  name_ = name;
+  address_ = address;
+  supports_rfcomm_ = false;
+  SDP_ELEMENT_DATA protocol_descriptor_list_data;
+  if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
+      blob_data,
+      blob_size,
+      kProtocolDescriptorListId,
+      &protocol_descriptor_list_data)) {
+    ExtractChannels(protocol_descriptor_list_data,
+                    &supports_rfcomm_,
+                    &rfcomm_channel_);
+  }
+  SDP_ELEMENT_DATA uuid_data;
+  if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
+      blob_data,
+      blob_size,
+      kUuidId,
+      &uuid_data)) {
+  ExtractUuid(uuid_data, &uuid_);
+  }
+}
+
+}  // namespace device
\ No newline at end of file
diff --git a/device/bluetooth/bluetooth_service_record_win.h b/device/bluetooth/bluetooth_service_record_win.h
new file mode 100644
index 0000000..b9f0331
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_win.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_WIN_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_WIN_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "device/bluetooth/bluetooth_init_win.h"
+#include "device/bluetooth/bluetooth_service_record.h"
+
+namespace device {
+
+class BluetoothServiceRecordWin : public BluetoothServiceRecord {
+ public:
+  BluetoothServiceRecordWin(const std::string& name,
+                            const std::string& address,
+                            uint64 blob_size,
+                            uint8* blob_data);
+
+  BTH_ADDR bth_addr() const {
+    return bth_addr_;
+  }
+
+ private:
+  BTH_ADDR bth_addr_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothServiceRecordWin);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SERVICE_RECORD_WIN_H_
diff --git a/device/bluetooth/bluetooth_service_record_win_unittest.cc b/device/bluetooth/bluetooth_service_record_win_unittest.cc
new file mode 100644
index 0000000..5f5c03e
--- /dev/null
+++ b/device/bluetooth/bluetooth_service_record_win_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/string_number_conversions.h"
+#include "device/bluetooth/bluetooth_service_record_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kTestNoRfcommSdpBytes[] =
+    "35510900000a00010001090001350319110a09000435103506190100090019350619001909"
+    "010209000535031910020900093508350619110d090102090100250c417564696f20536f75"
+    "726365090311090001";
+const int kTestNoRfcommSdpBytesSize = sizeof(kTestNoRfcommSdpBytes) / 2;
+const char kTestNoRfcommSdpUuid[] = "0000110a-0000-1000-8000-00805f9b34fb";
+
+const char kTestRfcommSdpBytes[] =
+    "354b0900000a000100030900013506191112191203090004350c3503190100350519000308"
+    "0b090005350319100209000935083506191108090100090100250d566f6963652047617465"
+    "776179";
+const int kTestRfcommSdpBytesSize = sizeof(kTestRfcommSdpBytes) / 2;
+const char kTestRfcommSdpUuid[] = "00001112-0000-1000-8000-00805f9b34fb";
+const int kTestRfcommChannel = 11;
+
+}  // namespace
+
+namespace device {
+
+class BluetoothServiceRecordWinTest : public testing::Test {
+ protected:
+  void ConvertSdpBytes(const char* sdp_hex_char, uint8* sdp_bytes_array) {
+    std::vector<uint8> sdp_bytes_vector;
+    base::HexStringToBytes(sdp_hex_char, &sdp_bytes_vector);
+    std::copy(sdp_bytes_vector.begin(),
+              sdp_bytes_vector.end(),
+              sdp_bytes_array);
+  }
+};
+
+TEST_F(BluetoothServiceRecordWinTest, NoRfcommSdp) {
+  uint8 sdp_bytes_array[kTestNoRfcommSdpBytesSize];
+  ConvertSdpBytes(kTestNoRfcommSdpBytes, sdp_bytes_array);
+  BluetoothServiceRecordWin service_record("NoRfcommSdp",
+                                           "01:02:03:0A:10:A0",
+                                           kTestNoRfcommSdpBytesSize,
+                                           sdp_bytes_array);
+  EXPECT_STREQ(kTestNoRfcommSdpUuid, service_record.uuid().c_str());
+  EXPECT_FALSE(service_record.SupportsRfcomm());
+}
+
+
+TEST_F(BluetoothServiceRecordWinTest, RfcommSdp) {
+  uint8 sdp_bytes_array[kTestRfcommSdpBytesSize];
+  ConvertSdpBytes(kTestRfcommSdpBytes, sdp_bytes_array);
+  BluetoothServiceRecordWin service_record("RfcommSdp",
+                                           "01:02:03:0A:10:A0",
+                                           kTestRfcommSdpBytesSize,
+                                           sdp_bytes_array);
+  EXPECT_STREQ(kTestRfcommSdpUuid, service_record.uuid().c_str());
+  EXPECT_TRUE(service_record.SupportsRfcomm());
+  EXPECT_EQ(kTestRfcommChannel, service_record.rfcomm_channel());
+}
+
+TEST_F(BluetoothServiceRecordWinTest, BthAddr) {
+  uint8 sdp_bytes_array[kTestRfcommSdpBytesSize];
+  ConvertSdpBytes(kTestRfcommSdpBytes, sdp_bytes_array);
+  BluetoothServiceRecordWin service_record("Sdp",
+                                           "01:02:03:0A:10:A0",
+                                           kTestRfcommSdpBytesSize,
+                                           sdp_bytes_array);
+  EXPECT_EQ(1108152553632, service_record.bth_addr());
+}
+
+}  // namespace device
\ No newline at end of file
diff --git a/device/bluetooth/bluetooth_socket.h b/device/bluetooth/bluetooth_socket.h
index b444110..6ae349e 100644
--- a/device/bluetooth/bluetooth_socket.h
+++ b/device/bluetooth/bluetooth_socket.h
@@ -5,8 +5,17 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_H_
 
+#include <string>
+
 #include "base/memory/ref_counted.h"
 
+namespace net {
+
+class DrainableIOBuffer;
+class GrowableIOBuffer;
+
+}  // namespace net
+
 namespace device {
 
 // BluetoothSocket represents a socket to a specific service on a
@@ -15,10 +24,17 @@
 // creation.
 class BluetoothSocket : public base::RefCounted<BluetoothSocket> {
  public:
-  // TODO(youngki): Replace this with an opaque id when read/write calls are
-  // added. This interface is platform-independent and file descriptor is
-  // linux-specific hence this method has to be renamed.
-  virtual int fd() const = 0;
+  // Receives data from the socket and stores it in |buffer|. It returns whether
+  // the reception has been successful. If it fails, the caller can get the
+  // error message through |GetLastErrorMessage()|.
+  virtual bool Receive(net::GrowableIOBuffer* buffer) = 0;
+
+  // Sends |buffer| to the socket. It returns whether the sending has been
+  // successful. If it fails, the caller can get the error message through
+  // |GetLastErrorMessage()|.
+  virtual bool Send(net::DrainableIOBuffer* buffer) = 0;
+
+  virtual std::string GetLastErrorMessage() const = 0;
 
  protected:
   friend class base::RefCounted<BluetoothSocket>;
diff --git a/device/bluetooth/bluetooth_socket_chromeos.cc b/device/bluetooth/bluetooth_socket_chromeos.cc
index 7e75a9d..c4781df 100644
--- a/device/bluetooth/bluetooth_socket_chromeos.cc
+++ b/device/bluetooth/bluetooth_socket_chromeos.cc
@@ -4,54 +4,54 @@
 
 #include "device/bluetooth/bluetooth_socket_chromeos.h"
 
-#include <vector>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
 #include <errno.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <string>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
 #include "base/logging.h"
-#include "device/bluetooth/bluetooth_service_record.h"
+#include "base/safe_strerror_posix.h"
+#include "device/bluetooth/bluetooth_service_record_chromeos.h"
 #include "device/bluetooth/bluetooth_utils.h"
+#include "net/base/io_buffer.h"
 
 using device::BluetoothServiceRecord;
 using device::BluetoothSocket;
 
 namespace chromeos {
 
-BluetoothSocketChromeOs::BluetoothSocketChromeOs(
-    const std::string& address, int fd)
-  : address_(address),
-    fd_(fd) {
+BluetoothSocketChromeOS::BluetoothSocketChromeOS(int fd) : fd_(fd) {
 }
 
-BluetoothSocketChromeOs::~BluetoothSocketChromeOs() {
+BluetoothSocketChromeOS::~BluetoothSocketChromeOS() {
   close(fd_);
 }
 
 // static
-scoped_refptr<BluetoothSocket> BluetoothSocketChromeOs::CreateBluetoothSocket(
+scoped_refptr<BluetoothSocket> BluetoothSocketChromeOS::CreateBluetoothSocket(
     const BluetoothServiceRecord& service_record) {
-  BluetoothSocketChromeOs* bluetooth_socket = NULL;
+  BluetoothSocketChromeOS* bluetooth_socket = NULL;
   if (service_record.SupportsRfcomm()) {
     int socket_fd = socket(
         AF_BLUETOOTH, SOCK_STREAM | SOCK_NONBLOCK, BTPROTO_RFCOMM);
     struct sockaddr_rc socket_address = { 0 };
     socket_address.rc_family = AF_BLUETOOTH;
     socket_address.rc_channel = service_record.rfcomm_channel();
-    device::bluetooth_utils::str2ba(service_record.address(),
-        &socket_address.rc_bdaddr);
+    const BluetoothServiceRecordChromeOS* service_record_chromeos =
+        static_cast<const BluetoothServiceRecordChromeOS*>(&service_record);
+    service_record_chromeos->GetBluetoothAddress(&socket_address.rc_bdaddr);
 
     int status = connect(socket_fd, (struct sockaddr *)&socket_address,
         sizeof(socket_address));
     int errsv = errno;
     if (status == 0 || errno == EINPROGRESS) {
-      bluetooth_socket = new BluetoothSocketChromeOs(service_record.address(),
-          socket_fd);
+      bluetooth_socket = new BluetoothSocketChromeOS(socket_fd);
     } else {
       LOG(ERROR) << "Failed to connect bluetooth socket "
           << "(" << service_record.address() << "): "
@@ -61,11 +61,44 @@
   }
   // TODO(bryeung): add support for L2CAP sockets as well.
 
-  return scoped_refptr<BluetoothSocketChromeOs>(bluetooth_socket);
+  return scoped_refptr<BluetoothSocketChromeOS>(bluetooth_socket);
 }
 
-int BluetoothSocketChromeOs::fd() const {
-  return fd_;
+bool BluetoothSocketChromeOS::Receive(net::GrowableIOBuffer* buffer) {
+  buffer->SetCapacity(1024);
+  ssize_t bytes_read;
+  do {
+    if (buffer->RemainingCapacity() == 0)
+      buffer->SetCapacity(buffer->capacity() * 2);
+    bytes_read = read(fd_, buffer, buffer->RemainingCapacity());
+    if (bytes_read > 0)
+      buffer->set_offset(buffer->offset() + bytes_read);
+  } while (bytes_read > 0);
+
+  if (bytes_read < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
+    error_message_ = safe_strerror(errno);
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothSocketChromeOS::Send(net::DrainableIOBuffer* buffer) {
+  ssize_t bytes_written;
+  do {
+    bytes_written = write(fd_, buffer, buffer->BytesRemaining());
+    if (bytes_written > 0)
+      buffer->DidConsume(bytes_written);
+  } while (buffer->BytesRemaining() > 0 && bytes_written > 0);
+
+  if (bytes_written < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
+    error_message_ = safe_strerror(errno);
+    return false;
+  }
+  return true;
+}
+
+std::string BluetoothSocketChromeOS::GetLastErrorMessage() const {
+  return error_message_;
 }
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_socket_chromeos.h b/device/bluetooth/bluetooth_socket_chromeos.h
index 0685830..d9e89fa 100644
--- a/device/bluetooth/bluetooth_socket_chromeos.h
+++ b/device/bluetooth/bluetooth_socket_chromeos.h
@@ -16,28 +16,37 @@
 
 }  // namespace device
 
+namespace net {
+
+class DrainableIOBuffer;
+class GrowableIOBuffer;
+
+}  // namespace net
+
 namespace chromeos {
 
 // This class is an implementation of BluetoothSocket class for Chrome OS
 // platform.
-class BluetoothSocketChromeOs : public device::BluetoothSocket {
+class BluetoothSocketChromeOS : public device::BluetoothSocket {
  public:
   static scoped_refptr<device::BluetoothSocket> CreateBluetoothSocket(
       const device::BluetoothServiceRecord& service_record);
 
   // BluetoothSocket override
-  virtual int fd() const OVERRIDE;
+  virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE;
+  virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE;
+  virtual std::string GetLastErrorMessage() const OVERRIDE;
 
  protected:
-  virtual ~BluetoothSocketChromeOs();
+  virtual ~BluetoothSocketChromeOS();
 
  private:
-  BluetoothSocketChromeOs(const std::string& address, int fd);
+  BluetoothSocketChromeOS(int fd);
 
-  const std::string address_;
   const int fd_;
+  std::string error_message_;
 
-  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketChromeOs);
+  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketChromeOS);
 };
 
 }  // namespace chromeos
diff --git a/device/bluetooth/bluetooth_socket_mac.h b/device/bluetooth/bluetooth_socket_mac.h
new file mode 100644
index 0000000..5689a42
--- /dev/null
+++ b/device/bluetooth/bluetooth_socket_mac.h
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "device/bluetooth/bluetooth_socket.h"
+
+#ifdef __OBJC__
+@class BluetoothRFCOMMChannelDelegate;
+@class IOBluetoothRFCOMMChannel;
+#else
+class BluetoothRFCOMMChannelDelegate;
+class IOBluetoothRFCOMMChannel;
+#endif
+
+namespace net {
+
+class DrainableIOBuffer;
+class GrowableIOBuffer;
+
+}  // namespace net
+
+namespace device {
+
+class BluetoothServiceRecord;
+
+// This class is an implementation of BluetoothSocket class for OSX platform.
+class BluetoothSocketMac : public BluetoothSocket {
+ public:
+  static scoped_refptr<BluetoothSocket> CreateBluetoothSocket(
+      const BluetoothServiceRecord& service_record);
+
+  // BluetoothSocket override
+  virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE;
+  virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE;
+  virtual std::string GetLastErrorMessage() const OVERRIDE;
+
+  // called by BluetoothRFCOMMChannelDelegate.
+  void OnDataReceived(IOBluetoothRFCOMMChannel* rfcomm_channel,
+                      void* data,
+                      size_t length);
+
+ protected:
+  virtual ~BluetoothSocketMac();
+
+ private:
+  explicit BluetoothSocketMac(IOBluetoothRFCOMMChannel* rfcomm_channel);
+
+  void ResetIncomingDataBuffer();
+
+  IOBluetoothRFCOMMChannel* rfcomm_channel_;
+  BluetoothRFCOMMChannelDelegate* delegate_;
+  scoped_refptr<net::GrowableIOBuffer> incoming_data_buffer_;
+  std::string error_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketMac);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_
diff --git a/device/bluetooth/bluetooth_socket_mac.mm b/device/bluetooth/bluetooth_socket_mac.mm
new file mode 100644
index 0000000..83b30a8
--- /dev/null
+++ b/device/bluetooth/bluetooth_socket_mac.mm
@@ -0,0 +1,141 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_socket_mac.h"
+
+#import <IOBluetooth/objc/IOBluetoothDevice.h>
+#import <IOBluetooth/objc/IOBluetoothRFCOMMChannel.h>
+
+#include <limits>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/stringprintf.h"
+#include "device/bluetooth/bluetooth_service_record.h"
+#include "device/bluetooth/bluetooth_service_record_mac.h"
+#include "net/base/io_buffer.h"
+
+@interface BluetoothRFCOMMChannelDelegate
+    : NSObject <IOBluetoothRFCOMMChannelDelegate> {
+ @private
+  device::BluetoothSocketMac* socket_;  // weak
+}
+
+- (id)initWithSocket:(device::BluetoothSocketMac*)socket;
+
+@end
+
+@implementation BluetoothRFCOMMChannelDelegate
+
+- (id)initWithSocket:(device::BluetoothSocketMac*)socket {
+  if ((self = [super init]))
+    socket_ = socket;
+
+  return self;
+}
+
+- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel
+                     data:(void*)dataPointer
+                   length:(size_t)dataLength {
+  socket_->OnDataReceived(rfcommChannel, dataPointer, dataLength);
+}
+
+@end
+
+namespace device {
+
+BluetoothSocketMac::BluetoothSocketMac(IOBluetoothRFCOMMChannel* rfcomm_channel)
+    : rfcomm_channel_(rfcomm_channel),
+      delegate_([[BluetoothRFCOMMChannelDelegate alloc] initWithSocket:this]) {
+  [rfcomm_channel_ setDelegate:delegate_];
+  ResetIncomingDataBuffer();
+}
+
+BluetoothSocketMac::~BluetoothSocketMac() {
+  [rfcomm_channel_ release];
+  [delegate_ release];
+}
+
+// static
+scoped_refptr<BluetoothSocket> BluetoothSocketMac::CreateBluetoothSocket(
+    const BluetoothServiceRecord& service_record) {
+  BluetoothSocketMac* bluetooth_socket = NULL;
+  if (service_record.SupportsRfcomm()) {
+    const BluetoothServiceRecordMac* service_record_mac =
+        static_cast<const BluetoothServiceRecordMac*>(&service_record);
+    IOBluetoothDevice* device = service_record_mac->GetIOBluetoothDevice();
+    IOBluetoothRFCOMMChannel* rfcomm_channel;
+    IOReturn status =
+        [device openRFCOMMChannelAsync:&rfcomm_channel
+                         withChannelID:service_record.rfcomm_channel()
+                              delegate:nil];
+    if (status == kIOReturnSuccess) {
+      bluetooth_socket = new BluetoothSocketMac(rfcomm_channel);
+    } else {
+      LOG(ERROR) << "Failed to connect bluetooth socket ("
+          << service_record.address() << "): (" << status << ")";
+    }
+  }
+  // TODO(youngki): add support for L2CAP sockets as well.
+
+  return scoped_refptr<BluetoothSocketMac>(bluetooth_socket);
+}
+
+bool BluetoothSocketMac::Receive(net::GrowableIOBuffer* buffer) {
+  CHECK(buffer->offset() == 0);
+  int length = incoming_data_buffer_->offset();
+  if (length > 0) {
+    buffer->SetCapacity(length);
+    memcpy(buffer->data(), incoming_data_buffer_->StartOfBuffer(), length);
+    buffer->set_offset(length);
+
+    ResetIncomingDataBuffer();
+  }
+  return true;
+}
+
+bool BluetoothSocketMac::Send(net::DrainableIOBuffer* buffer) {
+  int bytes_written = buffer->BytesRemaining();
+  IOReturn status = [rfcomm_channel_ writeAsync:buffer->data()
+                                         length:bytes_written
+                                         refcon:nil];
+  if (status != kIOReturnSuccess) {
+    error_message_ = base::StringPrintf(
+        "Failed to send data. IOReturn code: %u", status);
+    return false;
+  }
+
+  buffer->DidConsume(bytes_written);
+  return true;
+}
+
+std::string BluetoothSocketMac::GetLastErrorMessage() const {
+  return error_message_;
+}
+
+void BluetoothSocketMac::OnDataReceived(
+    IOBluetoothRFCOMMChannel* rfcomm_channel, void* data, size_t length) {
+  DCHECK(rfcomm_channel_ == rfcomm_channel);
+  CHECK_LT(length, static_cast<size_t>(std::numeric_limits<int>::max()));
+  int data_size = static_cast<int>(length);
+  if (incoming_data_buffer_->RemainingCapacity() < data_size) {
+    int additional_capacity =
+        std::max(data_size, incoming_data_buffer_->capacity());
+    CHECK_LT(
+        additional_capacity,
+        std::numeric_limits<int>::max() - incoming_data_buffer_->capacity());
+    incoming_data_buffer_->SetCapacity(
+        incoming_data_buffer_->capacity() + additional_capacity);
+  }
+  memcpy(incoming_data_buffer_->data(), data, data_size);
+  incoming_data_buffer_->set_offset(
+      incoming_data_buffer_->offset() + data_size);
+}
+
+void BluetoothSocketMac::ResetIncomingDataBuffer() {
+  incoming_data_buffer_ = new net::GrowableIOBuffer();
+  incoming_data_buffer_->SetCapacity(1024);
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_socket_win.cc b/device/bluetooth/bluetooth_socket_win.cc
index ab83a1f..01b8eee 100644
--- a/device/bluetooth/bluetooth_socket_win.cc
+++ b/device/bluetooth/bluetooth_socket_win.cc
@@ -1,24 +1,115 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// TODO(youngki): Implement this file.
 
 #include "device/bluetooth/bluetooth_socket_win.h"
 
+#include <string>
+
 #include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/sys_string_conversions.h"
+#include "device/bluetooth/bluetooth_init_win.h"
+#include "device/bluetooth/bluetooth_service_record_win.h"
+#include "net/base/io_buffer.h"
+#include "net/base/winsock_init.h"
+
+namespace {
+
+std::string FormatErrorMessage(DWORD error_code) {
+  TCHAR error_msg[1024];
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+                0,
+                error_code,
+                0,
+                error_msg,
+                1024,
+                NULL);
+  return base::SysWideToUTF8(error_msg);
+}
+
+}  // namespace
 
 namespace device {
 
-BluetoothSocketWin::BluetoothSocketWin() {
+BluetoothSocketWin::BluetoothSocketWin(SOCKET fd) : fd_(fd) {
 }
 
 BluetoothSocketWin::~BluetoothSocketWin() {
+  closesocket(fd_);
 }
 
-int BluetoothSocketWin::fd() const {
-  NOTIMPLEMENTED();
-  return -1;
+// static
+scoped_refptr<BluetoothSocket> BluetoothSocketWin::CreateBluetoothSocket(
+    const BluetoothServiceRecord& service_record) {
+  BluetoothSocketWin* bluetooth_socket = NULL;
+  if (service_record.SupportsRfcomm()) {
+    net::EnsureWinsockInit();
+    SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
+    SOCKADDR_BTH sa;
+    ZeroMemory(&sa, sizeof(sa));
+    sa.addressFamily = AF_BTH;
+    sa.port = service_record.rfcomm_channel();
+    const BluetoothServiceRecordWin* service_record_win =
+        static_cast<const BluetoothServiceRecordWin*>(&service_record);
+    sa.btAddr = service_record_win->bth_addr();
+
+    int status = connect(socket_fd,
+                         reinterpret_cast<SOCKADDR *>(&sa),
+                         sizeof(sa));
+    DWORD error_code = WSAGetLastError();
+    if (status == 0 || error_code == WSAEINPROGRESS) {
+      bluetooth_socket =
+          new BluetoothSocketWin(socket_fd);
+    } else {
+      LOG(ERROR) << "Failed to connect bluetooth socket "
+          << "(" << service_record.address() << "): "
+          << "(" << error_code << ")" << FormatErrorMessage(error_code);
+      closesocket(socket_fd);
+    }
+  }
+  // TODO(youngki) add support for L2CAP sockets as well.
+
+  return scoped_refptr<BluetoothSocketWin>(bluetooth_socket);
+}
+
+bool BluetoothSocketWin::Receive(net::GrowableIOBuffer* buffer) {
+  buffer->SetCapacity(1024);
+  int bytes_read;
+  do {
+    if (buffer->RemainingCapacity() == 0)
+      buffer->SetCapacity(buffer->capacity() * 2);
+    bytes_read = recv(fd_, buffer->data(), buffer->RemainingCapacity(), 0);
+    if (bytes_read > 0)
+      buffer->set_offset(buffer->offset() + bytes_read);
+  } while (bytes_read > 0);
+
+  DWORD error_code = WSAGetLastError();
+  if (bytes_read < 0 && error_code != WSAEWOULDBLOCK) {
+    error_message_ = FormatErrorMessage(error_code);
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothSocketWin::Send(net::DrainableIOBuffer* buffer) {
+  int bytes_written;
+  do {
+    bytes_written = send(fd_, buffer->data(), buffer->BytesRemaining(), 0);
+    if (bytes_written > 0)
+      buffer->DidConsume(bytes_written);
+  } while (buffer->BytesRemaining() > 0 && bytes_written > 0);
+
+  DWORD error_code = WSAGetLastError();
+  if (bytes_written < 0 && error_code != WSAEWOULDBLOCK) {
+    error_message_ = FormatErrorMessage(error_code);
+    return false;
+  }
+  return true;
+}
+
+std::string BluetoothSocketWin::GetLastErrorMessage() const {
+  return error_message_;
 }
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_socket_win.h b/device/bluetooth/bluetooth_socket_win.h
index e9fe120..41713e7 100644
--- a/device/bluetooth/bluetooth_socket_win.h
+++ b/device/bluetooth/bluetooth_socket_win.h
@@ -5,18 +5,46 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_WIN_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_WIN_H_
 
+#include <WinSock2.h>
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
 #include "device/bluetooth/bluetooth_socket.h"
 
+namespace net {
+
+class DrainableIOBuffer;
+class GrowableIOBuffer;
+
+}  // namespace net
+
 namespace device {
 
+class BluetoothServiceRecord;
+
+// This class is an implementation of BluetoothSocket class for Windows
+// platform.
 class BluetoothSocketWin : public BluetoothSocket {
  public:
+  static scoped_refptr<BluetoothSocket> CreateBluetoothSocket(
+      const BluetoothServiceRecord& service_record);
+
   // BluetoothSocket override
-  virtual int fd() const OVERRIDE;
+  virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE;
+  virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE;
+  virtual std::string GetLastErrorMessage() const OVERRIDE;
+
+ protected:
+  virtual ~BluetoothSocketWin();
 
  private:
-  BluetoothSocketWin();
-  virtual ~BluetoothSocketWin();
+  explicit BluetoothSocketWin(SOCKET fd);
+
+  const SOCKET fd_;
+  std::string error_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketWin);
 };
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc
new file mode 100644
index 0000000..b747f3b
--- /dev/null
+++ b/device/bluetooth/bluetooth_task_manager_win.cc
@@ -0,0 +1,420 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+
+#include <winsock2.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "base/stringprintf.h"
+#include "base/sys_string_conversions.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/win/scoped_handle.h"
+#include "device/bluetooth/bluetooth_init_win.h"
+#include "device/bluetooth/bluetooth_service_record_win.h"
+#include "net/base/winsock_init.h"
+
+namespace {
+
+const int kNumThreadsInWorkerPool = 3;
+const char kBluetoothThreadName[] = "BluetoothPollingThreadWin";
+const int kMaxNumDeviceAddressChar = 127;
+const int kServiceDiscoveryResultBufferSize = 5000;
+const int kMaxDeviceDiscoveryTimeout = 48;
+
+// Populates bluetooth adapter state using adapter_handle.
+void GetAdapterState(HANDLE adapter_handle,
+                     device::BluetoothTaskManagerWin::AdapterState* state) {
+  std::string name;
+  std::string address;
+  bool powered = false;
+  BLUETOOTH_RADIO_INFO adapter_info = { sizeof(BLUETOOTH_RADIO_INFO), 0 };
+  if (adapter_handle &&
+      ERROR_SUCCESS == BluetoothGetRadioInfo(adapter_handle,
+                                             &adapter_info)) {
+    name = base::SysWideToUTF8(adapter_info.szName);
+    address = base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
+        adapter_info.address.rgBytes[5],
+        adapter_info.address.rgBytes[4],
+        adapter_info.address.rgBytes[3],
+        adapter_info.address.rgBytes[2],
+        adapter_info.address.rgBytes[1],
+        adapter_info.address.rgBytes[0]);
+    powered = !!BluetoothIsConnectable(adapter_handle);
+  }
+  state->name = name;
+  state->address = address;
+  state->powered = powered;
+}
+
+void GetDeviceState(const BLUETOOTH_DEVICE_INFO& device_info,
+                    device::BluetoothTaskManagerWin::DeviceState* state) {
+  state->name = base::SysWideToUTF8(device_info.szName);
+  state->address = base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
+      device_info.Address.rgBytes[5],
+      device_info.Address.rgBytes[4],
+      device_info.Address.rgBytes[3],
+      device_info.Address.rgBytes[2],
+      device_info.Address.rgBytes[1],
+      device_info.Address.rgBytes[0]);
+  state->bluetooth_class = device_info.ulClassofDevice;
+  state->visible = true;
+  state->connected = !!device_info.fConnected;
+  state->authenticated = !!device_info.fAuthenticated;
+}
+
+}  // namespace
+
+namespace device {
+
+// static
+const int BluetoothTaskManagerWin::kPollIntervalMs = 500;
+
+BluetoothTaskManagerWin::BluetoothTaskManagerWin(
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
+    : ui_task_runner_(ui_task_runner),
+      discovering_(false) {
+}
+
+BluetoothTaskManagerWin::~BluetoothTaskManagerWin() {
+}
+
+void BluetoothTaskManagerWin::AddObserver(Observer* observer) {
+  DCHECK(observer);
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  observers_.AddObserver(observer);
+}
+
+void BluetoothTaskManagerWin::RemoveObserver(Observer* observer) {
+  DCHECK(observer);
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  observers_.RemoveObserver(observer);
+}
+
+void BluetoothTaskManagerWin::Initialize() {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  worker_pool_ = new base::SequencedWorkerPool(kNumThreadsInWorkerPool,
+                                               kBluetoothThreadName);
+  InitializeWithBluetoothTaskRunner(
+      worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
+          worker_pool_->GetSequenceToken(),
+          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
+}
+
+void BluetoothTaskManagerWin::InitializeWithBluetoothTaskRunner(
+    scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  bluetooth_task_runner_ = bluetooth_task_runner;
+  bluetooth_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::StartPolling, this));
+}
+
+void BluetoothTaskManagerWin::StartPolling() {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+
+  if (device::bluetooth_init_win::HasBluetoothStack()) {
+    PollAdapter();
+  } else {
+    // IF the bluetooth stack is not available, we still send an empty state
+    // to BluetoothAdapter so that it is marked initialized, but the adapter
+    // will not be present.
+    AdapterState* state = new AdapterState();
+    ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnAdapterStateChanged,
+                 this,
+                 base::Owned(state)));
+  }
+}
+
+void BluetoothTaskManagerWin::Shutdown() {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  if (worker_pool_)
+    worker_pool_->Shutdown();
+}
+
+void BluetoothTaskManagerWin::PostSetPoweredBluetoothTask(
+    bool powered,
+    const base::Closure& callback,
+    const BluetoothAdapter::ErrorCallback& error_callback) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  bluetooth_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::SetPowered,
+                 this,
+                 powered,
+                 callback,
+                 error_callback));
+}
+
+void BluetoothTaskManagerWin::PostStartDiscoveryTask() {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  bluetooth_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::StartDiscovery, this));
+}
+
+void BluetoothTaskManagerWin::PostStopDiscoveryTask() {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  bluetooth_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::StopDiscovery, this));
+}
+
+void BluetoothTaskManagerWin::OnAdapterStateChanged(const AdapterState* state) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+                    AdapterStateChanged(*state));
+}
+
+void BluetoothTaskManagerWin::OnDiscoveryStarted(bool success) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+                    DiscoveryStarted(success));
+}
+
+void BluetoothTaskManagerWin::OnDiscoveryStopped() {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+                    DiscoveryStopped());
+}
+
+void BluetoothTaskManagerWin::OnScanningChanged(bool scanning) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+                    ScanningChanged(scanning));
+}
+
+void BluetoothTaskManagerWin::OnDevicesDiscovered(
+    const ScopedVector<DeviceState>* devices) {
+  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+  FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+                    DevicesDiscovered(*devices));
+}
+
+void BluetoothTaskManagerWin::PollAdapter() {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+
+  // Skips updating the adapter info if the adapter is in discovery mode.
+  if (!discovering_) {
+    const BLUETOOTH_FIND_RADIO_PARAMS adapter_param =
+        { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
+    if (adapter_handle_)
+      adapter_handle_.Close();
+    HBLUETOOTH_RADIO_FIND handle = BluetoothFindFirstRadio(
+        &adapter_param, adapter_handle_.Receive());
+
+    if (handle) {
+      GetKnownDevices();
+      BluetoothFindRadioClose(handle);
+    }
+    PostAdapterStateToUi();
+  }
+
+  // Re-poll.
+  bluetooth_task_runner_->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::PollAdapter,
+                 this),
+      base::TimeDelta::FromMilliseconds(kPollIntervalMs));
+}
+
+void BluetoothTaskManagerWin::PostAdapterStateToUi() {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  AdapterState* state = new AdapterState();
+  GetAdapterState(adapter_handle_, state);
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnAdapterStateChanged,
+                 this,
+                 base::Owned(state)));
+}
+
+void BluetoothTaskManagerWin::SetPowered(
+    bool powered,
+    const base::Closure& callback,
+    const BluetoothAdapter::ErrorCallback& error_callback) {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  bool success = false;
+  if (adapter_handle_) {
+    if (!powered)
+      BluetoothEnableDiscovery(adapter_handle_, false);
+    success = !!BluetoothEnableIncomingConnections(adapter_handle_, powered);
+  }
+
+  if (success) {
+    PostAdapterStateToUi();
+    ui_task_runner_->PostTask(FROM_HERE, callback);
+  } else {
+    ui_task_runner_->PostTask(FROM_HERE, error_callback);
+  }
+}
+
+void BluetoothTaskManagerWin::StartDiscovery() {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStarted,
+                 this,
+                 !!adapter_handle_));
+  if (!adapter_handle_)
+    return;
+  discovering_ = true;
+
+  DiscoverDevices(1);
+}
+
+void BluetoothTaskManagerWin::StopDiscovery() {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  discovering_ = false;
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
+}
+
+void BluetoothTaskManagerWin::DiscoverDevices(int timeout) {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  if (!discovering_ || !adapter_handle_) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
+    return;
+  }
+
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnScanningChanged, this, true));
+
+  ScopedVector<DeviceState>* device_list = new ScopedVector<DeviceState>();
+  SearchDevices(timeout, false, device_list);
+  if (device_list->empty()) {
+    delete device_list;
+  } else {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BluetoothTaskManagerWin::OnScanningChanged, this, false));
+    DiscoverServices(device_list);
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BluetoothTaskManagerWin::OnDevicesDiscovered,
+                   this,
+                   base::Owned(device_list)));
+  }
+
+  if (timeout < kMaxDeviceDiscoveryTimeout) {
+    bluetooth_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BluetoothTaskManagerWin::DiscoverDevices,
+                   this,
+                   timeout + 1));
+  } else {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
+    discovering_ = false;
+  }
+}
+
+void BluetoothTaskManagerWin::GetKnownDevices() {
+  ScopedVector<DeviceState>* device_list = new ScopedVector<DeviceState>();
+  SearchDevices(1, true, device_list);
+  if (device_list->empty()) {
+    delete device_list;
+    return;
+  }
+  DiscoverServices(device_list);
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BluetoothTaskManagerWin::OnDevicesDiscovered,
+                 this,
+                 base::Owned(device_list)));
+}
+
+void BluetoothTaskManagerWin::SearchDevices(
+    int timeout,
+    bool search_cached_devices_only,
+    ScopedVector<DeviceState>* device_list) {
+  BLUETOOTH_DEVICE_SEARCH_PARAMS device_search_params = {
+      sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS),
+      1,  // return authenticated devices
+      1,  // return remembered devices
+      search_cached_devices_only ? 0 : 1,  // return unknown devices
+      1,  // return connected devices
+      search_cached_devices_only ? 0 : 1,  // issue a new inquiry
+      timeout,  // timeout for the inquiry in increments of 1.28 seconds
+      adapter_handle_
+  };
+
+  BLUETOOTH_DEVICE_INFO device_info = { sizeof(BLUETOOTH_DEVICE_INFO), 0 };
+  // Issues a device inquiry and waits for |timeout| * 1.28 seconds.
+  HBLUETOOTH_DEVICE_FIND handle =
+      BluetoothFindFirstDevice(&device_search_params, &device_info);
+  if (handle) {
+    do {
+      DeviceState* device_state = new DeviceState();
+      GetDeviceState(device_info, device_state);
+      device_list->push_back(device_state);
+    } while (BluetoothFindNextDevice(handle, &device_info));
+
+    BluetoothFindDeviceClose(handle);
+  }
+}
+
+void BluetoothTaskManagerWin::DiscoverServices(
+    ScopedVector<DeviceState>* device_list) {
+  DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
+  net::EnsureWinsockInit();
+  for (ScopedVector<DeviceState>::iterator iter = device_list->begin();
+      iter != device_list->end();
+      ++iter) {
+    const std::string device_address = (*iter)->address;
+    ScopedVector<ServiceRecordState>* service_record_states =
+        &(*iter)->service_record_states;
+    WSAQUERYSET sdp_query;
+    ZeroMemory(&sdp_query, sizeof(sdp_query));
+    sdp_query.dwSize = sizeof(sdp_query);
+    GUID protocol = L2CAP_PROTOCOL_UUID;
+    sdp_query.lpServiceClassId = &protocol;
+    sdp_query.dwNameSpace = NS_BTH;
+    wchar_t device_address_context[kMaxNumDeviceAddressChar];
+    std::size_t length =
+        base::SysUTF8ToWide("(" + device_address + ")").copy(
+            device_address_context, kMaxNumDeviceAddressChar);
+    device_address_context[length] = NULL;
+    sdp_query.lpszContext = device_address_context;
+    HANDLE sdp_handle;
+    if (ERROR_SUCCESS !=
+        WSALookupServiceBegin(&sdp_query, LUP_RETURN_ALL, &sdp_handle)) {
+      return;
+    }
+    char sdp_buffer[kServiceDiscoveryResultBufferSize];
+    LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer);
+    DWORD sdp_buffer_size = sizeof(sdp_buffer);
+    while (ERROR_SUCCESS == WSALookupServiceNext(sdp_handle,
+                                                 LUP_RETURN_ALL,
+                                                 &sdp_buffer_size,
+                                                 sdp_result_data)) {
+      ServiceRecordState* service_record_state = new ServiceRecordState();
+      service_record_state->name =
+          base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName);
+      service_record_state->address = device_address;
+      for (uint64 i = 0; i < sdp_result_data->lpBlob->cbSize; i++) {
+        service_record_state->sdp_bytes.push_back(
+            sdp_result_data->lpBlob->pBlobData[i]);
+      }
+      service_record_states->push_back(service_record_state);
+    }
+    WSALookupServiceEnd(sdp_handle);
+  }
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_task_manager_win.h b/device/bluetooth/bluetooth_task_manager_win.h
new file mode 100644
index 0000000..3608667
--- /dev/null
+++ b/device/bluetooth/bluetooth_task_manager_win.h
@@ -0,0 +1,157 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_TASK_MANAGER_WIN_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_TASK_MANAGER_WIN_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_vector.h"
+#include "base/observer_list.h"
+#include "base/win/scoped_handle.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+
+namespace base {
+
+class SequencedTaskRunner;
+class SequencedWorkerPool;
+
+}  // namespace base
+
+namespace device {
+
+// Manages the blocking Bluetooth tasks using |SequencedWorkerPool|. It runs
+// bluetooth tasks using |SequencedWorkerPool| and informs its observers of
+// bluetooth adapter state changes and any other bluetooth device inquiry
+// result.
+//
+// It delegates the blocking Windows API calls to |bluetooth_task_runner_|'s
+// message loop, and receives responses via methods like OnAdapterStateChanged
+// posted to UI thread.
+class BluetoothTaskManagerWin
+    : public base::RefCountedThreadSafe<BluetoothTaskManagerWin> {
+ public:
+  struct AdapterState {
+    std::string name;
+    std::string address;
+    bool powered;
+  };
+
+  struct ServiceRecordState {
+    std::string name;
+    std::string address;
+    std::vector<uint8> sdp_bytes;
+  };
+
+  struct DeviceState {
+    std::string name;
+    std::string address;
+    uint32 bluetooth_class;
+    bool visible;
+    bool connected;
+    bool authenticated;
+    ScopedVector<ServiceRecordState> service_record_states;
+  };
+
+  class Observer {
+   public:
+     virtual ~Observer() {}
+
+     virtual void AdapterStateChanged(const AdapterState& state) {}
+     virtual void DiscoveryStarted(bool success) {}
+     virtual void DiscoveryStopped() {}
+     virtual void ScanningChanged(bool scanning) {}
+     virtual void DevicesDiscovered(const ScopedVector<DeviceState>& devices) {}
+  };
+
+  explicit BluetoothTaskManagerWin(
+      scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  void Initialize();
+  void InitializeWithBluetoothTaskRunner(
+      scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner);
+  void Shutdown();
+
+  void PostSetPoweredBluetoothTask(
+      bool powered,
+      const base::Closure& callback,
+      const BluetoothAdapter::ErrorCallback& error_callback);
+  void PostStartDiscoveryTask();
+  void PostStopDiscoveryTask();
+
+ private:
+  friend class base::RefCountedThreadSafe<BluetoothTaskManagerWin>;
+  friend class BluetoothTaskManagerWinTest;
+
+  static const int kPollIntervalMs;
+
+  virtual ~BluetoothTaskManagerWin();
+
+  // Notify all Observers of updated AdapterState. Should only be called on the
+  // UI thread.
+  void OnAdapterStateChanged(const AdapterState* state);
+  void OnDiscoveryStarted(bool success);
+  void OnDiscoveryStopped();
+  void OnScanningChanged(bool scanning);
+  void OnDevicesDiscovered(const ScopedVector<DeviceState>* devices);
+
+  // Called on BluetoothTaskRunner.
+  void StartPolling();
+  void PollAdapter();
+  void PostAdapterStateToUi();
+  void SetPowered(bool powered,
+                  const base::Closure& callback,
+                  const BluetoothAdapter::ErrorCallback& error_callback);
+
+  // Starts discovery. Once the discovery starts, it issues a discovery inquiry
+  // with a short timeout, then issues more inquiries with greater timeout
+  // values. The discovery finishes when StopDiscovery() is called or timeout
+  // has reached its maximum value.
+  void StartDiscovery();
+  void StopDiscovery();
+
+  // Issues a device inquiry that runs for |timeout| * 1.28 seconds.
+  // This posts itself again with |timeout| + 1 until |timeout| reaches the
+  // maximum value or stop discovery call is received.
+  void DiscoverDevices(int timeout);
+
+  // Fetch already known device information. Similar to |StartDiscovery|, except
+  // this function does not issue a discovery inquiry. Instead it gets the
+  // device info cached in the adapter.
+  void GetKnownDevices();
+
+  // Sends a device search API call to the adapter.
+  void SearchDevices(int timeout,
+                     bool search_cached_devices_only,
+                     ScopedVector<DeviceState>* device_list);
+
+  // Discover services for the devices in |device_list|.
+  void DiscoverServices(ScopedVector<DeviceState>* device_list);
+
+  // UI task runner reference.
+  scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
+
+  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
+  scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner_;
+
+  // List of observers interested in event notifications.
+  ObserverList<Observer> observers_;
+
+  // Adapter handle owned by bluetooth task runner.
+  base::win::ScopedHandle adapter_handle_;
+
+  // indicates whether the adapter is in discovery mode or not.
+  bool discovering_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothTaskManagerWin);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_TASK_MANAGER_WIN_H_
diff --git a/device/bluetooth/bluetooth_task_manager_win_unittest.cc b/device/bluetooth/bluetooth_task_manager_win_unittest.cc
new file mode 100644
index 0000000..87a3ef5
--- /dev/null
+++ b/device/bluetooth/bluetooth_task_manager_win_unittest.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/test_pending_task.h"
+#include "base/test/test_simple_task_runner.h"
+#include "device/bluetooth/bluetooth_init_win.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class BluetoothTaskObserver : public device::BluetoothTaskManagerWin::Observer {
+ public:
+  BluetoothTaskObserver() {
+    Clear();
+  }
+
+  virtual ~BluetoothTaskObserver() {
+  }
+
+  virtual void AdapterStateChanged(
+    const device::BluetoothTaskManagerWin::AdapterState& state) OVERRIDE {
+    num_adapter_state_changed_++;
+  }
+
+  virtual void DiscoveryStarted(bool success) OVERRIDE {
+    num_discovery_started_++;
+  }
+
+  virtual void DiscoveryStopped() OVERRIDE {
+    num_discovery_stopped_++;
+  }
+
+  virtual void ScanningChanged(bool scanning) OVERRIDE {
+    num_scanning_changed_++;
+  }
+
+  virtual void DevicesDiscovered(
+      const ScopedVector<device::BluetoothTaskManagerWin::DeviceState>&
+          devices) OVERRIDE {
+    num_devices_discovered_++;
+  }
+
+  void Clear() {
+    num_adapter_state_changed_ = 0;
+    num_discovery_started_ = 0;
+    num_discovery_stopped_ = 0;
+    num_scanning_changed_ = 0;
+    num_devices_discovered_ = 0;
+  }
+
+  int num_adapter_state_changed() const {
+    return num_adapter_state_changed_;
+  }
+
+  int num_discovery_started() const {
+    return num_discovery_started_;
+  }
+
+  int num_discovery_stopped() const {
+    return num_discovery_stopped_;
+  }
+
+  int num_scanning_changed() const {
+    return num_scanning_changed_;
+  }
+
+  int num_devices_discovered() const {
+    return num_devices_discovered_;
+  }
+
+ private:
+   int num_adapter_state_changed_;
+   int num_discovery_started_;
+   int num_discovery_stopped_;
+   int num_scanning_changed_;
+   int num_devices_discovered_;
+};
+
+}  // namespace
+
+namespace device {
+
+class BluetoothTaskManagerWinTest : public testing::Test {
+ public:
+  BluetoothTaskManagerWinTest()
+      : ui_task_runner_(new base::TestSimpleTaskRunner()),
+        bluetooth_task_runner_(new base::TestSimpleTaskRunner()),
+        task_manager_(new BluetoothTaskManagerWin(ui_task_runner_)),
+        has_bluetooth_stack_(device::bluetooth_init_win::HasBluetoothStack()) {
+    task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner_);
+  }
+
+  virtual void SetUp() {
+    task_manager_->AddObserver(&observer_);
+  }
+
+  virtual void TearDown() {
+    task_manager_->RemoveObserver(&observer_);
+  }
+
+  int GetPollingIntervalMs() const {
+    return BluetoothTaskManagerWin::kPollIntervalMs;
+  }
+
+ protected:
+  scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;
+  scoped_refptr<base::TestSimpleTaskRunner> bluetooth_task_runner_;
+  scoped_refptr<BluetoothTaskManagerWin> task_manager_;
+  BluetoothTaskObserver observer_;
+  const bool has_bluetooth_stack_;
+};
+
+TEST_F(BluetoothTaskManagerWinTest, StartPolling) {
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+}
+
+TEST_F(BluetoothTaskManagerWinTest, PollAdapterIfBluetoothStackIsAvailable) {
+  bluetooth_task_runner_->RunPendingTasks();
+  int num_expected_pending_tasks = has_bluetooth_stack_ ? 1 : 0;
+  EXPECT_EQ(num_expected_pending_tasks,
+            bluetooth_task_runner_->GetPendingTasks().size());
+}
+
+TEST_F(BluetoothTaskManagerWinTest, Polling) {
+  if (!has_bluetooth_stack_)
+    return;
+
+  int num_polls = 5;
+
+  for (int i = 0; i < num_polls; i++) {
+    bluetooth_task_runner_->RunPendingTasks();
+  }
+
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_EQ(num_polls, observer_.num_adapter_state_changed());
+}
+
+TEST_F(BluetoothTaskManagerWinTest, SetPowered) {
+  if (!has_bluetooth_stack_)
+    return;
+
+  bluetooth_task_runner_->ClearPendingTasks();
+  base::Closure closure;
+  task_manager_->PostSetPoweredBluetoothTask(true, closure, closure);
+
+  EXPECT_EQ(1, bluetooth_task_runner_->GetPendingTasks().size());
+  bluetooth_task_runner_->RunPendingTasks();
+  EXPECT_TRUE(ui_task_runner_->GetPendingTasks().size() >= 1);
+}
+
+TEST_F(BluetoothTaskManagerWinTest, Discovery) {
+  if (!has_bluetooth_stack_)
+    return;
+
+  bluetooth_task_runner_->RunPendingTasks();
+  bluetooth_task_runner_->ClearPendingTasks();
+  task_manager_->PostStartDiscoveryTask();
+  bluetooth_task_runner_->RunPendingTasks();
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_EQ(1, observer_.num_discovery_started());
+  task_manager_->PostStopDiscoveryTask();
+  bluetooth_task_runner_->RunPendingTasks();
+  ui_task_runner_->RunPendingTasks();
+  EXPECT_EQ(1, observer_.num_discovery_stopped());
+}
+
+}  // namespace device
diff --git a/device/bluetooth/bluetooth_utils.cc b/device/bluetooth/bluetooth_utils.cc
index 6d06409..1e7b827 100644
--- a/device/bluetooth/bluetooth_utils.cc
+++ b/device/bluetooth/bluetooth_utils.cc
@@ -6,12 +6,8 @@
 
 #include <vector>
 
-#if defined(OS_CHROMEOS)
-#include <bluetooth/bluetooth.h>
-#endif
-
+#include "base/basictypes.h"
 #include "base/logging.h"
-#include "base/string_number_conversions.h"
 #include "base/string_util.h"
 
 namespace {
@@ -23,35 +19,6 @@
 namespace device {
 namespace bluetooth_utils {
 
-#if defined(OS_CHROMEOS)
-bool str2ba(const std::string& in_address, bdaddr_t* out_address) {
-  if (!out_address)
-    return false;
-
-  memset(out_address, 0, sizeof(*out_address));
-
-  if (in_address.size() != 17)
-    return false;
-
-  std::string numbers_only;
-  for (int i = 0; i < 6; ++i) {
-    numbers_only += in_address.substr(i * 3, 2);
-  }
-
-  std::vector<uint8> address_bytes;
-  if (base::HexStringToBytes(numbers_only, &address_bytes)) {
-    if (address_bytes.size() == 6) {
-      for (int i = 0; i < 6; ++i) {
-        out_address->b[5 - i] = address_bytes[i];
-      }
-      return true;
-    }
-  }
-
-  return false;
-}
-#endif
-
 std::string CanonicalUuid(std::string uuid) {
   if (uuid.empty())
     return "";
diff --git a/device/bluetooth/bluetooth_utils.h b/device/bluetooth/bluetooth_utils.h
index f796d5d..0995160 100644
--- a/device/bluetooth/bluetooth_utils.h
+++ b/device/bluetooth/bluetooth_utils.h
@@ -7,22 +7,11 @@
 
 #include <string>
 
-#if defined(OS_CHROMEOS)
-#include <bluetooth/bluetooth.h>
-#endif
+#include "base/basictypes.h"
 
 namespace device {
 namespace bluetooth_utils {
 
-#if defined(OS_CHROMEOS)
-// Converts a bluetooth address in the format "B0:D0:9C:0F:3A:2D" into a
-// bdaddr_t struct.  Returns true on success, false on failure.  The contents
-// of |out_address| are zeroed on failure.
-// Note that the order is reversed upon conversion.  For example,
-// "B0:D0:9C:0F:3A:2D" -> {"0x2d", "0x3a", "0x0f", "0x9c", "0xd0", "0xb0"}
-bool str2ba(const std::string& in_address, bdaddr_t* out_address);
-#endif
-
 // Takes a 4, 8 or 36 character UUID, validates it and returns it in 36
 // character format with all hex digits lower case.  If |uuid| is invalid, the
 // empty string is returned.
diff --git a/device/bluetooth/bluetooth_utils_unittest.cc b/device/bluetooth/bluetooth_utils_unittest.cc
index 0e05f8e..46d5f34 100644
--- a/device/bluetooth/bluetooth_utils_unittest.cc
+++ b/device/bluetooth/bluetooth_utils_unittest.cc
@@ -2,35 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#if defined(OS_CHROMEOS)
-#include <bluetooth/bluetooth.h>
-#endif
-
+#include "base/basictypes.h"
 #include "device/bluetooth/bluetooth_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
 
-#if defined(OS_CHROMEOS)
-TEST(BluetoothUtilsTest, str2ba) {
-  bdaddr_t bluetooth_address;
-
-  EXPECT_TRUE(bluetooth_utils::str2ba("01:02:03:0A:10:A0", &bluetooth_address));
-  EXPECT_EQ(1, bluetooth_address.b[5]);
-  EXPECT_EQ(2, bluetooth_address.b[4]);
-  EXPECT_EQ(3, bluetooth_address.b[3]);
-  EXPECT_EQ(10, bluetooth_address.b[2]);
-  EXPECT_EQ(16, bluetooth_address.b[1]);
-  EXPECT_EQ(160, bluetooth_address.b[0]);
-
-  EXPECT_FALSE(bluetooth_utils::str2ba("obviously wrong", &bluetooth_address));
-  EXPECT_FALSE(bluetooth_utils::str2ba("00:00", &bluetooth_address));
-  EXPECT_FALSE(
-      bluetooth_utils::str2ba("00:00:00:00:00:00:00", &bluetooth_address));
-  EXPECT_FALSE(bluetooth_utils::str2ba("01:02:03:0A:10:A0", NULL));
-}
-#endif
-
 TEST(BluetoothUtilsTest, CanonicalUuid) {
   // Does nothing for an already canonical UUID
   EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb",
diff --git a/device/bluetooth/test/mock_bluetooth_adapter.h b/device/bluetooth/test/mock_bluetooth_adapter.h
index 33f7afb..7d76a2b 100644
--- a/device/bluetooth/test/mock_bluetooth_adapter.h
+++ b/device/bluetooth/test/mock_bluetooth_adapter.h
@@ -24,6 +24,7 @@
     MOCK_METHOD2(AdapterPresentChanged, void(BluetoothAdapter*, bool));
     MOCK_METHOD2(AdapterPoweredChanged, void(BluetoothAdapter*, bool));
     MOCK_METHOD2(AdapterDiscoveringChanged, void(BluetoothAdapter*, bool));
+    MOCK_METHOD2(AdapterScanningChanged, void(BluetoothAdapter*, bool));
     MOCK_METHOD2(DeviceAdded, void(BluetoothAdapter*, BluetoothDevice*));
     MOCK_METHOD2(DeviceChanged, void(BluetoothAdapter*, BluetoothDevice*));
     MOCK_METHOD2(DeviceRemoved, void(BluetoothAdapter*, BluetoothDevice*));
@@ -33,6 +34,7 @@
 
   MOCK_METHOD1(AddObserver, void(BluetoothAdapter::Observer*));
   MOCK_METHOD1(RemoveObserver, void(BluetoothAdapter::Observer*));
+  MOCK_CONST_METHOD0(IsInitialized, bool());
   MOCK_CONST_METHOD0(IsPresent, bool());
   MOCK_CONST_METHOD0(IsPowered, bool());
   MOCK_METHOD3(SetPowered,
@@ -40,9 +42,12 @@
                     const base::Closure& callback,
                     const ErrorCallback& error_callback));
   MOCK_CONST_METHOD0(IsDiscovering, bool());
-  MOCK_METHOD3(SetDiscovering,
-               void(bool discovering,
-                    const base::Closure& callback,
+  MOCK_CONST_METHOD0(IsScanning, bool());
+  MOCK_METHOD2(StartDiscovering,
+               void(const base::Closure& callback,
+                    const ErrorCallback& error_callback));
+  MOCK_METHOD2(StopDiscovering,
+               void(const base::Closure& callback,
                     const ErrorCallback& error_callback));
   MOCK_CONST_METHOD0(GetDevices, BluetoothAdapter::ConstDeviceList());
   MOCK_METHOD1(GetDevice, BluetoothDevice*(const std::string& address));
diff --git a/device/bluetooth/test/mock_bluetooth_device.cc b/device/bluetooth/test/mock_bluetooth_device.cc
index f2f358d..6762e04 100644
--- a/device/bluetooth/test/mock_bluetooth_device.cc
+++ b/device/bluetooth/test/mock_bluetooth_device.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "device/bluetooth/test/mock_bluetooth_device.h"
+
 #include "base/utf_string_conversions.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
-#include "device/bluetooth/test/mock_bluetooth_device.h"
 
 namespace device {
 
diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h
index e917a30..56ca4c2 100644
--- a/device/bluetooth/test/mock_bluetooth_device.h
+++ b/device/bluetooth/test/mock_bluetooth_device.h
@@ -46,7 +46,8 @@
   MOCK_METHOD3(Connect,
                void(BluetoothDevice::PairingDelegate* pairnig_delegate,
                     const base::Closure& callback,
-                    const BluetoothDevice::ErrorCallback& error_callback));
+                    const BluetoothDevice::ConnectErrorCallback&
+                        error_callback));
   MOCK_METHOD1(SetPinCode, void(const std::string&));
   MOCK_METHOD1(SetPasskey, void(uint32));
   MOCK_METHOD0(ConfirmPairing, void());
diff --git a/device/bluetooth/test/mock_bluetooth_socket.cc b/device/bluetooth/test/mock_bluetooth_socket.cc
new file mode 100644
index 0000000..3c11518
--- /dev/null
+++ b/device/bluetooth/test/mock_bluetooth_socket.cc
@@ -0,0 +1,12 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/test/mock_bluetooth_socket.h"
+
+namespace device {
+
+MockBluetoothSocket::MockBluetoothSocket() {}
+MockBluetoothSocket::~MockBluetoothSocket() {}
+
+}  // namespace device
diff --git a/device/bluetooth/test/mock_bluetooth_socket.h b/device/bluetooth/test/mock_bluetooth_socket.h
new file mode 100644
index 0000000..8b5e142
--- /dev/null
+++ b/device/bluetooth/test/mock_bluetooth_socket.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_SOCKET_H_
+#define DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_SOCKET_H_
+
+#include <string>
+
+#include "device/bluetooth/bluetooth_socket.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace net {
+
+class DrainableIOBuffer;
+class GrowableIOBuffer;
+
+}  // namespace net
+
+namespace device {
+
+class MockBluetoothSocket : public BluetoothSocket {
+ public:
+  MockBluetoothSocket();
+  MOCK_METHOD1(Receive, bool(net::GrowableIOBuffer*));
+  MOCK_METHOD1(Send, bool(net::DrainableIOBuffer*));
+  MOCK_CONST_METHOD0(GetLastErrorMessage, std::string());
+
+ protected:
+  virtual ~MockBluetoothSocket();
+};
+
+}  // namespace device
+
+#endif  // DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_SOCKET_H_